comparison lwlink/objdump.c @ 378:1c31e9005ff7

Brought forward lwlink, lwar, and lwobjdump along with some misc junk
author lost@starbug
date Mon, 26 Apr 2010 19:30:44 -0600
parents old-trunk/lwlink/objdump.c@eb230fa7d28e
children a741d2e4869f
comparison
equal deleted inserted replaced
377:55ed7d06b136 378:1c31e9005ff7
1 /*
2 objdump.c
3 Copyright © 2009 William Astle
4
5 This file is part of LWLINK
6
7 LWLINK is free software: you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation, either version 3 of the License, or (at your option) any later
10 version.
11
12 This program is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 more details.
16
17 You should have received a copy of the GNU General Public License along with
18 this program. If not, see <http://www.gnu.org/licenses/>.
19
20
21 A standalone program to dump an object file in a text form to stdout
22
23 */
24 #include <config.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27
28 #include "util.h"
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 void read_lwobj16v0(unsigned char *filedata, long filesize);
35 char *program_name;
36
37 /*
38 The logic of reading the entire file into memory is simple. All the symbol
39 names in the file are NUL terminated strings and can be used directly without
40 making additional copies.
41 */
42 int main(int argc, char **argv)
43 {
44 int i;
45 long size;
46 FILE *f;
47 long bread;
48 unsigned char *filedata;
49
50 program_name = argv[0];
51 if (argc != 2)
52 {
53 fprintf(stderr, "Must specify exactly one input file.\n");
54 exit(1);
55 }
56
57 f = fopen(argv[1], "rb");
58 if (!f)
59 {
60 fprintf(stderr, "Can't open file %s:", argv[1]);
61 perror("");
62 exit(1);
63 }
64 fseek(f, 0, SEEK_END);
65 size = ftell(f);
66 rewind(f);
67
68 filedata = lw_malloc(size);
69
70 bread = fread(filedata, 1, size, f);
71 if (bread < size)
72 {
73 fprintf(stderr, "Short read on file %s (%ld/%ld):", argv[1], bread, size);
74 perror("");
75 exit(1);
76 }
77
78 fclose(f);
79
80 if (!memcmp(filedata, "LWOBJ16", 8))
81 {
82 // read v0 LWOBJ16 file
83 read_lwobj16v0(filedata, size);
84 }
85 else
86 {
87 fprintf(stderr, "%s: unknown file format\n", argv[1]);
88 exit(1);
89 }
90 exit(0);
91 }
92
93 // this macro is used to bail out if we run off the end of the file data
94 // while parsing - it keeps the code below cleaner
95 #define NEXTBYTE() do { cc++; if (cc > filesize) { fprintf(stderr, "***invalid file format\n"); exit(1); } } while (0)
96 // this macro is used to refer to the current byte in the stream
97 #define CURBYTE() (filedata[cc < filesize ? cc : filesize - 1])
98 // this one will leave the input pointer past the trailing NUL
99 #define CURSTR() read_lwobj16v0_str(&cc, &filedata, filesize)
100 unsigned char *read_lwobj16v0_str(long *cc1, unsigned char **filedata1, long filesize)
101 {
102 int cc = *cc1;
103 unsigned char *filedata = *filedata1;
104 unsigned char *fp;
105 fp = &CURBYTE();
106 while (CURBYTE())
107 NEXTBYTE();
108 NEXTBYTE();
109 *cc1 = cc;
110 *filedata1 = filedata;
111 return fp;
112 }
113 // the function below can be switched to dealing with data coming from a
114 // source other than an in-memory byte pool by adjusting the input data
115 // in "fn" and the above two macros
116 void read_lwobj16v0(unsigned char *filedata, long filesize)
117 {
118 unsigned char *fp;
119 long cc;
120 int val;
121 int bss;
122
123 static char *opernames[] = {
124 "?",
125 "PLUS",
126 "MINUS",
127 "TIMES",
128 "DIVIDE",
129 "MOD",
130 "INTDIV",
131 "BWAND",
132 "BWOR",
133 "BWXOR",
134 "AND",
135 "OR",
136 "NEG",
137 "COM"
138 };
139 static const int numopers = 13;
140
141 // start reading *after* the magic number
142 cc = 8;
143
144 while (1)
145 {
146 bss = 0;
147
148 // bail out if no more sections
149 if (!(CURBYTE()))
150 break;
151
152 fp = CURSTR();
153
154 printf("SECTION %s\n", fp);
155
156 // read flags
157 while (CURBYTE())
158 {
159 switch (CURBYTE())
160 {
161 case 0x01:
162 printf(" FLAG: BSS\n");
163 bss = 1;
164 break;
165
166 default:
167 printf(" FLAG: %02X (unknown)\n", CURBYTE());
168 break;
169 }
170 NEXTBYTE();
171 }
172 // skip NUL terminating flags
173 NEXTBYTE();
174
175 printf(" Local symbols:\n");
176 // now parse the local symbol table
177 while (CURBYTE())
178 {
179 fp = CURSTR();
180
181 // fp is the symbol name
182 val = (CURBYTE()) << 8;
183 NEXTBYTE();
184 val |= (CURBYTE());
185 NEXTBYTE();
186 // val is now the symbol value
187
188 printf(" %s=%04X\n", fp, val);
189
190 }
191 // skip terminating NUL
192 NEXTBYTE();
193
194 printf(" Exported symbols\n");
195
196 // now parse the exported symbol table
197 while (CURBYTE())
198 {
199 fp = CURSTR();
200
201 // fp is the symbol name
202 val = (CURBYTE()) << 8;
203 NEXTBYTE();
204 val |= (CURBYTE());
205 NEXTBYTE();
206 // val is now the symbol value
207
208 printf(" %s=%04X\n", fp, val);
209 }
210 // skip terminating NUL
211 NEXTBYTE();
212
213 // now parse the incomplete references and make a list of
214 // external references that need resolution
215 printf(" Incomplete references\n");
216 while (CURBYTE())
217 {
218 printf(" (");
219 // parse the expression
220 while (CURBYTE())
221 {
222 int tt = CURBYTE();
223 NEXTBYTE();
224 switch (tt)
225 {
226 case 0x01:
227 // 16 bit integer
228 tt = CURBYTE() << 8;
229 NEXTBYTE();
230 tt |= CURBYTE();
231 NEXTBYTE();
232 // normalize for negatives...
233 if (tt > 0x7fff)
234 tt -= 0x10000;
235 printf(" I16=%d", tt);
236 break;
237
238 case 0x02:
239 // external symbol reference
240 printf(" ES=%s", CURSTR());
241 break;
242
243 case 0x03:
244 // internal symbol reference
245 printf(" IS=%s", CURSTR());
246 break;
247
248 case 0x04:
249 // operator
250 if (CURBYTE() > 0 && CURBYTE() <= numopers)
251 printf(" OP=%s", opernames[CURBYTE()]);
252 else
253 printf(" OP=?");
254 NEXTBYTE();
255 break;
256
257 case 0x05:
258 // section base reference (NULL internal reference is
259 // the section base address
260 printf(" SB");
261 break;
262
263 case 0xFF:
264 // section flags
265 printf(" FLAGS=%02X", CURBYTE());
266 NEXTBYTE();
267 break;
268
269 default:
270 printf(" ERR");
271 }
272 }
273 // skip the NUL
274 NEXTBYTE();
275
276 // fetch the offset
277 val = CURBYTE() << 8;
278 NEXTBYTE();
279 val |= CURBYTE() & 0xff;
280 NEXTBYTE();
281 printf(" ) @ %04X\n", val);
282 }
283 // skip the NUL terminating the relocations
284 NEXTBYTE();
285
286 // now set code location and size and verify that the file
287 // contains data going to the end of the code (if !SECTION_BSS)
288 val = CURBYTE() << 8;
289 NEXTBYTE();
290 val |= CURBYTE();
291 NEXTBYTE();
292
293 printf(" CODE %04X bytes", val);
294
295 // skip the code if we're not in a BSS section
296 if (!bss)
297 {
298 int i;
299 for (i = 0; i < val; i++)
300 {
301 if (! (i % 16))
302 {
303 printf("\n %04X ", i);
304 }
305 printf("%02X", CURBYTE());
306 NEXTBYTE();
307 }
308 }
309 printf("\n");
310 }
311 }