CHDK_DE Vorschauversion  Trunk Rev. 5663
 Alle Datenstrukturen Dateien Funktionen Variablen Typdefinitionen Aufzählungen Aufzählungswerte Makrodefinitionen
firmware_load_ng.c-Dateireferenz
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <capstone.h>
#include "stubs_load.h"
#include "firmware_load_ng.h"
+ Include-Abhängigkeitsdiagramm für firmware_load_ng.c:

gehe zum Quellcode dieser Datei

Makrodefinitionen

#define MATCH_SIMPLE_FUNC_NONE   0x0
 
#define MATCH_SIMPLE_FUNC_NULLSUB   0x1
 
#define MATCH_SIMPLE_FUNC_IMM   0x2
 
#define MATCH_SIMPLE_FUNC_ANY   0x3
 

Funktionen

static void addBufRange (firmware *fw, int o, int l)
 
static void findRanges (firmware *fw)
 
BufRangegetBufRangeForIndex (firmware *fw, int i)
 
int find_Nth_str (firmware *fw, char *str, int N)
 
int find_str (firmware *fw, char *str)
 
uint32_t find_next_bytes_range (firmware *fw, const void *bytes, size_t len, uint32_t start_adr, uint32_t max_adr)
 
int find_bytes_all (firmware *fw, const void *bytes, size_t len, uint32_t adr, uint32_t *result, int max)
 
uint32_t find_next_substr_bytes (firmware *fw, const char *str, uint32_t adr)
 
uint32_t find_next_str_bytes_range (firmware *fw, const char *str, uint32_t adr, uint32_t max_adr)
 
uint32_t find_str_bytes_main_fw (firmware *fw, const char *str)
 
uint32_t find_next_str_bytes (firmware *fw, const char *str, uint32_t adr)
 
uint32_t find_str_bytes (firmware *fw, const char *str)
 
int isASCIIstring (firmware *fw, uint32_t adr)
 
adr_range_tadr_get_range (firmware *fw, uint32_t adr)
 
int adr_get_range_type (firmware *fw, uint32_t adr)
 
uint32_t ptr2adr (firmware *fw, uint8_t *ptr)
 
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)
 
const char * adr_range_desc_str (adr_range_t *r)
 
int adr_is_var (firmware *fw, uint32_t adr)
 
int adr_is_main_fw_code (firmware *fw, uint32_t adr)
 
uint32_t find_u32_adr_range (firmware *fw, uint32_t val, uint32_t start, uint32_t maxadr)
 
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)
 
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_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 (__attribute__((unused)) firmware *fw, cs_insn *insn)
 
uint32_t ADRx2adr (__attribute__((unused)) firmware *fw, cs_insn *insn)
 
uint32_t ADR2adr (__attribute__((unused)) firmware *fw, cs_insn *insn)
 
uint32_tADR2valptr (firmware *fw, cs_insn *insn)
 
uint32_t LDR_PC2val (firmware *fw, cs_insn *insn)
 
uint32_t LDR_PC_PC_target (firmware *fw, cs_insn *insn)
 
uint32_t B_target (__attribute__((unused)) firmware *fw, cs_insn *insn)
 
uint32_t CBx_target (__attribute__((unused)) firmware *fw, cs_insn *insn)
 
uint32_t BLXimm_target (__attribute__((unused)) firmware *fw, cs_insn *insn)
 
uint32_t BL_target (__attribute__((unused)) firmware *fw, cs_insn *insn)
 
uint32_t B_BL_target (__attribute__((unused)) firmware *fw, cs_insn *insn)
 
uint32_t B_BL_BLXimm_target (__attribute__((unused)) 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 (__attribute__((unused)) firmware *fw, iter_state_t *is, uint32_t adr)
 
int disasm_iter (__attribute__((unused)) 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, __attribute__((unused)) void *unused)
 
uint32_t search_disasm_str_ref (firmware *fw, iter_state_t *is, __attribute__((unused)) uint32_t val, void *udata)
 
uint32_t search_disasm_calls (firmware *fw, iter_state_t *is, uint32_t val, __attribute__((unused)) void *unused)
 
int search_calls_multi_end (__attribute__((unused)) firmware *fw, __attribute__((unused)) iter_state_t *is, __attribute__((unused)) uint32_t adr)
 
uint32_t search_disasm_calls_multi (firmware *fw, iter_state_t *is, __attribute__((unused)) 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_search_insns, int max_seq_insns, arm_reg match_val_reg, var_ldr_desc_t *result)
 
int check_simple_func (firmware *fw, uint32_t adr, int match_ftype, simple_func_desc_t *info)
 
uint32_t find_last_call_from_func (firmware *fw, iter_state_t *is, int min_insns, int max_insns)
 
int insn_match_seq (firmware *fw, iter_state_t *is, const insn_match_t *match)
 
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_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, int flags)
 
void find_dryos_vers (firmware *fw)
 
void firmware_load (firmware *fw, const char *filename, uint32_t base_adr, int fw_arch)
 
int do_blx_check (firmware *fw)
 
int firmware_init_capstone (firmware *fw)
 
int find_startup_copy (firmware *fw, iter_state_t *is, int max_search, uint32_t *src_start, uint32_t *dst_start, uint32_t *dst_end)
 
void find_exception_vec (firmware *fw, iter_state_t *is)
 
void firmware_init_data_ranges (firmware *fw)
 
void firmware_unload (firmware *fw)
 

Variablen

const insn_match_t match_b []
 
const insn_match_t match_bl []
 
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 MATCH_SIMPLE_FUNC_ANY   0x3

Definiert in Zeile 1583 der Datei firmware_load_ng.c.

#define MATCH_SIMPLE_FUNC_IMM   0x2

Definiert in Zeile 1580 der Datei firmware_load_ng.c.

#define MATCH_SIMPLE_FUNC_NONE   0x0

Definiert in Zeile 1576 der Datei firmware_load_ng.c.

#define MATCH_SIMPLE_FUNC_NULLSUB   0x1

Definiert in Zeile 1578 der Datei firmware_load_ng.c.

Dokumentation der Funktionen

static void addBufRange ( firmware fw,
int  o,
int  l 
)
static

Definiert in Zeile 13 der Datei firmware_load_ng.c.

14 {
15  BufRange *n = malloc(sizeof(BufRange));
16  n->p = fw->buf32 + o;
17  n->off = o;
18  n->len = l;
19  n->next = 0;
20  if (fw->br == 0)
21  {
22  fw->br = n;
23  }
24  else
25  {
26  fw->last->next = n;
27  }
28  fw->last = n;
29 }
uint32_t ADR2adr ( __attribute__((unused)) firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 729 der Datei firmware_load_ng.c.

730 {
731  if(insn->id != ARM_INS_ADR) {
732  return 0;
733  }
734  // TODO - capstone doesn't appear to generate ADR for ARM
735  /*
736  if(cs_insn_group(fw->cs_handle,insn,ARM_GRP_ARM)) {
737  return 0;
738  }
739  */
740  return (insn->address&~3)+4+insn->detail->arm.operands[1].imm;
741 }
uint8_t* adr2ptr ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 274 der Datei firmware_load_ng.c.

275 {
276  adr_range_t *r=adr_get_range(fw,adr);
277  if(!r) {
278  return NULL;
279  }
280  switch(r->type) {
281  case ADR_RANGE_RAM_CODE:
282  case ADR_RANGE_ROM:
283  return (r->buf)+(adr - r->start);
284  default:
285  return NULL;
286  }
287 }
uint8_t* adr2ptr_with_data ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 289 der Datei firmware_load_ng.c.

290 {
291  adr_range_t *r=adr_get_range(fw,adr);
292  if(!r) {
293  return NULL;
294  }
295  switch(r->type) {
296  case ADR_RANGE_RAM_CODE:
297  case ADR_RANGE_INIT_DATA:
298  case ADR_RANGE_ROM:
299  return (r->buf)+(adr - r->start);
300  default:
301  return NULL;
302  }
303 }
uint32_t* ADR2valptr ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 744 der Datei firmware_load_ng.c.

745 {
746  uint32_t adr=ADR2adr(fw,insn);
747  return (uint32_t *)adr2ptr(fw,adr);
748 }
adr_range_t* adr_get_range ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 245 der Datei firmware_load_ng.c.

246 {
247  int i;
248  adr_range_t *r=fw->adr_ranges;
249  for(i=0;i<fw->adr_range_count;i++) {
250  if(adr >= r->start && adr < r->start + r->bytes) {
251  return r;
252  }
253  r++;
254  }
255  return NULL;
256 }
int adr_get_range_type ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 259 der Datei firmware_load_ng.c.

260 {
261  adr_range_t *r=adr_get_range(fw,adr);
262  if(!r) {
263  return ADR_RANGE_INVALID;
264  }
265  return r->type;
266 }
void adr_hist_add ( adr_hist_t ah,
uint32_t  adr 
)

Definiert in Zeile 452 der Datei firmware_load_ng.c.

453 {
454  ah->cur=adr_hist_index(ah,1);
455  ah->adrs[ah->cur]=adr;
456  if(ah->count < ADR_HIST_SIZE) {
457  ah->count++;
458  }
459 }
uint32_t adr_hist_get ( adr_hist_t ah,
int  i 
)

Definiert in Zeile 463 der Datei firmware_load_ng.c.

464 {
465  if(!ah->count || i > ah->count) {
466  return 0;
467  }
468  return ah->adrs[adr_hist_index(ah,-i)];
469 }
int adr_hist_index ( adr_hist_t ah,
int  i 
)

Definiert in Zeile 442 der Datei firmware_load_ng.c.

443 {
444  int r=(ah->cur+i)%ADR_HIST_SIZE;
445  if(r < 0) {
446  return ADR_HIST_SIZE + r;
447  }
448  return r;
449 }
void adr_hist_reset ( adr_hist_t ah)

Definiert in Zeile 433 der Datei firmware_load_ng.c.

434 {
435  ah->cur=0;
436  ah->count=0;
437  // memset shouldn't be needed
438  // memset(ah->adrs,0,ADR_HIST_SIZE*4);
439 }
int adr_is_main_fw_code ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 351 der Datei firmware_load_ng.c.

352 {
353  int adr_type = adr_get_range_type(fw,adr);
354  if(adr_type == ADR_RANGE_RAM_CODE) {
355  return 1;
356  }
357  if(adr_type != ADR_RANGE_ROM) {
358  return 0;
359  }
360  if(adr < fw->rom_code_search_min_adr || adr > fw->rom_code_search_max_adr) {
361  return 0;
362  }
363  return 1;
364 }
int adr_is_var ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 345 der Datei firmware_load_ng.c.

346 {
347  return (adr > fw->data_start && adr < fw->memisostart);
348 }
const char* adr_range_desc_str ( adr_range_t r)

Definiert in Zeile 323 der Datei firmware_load_ng.c.

324 {
325  switch(r->type) {
326  case ADR_RANGE_INVALID:
327  return "(invalid)";
328  case ADR_RANGE_ROM:
329  return "ROM";
330  case ADR_RANGE_RAM_CODE:
331  if(r->flags & ADR_RANGE_FL_EVEC) {
332  return "EVEC";
333  } else if(r->flags & ADR_RANGE_FL_TCM) {
334  return "TCM code";
335  }
336  return "RAM code";
337  case ADR_RANGE_INIT_DATA:
338  return "RAM data";
339  default:
340  return "(unknown)";
341  }
342 }
const char* adr_range_type_str ( int  type)

Definiert in Zeile 306 der Datei firmware_load_ng.c.

307 {
308  switch(type) {
309  case ADR_RANGE_INVALID:
310  return "(invalid)";
311  case ADR_RANGE_ROM:
312  return "ROM";
313  case ADR_RANGE_RAM_CODE:
314  return "RAM code";
315  case ADR_RANGE_INIT_DATA:
316  return "RAM data";
317  default:
318  return "(unknown)";
319  }
320 }
uint32_t ADRx2adr ( __attribute__((unused)) firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 705 der Datei firmware_load_ng.c.

706 {
707  if(insn->id == ARM_INS_ADR) {
708  return (insn->address&~3)+4+insn->detail->arm.operands[1].imm;
709  }
710  if(isSUBW_PC(insn)) {
711  return (insn->address&~3)+4-insn->detail->arm.operands[2].imm;
712  }
713  if(isADDW_PC(insn)) {
714  return (insn->address&~3)+4+insn->detail->arm.operands[2].imm;
715  }
716  if(isARM(insn)) {
717  if(isADD_PC(insn)) {
718  return insn->address+8+insn->detail->arm.operands[2].imm;
719  }
720  if(isSUB_PC(insn)) {
721  return insn->address+8-insn->detail->arm.operands[2].imm;
722  }
723  }
724  return 0;
725 }
uint32_t B_BL_BLXimm_target ( __attribute__((unused)) firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 818 der Datei firmware_load_ng.c.

819 {
820  if(insn->id == ARM_INS_B
821  || insn->id == ARM_INS_BL
822  || (insn->id == ARM_INS_BLX && insn->detail->arm.operands[0].type == ARM_OP_IMM)) {
823  return insn->detail->arm.operands[0].imm;
824  }
825  return 0; // TODO could be valid
826 }
uint32_t B_BL_target ( __attribute__((unused)) firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 808 der Datei firmware_load_ng.c.

809 {
810  if(insn->id == ARM_INS_B || insn->id == ARM_INS_BL) {
811  return insn->detail->arm.operands[0].imm;
812  }
813  return 0; // TODO could be valid
814 }
uint32_t B_target ( __attribute__((unused)) firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 770 der Datei firmware_load_ng.c.

771 {
772  if(insn->id == ARM_INS_B) {
773  return insn->detail->arm.operands[0].imm;
774  }
775  return 0; // TODO could be valid
776 }
uint32_t BL_target ( __attribute__((unused)) firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 799 der Datei firmware_load_ng.c.

800 {
801  if(insn->id == ARM_INS_BL) {
802  return insn->detail->arm.operands[0].imm;
803  }
804  return 0; // TODO could be valid
805 }
uint32_t BLXimm_target ( __attribute__((unused)) firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 789 der Datei firmware_load_ng.c.

790 {
791  if(insn->id == ARM_INS_BLX && insn->detail->arm.operands[0].type == ARM_OP_IMM) {
792  return insn->detail->arm.operands[0].imm;
793  }
794  return 0; // TODO could be valid
795 }
uint32_t CBx_target ( __attribute__((unused)) firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 780 der Datei firmware_load_ng.c.

781 {
782  if(insn->id == ARM_INS_CBZ || insn->id == ARM_INS_CBNZ) {
783  return insn->detail->arm.operands[1].imm;
784  }
785  return 0; // TODO could be valid
786 }
int check_simple_func ( firmware fw,
uint32_t  adr,
int  match_ftype,
simple_func_desc_t info 
)

Definiert in Zeile 1584 der Datei firmware_load_ng.c.

1585 {
1586  const insn_match_t match_mov_r0_imm[]={
1587  {MATCH_INS(MOV, 2), {MATCH_OP_REG(R0), MATCH_OP_IMM_ANY}},
1588 #if CS_API_MAJOR < 4
1589  {MATCH_INS(MOVS, 2), {MATCH_OP_REG(R0), MATCH_OP_IMM_ANY}},
1590 #endif
1591  {ARM_INS_ENDING}
1592  };
1593 
1594  int found = 0;
1595  int found_val = 0;
1596  if(info) {
1597  info->ftype = MATCH_SIMPLE_FUNC_NONE;
1598  info->retval = 0;
1599  }
1600  if(!fw_disasm_iter_single(fw,adr)) {
1601  //fprintf(stderr,"check_simple_func: disasm_iter_single failed 0x%x\n",adr);
1602  return 0;
1603  }
1604  if(match_ftype & MATCH_SIMPLE_FUNC_IMM) {
1605  // check mov r0, #imm
1606  if(insn_match_any(fw->is->insn,match_mov_r0_imm)) {
1607  found_val = fw->is->insn->detail->arm.operands[1].imm;
1608  found = MATCH_SIMPLE_FUNC_IMM;
1609  // fprintf(stderr,"check_simple_func: found IMM\n");
1610  if(!fw_disasm_iter(fw)) {
1611  //fprintf(stderr,"check_simple_func: disasm_iter failed 0x%x\n",adr);
1612  return 0;
1613  }
1614  }
1615  }
1616  if(!isRETx(fw->is->insn)) {
1617  // fprintf(stderr,"check_simple_func: no ret\n");
1618  return 0;
1619  }
1620  // no previous found, check if ret alone
1621  if(!found && (match_ftype & MATCH_SIMPLE_FUNC_NULLSUB)) {
1622  found = MATCH_SIMPLE_FUNC_NULLSUB;
1623  // fprintf(stderr,"check_simple_func: found nullsub\n");
1624  }
1625  if(found) {
1626  if(info) {
1627  info->ftype = found;
1628  info->retval = found_val;
1629  }
1630  }
1631  return found;
1632 }
int disasm_iter ( __attribute__((unused)) firmware fw,
iter_state_t is 
)

Definiert in Zeile 994 der Datei firmware_load_ng.c.

995 {
996  // iter_start not called or invalid
997  if(!is->code) {
998  return 0;
999  }
1000  adr_hist_add(&is->ah,(uint32_t)is->adr | is->thumb); // record thumb state to allow backtracking through state changes
1001  return cs_disasm_iter(is->cs_handle, &is->code, &is->size, &is->adr, is->insn);
1002 }
void disasm_iter_free ( iter_state_t is)

Definiert in Zeile 939 der Datei firmware_load_ng.c.

940 {
941  cs_free(is->insn,1);
942  free(is);
943  return;
944 }
int disasm_iter_init ( __attribute__((unused)) firmware fw,
iter_state_t is,
uint32_t  adr 
)

Definiert in Zeile 985 der Datei firmware_load_ng.c.

986 {
987  adr_hist_reset(&is->ah);
988  return disasm_iter_set(fw,is,adr);
989 }
iter_state_t* disasm_iter_new ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 928 der Datei firmware_load_ng.c.

929 {
931  // it doesn't currently appear to matter which handle is used to allocate
932  // only used for overridable malloc functions and error reporting
933  is->insn=cs_malloc(fw->cs_handle_arm);
934  disasm_iter_init(fw,is,adr);
935  return is;
936 }
int disasm_iter_set ( firmware fw,
iter_state_t is,
uint32_t  adr 
)

Definiert in Zeile 948 der Datei firmware_load_ng.c.

949 {
950  // set handle based on thumb bit to allow disassembly
951  if(ADR_IS_THUMB(adr)) {
952  is->cs_handle=fw->cs_handle_thumb;
953  is->thumb=1;
954  is->insn_min_size=2;
955  adr=ADR_CLEAR_THUMB(adr);// ADR used for iteration must not contain thumb bit
956  } else {
957  is->cs_handle=fw->cs_handle_arm;
958  is->thumb=0;
959  is->insn_min_size=4;
960  if(!ADR_IS_ALIGN4(adr)) {
961  fprintf(stderr,"disasm_iter_set: unaligned ARM address 0x%08x\n",adr);
962  is->code=NULL;
963  is->size=0;
964  is->adr=0;
965  return 0;
966  }
967  }
968  uint8_t *p=adr2ptr(fw,adr);
969  if(!p) {
970 // TODO invalid currently allowed, for new
971 // fprintf(stderr,"disasm_iter_set: bad address 0x%08x\n",adr);
972  is->code=NULL; // make first iter fail
973  is->size=0;
974  is->adr=0;
975  return 0;
976  }
977  // TODO should maybe mark is.insn invalid?
978  is->code=p;
979  is->size=fw->size8 - (p-fw->buf8);
980  is->adr=adr;
981  return 1;
982 }
int do_blx_check ( firmware fw)

Definiert in Zeile 2114 der Datei firmware_load_ng.c.

2115 {
2116 /*
2117 test code blxbork.S
2118 .syntax unified
2119 .globl arm_code
2120 .globl _start
2121 _start:
2122 .code 16
2123 blx arm_code
2124 movs r0, #1
2125 blx arm_code
2126 .align 4
2127 .code 32
2128 arm_code:
2129 bx lr
2130 
2131 arm-none-eabi-gcc -nostdlib blxbork.S -o blxbork.elf
2132 */
2133 
2134 static const uint8_t code[]=
2135  "\x00\xf0\x06\xe8" // blx arm_code (start + 0x10)
2136  "\x01\x20" // movs r0,#1, to cause non-word align
2137  "\x00\xf0\x04\xe8" // blx arm_code
2138 ;
2139  cs_insn *insn;
2140  size_t count;
2141  count = cs_disasm(fw->cs_handle_thumb, code, sizeof(code), 0xFF000000, 3, &insn);
2142 
2143  if(!(count == 3 && insn[0].id == ARM_INS_BLX && insn[2].id == ARM_INS_BLX)) {
2144  fprintf(stderr,"do_blx_check: disassembly failed\n");
2145  return 0;
2146  }
2147 
2148  int r=(insn[0].detail->arm.operands[0].imm == insn[2].detail->arm.operands[0].imm);
2149 
2150 
2151  if(!r) {
2152  fprintf(stderr,"WARNING! Incorrect disassembly is likely\n");
2153  }
2154  cs_free(insn,count);
2155  return r;
2156 }
int find_and_get_var_ldr ( firmware fw,
iter_state_t is,
int  max_search_insns,
int  max_seq_insns,
arm_reg  match_val_reg,
var_ldr_desc_t result 
)

Definiert in Zeile 1487 der Datei firmware_load_ng.c.

1494 {
1495  if(!insn_match_find_next(fw,is,max_search_insns,match_ldr_pc)) {
1496  // printf("find_and_get_var_ldr: LDR PC not found\n");
1497  return 0;
1498  }
1499  var_ldr_desc_t r;
1500  memset(&r,0,sizeof(r));
1501  r.reg_base=is->insn->detail->arm.operands[0].reg;
1502  r.adr_base=LDR_PC2val(fw,is->insn);
1503  int seq_count=1;
1504 
1505  while(seq_count < max_seq_insns) {
1506  // disassembly failed, no match (could ignore..)
1507  if(!disasm_iter(fw,is)) {
1508  return 0;
1509  }
1510  // assume first encountered LDR x,[pc] is the one to use
1511  // give up if we encounter another. Don't know beforehand which reg is base
1512  // NOTE: backward search would allow matching base that eventually ends up in desired reg
1513  if(isLDR_PC(is->insn)) {
1514  // printf("find_and_get_var_ldr: second ldr pc\n");
1515  return 0;
1516  }
1517  seq_count++;
1518  // firmware may use add/sub to get actual firmware base address
1519  if(isADDx_imm(is->insn) || isSUBx_imm(is->insn)) {
1520  if((arm_reg)is->insn->detail->arm.operands[0].reg != r.reg_base) {
1521  continue;
1522  }
1523  if(isADDx_imm(is->insn)) {
1524  r.adj=is->insn->detail->arm.operands[1].imm;
1525  } else {
1526  r.adj=-is->insn->detail->arm.operands[1].imm;
1527  }
1528  if(!disasm_iter(fw,is)) {
1529  return 0;
1530  }
1531  seq_count++;
1532  } else {
1533  r.adj=0;
1534  }
1535  // try to bail out if base reg trashed
1536  // BL, BLX etc will trash r0-r3, B, BX go somewhere else
1537  // only break on unconditional - optimistic, could produce incorrect results
1538  // can't account for branches into searched code
1539  if((r.reg_base >= ARM_REG_R0 && r.reg_base <= ARM_REG_R3)
1540  && (is->insn->id == ARM_INS_BL || is->insn->id == ARM_INS_BLX
1541  || is->insn->id == ARM_INS_B || is->insn->id == ARM_INS_BX)
1542  && is->insn->detail->arm.cc == ARM_CC_AL) {
1543  // printf("find_and_get_var_ldr: bail B*\n");
1544  return 0;
1545  }
1546  if(is->insn->id != ARM_INS_LDR || (arm_reg)is->insn->detail->arm.operands[1].reg != r.reg_base) {
1547  // other operation on with base reg as first operand, give up
1548  // simplistic, many other things could affect reg
1549  if(is->insn->detail->arm.operands[0].type == ARM_OP_REG && (arm_reg)is->insn->detail->arm.operands[0].reg == r.reg_base) {
1550  // printf("find_and_get_var_ldr: bail mod base\n");
1551  return 0;
1552  }
1553  continue;
1554  }
1555  r.reg_val = is->insn->detail->arm.operands[0].reg;
1556  if(match_val_reg != ARM_REG_INVALID && (r.reg_val != match_val_reg)) {
1557  continue;
1558  }
1559  r.off = is->insn->detail->arm.operands[1].mem.disp;
1560  r.adr_adj = r.adr_base + r.adj;
1561  r.adr_final = r.adr_adj + r.off;
1562  memcpy(result,&r,sizeof(r));
1563  return 1;
1564  }
1565  return 0;
1566 }
int find_bytes_all ( firmware fw,
const void *  bytes,
size_t  len,
uint32_t  adr,
uint32_t result,
int  max 
)

Definiert in Zeile 174 der Datei firmware_load_ng.c.

175 {
176  int i;
177  for(i=0,adr=find_next_bytes_range(fw,bytes,len,0,0); adr && (i < max); adr=find_next_bytes_range(fw,bytes,len,adr+len,0),i++) {
178  result[i] = adr;
179  }
180  return i;
181 }
void find_dryos_vers ( firmware fw)

Definiert in Zeile 1978 der Datei firmware_load_ng.c.

1979 {
1980  const char *sig="DRYOS version 2.3, release #";
1982  /*
1983  int i;
1984  for(i=0;i<fw->dryos_ver_count;i++) {
1985  fprintf(stderr,"found %s (%d) @0x%08x\n",
1986  (char *)adr2ptr(fw,fw->dryos_ver_list[i]),
1987  atoi((char *)adr2ptr(fw,fw->dryos_ver_list[i]+strlen(sig))),
1988  fw->dryos_ver_list[i]);
1989  }
1990  */
1991  if(fw->dryos_ver_count) {
1992  if(fw->dryos_ver_count == FW_MAX_DRYOS_VERS) {
1993  fprintf(stderr,"WARNING hit FW_MAX_DRYOS_VERS\n");
1994  }
1995  uint32_t i;
1996  int match_i;
1997  uint32_t min_adr = 0xFFFFFFFF;
1998 
1999  // ref should easily be in the first 8M (most near start but g7x2 at >0x500000)
2000  uint32_t maxadr = (fw->rom_code_search_max_adr - 0x800000 > fw->base)?fw->base + 0x800000:fw->rom_code_search_max_adr;
2001  // look for pointer to dryos version nearest to main ROM start, before the string itself
2002  // NOTE it's the *pointer* that must be nearest, the string may not be the first
2003  for(i=0; i<fw->dryos_ver_count; i++) {
2004  // TODO could limit range more, ctypes should be ref'd a lot
2005  // could sanity check not a random value that happens to match
2007  if(adr && adr < min_adr) {
2008  min_adr = adr;
2009  match_i = i;
2010  }
2011  }
2012  if(min_adr == 0xFFFFFFFF) {
2013  fprintf(stderr,"WARNING dryos version pointer not found, defaulting to first\n");
2014  match_i = 0;
2015  min_adr = 0;
2016  }
2017  fw->dryos_ver_str = (char *)adr2ptr(fw,fw->dryos_ver_list[match_i]);
2018  fw->dryos_ver = atoi((char *)adr2ptr(fw,fw->dryos_ver_list[match_i]+strlen(sig)));
2019  fw->dryos_ver_adr = fw->dryos_ver_list[match_i];
2020  fw->dryos_ver_ref_adr = min_adr;
2021  // fprintf(stderr,"main firmware version %s @ 0x%08x ptr 0x%08x\n",fw->dryos_ver_str,fw->dryos_ver_adr,min_adr);
2022  } else {
2023  fw->dryos_ver=0;
2024  fw->dryos_ver_str=NULL;
2025  fw->dryos_ver_adr=0;
2026  }
2027 }
void find_exception_vec ( firmware fw,
iter_state_t is 
)

Definiert in Zeile 2235 der Datei firmware_load_ng.c.

2236 {
2237  // check for exception vector, d7 id
2238  // only on thumb2 for now
2239  if(fw->arch != FW_ARCH_ARMv7) {
2240  return;
2241  }
2242 
2243  const insn_match_t match_bl_mcr[]={
2244  {MATCH_INS(BL, 1), {MATCH_OP_IMM_ANY}},
2245  // Vector Base Address Register MCR p15, 0, <Rt>, c12, c0, 0 - not present on PMSA
2247  {ARM_INS_ENDING}
2248  };
2249 
2250  // reset to main fw start
2251  disasm_iter_init(fw, is, fw->base + fw->main_offs + 12 + fw->thumb_default);
2252  if(!insn_match_find_next(fw,is,4,match_bl_mcr)) {
2253  printf("no match!\n");
2254  return;
2255  }
2256  // check which instruction we matched
2257  uint32_t faddr = get_branch_call_insn_target(fw,is);
2258  if(faddr) {
2259  // bl = digic6, has function to set up exception vector
2260  disasm_iter_init(fw, is, faddr);
2261  disasm_iter(fw, is);
2262  int ra,rb;
2263  uint32_t va, vb;
2264  if(!IS_INSN_ID_MOVx(is->insn->id) || is->insn->detail->arm.operands[1].type != ARM_OP_IMM) {
2265  return;
2266  }
2267  ra = is->insn->detail->arm.operands[0].reg;
2268  va = is->insn->detail->arm.operands[1].imm;
2269  disasm_iter(fw, is);
2270  if(is->insn->id != ARM_INS_MOVT
2271  || is->insn->detail->arm.operands[0].reg != ra
2272  || is->insn->detail->arm.operands[1].type != ARM_OP_IMM) {
2273  return;
2274  }
2275  va = (is->insn->detail->arm.operands[1].imm << 16) | (va & 0xFFFF);
2276  // fw has BIC
2277  va = va & ~1;
2278  if(adr_get_range_type(fw,va) != ADR_RANGE_ROM) {
2279  return;
2280  }
2281  disasm_iter(fw, is);
2282  if(!IS_INSN_ID_MOVx(is->insn->id) || is->insn->detail->arm.operands[1].type != ARM_OP_IMM) {
2283  return;
2284  }
2285  rb = is->insn->detail->arm.operands[0].reg;
2286  vb = is->insn->detail->arm.operands[1].imm;
2287  disasm_iter(fw, is);
2288  if(is->insn->id != ARM_INS_MOVT
2289  || is->insn->detail->arm.operands[0].reg != rb
2290  || is->insn->detail->arm.operands[1].type != ARM_OP_IMM) {
2291  return;
2292  }
2293  vb = (is->insn->detail->arm.operands[1].imm << 16) | (vb & 0xFFFF);
2294  vb = vb & ~1;
2295  if(adr_get_range_type(fw,vb) != ADR_RANGE_ROM) {
2296  return;
2297  }
2298  if(va >= vb) {
2299  return;
2300  }
2302  // printf("ex vec 0x%08x-0x%08x\n",va,vb);
2303 
2304  } else if(is->insn->id == ARM_INS_MCR) {
2305  // digic 7 = mcr ...
2306  fw->arch_flags |= FW_ARCH_FL_VMSA;
2307  // rewind 1
2308  disasm_iter_init(fw, is, adr_hist_get(&is->ah,1));
2309  disasm_iter(fw, is);
2310  // uint32_t ex_vec = LDR_PC2val(fw,is->insn);
2311  //printf("found MCR @ 0x%"PRIx64" ex vec at 0x%08x\n",is->insn->address,ex_vec);
2312  }
2313 }
uint32_t find_last_call_from_func ( firmware fw,
iter_state_t is,
int  min_insns,
int  max_insns 
)

Definiert in Zeile 1641 der Datei firmware_load_ng.c.

1642 {
1643  int push_found=0;
1644  uint32_t last_adr=0;
1645  int count;
1646  for(count=0; count < max_insns; count++) {
1647  if(!disasm_iter(fw,is)) {
1648  fprintf(stderr,"find_last_call_from_func: disasm failed 0x%"PRIx64"\n",is->adr);
1649  return 0;
1650  }
1651  // TODO could match push regs with pop
1652  if(isPUSH_LR(is->insn)) {
1653  // already found a PUSH LR, probably in new function
1654  if(push_found) {
1655  //printf("find_last_call_from_func: second push pc 0x%"PRIx64"\n",is->adr);
1656  return 0;
1657  }
1658  push_found=1;
1659  continue;
1660  }
1661  // ignore everything before push (could be some mov/ldr, shoudln't be any calls)
1662  // TODO may want to allow starting in the middle of a function
1663  if(!push_found) {
1664  continue;
1665  }
1666  // found a potential call, store
1667  if(insn_match_any(is->insn,match_bl_blximm) && count >= min_insns) {
1668  //printf("find_last_call_from_func: found call 0x%"PRIx64"\n",is->adr);
1669  last_adr=get_branch_call_insn_target(fw,is);
1670  continue;
1671  }
1672  // found pop PC, can only be stored call if present
1673  if(isPOP_PC(is->insn)) {
1674  // printf("find_last_call_from_func: found pop PC 0x%"PRIx64"\n",is->adr);
1675  if(last_adr) {
1676  return last_adr;
1677  }
1678  // no call found, or not found within min
1679  return 0;
1680  }
1681  // found pop LR, check if next is unconditional B
1682  if(isPOP_LR(is->insn)) {
1683  // hit func end with less than min, no match
1684  if(count < min_insns) {
1685  // printf("find_last_call_from_func: pop before min 0x%"PRIx64"\n",is->adr);
1686  return 0;
1687  }
1688  if(!disasm_iter(fw,is)) {
1689  fprintf(stderr,"find_last_call_from_func: disasm failed 0x%"PRIx64"\n",is->adr);
1690  return 0;
1691  }
1692  if(is->insn->id == ARM_INS_B && is->insn->detail->arm.cc == ARM_CC_AL) {
1693  return get_branch_call_insn_target(fw,is);
1694  }
1695  // doen't go more than one insn after pop (could be more, but uncommon)
1696  // printf("find_last_call_from_func: more than one insn after pop 0x%"PRIx64"\n",is->adr);
1697  return 0;
1698  }
1699  // found another kind of ret, give up
1700  if(isRETx(is->insn)) {
1701  // printf("find_last_call_from_func: other ret 0x%"PRIx64"\n",is->adr);
1702  return 0;
1703  }
1704  }
1705  // printf("find_last_call_from_func: no match in range 0x%"PRIx64"\n",is->adr);
1706  return 0;
1707 }
uint32_t find_next_bytes_range ( firmware fw,
const void *  bytes,
size_t  len,
uint32_t  start_adr,
uint32_t  max_adr 
)

Definiert in Zeile 132 der Datei firmware_load_ng.c.

133 {
134  if(!start_adr) {
135  start_adr = fw->base;
136  }
137  if(start_adr < fw->base || start_adr >= fw->base + fw->size8) {
138  fprintf(stderr,"find_next_bytes_range invalid start_adr 0x%08x\n",start_adr);
139  return 0;
140  }
141  if(!max_adr) {
142  max_adr = fw->base + fw->size8-1;
143  }
144  if(max_adr < fw->base || max_adr >= fw->base + fw->size8) {
145  fprintf(stderr,"find_next_bytes_range invalid max_adr 0x%08x\n",max_adr);
146  return 0;
147  }
148  int end_k = (max_adr - fw->base);
149  BufRange *p = getBufRangeForIndex(fw,(start_adr - fw->base)/4);
150  if(!p) {
151  return 0;
152  }
153  int k = start_adr - fw->base;
154 
155  while (k < end_k)
156  {
157  for (; k < (p->off + p->len)*4; k++)
158  {
159  if (memcmp(fw->buf8+k,bytes,len) == 0) {
160  return fw->base+k;
161  }
162  }
163  p = p->next;
164  if(!p) {
165  break;
166  }
167  k = p->off*4;
168  }
169  return 0;
170 }
uint32_t find_next_str_bytes ( firmware fw,
const char *  str,
uint32_t  adr 
)

Definiert in Zeile 211 der Datei firmware_load_ng.c.

212 {
213  // +1 to include the null in memcmp
214  return find_next_bytes_range(fw,str,strlen(str)+1,adr,0);
215 }
uint32_t find_next_str_bytes_range ( firmware fw,
const char *  str,
uint32_t  adr,
uint32_t  max_adr 
)

Definiert in Zeile 190 der Datei firmware_load_ng.c.

191 {
192  // +1 to include the null in memcmp
193  return find_next_bytes_range(fw,str,strlen(str)+1,adr,max_adr);
194 }
uint32_t find_next_substr_bytes ( firmware fw,
const char *  str,
uint32_t  adr 
)

Definiert in Zeile 183 der Datei firmware_load_ng.c.

184 {
185  //fprintf(stderr,"find_next_substr_bytes 0x%08x\n",adr);
186  // strlen excludes null
187  return find_next_bytes_range(fw,str,strlen(str),adr,0);
188 }
int find_Nth_str ( firmware fw,
char *  str,
int  N 
)

Definiert in Zeile 99 der Datei firmware_load_ng.c.

100 {
101  int nlen = strlen(str);
102  uint32_t nm0 = *((uint32_t*)str);
103  uint32_t *p;
104  int j;
105 
106  BufRange *br = fw->br;
107  while (br)
108  {
109  for (p = br->p, j = 0; j < br->len - nlen/4; j++, p++)
110  {
111  if ((nm0 == *p) && ((nlen<=4) || (memcmp(p+1,str+4,nlen-4) == 0)) )
112  {
113  if (--N == 0)
114  return j+br->off;
115  }
116  }
117  br = br->next;
118  }
119 
120  return -1;
121 }
int find_startup_copy ( firmware fw,
iter_state_t is,
int  max_search,
uint32_t src_start,
uint32_t dst_start,
uint32_t dst_end 
)

Definiert in Zeile 2184 der Datei firmware_load_ng.c.

2190 {
2191  int count=0;
2192  uint32_t *fptr = NULL;
2193  uint32_t *dptr = NULL;
2194  uint32_t *eptr = NULL;
2195  *src_start=0;
2196  *dst_start=0;
2197  *dst_end=0;
2198 
2199  while(disasm_iter(fw,is) && count < max_search) {
2200  uint32_t *pv=LDR_PC2valptr(fw,is->insn);
2201  // not an LDR pc, reset
2202  // TODO some firmwares might use other instructions
2203  if(!pv) {
2204  fptr=dptr=eptr=NULL;
2205  }else if(!fptr) {
2206  // only candidate if in ROM
2207  if(*pv > fw->base) {
2208  fptr=pv;
2209  }
2210  } else if(!dptr) {
2211  if(*pv < fw->base) {
2212  dptr=pv;
2213  } else {
2214  fptr=NULL; // dest address in ROM, reset
2215  }
2216  } else if(!eptr) {
2217  if(*pv < fw->base && *pv > *dptr) {
2218  eptr=pv;
2219  } else { // dest end address in ROM, or before source, reset
2220  // TODO maybe should swap instead if < source
2221  fptr=dptr=NULL;
2222  }
2223  }
2224  if(fptr && dptr && eptr) {
2225  *src_start=*fptr;
2226  *dst_start=*dptr;
2227  *dst_end=*eptr;
2228  return 1;
2229  }
2230  count++;
2231  }
2232  return 0;
2233 }
int find_str ( firmware fw,
char *  str 
)

Definiert in Zeile 123 der Datei firmware_load_ng.c.

124 {
125  return find_Nth_str(fw, str, 1);
126 }
uint32_t find_str_bytes ( firmware fw,
const char *  str 
)

Definiert in Zeile 219 der Datei firmware_load_ng.c.

220 {
221  return find_next_str_bytes(fw,str,fw->base);
222 }
uint32_t find_str_bytes_main_fw ( firmware fw,
const char *  str 
)

Definiert in Zeile 197 der Datei firmware_load_ng.c.

198 {
199  // max is end of fw code + 4096, assuming it fits in fw
200  // while early code could technically load from base - 1k, unlikely
201  uint32_t max_adr;
202  if(fw->base + fw->size8 - 4096 > fw->rom_code_search_max_adr) {
203  max_adr = fw->rom_code_search_max_adr + 4096;
204  } else {
205  max_adr = fw->base + fw->size8;
206  }
207  // +1 to include the null in memcmp
208  return find_next_bytes_range(fw,str,strlen(str)+1,fw->rom_code_search_min_adr,max_adr);
209 }
uint32_t find_u32_adr ( firmware fw,
uint32_t  val,
uint32_t  start 
)

Definiert in Zeile 401 der Datei firmware_load_ng.c.

402 {
403  return find_u32_adr_range(fw,val,start, fw->base + (fw->size8 -4));
404 }
uint32_t find_u32_adr_range ( firmware fw,
uint32_t  val,
uint32_t  start,
uint32_t  maxadr 
)

Definiert in Zeile 369 der Datei firmware_load_ng.c.

370 {
371  // TODO
372  if(start == 0) {
373  start=fw->base;
374  }
375  if(start & 3) {
376  fprintf(stderr,"find_u32_adr unaligned start 0x%08x\n",start);
377  return 0;
378  }
379  uint32_t *p=(uint32_t *)adr2ptr(fw,start);
380  if(!p) {
381  fprintf(stderr,"find_u32_adr bad start 0x%08x\n",start);
382  return 0;
383  }
384  uint32_t *p_end;
385  if(maxadr) {
386  p_end = (uint32_t *)adr2ptr(fw,maxadr);
387  } else {
388  p_end = fw->buf32 + fw->size32 - 1;
389  }
390  // TODO should use buf ranges
391  while(p<=p_end) {
392  if(*p==val) {
393  return ptr2adr(fw,(uint8_t *)p);
394  }
395  p++;
396  }
397  return 0;
398 }
static void findRanges ( firmware fw)
static

Definiert in Zeile 32 der Datei firmware_load_ng.c.

33 {
34  int i, j, k;
35 
36  // Find all the valid ranges for checking (skips over large blocks of 0xFFFFFFFF)
37  fw->br = 0; fw->last = 0;
38  k = -1; j = 0;
39  for (i = 0; i < fw->size32; i++)
40  {
41  if (fw->buf32[i] == 0xFFFFFFFF) // Possible start of block to skip
42  {
43  if (k == -1) // Mark start of possible skip block
44  {
45  k = i;
46  }
47  }
48  else // Found end of block ?
49  {
50  if (k != -1)
51  {
52  if (i - k > 32) // If block more than 32 words then we want to skip it
53  {
54  if (k - j > 8)
55  {
56  // Add a range record for the previous valid range (ignore short ranges)
57  addBufRange(fw,j,k - j);
58  }
59  j = i; // Reset valid range start to current position
60  }
61  k = -1; // Reset marker for skip block
62  }
63  }
64  }
65  // Add range for last valid block
66  if (k != -1)
67  {
68  if (k - j > 8)
69  {
70  addBufRange(fw,j,k - j);
71  }
72  }
73  else
74  {
75  if (i - j > 8)
76  {
77  addBufRange(fw,j,i - j);
78  }
79  }
80 }
int firmware_init_capstone ( firmware fw)

Definiert in Zeile 2159 der Datei firmware_load_ng.c.

2160 {
2161  if (cs_open(CS_ARCH_ARM, CS_MODE_ARM, &fw->cs_handle_arm) != CS_ERR_OK) {
2162  fprintf(stderr,"cs_open ARM failed\n");
2163  return 0;
2164  }
2165  cs_option(fw->cs_handle_arm, CS_OPT_DETAIL, CS_OPT_ON);
2166  if (cs_open(CS_ARCH_ARM, CS_MODE_THUMB, &fw->cs_handle_thumb) != CS_ERR_OK) {
2167  fprintf(stderr,"cs_open thumb failed\n");
2168  return 0;
2169  }
2170  cs_option(fw->cs_handle_thumb, CS_OPT_DETAIL, CS_OPT_ON);
2171  fw->is=disasm_iter_new(fw,0);
2172  do_blx_check(fw);
2173  return 1;
2174 }
void firmware_init_data_ranges ( firmware fw)

highest known first copied ram code 0x01900000

Definiert in Zeile 2316 der Datei firmware_load_ng.c.

2317 {
2318 //TODO maybe should return status
2319  uint32_t src_start, dst_start, dst_end;
2320  uint32_t data_found_copy = 0;
2321 
2322  // start at fw start + 12 (32 bit jump, gaonisoy)
2323  iter_state_t *is=disasm_iter_new(fw, fw->base + fw->main_offs + 12 + fw->thumb_default);
2324 
2325  fw->data_init_start=0;
2326  fw->data_start=0;
2327  fw->data_len=0;
2328 
2329  fw->memisostart=0;
2330 
2331  int base2_found=0;
2332  int base3_found=0;
2333 
2334  // TODO pre-d6 ROMs have a lot more stuff before first copy
2335  int max_search=100;
2336  while(find_startup_copy(fw,is,max_search,&src_start,&dst_start,&dst_end)) {
2337  // all known copied code is 3f1000 or higher, guess data
2338  if(dst_start < 0x100000) {
2339  // fprintf(stderr, "data? @0x%"PRIx64" 0x%08x-0x%08x from 0x%08x\n",is->adr,dst_start,dst_end,src_start);
2340  if(fw->data_init_start) {
2341  fprintf(stderr,"firmware_init_data_ranges: data already found, unexpected start 0x%08x src 0x%08x end 0x%08x\n",
2342  dst_start,src_start,dst_end);
2343  continue;
2344  }
2345 
2346  // not a known value, warn
2347  if(dst_start != 0x1900 && dst_start != 0x8000) {
2348  fprintf(stderr,"firmware_init_data_ranges: guess unknown ROM data_start 0x%08x src 0x%08x end 0x%08x\n",
2349  dst_start,src_start,dst_end);
2350  }
2351  fw->data_init_start=src_start;
2352  fw->data_start=dst_start;
2353  fw->data_len=dst_end-dst_start;
2354  fw_add_adr_range(fw,dst_start,dst_end,src_start, ADR_RANGE_INIT_DATA, ADR_RANGE_FL_NONE);
2355  data_found_copy=is->adr;
2356  } else if(dst_start < 0x08000000) {
2357  // fprintf(stderr,"code1? @0x%"PRIx64" 0x%08x-0x%08x from 0x%08x\n",is->adr,dst_start,dst_end,src_start);
2358  if(base2_found) {
2359  fprintf(stderr,"firmware_init_data_ranges: base2 already found, unexpected start 0x%08x src 0x%08x end 0x%08x\n",
2360  dst_start,src_start,dst_end);
2361  continue;
2362  }
2363  base2_found=1;
2364  // known values
2365  if( dst_start != 0x003f1000 &&
2366  dst_start != 0x00431000 &&
2367  dst_start != 0x00471000 &&
2368  dst_start != 0x00685000 &&
2369  dst_start != 0x00671000 &&
2370  dst_start != 0x006b1000 &&
2371  dst_start != 0x010c1000 &&
2372  dst_start != 0x010e1000 &&
2373  dst_start != 0x01900000) {
2374  fprintf(stderr,"firmware_init_data_ranges: guess unknown base2 0x%08x src 0x%08x end 0x%08x\n",
2375  dst_start,src_start,dst_end);
2376  }
2377  fw_add_adr_range(fw,dst_start,dst_end,src_start,ADR_RANGE_RAM_CODE, ADR_RANGE_FL_NONE);
2378  } else { // know < ROM based on match, assume second copied code
2379  // fprintf(stderr, "code2? @0x%"PRIx64" 0x%08x-0x%08x from 0x%08x\n",is->adr,dst_start,dst_end,src_start);
2380  if(base3_found) {
2381  fprintf(stderr,"firmware_init_data_ranges: base3 already found, unexpected start 0x%08x src 0x%08x end 0x%08x\n",
2382  dst_start,src_start,dst_end);
2383  continue;
2384  }
2385  base3_found=1;
2386  if(dst_start != 0xbfe10800 && // known digic 6 value (g5x)
2387  dst_start != 0xdffc4900) { // known digic 7 value (m5)
2388  fprintf(stderr,"firmware_init_data_ranges: guess unknown base3 0x%08x src 0x%08x end 0x%08x\n",
2389  dst_start,src_start,dst_end);
2390  }
2391  fw_add_adr_range(fw,dst_start,dst_end,src_start,ADR_RANGE_RAM_CODE, ADR_RANGE_FL_TCM);
2392  }
2393  if(fw->data_start && base2_found && base3_found) {
2394  break;
2395  }
2396  // after first, shorter search range in between copies
2397  max_search=16;
2398  }
2399 
2400  // look for BSS init after last found copy
2401  if(data_found_copy) {
2402  int count=0;
2403  uint32_t *eptr=NULL;
2404  uint32_t *dptr=NULL;
2405  disasm_iter_init(fw,is,(data_found_copy-4) | fw->thumb_default);
2406  while(disasm_iter(fw,is) && count < 20) {
2407  uint32_t *pv=LDR_PC2valptr(fw,is->insn);
2408  // not an LDR pc, reset;
2409  if(!pv) {
2410  //dptr=eptr=NULL;
2411  } else if(!dptr) {
2412  // TODO older firmwares use reg with ending value from DATA copy
2413  // should be equal to end pointer of data
2414  if(*pv == fw->data_start + fw->data_len) {
2415  dptr=pv;
2416  }
2417  } else if(!eptr) {
2418  if(*pv < fw->base) {
2419  if(*pv != fw->data_start + fw->data_len) {
2420  eptr=pv;
2421  }
2422  } else { // dest end address in ROM, reset
2423  eptr=dptr=NULL;
2424  }
2425  }
2426  if(dptr && eptr) {
2427  // fprintf(stderr, "bss? @0x%"PRIx64" 0x%08x-0x%08x\n",is->adr,*dptr,*eptr);
2428  fw->memisostart=*eptr;
2429  break;
2430  }
2431  count++;
2432  }
2433  }
2434 
2435  find_exception_vec(fw,is);
2436 
2437  // if data found, adjust default code search range
2438  // TODO could use copied code regions too, but after data on known firmwares
2439  if(fw->data_start) {
2441  }
2442  // if dryos version string found, use as search limit
2443  if(fw->dryos_ver_adr) {
2444  if(fw->dryos_ver_adr < fw->rom_code_search_max_adr) {
2446  }
2447  }
2448  disasm_iter_free(is);
2449 }
void firmware_load ( firmware fw,
const char *  filename,
uint32_t  base_adr,
int  fw_arch 
)

Definiert in Zeile 2030 der Datei firmware_load_ng.c.

2031 {
2032  FILE *f = fopen(filename, "rb");
2033  if (f == NULL)
2034  {
2035  fprintf(stderr,"Error opening %s\n",filename);
2036  exit(1);
2037  }
2038  fseek(f,0,SEEK_END);
2039  fw->size8 = ftell(f);
2040  fseek(f,0,SEEK_SET);
2041  // dumps should be an integral number of 32 bit words
2042  // ensures accessing as 32 bit ints safe
2043  if(fw->size8&3) {
2044  fprintf(stderr,"WARNING: dump size %d is not divisible by 4, truncating\n",fw->size8);
2045  fw->size8 &= ~3;
2046  }
2047 
2048  // adjust to ensure base_adr + size doesn't overflow
2049  if((int)(0xFFFFFFFF - base_adr) < fw->size8) {
2050  fprintf(stderr,"adjusted dump size 0x%08x->",fw->size8);
2051  fw->size8 = 0xFFFFFFFC - base_adr;
2052  fprintf(stderr,"0x%08x\n",fw->size8);
2053  }
2054 
2055  fw->arch=fw_arch;
2056  fw->size32=fw->size8/4;
2057 
2058  fw->base = base_adr;
2059 
2060  fw->buf8 = malloc(fw->size8);
2061  if(!fw->buf8) {
2062  fprintf(stderr,"malloc %d failed\n",fw->size8);
2063  exit(1);
2064  }
2065  fread(fw->buf8, 1, fw->size8, f);
2066  fclose(f);
2067  findRanges(fw);
2068 
2069  fw->adr_range_count=0;
2070  // add ROM
2072 
2073  fw->main_offs = 0;
2074  int k = find_str(fw, "gaonisoy");
2075  // assume firmware start is 32 bit jump over goanisoy
2076  if(k == -1) {
2077  // suppress warning on vxworks, main firmware start is always offset 0
2078  if(find_str(fw,"VxWorks") == -1) {
2079  fprintf(stderr,"WARNING gaonisoy string not found, assuming code start offset 0\n");
2080  }
2081  } else if (k != 1) {
2082  // check at 0x20004 - note doesn't just use offset of first gaonisoy, because could be ref'd in romstarter
2083  if(fw_memcmp(fw,fw->base+0x20004,"gaonisoy",8) == 0) {
2084  fw->main_offs = 0x20000;
2085  } else if (fw_memcmp(fw,fw->base+0x10004,"gaonisoy",8) == 0) { // newer armv5 firmwares base ff81000 start at ff820000
2086  fw->main_offs = 0x10000;
2087  } else {
2088  fprintf(stderr,"WARNING code start offset not found, assuming 0\n");
2089  }
2090  }
2091 
2092  fw->rom_code_search_min_adr = fw->base + fw->main_offs; // 0 if not found
2093  fw->rom_code_search_max_adr=fw->base+fw->size8 - 4; // default == end of fw, may be adjusted by firmware_init_data_ranges
2094 
2095  find_dryos_vers(fw);
2096 
2097  fw->firmware_ver_str = 0;
2098  k = find_str(fw, "Firmware Ver ");
2099  if (k != -1)
2100  {
2101  fw->firmware_ver_str = (char *)fw->buf8 + k*4;
2102  }
2103  // set expected instruction set
2104  if(fw->arch==FW_ARCH_ARMv5) {
2105  fw->thumb_default = 0;
2106  } else if(fw->arch==FW_ARCH_ARMv7) {
2107  fw->thumb_default = 1;
2108  } else {
2109  fprintf(stderr,"firmware_init_capstone: invalid arch\n");
2110  }
2111 }
void firmware_unload ( firmware fw)

Definiert in Zeile 2452 der Datei firmware_load_ng.c.

2453 {
2454  if(!fw) {
2455  return;
2456  }
2457  if(fw->is) {
2458  disasm_iter_free(fw->is);
2459  }
2460  if(fw->cs_handle_arm) {
2461  cs_close(&fw->cs_handle_arm);
2462  }
2463  if(fw->cs_handle_thumb) {
2464  cs_close(&fw->cs_handle_thumb);
2465  }
2466  free(fw->buf8);
2467  memset(fw,0,sizeof(firmware));
2468 }
void fw_add_adr_range ( firmware fw,
uint32_t  start,
uint32_t  end,
uint32_t  src_start,
int  type,
int  flags 
)

Definiert in Zeile 1939 der Datei firmware_load_ng.c.

1940 {
1941  if(fw->adr_range_count == FW_MAX_ADR_RANGES) {
1942  fprintf(stderr,"fw_add_adr_range: FW_MAX_ADR_RANGES hit\n");
1943  return;
1944  }
1945  if(src_start < fw->base) {
1946  fprintf(stderr,"fw_add_adr_range: src_start 0x%08x < base 0x%08x\n",src_start,fw->base);
1947  return;
1948  }
1949  if(src_start >= fw->base+fw->size8) {
1950  fprintf(stderr,"fw_add_adr_range: src_start 0x%08x outside dump end 0x%08x\n",src_start,fw->base+fw->size8);
1951  return;
1952  }
1953  if(end <= start) {
1954  fprintf(stderr,"fw_add_adr_range: end 0x%08x <= start 0x%08x\n",end,start);
1955  return;
1956  }
1957  uint32_t len=end-start;
1958  if(len > 0xFFFFFFFF - src_start) {
1959  fprintf(stderr,"fw_add_adr_range: range too long %d\n",len);
1960  return;
1961  }
1962  if(len > fw->size8 - (start - fw->base)) {
1963  fprintf(stderr,"fw_add_adr_range: range outside of dump %d\n",len);
1964  return;
1965  }
1966  adr_range_t *r=&fw->adr_ranges[fw->adr_range_count];
1967  // TODO some firmware copies (i.e. g5x code 2) may end on non-word aligned address even though copy is words
1968  r->start=start;
1969  r->src_start=src_start;
1970  r->bytes=len;
1971  r->type=type;
1972  r->flags=flags;
1973  r->buf=fw->buf8 + (r->src_start - fw->base);
1974 
1975  fw->adr_range_count++;
1976 }
int fw_disasm_iter ( firmware fw)

Definiert in Zeile 1031 der Datei firmware_load_ng.c.

1032 {
1033  return disasm_iter(fw,fw->is);
1034 }
int fw_disasm_iter_single ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 1038 der Datei firmware_load_ng.c.

1039 {
1040  fw_disasm_iter_start(fw,adr);
1041  return fw_disasm_iter(fw);
1042 }
int fw_disasm_iter_start ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 1025 der Datei firmware_load_ng.c.

1026 {
1027  return disasm_iter_init(fw,fw->is,adr);
1028 }
int fw_memcmp ( firmware fw,
uint32_t  adr,
const void *  cmp,
size_t  n 
)

Definiert in Zeile 418 der Datei firmware_load_ng.c.

419 {
420  uint32_t *p=(uint32_t *)adr2ptr(fw,adr);
421  if(!p) {
422  return 1;
423  }
424  if(n >= fw->size8 - (adr - fw->base)) {
425  return 1;
426  }
427  return memcmp(p,cmp,n);
428 }
int fw_search_bytes ( firmware fw,
search_bytes_fn  func 
)

Definiert in Zeile 1920 der Datei firmware_load_ng.c.

1921 {
1922  BufRange *p = fw->br;
1923  while (p)
1924  {
1925  int k;
1926  for (k = p->off*4; k < (p->off + p->len)*4; k++)
1927  {
1928  if (func(fw,k))
1929  return 1;
1930  }
1931  p = p->next;
1932  }
1933  return 0;
1934 }
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 1072 der Datei firmware_load_ng.c.

1073 {
1074  uint32_t adr_start=is->adr;
1075  adr_range_t *r_start=adr_get_range(fw,adr_start);
1076  if(!r_start) {
1077  fprintf(stderr,"fw_search_insn: invalid start address 0x%08x\n",adr_start);
1078  return 0;
1079  }
1080 
1081  // default to end of start range
1082  if(!adr_end) {
1083  if(r_start->type == ADR_RANGE_ROM) {
1084  adr_end = fw->rom_code_search_max_adr;
1085  } else {
1086  adr_end=r_start->start + r_start->bytes - is->insn_min_size;
1087  }
1088  }
1089  adr_range_t *r_end=adr_get_range(fw,adr_end);
1090 
1091  if(!r_end) {
1092  fprintf(stderr,"fw_search_insn: invalid end address 0x%08x\n",adr_end);
1093  return 0;
1094  }
1095  // ignore thumb bit on end adr
1096  adr_end=ADR_CLEAR_THUMB(adr_end);
1097 
1098  if((r_start != r_end) || (adr_end < adr_start)) {
1099  fprintf(stderr,"fw_search_insn: invalid address range 0x%08x 0x%08x\n",adr_start,adr_end);
1100  return 0;
1101  }
1102 
1103  uint32_t adr=adr_start;
1104  // don't bother with buf ranges for RAM code
1105  if(r_start->type != ADR_RANGE_ROM) {
1106  while(adr < adr_end) {
1107  if(disasm_iter(fw,is)) {
1108  uint32_t r=f(fw,is,v1,udata);
1109  if(r) {
1110  return r;
1111  }
1112  adr=(uint32_t)is->adr; // adr was updated by iter or called sub
1113  } else {
1114  // disassembly failed
1115  // increment by minimum instruction size and re-init
1116  adr=adr+is->insn_min_size;
1117  if(!disasm_iter_init(fw,is,adr|is->thumb)) {
1118  fprintf(stderr,"fw_search_insn: disasm_iter_init failed\n");
1119  return 0;
1120  }
1121  }
1122  }
1123  return 0;
1124  }
1125  BufRange *br=fw->br;
1126  // TODO might want to (optionally?) turn off details? For now, caller can set, doesn't seem to help perf much
1127  // TODO when searching ROM, could skip over RAM copied areas (currently just limit default range)
1128  while(br && adr < adr_end) {
1129  uint32_t *p_adr=(uint32_t *)adr2ptr(fw,(uint32_t)adr);
1130  uint32_t *br_end = br->p + br->len;
1131  uint32_t adr_chunk_end = ptr2adr(fw,(uint8_t*)br_end);
1132  if(adr_end < adr_chunk_end) {
1133  adr_chunk_end = adr_end;
1134  }
1135  // address is before start of current range, adjust
1136  if(p_adr < br->p) {
1137  adr=ptr2adr(fw,(uint8_t *)br->p);
1138  if(!disasm_iter_init(fw,is,(uint32_t)adr)) {
1139  return 0;
1140  }
1141  p_adr=(uint32_t *)adr2ptr(fw,(uint32_t)adr);
1142  }
1143  //printf("br:0x%08x-0x%08x\n",ptr2adr(fw,(uint8_t *)br->p),ptr2adr(fw,(uint8_t *)(br->p+br->len)));
1144  while(adr < adr_chunk_end) {
1145  if(disasm_iter(fw,is)) {
1146  uint32_t r=f(fw,is,v1,udata);
1147  if(r) {
1148  return r;
1149  }
1150  adr=(uint32_t)is->adr; // adr was updated by iter or called sub
1151  } else {
1152  // disassembly failed. cs_disarm_iter does not update address
1153  // increment by half word and re-init
1154  adr=adr+is->insn_min_size;
1155  if(!disasm_iter_init(fw,is,adr|is->thumb)) {
1156  fprintf(stderr,"fw_search_insn: disasm_iter_init failed\n");
1157  return 0;
1158  }
1159  }
1160  }
1161  // next range
1162  br=br->next;
1163  }
1164  return 0;
1165 }
uint32_t fw_u32 ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 407 der Datei firmware_load_ng.c.

408 {
409  uint32_t *p=(uint32_t *)adr2ptr(fw,adr);
410  if(!p) {
411  fprintf(stderr,"fw_u32 bad adr 0x%08x\n",adr);
412  return 0;
413  }
414  return *p;
415 }
uint32_t get_branch_call_insn_target ( firmware fw,
iter_state_t is 
)

Definiert in Zeile 1441 der Datei firmware_load_ng.c.

1442 {
1443  uint32_t adr=B_BL_target(fw,is->insn);
1444  if(adr) {
1445  return (adr | is->thumb);
1446  }
1447  // CBx only exists in thumb
1448  if(is->thumb) {
1449  adr=CBx_target(fw,is->insn);
1450  if(adr) {
1451  return ADR_SET_THUMB(adr);
1452  }
1453  }
1454 
1455  adr=BLXimm_target(fw,is->insn);
1456  if(adr) {
1457  if(is->thumb) {
1458  return adr;
1459  } else {
1460  return adr | is->thumb;
1461  }
1462  }
1463 
1464  adr=LDR_PC_PC_target(fw,is->insn);
1465  if(adr) {
1466  return adr;
1467  }
1468  return 0;
1469 }
int get_call_const_args ( firmware fw,
iter_state_t is_init,
int  max_backtrack,
uint32_t res 
)

Definiert in Zeile 1265 der Datei firmware_load_ng.c.

1266 {
1267  int i;
1268  /*
1269  static int dbg_count=0;
1270  if(is_init->insn->address==...) {
1271  dbg_count=1;
1272  } else {
1273  dbg_count=0;
1274  }
1275  */
1276 
1277  // init regs to zero (to support adds etc)
1278  for (i=0;i<4;i++) {
1279  res[i]=0;
1280  }
1281 
1282  // count includes current instruction (i.e. BL of call)
1283  if(is_init->ah.count <= 1) {
1284  return 0;
1285  }
1286  if(is_init->ah.count - 1 < max_backtrack) {
1287  /*
1288  if(dbg_count > 0) {
1289  printf("max_backtrack %d hist count %d\n",max_backtrack,is_init->ah.count);
1290  }
1291  */
1292  max_backtrack = is_init->ah.count-1;
1293  }
1294  uint32_t found_bits=0; // registers with known const values
1295  uint32_t known_bits=0; // registers with some value
1296 
1297  for(i=1;i<=max_backtrack && known_bits !=0xf;i++) {
1298  // TODO going backwards and calling start each time inefficient
1299  // forward could also find multi-instruction constants in some cases (e.g mov + add, movw + movt)
1300  fw_disasm_iter_single(fw,adr_hist_get(&is_init->ah,i)); // thumb state comes from hist
1301  /*
1302  if(dbg_count > 0) {
1303  printf("backtrack %d:%d ",dbg_count,i);
1304  printf("%"PRIx64" %s %s\n",fw->is->insn->address,fw->is->insn->mnemonic, fw->is->insn->op_str);
1305  }
1306  */
1307  arm_insn insn_id = fw->is->insn->id;
1308  // BL, BLX etc will trash r0-r3
1309  // only break on unconditional - optimistic, could produce incorrect results
1310  if((insn_id == ARM_INS_BL || insn_id == ARM_INS_BLX
1311  // B/BX could mean execution goes somewhere totally different, but in practice it often just skipping over a word of data...
1312  /*|| insn_id == ARM_INS_B || insn_id == ARM_INS_BX*/)
1313  && fw->is->insn->detail->arm.cc == ARM_CC_AL) {
1314  break;
1315  }
1316 
1317  // if the first op isn't REG, continue
1318  // TODO lots of instructions could affect reg even if not first op
1319  if(fw->is->insn->detail->arm.operands[0].type != ARM_OP_REG) {
1320  continue;
1321  }
1322  arm_reg rd = fw->is->insn->detail->arm.operands[0].reg;
1323  // capstone arm.h regs enum R0-R12 are ordered
1324  // enum has entries before R0
1325  if(rd < ARM_REG_R0 || rd > ARM_REG_R3) {
1326  continue;
1327  }
1328 
1329  int rd_i = rd - ARM_REG_R0;
1330  uint32_t rd_bit = 1 << rd_i;
1331  // if we don't already have something for this reg
1332  if(!(known_bits & rd_bit)) {
1333  // know something has been done to this reg
1334  // note doesn't account for conditionals
1335  known_bits |=rd_bit;
1336  // is it an LDR
1337  uint32_t *pv=LDR_PC2valptr(fw,fw->is->insn);
1338  if(pv) {
1339  res[rd_i] += *pv;
1340 // if(dbg_count) printf("found ldr r%d,=0x%08x\n",rd_i,res[rd_i]);
1341  found_bits |=rd_bit;
1342  continue;
1343  }
1344  uint32_t v=ADRx2adr(fw,fw->is->insn); // assumes ADR doesn't generate 0, probably safe
1345  if(v) {
1346  res[rd_i] += v;
1347 // if(dbg_count) printf("found adrx r%d,0x%08x\n",rd_i,res[rd_i]);
1348  found_bits |=rd_bit;
1349  continue;
1350  }
1351  // immediate MOV note MOVT combinations, not accounted for, some handled ADDs below
1352  if( IS_INSN_ID_MOVx(insn_id)
1353  && fw->is->insn->detail->arm.operands[1].type == ARM_OP_IMM) {
1354  res[rd_i] += fw->is->insn->detail->arm.operands[1].imm;
1355 // if(dbg_count) printf("found move r%d,#0x%08x\n",rd_i,res[rd_i]);
1356  found_bits |=rd_bit;
1357  } else if(isADDx_imm(fw->is->insn)) {
1358  res[rd_i] += fw->is->insn->detail->arm.operands[1].imm;
1359 // if(dbg_count) printf("found add r%d,#0x%08x\n",rd_i,res[rd_i]);
1360  // pretend reg is not known
1361  known_bits ^=rd_bit;
1362  // do not set found bit here
1363  } else if(isSUBx_imm(fw->is->insn)) {
1364  res[rd_i] = (int)(res[rd_i]) - fw->is->insn->detail->arm.operands[1].imm;
1365 // if(dbg_count) printf("found add r%d,#0x%08x\n",rd_i,res[rd_i]);
1366  // pretend reg is not known
1367  known_bits ^=rd_bit;
1368  // do not set found bit here
1369  }/* else {
1370  }
1371  */
1372  }
1373  }
1374 // if(dbg_count) printf("get_call_const_args found 0x%08x\n",found_bits);
1375  return found_bits;
1376 }
uint32_t get_direct_jump_target ( firmware fw,
iter_state_t is_init 
)

Definiert in Zeile 1390 der Datei firmware_load_ng.c.

1391 {
1392  uint32_t adr=B_target(fw,is_init->insn);
1393  // B ... return with thumb set to current mode
1394  if(adr) {
1395  return (adr | is_init->thumb);
1396  }
1397  adr=LDR_PC_PC_target(fw,is_init->insn);
1398  // LDR pc #... thumb is set in the loaded address
1399  if(adr) {
1400  return adr;
1401  }
1402  // an immediate move to ip (R12), candidate for multi-instruction veneer
1403  if((is_init->insn->id == ARM_INS_MOV || is_init->insn->id == ARM_INS_MOVW)
1404  && is_init->insn->detail->arm.operands[0].reg == ARM_REG_IP
1405  && is_init->insn->detail->arm.operands[1].type == ARM_OP_IMM) {
1406  adr = is_init->insn->detail->arm.operands[1].imm;
1407  // iter in default state, starting from is_init
1408  if(!fw_disasm_iter_single(fw,is_init->adr | is_init->thumb)) {
1409  fprintf(stderr,"get_direct_jump_target: disasm single failed at 0x%"PRIx64"\n",fw->is->insn->address);
1410  return 0;
1411  }
1412  // check for MOVT ip, #x
1413  if(!(fw->is->insn->id == ARM_INS_MOVT
1414  && fw->is->insn->detail->arm.operands[0].reg == ARM_REG_IP
1415  && fw->is->insn->detail->arm.operands[1].type == ARM_OP_IMM)) {
1416 // doesn't match second two insn veneer, not really an arror
1417 // fprintf(stderr,"get_direct_jump_target: not 2 insn ip veneer 0x%"PRIx64"\n",fw->is->insn->address);
1418  return 0;
1419  }
1420  // thumb set in loaded adr
1421  adr = (fw->is->insn->detail->arm.operands[1].imm << 16) | (adr&0xFFFF);
1422  if(!fw_disasm_iter(fw)) {
1423  fprintf(stderr,"get_direct_jump_target: disasm 2 failed at 0x%"PRIx64"\n",fw->is->insn->address);
1424  return 0;
1425  }
1426  // BX ip ?
1427  if(fw->is->insn->id == ARM_INS_BX
1428  && fw->is->insn->detail->arm.operands[0].type == ARM_OP_REG
1429  && fw->is->insn->detail->arm.operands[0].reg == ARM_REG_IP) {
1430  return adr;
1431  }
1432  }
1433  return 0;
1434 }
int get_TBx_PC_info ( firmware fw,
iter_state_t is,
tbx_info_t ti 
)

Definiert in Zeile 831 der Datei firmware_load_ng.c.

832 {
833  if(!(is->insn->id == ARM_INS_TBH || is->insn->id == ARM_INS_TBB) || is->insn->detail->arm.operands[0].mem.base != ARM_REG_PC) {
834  return 0;
835  }
836  ti->start=(uint32_t)is->adr; // after current instruction
837  ti->first_target=0;
838  ti->bytes=(is->insn->id == ARM_INS_TBH)?2:1;
839 
840  uint32_t max_adr;
841  // max possible (assuming jumptable is contiguous)
842  if(ti->bytes==1) {
843  max_adr=ti->start+(2*255);
844  } else {
845  max_adr=ti->start+(2*65535);
846  }
847  arm_reg i_reg=is->insn->detail->arm.operands[0].mem.index;
848  // backtrack looking for
849  // cmp index reg,#imm
850  // ...
851  // bhs ...
852  int max_backtrack = 8;
853  if(is->ah.count - 1 < max_backtrack) {
854  max_backtrack = is->ah.count-1;
855  }
856 
857  int max_count=0;
858  int found_bhs=0;
859  int i;
860  for(i=1;i<=max_backtrack;i++) {
861  fw_disasm_iter_single(fw,adr_hist_get(&is->ah,i)); // thumb state comes from hist
862  if(fw->is->insn->id == ARM_INS_B && fw->is->insn->detail->arm.cc == ARM_CC_HS) {
863  found_bhs=1;
864  continue;
865  }
866  // TODO lots of other ways condition code or reg could be changed in between
867  if(found_bhs && fw->is->insn->id == ARM_INS_CMP) {
868  // cmp with correct operands, assume number of jumptable entries
869  if((arm_reg)fw->is->insn->detail->arm.operands[0].reg == i_reg
870  || fw->is->insn->detail->arm.operands[1].type == ARM_OP_IMM) {
871  max_count = fw->is->insn->detail->arm.operands[1].imm;
872  }
873  // otherwise, give up
874  break;
875  }
876  }
877  if(max_count) {
878  max_adr = ti->start+max_count*ti->bytes;
879  //printf("get_TBx_PC_info: max_count %d start 0x%08x max_adr=0x%08x\n",max_count,ti->start,max_adr);
880  }
881  uint32_t adr=ti->start;
882  while(adr < max_adr) {
883  uint8_t *p=adr2ptr(fw,adr);
884  if(!p) {
885  fprintf(stderr,"get_TBx_PC_info: jumptable outside of valid address range at 0x%08x\n",adr);
886  return 0;
887  }
888  uint16_t off;
889  if(ti->bytes==1) {
890  off=(uint16_t)*p;
891  } else {
892  off=*(uint16_t *)p;
893  }
894 
895  // 0, probably padding at the end (could probably break here)
896  // note shouldn't be padding on tbh, since aligned for thumb
897  if(!off) {
898  break;
899  }
900  uint32_t target = ti->start+2*off;
901  // may indicate non-jumptable entry, if count not found, so don't increment adr
902  if(target <= adr) {
903  fprintf(stderr,"get_TBx_PC_info: jumptable target 0x%08x inside jumptable %d at 0x%08x\n",target,off,adr);
904  break;
905  }
906  if(!ti->first_target || target < ti->first_target) {
907  ti->first_target=target;
908  if(target < max_adr) {
909  max_adr=target; // assume jump table ends at/before first target
910  }
911  }
912  adr+=ti->bytes;
913  }
914  // if found count, assume it's right
915  if(max_count) {
916  ti->count=max_count;
917  } else {
918  // otherwise, use final address
919  ti->count=(adr-ti->start)/ti->bytes;
920  }
921  return 1;
922 }
BufRange* getBufRangeForIndex ( firmware fw,
int  i 
)

Definiert in Zeile 83 der Datei firmware_load_ng.c.

84 {
85  BufRange *br = fw->br;
86  while (br) {
87  if(i >= br->off && i < br->off + br->len) {
88  return br;
89  }
90  br = br->next;
91  }
92  return NULL;
93 }
int insn_match ( cs_insn *  insn,
const insn_match_t match 
)

Definiert in Zeile 1761 der Datei firmware_load_ng.c.

1762 {
1763  // specific instruction ID requested, check
1764  if(match->id != ARM_INS_INVALID && insn->id != match->id) {
1765  return 0;
1766  }
1767  // condition code requested, check
1768  if(match->cc != ARM_CC_INVALID && insn->detail->arm.cc != match->cc) {
1769  return 0;
1770  }
1771  // no op checks, done
1772  if(match->op_count == MATCH_OPCOUNT_IGNORE) {
1773  return 1;
1774  }
1775  // operand count requested, check
1776  if(match->op_count >= 0 && insn->detail->arm.op_count != match->op_count) {
1777  return 0;
1778  }
1779  int i;
1780  // operands
1781  for(i=0;i<MATCH_MAX_OPS && i < insn->detail->arm.op_count; i++) {
1782  // specific type requested?
1783  if(match->operands[i].type != ARM_OP_INVALID && insn->detail->arm.operands[i].type != match->operands[i].type) {
1784  return 0;
1785  }
1786  // specific registers requested?
1787  if(match->operands[i].reg1 != ARM_REG_INVALID) {
1788  if(insn->detail->arm.operands[i].type == ARM_OP_REG) {
1789  if((arm_reg)insn->detail->arm.operands[i].reg != match->operands[i].reg1) {
1790  return 0;
1791  }
1792  } else if(insn->detail->arm.operands[i].type == ARM_OP_MEM) {
1793  if(insn->detail->arm.operands[i].mem.base != match->operands[i].reg1) {
1794  return 0;
1795  }
1796  } else {
1797  fprintf(stderr,"insn_match: reg1 match requested on operand not reg or mem %d\n",
1798  insn->detail->arm.operands[i].type);
1799  }
1800  }
1801  if(match->operands[i].reg2 != ARM_REG_INVALID) {
1802  if(insn->detail->arm.operands[i].type == ARM_OP_MEM) {
1803  if(insn->detail->arm.operands[i].mem.index != match->operands[i].reg2) {
1804  return 0;
1805  }
1806  } else {
1807  fprintf(stderr,"insn_match: reg2 match requested on operand not reg or mem %d\n",
1808  insn->detail->arm.operands[i].type);
1809  }
1810  }
1811  if(match->operands[i].flags & MATCH_OP_FL_IMM) {
1812  if(insn->detail->arm.operands[i].type == ARM_OP_IMM
1813  || insn->detail->arm.operands[i].type == ARM_OP_PIMM
1814  || insn->detail->arm.operands[i].type == ARM_OP_CIMM) {
1815  if(insn->detail->arm.operands[i].imm != match->operands[i].imm) {
1816  return 0;
1817  }
1818  } else if(insn->detail->arm.operands[i].type == ARM_OP_MEM) {
1819  if(insn->detail->arm.operands[i].mem.disp != match->operands[i].imm) {
1820  return 0;
1821  }
1822  } else {
1823  fprintf(stderr,"insn_match: imm match requested on operand not imm or mem %d\n",
1824  insn->detail->arm.operands[i].type);
1825  }
1826  }
1827  if(match->operands[i].flags & MATCH_OP_FL_LAST) {
1828  break;
1829  }
1830  }
1831  return 1;
1832 }
int insn_match_any ( cs_insn *  insn,
const insn_match_t match 
)

Definiert in Zeile 1835 der Datei firmware_load_ng.c.

1836 {
1837  const insn_match_t *m;
1838  // check matches
1839  for(m=match;m->id != ARM_INS_ENDING;m++) {
1840  if(insn_match(insn,m)) {
1841  return 1;
1842  }
1843  }
1844  return 0;
1845 }
int insn_match_find_next ( firmware fw,
iter_state_t is,
int  max_insns,
const insn_match_t match 
)

Definiert in Zeile 1848 der Datei firmware_load_ng.c.

1849 {
1850  int i=0;
1851  while(i < max_insns) {
1852  // disassembly failed, no match (could ignore..)
1853  if(!disasm_iter(fw,is)) {
1854  return 0;
1855  }
1856  // printf("%"PRIx64" insn_match_find_next %s %s\n",is->insn->address,is->insn->mnemonic,is->insn->op_str);
1857  if(insn_match_any(is->insn,match)) {
1858  return 1;
1859  }
1860  i++;
1861  }
1862  // limit hit
1863  return 0;
1864 }
int insn_match_find_next_seq ( firmware fw,
iter_state_t is,
int  max_insns,
const insn_match_t match 
)

Definiert in Zeile 1895 der Datei firmware_load_ng.c.

1896 {
1897  int count=0;
1898  while(count < max_insns) {
1899  const insn_match_t *m=match;
1900  //printf("%"PRIx64" insn_match_find_next_seq %s %s\n",is->insn->address,is->insn->mnemonic,is->insn->op_str);
1901  while(m->id != ARM_INS_ENDING && disasm_iter(fw,is) && insn_match(is->insn,m)) {
1902  m++;
1903  count++;
1904  }
1905  if(m->id == ARM_INS_ENDING) {
1906  return 1;
1907  }
1908  // non-matching
1909  count++;
1910  }
1911  return 0;
1912 }
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 1867 der Datei firmware_load_ng.c.

1868 {
1869  int i=0;
1870  int num_matched=0;
1871  while(i < max_insns) {
1872  // disassembly failed, no match (could ignore..)
1873  if(!disasm_iter(fw,is)) {
1874  return 0;
1875  }
1876  // printf("%"PRIx64" insn_match_find_next %s %s\n",is->insn->address,is->insn->mnemonic,is->insn->op_str);
1877 
1878  const insn_match_t *m;
1879  // check matches
1880  for(m=match;m->id != ARM_INS_ENDING;m++) {
1881  if(insn_match(is->insn,m)) {
1882  num_matched++;
1883  }
1884  }
1885  if(num_matched == num_to_match) {
1886  return 1;
1887  }
1888  i++;
1889  }
1890  // limit hit
1891  return 0;
1892 }
int insn_match_seq ( firmware fw,
iter_state_t is,
const insn_match_t match 
)

Definiert in Zeile 1750 der Datei firmware_load_ng.c.

1751 {
1752  //printf("%"PRIx64" insn_match_seq %s %s\n",is->insn->address,is->insn->mnemonic,is->insn->op_str);
1753  while(match->id != ARM_INS_ENDING && disasm_iter(fw,is) && insn_match(is->insn,match)) {
1754  //printf("%"PRIx64" insn_match_seq next %s %s\n",is->insn->address,is->insn->mnemonic,is->insn->op_str);
1755  match++;
1756  }
1757  return (match->id == ARM_INS_ENDING);
1758 }
int isADD_PC ( cs_insn *  insn)

Definiert in Zeile 534 der Datei firmware_load_ng.c.

535 {
536  return (insn->id == ARM_INS_ADD
537  && insn->detail->arm.op_count == 3
538  && insn->detail->arm.operands[0].reg != ARM_REG_PC
539  && insn->detail->arm.operands[1].type == ARM_OP_REG
540  && insn->detail->arm.operands[1].reg == ARM_REG_PC
541  && insn->detail->arm.operands[2].type == ARM_OP_IMM);
542 }
int isADDW_PC ( cs_insn *  insn)

Definiert in Zeile 522 der Datei firmware_load_ng.c.

523 {
524  return(insn->id == ARM_INS_ADDW
525  && insn->detail->arm.op_count == 3
526  && insn->detail->arm.operands[0].type == ARM_OP_REG
527  && insn->detail->arm.operands[0].reg != ARM_REG_PC
528  && insn->detail->arm.operands[1].type == ARM_OP_REG
529  && insn->detail->arm.operands[1].reg == ARM_REG_PC
530  && insn->detail->arm.operands[2].type == ARM_OP_IMM);
531 }
int isADDx_imm ( cs_insn *  insn)

Definiert in Zeile 638 der Datei firmware_load_ng.c.

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

Definiert in Zeile 649 der Datei firmware_load_ng.c.

650 {
651  return ((insn->id == ARM_INS_ADR)
652  || isSUBW_PC(insn)
653  || isADDW_PC(insn)
654  || (isARM(insn) && (isADD_PC(insn) || isSUB_PC(insn))));
655 }
int isARM ( cs_insn *  insn)

Definiert in Zeile 474 der Datei firmware_load_ng.c.

475 {
476  int i;
477  for(i=0;i<insn->detail->groups_count;i++) {
478  if(insn->detail->groups[i] == ARM_GRP_ARM) {
479  return 1;
480  }
481  }
482  return 0;
483 }
int isASCIIstring ( firmware fw,
uint32_t  adr 
)

Definiert in Zeile 224 der Datei firmware_load_ng.c.

225 {
226  unsigned char *p = (unsigned char*)adr2ptr_with_data(fw, adr);
227  if(!p) {
228  return 0;
229  }
230  // TODO should avoid running off end of dump
231  int i;
232  for (i = 0; (i < 100) && (p[i] != 0); i++)
233  {
234  if (!((p[i] == '\r') || (p[i] == '\n') || (p[i] == '\t') || ((p[i] >= 0x20) && (p[i] <= 0x7f))))
235  {
236  return 0;
237  }
238  }
239  if ((i >= 2) && (p[i] == 0))
240  return 1;
241  return 0;
242 }
int isLDR_PC ( cs_insn *  insn)

Definiert in Zeile 488 der Datei firmware_load_ng.c.

489 {
490  return insn->id == ARM_INS_LDR
491  && insn->detail->arm.op_count == 2
492  && insn->detail->arm.operands[0].type == ARM_OP_REG
493  && insn->detail->arm.operands[1].type == ARM_OP_MEM
494  && insn->detail->arm.operands[1].mem.base == ARM_REG_PC;
495 
496 }
int isLDR_PC_PC ( cs_insn *  insn)

Definiert in Zeile 501 der Datei firmware_load_ng.c.

502 {
503  if(!isLDR_PC(insn)) {
504  return 0;
505  }
506  return (insn->detail->arm.operands[0].reg == ARM_REG_PC);
507 }
int isPOP_LR ( cs_insn *  insn)

Definiert in Zeile 606 der Datei firmware_load_ng.c.

607 {
608  if(insn->id != ARM_INS_POP) {
609  return 0;
610  }
611  int i;
612  for(i=0; i < insn->detail->arm.op_count; i++) {
613  if(insn->detail->arm.operands[i].type == ARM_OP_REG
614  && insn->detail->arm.operands[i].reg == ARM_REG_LR) {
615  return 1;
616  }
617  }
618  return 0;
619 }
int isPOP_PC ( cs_insn *  insn)

Definiert in Zeile 622 der Datei firmware_load_ng.c.

623 {
624  if(insn->id != ARM_INS_POP) {
625  return 0;
626  }
627  int i;
628  for(i=0; i < insn->detail->arm.op_count; i++) {
629  if(insn->detail->arm.operands[i].type == ARM_OP_REG
630  && insn->detail->arm.operands[i].reg == ARM_REG_PC) {
631  return 1;
632  }
633  }
634  return 0;
635 }
int isPUSH_LR ( cs_insn *  insn)

Definiert in Zeile 590 der Datei firmware_load_ng.c.

591 {
592  if(insn->id != ARM_INS_PUSH) {
593  return 0;
594  }
595  int i;
596  for(i=0; i < insn->detail->arm.op_count; i++) {
597  if(insn->detail->arm.operands[i].type == ARM_OP_REG
598  && insn->detail->arm.operands[i].reg == ARM_REG_LR) {
599  return 1;
600  }
601  }
602  return 0;
603 }
int isRETx ( cs_insn *  insn)

Definiert in Zeile 556 der Datei firmware_load_ng.c.

557 {
558  // BX LR
559  if(insn->id == ARM_INS_BX
560  && insn->detail->arm.op_count == 1
561  && insn->detail->arm.operands[0].type == ARM_OP_REG
562  && insn->detail->arm.operands[0].reg == ARM_REG_LR) {
563  return 1;
564  }
565 
566  // TODO LDR pc, [sp], imm is somewhat common, but could also be function pointer call
567 
568  // POP. capstone translates LDMFD SP!,... in arm code to pop
569  if(insn->id == ARM_INS_POP) {
570  int i;
571  for(i=0; i < insn->detail->arm.op_count; i++) {
572  if(insn->detail->arm.operands[i].type == ARM_OP_REG
573  && insn->detail->arm.operands[i].reg == ARM_REG_PC) {
574  return 1;
575  }
576  }
577  }
578  // MOV PC, LR (some tools translate this to RET)
579  if(insn->id == ARM_INS_MOV
580  && insn->detail->arm.operands[0].type == ARM_OP_REG
581  && insn->detail->arm.operands[0].reg == ARM_REG_PC
582  && insn->detail->arm.operands[1].type == ARM_OP_REG
583  && insn->detail->arm.operands[1].reg == ARM_REG_LR) {
584  return 1;
585  }
586  return 0;
587 }
int isSUB_PC ( cs_insn *  insn)

Definiert in Zeile 545 der Datei firmware_load_ng.c.

546 {
547  return (insn->id == ARM_INS_SUB
548  && insn->detail->arm.op_count == 3
549  && insn->detail->arm.operands[0].reg != ARM_REG_PC
550  && insn->detail->arm.operands[1].type == ARM_OP_REG
551  && insn->detail->arm.operands[1].reg == ARM_REG_PC
552  && insn->detail->arm.operands[2].type == ARM_OP_IMM);
553 }
int isSUBW_PC ( cs_insn *  insn)

Definiert in Zeile 510 der Datei firmware_load_ng.c.

511 {
512  return(insn->id == ARM_INS_SUBW
513  && insn->detail->arm.op_count == 3
514  && insn->detail->arm.operands[0].type == ARM_OP_REG
515  && insn->detail->arm.operands[0].reg != ARM_REG_PC
516  && insn->detail->arm.operands[1].type == ARM_OP_REG
517  && insn->detail->arm.operands[1].reg == ARM_REG_PC
518  && insn->detail->arm.operands[2].type == ARM_OP_IMM);
519 }
int isSUBx_imm ( cs_insn *  insn)

Definiert in Zeile 643 der Datei firmware_load_ng.c.

644 {
645  return (IS_INSN_ID_SUBx(insn->id) && insn->detail->arm.operands[1].type == ARM_OP_IMM);
646 }
uint32_t LDR_PC2adr ( __attribute__((unused)) firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 692 der Datei firmware_load_ng.c.

693 {
694  if(!isLDR_PC(insn)) {
695  return 0;
696  }
697  if(isARM(insn)) {
698  return insn->address+8+insn->detail->arm.operands[1].mem.disp;
699  } else {
700  return (insn->address&~3)+4+insn->detail->arm.operands[1].mem.disp;
701  }
702 }
uint32_t LDR_PC2val ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 751 der Datei firmware_load_ng.c.

752 {
753  uint32_t *p=LDR_PC2valptr(fw,insn);
754  if(p) {
755  return *p;
756  }
757  return 0;
758 }
uint32_t* LDR_PC2valptr ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 682 der Datei firmware_load_ng.c.

683 {
684  if(isARM(insn)) {
685  return LDR_PC2valptr_arm(fw,insn);
686  } else {
687  return LDR_PC2valptr_thumb(fw,insn);
688  }
689 }
uint32_t* LDR_PC2valptr_arm ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 670 der Datei firmware_load_ng.c.

671 {
672  if(!isLDR_PC(insn)) {
673  return NULL;
674  }
675  uint32_t adr;
676  // TODO NOTE doesn't do anything with scale (which can supposedly be neg?),
677  // appears correct for examples seen so far
678  adr=insn->address+8+insn->detail->arm.operands[1].mem.disp;
679  return (uint32_t *)adr2ptr(fw,adr);
680 }
uint32_t* LDR_PC2valptr_thumb ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 658 der Datei firmware_load_ng.c.

659 {
660  if(!isLDR_PC(insn)) {
661  return NULL;
662  }
663  uint32_t adr;
664  // TODO NOTE doesn't do anything with scale (which can supposedly be neg?),
665  // appears correct for examples seen so far
666  adr=(insn->address&~3)+4+insn->detail->arm.operands[1].mem.disp;
667  return (uint32_t *)adr2ptr(fw,adr);
668 }
uint32_t LDR_PC_PC_target ( firmware fw,
cs_insn *  insn 
)

Definiert in Zeile 761 der Datei firmware_load_ng.c.

762 {
763  if(!isLDR_PC_PC(insn)) {
764  return 0;
765  }
766  return LDR_PC2val(fw,insn);
767 }
uint32_t ptr2adr ( firmware fw,
uint8_t *  ptr 
)

Definiert in Zeile 268 der Datei firmware_load_ng.c.

269 {
270  // TODO handle copied, or maybe another func to convert?
271  return (ptr-fw->buf8)+fw->base;
272 }
int search_calls_multi_end ( __attribute__((unused)) firmware fw,
__attribute__((unused)) iter_state_t is,
__attribute__((unused)) uint32_t  adr 
)

Definiert in Zeile 1232 der Datei firmware_load_ng.c.

1232  {
1233  return 1;
1234 }
uint32_t search_disasm_calls ( firmware fw,
iter_state_t is,
uint32_t  val,
__attribute__((unused)) void *  unused 
)

Definiert in Zeile 1219 der Datei firmware_load_ng.c.

1220 {
1221  //printf("%"PRIx64" %s %s\n",is->insn->address,is->insn->mnemonic, is->insn->op_str);
1223  if(sub) {
1224  if(sub == val) {
1225  return 1;
1226  }
1227  }
1228  return 0;
1229 }
uint32_t search_disasm_calls_multi ( firmware fw,
iter_state_t is,
__attribute__((unused)) uint32_t  unused,
void *  userdata 
)

Definiert in Zeile 1240 der Datei firmware_load_ng.c.

1241 {
1244  if(sub) {
1245  while(data->adr) {
1246  if(data->adr == sub) {
1247  return data->fn(fw,is,sub);
1248  }
1249  data++;
1250  }
1251  }
1252  return 0;
1253 }
uint32_t search_disasm_const_ref ( firmware fw,
iter_state_t is,
uint32_t  val,
__attribute__((unused)) void *  unused 
)

Definiert in Zeile 1170 der Datei firmware_load_ng.c.

1171 {
1172 // printf("%"PRIx64" %s %s\n",is->insn->address,is->insn->mnemonic, is->insn->op_str);
1173  uint32_t av=ADRx2adr(fw,is->insn);
1174  if(av) {
1175 // printf("adr 0x%08x\n",av);
1176  if(av == val) {
1177  return (uint32_t)is->insn->address;
1178  }
1179  return 0;
1180  }
1181  uint32_t *pv=LDR_PC2valptr(fw,is->insn);
1182  if(pv) {
1183 // printf("ldr 0x%08x\n",*pv);
1184  if(*pv == val) {
1185  return (uint32_t)is->insn->address;
1186  }
1187  }
1188  return 0;
1189 }
uint32_t search_disasm_str_ref ( firmware fw,
iter_state_t is,
__attribute__((unused)) uint32_t  val,
void *  udata 
)

Definiert in Zeile 1192 der Datei firmware_load_ng.c.

1193 {
1194  const char *str=(const char *)udata;
1195 // printf("%"PRIx64" %s %s\n",is->insn->address,is->insn->mnemonic, is->insn->op_str);
1196  uint32_t av=ADRx2adr(fw,is->insn);
1197  if(av) {
1198 // printf("adr 0x%08x\n",av);
1199  char *cmp=(char *)adr2ptr_with_data(fw,av);
1200  if(cmp && (strcmp(cmp,str) == 0)) {
1201  return (uint32_t)is->insn->address;
1202  }
1203  return 0;
1204  }
1205  uint32_t *pv=LDR_PC2valptr(fw,is->insn);
1206  if(pv) {
1207 // printf("ldr 0x%08x\n",*pv);
1208  char *cmp=(char *)adr2ptr_with_data(fw,*pv);
1209  if(cmp && (strcmp(cmp,str) == 0)) {
1210  return (uint32_t)is->insn->address;
1211  }
1212  }
1213  return 0;
1214 }

Variablen-Dokumentation

const insn_match_t match_b[]
Initialisierung:
={
{ARM_INS_ENDING}
}

Definiert in Zeile 1712 der Datei firmware_load_ng.c.

const insn_match_t match_b_bl[]
Initialisierung:
={
{ARM_INS_ENDING}
}

Definiert in Zeile 1720 der Datei firmware_load_ng.c.

const insn_match_t match_b_bl_blximm[]
Initialisierung:
={
{ARM_INS_ENDING}
}

Definiert in Zeile 1726 der Datei firmware_load_ng.c.

const insn_match_t match_bl[]
Initialisierung:
={
{ARM_INS_ENDING}
}

Definiert in Zeile 1716 der Datei firmware_load_ng.c.

const insn_match_t match_bl_blximm[]
Initialisierung:
={
{ARM_INS_ENDING}
}

Definiert in Zeile 1733 der Datei firmware_load_ng.c.

const insn_match_t match_bxlr[]
Initialisierung:
={
{MATCH_INS(BX, 1), {MATCH_OP_REG(LR)}},
{ARM_INS_ENDING}
}

Definiert in Zeile 1739 der Datei firmware_load_ng.c.

const insn_match_t match_ldr_pc[]
Initialisierung:
={
{ARM_INS_ENDING}
}

Definiert in Zeile 1744 der Datei firmware_load_ng.c.