diff options
Diffstat (limited to 'utils/disassembler/arm/main.c')
-rw-r--r-- | utils/disassembler/arm/main.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/utils/disassembler/arm/main.c b/utils/disassembler/arm/main.c new file mode 100644 index 0000000000..834dc5ff93 --- /dev/null +++ b/utils/disassembler/arm/main.c | |||
@@ -0,0 +1,118 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <string.h> | ||
3 | #include <stdlib.h> | ||
4 | |||
5 | #define ULONG unsigned long | ||
6 | #define USHORT unsigned short | ||
7 | #define UCHAR unsigned char | ||
8 | |||
9 | ULONG isdata[1000000]; /* each bit defines one byte as: code=0, data=1 */ | ||
10 | |||
11 | extern void dis_asm(ULONG off, ULONG val, char *stg); | ||
12 | |||
13 | void main(int argc, char **argv) | ||
14 | { | ||
15 | FILE *in, *out; | ||
16 | char *ptr, stg[256]; | ||
17 | ULONG pos, sz, val, loop; | ||
18 | int offset, offset1; | ||
19 | USHORT regid; | ||
20 | |||
21 | if(argc == 1 || strcmp(argv[1], "--help") == 0) | ||
22 | { printf("Usage: arm_disass [input file]\n"); | ||
23 | printf(" disassembles input file to 'disasm.txt'"); | ||
24 | exit(-1); | ||
25 | } | ||
26 | |||
27 | in = fopen(argv[1], "rb"); | ||
28 | if(in == NULL) | ||
29 | { printf("Cannot open %s", argv[1]); | ||
30 | exit(-1); | ||
31 | } | ||
32 | |||
33 | out = fopen("disasm.txt", "w"); | ||
34 | if(out == NULL) exit(-1); | ||
35 | |||
36 | fseek(in, 0, SEEK_END); | ||
37 | sz = ftell(in); | ||
38 | |||
39 | /* first loop only sets data/code tags */ | ||
40 | for(loop=0; loop<2; loop++) | ||
41 | { | ||
42 | for(pos=0; pos<sz; pos+=4) | ||
43 | { | ||
44 | /* clear disassembler string start */ | ||
45 | memset(stg, 0, 40); | ||
46 | /* read next code dword */ | ||
47 | fseek(in, pos, SEEK_SET); | ||
48 | fread(&val, 4, 1, in); | ||
49 | |||
50 | /* check for data tag set: if 1 byte out of 4 is marked => assume data */ | ||
51 | if((isdata[pos>>5] & (0xf << (pos & 31))) || (val & 0xffff0000) == 0) | ||
52 | { | ||
53 | sprintf(stg, "%6x: %08x", pos, val); | ||
54 | } | ||
55 | else | ||
56 | { | ||
57 | dis_asm(pos, val, stg); | ||
58 | |||
59 | /* check for instant mov operation */ | ||
60 | if(memcmp(stg+17, "mov ", 4) == 0 && (ptr=strstr(stg, "0x")) != NULL) | ||
61 | { | ||
62 | regid = *(USHORT*)(stg+22); | ||
63 | |||
64 | sscanf(ptr+2, "%x", &offset); | ||
65 | if(ptr[-1] == '-') | ||
66 | offset = -offset; | ||
67 | } | ||
68 | else | ||
69 | /* check for add/sub operation */ | ||
70 | if((ptr=strstr(stg, "0x")) != NULL | ||
71 | && (memcmp(stg+17, "add ", 4) == 0 || memcmp(stg+17, "sub ", 4) == 0)) | ||
72 | { | ||
73 | if(regid == *(USHORT*)(stg+22) && regid == *(USHORT*)(stg+26)) | ||
74 | { | ||
75 | sscanf(ptr+2, "%x", &offset1); | ||
76 | if(ptr[-1] == '-') | ||
77 | offset1 = -offset1; | ||
78 | |||
79 | if(memcmp(stg+17, "add ", 4) == 0) offset += offset1; | ||
80 | else offset -= offset1; | ||
81 | |||
82 | /* add result to disassembler string */ | ||
83 | sprintf(stg+strlen(stg), " <- 0x%x", offset); | ||
84 | } | ||
85 | else | ||
86 | regid = 0; | ||
87 | } | ||
88 | else | ||
89 | regid = 0; | ||
90 | |||
91 | /* check for const data */ | ||
92 | if(memcmp(stg+26, "[pc, ", 5) == 0 && (ptr=strstr(stg, "0x")) != NULL) | ||
93 | { | ||
94 | sscanf(ptr+2, "%x", &offset); | ||
95 | if(ptr[-1] == '-') | ||
96 | offset = -offset; | ||
97 | |||
98 | /* add data tag */ | ||
99 | isdata[(pos+offset+8)>>5] |= 1 << ((pos+offset+8) & 31); | ||
100 | |||
101 | /* add const data to disassembler string */ | ||
102 | fseek(in, pos+offset+8, SEEK_SET); | ||
103 | fread(&offset, 4, 1, in); | ||
104 | sprintf(stg+strlen(stg), " <- 0x%x", offset); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | /* remove trailing spaces */ | ||
109 | while(stg[strlen(stg)-1] == 32) | ||
110 | stg[strlen(stg)-1] = 0; | ||
111 | |||
112 | if(loop == 1) | ||
113 | fprintf(out, "%s\n", stg); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | fclose(in); | ||
118 | } \ No newline at end of file | ||