root/tools/firmware_load_ng.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


   1 #ifndef FIRMWARE_LOAD_NG_H
   2 #define FIRMWARE_LOAD_NG_H
   3 
   4 #define MIN(a,b) ((a) < (b) ? (a) : (b))
   5 #define MAX(a,b) ((a) > (b) ? (a) : (b))
   6 
   7 // Digic 2-5+ (ignoring S1)
   8 #define FW_ARCH_ARMv5       1
   9 // Digic 6, 7
  10 #define FW_ARCH_ARMv7       2
  11 
  12 // additional arch flags
  13 #define FW_ARCH_FL_VMSA     1 // firmware implements Virtual Memory System Architecture, i.e. has MMU
  14 
  15 // for clarity of thumb bit manipulations
  16 #define ADR_SET_THUMB(x) ((x)|1)
  17 #define ADR_CLEAR_THUMB(x) ((x)&~1)
  18 #define ADR_IS_THUMB(x) ((x)&1)
  19 
  20 #define ADR_ALIGN4(x) ((x)&~0x3)
  21 #define ADR_ALIGN2(x) ((x)&~0x1)
  22 
  23 #define ADR_IS_ALIGN4(x) (((x)&0x3)==0)
  24 
  25 // address regions
  26 #define ADR_RANGE_INVALID   0
  27 #define ADR_RANGE_ROM       1
  28 #define ADR_RANGE_RAM_CODE  2
  29 #define ADR_RANGE_INIT_DATA 3
  30 
  31 #define ADR_RANGE_FL_NONE   0
  32 #define ADR_RANGE_FL_TCM    1 // TCM
  33 #define ADR_RANGE_FL_EVEC   2 // exception vector
  34 
  35 // Stores a range of valid data in the firmware dump (used to skip over empty blocks)
  36 typedef struct bufrange {
  37     uint32_t *p;
  38     int off; // NOTE these are in 32 bit blocks, not bytes
  39     int len;
  40     struct bufrange* next;
  41 } BufRange;
  42 
  43 
  44 // TODO may want to make run-time adjustable
  45 #define ADR_HIST_SIZE 64
  46 typedef struct { 
  47     // circular buffer of previous adr values, for backtracking
  48     // use addresses rather than insn, because you might want to scan with detail off and then backtrack with on
  49     // addresses have thumb bit set when disassembling in thumb mode
  50     int cur; // index of current address, after iter
  51     int count; // total number of valid entries
  52     uint32_t adrs[ADR_HIST_SIZE]; 
  53 } adr_hist_t;
  54 
  55 // state for disassembly iteration
  56 typedef struct {
  57     const uint8_t *code; // pointer into buffer for code
  58     uint64_t adr; // firmware address - must be 64 bit for capstone iter, never has thumb bit set
  59                   // points to the next instruction to disassemble, insn->address gives the most 
  60                   // recently disassembled address
  61     size_t size; // remaining code size
  62     cs_insn *insn; // cached instruction
  63     uint32_t thumb; // thumb state
  64     uint32_t insn_min_size; // 2 or 4, depending on thumb/arm state
  65     csh cs_handle; // capstone handle to use with this state, updated for arm/thumb transitions
  66     adr_hist_t ah; // history of previous instructions
  67 }  iter_state_t;
  68 
  69 // struct for regions of ROM that are copied elsewhere
  70 typedef struct {
  71     uint8_t *buf;
  72     uint32_t start;     // copied / relocated firmware address 
  73     uint32_t src_start; // source ROM firmware address
  74     int bytes; // size in bytes
  75     int type;   // ADR_RANGE_* define
  76     int flags;  // ADR_RANGE_FL_*
  77 } adr_range_t;
  78 
  79 #define FW_MAX_ADR_RANGES 10
  80 
  81 #define FW_MAX_DRYOS_VERS 10
  82 
  83 // loaded firmware
  84 typedef struct {
  85     union {
  86         uint8_t        *buf8;                // Firmware data
  87         uint32_t       *buf32;               // Firmware data
  88     };
  89     BufRange        *br, *last;         // Valid ranges
  90 
  91     int             arch;           // firmware CPU arch, set by caller at load time
  92     int             arch_flags;     // additional CPU arch information, inferred
  93     uint32_t        base;           // Base address of the firmware in the camera
  94     int             main_offs;      // Offset of main firmware from the start of the dump
  95 
  96     uint32_t        memisostart;        // Start address of the Canon heap memory (where CHDK is loaded)
  97 
  98     int             size8;          // Size of the firmware (as loaded from the dump) in bytes
  99     int             size32;         // Size of the firmware in 32 bit words
 100 
 101     int             dryos_ver;          // main firmware DryOS version number
 102     char            *dryos_ver_str;     // main firmware DryOS version string
 103     uint32_t        dryos_ver_adr;      // address of main firmware DryOS version string
 104     uint32_t        dryos_ver_ref_adr;  // address of pointer used to identify main fw string
 105     uint32_t        dryos_ver_list[FW_MAX_DRYOS_VERS]; // addresses of all found DryOS version strings
 106     uint32_t        dryos_ver_count;    // number of version strings found
 107 
 108     char            *firmware_ver_str;  // Camera firmware version string
 109 
 110     // TODO duplicated with adr_range stuff below
 111     uint32_t        data_start;         // Start address of DATA section in RAM
 112     uint32_t        data_init_start;    // Start address of initialisation section for DATA in ROM
 113     int             data_len;           // Length of data section in bytes
 114     
 115     // address ranges for ROM and copied data
 116     int             adr_range_count;
 117     adr_range_t     adr_ranges[FW_MAX_ADR_RANGES];
 118     
 119     // convenience values to optimize code searching
 120     uint32_t        rom_code_search_min_adr; // minimum ROM address for normal code searches (i.e. firmware start)
 121     uint32_t        rom_code_search_max_adr; // max ROM address for normal code searches, i.e. before copied data / code if known
 122     // Values loaded from stubs & other files
 123     stub_values     *sv;
 124 
 125     uint32_t thumb_default; // 1 if initial firmware code is expected to be thumb, 0 for arm.
 126     csh cs_handle_thumb; // capstone handle for thumb disassembly
 127     csh cs_handle_arm; // capstone handle for arm disassembly
 128     iter_state_t* is;
 129 } firmware;
 130 
 131 /*
 132 convert firmware address to pointer, or NULL if not in valid range
 133 */
 134 uint8_t* adr2ptr(firmware *fw, uint32_t adr);
 135 
 136 // as above, but include initialized data area (NOTE may change on camera at runtime!)
 137 uint8_t* adr2ptr_with_data(firmware *fw, uint32_t adr);
 138 
 139 // return constant string describing type
 140 const char* adr_range_type_str(int type);
 141 
 142 // return constant string describing type + flags
 143 const char* adr_range_desc_str(adr_range_t *r);
 144 
 145 // convert pointer into buf into firmware address
 146 // current doesn't sanity check or adjust ranges
 147 uint32_t ptr2adr(firmware *fw, uint8_t *ptr);
 148 
 149 // return address range struct for adr, or NULL if not in known range
 150 adr_range_t *adr_get_range(firmware *fw, uint32_t adr);
 151 
 152 // return what kind of range adr is in
 153 int adr_get_range_type(firmware *fw, uint32_t adr);
 154 
 155 // return true if adr is in firmware DATA or BSS
 156 int adr_is_var(firmware *fw, uint32_t adr);
 157 
 158 // return true if adr is in the ROM search range, or one of the copied RAM code regions
 159 int adr_is_main_fw_code(firmware *fw, uint32_t adr);
 160 
 161 //
 162 // Find the index of a string in the firmware
 163 // Assumes the string starts on a 32bit boundary.
 164 // String + terminating zero byte should be at least 4 bytes long
 165 // Handles multiple string instances
 166 int find_Nth_str(firmware *fw, char *str, int N);
 167 
 168 // above, N=1
 169 int find_str(firmware *fw, char *str);
 170 
 171 // find sequence of bytes, starting from star_adr, up to max_adr, any alignment
 172 // returns firmware address or 0
 173 // use repeated calls to find multiple
 174 // NOTE only handles ROM addresses
 175 uint32_t find_next_bytes_range(firmware *fw, const void *bytes, size_t len, uint32_t start_adr, uint32_t max_adr);
 176 
 177 // find up to maxmatch matching byte sequences, storing addresses in result
 178 // returns count
 179 int find_bytes_all(firmware *fw, const void *bytes, size_t len, uint32_t adr, uint32_t *result, int maxmatch);
 180 
 181 // find index of string, starting from address, str can start at any address
 182 // returns firmware address or 0
 183 // use repeated calls to find multiple
 184 // NOTE only handles ROM addresses
 185 uint32_t find_next_str_bytes(firmware *fw, const char *str, uint32_t adr);
 186 
 187 // as above, but without terminating null
 188 uint32_t find_next_substr_bytes(firmware *fw, const char *str, uint32_t adr);
 189 
 190 // find a string within range of LDR pc or ADR, starting from main fw
 191 // i.e., a string directly referenced from main code
 192 uint32_t find_str_bytes_main_fw(firmware *fw, const char *str);
 193 
 194 // as find_next_str_bytes, first match
 195 uint32_t find_str_bytes(firmware *fw, const char *str);
 196 
 197 int isASCIIstring(firmware *fw, uint32_t adr);
 198 
 199 /*
 200 return firmware address of 32 bit value, starting at address "start", up to "maxadr"
 201 */
 202 uint32_t find_u32_adr_range(firmware *fw, uint32_t val, uint32_t start, uint32_t maxadr);
 203 
 204 /*
 205 return firmware address of 32 bit value, starting at address "start", to end of dump
 206 */
 207 uint32_t find_u32_adr(firmware *fw, uint32_t val, uint32_t start);
 208 
 209 // return u32 value at adr
 210 uint32_t fw_u32(firmware *fw, uint32_t adr);
 211 
 212 // memcmp, but using a firmware address, returning 1 adr/size out of range
 213 int fw_memcmp(firmware *fw, uint32_t adr,const void *cmp, size_t n);
 214 
 215 // ****** address history functions ******
 216 // reset address history to empty
 217 void adr_hist_reset(adr_hist_t *ah);
 218 
 219 // return the index of current entry + i. may be negative or positive, wraps. Does not check validity
 220 int adr_hist_index(adr_hist_t *ah, int i);
 221 
 222 // add an entry to address history
 223 void adr_hist_add(adr_hist_t *ah, uint32_t adr);
 224 
 225 // return the i'th previous entry in this history, or 0 if not valid (maybe should be -1?)
 226 // i= 0 = most recently disassembled instruction, if any
 227 uint32_t adr_hist_get(adr_hist_t *ah, int i);
 228 
 229 // ****** instruction analysis utilities ******
 230 // handle varying instruction ID enums in different capstone versions
 231 // note these take an arm_insn enum, NOT a cs_insn *
 232 #if CS_API_MAJOR < 4
 233 // is insn_id a full reg MOV (does not include MOVT)
 234 #define IS_INSN_ID_MOVx(insn_id) ((insn_id) == ARM_INS_MOV || (insn_id) == ARM_INS_MOVS || (insn_id) == ARM_INS_MOVW)
 235 // is insn_id a a sub*
 236 #define IS_INSN_ID_SUBx(insn_id) ((insn_id) == ARM_INS_SUB || (insn_id) == ARM_INS_SUBW || (insn_id) == ARM_INS_SUBS)
 237 #else
 238 #define IS_INSN_ID_MOVx(insn_id) ((insn_id) == ARM_INS_MOV || (insn_id) == ARM_INS_MOVW)
 239 #define IS_INSN_ID_SUBx(insn_id) ((insn_id) == ARM_INS_SUB || (insn_id) == ARM_INS_SUBW)
 240 #endif
 241 
 242 
 243 // is insn an ARM instruction?
 244 // like cs_insn_group(cs_handle,insn,ARM_GRP_ARM) but doesn't require handle and doesn't check or report errors
 245 int isARM(cs_insn *insn);
 246 
 247 /*
 248 is insn a PC relative load?
 249 */
 250 int isLDR_PC(cs_insn *insn);
 251 
 252 /*
 253 is insn a PC relative load to PC?
 254 */
 255 int isLDR_PC_PC(cs_insn *insn);
 256 
 257 // if insn is LDR Rn, [pc,#x] return pointer to value, otherwise null
 258 uint32_t* LDR_PC2valptr_thumb(firmware *fw, cs_insn *insn);
 259 uint32_t* LDR_PC2valptr_arm(firmware *fw, cs_insn *insn);
 260 uint32_t* LDR_PC2valptr(firmware *fw, cs_insn *insn);
 261 
 262 // return the address of value loaded by LDR rd, [pc, #x] or 0 if not LDR PC
 263 uint32_t LDR_PC2adr(firmware *fw, cs_insn *insn);
 264 
 265 // is insn address calculated with subw rd, pc, ...
 266 int isSUBW_PC(cs_insn *insn);
 267 
 268 // is insn address calculated with addw rd, pc, ...
 269 int isADDW_PC(cs_insn *insn);
 270 
 271 // is insn ADD rd, pc, #x  (only generated for ARM in capstone)
 272 int isADD_PC(cs_insn *insn);
 273 
 274 // is insn SUB rd, pc, #x  (only generated for ARM in capstone)
 275 int isSUB_PC(cs_insn *insn);
 276 
 277 // does insn look like a function return?
 278 int isRETx(cs_insn *insn);
 279 
 280 // does insn push LR (function start -ish)
 281 int isPUSH_LR(cs_insn *insn);
 282 
 283 // does insn pop LR (func end before tail call)
 284 int isPOP_LR(cs_insn *insn);
 285 
 286 // does insn pop PC
 287 int isPOP_PC(cs_insn *insn);
 288 
 289 // is the instruction ADD* rx, imm
 290 int isADDx_imm(cs_insn *insn);
 291 
 292 // is the instruction SUB* rx, imm
 293 int isSUBx_imm(cs_insn *insn);
 294 
 295 // is the instruction an ADR or ADR-like instruction?
 296 int isADRx(cs_insn *insn);
 297 
 298 // return value generated by an ADR or ADR-like instruction, or 0 (which should be rarely generated by ADR)
 299 uint32_t ADRx2adr(firmware *fw, cs_insn *insn);
 300 
 301 // return the value generated by an ADR (ie, the location of the value as a firmware address)
 302 // NOTE not checked if it is in dump
 303 uint32_t ADR2adr(firmware *fw, cs_insn *insn);
 304 
 305 // if insn is adr/ AKA ADD Rn, pc,#x return pointer to value, otherwise null
 306 uint32_t* ADR2valptr(firmware *fw, cs_insn *insn);
 307 
 308 // return value loaded by PC relative LDR instruction, or 0 if out of range
 309 uint32_t LDR_PC2val(firmware *fw, cs_insn *insn);
 310 
 311 // return the target of B instruction, or 0 if current instruction isn't B
 312 // both ARM and thumb instructions will NOT have the thumb bit set,
 313 // thumbness must be determined from current state
 314 uint32_t B_target(firmware *fw, cs_insn *insn);
 315 
 316 // return the target of CBZ / CBNZ instruction, or 0 if current instruction isn't CBx
 317 uint32_t CBx_target(firmware *fw, cs_insn *insn);
 318 
 319 // return the target of BLX instruction, or 0 if current instruction isn't BLX imm
 320 uint32_t BLXimm_target(firmware *fw, cs_insn *insn);
 321 
 322 // return the target of BL instruction, or 0 if current instruction isn't BL
 323 // both ARM and thumb instructions will NOT have the thumb bit set,
 324 // thumbness must be determined from current state
 325 uint32_t BL_target(firmware *fw, cs_insn *insn);
 326 
 327 // as above, but also including B for tail calls
 328 uint32_t B_BL_target(firmware *fw, cs_insn *insn);
 329 
 330 // as above, but also including BLX imm
 331 uint32_t B_BL_BLXimm_target(firmware *fw, cs_insn *insn);
 332 
 333 // results from get_TBx_PC_info
 334 typedef struct {
 335     uint32_t start; // address of first jumptable entry
 336     uint32_t count; // number of entries, from preceding cmp, first_target or first invalid value
 337     uint32_t first_target; // lowest jumptable target address (presumably, >= end of jump table in normal code)
 338     int bytes; // size of jump table entries: 1 = tbb, 2=tbh
 339 } tbx_info_t; // tbb/tbh info
 340 
 341 // get the (likely) range of jumptable entries from a pc relative TBB or TBH instruction
 342 // returns 0 on error or if instruction is not TBB/TBH, otherwise 1
 343 int get_TBx_PC_info(firmware *fw,iter_state_t *is, tbx_info_t *ti);
 344 
 345 // ****** disassembly iterator utilities ******
 346 // allocate a new iterator state, optionally initializing at adr (0/invalid OK)
 347 iter_state_t *disasm_iter_new(firmware *fw, uint32_t adr);
 348 
 349 // free iterator state and associated resources
 350 void disasm_iter_free(iter_state_t *is);
 351 
 352 // set iterator to adr, without clearing history (for branch following)
 353 // thumb bit in adr sets mode
 354 int disasm_iter_set(firmware *fw, iter_state_t *is, uint32_t adr);
 355 
 356 // initialize iterator state at adr, clearing history
 357 // thumb bit in adr sets mode
 358 int disasm_iter_init(firmware *fw, iter_state_t *is, uint32_t adr);
 359 
 360 /*
 361 disassemble next instruction, recording address in history
 362 returns false if state invalid or disassembly fails
 363 if disassembly fails, is->adr is not incremented
 364 */
 365 int disasm_iter(firmware *fw, iter_state_t *is);
 366 
 367 // ***** disassembly utilities operating on the default iterator state *****
 368 // use the fw_disasm_iter functions to disassemble without setting up a new state,
 369 // but beware some other functions might change them
 370 /*
 371 initialize iter state to begin iterating at adr
 372 */
 373 int fw_disasm_iter_start(firmware *fw, uint32_t adr);
 374 
 375 // disassemble the next instruction, updating cached state
 376 int fw_disasm_iter(firmware *fw);
 377 
 378 // disassemble single instruction at given adr, updating cached values
 379 // history is cleared
 380 int fw_disasm_iter_single(firmware *fw, uint32_t adr);
 381 
 382 // ****** standalone disassembly without an iter_state ******
 383 /*
 384 disassemble up to count instructions starting at firmware address adr
 385 allocates and returns insns in insn, can be freed with cs_free(insn, count)
 386 returns actual number disassembled, less than count on error
 387 */
 388 // UNUSED for now
 389 //size_t fw_disasm_adr(firmware *fw, uint32_t adr, unsigned count, cs_insn **insn);
 390 
 391 
 392 // ***** utilities for searching disassembly over large ranges ******
 393 /*
 394 callback used by fw_search_insn, called on valid instructions
 395 _search continues iterating until callback returns non-zero.
 396 is points to the most recently disassembled instruction
 397 callback may advance is directly by calling disasm_iter
 398 v1 and udata are passed through from the call to _search
 399 */
 400 typedef uint32_t (*search_insn_fn)(firmware *fw, iter_state_t *is, uint32_t v1, void *udata);
 401 
 402 /*
 403 iterate over firmware disassembling, calling callback described above after each
 404 successful disassembly iteration.  If disassembly fails, the iter state is advanced
 405 2 bytes without calling the callback.
 406 starts at address is taken from the iter_state, which should be initialized by disasm_iter_new()
 407 disasm_iter_init(), or a previous search or iter call.
 408 end defaults to end of ram code or rom code (before init data, if known), based on start
 409 v1 and udata are provided to the callback
 410 */
 411 uint32_t fw_search_insn(firmware *fw, iter_state_t *is, search_insn_fn f,uint32_t v1, void *udata, uint32_t adr_end);
 412 
 413 // ****** callbacks for use with fw_search_insn ******
 414 // search for constant references
 415 uint32_t search_disasm_const_ref(firmware *fw, iter_state_t *is, uint32_t val, void *unused);
 416 
 417 // search for string ref
 418 uint32_t search_disasm_str_ref(firmware *fw, iter_state_t *is, uint32_t val, void *str);
 419 
 420 // search for calls/jumps to immediate addresses
 421 // thumb bit in address should be set appropriately 
 422 // returns 1 if found, address can be obtained from insn
 423 uint32_t search_disasm_calls(firmware *fw, iter_state_t *is, uint32_t val, void *unused);
 424 
 425 // callback for use with search_disasm_calls_multi
 426 // adr is the matching address
 427 typedef int (*search_calls_multi_fn)(firmware *fw, iter_state_t *is, uint32_t adr);
 428 
 429 // structure used to define functions searched for, and functions to handle matches
 430 // fn should be address with thumb bit set appropriately 
 431 typedef struct {
 432     uint32_t adr;
 433     search_calls_multi_fn fn;
 434 } search_calls_multi_data_t;
 435 
 436 // a search_calls_multi_fn that just returns 1
 437 int search_calls_multi_end(firmware *fw, iter_state_t *is, uint32_t adr);
 438 
 439 // Search for calls to multiple functions (more efficient than multiple passes)
 440 // if adr is found in null terminated search_calls_multi_data array, returns fn return value
 441 // otherwise 0
 442 uint32_t search_disasm_calls_multi(firmware *fw, iter_state_t *is, uint32_t unused, void *userdata);
 443 
 444 // ****** utilities for extracting register values ******
 445 /*
 446 backtrack through is_init state history picking up constants loaded into r0-r3
 447 return bitmask of regs with values found
 448 affects fw->is, does not affect is_init
 449 
 450 NOTE values may be inaccurate for many reasons, doesn't track all reg affecting ops,
 451 doesn't account for branches landing in the middle of inspected code
 452 doesn't account for many conditional cases
 453 */
 454 int get_call_const_args(firmware *fw, iter_state_t *is_init, int max_backtrack, uint32_t *res);
 455 
 456 /*
 457 starting from is_init, look for a direct jump, such as
 458  B <target>
 459  LDR PC, [pc, #x]
 460  movw ip, #x
 461  movt ip, #x
 462  bx ip
 463 if found, return target address with thumb bit set appropriately
 464 NOTE does not check for conditional
 465 uses fw->is
 466 does not check CBx, since it would generally be part of a function not a veneer
 467 */
 468 uint32_t get_direct_jump_target(firmware *fw, iter_state_t *is_init);
 469 
 470 /*
 471 return target of any single instruction branch or function call instruction, 
 472 with thumb bit set appropriately
 473 returns 0 if current instruction not branch/call
 474 */
 475 uint32_t get_branch_call_insn_target(firmware *fw, iter_state_t *is);
 476 
 477 /*
 478 search up to max_search_ins for first LDR, =value
 479 and then match up to max_seq_insns for a sequence like
 480 LDR Rbase,=adr
 481 ... possible intervening ins
 482 SUB Rbase,#adj // optional, may be any add/sub variant
 483 ... possible intervening ins
 484 LDR Rval,[Rbase + #off]
 485 
 486 returns 1 if found, 0 if not
 487 stores registers and constants in *result if successful
 488 
 489 NOTE bad values are possible with intervening ins, short sequences recommended
 490 
 491 TODO similar code for STR would be useful, but in many cases would have to handle load or move into reg_val
 492 */
 493 typedef struct {
 494     arm_reg reg_base;
 495     arm_reg reg_val;
 496     uint32_t adr_base; // address from original LDR 
 497     uint32_t adr_adj; // address adjusted by adj if present, normally struct address useful for stubs comments
 498     uint32_t adr_final; // full address
 499     // offsets are guaranteed to be small
 500     int adj;
 501     int off;
 502 } var_ldr_desc_t;
 503 int find_and_get_var_ldr(firmware *fw,
 504                             iter_state_t *is,
 505                             int max_search_insns,
 506                             int max_seq_insns,
 507                             arm_reg match_val_reg, // ARM_REG_INVALID for any
 508                             var_ldr_desc_t *result);
 509 
 510 /*
 511 check for, and optionally return information about 
 512 functions with return values that can be completely determined
 513 from disassembly
 514 uses fw->is
 515 */
 516 // constants below may  as flags on input, and as return valaue
 517 // no simple function found
 518 #define MATCH_SIMPLE_FUNC_NONE    0x0
 519 // immediately returns, with no value
 520 #define MATCH_SIMPLE_FUNC_NULLSUB 0x1
 521 // immediately returns with a MOV constant
 522 #define MATCH_SIMPLE_FUNC_IMM     0x2
 523 // TODO LDR pc, =const,  ADR
 524 // TODO could also do pointer derefs and return pointer info without val
 525 #define MATCH_SIMPLE_FUNC_ANY     0x3
 526 typedef struct {
 527     int ftype;
 528     uint32_t retval;
 529 } simple_func_desc_t;
 530 int check_simple_func(firmware *fw, uint32_t adr, int match_ftype, simple_func_desc_t *info);
 531 
 532 /*
 533 advance is trying to find the last function called by a function
 534 function assumed to push lr, pop lr or pc (many small functions don't!)
 535 either the last bl/blximmg before pop {... pc}
 536 or b after pop {... lr}
 537 after min_insns up to max_insns
 538 */
 539 uint32_t find_last_call_from_func(firmware *fw, iter_state_t *is,int min_insns, int max_insns);
 540 
 541 // ****** utilities for matching instructions and instruction sequences ******
 542 
 543 // use XXX_INVALID (=0) for don't care
 544 typedef struct {
 545     arm_op_type type; // ARM_OP_... REG, IMM, MEM support additional tests
 546     arm_reg reg1; // reg for register type operands, base for mem
 547     uint32_t flags; // 
 548     int32_t imm;  // immediate value for imm, disp for mem
 549     arm_reg reg2; // index reg form mem
 550 } op_match_t;
 551 #define MATCH_OP_FL_IMM     0x0001 // use IMM value
 552 #define MATCH_OP_FL_LAST    0x0002 // ignore all following ops, only check count
 553 // macros for initializing above
 554 //                                  type            reg1                flags               imm     reg2
 555 #define MATCH_OP_ANY                {ARM_OP_INVALID,ARM_REG_INVALID,    0,                  0,      ARM_REG_INVALID}
 556 #define MATCH_OP_REST_ANY           {ARM_OP_INVALID,ARM_REG_INVALID,    MATCH_OP_FL_LAST,   0,      ARM_REG_INVALID}
 557 #define MATCH_OP_REG_ANY            {ARM_OP_REG,    ARM_REG_INVALID,    0,                  0,      ARM_REG_INVALID}
 558 #define MATCH_OP_REG(r)             {ARM_OP_REG,    ARM_REG_##r,        0,                  0,      ARM_REG_INVALID}
 559 #define MATCH_OP_IMM_ANY            {ARM_OP_IMM,    ARM_REG_INVALID,    0,                  0,      ARM_REG_INVALID}
 560 #define MATCH_OP_IMM(imm)           {ARM_OP_IMM,    ARM_REG_INVALID,    MATCH_OP_FL_IMM,    (imm),  ARM_REG_INVALID}
 561 #define MATCH_OP_PIMM_ANY           {ARM_OP_PIMM,   ARM_REG_INVALID,    0,                  0,      ARM_REG_INVALID}
 562 #define MATCH_OP_PIMM(imm)          {ARM_OP_PIMM,   ARM_REG_INVALID,    MATCH_OP_FL_IMM,    (imm),  ARM_REG_INVALID}
 563 #define MATCH_OP_CIMM_ANY           {ARM_OP_CIMM,   ARM_REG_INVALID,    0,                  0,      ARM_REG_INVALID}
 564 #define MATCH_OP_CIMM(imm)          {ARM_OP_CIMM,   ARM_REG_INVALID,    MATCH_OP_FL_IMM,    (imm),  ARM_REG_INVALID}
 565 #define MATCH_OP_MEM_ANY            {ARM_OP_MEM,    ARM_REG_INVALID,    0,                  0,      ARM_REG_INVALID}
 566 #define MATCH_OP_MEM(rb,ri,imm)     {ARM_OP_MEM,    ARM_REG_##rb,       MATCH_OP_FL_IMM,    (imm),  ARM_REG_##ri}
 567 #define MATCH_OP_MEM_BASE(r)        {ARM_OP_MEM,    ARM_REG_##r,        0,                  0,      ARM_REG_INVALID}
 568 #define MATCH_OP_MEM_REGS(rb,ri)    {ARM_OP_MEM,    ARM_REG_##rb,       0,                  0,      ARM_REG_##ri}
 569 
 570 #define MATCH_MAX_OPS 16
 571 
 572 #define MATCH_OPCOUNT_ANY       -1 // match any operands specified in operands, without checking count
 573 #define MATCH_OPCOUNT_IGNORE    -2 // don't check ops at all
 574 
 575 #define MATCH_INS(ins,opcount)          ARM_INS_##ins,(opcount),ARM_CC_INVALID
 576 #define MATCH_INS_CC(ins,cc,opcount)    ARM_INS_##ins,(opcount),ARM_CC_##cc
 577 
 578 // use id ARM_INS_INVALID for don't care, ARM_INS_ENDING to end list of matches
 579 typedef struct {
 580     arm_insn id;
 581     int op_count; // negative = special values above
 582     arm_cc cc; // match condition code _INVALID = don't care
 583     op_match_t operands[MATCH_MAX_OPS];
 584 } insn_match_t;
 585 
 586 // some common matches for insn_match_find_next
 587 // match a B instruction
 588 extern const insn_match_t match_b[];
 589 
 590 // match B and BL
 591 extern const insn_match_t match_b_bl[];
 592 
 593 // match B and BL, and BLX with an immediate
 594 extern const insn_match_t match_b_bl_blximm[];
 595 
 596 // match only calls: BL or BLX imm
 597 extern const insn_match_t match_bl_blximm[];
 598 
 599 // match BX LR
 600 extern const insn_match_t match_bxlr[];
 601 
 602 // match LDR rx [pc, ...]
 603 extern const insn_match_t match_ldr_pc[];
 604 
 605 // check if single insn matches values defined by match
 606 int insn_match(cs_insn *insn, const insn_match_t *match);
 607 
 608 // check if single insn matches any of the provided matches
 609 int insn_match_any(cs_insn *insn,const insn_match_t *match);
 610 
 611 // iterate is until current instruction matches any of the provided matches or until limit reached
 612 int insn_match_find_next(firmware *fw, iter_state_t *is, int max_insns, const insn_match_t *match);
 613 
 614 // iterate is until current has matched any of the provided matches N times or until max_insns reached
 615 int insn_match_find_nth(firmware *fw, iter_state_t *is, int max_insns, int num_to_match, const insn_match_t *match);
 616 
 617 // iterate as long as sequence of instructions matches sequence defined in match
 618 int insn_match_seq(firmware *fw, iter_state_t *is, const insn_match_t *match);
 619 
 620 // find next matching sequence starting within max_insns
 621 int insn_match_find_next_seq(firmware *fw, iter_state_t *is, int max_insns, const insn_match_t *match);
 622 
 623 // ****** utilities for non-disasm searching ******
 624 // Search the firmware for something. The desired matching is performed using the supplied 'func' function.
 625 // Continues searching until 'func' returns non-zero - then returns 1
 626 // otherwise returns 0.
 627 // Uses the BufRange structs to speed up searching
 628 // Note: this version searches byte by byte in the firmware dump instead of by words
 629 // borrowed from finsig_dryos
 630 typedef int (*search_bytes_fn)(firmware*, int k);
 631 int fw_search_bytes(firmware *fw, search_bytes_fn func);
 632 
 633 // ****** firmware loading / initialization / de-allocation ******
 634 // add given address range
 635 void fw_add_adr_range(firmware *fw, uint32_t start, uint32_t end, uint32_t src_start, int type, int flags);
 636 
 637 // load firmware and initialize stuff that doesn't require disassembly
 638 void firmware_load(firmware *fw, const char *filename, uint32_t base_adr,int fw_arch);
 639 
 640 // initialize capstone state for loaded fw
 641 int firmware_init_capstone(firmware *fw);
 642 
 643 // init basic copied RAM code / data ranges - init_capstone must be called first
 644 void firmware_init_data_ranges(firmware *fw);
 645 
 646 // free resources associated with fw
 647 void firmware_unload(firmware *fw);
 648 #endif

/* [<][>][^][v][top][bottom][index][help] */