CHDK_DE Vorschauversion  Trunk Rev. 5249
 Alle Datenstrukturen Dateien Funktionen Variablen Typdefinitionen Aufzählungen Aufzählungswerte Makrodefinitionen
firmware_load_ng.h-Dateireferenz
+ Dieser Graph zeigt, welche Datei direkt oder indirekt diese Datei enthält:

gehe zum Quellcode dieser Datei

Datenstrukturen

struct  bufrange
 
struct  adr_hist_t
 
struct  iter_state_t
 
struct  adr_range_t
 
struct  firmware
 
struct  tbx_info_t
 
struct  search_calls_multi_data_t
 
struct  var_ldr_desc_t
 
struct  op_match_t
 
struct  insn_match_t
 

Makrodefinitionen

#define MIN(a, b)   ((a) < (b) ? (a) : (b))
 
#define MAX(a, b)   ((a) > (b) ? (a) : (b))
 
#define FW_ARCH_ARMv5   1
 
#define FW_ARCH_ARMv7   2
 
#define ADR_SET_THUMB(x)   ((x)|1)
 
#define ADR_CLEAR_THUMB(x)   ((x)&~1)
 
#define ADR_IS_THUMB(x)   ((x)&1)
 
#define ADR_ALIGN4(x)   ((x)&~0x3)
 
#define ADR_ALIGN2(x)   ((x)&~0x1)
 
#define ADR_IS_ALIGN4(x)   (((x)&0x3)==0)
 
#define ADR_RANGE_INVALID   0
 
#define ADR_RANGE_ROM   1
 
#define ADR_RANGE_RAM_CODE   2
 
#define ADR_RANGE_INIT_DATA   3
 
#define ADR_HIST_SIZE   64
 
#define FW_MAX_ADR_RANGES   5
 
#define MATCH_OP_FL_IMM   0x0001
 
#define MATCH_OP_FL_LAST   0x0002
 
#define MATCH_OP_ANY   {ARM_OP_INVALID,ARM_REG_INVALID, 0, 0, ARM_REG_INVALID}
 
#define MATCH_OP_REST_ANY   {ARM_OP_INVALID,ARM_REG_INVALID, MATCH_OP_FL_LAST, 0, ARM_REG_INVALID}
 
#define MATCH_OP_REG_ANY   {ARM_OP_REG, ARM_REG_INVALID, 0, 0, ARM_REG_INVALID}
 
#define MATCH_OP_REG(r)   {ARM_OP_REG, ARM_REG_##r, 0, 0, ARM_REG_INVALID}
 
#define MATCH_OP_IMM_ANY   {ARM_OP_IMM, ARM_REG_INVALID, 0, 0, ARM_REG_INVALID}
 
#define MATCH_OP_IMM(imm)   {ARM_OP_IMM, ARM_REG_INVALID, MATCH_OP_FL_IMM, (imm), ARM_REG_INVALID}
 
#define MATCH_OP_MEM_ANY   {ARM_OP_MEM, ARM_REG_INVALID, 0, 0, ARM_REG_INVALID}
 
#define MATCH_OP_MEM(rb, ri, imm)   {ARM_OP_MEM, ARM_REG_##rb, MATCH_OP_FL_IMM, (imm), ARM_REG_##ri}
 
#define MATCH_OP_MEM_BASE(r)   {ARM_OP_MEM, ARM_REG_##r, 0, 0, ARM_REG_INVALID}
 
#define MATCH_OP_MEM_REGS(rb, ri)   {ARM_OP_MEM, ARM_REG_##rb, 0, 0, ARM_REG_##ri}
 
#define MATCH_MAX_OPS   16
 
#define MATCH_OPCOUNT_ANY   -1
 
#define MATCH_OPCOUNT_IGNORE   -2
 
#define MATCH_INS(ins, opcount)   ARM_INS_##ins,(opcount),ARM_CC_INVALID
 
#define MATCH_INS_CC(ins, cc, opcount)   ARM_INS_##ins,(opcount),ARM_CC_##cc
 

Typdefinitionen

typedef struct bufrange BufRange
 
typedef uint32_t(* search_insn_fn )(firmware *fw, iter_state_t *is, uint32_t v1, void *udata)
 
typedef int(* search_calls_multi_fn )(firmware *fw, iter_state_t *is, uint32_t adr)
 
typedef int(* search_bytes_fn )(firmware *, int k)
 

Funktionen

uint8_t * adr2ptr (firmware *fw, uint32_t adr)
 
uint8_t * adr2ptr_with_data (firmware *fw, uint32_t adr)
 
const char * adr_range_type_str (int type)
 
uint32_t ptr2adr (firmware *fw, uint8_t *ptr)
 
adr_range_tadr_get_range (firmware *fw, uint32_t adr)
 
int adr_is_var (firmware *fw, uint32_t adr)
 
int find_Nth_str (firmware *fw, char *str, int N)
 
int find_str (firmware *fw, char *str)
 
uint32_t find_str_bytes (firmware *fw, char *str)
 
int isASCIIstring (firmware *fw, uint32_t adr)
 
uint32_t find_u32_adr (firmware *fw, uint32_t val, uint32_t start)
 
uint32_t fw_u32 (firmware *fw, uint32_t adr)
 
int fw_memcmp (firmware *fw, uint32_t adr, const void *cmp, size_t n)
 
void adr_hist_reset (adr_hist_t *ah)
 
int adr_hist_index (adr_hist_t *ah, int i)
 
void adr_hist_add (adr_hist_t *ah, uint32_t adr)
 
uint32_t adr_hist_get (adr_hist_t *ah, int i)
 
int isARM (cs_insn *insn)
 
int isLDR_PC (cs_insn *insn)
 
int isLDR_PC_PC (cs_insn *insn)
 
uint32_tLDR_PC2valptr_thumb (firmware *fw, cs_insn *insn)
 
uint32_tLDR_PC2valptr_arm (firmware *fw, cs_insn *insn)
 
uint32_tLDR_PC2valptr (firmware *fw, cs_insn *insn)
 
uint32_t LDR_PC2adr (firmware *fw, cs_insn *insn)
 
int isSUBW_PC (cs_insn *insn)
 
int isADDW_PC (cs_insn *insn)
 
int isADD_PC (cs_insn *insn)
 
int isSUB_PC (cs_insn *insn)
 
int isRETx (cs_insn *insn)
 
int isPUSH_LR (cs_insn *insn)
 
int isPOP_LR (cs_insn *insn)
 
int isPOP_PC (cs_insn *insn)
 
int isADDx_imm (cs_insn *insn)
 
int isSUBx_imm (cs_insn *insn)
 
int isADRx (cs_insn *insn)
 
uint32_t ADRx2adr (firmware *fw, cs_insn *insn)
 
uint32_t ADR2adr (firmware *fw, cs_insn *insn)
 
uint32_tADR2valptr (firmware *fw, cs_insn *insn)
 
uint32_t LDR_PC2val (firmware *fw, cs_insn *insn)
 
uint32_t B_target (firmware *fw, cs_insn *insn)
 
uint32_t CBx_target (firmware *fw, cs_insn *insn)
 
uint32_t BLXimm_target (firmware *fw, cs_insn *insn)
 
uint32_t BL_target (firmware *fw, cs_insn *insn)
 
uint32_t B_BL_target (firmware *fw, cs_insn *insn)
 
uint32_t B_BL_BLXimm_target (firmware *fw, cs_insn *insn)
 
int get_TBx_PC_info (firmware *fw, iter_state_t *is, tbx_info_t *ti)
 
iter_state_tdisasm_iter_new (firmware *fw, uint32_t adr)
 
void disasm_iter_free (iter_state_t *is)
 
int disasm_iter_set (firmware *fw, iter_state_t *is, uint32_t adr)
 
int disasm_iter_init (firmware *fw, iter_state_t *is, uint32_t adr)
 
int disasm_iter (firmware *fw, iter_state_t *is)
 
int fw_disasm_iter_start (firmware *fw, uint32_t adr)
 
int fw_disasm_iter (firmware *fw)
 
int fw_disasm_iter_single (firmware *fw, uint32_t adr)
 
uint32_t fw_search_insn (firmware *fw, iter_state_t *is, search_insn_fn f, uint32_t v1, void *udata, uint32_t adr_end)
 
uint32_t search_disasm_const_ref (firmware *fw, iter_state_t *is, uint32_t val, void *unused)
 
uint32_t search_disasm_str_ref (firmware *fw, iter_state_t *is, uint32_t val, void *str)
 
uint32_t search_disasm_calls (firmware *fw, iter_state_t *is, uint32_t val, void *unused)
 
int search_calls_multi_end (firmware *fw, iter_state_t *is, uint32_t adr)
 
uint32_t search_disasm_calls_multi (firmware *fw, iter_state_t *is, uint32_t unused, void *userdata)
 
int get_call_const_args (firmware *fw, iter_state_t *is_init, int max_backtrack, uint32_t *res)
 
uint32_t get_direct_jump_target (firmware *fw, iter_state_t *is_init)
 
uint32_t get_branch_call_insn_target (firmware *fw, iter_state_t *is)
 
int find_and_get_var_ldr (firmware *fw, iter_state_t *is, int max_insns, arm_reg match_val_reg, var_ldr_desc_t *result)
 
int insn_match (cs_insn *insn, const insn_match_t *match)
 
int insn_match_any (cs_insn *insn, const insn_match_t *match)
 
int insn_match_find_next (firmware *fw, iter_state_t *is, int max_insns, const insn_match_t *match)
 
int insn_match_find_nth (firmware *fw, iter_state_t *is, int max_insns, int num_to_match, const insn_match_t *match)
 
int insn_match_seq (firmware *fw, iter_state_t *is, const insn_match_t *match)
 
int insn_match_find_next_seq (firmware *fw, iter_state_t *is, int max_insns, const insn_match_t *match)
 
int fw_search_bytes (firmware *fw, search_bytes_fn func)
 
void fw_add_adr_range (firmware *fw, uint32_t start, uint32_t end, uint32_t src_start, int type)
 
void firmware_load (firmware *fw, const char *filename, uint32_t base_adr, int fw_arch)
 
int firmware_init_capstone (firmware *fw)
 
void firmware_init_data_ranges (firmware *fw)
 
void firmware_unload (firmware *fw)
 

Variablen

const insn_match_t match_b []
 
const insn_match_t match_b_bl []
 
const insn_match_t match_b_bl_blximm []
 
const insn_match_t match_bl_blximm []
 
const insn_match_t match_bxlr []
 
const insn_match_t match_ldr_pc []
 

Makro-Dokumentation

#define ADR_ALIGN2 (   x)    ((x)&~0x1)

Definiert in Zeile 18 der Datei firmware_load_ng.h.

#define ADR_ALIGN4 (   x)    ((x)&~0x3)

Definiert in Zeile 17 der Datei firmware_load_ng.h.

#define ADR_CLEAR_THUMB (   x)    ((x)&~1)

Definiert in Zeile 14 der Datei firmware_load_ng.h.

#define ADR_HIST_SIZE   64

Definiert in Zeile 39 der Datei firmware_load_ng.h.

#define ADR_IS_ALIGN4 (   x)    (((x)&0x3)==0)

Definiert in Zeile 20 der Datei firmware_load_ng.h.

#define ADR_IS_THUMB (   x)    ((x)&1)

Definiert in Zeile 15 der Datei firmware_load_ng.h.

#define ADR_RANGE_INIT_DATA   3

Definiert in Zeile 26 der Datei firmware_load_ng.h.

#define ADR_RANGE_INVALID   0

Definiert in Zeile 23 der Datei firmware_load_ng.h.

#define ADR_RANGE_RAM_CODE   2

Definiert in Zeile 25 der Datei firmware_load_ng.h.

#define ADR_RANGE_ROM   1

Definiert in Zeile 24 der Datei firmware_load_ng.h.

#define ADR_SET_THUMB (   x)    ((x)|1)

Definiert in Zeile 13 der Datei firmware_load_ng.h.

#define FW_ARCH_ARMv5   1

Definiert in Zeile 8 der Datei firmware_load_ng.h.

#define FW_ARCH_ARMv7   2

Definiert in Zeile 10 der Datei firmware_load_ng.h.

#define FW_MAX_ADR_RANGES   5

Definiert in Zeile 72 der Datei firmware_load_ng.h.

#define MATCH_INS (   ins,
  opcount 
)    ARM_INS_##ins,(opcount),ARM_CC_INVALID

Definiert in Zeile 470 der Datei firmware_load_ng.h.

#define MATCH_INS_CC (   ins,
  cc,
  opcount 
)    ARM_INS_##ins,(opcount),ARM_CC_##cc

Definiert in Zeile 471 der Datei firmware_load_ng.h.

#define MATCH_MAX_OPS   16

Definiert in Zeile 465 der Datei firmware_load_ng.h.

#define MATCH_OP_ANY   {ARM_OP_INVALID,ARM_REG_INVALID, 0, 0, ARM_REG_INVALID}

Definiert in Zeile 454 der Datei firmware_load_ng.h.

#define MATCH_OP_FL_IMM   0x0001

Definiert in Zeile 450 der Datei firmware_load_ng.h.

#define MATCH_OP_FL_LAST   0x0002

Definiert in Zeile 451 der Datei firmware_load_ng.h.

#define MATCH_OP_IMM (   imm)    {ARM_OP_IMM, ARM_REG_INVALID, MATCH_OP_FL_IMM, (imm), ARM_REG_INVALID}

Definiert in Zeile 459 der Datei firmware_load_ng.h.

#define MATCH_OP_IMM_ANY   {ARM_OP_IMM, ARM_REG_INVALID, 0, 0, ARM_REG_INVALID}

Definiert in Zeile 458 der Datei firmware_load_ng.h.

#define MATCH_OP_MEM (   rb,
  ri,
  imm 
)    {ARM_OP_MEM, ARM_REG_##rb, MATCH_OP_FL_IMM, (imm), ARM_REG_##ri}

Definiert in Zeile 461 der Datei firmware_load_ng.h.

#define MATCH_OP_MEM_ANY   {ARM_OP_MEM, ARM_REG_INVALID, 0, 0, ARM_REG_INVALID}

Definiert in Zeile 460 der Datei firmware_load_ng.h.

#define MATCH_OP_MEM_BASE (   r)    {ARM_OP_MEM, ARM_REG_##r, 0, 0, ARM_REG_INVALID}

Definiert in Zeile 462 der Datei firmware_load_ng.h.

#define MATCH_OP_MEM_REGS (   rb,
  ri 
)    {ARM_OP_MEM, ARM_REG_##rb, 0, 0, ARM_REG_##ri}

Definiert in Zeile 463 der Datei firmware_load_ng.h.

#define MATCH_OP_REG (   r)    {ARM_OP_REG, ARM_REG_##r, 0, 0, ARM_REG_INVALID}

Definiert in Zeile 457 der Datei firmware_load_ng.h.

#define MATCH_OP_REG_ANY   {ARM_OP_REG, ARM_REG_INVALID, 0, 0, ARM_REG_INVALID}

Definiert in Zeile 456 der Datei firmware_load_ng.h.

#define MATCH_OP_REST_ANY   {ARM_OP_INVALID,ARM_REG_INVALID, MATCH_OP_FL_LAST, 0, ARM_REG_INVALID}

Definiert in Zeile 455 der Datei firmware_load_ng.h.

#define MATCH_OPCOUNT_ANY   -1

Definiert in Zeile 467 der Datei firmware_load_ng.h.

#define MATCH_OPCOUNT_IGNORE   -2

Definiert in Zeile 468 der Datei firmware_load_ng.h.

#define MAX (   a,
 
)    ((a) > (b) ? (a) : (b))

Definiert in Zeile 5 der Datei firmware_load_ng.h.

#define MIN (   a,
 
)    ((a) < (b) ? (a) : (b))

Definiert in Zeile 4 der Datei firmware_load_ng.h.

Dokumentation der benutzerdefinierten Typen

typedef struct bufrange BufRange
typedef int(* search_bytes_fn)(firmware *, int k)

Definiert in Zeile 525 der Datei firmware_load_ng.h.

typedef int(* search_calls_multi_fn)(firmware *fw, iter_state_t *is, uint32_t adr)

Definiert in Zeile 363 der Datei firmware_load_ng.h.

typedef uint32_t(* search_insn_fn)(firmware *fw, iter_state_t *is, uint32_t v1, void *udata)

Definiert in Zeile 336 der Datei firmware_load_ng.h.

Dokumentation der Funktionen

uint32_t ADR2adr ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 584 der Datei firmware_load_ng.c.

585 {
586  if(insn->id != ARM_INS_ADR) {
587  return 0;
588  }
589  // TODO - capstone doesn't appear to generate ADR for ARM
590  /*
591  if(cs_insn_group(fw->cs_handle,insn,ARM_GRP_ARM)) {
592  return 0;
593  }
594  */
595  return (insn->address&~3)+4+insn->detail->arm.operands[1].imm;
596 }
uint8_t* adr2ptr ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 174 der Datei firmware_load.c.

175 {
176  if ((fw->dryos_ver >= 51) && (fw->alt_base) && (adr >= fw->alt_base))
177  {
178  return ((char*)fw->buf) + (adr - fw->alt_base);
179  }
180  if ((fw->dryos_ver >= 50) && (adr < fw->base))
181  {
182  adr = (adr - fw->base2) + fw->base_copied;
183  }
184  return ((char*)fw->buf) + (adr - fw->base);
185 }
uint8_t* adr2ptr_with_data ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 189 der Datei firmware_load_ng.c.

190 {
191  adr_range_t *r=adr_get_range(fw,adr);
192  if(!r) {
193  return NULL;
194  }
195  switch(r->type) {
196  case ADR_RANGE_RAM_CODE:
197  case ADR_RANGE_INIT_DATA:
198  case ADR_RANGE_ROM:
199  return (r->buf)+(adr - r->start);
200  default:
201  return NULL;
202  }
203 }
uint32_t* ADR2valptr ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 599 der Datei firmware_load_ng.c.

600 {
601  uint32_t adr=ADR2adr(fw,insn);
602  return (uint32_t *)adr2ptr(fw,adr);
603 }
adr_range_t* adr_get_range ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 155 der Datei firmware_load_ng.c.

156 {
157  int i;
158  adr_range_t *r=fw->adr_ranges;
159  for(i=0;i<fw->adr_range_count;i++) {
160  if(adr >= r->start && adr < r->start + r->bytes) {
161  return r;
162  }
163  r++;
164  }
165  return NULL;
166 }
void adr_hist_add ( adr_hist_t ah,
uint32_t  adr 
)

Definiert in Zeile 303 der Datei firmware_load_ng.c.

304 {
305  ah->cur=adr_hist_index(ah,1);
306  ah->adrs[ah->cur]=adr;
307  if(ah->count < ADR_HIST_SIZE) {
308  ah->count++;
309  }
310 }
uint32_t adr_hist_get ( adr_hist_t ah,
int  i 
)

Definiert in Zeile 314 der Datei firmware_load_ng.c.

315 {
316  if(!ah->count || i > ah->count) {
317  return 0;
318  }
319  return ah->adrs[adr_hist_index(ah,-i)];
320 }
int adr_hist_index ( adr_hist_t ah,
int  i 
)

Definiert in Zeile 293 der Datei firmware_load_ng.c.

294 {
295  int r=(ah->cur+i)%ADR_HIST_SIZE;
296  if(r < 0) {
297  return ADR_HIST_SIZE + r;
298  }
299  return r;
300 }
void adr_hist_reset ( adr_hist_t ah)

Definiert in Zeile 284 der Datei firmware_load_ng.c.

285 {
286  ah->cur=0;
287  ah->count=0;
288  // memset shouldn't be needed
289  // memset(ah->adrs,0,ADR_HIST_SIZE*4);
290 }
int adr_is_var ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 223 der Datei firmware_load_ng.c.

224 {
225  return (adr > fw->data_start && adr < fw->memisostart);
226 }
const char* adr_range_type_str ( int  type)

Definiert in Zeile 206 der Datei firmware_load_ng.c.

207 {
208  switch(type) {
209  case ADR_RANGE_INVALID:
210  return "(invalid)";
211  case ADR_RANGE_ROM:
212  return "ROM";
213  case ADR_RANGE_RAM_CODE:
214  return "RAM code";
215  case ADR_RANGE_INIT_DATA:
216  return "RAM data";
217  default:
218  return "(unknown)";
219  }
220 }
uint32_t ADRx2adr ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 560 der Datei firmware_load_ng.c.

561 {
562  if(insn->id == ARM_INS_ADR) {
563  return (insn->address&~3)+4+insn->detail->arm.operands[1].imm;
564  }
565  if(isSUBW_PC(insn)) {
566  return (insn->address&~3)+4-insn->detail->arm.operands[2].imm;
567  }
568  if(isADDW_PC(insn)) {
569  return (insn->address&~3)+4+insn->detail->arm.operands[2].imm;
570  }
571  if(isARM(insn)) {
572  if(isADD_PC(insn)) {
573  return insn->address+8+insn->detail->arm.operands[2].imm;
574  }
575  if(isSUB_PC(insn)) {
576  return insn->address+8-insn->detail->arm.operands[2].imm;
577  }
578  }
579  return 0;
580 }
uint32_t B_BL_BLXimm_target ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 673 der Datei firmware_load_ng.c.

674 {
675  if(insn->id == ARM_INS_B
676  || insn->id == ARM_INS_BL
677  || (insn->id == ARM_INS_BLX && insn->detail->arm.operands[0].type == ARM_OP_IMM)) {
678  return insn->detail->arm.operands[0].imm;
679  }
680  return 0; // TODO could be valid
681 }
uint32_t B_BL_target ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 663 der Datei firmware_load_ng.c.

664 {
665  if(insn->id == ARM_INS_B || insn->id == ARM_INS_BL) {
666  return insn->detail->arm.operands[0].imm;
667  }
668  return 0; // TODO could be valid
669 }
uint32_t B_target ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 625 der Datei firmware_load_ng.c.

626 {
627  if(insn->id == ARM_INS_B) {
628  return insn->detail->arm.operands[0].imm;
629  }
630  return 0; // TODO could be valid
631 }
uint32_t BL_target ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 654 der Datei firmware_load_ng.c.

655 {
656  if(insn->id == ARM_INS_BL) {
657  return insn->detail->arm.operands[0].imm;
658  }
659  return 0; // TODO could be valid
660 }
uint32_t BLXimm_target ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 644 der Datei firmware_load_ng.c.

645 {
646  if(insn->id == ARM_INS_BLX && insn->detail->arm.operands[0].type == ARM_OP_IMM) {
647  return insn->detail->arm.operands[0].imm;
648  }
649  return 0; // TODO could be valid
650 }
uint32_t CBx_target ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 635 der Datei firmware_load_ng.c.

636 {
637  if(insn->id == ARM_INS_CBZ || insn->id == ARM_INS_CBNZ) {
638  return insn->detail->arm.operands[1].imm;
639  }
640  return 0; // TODO could be valid
641 }
int disasm_iter ( firmware fw,
iter_state_t is 
)

Definiert in Zeile 849 der Datei firmware_load_ng.c.

850 {
851  // iter_start not called or invalid
852  if(!is->code) {
853  return 0;
854  }
855  adr_hist_add(&is->ah,(uint32_t)is->adr | is->thumb); // record thumb state to allow backtracking through state changes
856  return cs_disasm_iter(is->cs_handle, &is->code, &is->size, &is->adr, is->insn);
857 }
void disasm_iter_free ( iter_state_t is)

Definiert in Zeile 794 der Datei firmware_load_ng.c.

795 {
796  cs_free(is->insn,1);
797  free(is);
798  return;
799 }
int disasm_iter_init ( firmware fw,
iter_state_t is,
uint32_t  adr 
)

Definiert in Zeile 840 der Datei firmware_load_ng.c.

841 {
842  adr_hist_reset(&is->ah);
843  return disasm_iter_set(fw,is,adr);
844 }
iter_state_t* disasm_iter_new ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 783 der Datei firmware_load_ng.c.

784 {
786  // it doesn't currently appear to matter which handle is used to allocate
787  // only used for overridable malloc functions and error reporting
788  is->insn=cs_malloc(fw->cs_handle_arm);
789  disasm_iter_init(fw,is,adr);
790  return is;
791 }
int disasm_iter_set ( firmware fw,
iter_state_t is,
uint32_t  adr 
)

Definiert in Zeile 803 der Datei firmware_load_ng.c.

804 {
805  // set handle based on thumb bit to allow disassembly
806  if(ADR_IS_THUMB(adr)) {
807  is->cs_handle=fw->cs_handle_thumb;
808  is->thumb=1;
809  is->insn_min_size=2;
810  adr=ADR_CLEAR_THUMB(adr);// ADR used for iteration must not contain thumb bit
811  } else {
812  is->cs_handle=fw->cs_handle_arm;
813  is->thumb=0;
814  is->insn_min_size=4;
815  if(!ADR_IS_ALIGN4(adr)) {
816  fprintf(stderr,"disasm_iter_set: unaligned ARM address 0x%08x\n",adr);
817  is->code=NULL;
818  is->size=0;
819  is->adr=0;
820  return 0;
821  }
822  }
823  uint8_t *p=adr2ptr(fw,adr);
824  if(!p) {
825 // TODO invalid currently allowed, for new
826 // fprintf(stderr,"disasm_iter_set: bad address 0x%08x\n",adr);
827  is->code=NULL; // make first iter fail
828  is->size=0;
829  is->adr=0;
830  return 0;
831  }
832  // TODO should maybe mark is.insn invalid?
833  is->code=p;
834  is->size=fw->size8 - (p-fw->buf8);
835  is->adr=adr;
836  return 1;
837 }
int find_and_get_var_ldr ( firmware fw,
iter_state_t is,
int  max_insns,
arm_reg  match_val_reg,
var_ldr_desc_t result 
)

Definiert in Zeile 1340 der Datei firmware_load_ng.c.

1346 {
1347  var_ldr_desc_t r;
1348  int i=0;
1349  while(i < max_insns) {
1350  // disassembly failed, no match (could ignore..)
1351  if(!disasm_iter(fw,is)) {
1352  return 0;
1353  }
1354  if(!isLDR_PC(is->insn)) {
1355  continue;
1356  }
1357  r.reg_base=is->insn->detail->arm.operands[0].reg;
1358  r.adr_base=LDR_PC2val(fw,is->insn);
1359  if(!disasm_iter(fw,is)) {
1360  return 0;
1361  }
1362  i++;
1363  // firmware may use add/sub to get actual firmware base address
1364  if(isADDx_imm(is->insn) || isSUBx_imm(is->insn)) {
1365  if(is->insn->detail->arm.operands[0].reg != r.reg_base) {
1366  continue;
1367  }
1368  if(isADDx_imm(is->insn)) {
1369  r.adj=is->insn->detail->arm.operands[1].imm;
1370  } else {
1371  r.adj=-is->insn->detail->arm.operands[1].imm;
1372  }
1373  if(!disasm_iter(fw,is)) {
1374  return 0;
1375  }
1376  i++;
1377  } else {
1378  r.adj=0;
1379  }
1380  if(is->insn->id != ARM_INS_LDR || is->insn->detail->arm.operands[1].reg != r.reg_base) {
1381  continue;
1382  }
1383  r.reg_val = is->insn->detail->arm.operands[0].reg;
1384  if(match_val_reg != ARM_REG_INVALID && (r.reg_val != match_val_reg)) {
1385  continue;
1386  }
1387  r.off = is->insn->detail->arm.operands[1].mem.disp;
1388  r.adr_adj = r.adr_base + r.adj;
1389  r.adr_final = r.adr_adj + r.off;
1390  memcpy(result,&r,sizeof(r));
1391  return 1;
1392  }
1393  return 0;
1394 }
int find_Nth_str ( firmware fw,
char *  str,
int  N 
)

Definiert in Zeile 642 der Datei firmware_load.c.

643 {
644  int nlen = strlen(str);
645  uint32_t nm0 = *((uint32_t*)str);
646  uint32_t *p;
647  int j;
648 
649  BufRange *br = fw->br;
650  while (br)
651  {
652  for (p = br->p, j = 0; j < br->len - nlen/4; j++, p++)
653  {
654  if ((nm0 == *p) && ((nlen<=4) || (memcmp(p+1,str+4,nlen-4) == 0)) )
655  {
656  if (--N == 0)
657  return j+br->off;
658  }
659  }
660  br = br->next;
661  }
662 
663  return -1;
664 }
int find_str ( firmware fw,
char *  str 
)

Definiert in Zeile 666 der Datei firmware_load.c.

667 {
668  return find_Nth_str(fw, str, 1);
669 }
uint32_t find_str_bytes ( firmware fw,
char *  str 
)

Definiert in Zeile 673 der Datei firmware_load.c.

674 {
675  BufRange *p = fw->br;
676  while (p)
677  {
678  int k;
679  for (k = p->off*4; k < (p->off + p->len)*4; k++)
680  {
681  if (strcmp(((char*)fw->buf)+k,str) == 0)
682  return fw->base+k;
683  }
684  p = p->next;
685  }
686 
687  return 0;
688 }
uint32_t find_u32_adr ( firmware fw,
uint32_t  val,
uint32_t  start 
)

Definiert in Zeile 232 der Datei firmware_load_ng.c.

233 {
234  // TODO
235  if(start == 0) {
236  start=fw->base;
237  }
238  if(start & 3) {
239  fprintf(stderr,"find_u32_adr unaligned start 0x%08x\n",start);
240  return 0;
241  }
242  uint32_t *p=(uint32_t *)adr2ptr(fw,start);
243  if(!p) {
244  fprintf(stderr,"find_u32_adr bad start 0x%08x\n",start);
245  return 0;
246  }
247  uint32_t *p_end=fw->buf32 + fw->size32;
248  while(p<p_end) {
249  if(*p==val) {
250  return ptr2adr(fw,(uint8_t *)p);
251  }
252  p++;
253  }
254  return 0;
255 }
int firmware_init_capstone ( firmware fw)

Definiert in Zeile 1793 der Datei firmware_load_ng.c.

1794 {
1795  if (cs_open(CS_ARCH_ARM, CS_MODE_ARM, &fw->cs_handle_arm) != CS_ERR_OK) {
1796  fprintf(stderr,"cs_open ARM failed\n");
1797  return 0;
1798  }
1799  cs_option(fw->cs_handle_arm, CS_OPT_DETAIL, CS_OPT_ON);
1800  if (cs_open(CS_ARCH_ARM, CS_MODE_THUMB, &fw->cs_handle_thumb) != CS_ERR_OK) {
1801  fprintf(stderr,"cs_open thumb failed\n");
1802  return 0;
1803  }
1804  cs_option(fw->cs_handle_thumb, CS_OPT_DETAIL, CS_OPT_ON);
1805  fw->is=disasm_iter_new(fw,0);
1806  do_blx_check(fw);
1807  return 1;
1808 }
void firmware_init_data_ranges ( firmware fw)

highest known first copied ram code 0x01900000

Definiert in Zeile 1869 der Datei firmware_load_ng.c.

1870 {
1871 //TODO maybe should return status
1872  uint32_t src_start, dst_start, dst_end;
1873  uint32_t data_found_copy = 0;
1874 
1875  // start at fw start + 12 (32 bit jump, gaonisoy)
1876  iter_state_t *is=disasm_iter_new(fw, fw->base + fw->main_offs + 12 + fw->thumb_default);
1877 
1878  fw->data_init_start=0;
1879  fw->data_start=0;
1880  fw->data_len=0;
1881 
1882  fw->memisostart=0;
1883 
1884  int base2_found=0;
1885  int base3_found=0;
1886 
1887  // TODO pre-d6 ROMs have a lot more stuff before first copy
1888  int max_search=100;
1889  while(find_startup_copy(fw,is,max_search,&src_start,&dst_start,&dst_end)) {
1890  // all known copied code is 3f1000 or higher, guess data
1891  if(dst_start < 0x100000) {
1892  // fprintf(stderr, "data? @0x%"PRIx64" 0x%08x-0x%08x from 0x%08x\n",is->adr,dst_start,dst_end,src_start);
1893  if(fw->data_init_start) {
1894  fprintf(stderr,"firmware_init_data_ranges: data already found, unexpected start 0x%08x src 0x%08x end 0x%08x\n",
1895  dst_start,src_start,dst_end);
1896  continue;
1897  }
1898 
1899  // not a known value, warn
1900  if(dst_start != 0x1900 && dst_start != 0x8000) {
1901  fprintf(stderr,"firmware_init_data_ranges: guess unknown ROM data_start 0x%08x src 0x%08x end 0x%08x\n",
1902  dst_start,src_start,dst_end);
1903  }
1904  fw->data_init_start=src_start;
1905  fw->data_start=dst_start;
1906  fw->data_len=dst_end-dst_start;
1907  fw_add_adr_range(fw,dst_start,dst_end,src_start, ADR_RANGE_INIT_DATA);
1908  data_found_copy=is->adr;
1909  } else if(dst_start < 0x08000000) {
1910  // fprintf(stderr,"code1? @0x%"PRIx64" 0x%08x-0x%08x from 0x%08x\n",is->adr,dst_start,dst_end,src_start);
1911  if(base2_found) {
1912  fprintf(stderr,"firmware_init_data_ranges: base2 already found, unexpected start 0x%08x src 0x%08x end 0x%08x\n",
1913  dst_start,src_start,dst_end);
1914  continue;
1915  }
1916  base2_found=1;
1917  // known values
1918  if( dst_start != 0x003f1000 &&
1919  dst_start != 0x00431000 &&
1920  dst_start != 0x00471000 &&
1921  dst_start != 0x00685000 &&
1922  dst_start != 0x00671000 &&
1923  dst_start != 0x006b1000 &&
1924  dst_start != 0x010c1000 &&
1925  dst_start != 0x010e1000 &&
1926  dst_start != 0x01900000) {
1927  fprintf(stderr,"firmware_init_data_ranges: guess unknown base2 0x%08x src 0x%08x end 0x%08x\n",
1928  dst_start,src_start,dst_end);
1929  }
1930  fw_add_adr_range(fw,dst_start,dst_end,src_start,ADR_RANGE_RAM_CODE);
1931  } else { // know < ROM based on match, assume second copied code
1932  // fprintf(stderr, "code2? @0x%"PRIx64" 0x%08x-0x%08x from 0x%08x\n",is->adr,dst_start,dst_end,src_start);
1933  if(base3_found) {
1934  fprintf(stderr,"firmware_init_data_ranges: base3 already found, unexpected start 0x%08x src 0x%08x end 0x%08x\n",
1935  dst_start,src_start,dst_end);
1936  continue;
1937  }
1938  base3_found=1;
1939  if(dst_start != 0xbfe10800 && // known digic 6 value (g5x)
1940  dst_start != 0xdffc4900) { // known digic 7 value (m5)
1941  fprintf(stderr,"firmware_init_data_ranges: guess unknown base3 0x%08x src 0x%08x end 0x%08x\n",
1942  dst_start,src_start,dst_end);
1943  }
1944  fw_add_adr_range(fw,dst_start,dst_end,src_start,ADR_RANGE_RAM_CODE);
1945  }
1946  if(fw->data_start && base2_found && base3_found) {
1947  break;
1948  }
1949  // after first, shorter search range in between copies
1950  max_search=16;
1951  }
1952 
1953  // look for BSS init after last found copy
1954  if(data_found_copy) {
1955  int count=0;
1956  uint32_t *eptr=NULL;
1957  uint32_t *dptr=NULL;
1958  disasm_iter_init(fw,is,(data_found_copy-4) | fw->thumb_default);
1959  while(disasm_iter(fw,is) && count < 20) {
1960  uint32_t *pv=LDR_PC2valptr(fw,is->insn);
1961  // not an LDR pc, reset;
1962  if(!pv) {
1963  //dptr=eptr=NULL;
1964  } else if(!dptr) {
1965  // TODO older firmwares use reg with ending value from DATA copy
1966  // should be equal to end pointer of data
1967  if(*pv == fw->data_start + fw->data_len) {
1968  dptr=pv;
1969  }
1970  } else if(!eptr) {
1971  if(*pv < fw->base) {
1972  if(*pv != fw->data_start + fw->data_len) {
1973  eptr=pv;
1974  }
1975  } else { // dest end address in ROM, reset
1976  eptr=dptr=NULL;
1977  }
1978  }
1979  if(dptr && eptr) {
1980  // fprintf(stderr, "bss? @0x%"PRIx64" 0x%08x-0x%08x\n",is->adr,*dptr,*eptr);
1981  fw->memisostart=*eptr;
1982  break;
1983  }
1984  count++;
1985  }
1986  }
1987  // if data found, adjust default code search range
1988  // TODO could use copied code regions too, but after data on known firmwares
1989  if(fw->data_start) {
1991  }
1992  disasm_iter_free(is);
1993 }
void firmware_load ( firmware fw,
const char *  filename,
uint32_t  base_adr,
int  fw_arch 
)

Definiert in Zeile 1660 der Datei firmware_load_ng.c.

1661 {
1662  FILE *f = fopen(filename, "rb");
1663  if (f == NULL)
1664  {
1665  fprintf(stderr,"Error opening %s\n",filename);
1666  exit(1);
1667  }
1668  fseek(f,0,SEEK_END);
1669  fw->size8 = ftell(f);
1670  fseek(f,0,SEEK_SET);
1671  // dumps should be an integral number of 32 bit words
1672  // ensures accessing as 32 bit ints safe
1673  if(fw->size8&3) {
1674  fprintf(stderr,"WARNING: dump size %d is not divisible by 4, truncating\n",fw->size8);
1675  fw->size8 &= ~3;
1676  }
1677 
1678  // adjust to ensure base_adr + size doesn't overflow
1679  if(0xFFFFFFFF - base_adr < fw->size8) {
1680  fprintf(stderr,"adjusted dump size 0x%08x->",fw->size8);
1681  fw->size8 = 0xFFFFFFFC - base_adr;
1682  fprintf(stderr,"0x%08x\n",fw->size8);
1683  }
1684 
1685  fw->arch=fw_arch;
1686  fw->size32=fw->size8/4;
1687 
1688  fw->base = base_adr;
1689 
1690  fw->buf8 = malloc(fw->size8);
1691  if(!fw->buf8) {
1692  fprintf(stderr,"malloc %d failed\n",fw->size8);
1693  exit(1);
1694  }
1695  fread(fw->buf8, 1, fw->size8, f);
1696  fclose(f);
1697  findRanges(fw);
1698 
1699  fw->adr_range_count=0;
1700  // add ROM
1701  fw_add_adr_range(fw,fw->base, fw->base+fw->size8, fw->base, ADR_RANGE_ROM);
1702 
1703  fw->main_offs = 0;
1704  int k = find_str(fw, "gaonisoy");
1705  // assume firmware start is 32 bit jump over goanisoy
1706  if(k == -1) {
1707  // suppress warning on vxworks, main firmware start is always offset 0
1708  if(find_str(fw,"VxWorks") == -1) {
1709  fprintf(stderr,"WARNING gaonisoy string not found, assuming code start offset 0\n");
1710  }
1711  } else if (k != 1) {
1712  // check at 0x20004 - note doesn't just use offset of first gaonisoy, because could be ref'd in romstarter
1713  if(fw_memcmp(fw,fw->base+0x20004,"gaonisoy",8) == 0) {
1714  fw->main_offs = 0x20000;
1715  } else {
1716  fprintf(stderr,"WARNING code start offset not found, assuming 0\n");
1717  }
1718  }
1719  k = find_str(fw, "DRYOS version 2.3, release #");
1720  if (k != -1)
1721  {
1722  fw->dryos_ver = atoi((char *)fw->buf8 + k*4 + 28);
1723  fw->dryos_ver_str = (char *)fw->buf8 + k*4;
1724  } else {
1725  fw->dryos_ver=0;
1726  fw->dryos_ver_str=NULL;
1727  }
1728 
1729  fw->firmware_ver_str = 0;
1730  k = find_str(fw, "Firmware Ver ");
1731  if (k != -1)
1732  {
1733  fw->firmware_ver_str = (char *)fw->buf8 + k*4;
1734  }
1735  fw->rom_code_search_min_adr = fw->base + fw->main_offs; // 0 if not found
1736  fw->rom_code_search_max_adr=fw->base+fw->size8 - 4; // default == end of fw, may be adjusted by firmware_init_data_ranges
1737  // set expected instruction set
1738  if(fw->arch==FW_ARCH_ARMv5) {
1739  fw->thumb_default = 0;
1740  } else if(fw->arch==FW_ARCH_ARMv7) {
1741  fw->thumb_default = 1;
1742  } else {
1743  fprintf(stderr,"firmware_init_capstone: invalid arch\n");
1744  }
1745 }
void firmware_unload ( firmware fw)

Definiert in Zeile 1996 der Datei firmware_load_ng.c.

1997 {
1998  if(!fw) {
1999  return;
2000  }
2001  if(fw->is) {
2002  disasm_iter_free(fw->is);
2003  }
2004  if(fw->cs_handle_arm) {
2005  cs_close(&fw->cs_handle_arm);
2006  }
2007  if(fw->cs_handle_thumb) {
2008  cs_close(&fw->cs_handle_thumb);
2009  }
2010  free(fw->buf8);
2011  memset(fw,0,sizeof(firmware));
2012 }
void fw_add_adr_range ( firmware fw,
uint32_t  start,
uint32_t  end,
uint32_t  src_start,
int  type 
)

Definiert in Zeile 1620 der Datei firmware_load_ng.c.

1621 {
1622  if(fw->adr_range_count == FW_MAX_ADR_RANGES) {
1623  fprintf(stderr,"fw_add_adr_range: FW_MAX_ADR_RANGES hit\n");
1624  return;
1625  }
1626  if(src_start < fw->base) {
1627  fprintf(stderr,"fw_add_adr_range: src_start 0x%08x < base 0x%08x\n",src_start,fw->base);
1628  return;
1629  }
1630  if(src_start >= fw->base+fw->size8) {
1631  fprintf(stderr,"fw_add_adr_range: src_start 0x%08x outside dump end 0x%08x\n",src_start,fw->base+fw->size8);
1632  return;
1633  }
1634  if(end <= start) {
1635  fprintf(stderr,"fw_add_adr_range: end 0x%08x <= start 0x%08x\n",end,start);
1636  return;
1637  }
1638  int len=end-start;
1639  if(len > 0xFFFFFFFF - src_start) {
1640  fprintf(stderr,"fw_add_adr_range: range too long %d\n",len);
1641  return;
1642  }
1643  if(len > fw->size8 - (start - fw->base)) {
1644  fprintf(stderr,"fw_add_adr_range: range outside of dump %d\n",len);
1645  return;
1646  }
1647  adr_range_t *r=&fw->adr_ranges[fw->adr_range_count];
1648  // TODO some firmware copies (i.e. g5x code 2) may end on non-word aligned address even though copy is words
1649  r->start=start;
1650  r->src_start=src_start;
1651  r->bytes=len;
1652  r->type=type;
1653  r->buf=fw->buf8 + (r->src_start - fw->base);
1654 
1655  fw->adr_range_count++;
1656 }
int fw_disasm_iter ( firmware fw)

Definiert in Zeile 886 der Datei firmware_load_ng.c.

887 {
888  return disasm_iter(fw,fw->is);
889 }
int fw_disasm_iter_single ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 893 der Datei firmware_load_ng.c.

894 {
895  fw_disasm_iter_start(fw,adr);
896  return fw_disasm_iter(fw);
897 }
int fw_disasm_iter_start ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 880 der Datei firmware_load_ng.c.

881 {
882  return disasm_iter_init(fw,fw->is,adr);
883 }
int fw_memcmp ( firmware fw,
uint32_t  adr,
const void *  cmp,
size_t  n 
)

Definiert in Zeile 269 der Datei firmware_load_ng.c.

270 {
271  uint32_t *p=(uint32_t *)adr2ptr(fw,adr);
272  if(!p) {
273  return 1;
274  }
275  if(n >= fw->size8 - (adr - fw->base)) {
276  return 1;
277  }
278  return memcmp(p,cmp,n);
279 }
int fw_search_bytes ( firmware fw,
search_bytes_fn  func 
)

Definiert in Zeile 1601 der Datei firmware_load_ng.c.

1602 {
1603  BufRange *p = fw->br;
1604  while (p)
1605  {
1606  int k;
1607  for (k = p->off*4; k < (p->off + p->len)*4; k++)
1608  {
1609  if (func(fw,k))
1610  return 1;
1611  }
1612  p = p->next;
1613  }
1614  return 0;
1615 }
uint32_t fw_search_insn ( firmware fw,
iter_state_t is,
search_insn_fn  f,
uint32_t  v1,
void *  udata,
uint32_t  adr_end 
)

Definiert in Zeile 927 der Datei firmware_load_ng.c.

928 {
929  uint32_t adr_start=is->adr;
930  adr_range_t *r_start=adr_get_range(fw,adr_start);
931  if(!r_start) {
932  fprintf(stderr,"fw_search_insn: invalid start address 0x%08x\n",adr_start);
933  return 0;
934  }
935 
936  // default to end of start range
937  if(!adr_end) {
938  if(r_start->type == ADR_RANGE_ROM) {
939  adr_end = fw->rom_code_search_max_adr;
940  } else {
941  adr_end=r_start->start + r_start->bytes - is->insn_min_size;
942  }
943  }
944  adr_range_t *r_end=adr_get_range(fw,adr_end);
945 
946  if(!r_end) {
947  fprintf(stderr,"fw_search_insn: invalid end address 0x%08x\n",adr_end);
948  return 0;
949  }
950  // ignore thumb bit on end adr
951  adr_end=ADR_CLEAR_THUMB(adr_end);
952 
953  if((r_start != r_end) || (adr_end < adr_start)) {
954  fprintf(stderr,"fw_search_insn: invalid address range 0x%08x 0x%08x\n",adr_start,adr_end);
955  return 0;
956  }
957 
958  uint32_t adr=adr_start;
959  // don't bother with buf ranges for RAM code
960  if(r_start->type != ADR_RANGE_ROM) {
961  while(adr < adr_end) {
962  if(disasm_iter(fw,is)) {
963  uint32_t r=f(fw,is,v1,udata);
964  if(r) {
965  return r;
966  }
967  adr=(uint32_t)is->adr; // adr was updated by iter or called sub
968  } else {
969  // disassembly failed
970  // increment by minimum instruction size and re-init
971  adr=adr+is->insn_min_size;
972  if(!disasm_iter_init(fw,is,adr|is->thumb)) {
973  fprintf(stderr,"fw_search_insn: disasm_iter_init failed\n");
974  return 0;
975  }
976  }
977  }
978  return 0;
979  }
980  BufRange *br=fw->br;
981  // TODO might want to (optionally?) turn off details? For now, caller can set, doesn't seem to help perf much
982  // TODO when searching ROM, could skip over RAM copied areas (currently just limit default range)
983  while(br && adr < adr_end) {
984  uint32_t *p_adr=(uint32_t *)adr2ptr(fw,(uint32_t)adr);
985  uint32_t *br_end = br->p + br->len;
986  uint32_t adr_chunk_end = ptr2adr(fw,(uint8_t*)br_end);
987  if(adr_end < adr_chunk_end) {
988  adr_chunk_end = adr_end;
989  }
990  // address is before start of current range, adjust
991  if(p_adr < br->p) {
992  adr=ptr2adr(fw,(uint8_t *)br->p);
993  if(!disasm_iter_init(fw,is,(uint32_t)adr)) {
994  return 0;
995  }
996  p_adr=(uint32_t *)adr2ptr(fw,(uint32_t)adr);
997  }
998  //printf("br:0x%08x-0x%08x\n",ptr2adr(fw,(uint8_t *)br->p),ptr2adr(fw,(uint8_t *)(br->p+br->len)));
999  while(adr < adr_chunk_end) {
1000  if(disasm_iter(fw,is)) {
1001  uint32_t r=f(fw,is,v1,udata);
1002  if(r) {
1003  return r;
1004  }
1005  adr=(uint32_t)is->adr; // adr was updated by iter or called sub
1006  } else {
1007  // disassembly failed. cs_disarm_iter does not update address
1008  // increment by half word and re-init
1009  adr=adr+is->insn_min_size;
1010  if(!disasm_iter_init(fw,is,adr|is->thumb)) {
1011  fprintf(stderr,"fw_search_insn: disasm_iter_init failed\n");
1012  return 0;
1013  }
1014  }
1015  }
1016  // next range
1017  br=br->next;
1018  }
1019  return 0;
1020 }
uint32_t fw_u32 ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 258 der Datei firmware_load_ng.c.

259 {
260  uint32_t *p=(uint32_t *)adr2ptr(fw,adr);
261  if(!p) {
262  fprintf(stderr,"fw_u32 bad adr 0x%08x\n",adr);
263  return 0;
264  }
265  return *p;
266 }
uint32_t get_branch_call_insn_target ( firmware fw,
iter_state_t is 
)

Definiert in Zeile 1300 der Datei firmware_load_ng.c.

1301 {
1302  uint32_t adr=B_BL_target(fw,is->insn);
1303  if(adr) {
1304  return (adr | is->thumb);
1305  }
1306  // CBx only exists in thumb
1307  if(is->thumb) {
1308  adr=CBx_target(fw,is->insn);
1309  if(adr) {
1310  return ADR_SET_THUMB(adr);
1311  }
1312  }
1313 
1314  adr=BLXimm_target(fw,is->insn);
1315  if(adr) {
1316  if(is->thumb) {
1317  return adr;
1318  } else {
1319  return adr | is->thumb;
1320  }
1321  }
1322 
1323  adr=LDR_PC_PC_target(fw,is->insn);
1324  if(adr) {
1325  return adr;
1326  }
1327  return 0;
1328 }
int get_call_const_args ( firmware fw,
iter_state_t is_init,
int  max_backtrack,
uint32_t res 
)

Definiert in Zeile 1120 der Datei firmware_load_ng.c.

1121 {
1122  int i;
1123  /*
1124  static int dbg_count=0;
1125  if(is_init->insn->address==...) {
1126  dbg_count=1;
1127  } else {
1128  dbg_count=0;
1129  }
1130  */
1131 
1132  // init regs to zero (to support adds etc)
1133  for (i=0;i<4;i++) {
1134  res[i]=0;
1135  }
1136 
1137  // count includes current instruction (i.e. BL of call)
1138  if(is_init->ah.count <= 1) {
1139  return 0;
1140  }
1141  if(is_init->ah.count - 1 < max_backtrack) {
1142  /*
1143  if(dbg_count > 0) {
1144  printf("max_backtrack %d hist count %d\n",max_backtrack,is_init->ah.count);
1145  }
1146  */
1147  max_backtrack = is_init->ah.count-1;
1148  }
1149  uint32_t found_bits=0; // registers with known const values
1150  uint32_t known_bits=0; // registers with some value
1151 
1152  for(i=1;i<=max_backtrack && known_bits !=0xf;i++) {
1153  // TODO going backwards and calling start each time inefficient
1154  // forward could also find multi-instruction constants in some cases (e.g mov + add, movw + movt)
1155  fw_disasm_iter_single(fw,adr_hist_get(&is_init->ah,i)); // thumb state comes from hist
1156  /*
1157  if(dbg_count > 0) {
1158  printf("backtrack %d:%d ",dbg_count,i);
1159  printf("%"PRIx64" %s %s\n",fw->is->insn->address,fw->is->insn->mnemonic, fw->is->insn->op_str);
1160  }
1161  */
1162  arm_insn insn_id = fw->is->insn->id;
1163  // BL, BLX etc will trash r0-r3
1164  // only break on unconditional - optimistic, could produce incorrect results
1165  if((insn_id == ARM_INS_BL || insn_id == ARM_INS_BLX
1166  // B/BX could mean execution goes somewhere totally different, but in practice it often just skipping over a word of data...
1167  /*|| insn_id == ARM_INS_B || insn_id == ARM_INS_BX*/)
1168  && fw->is->insn->detail->arm.cc == ARM_CC_AL) {
1169  break;
1170  }
1171 
1172  // if the first op isn't REG, continue
1173  // TODO lots of instructions could affect reg even if not first op
1174  if(fw->is->insn->detail->arm.operands[0].type != ARM_OP_REG) {
1175  continue;
1176  }
1177  arm_reg rd = fw->is->insn->detail->arm.operands[0].reg;
1178  // capstone arm.h regs enum R0-R12 are ordered
1179  // enum has entries before R0
1180  if(rd < ARM_REG_R0 || rd > ARM_REG_R3) {
1181  continue;
1182  }
1183 
1184  int rd_i = rd - ARM_REG_R0;
1185  uint32_t rd_bit = 1 << rd_i;
1186  // if we don't already have something for this reg
1187  if(!(known_bits & rd_bit)) {
1188  // know something has been done to this reg
1189  // note doesn't account for conditionals
1190  known_bits |=rd_bit;
1191  // is it an LDR
1192  uint32_t *pv=LDR_PC2valptr(fw,fw->is->insn);
1193  if(pv) {
1194  res[rd_i] += *pv;
1195 // if(dbg_count) printf("found ldr r%d,=0x%08x\n",rd_i,res[rd_i]);
1196  found_bits |=rd_bit;
1197  continue;
1198  }
1199  uint32_t v=ADRx2adr(fw,fw->is->insn); // assumes ADR doesn't generate 0, probably safe
1200  if(v) {
1201  res[rd_i] += v;
1202 // if(dbg_count) printf("found adrx r%d,0x%08x\n",rd_i,res[rd_i]);
1203  found_bits |=rd_bit;
1204  continue;
1205  }
1206  // immediate MOV note MOVT combinations, not accounted for, some handled ADDs below
1207 #if CS_API_MAJOR < 4
1208  if( (insn_id == ARM_INS_MOV || insn_id == ARM_INS_MOVS || insn_id == ARM_INS_MOVW)
1209 #else
1210  if( (insn_id == ARM_INS_MOV || insn_id == ARM_INS_MOVW)
1211 #endif
1212  && fw->is->insn->detail->arm.operands[1].type == ARM_OP_IMM) {
1213  res[rd_i] += fw->is->insn->detail->arm.operands[1].imm;
1214 // if(dbg_count) printf("found move r%d,#0x%08x\n",rd_i,res[rd_i]);
1215  found_bits |=rd_bit;
1216  } else if(isADDx_imm(fw->is->insn)) {
1217  res[rd_i] += fw->is->insn->detail->arm.operands[1].imm;
1218 // if(dbg_count) printf("found add r%d,#0x%08x\n",rd_i,res[rd_i]);
1219  // pretend reg is not known
1220  known_bits ^=rd_bit;
1221  // do not set found bit here
1222  } else if(isSUBx_imm(fw->is->insn)) {
1223  res[rd_i] = (int)(res[rd_i]) - fw->is->insn->detail->arm.operands[1].imm;
1224 // if(dbg_count) printf("found add r%d,#0x%08x\n",rd_i,res[rd_i]);
1225  // pretend reg is not known
1226  known_bits ^=rd_bit;
1227  // do not set found bit here
1228  }/* else {
1229  }
1230  */
1231  }
1232  }
1233 // if(dbg_count) printf("get_call_const_args found 0x%08x\n",found_bits);
1234  return found_bits;
1235 }
uint32_t get_direct_jump_target ( firmware fw,
iter_state_t is_init 
)

Definiert in Zeile 1249 der Datei firmware_load_ng.c.

1250 {
1251  uint32_t adr=B_target(fw,is_init->insn);
1252  // B ... return with thumb set to current mode
1253  if(adr) {
1254  return (adr | is_init->thumb);
1255  }
1256  adr=LDR_PC_PC_target(fw,is_init->insn);
1257  // LDR pc #... thumb is set in the loaded address
1258  if(adr) {
1259  return adr;
1260  }
1261  // an immediate move to ip (R12), candidate for multi-instruction veneer
1262  if((is_init->insn->id == ARM_INS_MOV || is_init->insn->id == ARM_INS_MOVW)
1263  && is_init->insn->detail->arm.operands[0].reg == ARM_REG_IP
1264  && is_init->insn->detail->arm.operands[1].type == ARM_OP_IMM) {
1265  adr = is_init->insn->detail->arm.operands[1].imm;
1266  // iter in default state, starting from is_init
1267  if(!fw_disasm_iter_single(fw,is_init->adr | is_init->thumb)) {
1268  fprintf(stderr,"get_direct_jump_target: disasm single failed at 0x%"PRIx64"\n",fw->is->insn->address);
1269  return 0;
1270  }
1271  // check for MOVT ip, #x
1272  if(!(fw->is->insn->id == ARM_INS_MOVT
1273  && fw->is->insn->detail->arm.operands[0].reg == ARM_REG_IP
1274  && fw->is->insn->detail->arm.operands[1].type == ARM_OP_IMM)) {
1275 // doesn't match second two insn veneer, not really an arror
1276 // fprintf(stderr,"get_direct_jump_target: not 2 insn ip veneer 0x%"PRIx64"\n",fw->is->insn->address);
1277  return 0;
1278  }
1279  // thumb set in loaded adr
1280  adr = (fw->is->insn->detail->arm.operands[1].imm << 16) | (adr&0xFFFF);
1281  if(!fw_disasm_iter(fw)) {
1282  fprintf(stderr,"get_direct_jump_target: disasm 2 failed at 0x%"PRIx64"\n",fw->is->insn->address);
1283  return 0;
1284  }
1285  // BX ip ?
1286  if(fw->is->insn->id == ARM_INS_BX
1287  && fw->is->insn->detail->arm.operands[0].type == ARM_OP_REG
1288  && fw->is->insn->detail->arm.operands[0].reg == ARM_REG_IP) {
1289  return adr;
1290  }
1291  }
1292  return 0;
1293 }
int get_TBx_PC_info ( firmware fw,
iter_state_t is,
tbx_info_t ti 
)

Definiert in Zeile 686 der Datei firmware_load_ng.c.

687 {
688  if(!(is->insn->id == ARM_INS_TBH || is->insn->id == ARM_INS_TBB) || is->insn->detail->arm.operands[0].mem.base != ARM_REG_PC) {
689  return 0;
690  }
691  ti->start=(uint32_t)is->adr; // after current instruction
692  ti->first_target=0;
693  ti->bytes=(is->insn->id == ARM_INS_TBH)?2:1;
694 
695  uint32_t max_adr;
696  // max possible (assuming jumptable is contiguous)
697  if(ti->bytes==1) {
698  max_adr=ti->start+(2*255);
699  } else {
700  max_adr=ti->start+(2*65535);
701  }
702  arm_reg i_reg=is->insn->detail->arm.operands[0].mem.index;
703  // backtrack looking for
704  // cmp index reg,#imm
705  // ...
706  // bhs ...
707  int max_backtrack = 8;
708  if(is->ah.count - 1 < max_backtrack) {
709  max_backtrack = is->ah.count-1;
710  }
711 
712  int max_count=0;
713  int found_bhs=0;
714  int i;
715  for(i=1;i<=max_backtrack;i++) {
716  fw_disasm_iter_single(fw,adr_hist_get(&is->ah,i)); // thumb state comes from hist
717  if(fw->is->insn->id == ARM_INS_B && fw->is->insn->detail->arm.cc == ARM_CC_HS) {
718  found_bhs=1;
719  continue;
720  }
721  // TODO lots of other ways condition code or reg could be changed in between
722  if(found_bhs && fw->is->insn->id == ARM_INS_CMP) {
723  // cmp with correct operands, assume number of jumptable entries
724  if(fw->is->insn->detail->arm.operands[0].reg == i_reg
725  || fw->is->insn->detail->arm.operands[1].type == ARM_OP_IMM) {
726  max_count = fw->is->insn->detail->arm.operands[1].imm;
727  }
728  // otherwise, give up
729  break;
730  }
731  }
732  if(max_count) {
733  max_adr = ti->start+max_count*ti->bytes;
734  //printf("get_TBx_PC_info: max_count %d start 0x%08x max_adr=0x%08x\n",max_count,ti->start,max_adr);
735  }
736  uint32_t adr=ti->start;
737  while(adr < max_adr) {
738  uint8_t *p=adr2ptr(fw,adr);
739  if(!p) {
740  fprintf(stderr,"get_TBx_PC_info: jumptable outside of valid address range at 0x%08x\n",adr);
741  return 0;
742  }
743  uint16_t off;
744  if(ti->bytes==1) {
745  off=(uint16_t)*p;
746  } else {
747  off=*(uint16_t *)p;
748  }
749 
750  // 0, probably padding at the end (could probably break here)
751  // note shouldn't be padding on tbh, since aligned for thumb
752  if(!off) {
753  break;
754  }
755  uint32_t target = ti->start+2*off;
756  // may indicate non-jumptable entry, if count not found, so don't increment adr
757  if(target <= adr) {
758  fprintf(stderr,"get_TBx_PC_info: jumptable target 0x%08x inside jumptable %d at 0x%08x\n",target,off,adr);
759  break;
760  }
761  if(!ti->first_target || target < ti->first_target) {
762  ti->first_target=target;
763  if(target < max_adr) {
764  max_adr=target; // assume jump table ends at/before first target
765  }
766  }
767  adr+=ti->bytes;
768  }
769  // if found count, assume it's right
770  if(max_count) {
771  ti->count=max_count;
772  } else {
773  // otherwise, use final address
774  ti->count=(adr-ti->start)/ti->bytes;
775  }
776  return 1;
777 }
int insn_match ( cs_insn *  insn,
const insn_match_t match 
)

Definiert in Zeile 1444 der Datei firmware_load_ng.c.

1445 {
1446  // specific instruction ID requested, check
1447  if(match->id != ARM_INS_INVALID && insn->id != match->id) {
1448  return 0;
1449  }
1450  // condition code requested, check
1451  if(match->cc != ARM_CC_INVALID && insn->detail->arm.cc != match->cc) {
1452  return 0;
1453  }
1454  // no op checks, done
1455  if(match->op_count == MATCH_OPCOUNT_IGNORE) {
1456  return 1;
1457  }
1458  // operand count requested, check
1459  if(match->op_count >= 0 && insn->detail->arm.op_count != match->op_count) {
1460  return 0;
1461  }
1462  int i;
1463  // operands
1464  for(i=0;i<MATCH_MAX_OPS && i < insn->detail->arm.op_count; i++) {
1465  // specific type requested?
1466  if(match->operands[i].type != ARM_OP_INVALID && insn->detail->arm.operands[i].type != match->operands[i].type) {
1467  return 0;
1468  }
1469  // specific registers requested?
1470  if(match->operands[i].reg1 != ARM_REG_INVALID) {
1471  if(insn->detail->arm.operands[i].type == ARM_OP_REG) {
1472  if(insn->detail->arm.operands[i].reg != match->operands[i].reg1) {
1473  return 0;
1474  }
1475  } else if(insn->detail->arm.operands[i].type == ARM_OP_MEM) {
1476  if(insn->detail->arm.operands[i].mem.base != match->operands[i].reg1) {
1477  return 0;
1478  }
1479  } else {
1480  fprintf(stderr,"insn_match: reg1 match requested on operand not reg or mem %d\n",
1481  insn->detail->arm.operands[i].type);
1482  }
1483  }
1484  if(match->operands[i].reg2 != ARM_REG_INVALID) {
1485  if(insn->detail->arm.operands[i].type == ARM_OP_MEM) {
1486  if(insn->detail->arm.operands[i].mem.index != match->operands[i].reg2) {
1487  return 0;
1488  }
1489  } else {
1490  fprintf(stderr,"insn_match: reg2 match requested on operand not reg or mem %d\n",
1491  insn->detail->arm.operands[i].type);
1492  }
1493  }
1494  if(match->operands[i].flags & MATCH_OP_FL_IMM) {
1495  if(insn->detail->arm.operands[i].type == ARM_OP_IMM) {
1496  if(insn->detail->arm.operands[i].imm != match->operands[i].imm) {
1497  return 0;
1498  }
1499  } else if(insn->detail->arm.operands[i].type == ARM_OP_MEM) {
1500  if(insn->detail->arm.operands[i].mem.disp != match->operands[i].imm) {
1501  return 0;
1502  }
1503  } else {
1504  fprintf(stderr,"insn_match: imm match requested on operand not imm or mem %d\n",
1505  insn->detail->arm.operands[i].type);
1506  }
1507  }
1508  if(match->operands[i].flags & MATCH_OP_FL_LAST) {
1509  break;
1510  }
1511  }
1512  return 1;
1513 }
int insn_match_any ( cs_insn *  insn,
const insn_match_t match 
)

Definiert in Zeile 1516 der Datei firmware_load_ng.c.

1517 {
1518  const insn_match_t *m;
1519  // check matches
1520  for(m=match;m->id != ARM_INS_ENDING;m++) {
1521  if(insn_match(insn,m)) {
1522  return 1;
1523  }
1524  }
1525  return 0;
1526 }
int insn_match_find_next ( firmware fw,
iter_state_t is,
int  max_insns,
const insn_match_t match 
)

Definiert in Zeile 1529 der Datei firmware_load_ng.c.

1530 {
1531  int i=0;
1532  while(i < max_insns) {
1533  // disassembly failed, no match (could ignore..)
1534  if(!disasm_iter(fw,is)) {
1535  return 0;
1536  }
1537  // printf("%"PRIx64" insn_match_find_next %s %s\n",is->insn->address,is->insn->mnemonic,is->insn->op_str);
1538  if(insn_match_any(is->insn,match)) {
1539  return 1;
1540  }
1541  i++;
1542  }
1543  // limit hit
1544  return 0;
1545 }
int insn_match_find_next_seq ( firmware fw,
iter_state_t is,
int  max_insns,
const insn_match_t match 
)

Definiert in Zeile 1576 der Datei firmware_load_ng.c.

1577 {
1578  int count=0;
1579  while(count < max_insns) {
1580  const insn_match_t *m=match;
1581  //printf("%"PRIx64" insn_match_find_next_seq %s %s\n",is->insn->address,is->insn->mnemonic,is->insn->op_str);
1582  while(m->id != ARM_INS_ENDING && disasm_iter(fw,is) && insn_match(is->insn,m)) {
1583  m++;
1584  count++;
1585  }
1586  if(m->id == ARM_INS_ENDING) {
1587  return 1;
1588  }
1589  // non-matching
1590  count++;
1591  }
1592  return 0;
1593 }
int insn_match_find_nth ( firmware fw,
iter_state_t is,
int  max_insns,
int  num_to_match,
const insn_match_t match 
)

Definiert in Zeile 1548 der Datei firmware_load_ng.c.

1549 {
1550  int i=0;
1551  int num_matched=0;
1552  while(i < max_insns) {
1553  // disassembly failed, no match (could ignore..)
1554  if(!disasm_iter(fw,is)) {
1555  return 0;
1556  }
1557  // printf("%"PRIx64" insn_match_find_next %s %s\n",is->insn->address,is->insn->mnemonic,is->insn->op_str);
1558 
1559  const insn_match_t *m;
1560  // check matches
1561  for(m=match;m->id != ARM_INS_ENDING;m++) {
1562  if(insn_match(is->insn,m)) {
1563  num_matched++;
1564  }
1565  }
1566  if(num_matched == num_to_match) {
1567  return 1;
1568  }
1569  i++;
1570  }
1571  // limit hit
1572  return 0;
1573 }
int insn_match_seq ( firmware fw,
iter_state_t is,
const insn_match_t match 
)

Definiert in Zeile 1433 der Datei firmware_load_ng.c.

1434 {
1435  //printf("%"PRIx64" insn_match_seq %s %s\n",is->insn->address,is->insn->mnemonic,is->insn->op_str);
1436  while(match->id != ARM_INS_ENDING && disasm_iter(fw,is) && insn_match(is->insn,match)) {
1437  //printf("%"PRIx64" insn_match_seq next %s %s\n",is->insn->address,is->insn->mnemonic,is->insn->op_str);
1438  match++;
1439  }
1440  return (match->id == ARM_INS_ENDING);
1441 }
int isADD_PC ( cs_insn *  insn)

Definiert in Zeile 385 der Datei firmware_load_ng.c.

386 {
387  return (insn->id == ARM_INS_ADD
388  && insn->detail->arm.op_count == 3
389  && insn->detail->arm.operands[0].reg != ARM_REG_PC
390  && insn->detail->arm.operands[1].type == ARM_OP_REG
391  && insn->detail->arm.operands[1].reg == ARM_REG_PC
392  && insn->detail->arm.operands[2].type == ARM_OP_IMM);
393 }
int isADDW_PC ( cs_insn *  insn)

Definiert in Zeile 373 der Datei firmware_load_ng.c.

374 {
375  return(insn->id == ARM_INS_ADDW
376  && insn->detail->arm.op_count == 3
377  && insn->detail->arm.operands[0].type == ARM_OP_REG
378  && insn->detail->arm.operands[0].reg != ARM_REG_PC
379  && insn->detail->arm.operands[1].type == ARM_OP_REG
380  && insn->detail->arm.operands[1].reg == ARM_REG_PC
381  && insn->detail->arm.operands[2].type == ARM_OP_IMM);
382 }
int isADDx_imm ( cs_insn *  insn)

Definiert in Zeile 489 der Datei firmware_load_ng.c.

490 {
491  return ((insn->id == ARM_INS_ADD || insn->id == ARM_INS_ADDW) && insn->detail->arm.operands[1].type == ARM_OP_IMM);
492 }
int isADRx ( cs_insn *  insn)

Definiert in Zeile 504 der Datei firmware_load_ng.c.

505 {
506  return ((insn->id == ARM_INS_ADR)
507  || isSUBW_PC(insn)
508  || isADDW_PC(insn)
509  || (isARM(insn) && (isADD_PC(insn) || isSUB_PC(insn))));
510 }
int isARM ( cs_insn *  insn)

Definiert in Zeile 325 der Datei firmware_load_ng.c.

326 {
327  int i;
328  for(i=0;i<insn->detail->groups_count;i++) {
329  if(insn->detail->groups[i] == ARM_GRP_ARM) {
330  return 1;
331  }
332  }
333  return 0;
334 }
int isASCIIstring ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 618 der Datei firmware_load.c.

619 {
620  if (idx_valid(fw, adr2idx(fw, adr)))
621  {
622  unsigned char *p = (unsigned char*)adr2ptr(fw, adr);
623  int i;
624  for (i = 0; (i < 100) && (p[i] != 0); i++)
625  {
626  if (!((p[i] == '\r') || (p[i] == '\n') || (p[i] == '\t') || ((p[i] >= 0x20) && (p[i] <= 0x7f))))
627  {
628  return 0;
629  }
630  }
631  if ((i >= 2) && (p[i] == 0))
632  return 1;
633  }
634  return 0;
635 }
int isLDR_PC ( cs_insn *  insn)

Definiert in Zeile 339 der Datei firmware_load_ng.c.

340 {
341  return insn->id == ARM_INS_LDR
342  && insn->detail->arm.op_count == 2
343  && insn->detail->arm.operands[0].type == ARM_OP_REG
344  && insn->detail->arm.operands[1].type == ARM_OP_MEM
345  && insn->detail->arm.operands[1].mem.base == ARM_REG_PC;
346 
347 }
int isLDR_PC_PC ( cs_insn *  insn)

Definiert in Zeile 352 der Datei firmware_load_ng.c.

353 {
354  if(!isLDR_PC(insn)) {
355  return 0;
356  }
357  return (insn->detail->arm.operands[0].reg == ARM_REG_PC);
358 }
int isPOP_LR ( cs_insn *  insn)

Definiert in Zeile 457 der Datei firmware_load_ng.c.

458 {
459  if(insn->id != ARM_INS_POP) {
460  return 0;
461  }
462  int i;
463  for(i=0; i < insn->detail->arm.op_count; i++) {
464  if(insn->detail->arm.operands[i].type == ARM_OP_REG
465  && insn->detail->arm.operands[i].reg == ARM_REG_LR) {
466  return 1;
467  }
468  }
469  return 0;
470 }
int isPOP_PC ( cs_insn *  insn)

Definiert in Zeile 473 der Datei firmware_load_ng.c.

474 {
475  if(insn->id != ARM_INS_POP) {
476  return 0;
477  }
478  int i;
479  for(i=0; i < insn->detail->arm.op_count; i++) {
480  if(insn->detail->arm.operands[i].type == ARM_OP_REG
481  && insn->detail->arm.operands[i].reg == ARM_REG_PC) {
482  return 1;
483  }
484  }
485  return 0;
486 }
int isPUSH_LR ( cs_insn *  insn)

Definiert in Zeile 441 der Datei firmware_load_ng.c.

442 {
443  if(insn->id != ARM_INS_PUSH) {
444  return 0;
445  }
446  int i;
447  for(i=0; i < insn->detail->arm.op_count; i++) {
448  if(insn->detail->arm.operands[i].type == ARM_OP_REG
449  && insn->detail->arm.operands[i].reg == ARM_REG_LR) {
450  return 1;
451  }
452  }
453  return 0;
454 }
int isRETx ( cs_insn *  insn)

Definiert in Zeile 407 der Datei firmware_load_ng.c.

408 {
409  // BX LR
410  if(insn->id == ARM_INS_BX
411  && insn->detail->arm.op_count == 1
412  && insn->detail->arm.operands[0].type == ARM_OP_REG
413  && insn->detail->arm.operands[0].reg == ARM_REG_LR) {
414  return 1;
415  }
416 
417  // TODO LDR pc, [sp], imm is somewhat common, but could also be function pointer call
418 
419  // POP. capstone translates LDMFD SP!,... in arm code to pop
420  if(insn->id == ARM_INS_POP) {
421  int i;
422  for(i=0; i < insn->detail->arm.op_count; i++) {
423  if(insn->detail->arm.operands[i].type == ARM_OP_REG
424  && insn->detail->arm.operands[i].reg == ARM_REG_PC) {
425  return 1;
426  }
427  }
428  }
429  // MOV PC, LR (some tools translate this to RET)
430  if(insn->id == ARM_INS_MOV
431  && insn->detail->arm.operands[0].type == ARM_OP_REG
432  && insn->detail->arm.operands[0].reg == ARM_REG_PC
433  && insn->detail->arm.operands[1].type == ARM_OP_REG
434  && insn->detail->arm.operands[1].reg == ARM_REG_LR) {
435  return 1;
436  }
437  return 0;
438 }
int isSUB_PC ( cs_insn *  insn)

Definiert in Zeile 396 der Datei firmware_load_ng.c.

397 {
398  return (insn->id == ARM_INS_SUB
399  && insn->detail->arm.op_count == 3
400  && insn->detail->arm.operands[0].reg != ARM_REG_PC
401  && insn->detail->arm.operands[1].type == ARM_OP_REG
402  && insn->detail->arm.operands[1].reg == ARM_REG_PC
403  && insn->detail->arm.operands[2].type == ARM_OP_IMM);
404 }
int isSUBW_PC ( cs_insn *  insn)

Definiert in Zeile 361 der Datei firmware_load_ng.c.

362 {
363  return(insn->id == ARM_INS_SUBW
364  && insn->detail->arm.op_count == 3
365  && insn->detail->arm.operands[0].type == ARM_OP_REG
366  && insn->detail->arm.operands[0].reg != ARM_REG_PC
367  && insn->detail->arm.operands[1].type == ARM_OP_REG
368  && insn->detail->arm.operands[1].reg == ARM_REG_PC
369  && insn->detail->arm.operands[2].type == ARM_OP_IMM);
370 }
int isSUBx_imm ( cs_insn *  insn)

Definiert in Zeile 494 der Datei firmware_load_ng.c.

495 {
496 #if CS_API_MAJOR < 4
497  return ((insn->id == ARM_INS_SUB || insn->id == ARM_INS_SUBW || insn->id == ARM_INS_SUBS) && insn->detail->arm.operands[1].type == ARM_OP_IMM);
498 #else
499  return ((insn->id == ARM_INS_SUB || insn->id == ARM_INS_SUBW) && insn->detail->arm.operands[1].type == ARM_OP_IMM);
500 #endif
501 }
uint32_t LDR_PC2adr ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 547 der Datei firmware_load_ng.c.

548 {
549  if(!isLDR_PC(insn)) {
550  return 0;
551  }
552  if(isARM(insn)) {
553  return insn->address+8+insn->detail->arm.operands[1].mem.disp;
554  } else {
555  return (insn->address&~3)+4+insn->detail->arm.operands[1].mem.disp;
556  }
557 }
uint32_t LDR_PC2val ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 606 der Datei firmware_load_ng.c.

607 {
608  uint32_t *p=LDR_PC2valptr(fw,insn);
609  if(p) {
610  return *p;
611  }
612  return 0;
613 }
uint32_t* LDR_PC2valptr ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 537 der Datei firmware_load_ng.c.

538 {
539  if(isARM(insn)) {
540  return LDR_PC2valptr_arm(fw,insn);
541  } else {
542  return LDR_PC2valptr_thumb(fw,insn);
543  }
544 }
uint32_t* LDR_PC2valptr_arm ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 525 der Datei firmware_load_ng.c.

526 {
527  if(!isLDR_PC(insn)) {
528  return NULL;
529  }
530  uint32_t adr;
531  // TODO NOTE doesn't do anything with scale (which can supposedly be neg?),
532  // appears correct for examples seen so far
533  adr=insn->address+8+insn->detail->arm.operands[1].mem.disp;
534  return (uint32_t *)adr2ptr(fw,adr);
535 }
uint32_t* LDR_PC2valptr_thumb ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 513 der Datei firmware_load_ng.c.

514 {
515  if(!isLDR_PC(insn)) {
516  return NULL;
517  }
518  uint32_t adr;
519  // TODO NOTE doesn't do anything with scale (which can supposedly be neg?),
520  // appears correct for examples seen so far
521  adr=(insn->address&~3)+4+insn->detail->arm.operands[1].mem.disp;
522  return (uint32_t *)adr2ptr(fw,adr);
523 }
uint32_t ptr2adr ( firmware fw,
uint8_t *  ptr 
)

Definiert in Zeile 168 der Datei firmware_load_ng.c.

169 {
170  // TODO handle copied, or maybe another func to convert?
171  return (ptr-fw->buf8)+fw->base;
172 }
int search_calls_multi_end ( firmware fw,
iter_state_t is,
uint32_t  adr 
)

Definiert in Zeile 1087 der Datei firmware_load_ng.c.

1087  {
1088  return 1;
1089 }
uint32_t search_disasm_calls ( firmware fw,
iter_state_t is,
uint32_t  val,
void *  unused 
)

Definiert in Zeile 1074 der Datei firmware_load_ng.c.

1075 {
1076  //printf("%"PRIx64" %s %s\n",is->insn->address,is->insn->mnemonic, is->insn->op_str);
1078  if(sub) {
1079  if(sub == val) {
1080  return 1;
1081  }
1082  }
1083  return 0;
1084 }
uint32_t search_disasm_calls_multi ( firmware fw,
iter_state_t is,
uint32_t  unused,
void *  userdata 
)

Definiert in Zeile 1095 der Datei firmware_load_ng.c.

1096 {
1099  if(sub) {
1100  while(data->adr) {
1101  if(data->adr == sub) {
1102  return data->fn(fw,is,sub);
1103  }
1104  data++;
1105  }
1106  }
1107  return 0;
1108 }
uint32_t search_disasm_const_ref ( firmware fw,
iter_state_t is,
uint32_t  val,
void *  unused 
)

Definiert in Zeile 1025 der Datei firmware_load_ng.c.

1026 {
1027 // printf("%"PRIx64" %s %s\n",is->insn->address,is->insn->mnemonic, is->insn->op_str);
1028  uint32_t av=ADRx2adr(fw,is->insn);
1029  if(av) {
1030 // printf("adr 0x%08x\n",av);
1031  if(av == val) {
1032  return (uint32_t)is->insn->address;
1033  }
1034  return 0;
1035  }
1036  uint32_t *pv=LDR_PC2valptr(fw,is->insn);
1037  if(pv) {
1038 // printf("ldr 0x%08x\n",*pv);
1039  if(*pv == val) {
1040  return (uint32_t)is->insn->address;
1041  }
1042  }
1043  return 0;
1044 }
uint32_t search_disasm_str_ref ( firmware fw,
iter_state_t is,
uint32_t  val,
void *  str 
)

Definiert in Zeile 1047 der Datei firmware_load_ng.c.

1048 {
1049  const char *str=(const char *)udata;
1050 // printf("%"PRIx64" %s %s\n",is->insn->address,is->insn->mnemonic, is->insn->op_str);
1051  uint32_t av=ADRx2adr(fw,is->insn);
1052  if(av) {
1053 // printf("adr 0x%08x\n",av);
1054  char *cmp=(char *)adr2ptr_with_data(fw,av);
1055  if(cmp && (strcmp(cmp,str) == 0)) {
1056  return (uint32_t)is->insn->address;
1057  }
1058  return 0;
1059  }
1060  uint32_t *pv=LDR_PC2valptr(fw,is->insn);
1061  if(pv) {
1062 // printf("ldr 0x%08x\n",*pv);
1063  char *cmp=(char *)adr2ptr_with_data(fw,*pv);
1064  if(cmp && (strcmp(cmp,str) == 0)) {
1065  return (uint32_t)is->insn->address;
1066  }
1067  }
1068  return 0;
1069 }

Variablen-Dokumentation

const insn_match_t match_b[]

Definiert in Zeile 1399 der Datei firmware_load_ng.c.

const insn_match_t match_b_bl[]

Definiert in Zeile 1403 der Datei firmware_load_ng.c.

const insn_match_t match_b_bl_blximm[]

Definiert in Zeile 1409 der Datei firmware_load_ng.c.

const insn_match_t match_bl_blximm[]

Definiert in Zeile 1416 der Datei firmware_load_ng.c.

const insn_match_t match_bxlr[]

Definiert in Zeile 1422 der Datei firmware_load_ng.c.

const insn_match_t match_ldr_pc[]

Definiert in Zeile 1427 der Datei firmware_load_ng.c.