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

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