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

gehe zum Quellcode dieser Datei

Datenstrukturen

struct  lnode
 
struct  llist
 

Makrodefinitionen

#define ADDR_HASH_BITS   20
 
#define ADDR_HASH_BUCKETS   (1<<ADDR_HASH_BITS)
 
#define ADDR_HASH_MASK   (ADDR_HASH_BUCKETS-1)
 
#define ADDR_HASH(addr)   (((unsigned)(addr) >> 2) & ADDR_HASH_MASK)
 
#define COMMENT_LEN   255
 
#define DIS_OPT_LABELS   0x00000001
 
#define DIS_OPT_SUBS   0x00000002
 
#define DIS_OPT_CONSTS   0x00000004
 
#define DIS_OPT_FMT_CHDK   0x00000008
 
#define DIS_OPT_FMT_OBJDUMP   0x00000010
 
#define DIS_OPT_ADR_LDR   0x00000020
 
#define DIS_OPT_STR   0x00000040
 
#define DIS_OPT_STUBS   0x00000080
 
#define DIS_OPT_STUBS_LABEL   0x00000100
 
#define DIS_OPT_PROPS   0x00000200
 
#define DIS_OPT_JMP_BACK   0x00000400
 
#define DIS_OPT_END_RET   0x00000800
 
#define DIS_OPT_SIMPLE_FUNCS   0x00001000
 
#define DIS_OPT_DETAIL_GROUP   0x00010000
 
#define DIS_OPT_DETAIL_OP   0x00020000
 
#define DIS_OPT_DETAIL_ADDR   0x00040000
 
#define DIS_OPT_DETAIL_BIN   0x00080000
 
#define DIS_OPT_DETAIL_CONST   0x00100000
 
#define DIS_OPT_DETAIL_ALL
 

Typdefinitionen

typedef unsigned int t_address
 
typedef unsigned int t_value
 

Funktionen

struct llistnew_list ()
 
void free_list (struct llist *lst)
 
struct lnodenew_node (t_address address, t_value data)
 
struct lnodel_search (struct llist *ls, t_address address)
 
int l_insert (struct llist *ls, t_address address, t_value data)
 
void l_remove (struct llist *ls, t_address addr)
 
struct llist ** addr_hash_new ()
 
void addr_hash_free (struct llist **addr_hash)
 
struct lnodeaddr_hash_get (struct llist **addr_hash, t_address addr)
 
void addr_hash_add (struct llist **addr_hash, t_address addr)
 
void usage (void)
 
static const char * arm_op_type_name (int op_type)
 
static void describe_insn_ops (csh handle, cs_insn *insn)
 
static void describe_insn_groups (csh handle, cs_insn *insn)
 
static void describe_str (firmware *fw, char *comment, uint32_t adr)
 
void describe_const_op (firmware *fw, unsigned dis_opts, char *comment, uint32_t adr)
 
void describe_prop_call (firmware *fw, iter_state_t *is, unsigned dis_opts, char *comment, uint32_t target)
 
void describe_simple_func (firmware *fw, unsigned dis_opts, char *comment, uint32_t target)
 
int do_dis_branch (firmware *fw, iter_state_t *is, unsigned dis_opts, char *ops, char *comment)
 
int do_dis_call (firmware *fw, iter_state_t *is, unsigned dis_opts, char *ops, char *comment)
 
static void do_dis_insn (firmware *fw, iter_state_t *is, unsigned dis_opts, char *mnem, char *ops, char *comment, tbx_info_t *ti)
 
void do_adr_label (firmware *fw, struct llist **branch_list, iter_state_t *is, unsigned dis_opts)
 
static void do_tbb_data (firmware *fw, iter_state_t *is, unsigned dis_opts, tbx_info_t *ti)
 
static void do_tbh_data (firmware *fw, iter_state_t *is, unsigned dis_opts, tbx_info_t *ti)
 
static void do_tbx_pass1 (firmware *fw, iter_state_t *is, struct llist **branch_list, unsigned dis_opts, tbx_info_t *ti)
 
static void do_tbx_data (firmware *fw, iter_state_t *is, unsigned dis_opts, tbx_info_t *ti)
 
static void do_dis_range (firmware *fw, unsigned dis_start, unsigned dis_count, unsigned dis_end, unsigned dis_end_ret_count, unsigned dis_opts)
 
int main (int argc, char **argv)
 

Variablen

static t_address set_prop
 
static t_address get_prop
 
const char * comment_start = ";"
 

Makro-Dokumentation

#define ADDR_HASH (   addr)    (((unsigned)(addr) >> 2) & ADDR_HASH_MASK)

Definiert in Zeile 145 der Datei capdis.c.

#define ADDR_HASH_BITS   20

Definiert in Zeile 142 der Datei capdis.c.

#define ADDR_HASH_BUCKETS   (1<<ADDR_HASH_BITS)

Definiert in Zeile 143 der Datei capdis.c.

#define ADDR_HASH_MASK   (ADDR_HASH_BUCKETS-1)

Definiert in Zeile 144 der Datei capdis.c.

#define COMMENT_LEN   255

Definiert in Zeile 293 der Datei capdis.c.

#define DIS_OPT_ADR_LDR   0x00000020

Definiert in Zeile 375 der Datei capdis.c.

#define DIS_OPT_CONSTS   0x00000004

Definiert in Zeile 372 der Datei capdis.c.

#define DIS_OPT_DETAIL_ADDR   0x00040000

Definiert in Zeile 386 der Datei capdis.c.

#define DIS_OPT_DETAIL_ALL
#define DIS_OPT_DETAIL_BIN   0x00080000

Definiert in Zeile 387 der Datei capdis.c.

#define DIS_OPT_DETAIL_CONST   0x00100000

Definiert in Zeile 388 der Datei capdis.c.

#define DIS_OPT_DETAIL_GROUP   0x00010000

Definiert in Zeile 384 der Datei capdis.c.

#define DIS_OPT_DETAIL_OP   0x00020000

Definiert in Zeile 385 der Datei capdis.c.

#define DIS_OPT_END_RET   0x00000800

Definiert in Zeile 381 der Datei capdis.c.

#define DIS_OPT_FMT_CHDK   0x00000008

Definiert in Zeile 373 der Datei capdis.c.

#define DIS_OPT_FMT_OBJDUMP   0x00000010

Definiert in Zeile 374 der Datei capdis.c.

#define DIS_OPT_JMP_BACK   0x00000400

Definiert in Zeile 380 der Datei capdis.c.

#define DIS_OPT_LABELS   0x00000001

Definiert in Zeile 370 der Datei capdis.c.

#define DIS_OPT_PROPS   0x00000200

Definiert in Zeile 379 der Datei capdis.c.

#define DIS_OPT_SIMPLE_FUNCS   0x00001000

Definiert in Zeile 382 der Datei capdis.c.

#define DIS_OPT_STR   0x00000040

Definiert in Zeile 376 der Datei capdis.c.

#define DIS_OPT_STUBS   0x00000080

Definiert in Zeile 377 der Datei capdis.c.

#define DIS_OPT_STUBS_LABEL   0x00000100

Definiert in Zeile 378 der Datei capdis.c.

#define DIS_OPT_SUBS   0x00000002

Definiert in Zeile 371 der Datei capdis.c.

Dokumentation der benutzerdefinierten Typen

typedef unsigned int t_address

Definiert in Zeile 14 der Datei capdis.c.

typedef unsigned int t_value

Definiert in Zeile 15 der Datei capdis.c.

Dokumentation der Funktionen

void addr_hash_add ( struct llist **  addr_hash,
t_address  addr 
)

Definiert in Zeile 173 der Datei capdis.c.

173  {
174  unsigned key = ADDR_HASH(addr);
175  if(!addr_hash[key]) {
176  addr_hash[key] = new_list();
177  }
178  l_insert(addr_hash[key],addr,0);
179 }
void addr_hash_free ( struct llist **  addr_hash)

Definiert in Zeile 156 der Datei capdis.c.

156  {
157  int i;
158  for(i=0;i<ADDR_HASH_BUCKETS; i++) {
159  if(addr_hash[i]) {
160  free_list(addr_hash[i]);
161  }
162  }
163  free(addr_hash);
164 }
struct lnode* addr_hash_get ( struct llist **  addr_hash,
t_address  addr 
)

Definiert in Zeile 165 der Datei capdis.c.

165  {
166  unsigned key = ADDR_HASH(addr);
167  if(!addr_hash[key]) {
168  return NULL;
169  }
170  return l_search(addr_hash[key],addr);
171 }
struct llist** addr_hash_new ( )

Definiert in Zeile 146 der Datei capdis.c.

146  {
147  struct llist **addr_hash = malloc(ADDR_HASH_BUCKETS*sizeof(struct llist *));
148  if(!addr_hash) {
149  fprintf(stderr,"addr_hash_now: malloc failed\n");
150  exit(1);
151  }
152  memset(addr_hash,0,ADDR_HASH_BUCKETS*sizeof(struct llist *));
153  return addr_hash;
154 }
static const char* arm_op_type_name ( int  op_type)
static

Definiert in Zeile 219 der Datei capdis.c.

219  {
220  switch(op_type) {
221  case ARM_OP_INVALID:
222  return "invalid";
223  case ARM_OP_REG:
224  return "reg";
225  case ARM_OP_IMM:
226  return "imm";
227  case ARM_OP_MEM:
228  return "mem";
229  case ARM_OP_FP:
230  return "fp";
231  case ARM_OP_CIMM:
232  return "cimm";
233  case ARM_OP_PIMM:
234  return "pimm";
235  case ARM_OP_SETEND:
236  return "setend";
237  case ARM_OP_SYSREG:
238  return "sysreg";
239  }
240  return "unk";
241 }
void describe_const_op ( firmware fw,
unsigned  dis_opts,
char *  comment,
uint32_t  adr 
)

Definiert in Zeile 396 der Datei capdis.c.

397 {
398  osig* ostub=NULL;
399  if(dis_opts & DIS_OPT_STUBS) {
400  ostub = find_sig_val(fw->sv->stubs,adr);
401  if(!ostub) {
402  uint32_t *p=(uint32_t *)adr2ptr(fw,adr);
403  if(p) {
404  ostub = find_sig_val(fw->sv->stubs,*p);
405  }
406  }
407  // found, and not null
408  if(ostub && ostub->val) {
409  // TODO overflow
410  strcat(comment," ");
411  strcat(comment,ostub->nm);
412  // don't bother trying to comment as string
413  return;
414  }
415  }
416  if(dis_opts & DIS_OPT_STR) {
417  describe_str(fw,comment,adr);
418  }
419 }
static void describe_insn_groups ( csh  handle,
cs_insn *  insn 
)
static

Definiert in Zeile 281 der Datei capdis.c.

281  {
282  int i;
283  printf("%s GROUPS %d:",comment_start,insn->detail->groups_count);
284  for(i=0;i<insn->detail->groups_count;i++) {
285  if(i>0) {
286  printf(",");
287  }
288  printf("%s",cs_group_name(handle,insn->detail->groups[i]));
289  }
290  printf("\n");
291 }
static void describe_insn_ops ( csh  handle,
cs_insn *  insn 
)
static

Definiert in Zeile 245 der Datei capdis.c.

245  {
246  printf("%s OPERANDS %d:\n",comment_start,insn->detail->arm.op_count);
247  int i;
248  for(i=0;i<insn->detail->arm.op_count;i++) {
249  printf("%s %d: %s",comment_start,i,arm_op_type_name(insn->detail->arm.operands[i].type));
250  switch(insn->detail->arm.operands[i].type) {
251  case ARM_OP_IMM:
252  case ARM_OP_PIMM:
253  case ARM_OP_CIMM:
254  printf("=0x%x",insn->detail->arm.operands[i].imm);
255  break;
256  case ARM_OP_MEM: {
257  const char *reg=cs_reg_name(handle,insn->detail->arm.operands[i].mem.base);
258  if(reg) {
259  printf(" base=%s",reg);
260  }
261  reg=cs_reg_name(handle,insn->detail->arm.operands[i].mem.index);
262  if(reg) {
263  printf(" index=%s",reg);
264  }
265  if(insn->detail->arm.operands[i].mem.disp) {
266  printf(" scale=%d disp=0x%08x",
267  insn->detail->arm.operands[i].mem.scale,
268  insn->detail->arm.operands[i].mem.disp);
269  }
270  break;
271  }
272  case ARM_OP_REG:
273  printf(" %s",cs_reg_name(handle,insn->detail->arm.operands[i].reg));
274  break;
275  default:
276  break;
277  }
278  printf("\n");
279  }
280 }
void describe_prop_call ( firmware fw,
iter_state_t is,
unsigned  dis_opts,
char *  comment,
uint32_t  target 
)

Definiert in Zeile 421 der Datei capdis.c.

422 {
423  if(!(dis_opts & DIS_OPT_PROPS) || (target != get_prop && target != set_prop)) {
424  return;
425  }
426 
427  uint32_t regs[4];
428  // backtrack up to 6 instructions, looking for r0 (propcase ID)
429  if((get_call_const_args(fw,is,6,regs)&1)!=1) {
430  return;
431  }
432  osig* ostub = find_sig_val(fw->sv->propcases,regs[0]);
433  if(ostub && ostub->val) {
434  sprintf(comment+strlen(comment)," %s (%d)",ostub->nm,ostub->val);
435  } else {
436  sprintf(comment+strlen(comment)," (%d)",regs[0]); // print number on propcase call line for easier searching
437  }
438 }
void describe_simple_func ( firmware fw,
unsigned  dis_opts,
char *  comment,
uint32_t  target 
)

Definiert in Zeile 440 der Datei capdis.c.

441 {
442  if(!(dis_opts & DIS_OPT_SIMPLE_FUNCS)) {
443  return;
444  }
445  simple_func_desc_t info;
446  if(!check_simple_func(fw, target, MATCH_SIMPLE_FUNC_ANY, &info)) {
447  return;
448  }
449  if(info.ftype == MATCH_SIMPLE_FUNC_NULLSUB) {
450  strcat(comment," return");
451  } else if (info.ftype == MATCH_SIMPLE_FUNC_IMM) {
452  sprintf(comment+strlen(comment)," return %#x",info.retval);
453  }
454 }
static void describe_str ( firmware fw,
char *  comment,
uint32_t  adr 
)
static

Definiert in Zeile 298 der Datei capdis.c.

299 {
300  int plevel=1;
301  char *s=(char *)adr2ptr_with_data(fw,adr);
302  if(!s) {
303  //printf("s1 bad ptr 0x%08x\n",adr);
304  return;
305  }
306  if(!isASCIIstring(fw,adr)) {
307  //printf("s1 not ASCII 0x%08x\n",adr);
308  // not a string, check for valid pointer
309  uint32_t adr2=*(uint32_t *)s;
310  //
311  s=(char *)adr2ptr_with_data(fw,adr2);
312  if(!s) {
313  //printf("s2 bad ptr 0x%08x\n",adr2);
314  return;
315  }
316  if(!isASCIIstring(fw,adr2)) {
317  //printf("s2 not ASCII 0x%08x\n",adr2);
318  return;
319  }
320  plevel++;
321  }
322  int l=strlen(comment);
323  // remaining space
324  // TODO might want to limit max string to a modest number of chars
325  int r=COMMENT_LEN - (l + 4 + plevel); // 4 for space, "" and possibly one inserted backslash
326  if(r < 1) {
327  return;
328  }
329  char *p=comment+l;
330  *p++=' ';
331  int i;
332  for(i=0;i<plevel;i++) {
333  *p++='*';
334  }
335  *p++='"';
336  char *e;
337  int trunc=0;
338  if((int)strlen(s) < r) {
339  e=p+strlen(s);
340  } else {
341  // not enough space for ellipsis, give up
342  if(r <= 3) {
343  *p++='"';
344  *p++=0;
345  return;
346  }
347  e=p+r - 3;
348  trunc=1;
349  }
350  while(p < e) {
351  if(*s == '\r') {
352  *p++='\\';
353  *p++='r';
354  } else if(*s == '\n') {
355  *p++='\\';
356  *p++='n';
357  } else {
358  *p++=*s;
359  }
360  s++;
361  }
362  if(trunc) {
363  strcpy(p,"...");
364  p+=3;
365  }
366  *p++='"';
367  *p++=0;
368 }
void do_adr_label ( firmware fw,
struct llist **  branch_list,
iter_state_t is,
unsigned  dis_opts 
)

Definiert in Zeile 663 der Datei capdis.c.

664 {
665 
666  uint32_t adr=is->insn->address;
667  osig* ostub = NULL;
668 
669  if(dis_opts & DIS_OPT_STUBS_LABEL) {
670  // assume stub was recorded with same thumb state we are disassembling
671  ostub = find_sig_val(fw->sv->stubs,adr|is->thumb);
672  // TODO just comment for now
673  if(ostub) {
674  printf("%s %s 0x%08x\n",comment_start,ostub->nm,ostub->val);
675  }
676  }
677  if(dis_opts & DIS_OPT_LABELS) {
678  struct lnode *label = addr_hash_get(branch_list,adr);
679  if(label) {
680  if(dis_opts & DIS_OPT_FMT_CHDK) {
681  printf("\"");
682  }
683  printf("loc_%08x:", label->address);
684  if(dis_opts & DIS_OPT_FMT_CHDK) {
685  printf("\\n\"");
686  }
687  printf("\n");
688  }
689  }
690 }
int do_dis_branch ( firmware fw,
iter_state_t is,
unsigned  dis_opts,
char *  ops,
char *  comment 
)

Definiert in Zeile 458 der Datei capdis.c.

459 {
460  uint32_t target = B_target(fw,is->insn);
461  char op_pfx[8]="";
462  if(!target) {
463  target = CBx_target(fw,is->insn);
464  if(!target) {
465  return 0;
466  }
467  sprintf(op_pfx,"%s, ",cs_reg_name(is->cs_handle,is->insn->detail->arm.operands[0].reg));
468  }
469  osig* ostub=NULL;
470  char *subname=NULL;
471  uint32_t j_target=0;
472  if(dis_opts & DIS_OPT_STUBS) {
473  // search for current thumb state (there is no BX imm, don't currently handle ldr pc,...)
474  ostub = find_sig_val(fw->sv->stubs,target|is->thumb);
475  if(ostub) {
476  if(ostub->is_comment) {
477  strcat(comment,ostub->nm);
478  } else {
479  subname=ostub->nm;
480  }
481  } else {
482  // check for veneer to known function
483  if(fw_disasm_iter_single(fw,target|is->thumb)) {
484  j_target=get_direct_jump_target(fw,fw->is);
485  if(j_target) {
486  ostub = find_sig_val(fw->sv->stubs,j_target);
487  if(ostub) {
488  strcat(comment,"-> ");
489  strcat(comment,ostub->nm);
490  }
491  }
492  }
493  }
494  }
495  if(dis_opts & DIS_OPT_LABELS) {
496  if(subname) {
497  if(dis_opts & DIS_OPT_FMT_CHDK) {
498  sprintf(ops,"%s_%s",op_pfx,subname);
499  } else {
500  sprintf(ops,"%s%s",op_pfx,subname);
501  }
502  } else {
503  sprintf(ops,"%sloc_%08x",op_pfx,target);
504  }
505  } else if (subname) {
506  strcat(comment,subname);
507  }
508  uint32_t desc_adr = (j_target)?j_target:target;
509  describe_prop_call(fw,is,dis_opts,comment,desc_adr | is->thumb);
510  describe_simple_func(fw,dis_opts,comment,desc_adr | is->thumb);
511  return 1;
512 }
int do_dis_call ( firmware fw,
iter_state_t is,
unsigned  dis_opts,
char *  ops,
char *  comment 
)

Definiert in Zeile 515 der Datei capdis.c.

516 {
517  if(!((is->insn->id == ARM_INS_BL || is->insn->id == ARM_INS_BLX)
518  && is->insn->detail->arm.operands[0].type == ARM_OP_IMM)) {
519  return 0;
520  }
521 
522  uint32_t target = get_branch_call_insn_target(fw,is); // target with thumb bit set appropriately
523  osig* ostub=NULL;
524  char *subname=NULL;
525  uint32_t j_target=0;
526  if(dis_opts & DIS_OPT_STUBS) {
527  ostub = find_sig_val(fw->sv->stubs,target);
528  if(ostub) {
529  if(ostub->is_comment) {
530  strcat(comment,ostub->nm);
531  } else {
532  subname=ostub->nm;
533  }
534  } else {
535  // check for veneer to known function
536  if(fw_disasm_iter_single(fw,target)) {
537  j_target=get_direct_jump_target(fw,fw->is);
538  if(j_target) {
539  ostub = find_sig_val(fw->sv->stubs,j_target);
540  if(ostub) {
541  // TODO could translate directly into sub call, but need to resolve BL vs BLX
542  strcat(comment,"-> ");
543  strcat(comment,ostub->nm);
544  }
545  }
546  }
547  }
548  }
549  if(dis_opts & DIS_OPT_SUBS) {
550  if(subname) {
551  if(dis_opts & DIS_OPT_FMT_CHDK) {
552  sprintf(ops,"_%s",subname);
553  } else {
554  strcpy(ops,subname);
555  }
556  } else {
557  sprintf(ops,"sub_%08x",ADR_CLEAR_THUMB(target));
558  }
559  } else if (subname) {
560  strcat(comment,subname);
561  }
562  uint32_t desc_adr = (j_target)?j_target:target;
563  describe_prop_call(fw,is,dis_opts,comment,desc_adr);
564  describe_simple_func(fw,dis_opts,comment,desc_adr);
565  return 1;
566 }
static void do_dis_insn ( firmware fw,
iter_state_t is,
unsigned  dis_opts,
char *  mnem,
char *  ops,
char *  comment,
tbx_info_t ti 
)
static

Definiert in Zeile 568 der Datei capdis.c.

575  {
576 
577  cs_insn *insn=is->insn;
578 
579  // default - use capstone disasm text as-is
580  strcpy(mnem,insn->mnemonic);
581  strcpy(ops,insn->op_str);
582  comment[0]=0;
583  // handle special cases, naming etc
584  if(do_dis_branch(fw,is,dis_opts,ops,comment)) {
585  return;
586  }
587  if(do_dis_call(fw,is,dis_opts,ops,comment)) {
588  return;
589  }
590  if((dis_opts & (DIS_OPT_CONSTS|DIS_OPT_DETAIL_CONST)) && isLDR_PC(insn)) {
591  // get address for display, rather than LDR_PC2valptr directly
592  uint32_t ad=LDR_PC2adr(fw,insn);
593  uint32_t *pv=(uint32_t *)adr2ptr(fw,ad);
594  // don't handle neg scale for now, make sure not out of bounds
595  if(pv) {
596  if(dis_opts & DIS_OPT_CONSTS) {
597  sprintf(ops,"%s, =0x%08x",
598  cs_reg_name(is->cs_handle,insn->detail->arm.operands[0].reg),
599  *pv);
600  if(dis_opts & DIS_OPT_DETAIL_CONST) {
601  // show pc + and calculated addr
602  sprintf(comment,"[pc, #%d] (0x%08x)",insn->detail->arm.operands[1].mem.disp,ad);
603  }
604  } else if(dis_opts & DIS_OPT_DETAIL_CONST) {
605  // thumb2dis.pl style
606  sprintf(comment,"0x%08x: (%08x)",ad,*pv);
607  }
608  describe_const_op(fw,dis_opts,comment,ad);
609  } else {
610  sprintf(comment,"WARNING didn't convert PC rel to constant!");
611  }
612  } else if((dis_opts & (DIS_OPT_CONSTS|DIS_OPT_DETAIL_CONST)) && isADRx(insn)) {
613  unsigned ad=ADRx2adr(fw,insn);
614  uint32_t *pv=(uint32_t *)adr2ptr(fw,ad);
615  if(pv) {
616  if(dis_opts & DIS_OPT_ADR_LDR) {
617  strcpy(mnem,"ldr");
618  sprintf(ops,"%s, =0x%08x",
619  cs_reg_name(is->cs_handle,insn->detail->arm.operands[0].reg),
620  ad);
621  if(dis_opts & DIS_OPT_DETAIL_CONST) {
622  // show original op
623  if(insn->id == ARM_INS_ADR) {
624  sprintf(comment,"adr %s, #%x (0x%08x)",
625  cs_reg_name(is->cs_handle,insn->detail->arm.operands[0].reg),
626  insn->detail->arm.operands[1].imm,
627  *pv);
628  } else {
629  sprintf(comment,"%s %s, pc, #%x (0x%08x)",
630  insn->mnemonic,
631  cs_reg_name(is->cs_handle,insn->detail->arm.operands[0].reg),
632  insn->detail->arm.operands[2].imm,
633  *pv);
634  }
635  }
636  } else {
637  if(insn->id == ARM_INS_ADR) {
638  if(dis_opts & DIS_OPT_FMT_OBJDUMP) {
639  strcpy(mnem,"add");
640  sprintf(ops,"%s, pc, #%d",
641  cs_reg_name(is->cs_handle,insn->detail->arm.operands[0].reg),
642  insn->detail->arm.operands[1].imm);
643  } // else keep as adr
644  }
645  if(dis_opts & DIS_OPT_DETAIL_CONST) {
646  // thumb2dis.pl style
647  sprintf(comment,"0x%08x: (%08x)",ad,*pv);
648  }
649  }
650  describe_const_op(fw,dis_opts,comment,ad);
651  } else {
652  sprintf(comment,"WARNING didn't convert ADR/ADD/SUB Rd, PC, #x to constant!");
653  }
654  } else if(get_TBx_PC_info(fw,is,ti)) {
655  sprintf(comment+strlen(comment),
656  "(jumptable r%d %d elements)",
657  insn->detail->arm.operands[0].mem.index - ARM_REG_R0,
658  ti->count);
659  }
660  // else ... default disassembly
661 }
static void do_dis_range ( firmware fw,
unsigned  dis_start,
unsigned  dis_count,
unsigned  dis_end,
unsigned  dis_end_ret_count,
unsigned  dis_opts 
)
static

Definiert in Zeile 844 der Datei capdis.c.

850 {
851  iter_state_t *is=disasm_iter_new(fw,dis_start);
852  size_t count=0;
853  struct llist **branch_list = addr_hash_new();
854  tbx_info_t ti;
855 
856  // pre-scan for branches
857  if(dis_opts & DIS_OPT_LABELS) {
858  // TODO should use fw_search_insn, but doesn't easily support count
859  while(count < dis_count && is->adr < dis_end) {
860  if(disasm_iter(fw,is)) {
862  if(b_tgt) {
863  // currently ignore thumb bit
864  addr_hash_add(branch_list,ADR_CLEAR_THUMB(b_tgt));
865  } else if(get_TBx_PC_info(fw,is,&ti)) {
866  // handle tbx, so instruction counts will match,
867  // less chance of spurious stuff from disassembling jumptable data
868  do_tbx_pass1(fw,is,branch_list,dis_opts,&ti);
869  }
870  } else {
871  if(!disasm_iter_init(fw,is,(is->adr+is->insn_min_size) | is->thumb)) {
872  fprintf(stderr,"do_dis_range: disasm_iter_init failed\n");
873  break;
874  }
875  }
876  count++;
877  }
878  }
879  count=0;
880  disasm_iter_init(fw,is,dis_start);
881  while(count < dis_count && is->adr < dis_end) {
882  if(disasm_iter(fw,is)) {
883  do_adr_label(fw,branch_list,is,dis_opts);
884  if(!(dis_opts & DIS_OPT_FMT_OBJDUMP) // objdump format puts these on same line as instruction
885  && (dis_opts & (DIS_OPT_DETAIL_ADDR | DIS_OPT_DETAIL_BIN))) {
886  printf("%s",comment_start);
887  if(dis_opts & DIS_OPT_DETAIL_ADDR) {
888  printf(" 0x%"PRIx64"",is->insn->address);
889  }
890  if(dis_opts & DIS_OPT_DETAIL_BIN) {
891  int k;
892  for(k=0;k<is->insn->size;k++) {
893  printf(" %02x",is->insn->bytes[k]);
894  }
895  }
896  printf("\n");
897  }
898  if(dis_opts & DIS_OPT_DETAIL_OP) {
900  }
901  if(dis_opts & DIS_OPT_DETAIL_GROUP) {
903  }
904  // mnemonic and op size from capstone.h
905  char insn_mnemonic[32], insn_ops[160], comment[COMMENT_LEN+1];
906  ti.start=0; // flag so we can do jump table dump below
907  do_dis_insn(fw,is,dis_opts,insn_mnemonic,insn_ops,comment,&ti);
908  if(dis_opts & DIS_OPT_FMT_CHDK) {
909  printf("\"");
910  }
911 /*
912 objdump / thumb2dis format examples
913 fc000016: \tf8df d004 \tldr.w\tsp, [pc, #4]\t; 0xfc00001c: (1ffffffc)
914 fc000020: \tbf00 \tnop
915 
916 TODO most constants are decimal, while capstone defaults to hex
917 */
918 
919  if(dis_opts & DIS_OPT_FMT_OBJDUMP) {// objdump format puts these on same line as instruction
920  if(dis_opts & DIS_OPT_DETAIL_ADDR) {
921  printf("%08"PRIx64": \t",is->insn->address);
922  }
923  if(dis_opts & DIS_OPT_DETAIL_BIN) {
924  if(is->insn->size == 2) {
925  printf("%02x%02x ",is->insn->bytes[1],is->insn->bytes[0]);
926  } else if(is->insn->size == 4) {
927  printf("%02x%02x %02x%02x",is->insn->bytes[1],is->insn->bytes[0],is->insn->bytes[3],is->insn->bytes[2]);
928  }
929  }
930  printf(" \t%s", insn_mnemonic);
931  if(strlen(insn_ops)) {
932  printf("\t%s",insn_ops);
933  }
934  if(strlen(comment)) {
935  printf("\t%s %s",comment_start,comment);
936  }
937  } else {
938  printf(" %-7s", insn_mnemonic);
939  if(strlen(insn_ops)) {
940  printf(" %s",insn_ops);
941  }
942  if(dis_opts & DIS_OPT_FMT_CHDK) {
943  printf("\\n\"");
944  }
945  if(strlen(comment)) {
946  printf(" %s %s",comment_start,comment);
947  }
948  }
949  printf("\n");
950  if(ti.start) {
951  do_tbx_data(fw,is,dis_opts,&ti);
952  }
953  if((dis_opts & DIS_OPT_END_RET) && isRETx(is->insn)) { // end disassembly on return
954  if(dis_end_ret_count > 1) {
955  dis_end_ret_count--;
956  } else {
957  count++;
958  // could do this, but eret in code should work better pasting between ports
959  /*
960  if(dis_opts & DIS_OPT_FMT_CHDK) {
961  printf("// -f=chdk -s=0x%08x -c=%d\n",dis_start,(unsigned)count);
962  }
963  */
964  break;
965  }
966  }
967  } else {
968  uint16_t *pv=(uint16_t *)adr2ptr(fw,is->adr);
969  // TODO optional data directives
970  if(pv) {
971  if(is->thumb) {
972  printf("%s %04x\n",comment_start,*pv);
973  } else {
974  printf("%s %04x %04x\n",comment_start,*pv,*(pv+1));
975  }
976  } else {
977  printf("%s invalid address %"PRIx64"\n",comment_start,is->adr);
978  }
979  if(!disasm_iter_init(fw,is,(is->adr+is->insn_min_size)|is->thumb)) {
980  fprintf(stderr,"do_dis_range: disasm_iter_init failed\n");
981  break;
982  }
983  }
984  count++;
985  }
986  if(dis_opts & DIS_OPT_JMP_BACK) {
987  if(dis_opts & DIS_OPT_FMT_CHDK) {
988  printf("\"");
989  }
990  // note objdump format ignored, doesn't really make sense with jump back anyway
991  printf(" ldr pc, =0x%"PRIx64,is->adr|is->thumb);
992  if(dis_opts & DIS_OPT_FMT_CHDK) {
993  printf("\\n\"");
994  }
995  printf(" %s Continue in firmware\n",comment_start);
996  }
997  addr_hash_free(branch_list);
998 }
static void do_tbb_data ( firmware fw,
iter_state_t is,
unsigned  dis_opts,
tbx_info_t ti 
)
static

Definiert in Zeile 692 der Datei capdis.c.

693 {
694  uint32_t adr=ti->start;
695  if(dis_opts & DIS_OPT_FMT_CHDK) {
696  printf("\"branchtable_%08x:\\n\"\n",adr);
697  } else {
698  printf("branchtable_%08x:\n",adr);
699  }
700  uint32_t i=0;
701  while(i < ti->count) {
702  uint8_t *p=adr2ptr(fw,adr);
703  if(!p) {
704  fprintf(stderr,"do_tbb_data: jumptable outside of valid address range at 0x%08x\n",adr);
705  break;
706  }
707  uint32_t target = ti->start+2**p;
708  // shouldn't happen in normal code? may indicate problem?
709  if(target <= adr) {
710  if(dis_opts & DIS_OPT_FMT_CHDK) {
711  printf("\" .byte 0x%02x\\n\" %s invalid juptable data?\n",*p,comment_start);
712  } else {
713  printf(" .byte 0x%02x ; invalid juptable data?\n",*p);
714  }
715  i++;
716  adr++;
717  continue;
718  }
719  if(dis_opts & DIS_OPT_FMT_CHDK) {
720  printf("\" .byte((loc_%08x - branchtable_%08x) / 2)\\n\" %s (case %d)\n",target,ti->start,comment_start,i);
721  } else {
722  printf(" .byte 0x%02x %s jump to loc_%08x (case %d)\n",*p,comment_start,target,i);
723  }
724  adr++;
725  i++;
726  }
727  if(dis_opts & DIS_OPT_FMT_CHDK) {
728 // note, this is halfword aligned https://sourceware.org/binutils/docs/as/Align.html#Align
729 // "For other systems, including ppc, i386 using a.out format, arm and strongarm,
730 // it is the number of low-order zero bits the location counter must have after advancement."
731  printf("\".align 1\\n\"\n");
732  }
733  // ensure final adr is halfword aligned
734  if(adr & 1) {
735  uint8_t *p=adr2ptr(fw,adr);
736  if(p) {
737  if(!(dis_opts & DIS_OPT_FMT_CHDK)) {
738  printf(" .byte 0x%02x\n",*p);
739  }
740  } else {
741  fprintf(stderr,"do_tbb_data: jumptable outside of valid address range at 0x%08x\n",adr);
742  }
743  adr++;
744  }
745  // skip over jumptable
746  if(!disasm_iter_init(fw,is,adr | is->thumb)) {
747  fprintf(stderr,"do_tbb_data: disasm_iter_init failed\n");
748  }
749 }
static void do_tbh_data ( firmware fw,
iter_state_t is,
unsigned  dis_opts,
tbx_info_t ti 
)
static

Definiert in Zeile 754 der Datei capdis.c.

755 {
756  uint32_t adr=ti->start;
757  if(dis_opts & DIS_OPT_FMT_CHDK) {
758  printf("\"branchtable_%08x:\\n\"\n",adr);
759  } else {
760  printf("branchtable_%08x:\n",adr);
761  }
762  uint32_t i=0;
763  while(i < ti->count) {
764  uint16_t *p=(uint16_t *)adr2ptr(fw,adr);
765  if(!p) {
766  fprintf(stderr,"do_tbh_data: jumptable outside of valid address range at 0x%08x\n",adr);
767  break;
768  }
769  uint32_t target = ti->start+2**p;
770  // shouldn't happen in normal code? may indicate problem?
771  if(target <= adr) {
772  if(dis_opts & DIS_OPT_FMT_CHDK) {
773  printf("\" .short 0x%04x\\n\" %s invalid juptable data?\n",*p,comment_start);
774  } else {
775  printf(" .short 0x%04x ; invalid juptable data?\n",*p);
776  }
777  i++;
778  adr+=ti->bytes;
779  continue;
780  }
781  if(dis_opts & DIS_OPT_FMT_CHDK) {
782  printf("\" .short((loc_%08x - branchtable_%08x) / 2)\\n\" %s (case %d)\n",target,ti->start,comment_start,i);
783  } else {
784  printf(" .short 0x%04x %s jump to loc_%08x (case %d)\n",*p,comment_start,target,i);
785  }
786  adr+=ti->bytes;
787  i++;
788  }
789  // tbh shouldn't need any alignment fixup
790  // skip over jumptable
791  if(!disasm_iter_init(fw,is,adr | is->thumb)) {
792  fprintf(stderr,"do_tbh_data: disasm_iter_init failed\n");
793  }
794 }
static void do_tbx_data ( firmware fw,
iter_state_t is,
unsigned  dis_opts,
tbx_info_t ti 
)
static

Definiert in Zeile 835 der Datei capdis.c.

836 {
837  if(ti->bytes==1) {
838  do_tbb_data(fw,is,dis_opts,ti);
839  } else {
840  do_tbh_data(fw,is,dis_opts,ti);
841  }
842 }
static void do_tbx_pass1 ( firmware fw,
iter_state_t is,
struct llist **  branch_list,
unsigned  dis_opts,
tbx_info_t ti 
)
static

Definiert in Zeile 796 der Datei capdis.c.

797 {
798  uint32_t adr=ti->start;
799  uint32_t i=0;
800  while(i < ti->count) {
801  uint8_t *p=adr2ptr(fw,adr);
802  if(!p) {
803  fprintf(stderr,"do_tbb_data: jumptable outside of valid address range at 0x%08x\n",adr);
804  break;
805  }
806  uint16_t off;
807  if(ti->bytes==1) {
808  off=(uint16_t)*p;
809  } else {
810  off=*(uint16_t *)p;
811  }
812  uint32_t target = ti->start+2*off;
813  // shouldn't happen in normal code? may indicate problem? don't add label
814  if(target <= adr) {
815  adr++;
816  continue;
817  }
818  if(dis_opts & DIS_OPT_LABELS) {
819  addr_hash_add(branch_list,target);
820  }
821  adr+=ti->bytes;
822  i++;
823  }
824  // ensure final adr is halfword aligned (should only apply to tbb)
825  if(adr & 1) {
826  adr++;
827  }
828  // skip over jumptable data
829  if(!disasm_iter_init(fw,is,adr | is->thumb)) {
830  fprintf(stderr,"do_tbb_data: disasm_iter_init failed\n");
831  }
832 }
void free_list ( struct llist lst)

Definiert in Zeile 50 der Datei capdis.c.

51 {
52  if (lst)
53  {
54  struct lnode *p, *n;
55  p = lst->head;
56  while (p)
57  {
58  n = p->next;
59  free(p);
60  p = n;
61  }
62  free(lst);
63  }
64 }
int l_insert ( struct llist ls,
t_address  address,
t_value  data 
)

Definiert in Zeile 104 der Datei capdis.c.

105 {
106  struct lnode *node;
107 
108  if( l_search(ls, address)) return -1 ;
109  node = new_node(address, data);
110  if (node == NULL) return 0;
111  node->next = ls->head;
112  ls->head = node;
113  (ls->size)++;
114 
115  return 1;
116 }
void l_remove ( struct llist ls,
t_address  addr 
)

Definiert in Zeile 118 der Datei capdis.c.

119 {
120  if (ls)
121  {
122  struct lnode *p, *l;
123  l = 0;
124  p = ls->head;
125  while (p)
126  {
127  if (p->address == addr)
128  {
129  if (l)
130  l->next = p->next;
131  else
132  ls->head = p->next;
133  (ls->size)--;
134  return;
135  }
136  l = p;
137  p = p->next;
138  }
139  }
140 }
struct lnode* l_search ( struct llist ls,
t_address  address 
)

Definiert in Zeile 87 der Datei capdis.c.

87  {
88  struct lnode *node;
89 
90  node = ls->head;
91  while ( node != NULL && node->address != address ) {
92  node = node->next ;
93  }
94  if (node == NULL) {
95  return 0; /* 'item' not found */
96  }
97 
98  return node;
99 }
int main ( int  argc,
char **  argv 
)

Definiert in Zeile 1000 der Datei capdis.c.

1001 {
1002  char stubs_dir[256]="";
1003  char *dumpname=NULL;
1004  unsigned load_addr=0xFFFFFFFF;
1005  unsigned offset=0xFFFFFFFF;
1006  unsigned dis_start=0;
1007  const char *dis_start_fn=NULL;
1008  unsigned dis_end=0;
1009  unsigned dis_end_ret_count=0;
1010  unsigned dis_count=0;
1011  int do_fw_data_init=1;
1012  int verbose=0;
1014  int dis_arch=FW_ARCH_ARMv7;
1015  int do_propset=0;
1016  if(argc < 2) {
1017  usage();
1018  }
1019  int i;
1020  for(i=1; i < argc; i++) {
1021  if ( strncmp(argv[i],"-c=",3) == 0 ) {
1022  dis_count=strtoul(argv[i]+3,NULL,0);
1023  }
1024  else if ( strncmp(argv[i],"-o=",3) == 0 ) {
1025  offset=strtoul(argv[i]+3,NULL,0);
1026  }
1027  else if ( strncmp(argv[i],"-s=",3) == 0 ) {
1028  if(!isdigit(argv[i][3])) {
1029  dis_start_fn = argv[i]+3;
1030  } else {
1031  dis_start=strtoul(argv[i]+3,NULL,0);
1032  }
1033  }
1034  else if ( strncmp(argv[i],"-e=",3) == 0 ) {
1035  dis_end=strtoul(argv[i]+3,NULL,0);
1036  }
1037  else if ( strncmp(argv[i],"-f=",3) == 0 ) {
1038  if ( strcmp(argv[i]+3,"chdk") == 0 ) {
1039  dis_opts |= DIS_OPT_FMT_CHDK;
1040  dis_opts |= DIS_OPT_ADR_LDR;
1041  } else if ( strcmp(argv[i]+3,"objdump") == 0 ) {
1042  dis_opts |= DIS_OPT_FMT_OBJDUMP;
1043  } else {
1044  fprintf(stderr,"unknown output format %s\n",argv[i]+3);
1045  usage();
1046  }
1047  }
1048  else if ( strcmp(argv[i],"-armv5") == 0 ) {
1049  dis_arch=FW_ARCH_ARMv5;
1050  }
1051  else if ( strcmp(argv[i],"-stubs") == 0 ) {
1052  strcpy(stubs_dir,".");
1053  }
1054  else if ( strncmp(argv[i],"-stubs=",7) == 0 ) {
1055  strcpy(stubs_dir,argv[i]+7);
1056  }
1057  else if ( strncmp(argv[i],"-props=",7) == 0 ) {
1058  do_propset=strtoul(argv[i]+7,NULL,0);
1059  }
1060  else if ( strcmp(argv[i],"-v") == 0 ) {
1061  verbose++;
1062  }
1063  else if ( strcmp(argv[i],"-d") == 0 ) {
1064  dis_opts |= DIS_OPT_DETAIL_ALL;
1065  }
1066  else if ( strcmp(argv[i],"-noloc") == 0 ) {
1067  dis_opts &= ~DIS_OPT_LABELS;
1068  }
1069  else if ( strcmp(argv[i],"-nosub") == 0 ) {
1070  dis_opts &= ~DIS_OPT_SUBS;
1071  }
1072  else if ( strcmp(argv[i],"-noconst") == 0 ) {
1073  dis_opts &= ~DIS_OPT_CONSTS;
1074  }
1075  else if ( strcmp(argv[i],"-nostr") == 0 ) {
1076  dis_opts &= ~DIS_OPT_STR;
1077  }
1078  else if ( strcmp(argv[i],"-noadrldr") == 0 ) {
1079  dis_opts &= ~DIS_OPT_ADR_LDR;
1080  }
1081  else if ( strcmp(argv[i],"-nofwdata") == 0 ) {
1082  do_fw_data_init = 0;
1083  }
1084  else if ( strcmp(argv[i],"-nosimplefunc") == 0 ) {
1085  dis_opts &= ~DIS_OPT_SIMPLE_FUNCS;
1086  }
1087  else if ( strcmp(argv[i],"-adrldr") == 0 ) {
1088  dis_opts |= DIS_OPT_ADR_LDR;
1089  }
1090  else if ( strcmp(argv[i],"-jfw") == 0 ) {
1091  dis_opts |= DIS_OPT_JMP_BACK;
1092  }
1093  else if ( strcmp(argv[i],"-eret") == 0 ) {
1094  dis_opts |= DIS_OPT_END_RET;
1095  }
1096  else if ( strncmp(argv[i],"-eret=",6) == 0 ) {
1097  dis_opts |= DIS_OPT_END_RET;
1098  dis_end_ret_count=strtoul(argv[i]+6,NULL,0);
1099  }
1100  else if ( strcmp(argv[i],"-d-const") == 0 ) {
1101  dis_opts |= DIS_OPT_DETAIL_CONST;
1102  }
1103  else if ( strcmp(argv[i],"-d-group") == 0 ) {
1104  dis_opts |= DIS_OPT_DETAIL_GROUP;
1105  }
1106  else if ( strcmp(argv[i],"-d-op") == 0 ) {
1107  dis_opts |= DIS_OPT_DETAIL_OP;
1108  }
1109  else if ( strcmp(argv[i],"-d-addr") == 0 ) {
1110  dis_opts |= DIS_OPT_DETAIL_ADDR;
1111  }
1112  else if ( strcmp(argv[i],"-d-bin") == 0 ) {
1113  dis_opts |= DIS_OPT_DETAIL_BIN;
1114  }
1115  else if ( argv[i][0]=='-' ) {
1116  fprintf(stderr,"unknown option %s\n",argv[i]);
1117  usage();
1118  } else {
1119  if(!dumpname) {
1120  dumpname=argv[i];
1121  } else if(load_addr == 0xFFFFFFFF) {
1122  load_addr=strtoul(argv[i],NULL,0);
1123  } else {
1124  fprintf(stderr,"unexpected %s\n",argv[i]);
1125  usage();
1126  }
1127  }
1128  }
1129  if(!dumpname) {
1130  fprintf(stderr,"missing input file\n");
1131  usage();
1132  }
1133  struct stat st;
1134  if(stat(dumpname,&st) != 0) {
1135  fprintf(stderr,"bad input file %s\n",dumpname);
1136  return 1;
1137  }
1138  int dumpsize = st.st_size;
1139 
1140  if(load_addr==0xFFFFFFFF) {
1141  fprintf(stderr,"missing load address\n");
1142  usage();
1143  }
1144 
1145  firmware fw;
1146  if(stubs_dir[0]) {
1147  dis_opts |= (DIS_OPT_STUBS|DIS_OPT_STUBS_LABEL); // TODO may want to split various places stubs names could be used
1148  fw.sv = new_stub_values();
1149  char stubs_path[300];
1150  sprintf(stubs_path,"%s/%s",stubs_dir,"funcs_by_name.csv");
1151  load_funcs(fw.sv, stubs_path);
1152  sprintf(stubs_path,"%s/%s",stubs_dir,"stubs_entry.S");
1153  load_stubs(fw.sv, stubs_path, 1);
1154  sprintf(stubs_path,"%s/%s",stubs_dir,"stubs_min.S");
1155  load_stubs(fw.sv, stubs_path, 1);
1156  sprintf(stubs_path,"%s/%s",stubs_dir,"stubs_entry_2.S");
1157  load_stubs(fw.sv, stubs_path, 1); // Load second so values override stubs_entry.S
1158  }
1159  if(do_propset) {
1160  fw.sv->propcases = NULL;
1161  if(!(dis_opts & DIS_OPT_STUBS)) {
1162  fprintf(stderr,"-props requires -stubs\n");
1163  usage();
1164  }
1165  char props_path[300];
1166  sprintf(props_path,"%s/../../../../include/propset%d.h",stubs_dir,do_propset);
1167  // printf("load props %s %d\n",props_path,do_propset);
1168  load_propcases(fw.sv, props_path);
1169  if(!fw.sv->propcases) {
1170  fprintf(stderr,"propset %d load failed\n",do_propset);
1171  exit(1);
1172  }
1173  osig *ostub=find_sig(fw.sv->stubs,"SetPropertyCase");
1174  if(!ostub || !ostub->val) {
1175  fprintf(stderr,"SetPropertyCase not found, ignoring -props\n");
1176  set_prop = 0;
1177  } else {
1178  set_prop = ostub->val;
1179  }
1180  ostub=find_sig(fw.sv->stubs,"GetPropertyCase");
1181  if(!ostub || !ostub->val) {
1182  fprintf(stderr,"GetPropertyCase not found, ignoring -props\n");
1183  get_prop = 0;
1184  } else {
1185  get_prop = ostub->val;
1186  }
1187  if(get_prop && set_prop) {
1188  dis_opts |= DIS_OPT_PROPS;
1189  } else {
1190  do_propset=0;
1191  }
1192  }
1193  if(dis_start_fn) {
1194  if(!stubs_dir[0]) {
1195  fprintf(stderr,"-s with function name requires -stubs (did you forget an 0x?)\n");
1196  usage();
1197  }
1198  osig *ostub=find_sig(fw.sv->stubs,dis_start_fn);
1199  if(!ostub || !ostub->val) {
1200  fprintf(stderr,"start function %s not found (did you forget an 0x?)\n",dis_start_fn);
1201  return 1;
1202  }
1203  dis_start=ostub->val;
1204  }
1205 
1206  if(offset != 0xFFFFFFFF) {
1207  if(dis_start) {
1208  fprintf(stderr,"both start and and offset given\n");
1209  usage();
1210  }
1211  dis_start = offset+load_addr;
1212  }
1213  if(dis_end) {
1214  if(dis_count) {
1215  fprintf(stderr,"both end and count given\n");
1216  usage();
1217  }
1218  if(dis_end > load_addr+dumpsize) {
1219  fprintf(stderr,"end > load address + size\n");
1220  usage();
1221  }
1222  if(dis_end < dis_start) {
1223  fprintf(stderr,"end < start\n");
1224  usage();
1225  }
1226  dis_count=(dis_end-dis_start)/2; // need a count for do_dis_range, assume all 16 bit ins
1227  }
1228  // allow eret without count, enough for most cases
1229  if((dis_count==0) && (dis_opts & DIS_OPT_END_RET)) {
1230  dis_count=500;
1231  }
1232  if(dis_count==0) {
1233  fprintf(stderr,"missing instruction count\n");
1234  usage();
1235  }
1236  // count, no end
1237  if(dis_end==0) {
1238  dis_end=dis_start + dis_count * 4; // assume all 32 bit ins
1239  }
1241  fprintf(stderr,"multiple -f options not allowed\n");
1242  usage();
1243  }
1244  if(dis_opts & (DIS_OPT_FMT_CHDK)) {
1245  comment_start = "//";
1246  }
1247 
1248  firmware_load(&fw,dumpname,load_addr,dis_arch);
1250  if(do_fw_data_init) {
1252  }
1253 
1254  // check for RAM code address
1255  if(dis_start < fw.base) {
1256  adr_range_t *ar=adr_get_range(&fw,dis_start);
1257  if(!ar || ar->type != ADR_RANGE_RAM_CODE) {
1258  fprintf(stderr,"invalid start address 0x%08x\n",dis_start);
1259  return 1;
1260  }
1261  }
1262 
1263  if(verbose) {
1264  printf("%s %s size:0x%x start:0x%x instructions:%d opts:0x%x\n",comment_start,dumpname,dumpsize,dis_start,dis_count,dis_opts);
1265  }
1266 
1267 
1268  do_dis_range(&fw, dis_start, dis_count, dis_end, dis_end_ret_count, dis_opts);
1269 
1270  firmware_unload(&fw);
1271 
1272 
1273  return 0;
1274 }
struct llist* new_list ( )

Definiert in Zeile 35 der Datei capdis.c.

36 {
37  struct llist *lst;
38 
39  lst = (struct llist *) malloc(sizeof(struct llist));
40  if (lst == NULL) {
41  printf("\n **new_list() : malloc error");
42  return NULL;
43  }
44  lst->head = 0;
45  lst->size = 0;
46 
47  return lst;
48 }
struct lnode* new_node ( t_address  address,
t_value  data 
)

Definiert in Zeile 69 der Datei capdis.c.

69  {
70  struct lnode *node;
71 
72  node = (struct lnode *) malloc (sizeof (struct lnode));
73  if (node == NULL) {
74  printf("\n **new_node() : malloc error");
75  return NULL;
76  }
77  node->address = address;
78  node->data = data;
79  node->next = 0;
80 
81  return node;
82 }
void usage ( void  )

Definiert in Zeile 186 der Datei capdis.c.

186  {
187  fprintf(stderr,"usage capdis [options] <file> <load address>\n"
188  "options:\n"
189  " -c=<count> disassemble at most <count> instructions\n"
190  " -s=<address|stub name> start disassembling at <address>. LSB controls ARM/thumb mode\n"
191  " -e=<address> stop disassembling at <address>\n"
192  " -o=<offset> start disassembling at <offset>. LSB controls ARM/thumb mode\n"
193  " -f=<chdk|objdump> format as CHDK inline ASM, or similar to objdump (default clean ASM)\n"
194  " -armv5 make firmware_load treat firmware as armv5\n"
195  " -stubs[=dir] load / use stubs from dir (default .) for names\n"
196  " -props=<n> load propset<n>.h and identify propcases in calls. Requires -stubs\n"
197  " -v increase verbosity\n"
198  " -d-const add details about pc relative constant LDRs\n"
199  " -d-bin print instruction hex dump\n"
200  " -d-addr print instruction addresses\n"
201  " -d-ops print instruction operand information\n"
202  " -d-groups print instruction group information\n"
203  " -d all of the -d-* above\n"
204  " -noloc don't generate loc_xxx: labels and B loc_xxx\n"
205  " -nosub don't generate BL sub_xxx\n"
206  " -noconst don't generate LDR Rd,=0xFOO\n"
207  " -nostr don't comments for string refs\n"
208  " -adrldr convert ADR Rd,#x and similar to LDR RD,=... (default with -f=chdk)\n"
209  " -noadrldr don't convert ADR Rd,#x and similar to LDR RD,=...\n"
210  " -nofwdata don't attempt to initialize firmware data ranges\n"
211  " -nosimplefunc don't comment calls / jumps that return immediately or imm constant\n"
212  " -jfw generate LDR PC,=0x... to return to firmware at end of disassembled range\n"
213  " -eret[=n] stop on Nth return-like instruction (if no count / end, sets count=500)\n"
214  );
215  exit(1);
216 }

Variablen-Dokumentation

const char* comment_start = ";"

Definiert in Zeile 243 der Datei capdis.c.

t_address get_prop
static

Definiert in Zeile 184 der Datei capdis.c.

t_address set_prop
static

Definiert in Zeile 183 der Datei capdis.c.