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

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