This source file includes following definitions.
- addBufRange
- findRanges
- getBufRangeForIndex
- find_Nth_str
- find_str
- find_next_bytes_range
- find_bytes_all
- find_next_substr_bytes
- find_next_str_bytes_range
- find_str_bytes_main_fw
- find_next_str_bytes
- find_str_bytes
- isASCIIstring
- adr_get_range
- adr_get_range_type
- ptr2adr
- adr2ptr
- adr2ptr_with_data
- adr_range_type_str
- adr_range_desc_str
- adr_is_var
- adr_is_main_fw_code
- find_u32_adr_range
- find_u32_adr
- fw_u32
- fw_memcmp
- adr_hist_reset
- adr_hist_index
- adr_hist_add
- adr_hist_get
- isARM
- isLDR_PC
- isLDR_PC_PC
- isSUBW_PC
- isADDW_PC
- isADD_PC
- isSUB_PC
- isRETx
- isPUSH_LR
- isPOP_LR
- isPOP_PC
- isADDx_imm
- isSUBx_imm
- isADRx
- LDR_PC2valptr_thumb
- LDR_PC2valptr_arm
- LDR_PC2valptr
- LDR_PC2adr
- ADRx2adr
- ADR2adr
- ADR2valptr
- LDR_PC2val
- LDR_PC_PC_target
- B_target
- CBx_target
- BLXimm_target
- BL_target
- B_BL_target
- B_BL_BLXimm_target
- get_TBx_PC_info
- disasm_iter_new
- disasm_iter_free
- disasm_iter_set
- disasm_iter_init
- disasm_iter
- disasm_iter_redo
- fw_disasm_iter_start
- fw_disasm_iter
- fw_disasm_iter_single
- fw_disasm_adr
- fw_search_insn
- search_disasm_const_ref
- search_disasm_str_ref
- search_disasm_calls
- search_calls_multi_end
- search_disasm_calls_multi
- search_disasm_calls_veneer_multi
- get_call_const_args
- get_direct_jump_target
- get_branch_call_insn_target
- find_and_get_var_ldr
- check_simple_func
- find_last_call_from_func
- insn_match_seq
- insn_match
- insn_match_any
- insn_match_find_next
- insn_match_find_nth
- insn_match_find_next_seq
- fw_search_bytes
- fw_add_adr_range
- find_dryos_vers
- firmware_load
- do_blx_check
- firmware_init_capstone
- find_startup_copy
- find_exception_vec
- firmware_init_data_ranges
- firmware_unload
1 #include <inttypes.h>
2 #include <stdio.h>
3 #include <stdint.h>
4 #include <string.h>
5
6 #include <capstone.h>
7
8 #include "stubs_load.h"
9 #include "firmware_load_ng.h"
10
11
12
13 static void addBufRange(firmware *fw, int o, int l)
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 }
30
31
32 static void findRanges(firmware *fw)
33 {
34 int i, j, k;
35
36
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)
42 {
43 if (k == -1)
44 {
45 k = i;
46 }
47 }
48 else
49 {
50 if (k != -1)
51 {
52 if (i - k > 32)
53 {
54 if (k - j > 8)
55 {
56
57 addBufRange(fw,j,k - j);
58 }
59 j = i;
60 }
61 k = -1;
62 }
63 }
64 }
65
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 }
81
82
83 BufRange *getBufRangeForIndex(firmware *fw,int i)
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 }
94
95
96
97
98
99 int find_Nth_str(firmware *fw, char *str, int N)
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 }
122
123 int find_str(firmware *fw, char *str)
124 {
125 return find_Nth_str(fw, str, 1);
126 }
127
128
129
130
131
132 uint32_t find_next_bytes_range(firmware *fw, const void *bytes, size_t len, uint32_t start_adr, uint32_t max_adr)
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 }
171
172
173
174 int find_bytes_all(firmware *fw, const void *bytes, size_t len, uint32_t adr, uint32_t *result, int max)
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 }
182
183 uint32_t find_next_substr_bytes(firmware *fw, const char *str, uint32_t adr)
184 {
185
186
187 return find_next_bytes_range(fw,str,strlen(str),adr,0);
188 }
189
190 uint32_t find_next_str_bytes_range(firmware *fw, const char *str, uint32_t adr,uint32_t max_adr)
191 {
192
193 return find_next_bytes_range(fw,str,strlen(str)+1,adr,max_adr);
194 }
195
196
197 uint32_t find_str_bytes_main_fw(firmware *fw, const char *str)
198 {
199
200
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
208 return find_next_bytes_range(fw,str,strlen(str)+1,fw->rom_code_search_min_adr,max_adr);
209 }
210
211 uint32_t find_next_str_bytes(firmware *fw, const char *str, uint32_t adr)
212 {
213
214 return find_next_bytes_range(fw,str,strlen(str)+1,adr,0);
215 }
216
217
218
219 uint32_t find_str_bytes(firmware *fw, const char *str)
220 {
221 return find_next_str_bytes(fw,str,fw->base);
222 }
223
224 int isASCIIstring(firmware *fw, uint32_t adr)
225 {
226 unsigned char *p = (unsigned char*)adr2ptr_with_data(fw, adr);
227 if(!p) {
228 return 0;
229 }
230
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 }
243
244
245 adr_range_t *adr_get_range(firmware *fw, uint32_t adr)
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 }
257
258
259 int adr_get_range_type(firmware *fw, uint32_t adr)
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 }
267
268 uint32_t ptr2adr(firmware *fw, uint8_t *ptr)
269 {
270
271 return (ptr-fw->buf8)+fw->base;
272 }
273
274 uint8_t* adr2ptr(firmware *fw, uint32_t adr)
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 }
288
289 uint8_t* adr2ptr_with_data(firmware *fw, uint32_t adr)
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 }
304
305
306 const char* adr_range_type_str(int type)
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 }
321
322
323 const char* adr_range_desc_str(adr_range_t *r)
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 }
343
344
345 int adr_is_var(firmware *fw, uint32_t adr)
346 {
347 return (adr > fw->data_start && adr < fw->memisostart);
348 }
349
350
351 int adr_is_main_fw_code(firmware *fw, uint32_t adr)
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 }
365
366
367
368
369 uint32_t find_u32_adr_range(firmware *fw, uint32_t val, uint32_t start,uint32_t maxadr)
370 {
371
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
391 while(p<=p_end) {
392 if(*p==val) {
393 return ptr2adr(fw,(uint8_t *)p);
394 }
395 p++;
396 }
397 return 0;
398 }
399
400
401 uint32_t find_u32_adr(firmware *fw, uint32_t val, uint32_t start)
402 {
403 return find_u32_adr_range(fw,val,start, fw->base + (fw->size8 -4));
404 }
405
406
407 uint32_t fw_u32(firmware *fw, uint32_t adr)
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 }
416
417
418 int fw_memcmp(firmware *fw, uint32_t adr,const void *cmp, size_t n)
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 }
429
430
431
432
433 void adr_hist_reset(adr_hist_t *ah)
434 {
435 ah->cur=0;
436 ah->count=0;
437
438
439 }
440
441
442 int adr_hist_index(adr_hist_t *ah, int i)
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 }
450
451
452 void adr_hist_add(adr_hist_t *ah, uint32_t adr)
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 }
460
461
462
463 uint32_t adr_hist_get(adr_hist_t *ah, int i)
464 {
465 if(!ah->count || i > ah->count) {
466 return 0;
467 }
468 return ah->adrs[adr_hist_index(ah,-i)];
469 }
470
471
472
473
474 int isARM(cs_insn *insn)
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 }
484
485
486
487
488 int isLDR_PC(cs_insn *insn)
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 }
497
498
499
500
501 int isLDR_PC_PC(cs_insn *insn)
502 {
503 if(!isLDR_PC(insn)) {
504 return 0;
505 }
506 return (insn->detail->arm.operands[0].reg == ARM_REG_PC);
507 }
508
509
510 int isSUBW_PC(cs_insn *insn)
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 }
520
521
522 int isADDW_PC(cs_insn *insn)
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 }
532
533
534 int isADD_PC(cs_insn *insn)
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 }
543
544
545 int isSUB_PC(cs_insn *insn)
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 }
554
555
556 int isRETx(cs_insn *insn)
557 {
558
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
567
568
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
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 }
588
589
590 int isPUSH_LR(cs_insn *insn)
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 }
604
605
606 int isPOP_LR(cs_insn *insn)
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 }
620
621
622 int isPOP_PC(cs_insn *insn)
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 }
636
637
638 int isADDx_imm(cs_insn *insn)
639 {
640 return ((insn->id == ARM_INS_ADD || insn->id == ARM_INS_ADDW) && insn->detail->arm.operands[1].type == ARM_OP_IMM);
641 }
642
643 int isSUBx_imm(cs_insn *insn)
644 {
645 return (IS_INSN_ID_SUBx(insn->id) && insn->detail->arm.operands[1].type == ARM_OP_IMM);
646 }
647
648
649 int isADRx(cs_insn *insn)
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 }
656
657
658 uint32_t* LDR_PC2valptr_thumb(firmware *fw, cs_insn *insn)
659 {
660 if(!isLDR_PC(insn)) {
661 return NULL;
662 }
663 uint32_t adr;
664
665
666 adr=(insn->address&~3)+4+insn->detail->arm.operands[1].mem.disp;
667 return (uint32_t *)adr2ptr(fw,adr);
668 }
669
670 uint32_t* LDR_PC2valptr_arm(firmware *fw, cs_insn *insn)
671 {
672 if(!isLDR_PC(insn)) {
673 return NULL;
674 }
675 uint32_t adr;
676
677
678 adr=insn->address+8+insn->detail->arm.operands[1].mem.disp;
679 return (uint32_t *)adr2ptr(fw,adr);
680 }
681
682 uint32_t* LDR_PC2valptr(firmware *fw, cs_insn *insn)
683 {
684 if(isARM(insn)) {
685 return LDR_PC2valptr_arm(fw,insn);
686 } else {
687 return LDR_PC2valptr_thumb(fw,insn);
688 }
689 }
690
691
692 uint32_t LDR_PC2adr(__attribute__ ((unused))firmware *fw, cs_insn *insn)
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 }
703
704
705 uint32_t ADRx2adr(__attribute__ ((unused))firmware *fw, cs_insn *insn)
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 }
726
727
728
729 uint32_t ADR2adr(__attribute__ ((unused))firmware *fw, cs_insn *insn)
730 {
731 if(insn->id != ARM_INS_ADR) {
732 return 0;
733 }
734
735
736
737
738
739
740 return (insn->address&~3)+4+insn->detail->arm.operands[1].imm;
741 }
742
743
744 uint32_t* ADR2valptr(firmware *fw, cs_insn *insn)
745 {
746 uint32_t adr=ADR2adr(fw,insn);
747 return (uint32_t *)adr2ptr(fw,adr);
748 }
749
750
751 uint32_t LDR_PC2val(firmware *fw, cs_insn *insn)
752 {
753 uint32_t *p=LDR_PC2valptr(fw,insn);
754 if(p) {
755 return *p;
756 }
757 return 0;
758 }
759
760
761 uint32_t LDR_PC_PC_target(firmware *fw, cs_insn *insn)
762 {
763 if(!isLDR_PC_PC(insn)) {
764 return 0;
765 }
766 return LDR_PC2val(fw,insn);
767 }
768
769
770 uint32_t B_target(__attribute__ ((unused))firmware *fw, cs_insn *insn)
771 {
772 if(insn->id == ARM_INS_B) {
773 return insn->detail->arm.operands[0].imm;
774 }
775 return 0;
776 }
777
778
779
780 uint32_t CBx_target(__attribute__ ((unused))firmware *fw, cs_insn *insn)
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;
786 }
787
788
789 uint32_t BLXimm_target(__attribute__ ((unused))firmware *fw, cs_insn *insn)
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;
795 }
796
797
798
799 uint32_t BL_target(__attribute__ ((unused))firmware *fw, cs_insn *insn)
800 {
801 if(insn->id == ARM_INS_BL) {
802 return insn->detail->arm.operands[0].imm;
803 }
804 return 0;
805 }
806
807
808 uint32_t B_BL_target(__attribute__ ((unused))firmware *fw, cs_insn *insn)
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;
814 }
815
816
817
818 uint32_t B_BL_BLXimm_target(__attribute__ ((unused))firmware *fw, cs_insn *insn)
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;
826 }
827
828
829
830
831 int get_TBx_PC_info(firmware *fw,iter_state_t *is, tbx_info_t *ti)
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;
837 ti->first_target=0;
838 ti->bytes=(is->insn->id == ARM_INS_TBH)?2:1;
839
840 uint32_t max_adr;
841
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
849
850
851
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));
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
867 if(found_bhs && fw->is->insn->id == ARM_INS_CMP) {
868
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
874 break;
875 }
876 }
877 if(max_count) {
878 max_adr = ti->start+max_count*ti->bytes;
879
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
896
897 if(!off) {
898 break;
899 }
900 uint32_t target = ti->start+2*off;
901
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;
910 }
911 }
912 adr+=ti->bytes;
913 }
914
915 if(max_count) {
916 ti->count=max_count;
917 } else {
918
919 ti->count=(adr-ti->start)/ti->bytes;
920 }
921 return 1;
922 }
923
924
925
926
927
928 iter_state_t *disasm_iter_new(firmware *fw, uint32_t adr)
929 {
930 iter_state_t *is=(iter_state_t *)malloc(sizeof(iter_state_t));
931
932
933 is->insn=cs_malloc(fw->cs_handle_arm);
934 disasm_iter_init(fw,is,adr);
935 return is;
936 }
937
938
939 void disasm_iter_free(iter_state_t *is)
940 {
941 cs_free(is->insn,1);
942 free(is);
943 return;
944 }
945
946
947
948 int disasm_iter_set(firmware *fw, iter_state_t *is, uint32_t adr)
949 {
950
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);
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
971
972 is->code=NULL;
973 is->size=0;
974 is->adr=0;
975 return 0;
976 }
977
978 is->code=p;
979 is->size=fw->size8 - (p-fw->buf8);
980 is->adr=adr;
981 return 1;
982 }
983
984
985 int disasm_iter_init(__attribute__ ((unused))firmware *fw, iter_state_t *is, uint32_t adr)
986 {
987 adr_hist_reset(&is->ah);
988 return disasm_iter_set(fw,is,adr);
989 }
990
991
992
993
994 int disasm_iter(__attribute__ ((unused))firmware *fw, iter_state_t *is)
995 {
996
997 if(!is->code) {
998 return 0;
999 }
1000 adr_hist_add(&is->ah,(uint32_t)is->adr | is->thumb);
1001 return cs_disasm_iter(is->cs_handle, &is->code, &is->size, &is->adr, is->insn);
1002 }
1003
1004
1005
1006
1007 #if 0
1008 int disasm_iter_redo(firmware *fw,iter_state_t *is) {
1009 if(!is->code || !is->ah.count) {
1010 return 0;
1011 }
1012 is->code -= is->insn->size;
1013 is->adr -= is->insn->size;
1014 is->size += is->insn->size;
1015
1016 return cs_disasm_iter(is->cs_handle, &is->code, &is->size, &is->adr, is->insn);
1017 }
1018 #endif
1019
1020
1021
1022
1023
1024
1025 int fw_disasm_iter_start(firmware *fw, uint32_t adr)
1026 {
1027 return disasm_iter_init(fw,fw->is,adr);
1028 }
1029
1030
1031 int fw_disasm_iter(firmware *fw)
1032 {
1033 return disasm_iter(fw,fw->is);
1034 }
1035
1036
1037
1038 int fw_disasm_iter_single(firmware *fw, uint32_t adr)
1039 {
1040 fw_disasm_iter_start(fw,adr);
1041 return fw_disasm_iter(fw);
1042 }
1043
1044
1045
1046
1047
1048
1049
1050 #if 0
1051 size_t fw_disasm_adr(firmware *fw, uint32_t adr, unsigned count, cs_insn **insn)
1052 {
1053 uint8_t *p=adr2ptr(fw,adr);
1054 if(!p) {
1055 *insn=NULL;
1056 return 0;
1057 }
1058 return cs_disasm(fw->cs_handle, p, fw->size8 - (p-fw->buf8), adr, count, insn);
1059 }
1060 #endif
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072 uint32_t fw_search_insn(firmware *fw, iter_state_t *is, search_insn_fn f, uint32_t v1, void *udata, uint32_t adr_end)
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
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
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
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;
1113 } else {
1114
1115
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
1127
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
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
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;
1151 } else {
1152
1153
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
1162 br=br->next;
1163 }
1164 return 0;
1165 }
1166
1167
1168
1169
1170 uint32_t search_disasm_const_ref(firmware *fw, iter_state_t *is, uint32_t val, __attribute__ ((unused))void *unused)
1171 {
1172
1173 uint32_t av=ADRx2adr(fw,is->insn);
1174 if(av) {
1175
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
1184 if(*pv == val) {
1185 return (uint32_t)is->insn->address;
1186 }
1187 }
1188 return 0;
1189 }
1190
1191
1192 uint32_t search_disasm_str_ref(firmware *fw, iter_state_t *is, __attribute__ ((unused))uint32_t val, void *udata)
1193 {
1194 const char *str=(const char *)udata;
1195
1196 uint32_t av=ADRx2adr(fw,is->insn);
1197 if(av) {
1198
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
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 }
1215
1216
1217
1218
1219 uint32_t search_disasm_calls(firmware *fw, iter_state_t *is, uint32_t val, __attribute__ ((unused))void *unused)
1220 {
1221
1222 uint32_t sub=get_branch_call_insn_target(fw,is);
1223 if(sub) {
1224 if(sub == val) {
1225 return 1;
1226 }
1227 }
1228 return 0;
1229 }
1230
1231
1232 int search_calls_multi_end(__attribute__ ((unused))firmware *fw, __attribute__ ((unused))iter_state_t *is, __attribute__ ((unused))uint32_t adr) {
1233 return 1;
1234 }
1235
1236
1237
1238
1239
1240 uint32_t search_disasm_calls_multi(firmware *fw, iter_state_t *is, __attribute__ ((unused))uint32_t unused, void *userdata)
1241 {
1242 search_calls_multi_data_t *data=(search_calls_multi_data_t *)userdata;
1243 uint32_t sub=get_branch_call_insn_target(fw,is);
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 }
1254
1255
1256 uint32_t search_disasm_calls_veneer_multi(firmware *fw, iter_state_t *is, __attribute__ ((unused))uint32_t unused, void *userdata)
1257 {
1258 search_calls_multi_data_t *data=(search_calls_multi_data_t *)userdata;
1259 uint32_t sub=get_branch_call_insn_target(fw,is);
1260 if(sub) {
1261 while(data->adr) {
1262 if(data->adr == sub) {
1263 return data->fn(fw,is,sub);
1264 }
1265 data++;
1266 }
1267 uint32_t veneer=0;
1268 fw_disasm_iter_single(fw,sub);
1269 veneer=get_branch_call_insn_target(fw,fw->is);
1270 data=(search_calls_multi_data_t *)userdata;
1271 while(data->adr) {
1272 if(data->adr == veneer) {
1273 return data->fn(fw,is,sub);
1274 }
1275 data++;
1276 }
1277 }
1278 return 0;
1279 }
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291 int get_call_const_args(firmware *fw, iter_state_t *is_init, int max_backtrack, uint32_t *res)
1292 {
1293 int i;
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304 for (i=0;i<4;i++) {
1305 res[i]=0;
1306 }
1307
1308
1309 if(is_init->ah.count <= 1) {
1310 return 0;
1311 }
1312 if(is_init->ah.count - 1 < max_backtrack) {
1313
1314
1315
1316
1317
1318 max_backtrack = is_init->ah.count-1;
1319 }
1320 uint32_t found_bits=0;
1321 uint32_t known_bits=0;
1322
1323 for(i=1;i<=max_backtrack && known_bits !=0xf;i++) {
1324
1325
1326 fw_disasm_iter_single(fw,adr_hist_get(&is_init->ah,i));
1327
1328
1329
1330
1331
1332
1333 arm_insn insn_id = fw->is->insn->id;
1334
1335
1336 if((insn_id == ARM_INS_BL || insn_id == ARM_INS_BLX
1337
1338 )
1339 && fw->is->insn->detail->arm.cc == ARM_CC_AL) {
1340 break;
1341 }
1342
1343
1344
1345 if(fw->is->insn->detail->arm.operands[0].type != ARM_OP_REG) {
1346 continue;
1347 }
1348 arm_reg rd = fw->is->insn->detail->arm.operands[0].reg;
1349
1350
1351 if(rd < ARM_REG_R0 || rd > ARM_REG_R3) {
1352 continue;
1353 }
1354
1355 int rd_i = rd - ARM_REG_R0;
1356 uint32_t rd_bit = 1 << rd_i;
1357
1358 if(!(known_bits & rd_bit)) {
1359
1360
1361 known_bits |=rd_bit;
1362
1363 uint32_t *pv=LDR_PC2valptr(fw,fw->is->insn);
1364 if(pv) {
1365 res[rd_i] += *pv;
1366
1367 found_bits |=rd_bit;
1368 continue;
1369 }
1370 uint32_t v=ADRx2adr(fw,fw->is->insn);
1371 if(v) {
1372 res[rd_i] += v;
1373
1374 found_bits |=rd_bit;
1375 continue;
1376 }
1377
1378 if( IS_INSN_ID_MOVx(insn_id)
1379 && fw->is->insn->detail->arm.operands[1].type == ARM_OP_IMM) {
1380 res[rd_i] += fw->is->insn->detail->arm.operands[1].imm;
1381
1382 found_bits |=rd_bit;
1383 } else if(isADDx_imm(fw->is->insn)) {
1384 res[rd_i] += fw->is->insn->detail->arm.operands[1].imm;
1385
1386
1387 known_bits ^=rd_bit;
1388
1389 } else if(isSUBx_imm(fw->is->insn)) {
1390 res[rd_i] = (int)(res[rd_i]) - fw->is->insn->detail->arm.operands[1].imm;
1391
1392
1393 known_bits ^=rd_bit;
1394
1395 }
1396
1397
1398 }
1399 }
1400
1401 return found_bits;
1402 }
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416 uint32_t get_direct_jump_target(firmware *fw, iter_state_t *is_init)
1417 {
1418 uint32_t adr=B_target(fw,is_init->insn);
1419
1420 if(adr) {
1421 return (adr | is_init->thumb);
1422 }
1423 adr=LDR_PC_PC_target(fw,is_init->insn);
1424
1425 if(adr) {
1426 return adr;
1427 }
1428
1429 if((is_init->insn->id == ARM_INS_MOV || is_init->insn->id == ARM_INS_MOVW)
1430 && is_init->insn->detail->arm.operands[0].reg == ARM_REG_IP
1431 && is_init->insn->detail->arm.operands[1].type == ARM_OP_IMM) {
1432 adr = is_init->insn->detail->arm.operands[1].imm;
1433
1434 if(!fw_disasm_iter_single(fw,is_init->adr | is_init->thumb)) {
1435 fprintf(stderr,"get_direct_jump_target: disasm single failed at 0x%"PRIx64"\n",fw->is->insn->address);
1436 return 0;
1437 }
1438
1439 if(!(fw->is->insn->id == ARM_INS_MOVT
1440 && fw->is->insn->detail->arm.operands[0].reg == ARM_REG_IP
1441 && fw->is->insn->detail->arm.operands[1].type == ARM_OP_IMM)) {
1442
1443
1444 return 0;
1445 }
1446
1447 adr = (fw->is->insn->detail->arm.operands[1].imm << 16) | (adr&0xFFFF);
1448 if(!fw_disasm_iter(fw)) {
1449 fprintf(stderr,"get_direct_jump_target: disasm 2 failed at 0x%"PRIx64"\n",fw->is->insn->address);
1450 return 0;
1451 }
1452
1453 if(fw->is->insn->id == ARM_INS_BX
1454 && fw->is->insn->detail->arm.operands[0].type == ARM_OP_REG
1455 && fw->is->insn->detail->arm.operands[0].reg == ARM_REG_IP) {
1456 return adr;
1457 }
1458 }
1459 return 0;
1460 }
1461
1462
1463
1464
1465
1466
1467 uint32_t get_branch_call_insn_target(firmware *fw, iter_state_t *is)
1468 {
1469 uint32_t adr=B_BL_target(fw,is->insn);
1470 if(adr) {
1471 return (adr | is->thumb);
1472 }
1473
1474 if(is->thumb) {
1475 adr=CBx_target(fw,is->insn);
1476 if(adr) {
1477 return ADR_SET_THUMB(adr);
1478 }
1479 }
1480
1481 adr=BLXimm_target(fw,is->insn);
1482 if(adr) {
1483 if(is->thumb) {
1484 return adr;
1485 } else {
1486 return adr | is->thumb;
1487 }
1488 }
1489
1490 adr=LDR_PC_PC_target(fw,is->insn);
1491 if(adr) {
1492 return adr;
1493 }
1494 return 0;
1495 }
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513 int find_and_get_var_ldr(firmware *fw,
1514 iter_state_t *is,
1515 int max_search_insns,
1516 int max_seq_insns,
1517 arm_reg match_val_reg,
1518 var_ldr_desc_t *result)
1519
1520 {
1521 if(!insn_match_find_next(fw,is,max_search_insns,match_ldr_pc)) {
1522
1523 return 0;
1524 }
1525 var_ldr_desc_t r;
1526 memset(&r,0,sizeof(r));
1527 r.reg_base=is->insn->detail->arm.operands[0].reg;
1528 r.adr_base=LDR_PC2val(fw,is->insn);
1529 int seq_count=1;
1530
1531 while(seq_count < max_seq_insns) {
1532
1533 if(!disasm_iter(fw,is)) {
1534 return 0;
1535 }
1536
1537
1538
1539 if(isLDR_PC(is->insn)) {
1540
1541 return 0;
1542 }
1543 seq_count++;
1544
1545 if(isADDx_imm(is->insn) || isSUBx_imm(is->insn)) {
1546 if((arm_reg)is->insn->detail->arm.operands[0].reg != r.reg_base) {
1547 continue;
1548 }
1549 if(isADDx_imm(is->insn)) {
1550 r.adj=is->insn->detail->arm.operands[1].imm;
1551 } else {
1552 r.adj=-is->insn->detail->arm.operands[1].imm;
1553 }
1554 if(!disasm_iter(fw,is)) {
1555 return 0;
1556 }
1557 seq_count++;
1558 } else {
1559 r.adj=0;
1560 }
1561
1562
1563
1564
1565 if((r.reg_base >= ARM_REG_R0 && r.reg_base <= ARM_REG_R3)
1566 && (is->insn->id == ARM_INS_BL || is->insn->id == ARM_INS_BLX
1567 || is->insn->id == ARM_INS_B || is->insn->id == ARM_INS_BX)
1568 && is->insn->detail->arm.cc == ARM_CC_AL) {
1569
1570 return 0;
1571 }
1572 if(is->insn->id != ARM_INS_LDR || (arm_reg)is->insn->detail->arm.operands[1].reg != r.reg_base) {
1573
1574
1575 if(is->insn->detail->arm.operands[0].type == ARM_OP_REG && (arm_reg)is->insn->detail->arm.operands[0].reg == r.reg_base) {
1576
1577 return 0;
1578 }
1579 continue;
1580 }
1581 r.reg_val = is->insn->detail->arm.operands[0].reg;
1582 if(match_val_reg != ARM_REG_INVALID && (r.reg_val != match_val_reg)) {
1583 continue;
1584 }
1585 r.off = is->insn->detail->arm.operands[1].mem.disp;
1586 r.adr_adj = r.adr_base + r.adj;
1587 r.adr_final = r.adr_adj + r.off;
1588 memcpy(result,&r,sizeof(r));
1589 return 1;
1590 }
1591 return 0;
1592 }
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602 #define MATCH_SIMPLE_FUNC_NONE 0x0
1603
1604 #define MATCH_SIMPLE_FUNC_NULLSUB 0x1
1605
1606 #define MATCH_SIMPLE_FUNC_IMM 0x2
1607
1608
1609 #define MATCH_SIMPLE_FUNC_ANY 0x3
1610 int check_simple_func(firmware *fw, uint32_t adr, int match_ftype, simple_func_desc_t *info)
1611 {
1612 const insn_match_t match_mov_r0_imm[]={
1613 {MATCH_INS(MOV, 2), {MATCH_OP_REG(R0), MATCH_OP_IMM_ANY}},
1614 #if CS_API_MAJOR < 4
1615 {MATCH_INS(MOVS, 2), {MATCH_OP_REG(R0), MATCH_OP_IMM_ANY}},
1616 #endif
1617 {ARM_INS_ENDING}
1618 };
1619
1620 int found = 0;
1621 int found_val = 0;
1622 if(info) {
1623 info->ftype = MATCH_SIMPLE_FUNC_NONE;
1624 info->retval = 0;
1625 }
1626 if(!fw_disasm_iter_single(fw,adr)) {
1627
1628 return 0;
1629 }
1630 if(match_ftype & MATCH_SIMPLE_FUNC_IMM) {
1631
1632 if(insn_match_any(fw->is->insn,match_mov_r0_imm)) {
1633 found_val = fw->is->insn->detail->arm.operands[1].imm;
1634 found = MATCH_SIMPLE_FUNC_IMM;
1635
1636 if(!fw_disasm_iter(fw)) {
1637
1638 return 0;
1639 }
1640 }
1641 }
1642 if(!isRETx(fw->is->insn)) {
1643
1644 return 0;
1645 }
1646
1647 if(!found && (match_ftype & MATCH_SIMPLE_FUNC_NULLSUB)) {
1648 found = MATCH_SIMPLE_FUNC_NULLSUB;
1649
1650 }
1651 if(found) {
1652 if(info) {
1653 info->ftype = found;
1654 info->retval = found_val;
1655 }
1656 }
1657 return found;
1658 }
1659
1660
1661
1662
1663
1664
1665
1666
1667 uint32_t find_last_call_from_func(firmware *fw, iter_state_t *is,int min_insns, int max_insns)
1668 {
1669 int push_found=0;
1670 uint32_t last_adr=0;
1671 int count;
1672 for(count=0; count < max_insns; count++) {
1673 if(!disasm_iter(fw,is)) {
1674 fprintf(stderr,"find_last_call_from_func: disasm failed 0x%"PRIx64"\n",is->adr);
1675 return 0;
1676 }
1677
1678 if(isPUSH_LR(is->insn)) {
1679
1680 if(push_found) {
1681
1682 return 0;
1683 }
1684 push_found=1;
1685 continue;
1686 }
1687
1688
1689 if(!push_found) {
1690 continue;
1691 }
1692
1693 if(insn_match_any(is->insn,match_bl_blximm) && count >= min_insns) {
1694
1695 last_adr=get_branch_call_insn_target(fw,is);
1696 continue;
1697 }
1698
1699 if(isPOP_PC(is->insn)) {
1700
1701 if(last_adr) {
1702 return last_adr;
1703 }
1704
1705 return 0;
1706 }
1707
1708 if(isPOP_LR(is->insn)) {
1709
1710 if(count < min_insns) {
1711
1712 return 0;
1713 }
1714 if(!disasm_iter(fw,is)) {
1715 fprintf(stderr,"find_last_call_from_func: disasm failed 0x%"PRIx64"\n",is->adr);
1716 return 0;
1717 }
1718 if(is->insn->id == ARM_INS_B && is->insn->detail->arm.cc == ARM_CC_AL) {
1719 return get_branch_call_insn_target(fw,is);
1720 }
1721
1722
1723 return 0;
1724 }
1725
1726 if(isRETx(is->insn)) {
1727
1728 return 0;
1729 }
1730 }
1731
1732 return 0;
1733 }
1734
1735
1736
1737
1738 const insn_match_t match_b[]={
1739 {MATCH_INS(B, MATCH_OPCOUNT_IGNORE)},
1740 {ARM_INS_ENDING}
1741 };
1742 const insn_match_t match_bl[]={
1743 {MATCH_INS(BL, MATCH_OPCOUNT_IGNORE)},
1744 {ARM_INS_ENDING}
1745 };
1746 const insn_match_t match_b_bl[]={
1747 {MATCH_INS(B, MATCH_OPCOUNT_IGNORE)},
1748 {MATCH_INS(BL, MATCH_OPCOUNT_IGNORE)},
1749 {ARM_INS_ENDING}
1750 };
1751
1752 const insn_match_t match_b_bl_blximm[]={
1753 {MATCH_INS(B, MATCH_OPCOUNT_IGNORE)},
1754 {MATCH_INS(BL, MATCH_OPCOUNT_IGNORE)},
1755 {MATCH_INS(BLX, 1), {MATCH_OP_IMM_ANY}},
1756 {ARM_INS_ENDING}
1757 };
1758
1759 const insn_match_t match_bl_blximm[]={
1760 {MATCH_INS(BL, MATCH_OPCOUNT_IGNORE)},
1761 {MATCH_INS(BLX, 1), {MATCH_OP_IMM_ANY}},
1762 {ARM_INS_ENDING}
1763 };
1764
1765 const insn_match_t match_bxlr[]={
1766 {MATCH_INS(BX, 1), {MATCH_OP_REG(LR)}},
1767 {ARM_INS_ENDING}
1768 };
1769
1770 const insn_match_t match_ldr_pc[]={
1771 {MATCH_INS(LDR, 2), {MATCH_OP_REG_ANY, MATCH_OP_MEM_BASE(PC)}},
1772 {ARM_INS_ENDING}
1773 };
1774
1775
1776 int insn_match_seq(firmware *fw, iter_state_t *is, const insn_match_t *match)
1777 {
1778
1779 while(match->id != ARM_INS_ENDING && disasm_iter(fw,is) && insn_match(is->insn,match)) {
1780
1781 match++;
1782 }
1783 return (match->id == ARM_INS_ENDING);
1784 }
1785
1786
1787 int insn_match(cs_insn *insn,const insn_match_t *match)
1788 {
1789
1790 if(match->id != ARM_INS_INVALID && insn->id != match->id) {
1791 return 0;
1792 }
1793
1794 if(match->cc != ARM_CC_INVALID && insn->detail->arm.cc != match->cc) {
1795 return 0;
1796 }
1797
1798 if(match->op_count == MATCH_OPCOUNT_IGNORE) {
1799 return 1;
1800 }
1801
1802 if(match->op_count >= 0 && insn->detail->arm.op_count != match->op_count) {
1803 return 0;
1804 }
1805 int i;
1806
1807 for(i=0;i<MATCH_MAX_OPS && i < insn->detail->arm.op_count; i++) {
1808
1809 if(match->operands[i].type != ARM_OP_INVALID && insn->detail->arm.operands[i].type != match->operands[i].type) {
1810 return 0;
1811 }
1812
1813 if(match->operands[i].reg1 != ARM_REG_INVALID) {
1814 if(insn->detail->arm.operands[i].type == ARM_OP_REG) {
1815 if((arm_reg)insn->detail->arm.operands[i].reg != match->operands[i].reg1) {
1816 return 0;
1817 }
1818 } else if(insn->detail->arm.operands[i].type == ARM_OP_MEM) {
1819 if(insn->detail->arm.operands[i].mem.base != match->operands[i].reg1) {
1820 return 0;
1821 }
1822 } else {
1823 fprintf(stderr,"insn_match: reg1 match requested on operand not reg or mem %d\n",
1824 insn->detail->arm.operands[i].type);
1825 }
1826 }
1827 if(match->operands[i].reg2 != ARM_REG_INVALID) {
1828 if(insn->detail->arm.operands[i].type == ARM_OP_MEM) {
1829 if(insn->detail->arm.operands[i].mem.index != match->operands[i].reg2) {
1830 return 0;
1831 }
1832 } else {
1833 fprintf(stderr,"insn_match: reg2 match requested on operand not reg or mem %d\n",
1834 insn->detail->arm.operands[i].type);
1835 }
1836 }
1837 if(match->operands[i].flags & MATCH_OP_FL_IMM) {
1838 if(insn->detail->arm.operands[i].type == ARM_OP_IMM
1839 || insn->detail->arm.operands[i].type == ARM_OP_PIMM
1840 || insn->detail->arm.operands[i].type == ARM_OP_CIMM) {
1841 if(insn->detail->arm.operands[i].imm != match->operands[i].imm) {
1842 return 0;
1843 }
1844 } else if(insn->detail->arm.operands[i].type == ARM_OP_MEM) {
1845 if(insn->detail->arm.operands[i].mem.disp != match->operands[i].imm) {
1846 return 0;
1847 }
1848 } else {
1849 fprintf(stderr,"insn_match: imm match requested on operand not imm or mem %d\n",
1850 insn->detail->arm.operands[i].type);
1851 }
1852 }
1853 if(match->operands[i].flags & MATCH_OP_FL_LAST) {
1854 break;
1855 }
1856 }
1857 return 1;
1858 }
1859
1860
1861 int insn_match_any(cs_insn *insn,const insn_match_t *match)
1862 {
1863 const insn_match_t *m;
1864
1865 for(m=match;m->id != ARM_INS_ENDING;m++) {
1866 if(insn_match(insn,m)) {
1867 return 1;
1868 }
1869 }
1870 return 0;
1871 }
1872
1873
1874 int insn_match_find_next(firmware *fw, iter_state_t *is, int max_insns, const insn_match_t *match)
1875 {
1876 int i=0;
1877 while(i < max_insns) {
1878
1879 if(!disasm_iter(fw,is)) {
1880 return 0;
1881 }
1882
1883 if(insn_match_any(is->insn,match)) {
1884 return 1;
1885 }
1886 i++;
1887 }
1888
1889 return 0;
1890 }
1891
1892
1893 int insn_match_find_nth(firmware *fw, iter_state_t *is, int max_insns, int num_to_match, const insn_match_t *match)
1894 {
1895 int i=0;
1896 int num_matched=0;
1897 while(i < max_insns) {
1898
1899 if(!disasm_iter(fw,is)) {
1900 return 0;
1901 }
1902
1903
1904 const insn_match_t *m;
1905
1906 for(m=match;m->id != ARM_INS_ENDING;m++) {
1907 if(insn_match(is->insn,m)) {
1908 num_matched++;
1909 }
1910 }
1911 if(num_matched == num_to_match) {
1912 return 1;
1913 }
1914 i++;
1915 }
1916
1917 return 0;
1918 }
1919
1920
1921 int insn_match_find_next_seq(firmware *fw, iter_state_t *is, int max_insns, const insn_match_t *match)
1922 {
1923 int count=0;
1924 while(count < max_insns) {
1925 const insn_match_t *m=match;
1926
1927 while(m->id != ARM_INS_ENDING && disasm_iter(fw,is) && insn_match(is->insn,m)) {
1928 m++;
1929 count++;
1930 }
1931 if(m->id == ARM_INS_ENDING) {
1932 return 1;
1933 }
1934
1935 count++;
1936 }
1937 return 0;
1938 }
1939
1940
1941
1942
1943
1944
1945
1946 int fw_search_bytes(firmware *fw, search_bytes_fn func)
1947 {
1948 BufRange *p = fw->br;
1949 while (p)
1950 {
1951 int k;
1952 for (k = p->off*4; k < (p->off + p->len)*4; k++)
1953 {
1954 if (func(fw,k))
1955 return 1;
1956 }
1957 p = p->next;
1958 }
1959 return 0;
1960 }
1961
1962
1963
1964
1965 void fw_add_adr_range(firmware *fw, uint32_t start, uint32_t end, uint32_t src_start, int type, int flags)
1966 {
1967 if(fw->adr_range_count == FW_MAX_ADR_RANGES) {
1968 fprintf(stderr,"fw_add_adr_range: FW_MAX_ADR_RANGES hit\n");
1969 return;
1970 }
1971 if(src_start < fw->base) {
1972 fprintf(stderr,"fw_add_adr_range: src_start 0x%08x < base 0x%08x\n",src_start,fw->base);
1973 return;
1974 }
1975 if(src_start >= fw->base+fw->size8) {
1976 fprintf(stderr,"fw_add_adr_range: src_start 0x%08x outside dump end 0x%08x\n",src_start,fw->base+fw->size8);
1977 return;
1978 }
1979 if(end <= start) {
1980 fprintf(stderr,"fw_add_adr_range: end 0x%08x <= start 0x%08x\n",end,start);
1981 return;
1982 }
1983 uint32_t len=end-start;
1984 if(len > 0xFFFFFFFF - src_start) {
1985 fprintf(stderr,"fw_add_adr_range: range too long %d\n",len);
1986 return;
1987 }
1988 if(len > fw->size8 - (start - fw->base)) {
1989 fprintf(stderr,"fw_add_adr_range: range outside of dump %d\n",len);
1990 return;
1991 }
1992 adr_range_t *r=&fw->adr_ranges[fw->adr_range_count];
1993
1994 r->start=start;
1995 r->src_start=src_start;
1996 r->bytes=len;
1997 r->type=type;
1998 r->flags=flags;
1999 r->buf=fw->buf8 + (r->src_start - fw->base);
2000
2001 fw->adr_range_count++;
2002 }
2003
2004 void find_dryos_vers(firmware *fw)
2005 {
2006 const char *sig="DRYOS version 2.3, release #";
2007 fw->dryos_ver_count = find_bytes_all(fw,sig,strlen(sig),fw->base,fw->dryos_ver_list,FW_MAX_DRYOS_VERS);
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017 if(fw->dryos_ver_count) {
2018 if(fw->dryos_ver_count == FW_MAX_DRYOS_VERS) {
2019 fprintf(stderr,"WARNING hit FW_MAX_DRYOS_VERS\n");
2020 }
2021 uint32_t i;
2022 int match_i;
2023 uint32_t min_adr = 0xFFFFFFFF;
2024
2025
2026 uint32_t maxadr = (fw->rom_code_search_max_adr - 0x800000 > fw->base)?fw->base + 0x800000:fw->rom_code_search_max_adr;
2027
2028
2029 for(i=0; i<fw->dryos_ver_count; i++) {
2030
2031
2032 uint32_t adr = find_u32_adr_range(fw,fw->dryos_ver_list[i],fw->rom_code_search_min_adr,maxadr);
2033 if(adr && adr < min_adr) {
2034 min_adr = adr;
2035 match_i = i;
2036 }
2037 }
2038 if(min_adr == 0xFFFFFFFF) {
2039 fprintf(stderr,"WARNING dryos version pointer not found, defaulting to first\n");
2040 match_i = 0;
2041 min_adr = 0;
2042 }
2043 fw->dryos_ver_str = (char *)adr2ptr(fw,fw->dryos_ver_list[match_i]);
2044 fw->dryos_ver = atoi((char *)adr2ptr(fw,fw->dryos_ver_list[match_i]+strlen(sig)));
2045 fw->dryos_ver_adr = fw->dryos_ver_list[match_i];
2046 fw->dryos_ver_ref_adr = min_adr;
2047
2048 } else {
2049 fw->dryos_ver=0;
2050 fw->dryos_ver_str=NULL;
2051 fw->dryos_ver_adr=0;
2052 }
2053 }
2054
2055
2056 void firmware_load(firmware *fw, const char *filename, uint32_t base_adr,int fw_arch)
2057 {
2058 FILE *f = fopen(filename, "rb");
2059 if (f == NULL)
2060 {
2061 fprintf(stderr,"Error opening %s\n",filename);
2062 exit(1);
2063 }
2064 fseek(f,0,SEEK_END);
2065 fw->size8 = ftell(f);
2066 fseek(f,0,SEEK_SET);
2067
2068
2069 if(fw->size8&3) {
2070 fprintf(stderr,"WARNING: dump size %d is not divisible by 4, truncating\n",fw->size8);
2071 fw->size8 &= ~3;
2072 }
2073
2074
2075 if((int)(0xFFFFFFFF - base_adr) < fw->size8) {
2076 fprintf(stderr,"adjusted dump size 0x%08x->",fw->size8);
2077 fw->size8 = 0xFFFFFFFC - base_adr;
2078 fprintf(stderr,"0x%08x\n",fw->size8);
2079 }
2080
2081 fw->arch=fw_arch;
2082 fw->size32=fw->size8/4;
2083
2084 fw->base = base_adr;
2085
2086 fw->buf8 = malloc(fw->size8);
2087 if(!fw->buf8) {
2088 fprintf(stderr,"malloc %d failed\n",fw->size8);
2089 exit(1);
2090 }
2091 fread(fw->buf8, 1, fw->size8, f);
2092 fclose(f);
2093 findRanges(fw);
2094
2095 fw->adr_range_count=0;
2096
2097 fw_add_adr_range(fw,fw->base, fw->base+fw->size8, fw->base, ADR_RANGE_ROM, ADR_RANGE_FL_NONE);
2098
2099 fw->main_offs = 0;
2100 int k = find_str(fw, "gaonisoy");
2101
2102 if(k == -1) {
2103
2104 if(find_str(fw,"VxWorks") == -1) {
2105 fprintf(stderr,"WARNING gaonisoy string not found, assuming code start offset 0\n");
2106 }
2107 } else if (k != 1) {
2108
2109 if(fw_memcmp(fw,fw->base+0x20004,"gaonisoy",8) == 0) {
2110 fw->main_offs = 0x20000;
2111 } else if (fw_memcmp(fw,fw->base+0x10004,"gaonisoy",8) == 0) {
2112 fw->main_offs = 0x10000;
2113 } else {
2114 fprintf(stderr,"WARNING code start offset not found, assuming 0\n");
2115 }
2116 }
2117
2118 fw->rom_code_search_min_adr = fw->base + fw->main_offs;
2119 fw->rom_code_search_max_adr=fw->base+fw->size8 - 4;
2120
2121 find_dryos_vers(fw);
2122
2123 fw->firmware_ver_str = 0;
2124 k = find_str(fw, "Firmware Ver ");
2125 if (k != -1)
2126 {
2127 fw->firmware_ver_str = (char *)fw->buf8 + k*4;
2128 }
2129
2130 if(fw->arch==FW_ARCH_ARMv5) {
2131 fw->thumb_default = 0;
2132 } else if(fw->arch==FW_ARCH_ARMv7) {
2133 fw->thumb_default = 1;
2134 } else {
2135 fprintf(stderr,"firmware_init_capstone: invalid arch\n");
2136 }
2137 }
2138
2139
2140 int do_blx_check(firmware *fw)
2141 {
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160 static const uint8_t code[]=
2161 "\x00\xf0\x06\xe8"
2162 "\x01\x20"
2163 "\x00\xf0\x04\xe8"
2164 ;
2165 cs_insn *insn;
2166 size_t count;
2167 count = cs_disasm(fw->cs_handle_thumb, code, sizeof(code), 0xFF000000, 3, &insn);
2168
2169 if(!(count == 3 && insn[0].id == ARM_INS_BLX && insn[2].id == ARM_INS_BLX)) {
2170 fprintf(stderr,"do_blx_check: disassembly failed\n");
2171 return 0;
2172 }
2173
2174 int r=(insn[0].detail->arm.operands[0].imm == insn[2].detail->arm.operands[0].imm);
2175
2176
2177 if(!r) {
2178 fprintf(stderr,"WARNING! Incorrect disassembly is likely\n");
2179 }
2180 cs_free(insn,count);
2181 return r;
2182 }
2183
2184
2185 int firmware_init_capstone(firmware *fw)
2186 {
2187 if (cs_open(CS_ARCH_ARM, CS_MODE_ARM, &fw->cs_handle_arm) != CS_ERR_OK) {
2188 fprintf(stderr,"cs_open ARM failed\n");
2189 return 0;
2190 }
2191 cs_option(fw->cs_handle_arm, CS_OPT_DETAIL, CS_OPT_ON);
2192 if (cs_open(CS_ARCH_ARM, CS_MODE_THUMB, &fw->cs_handle_thumb) != CS_ERR_OK) {
2193 fprintf(stderr,"cs_open thumb failed\n");
2194 return 0;
2195 }
2196 cs_option(fw->cs_handle_thumb, CS_OPT_DETAIL, CS_OPT_ON);
2197 fw->is=disasm_iter_new(fw,0);
2198 do_blx_check(fw);
2199 return 1;
2200 }
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210 int find_startup_copy(firmware *fw,
2211 iter_state_t *is,
2212 int max_search,
2213 uint32_t *src_start,
2214 uint32_t *dst_start,
2215 uint32_t *dst_end)
2216 {
2217 int count=0;
2218 uint32_t *fptr = NULL;
2219 uint32_t *dptr = NULL;
2220 uint32_t *eptr = NULL;
2221 *src_start=0;
2222 *dst_start=0;
2223 *dst_end=0;
2224
2225 while(disasm_iter(fw,is) && count < max_search) {
2226 uint32_t *pv=LDR_PC2valptr(fw,is->insn);
2227
2228
2229 if(!pv) {
2230 fptr=dptr=eptr=NULL;
2231 }else if(!fptr) {
2232
2233 if(*pv > fw->base) {
2234 fptr=pv;
2235 }
2236 } else if(!dptr) {
2237 if(*pv < fw->base) {
2238 dptr=pv;
2239 } else {
2240 fptr=NULL;
2241 }
2242 } else if(!eptr) {
2243 if(*pv < fw->base && *pv > *dptr) {
2244 eptr=pv;
2245 } else {
2246
2247 fptr=dptr=NULL;
2248 }
2249 }
2250 if(fptr && dptr && eptr) {
2251 *src_start=*fptr;
2252 *dst_start=*dptr;
2253 *dst_end=*eptr;
2254 return 1;
2255 }
2256 count++;
2257 }
2258 return 0;
2259 }
2260
2261 void find_exception_vec(firmware *fw, iter_state_t *is)
2262 {
2263
2264
2265 if(fw->arch != FW_ARCH_ARMv7) {
2266 return;
2267 }
2268
2269 const insn_match_t match_bl_mcr[]={
2270 {MATCH_INS(BL, 1), {MATCH_OP_IMM_ANY}},
2271
2272 {MATCH_INS(MCR, 6), {MATCH_OP_PIMM(15),MATCH_OP_IMM(0),MATCH_OP_REG_ANY,MATCH_OP_CIMM(12),MATCH_OP_CIMM(0),MATCH_OP_IMM(0)}},
2273 {ARM_INS_ENDING}
2274 };
2275
2276
2277 disasm_iter_init(fw, is, fw->base + fw->main_offs + 12 + fw->thumb_default);
2278 if(!insn_match_find_next(fw,is,4,match_bl_mcr)) {
2279 printf("no match!\n");
2280 return;
2281 }
2282
2283 uint32_t faddr = get_branch_call_insn_target(fw,is);
2284 if(faddr) {
2285
2286 disasm_iter_init(fw, is, faddr);
2287 disasm_iter(fw, is);
2288 int ra,rb;
2289 uint32_t va, vb;
2290 if(!IS_INSN_ID_MOVx(is->insn->id) || is->insn->detail->arm.operands[1].type != ARM_OP_IMM) {
2291 return;
2292 }
2293 ra = is->insn->detail->arm.operands[0].reg;
2294 va = is->insn->detail->arm.operands[1].imm;
2295 disasm_iter(fw, is);
2296 if(is->insn->id != ARM_INS_MOVT
2297 || is->insn->detail->arm.operands[0].reg != ra
2298 || is->insn->detail->arm.operands[1].type != ARM_OP_IMM) {
2299 return;
2300 }
2301 va = (is->insn->detail->arm.operands[1].imm << 16) | (va & 0xFFFF);
2302
2303 va = va & ~1;
2304 if(adr_get_range_type(fw,va) != ADR_RANGE_ROM) {
2305 return;
2306 }
2307 disasm_iter(fw, is);
2308 if(!IS_INSN_ID_MOVx(is->insn->id) || is->insn->detail->arm.operands[1].type != ARM_OP_IMM) {
2309 return;
2310 }
2311 rb = is->insn->detail->arm.operands[0].reg;
2312 vb = is->insn->detail->arm.operands[1].imm;
2313 disasm_iter(fw, is);
2314 if(is->insn->id != ARM_INS_MOVT
2315 || is->insn->detail->arm.operands[0].reg != rb
2316 || is->insn->detail->arm.operands[1].type != ARM_OP_IMM) {
2317 return;
2318 }
2319 vb = (is->insn->detail->arm.operands[1].imm << 16) | (vb & 0xFFFF);
2320 vb = vb & ~1;
2321 if(adr_get_range_type(fw,vb) != ADR_RANGE_ROM) {
2322 return;
2323 }
2324 if(va >= vb) {
2325 return;
2326 }
2327 fw_add_adr_range(fw,0,vb - va, va, ADR_RANGE_RAM_CODE, ADR_RANGE_FL_EVEC | ADR_RANGE_FL_TCM);
2328
2329
2330 } else if(is->insn->id == ARM_INS_MCR) {
2331
2332 fw->arch_flags |= FW_ARCH_FL_VMSA;
2333
2334 disasm_iter_init(fw, is, adr_hist_get(&is->ah,1));
2335 disasm_iter(fw, is);
2336
2337
2338 }
2339 }
2340
2341
2342 void firmware_init_data_ranges(firmware *fw)
2343 {
2344
2345 uint32_t src_start, dst_start, dst_end;
2346 uint32_t data_found_copy = 0;
2347
2348
2349 iter_state_t *is=disasm_iter_new(fw, fw->base + fw->main_offs + 12 + fw->thumb_default);
2350
2351 fw->data_init_start=0;
2352 fw->data_start=0;
2353 fw->data_len=0;
2354
2355 fw->memisostart=0;
2356
2357 int base2_found=0;
2358 int base3_found=0;
2359
2360
2361 int max_search=100;
2362 while(find_startup_copy(fw,is,max_search,&src_start,&dst_start,&dst_end)) {
2363
2364 if(dst_start < 0x100000) {
2365
2366 if(fw->data_init_start) {
2367 fprintf(stderr,"firmware_init_data_ranges: data already found, unexpected start 0x%08x src 0x%08x end 0x%08x\n",
2368 dst_start,src_start,dst_end);
2369 continue;
2370 }
2371
2372
2373 if(dst_start != 0x1900 && dst_start != 0x8000) {
2374 fprintf(stderr,"firmware_init_data_ranges: guess unknown ROM data_start 0x%08x src 0x%08x end 0x%08x\n",
2375 dst_start,src_start,dst_end);
2376 }
2377 fw->data_init_start=src_start;
2378 fw->data_start=dst_start;
2379 fw->data_len=dst_end-dst_start;
2380 fw_add_adr_range(fw,dst_start,dst_end,src_start, ADR_RANGE_INIT_DATA, ADR_RANGE_FL_NONE);
2381 data_found_copy=is->adr;
2382 } else if(dst_start < 0x08000000) {
2383
2384 if(base2_found) {
2385 fprintf(stderr,"firmware_init_data_ranges: base2 already found, unexpected start 0x%08x src 0x%08x end 0x%08x\n",
2386 dst_start,src_start,dst_end);
2387 continue;
2388 }
2389 base2_found=1;
2390
2391 if( dst_start != 0x003f1000 &&
2392 dst_start != 0x00431000 &&
2393 dst_start != 0x00471000 &&
2394 dst_start != 0x00685000 &&
2395 dst_start != 0x00671000 &&
2396 dst_start != 0x006b1000 &&
2397 dst_start != 0x010c1000 &&
2398 dst_start != 0x010e1000 &&
2399 dst_start != 0x01900000) {
2400 fprintf(stderr,"firmware_init_data_ranges: guess unknown base2 0x%08x src 0x%08x end 0x%08x\n",
2401 dst_start,src_start,dst_end);
2402 }
2403 fw_add_adr_range(fw,dst_start,dst_end,src_start,ADR_RANGE_RAM_CODE, ADR_RANGE_FL_NONE);
2404 } else {
2405
2406 if(base3_found) {
2407 fprintf(stderr,"firmware_init_data_ranges: base3 already found, unexpected start 0x%08x src 0x%08x end 0x%08x\n",
2408 dst_start,src_start,dst_end);
2409 continue;
2410 }
2411 base3_found=1;
2412 if(dst_start != 0xbfe10800 &&
2413 dst_start != 0xdffc4900) {
2414 fprintf(stderr,"firmware_init_data_ranges: guess unknown base3 0x%08x src 0x%08x end 0x%08x\n",
2415 dst_start,src_start,dst_end);
2416 }
2417 fw_add_adr_range(fw,dst_start,dst_end,src_start,ADR_RANGE_RAM_CODE, ADR_RANGE_FL_TCM);
2418 }
2419 if(fw->data_start && base2_found && base3_found) {
2420 break;
2421 }
2422
2423 max_search=16;
2424 }
2425
2426
2427 if(data_found_copy) {
2428 int count=0;
2429 uint32_t *eptr=NULL;
2430 uint32_t *dptr=NULL;
2431 disasm_iter_init(fw,is,(data_found_copy-4) | fw->thumb_default);
2432 while(disasm_iter(fw,is) && count < 20) {
2433 uint32_t *pv=LDR_PC2valptr(fw,is->insn);
2434
2435 if(!pv) {
2436
2437 } else if(!dptr) {
2438
2439
2440 if(*pv == fw->data_start + fw->data_len) {
2441 dptr=pv;
2442 }
2443 } else if(!eptr) {
2444 if(*pv < fw->base) {
2445 if(*pv != fw->data_start + fw->data_len) {
2446 eptr=pv;
2447 }
2448 } else {
2449 eptr=dptr=NULL;
2450 }
2451 }
2452 if(dptr && eptr) {
2453
2454 fw->memisostart=*eptr;
2455 break;
2456 }
2457 count++;
2458 }
2459 }
2460
2461 find_exception_vec(fw,is);
2462
2463
2464
2465 if(fw->data_start) {
2466 fw->rom_code_search_max_adr=fw->data_init_start;
2467 }
2468
2469 if(fw->dryos_ver_adr) {
2470 if(fw->dryos_ver_adr < fw->rom_code_search_max_adr) {
2471 fw->rom_code_search_max_adr = fw->dryos_ver_adr;
2472 }
2473 }
2474 disasm_iter_free(is);
2475 }
2476
2477
2478 void firmware_unload(firmware *fw)
2479 {
2480 if(!fw) {
2481 return;
2482 }
2483 if(fw->is) {
2484 disasm_iter_free(fw->is);
2485 }
2486 if(fw->cs_handle_arm) {
2487 cs_close(&fw->cs_handle_arm);
2488 }
2489 if(fw->cs_handle_thumb) {
2490 cs_close(&fw->cs_handle_thumb);
2491 }
2492 free(fw->buf8);
2493 memset(fw,0,sizeof(firmware));
2494 }