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 a BL instruction 591 extern const insn_match_t match_bl[]; 592 593 // match B and BL 594 extern const insn_match_t match_b_bl[]; 595 596 // match B and BL, and BLX with an immediate 597 extern const insn_match_t match_b_bl_blximm[]; 598 599 // match only calls: BL or BLX imm 600 extern const insn_match_t match_bl_blximm[]; 601 602 // match BX LR 603 extern const insn_match_t match_bxlr[]; 604 605 // match LDR rx [pc, ...] 606 extern const insn_match_t match_ldr_pc[]; 607 608 // check if single insn matches values defined by match 609 int insn_match(cs_insn *insn, const insn_match_t *match); 610 611 // check if single insn matches any of the provided matches 612 int insn_match_any(cs_insn *insn,const insn_match_t *match); 613 614 // iterate is until current instruction matches any of the provided matches or until limit reached 615 int insn_match_find_next(firmware *fw, iter_state_t *is, int max_insns, const insn_match_t *match); 616 617 // iterate is until current has matched any of the provided matches N times or until max_insns reached 618 int insn_match_find_nth(firmware *fw, iter_state_t *is, int max_insns, int num_to_match, const insn_match_t *match); 619 620 // iterate as long as sequence of instructions matches sequence defined in match 621 int insn_match_seq(firmware *fw, iter_state_t *is, const insn_match_t *match); 622 623 // find next matching sequence starting within max_insns 624 int insn_match_find_next_seq(firmware *fw, iter_state_t *is, int max_insns, const insn_match_t *match); 625 626 // ****** utilities for non-disasm searching ****** 627 // Search the firmware for something. The desired matching is performed using the supplied 'func' function. 628 // Continues searching until 'func' returns non-zero - then returns 1 629 // otherwise returns 0. 630 // Uses the BufRange structs to speed up searching 631 // Note: this version searches byte by byte in the firmware dump instead of by words 632 // borrowed from finsig_dryos 633 typedef int (*search_bytes_fn)(firmware*, int k); 634 int fw_search_bytes(firmware *fw, search_bytes_fn func); 635 636 // ****** firmware loading / initialization / de-allocation ****** 637 // add given address range 638 void fw_add_adr_range(firmware *fw, uint32_t start, uint32_t end, uint32_t src_start, int type, int flags); 639 640 // load firmware and initialize stuff that doesn't require disassembly 641 void firmware_load(firmware *fw, const char *filename, uint32_t base_adr,int fw_arch); 642 643 // initialize capstone state for loaded fw 644 int firmware_init_capstone(firmware *fw); 645 646 // init basic copied RAM code / data ranges - init_capstone must be called first 647 void firmware_init_data_ranges(firmware *fw); 648 649 // free resources associated with fw 650 void firmware_unload(firmware *fw); 651 652 // get iter_state instruction address with optional thumb bit 653 #define iter_state_adr(is) ((uint32_t)is->insn->address | is->thumb) 654 #endif