Mercurial > repos > blastem
comparison dis.c @ 631:de6f00204fa2
Add support for disassembling VOS program modules
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 11 Oct 2014 20:32:17 -0700 |
parents | 140af5509ce7 |
children | 80e111b48d4b |
comparison
equal
deleted
inserted
replaced
630:47123183c336 | 631:de6f00204fa2 |
---|---|
1 /* | 1 /* |
2 Copyright 2013 Michael Pavone | 2 Copyright 2013 Michael Pavone |
3 This file is part of BlastEm. | 3 This file is part of BlastEm. |
4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. | 4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. |
5 */ | 5 */ |
6 #include "68kinst.h" | 6 #include "68kinst.h" |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 #include <stdlib.h> | 8 #include <stdlib.h> |
9 #include <string.h> | |
10 #include "vos_program_module.h" | |
11 #include "tern.h" | |
9 | 12 |
10 uint8_t visited[(16*1024*1024)/16]; | 13 uint8_t visited[(16*1024*1024)/16]; |
11 uint8_t label[(16*1024*1024)/8]; | 14 uint8_t label[(16*1024*1024)/8]; |
12 | 15 |
13 void visit(uint32_t address) | 16 void visit(uint32_t address) |
31 | 34 |
32 uint8_t is_label(uint32_t address) | 35 uint8_t is_label(uint32_t address) |
33 { | 36 { |
34 address &= 0xFFFFFF; | 37 address &= 0xFFFFFF; |
35 return label[address/16] & (1 << (address % 8)); | 38 return label[address/16] & (1 << (address % 8)); |
39 } | |
40 | |
41 typedef struct { | |
42 uint32_t num_labels; | |
43 uint32_t storage; | |
44 char *labels[]; | |
45 } label_names; | |
46 | |
47 tern_node * add_label(tern_node * head, char * name, uint32_t address) | |
48 { | |
49 char key[MAX_INT_KEY_SIZE]; | |
50 address &= 0xFFFFFF; | |
51 reference(address); | |
52 tern_int_key(address, key); | |
53 label_names * names = tern_find_ptr(head, key); | |
54 if (names) | |
55 { | |
56 if (names->num_labels == names->storage) | |
57 { | |
58 names->storage = names->storage + (names->storage >> 1); | |
59 names = realloc(names, sizeof(label_names) + names->storage * sizeof(char *)); | |
60 } | |
61 } else { | |
62 names = malloc(sizeof(label_names) + 4 * sizeof(char *)); | |
63 names->num_labels = 0; | |
64 names->storage = 4; | |
65 head = tern_insert_ptr(head, key, names); | |
66 } | |
67 names->labels[names->num_labels++] = strdup(name); | |
68 return head; | |
36 } | 69 } |
37 | 70 |
38 typedef struct deferred { | 71 typedef struct deferred { |
39 uint32_t address; | 72 uint32_t address; |
40 struct deferred *next; | 73 struct deferred *next; |
64 reference(op->params.immed); | 97 reference(op->params.immed); |
65 break; | 98 break; |
66 } | 99 } |
67 } | 100 } |
68 | 101 |
69 uint8_t labels = 0; | |
70 uint8_t addr = 0; | |
71 uint8_t only = 0; | |
72 | |
73 int main(int argc, char ** argv) | 102 int main(int argc, char ** argv) |
74 { | 103 { |
75 long filesize; | 104 long filesize; |
76 unsigned short *filebuf; | 105 unsigned short *filebuf; |
77 char disbuf[1024]; | 106 char disbuf[1024]; |
78 m68kinst instbuf; | 107 m68kinst instbuf; |
79 unsigned short * cur; | 108 unsigned short * cur; |
80 FILE * f = fopen(argv[1], "rb"); | |
81 fseek(f, 0, SEEK_END); | |
82 filesize = ftell(f); | |
83 fseek(f, 0, SEEK_SET); | |
84 filebuf = malloc(filesize); | |
85 fread(filebuf, 2, filesize/2, f); | |
86 fclose(f); | |
87 deferred *def = NULL, *tmpd; | 109 deferred *def = NULL, *tmpd; |
110 | |
111 uint8_t labels = 0, addr = 0, only = 0, vos = 0; | |
112 | |
88 for(uint8_t opt = 2; opt < argc; ++opt) { | 113 for(uint8_t opt = 2; opt < argc; ++opt) { |
89 if (argv[opt][0] == '-') { | 114 if (argv[opt][0] == '-') { |
90 FILE * address_log; | 115 FILE * address_log; |
91 switch (argv[opt][1]) | 116 switch (argv[opt][1]) |
92 { | 117 { |
97 addr = 1; | 122 addr = 1; |
98 break; | 123 break; |
99 case 'o': | 124 case 'o': |
100 only = 1; | 125 only = 1; |
101 break; | 126 break; |
127 case 'v': | |
128 vos = 1; | |
129 break; | |
102 case 'f': | 130 case 'f': |
103 opt++; | 131 opt++; |
104 if (opt >= argc) { | 132 if (opt >= argc) { |
105 fputs("-f must be followed by a filename\n", stderr); | 133 fputs("-f must be followed by a filename\n", stderr); |
106 exit(1); | 134 exit(1); |
124 uint32_t address = strtol(argv[opt], NULL, 16); | 152 uint32_t address = strtol(argv[opt], NULL, 16); |
125 def = defer(address, def); | 153 def = defer(address, def); |
126 reference(address); | 154 reference(address); |
127 } | 155 } |
128 } | 156 } |
129 for(cur = filebuf; cur - filebuf < (filesize/2); ++cur) | 157 |
158 FILE * f = fopen(argv[1], "rb"); | |
159 fseek(f, 0, SEEK_END); | |
160 filesize = ftell(f); | |
161 fseek(f, 0, SEEK_SET); | |
162 | |
163 tern_node * named_labels = NULL; | |
164 char int_key[MAX_INT_KEY_SIZE]; | |
165 uint32_t address_off, address_end; | |
166 if (vos) | |
130 { | 167 { |
131 *cur = (*cur >> 8) | (*cur << 8); | 168 vos_program_module header; |
132 } | 169 vos_read_header(f, &header); |
133 uint32_t start = filebuf[2] << 16 | filebuf[3], tmp_addr; | 170 vos_read_alloc_module_map(f, &header); |
134 uint32_t int_2 = filebuf[0x68/2] << 16 | filebuf[0x6A/2]; | 171 address_off = header.user_boundary; |
135 uint32_t int_4 = filebuf[0x70/2] << 16 | filebuf[0x72/2]; | 172 address_end = address_off + filesize - 0x1000; |
136 uint32_t int_6 = filebuf[0x78/2] << 16 | filebuf[0x7A/2]; | 173 def = defer(header.main_entry_link.code_address, def); |
174 named_labels = add_label(named_labels, "main_entry_link", header.main_entry_link.code_address); | |
175 for (int i = 0; i < header.n_modules; i++) | |
176 { | |
177 def = defer(header.module_map_entries[i].code_address, def); | |
178 named_labels = add_label(named_labels, header.module_map_entries[i].name.str, header.module_map_entries[i].code_address); | |
179 } | |
180 fseek(f, 0x1000, SEEK_SET); | |
181 filebuf = malloc(filesize - 0x1000); | |
182 if (fread(filebuf, 2, (filesize - 0x1000)/2, f) != (filesize - 0x1000)/2) | |
183 { | |
184 fprintf(stderr, "Failure while reading file %s\n", argv[1]); | |
185 } | |
186 fclose(f); | |
187 for(cur = filebuf; cur - filebuf < ((filesize - 0x1000)/2); ++cur) | |
188 { | |
189 *cur = (*cur >> 8) | (*cur << 8); | |
190 } | |
191 } else { | |
192 address_off = 0; | |
193 address_end = filesize; | |
194 filebuf = malloc(filesize); | |
195 if (fread(filebuf, 2, filesize/2, f) != filesize/2) | |
196 { | |
197 fprintf(stderr, "Failure while reading file %s\n", argv[1]); | |
198 } | |
199 fclose(f); | |
200 for(cur = filebuf; cur - filebuf < (filesize/2); ++cur) | |
201 { | |
202 *cur = (*cur >> 8) | (*cur << 8); | |
203 } | |
204 uint32_t start = filebuf[2] << 16 | filebuf[3]; | |
205 uint32_t int_2 = filebuf[0x68/2] << 16 | filebuf[0x6A/2]; | |
206 uint32_t int_4 = filebuf[0x70/2] << 16 | filebuf[0x72/2]; | |
207 uint32_t int_6 = filebuf[0x78/2] << 16 | filebuf[0x7A/2]; | |
208 named_labels = add_label(named_labels, "start", start); | |
209 named_labels = add_label(named_labels, "int_2", int_2); | |
210 named_labels = add_label(named_labels, "int_4", int_4); | |
211 named_labels = add_label(named_labels, "int_6", int_6); | |
212 if (!def || !only) { | |
213 def = defer(start, def); | |
214 def = defer(int_2, def); | |
215 def = defer(int_4, def); | |
216 def = defer(int_6, def); | |
217 } | |
218 } | |
137 uint16_t *encoded, *next; | 219 uint16_t *encoded, *next; |
138 uint32_t size; | 220 uint32_t size, tmp_addr; |
139 if (!def || !only) { | |
140 def = defer(start, def); | |
141 def = defer(int_2, def); | |
142 def = defer(int_4, def); | |
143 def = defer(int_6, def); | |
144 } | |
145 uint32_t address; | 221 uint32_t address; |
146 while(def) { | 222 while(def) { |
147 do { | 223 do { |
148 encoded = NULL; | 224 encoded = NULL; |
149 address = def->address; | 225 address = def->address; |
216 printf("ADR_%X equ $%X\n", address, address); | 292 printf("ADR_%X equ $%X\n", address, address); |
217 } | 293 } |
218 } | 294 } |
219 puts(""); | 295 puts(""); |
220 } | 296 } |
221 for (address = 0; address < filesize; address+=2) { | 297 for (address = address_off; address < filesize; address+=2) { |
222 if (is_visited(address)) { | 298 if (is_visited(address)) { |
223 encoded = filebuf + address/2; | 299 encoded = filebuf + (address-address_off)/2; |
224 m68k_decode(encoded, &instbuf, address); | 300 m68k_decode(encoded, &instbuf, address); |
225 if (labels) { | 301 if (labels) { |
226 m68k_disasm_labels(&instbuf, disbuf); | 302 m68k_disasm_labels(&instbuf, disbuf); |
227 if (address == start) { | 303 char keybuf[MAX_INT_KEY_SIZE]; |
228 puts("start:"); | 304 label_names * names = tern_find_ptr(named_labels, tern_int_key(address, keybuf)); |
229 } | 305 if (names) |
230 if(address == int_2) { | 306 { |
231 puts("int_2:"); | 307 for (int i = 0; i < names->num_labels; i++) |
232 } | 308 { |
233 if(address == int_4) { | 309 printf("%s:\n", names->labels[i]); |
234 puts("int_4:"); | 310 } |
235 } | 311 } else if (is_label(instbuf.address)) { |
236 if(address == int_6) { | |
237 puts("int_6:"); | |
238 } | |
239 if (is_label(instbuf.address)) { | |
240 printf("ADR_%X:\n", instbuf.address); | 312 printf("ADR_%X:\n", instbuf.address); |
241 } | 313 } |
242 if (addr) { | 314 if (addr) { |
243 printf("\t%s\t;%X\n", disbuf, instbuf.address); | 315 printf("\t%s\t;%X\n", disbuf, instbuf.address); |
244 } else { | 316 } else { |