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
- 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(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(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(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(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(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(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(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(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(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(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(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(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, 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, 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, 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(firmware *fw, iter_state_t *is, 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, 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
1257
1258
1259
1260
1261
1262
1263
1264
1265 int get_call_const_args(firmware *fw, iter_state_t *is_init, int max_backtrack, uint32_t *res)
1266 {
1267 int i;
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278 for (i=0;i<4;i++) {
1279 res[i]=0;
1280 }
1281
1282
1283 if(is_init->ah.count <= 1) {
1284 return 0;
1285 }
1286 if(is_init->ah.count - 1 < max_backtrack) {
1287
1288
1289
1290
1291
1292 max_backtrack = is_init->ah.count-1;
1293 }
1294 uint32_t found_bits=0;
1295 uint32_t known_bits=0;
1296
1297 for(i=1;i<=max_backtrack && known_bits !=0xf;i++) {
1298
1299
1300 fw_disasm_iter_single(fw,adr_hist_get(&is_init->ah,i));
1301
1302
1303
1304
1305
1306
1307 arm_insn insn_id = fw->is->insn->id;
1308
1309
1310 if((insn_id == ARM_INS_BL || insn_id == ARM_INS_BLX
1311
1312 )
1313 && fw->is->insn->detail->arm.cc == ARM_CC_AL) {
1314 break;
1315 }
1316
1317
1318
1319 if(fw->is->insn->detail->arm.operands[0].type != ARM_OP_REG) {
1320 continue;
1321 }
1322 arm_reg rd = fw->is->insn->detail->arm.operands[0].reg;
1323
1324
1325 if(rd < ARM_REG_R0 || rd > ARM_REG_R3) {
1326 continue;
1327 }
1328
1329 int rd_i = rd - ARM_REG_R0;
1330 uint32_t rd_bit = 1 << rd_i;
1331
1332 if(!(known_bits & rd_bit)) {
1333
1334
1335 known_bits |=rd_bit;
1336
1337 uint32_t *pv=LDR_PC2valptr(fw,fw->is->insn);
1338 if(pv) {
1339 res[rd_i] += *pv;
1340
1341 found_bits |=rd_bit;
1342 continue;
1343 }
1344 uint32_t v=ADRx2adr(fw,fw->is->insn);
1345 if(v) {
1346 res[rd_i] += v;
1347
1348 found_bits |=rd_bit;
1349 continue;
1350 }
1351
1352 if( IS_INSN_ID_MOVx(insn_id)
1353 && fw->is->insn->detail->arm.operands[1].type == ARM_OP_IMM) {
1354 res[rd_i] += fw->is->insn->detail->arm.operands[1].imm;
1355
1356 found_bits |=rd_bit;
1357 } else if(isADDx_imm(fw->is->insn)) {
1358 res[rd_i] += fw->is->insn->detail->arm.operands[1].imm;
1359
1360
1361 known_bits ^=rd_bit;
1362
1363 } else if(isSUBx_imm(fw->is->insn)) {
1364 res[rd_i] = (int)(res[rd_i]) - fw->is->insn->detail->arm.operands[1].imm;
1365
1366
1367 known_bits ^=rd_bit;
1368
1369 }
1370
1371
1372 }
1373 }
1374
1375 return found_bits;
1376 }
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390 uint32_t get_direct_jump_target(firmware *fw, iter_state_t *is_init)
1391 {
1392 uint32_t adr=B_target(fw,is_init->insn);
1393
1394 if(adr) {
1395 return (adr | is_init->thumb);
1396 }
1397 adr=LDR_PC_PC_target(fw,is_init->insn);
1398
1399 if(adr) {
1400 return adr;
1401 }
1402
1403 if((is_init->insn->id == ARM_INS_MOV || is_init->insn->id == ARM_INS_MOVW)
1404 && is_init->insn->detail->arm.operands[0].reg == ARM_REG_IP
1405 && is_init->insn->detail->arm.operands[1].type == ARM_OP_IMM) {
1406 adr = is_init->insn->detail->arm.operands[1].imm;
1407
1408 if(!fw_disasm_iter_single(fw,is_init->adr | is_init->thumb)) {
1409 fprintf(stderr,"get_direct_jump_target: disasm single failed at 0x%"PRIx64"\n",fw->is->insn->address);
1410 return 0;
1411 }
1412
1413 if(!(fw->is->insn->id == ARM_INS_MOVT
1414 && fw->is->insn->detail->arm.operands[0].reg == ARM_REG_IP
1415 && fw->is->insn->detail->arm.operands[1].type == ARM_OP_IMM)) {
1416
1417
1418 return 0;
1419 }
1420
1421 adr = (fw->is->insn->detail->arm.operands[1].imm << 16) | (adr&0xFFFF);
1422 if(!fw_disasm_iter(fw)) {
1423 fprintf(stderr,"get_direct_jump_target: disasm 2 failed at 0x%"PRIx64"\n",fw->is->insn->address);
1424 return 0;
1425 }
1426
1427 if(fw->is->insn->id == ARM_INS_BX
1428 && fw->is->insn->detail->arm.operands[0].type == ARM_OP_REG
1429 && fw->is->insn->detail->arm.operands[0].reg == ARM_REG_IP) {
1430 return adr;
1431 }
1432 }
1433 return 0;
1434 }
1435
1436
1437
1438
1439
1440
1441 uint32_t get_branch_call_insn_target(firmware *fw, iter_state_t *is)
1442 {
1443 uint32_t adr=B_BL_target(fw,is->insn);
1444 if(adr) {
1445 return (adr | is->thumb);
1446 }
1447
1448 if(is->thumb) {
1449 adr=CBx_target(fw,is->insn);
1450 if(adr) {
1451 return ADR_SET_THUMB(adr);
1452 }
1453 }
1454
1455 adr=BLXimm_target(fw,is->insn);
1456 if(adr) {
1457 if(is->thumb) {
1458 return adr;
1459 } else {
1460 return adr | is->thumb;
1461 }
1462 }
1463
1464 adr=LDR_PC_PC_target(fw,is->insn);
1465 if(adr) {
1466 return adr;
1467 }
1468 return 0;
1469 }
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487 int find_and_get_var_ldr(firmware *fw,
1488 iter_state_t *is,
1489 int max_search_insns,
1490 int max_seq_insns,
1491 arm_reg match_val_reg,
1492 var_ldr_desc_t *result)
1493
1494 {
1495 if(!insn_match_find_next(fw,is,max_search_insns,match_ldr_pc)) {
1496
1497 return 0;
1498 }
1499 var_ldr_desc_t r;
1500 memset(&r,0,sizeof(r));
1501 r.reg_base=is->insn->detail->arm.operands[0].reg;
1502 r.adr_base=LDR_PC2val(fw,is->insn);
1503 int seq_count=1;
1504
1505 while(seq_count < max_seq_insns) {
1506
1507 if(!disasm_iter(fw,is)) {
1508 return 0;
1509 }
1510
1511
1512
1513 if(isLDR_PC(is->insn)) {
1514
1515 return 0;
1516 }
1517 seq_count++;
1518
1519 if(isADDx_imm(is->insn) || isSUBx_imm(is->insn)) {
1520 if(is->insn->detail->arm.operands[0].reg != r.reg_base) {
1521 continue;
1522 }
1523 if(isADDx_imm(is->insn)) {
1524 r.adj=is->insn->detail->arm.operands[1].imm;
1525 } else {
1526 r.adj=-is->insn->detail->arm.operands[1].imm;
1527 }
1528 if(!disasm_iter(fw,is)) {
1529 return 0;
1530 }
1531 seq_count++;
1532 } else {
1533 r.adj=0;
1534 }
1535
1536
1537
1538
1539 if((r.reg_base >= ARM_REG_R0 && r.reg_base <= ARM_REG_R3)
1540 && (is->insn->id == ARM_INS_BL || is->insn->id == ARM_INS_BLX
1541 || is->insn->id == ARM_INS_B || is->insn->id == ARM_INS_BX)
1542 && is->insn->detail->arm.cc == ARM_CC_AL) {
1543
1544 return 0;
1545 }
1546 if(is->insn->id != ARM_INS_LDR || is->insn->detail->arm.operands[1].reg != r.reg_base) {
1547
1548
1549 if(is->insn->detail->arm.operands[0].type == ARM_OP_REG && is->insn->detail->arm.operands[0].reg == r.reg_base) {
1550
1551 return 0;
1552 }
1553 continue;
1554 }
1555 r.reg_val = is->insn->detail->arm.operands[0].reg;
1556 if(match_val_reg != ARM_REG_INVALID && (r.reg_val != match_val_reg)) {
1557 continue;
1558 }
1559 r.off = is->insn->detail->arm.operands[1].mem.disp;
1560 r.adr_adj = r.adr_base + r.adj;
1561 r.adr_final = r.adr_adj + r.off;
1562 memcpy(result,&r,sizeof(r));
1563 return 1;
1564 }
1565 return 0;
1566 }
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576 #define MATCH_SIMPLE_FUNC_NONE 0x0
1577
1578 #define MATCH_SIMPLE_FUNC_NULLSUB 0x1
1579
1580 #define MATCH_SIMPLE_FUNC_IMM 0x2
1581
1582
1583 #define MATCH_SIMPLE_FUNC_ANY 0x3
1584 int check_simple_func(firmware *fw, uint32_t adr, int match_ftype, simple_func_desc_t *info)
1585 {
1586 const insn_match_t match_mov_r0_imm[]={
1587 {MATCH_INS(MOV, 2), {MATCH_OP_REG(R0), MATCH_OP_IMM_ANY}},
1588 #if CS_API_MAJOR < 4
1589 {MATCH_INS(MOVS, 2), {MATCH_OP_REG(R0), MATCH_OP_IMM_ANY}},
1590 #endif
1591 {ARM_INS_ENDING}
1592 };
1593
1594 int found = 0;
1595 int found_val = 0;
1596 if(info) {
1597 info->ftype = MATCH_SIMPLE_FUNC_NONE;
1598 info->retval = 0;
1599 }
1600 if(!fw_disasm_iter_single(fw,adr)) {
1601
1602 return 0;
1603 }
1604 if(match_ftype & MATCH_SIMPLE_FUNC_IMM) {
1605
1606 if(insn_match_any(fw->is->insn,match_mov_r0_imm)) {
1607 found_val = fw->is->insn->detail->arm.operands[1].imm;
1608 found = MATCH_SIMPLE_FUNC_IMM;
1609
1610 if(!fw_disasm_iter(fw)) {
1611
1612 return 0;
1613 }
1614 }
1615 }
1616 if(!isRETx(fw->is->insn)) {
1617
1618 return 0;
1619 }
1620
1621 if(!found && (match_ftype & MATCH_SIMPLE_FUNC_NULLSUB)) {
1622 found = MATCH_SIMPLE_FUNC_NULLSUB;
1623
1624 }
1625 if(found) {
1626 if(info) {
1627 info->ftype = found;
1628 info->retval = found_val;
1629 }
1630 }
1631 return found;
1632 }
1633
1634
1635
1636
1637
1638
1639
1640
1641 uint32_t find_last_call_from_func(firmware *fw, iter_state_t *is,int min_insns, int max_insns)
1642 {
1643 int push_found=0;
1644 uint32_t last_adr=0;
1645 int count;
1646 for(count=0; count < max_insns; count++) {
1647 if(!disasm_iter(fw,is)) {
1648 fprintf(stderr,"find_last_call_from_func: disasm failed 0x%"PRIx64"\n",is->adr);
1649 return 0;
1650 }
1651
1652 if(isPUSH_LR(is->insn)) {
1653
1654 if(push_found) {
1655
1656 return 0;
1657 }
1658 push_found=1;
1659 continue;
1660 }
1661
1662
1663 if(!push_found) {
1664 continue;
1665 }
1666
1667 if(insn_match_any(is->insn,match_bl_blximm) && count >= min_insns) {
1668
1669 last_adr=get_branch_call_insn_target(fw,is);
1670 continue;
1671 }
1672
1673 if(isPOP_PC(is->insn)) {
1674
1675 if(last_adr) {
1676 return last_adr;
1677 }
1678
1679 return 0;
1680 }
1681
1682 if(isPOP_LR(is->insn)) {
1683
1684 if(count < min_insns) {
1685
1686 return 0;
1687 }
1688 if(!disasm_iter(fw,is)) {
1689 fprintf(stderr,"find_last_call_from_func: disasm failed 0x%"PRIx64"\n",is->adr);
1690 return 0;
1691 }
1692 if(is->insn->id == ARM_INS_B && is->insn->detail->arm.cc == ARM_CC_AL) {
1693 return get_branch_call_insn_target(fw,is);
1694 }
1695
1696
1697 return 0;
1698 }
1699
1700 if(isRETx(is->insn)) {
1701
1702 return 0;
1703 }
1704 }
1705
1706 return 0;
1707 }
1708
1709
1710
1711
1712 const insn_match_t match_b[]={
1713 {MATCH_INS(B, MATCH_OPCOUNT_IGNORE)},
1714 {ARM_INS_ENDING}
1715 };
1716 const insn_match_t match_bl[]={
1717 {MATCH_INS(BL, MATCH_OPCOUNT_IGNORE)},
1718 {ARM_INS_ENDING}
1719 };
1720 const insn_match_t match_b_bl[]={
1721 {MATCH_INS(B, MATCH_OPCOUNT_IGNORE)},
1722 {MATCH_INS(BL, MATCH_OPCOUNT_IGNORE)},
1723 {ARM_INS_ENDING}
1724 };
1725
1726 const insn_match_t match_b_bl_blximm[]={
1727 {MATCH_INS(B, MATCH_OPCOUNT_IGNORE)},
1728 {MATCH_INS(BL, MATCH_OPCOUNT_IGNORE)},
1729 {MATCH_INS(BLX, 1), {MATCH_OP_IMM_ANY}},
1730 {ARM_INS_ENDING}
1731 };
1732
1733 const insn_match_t match_bl_blximm[]={
1734 {MATCH_INS(BL, MATCH_OPCOUNT_IGNORE)},
1735 {MATCH_INS(BLX, 1), {MATCH_OP_IMM_ANY}},
1736 {ARM_INS_ENDING}
1737 };
1738
1739 const insn_match_t match_bxlr[]={
1740 {MATCH_INS(BX, 1), {MATCH_OP_REG(LR)}},
1741 {ARM_INS_ENDING}
1742 };
1743
1744 const insn_match_t match_ldr_pc[]={
1745 {MATCH_INS(LDR, 2), {MATCH_OP_REG_ANY, MATCH_OP_MEM_BASE(PC)}},
1746 {ARM_INS_ENDING}
1747 };
1748
1749
1750 int insn_match_seq(firmware *fw, iter_state_t *is, const insn_match_t *match)
1751 {
1752
1753 while(match->id != ARM_INS_ENDING && disasm_iter(fw,is) && insn_match(is->insn,match)) {
1754
1755 match++;
1756 }
1757 return (match->id == ARM_INS_ENDING);
1758 }
1759
1760
1761 int insn_match(cs_insn *insn,const insn_match_t *match)
1762 {
1763
1764 if(match->id != ARM_INS_INVALID && insn->id != match->id) {
1765 return 0;
1766 }
1767
1768 if(match->cc != ARM_CC_INVALID && insn->detail->arm.cc != match->cc) {
1769 return 0;
1770 }
1771
1772 if(match->op_count == MATCH_OPCOUNT_IGNORE) {
1773 return 1;
1774 }
1775
1776 if(match->op_count >= 0 && insn->detail->arm.op_count != match->op_count) {
1777 return 0;
1778 }
1779 int i;
1780
1781 for(i=0;i<MATCH_MAX_OPS && i < insn->detail->arm.op_count; i++) {
1782
1783 if(match->operands[i].type != ARM_OP_INVALID && insn->detail->arm.operands[i].type != match->operands[i].type) {
1784 return 0;
1785 }
1786
1787 if(match->operands[i].reg1 != ARM_REG_INVALID) {
1788 if(insn->detail->arm.operands[i].type == ARM_OP_REG) {
1789 if(insn->detail->arm.operands[i].reg != match->operands[i].reg1) {
1790 return 0;
1791 }
1792 } else if(insn->detail->arm.operands[i].type == ARM_OP_MEM) {
1793 if(insn->detail->arm.operands[i].mem.base != match->operands[i].reg1) {
1794 return 0;
1795 }
1796 } else {
1797 fprintf(stderr,"insn_match: reg1 match requested on operand not reg or mem %d\n",
1798 insn->detail->arm.operands[i].type);
1799 }
1800 }
1801 if(match->operands[i].reg2 != ARM_REG_INVALID) {
1802 if(insn->detail->arm.operands[i].type == ARM_OP_MEM) {
1803 if(insn->detail->arm.operands[i].mem.index != match->operands[i].reg2) {
1804 return 0;
1805 }
1806 } else {
1807 fprintf(stderr,"insn_match: reg2 match requested on operand not reg or mem %d\n",
1808 insn->detail->arm.operands[i].type);
1809 }
1810 }
1811 if(match->operands[i].flags & MATCH_OP_FL_IMM) {
1812 if(insn->detail->arm.operands[i].type == ARM_OP_IMM
1813 || insn->detail->arm.operands[i].type == ARM_OP_PIMM
1814 || insn->detail->arm.operands[i].type == ARM_OP_CIMM) {
1815 if(insn->detail->arm.operands[i].imm != match->operands[i].imm) {
1816 return 0;
1817 }
1818 } else if(insn->detail->arm.operands[i].type == ARM_OP_MEM) {
1819 if(insn->detail->arm.operands[i].mem.disp != match->operands[i].imm) {
1820 return 0;
1821 }
1822 } else {
1823 fprintf(stderr,"insn_match: imm match requested on operand not imm or mem %d\n",
1824 insn->detail->arm.operands[i].type);
1825 }
1826 }
1827 if(match->operands[i].flags & MATCH_OP_FL_LAST) {
1828 break;
1829 }
1830 }
1831 return 1;
1832 }
1833
1834
1835 int insn_match_any(cs_insn *insn,const insn_match_t *match)
1836 {
1837 const insn_match_t *m;
1838
1839 for(m=match;m->id != ARM_INS_ENDING;m++) {
1840 if(insn_match(insn,m)) {
1841 return 1;
1842 }
1843 }
1844 return 0;
1845 }
1846
1847
1848 int insn_match_find_next(firmware *fw, iter_state_t *is, int max_insns, const insn_match_t *match)
1849 {
1850 int i=0;
1851 while(i < max_insns) {
1852
1853 if(!disasm_iter(fw,is)) {
1854 return 0;
1855 }
1856
1857 if(insn_match_any(is->insn,match)) {
1858 return 1;
1859 }
1860 i++;
1861 }
1862
1863 return 0;
1864 }
1865
1866
1867 int insn_match_find_nth(firmware *fw, iter_state_t *is, int max_insns, int num_to_match, const insn_match_t *match)
1868 {
1869 int i=0;
1870 int num_matched=0;
1871 while(i < max_insns) {
1872
1873 if(!disasm_iter(fw,is)) {
1874 return 0;
1875 }
1876
1877
1878 const insn_match_t *m;
1879
1880 for(m=match;m->id != ARM_INS_ENDING;m++) {
1881 if(insn_match(is->insn,m)) {
1882 num_matched++;
1883 }
1884 }
1885 if(num_matched == num_to_match) {
1886 return 1;
1887 }
1888 i++;
1889 }
1890
1891 return 0;
1892 }
1893
1894
1895 int insn_match_find_next_seq(firmware *fw, iter_state_t *is, int max_insns, const insn_match_t *match)
1896 {
1897 int count=0;
1898 while(count < max_insns) {
1899 const insn_match_t *m=match;
1900
1901 while(m->id != ARM_INS_ENDING && disasm_iter(fw,is) && insn_match(is->insn,m)) {
1902 m++;
1903 count++;
1904 }
1905 if(m->id == ARM_INS_ENDING) {
1906 return 1;
1907 }
1908
1909 count++;
1910 }
1911 return 0;
1912 }
1913
1914
1915
1916
1917
1918
1919
1920 int fw_search_bytes(firmware *fw, search_bytes_fn func)
1921 {
1922 BufRange *p = fw->br;
1923 while (p)
1924 {
1925 int k;
1926 for (k = p->off*4; k < (p->off + p->len)*4; k++)
1927 {
1928 if (func(fw,k))
1929 return 1;
1930 }
1931 p = p->next;
1932 }
1933 return 0;
1934 }
1935
1936
1937
1938
1939 void fw_add_adr_range(firmware *fw, uint32_t start, uint32_t end, uint32_t src_start, int type, int flags)
1940 {
1941 if(fw->adr_range_count == FW_MAX_ADR_RANGES) {
1942 fprintf(stderr,"fw_add_adr_range: FW_MAX_ADR_RANGES hit\n");
1943 return;
1944 }
1945 if(src_start < fw->base) {
1946 fprintf(stderr,"fw_add_adr_range: src_start 0x%08x < base 0x%08x\n",src_start,fw->base);
1947 return;
1948 }
1949 if(src_start >= fw->base+fw->size8) {
1950 fprintf(stderr,"fw_add_adr_range: src_start 0x%08x outside dump end 0x%08x\n",src_start,fw->base+fw->size8);
1951 return;
1952 }
1953 if(end <= start) {
1954 fprintf(stderr,"fw_add_adr_range: end 0x%08x <= start 0x%08x\n",end,start);
1955 return;
1956 }
1957 int len=end-start;
1958 if(len > 0xFFFFFFFF - src_start) {
1959 fprintf(stderr,"fw_add_adr_range: range too long %d\n",len);
1960 return;
1961 }
1962 if(len > fw->size8 - (start - fw->base)) {
1963 fprintf(stderr,"fw_add_adr_range: range outside of dump %d\n",len);
1964 return;
1965 }
1966 adr_range_t *r=&fw->adr_ranges[fw->adr_range_count];
1967
1968 r->start=start;
1969 r->src_start=src_start;
1970 r->bytes=len;
1971 r->type=type;
1972 r->flags=flags;
1973 r->buf=fw->buf8 + (r->src_start - fw->base);
1974
1975 fw->adr_range_count++;
1976 }
1977
1978 void find_dryos_vers(firmware *fw)
1979 {
1980 const char *sig="DRYOS version 2.3, release #";
1981 fw->dryos_ver_count = find_bytes_all(fw,sig,strlen(sig),fw->base,fw->dryos_ver_list,FW_MAX_DRYOS_VERS);
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991 if(fw->dryos_ver_count) {
1992 if(fw->dryos_ver_count == FW_MAX_DRYOS_VERS) {
1993 fprintf(stderr,"WARNING hit FW_MAX_DRYOS_VERS\n");
1994 }
1995 int i;
1996 int match_i;
1997 uint32_t min_adr = 0xFFFFFFFF;
1998
1999
2000 uint32_t maxadr = (fw->rom_code_search_max_adr - 0x800000 > fw->base)?fw->base + 0x800000:fw->rom_code_search_max_adr;
2001
2002
2003 for(i=0; i<fw->dryos_ver_count; i++) {
2004
2005
2006 uint32_t adr = find_u32_adr_range(fw,fw->dryos_ver_list[i],fw->rom_code_search_min_adr,maxadr);
2007 if(adr && adr < min_adr) {
2008 min_adr = adr;
2009 match_i = i;
2010 }
2011 }
2012 if(min_adr == 0xFFFFFFFF) {
2013 fprintf(stderr,"WARNING dryos version pointer not found, defaulting to first\n");
2014 match_i = 0;
2015 min_adr = 0;
2016 }
2017 fw->dryos_ver_str = (char *)adr2ptr(fw,fw->dryos_ver_list[match_i]);
2018 fw->dryos_ver = atoi((char *)adr2ptr(fw,fw->dryos_ver_list[match_i]+strlen(sig)));
2019 fw->dryos_ver_adr = fw->dryos_ver_list[match_i];
2020 fw->dryos_ver_ref_adr = min_adr;
2021
2022 } else {
2023 fw->dryos_ver=0;
2024 fw->dryos_ver_str=NULL;
2025 fw->dryos_ver_adr=0;
2026 }
2027 }
2028
2029
2030 void firmware_load(firmware *fw, const char *filename, uint32_t base_adr,int fw_arch)
2031 {
2032 FILE *f = fopen(filename, "rb");
2033 if (f == NULL)
2034 {
2035 fprintf(stderr,"Error opening %s\n",filename);
2036 exit(1);
2037 }
2038 fseek(f,0,SEEK_END);
2039 fw->size8 = ftell(f);
2040 fseek(f,0,SEEK_SET);
2041
2042
2043 if(fw->size8&3) {
2044 fprintf(stderr,"WARNING: dump size %d is not divisible by 4, truncating\n",fw->size8);
2045 fw->size8 &= ~3;
2046 }
2047
2048
2049 if(0xFFFFFFFF - base_adr < fw->size8) {
2050 fprintf(stderr,"adjusted dump size 0x%08x->",fw->size8);
2051 fw->size8 = 0xFFFFFFFC - base_adr;
2052 fprintf(stderr,"0x%08x\n",fw->size8);
2053 }
2054
2055 fw->arch=fw_arch;
2056 fw->size32=fw->size8/4;
2057
2058 fw->base = base_adr;
2059
2060 fw->buf8 = malloc(fw->size8);
2061 if(!fw->buf8) {
2062 fprintf(stderr,"malloc %d failed\n",fw->size8);
2063 exit(1);
2064 }
2065 fread(fw->buf8, 1, fw->size8, f);
2066 fclose(f);
2067 findRanges(fw);
2068
2069 fw->adr_range_count=0;
2070
2071 fw_add_adr_range(fw,fw->base, fw->base+fw->size8, fw->base, ADR_RANGE_ROM, ADR_RANGE_FL_NONE);
2072
2073 fw->main_offs = 0;
2074 int k = find_str(fw, "gaonisoy");
2075
2076 if(k == -1) {
2077
2078 if(find_str(fw,"VxWorks") == -1) {
2079 fprintf(stderr,"WARNING gaonisoy string not found, assuming code start offset 0\n");
2080 }
2081 } else if (k != 1) {
2082
2083 if(fw_memcmp(fw,fw->base+0x20004,"gaonisoy",8) == 0) {
2084 fw->main_offs = 0x20000;
2085 } else if (fw_memcmp(fw,fw->base+0x10004,"gaonisoy",8) == 0) {
2086 fw->main_offs = 0x10000;
2087 } else {
2088 fprintf(stderr,"WARNING code start offset not found, assuming 0\n");
2089 }
2090 }
2091
2092 fw->rom_code_search_min_adr = fw->base + fw->main_offs;
2093 fw->rom_code_search_max_adr=fw->base+fw->size8 - 4;
2094
2095 find_dryos_vers(fw);
2096
2097 fw->firmware_ver_str = 0;
2098 k = find_str(fw, "Firmware Ver ");
2099 if (k != -1)
2100 {
2101 fw->firmware_ver_str = (char *)fw->buf8 + k*4;
2102 }
2103
2104 if(fw->arch==FW_ARCH_ARMv5) {
2105 fw->thumb_default = 0;
2106 } else if(fw->arch==FW_ARCH_ARMv7) {
2107 fw->thumb_default = 1;
2108 } else {
2109 fprintf(stderr,"firmware_init_capstone: invalid arch\n");
2110 }
2111 }
2112
2113
2114 int do_blx_check(firmware *fw)
2115 {
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134 static const uint8_t code[]=
2135 "\x00\xf0\x06\xe8"
2136 "\x01\x20"
2137 "\x00\xf0\x04\xe8"
2138 ;
2139 cs_insn *insn;
2140 size_t count;
2141 count = cs_disasm(fw->cs_handle_thumb, code, sizeof(code), 0xFF000000, 3, &insn);
2142
2143 if(!(count == 3 && insn[0].id == ARM_INS_BLX && insn[2].id == ARM_INS_BLX)) {
2144 fprintf(stderr,"do_blx_check: disassembly failed\n");
2145 return 0;
2146 }
2147
2148 int r=(insn[0].detail->arm.operands[0].imm == insn[2].detail->arm.operands[0].imm);
2149
2150
2151 if(!r) {
2152 fprintf(stderr,"WARNING! Incorrect disassembly is likely\n");
2153 }
2154 cs_free(insn,count);
2155 return r;
2156 }
2157
2158
2159 int firmware_init_capstone(firmware *fw)
2160 {
2161 if (cs_open(CS_ARCH_ARM, CS_MODE_ARM, &fw->cs_handle_arm) != CS_ERR_OK) {
2162 fprintf(stderr,"cs_open ARM failed\n");
2163 return 0;
2164 }
2165 cs_option(fw->cs_handle_arm, CS_OPT_DETAIL, CS_OPT_ON);
2166 if (cs_open(CS_ARCH_ARM, CS_MODE_THUMB, &fw->cs_handle_thumb) != CS_ERR_OK) {
2167 fprintf(stderr,"cs_open thumb failed\n");
2168 return 0;
2169 }
2170 cs_option(fw->cs_handle_thumb, CS_OPT_DETAIL, CS_OPT_ON);
2171 fw->is=disasm_iter_new(fw,0);
2172 do_blx_check(fw);
2173 return 1;
2174 }
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184 int find_startup_copy(firmware *fw,
2185 iter_state_t *is,
2186 int max_search,
2187 uint32_t *src_start,
2188 uint32_t *dst_start,
2189 uint32_t *dst_end)
2190 {
2191 int count=0;
2192 uint32_t *fptr = NULL;
2193 uint32_t *dptr = NULL;
2194 uint32_t *eptr = NULL;
2195 *src_start=0;
2196 *dst_start=0;
2197 *dst_end=0;
2198
2199 while(disasm_iter(fw,is) && count < max_search) {
2200 uint32_t *pv=LDR_PC2valptr(fw,is->insn);
2201
2202
2203 if(!pv) {
2204 fptr=dptr=eptr=NULL;
2205 }else if(!fptr) {
2206
2207 if(*pv > fw->base) {
2208 fptr=pv;
2209 }
2210 } else if(!dptr) {
2211 if(*pv < fw->base) {
2212 dptr=pv;
2213 } else {
2214 fptr=NULL;
2215 }
2216 } else if(!eptr) {
2217 if(*pv < fw->base && *pv > *dptr) {
2218 eptr=pv;
2219 } else {
2220
2221 fptr=dptr=NULL;
2222 }
2223 }
2224 if(fptr && dptr && eptr) {
2225 *src_start=*fptr;
2226 *dst_start=*dptr;
2227 *dst_end=*eptr;
2228 return 1;
2229 }
2230 count++;
2231 }
2232 return 0;
2233 }
2234
2235 void find_exception_vec(firmware *fw, iter_state_t *is)
2236 {
2237
2238
2239 if(fw->arch != FW_ARCH_ARMv7) {
2240 return;
2241 }
2242
2243 const insn_match_t match_bl_mcr[]={
2244 {MATCH_INS(BL, 1), {MATCH_OP_IMM_ANY}},
2245
2246 {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)}},
2247 {ARM_INS_ENDING}
2248 };
2249
2250
2251 disasm_iter_init(fw, is, fw->base + fw->main_offs + 12 + fw->thumb_default);
2252 if(!insn_match_find_next(fw,is,4,match_bl_mcr)) {
2253 printf("no match!\n");
2254 return;
2255 }
2256
2257 uint32_t faddr = get_branch_call_insn_target(fw,is);
2258 if(faddr) {
2259
2260 disasm_iter_init(fw, is, faddr);
2261 disasm_iter(fw, is);
2262 int ra,rb;
2263 uint32_t va, vb;
2264 if(!IS_INSN_ID_MOVx(is->insn->id) || is->insn->detail->arm.operands[1].type != ARM_OP_IMM) {
2265 return;
2266 }
2267 ra = is->insn->detail->arm.operands[0].reg;
2268 va = is->insn->detail->arm.operands[1].imm;
2269 disasm_iter(fw, is);
2270 if(is->insn->id != ARM_INS_MOVT
2271 || is->insn->detail->arm.operands[0].reg != ra
2272 || is->insn->detail->arm.operands[1].type != ARM_OP_IMM) {
2273 return;
2274 }
2275 va = (is->insn->detail->arm.operands[1].imm << 16) | (va & 0xFFFF);
2276
2277 va = va & ~1;
2278 if(adr_get_range_type(fw,va) != ADR_RANGE_ROM) {
2279 return;
2280 }
2281 disasm_iter(fw, is);
2282 if(!IS_INSN_ID_MOVx(is->insn->id) || is->insn->detail->arm.operands[1].type != ARM_OP_IMM) {
2283 return;
2284 }
2285 rb = is->insn->detail->arm.operands[0].reg;
2286 vb = is->insn->detail->arm.operands[1].imm;
2287 disasm_iter(fw, is);
2288 if(is->insn->id != ARM_INS_MOVT
2289 || is->insn->detail->arm.operands[0].reg != rb
2290 || is->insn->detail->arm.operands[1].type != ARM_OP_IMM) {
2291 return;
2292 }
2293 vb = (is->insn->detail->arm.operands[1].imm << 16) | (vb & 0xFFFF);
2294 vb = vb & ~1;
2295 if(adr_get_range_type(fw,vb) != ADR_RANGE_ROM) {
2296 return;
2297 }
2298 if(va >= vb) {
2299 return;
2300 }
2301 fw_add_adr_range(fw,0,vb - va, va, ADR_RANGE_RAM_CODE, ADR_RANGE_FL_EVEC | ADR_RANGE_FL_TCM);
2302
2303
2304 } else if(is->insn->id == ARM_INS_MCR) {
2305
2306 fw->arch_flags |= FW_ARCH_FL_VMSA;
2307
2308 disasm_iter_init(fw, is, adr_hist_get(&is->ah,1));
2309 disasm_iter(fw, is);
2310
2311
2312 }
2313 }
2314
2315
2316 void firmware_init_data_ranges(firmware *fw)
2317 {
2318
2319 uint32_t src_start, dst_start, dst_end;
2320 uint32_t data_found_copy = 0;
2321
2322
2323 iter_state_t *is=disasm_iter_new(fw, fw->base + fw->main_offs + 12 + fw->thumb_default);
2324
2325 fw->data_init_start=0;
2326 fw->data_start=0;
2327 fw->data_len=0;
2328
2329 fw->memisostart=0;
2330
2331 int base2_found=0;
2332 int base3_found=0;
2333
2334
2335 int max_search=100;
2336 while(find_startup_copy(fw,is,max_search,&src_start,&dst_start,&dst_end)) {
2337
2338 if(dst_start < 0x100000) {
2339
2340 if(fw->data_init_start) {
2341 fprintf(stderr,"firmware_init_data_ranges: data already found, unexpected start 0x%08x src 0x%08x end 0x%08x\n",
2342 dst_start,src_start,dst_end);
2343 continue;
2344 }
2345
2346
2347 if(dst_start != 0x1900 && dst_start != 0x8000) {
2348 fprintf(stderr,"firmware_init_data_ranges: guess unknown ROM data_start 0x%08x src 0x%08x end 0x%08x\n",
2349 dst_start,src_start,dst_end);
2350 }
2351 fw->data_init_start=src_start;
2352 fw->data_start=dst_start;
2353 fw->data_len=dst_end-dst_start;
2354 fw_add_adr_range(fw,dst_start,dst_end,src_start, ADR_RANGE_INIT_DATA, ADR_RANGE_FL_NONE);
2355 data_found_copy=is->adr;
2356 } else if(dst_start < 0x08000000) {
2357
2358 if(base2_found) {
2359 fprintf(stderr,"firmware_init_data_ranges: base2 already found, unexpected start 0x%08x src 0x%08x end 0x%08x\n",
2360 dst_start,src_start,dst_end);
2361 continue;
2362 }
2363 base2_found=1;
2364
2365 if( dst_start != 0x003f1000 &&
2366 dst_start != 0x00431000 &&
2367 dst_start != 0x00471000 &&
2368 dst_start != 0x00685000 &&
2369 dst_start != 0x00671000 &&
2370 dst_start != 0x006b1000 &&
2371 dst_start != 0x010c1000 &&
2372 dst_start != 0x010e1000 &&
2373 dst_start != 0x01900000) {
2374 fprintf(stderr,"firmware_init_data_ranges: guess unknown base2 0x%08x src 0x%08x end 0x%08x\n",
2375 dst_start,src_start,dst_end);
2376 }
2377 fw_add_adr_range(fw,dst_start,dst_end,src_start,ADR_RANGE_RAM_CODE, ADR_RANGE_FL_NONE);
2378 } else {
2379
2380 if(base3_found) {
2381 fprintf(stderr,"firmware_init_data_ranges: base3 already found, unexpected start 0x%08x src 0x%08x end 0x%08x\n",
2382 dst_start,src_start,dst_end);
2383 continue;
2384 }
2385 base3_found=1;
2386 if(dst_start != 0xbfe10800 &&
2387 dst_start != 0xdffc4900) {
2388 fprintf(stderr,"firmware_init_data_ranges: guess unknown base3 0x%08x src 0x%08x end 0x%08x\n",
2389 dst_start,src_start,dst_end);
2390 }
2391 fw_add_adr_range(fw,dst_start,dst_end,src_start,ADR_RANGE_RAM_CODE, ADR_RANGE_FL_TCM);
2392 }
2393 if(fw->data_start && base2_found && base3_found) {
2394 break;
2395 }
2396
2397 max_search=16;
2398 }
2399
2400
2401 if(data_found_copy) {
2402 int count=0;
2403 uint32_t *eptr=NULL;
2404 uint32_t *dptr=NULL;
2405 disasm_iter_init(fw,is,(data_found_copy-4) | fw->thumb_default);
2406 while(disasm_iter(fw,is) && count < 20) {
2407 uint32_t *pv=LDR_PC2valptr(fw,is->insn);
2408
2409 if(!pv) {
2410
2411 } else if(!dptr) {
2412
2413
2414 if(*pv == fw->data_start + fw->data_len) {
2415 dptr=pv;
2416 }
2417 } else if(!eptr) {
2418 if(*pv < fw->base) {
2419 if(*pv != fw->data_start + fw->data_len) {
2420 eptr=pv;
2421 }
2422 } else {
2423 eptr=dptr=NULL;
2424 }
2425 }
2426 if(dptr && eptr) {
2427
2428 fw->memisostart=*eptr;
2429 break;
2430 }
2431 count++;
2432 }
2433 }
2434
2435 find_exception_vec(fw,is);
2436
2437
2438
2439 if(fw->data_start) {
2440 fw->rom_code_search_max_adr=fw->data_init_start;
2441 }
2442
2443 if(fw->dryos_ver_adr) {
2444 if(fw->dryos_ver_adr < fw->rom_code_search_max_adr) {
2445 fw->rom_code_search_max_adr = fw->dryos_ver_adr;
2446 }
2447 }
2448 disasm_iter_free(is);
2449 }
2450
2451
2452 void firmware_unload(firmware *fw)
2453 {
2454 if(!fw) {
2455 return;
2456 }
2457 if(fw->is) {
2458 disasm_iter_free(fw->is);
2459 }
2460 if(fw->cs_handle_arm) {
2461 cs_close(&fw->cs_handle_arm);
2462 }
2463 if(fw->cs_handle_thumb) {
2464 cs_close(&fw->cs_handle_thumb);
2465 }
2466 free(fw->buf8);
2467 memset(fw,0,sizeof(firmware));
2468 }