main.c - scc - simple c99 compiler
(HTM) git clone git://git.simple-cc.org/scc
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
main.c (7784B)
---
1 #include <ctype.h>
2 #include <errno.h>
3 #include <limits.h>
4 #include <stdarg.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <time.h>
9
10 #include <scc/ar.h>
11 #include <scc/arg.h>
12 #include <scc/scc.h>
13 #include <scc/mach.h>
14
15 #include "objdump.h"
16
17 struct binops {
18 void (*dumpsyms)(Obj *);
19 void (*dumpsecs)(Obj *);
20 void (*dumpfhdr)(Obj *, unsigned long long *, Flags *);
21 int (*hasrelloc)(Obj *, Section *);
22 };
23
24 int tflag, fflag, hflag, pflag, aflag, rflag, sflag;
25 char *argv0;
26
27 static int status, nsecs;
28 static char *filename, *membname, **secs;
29
30 static struct binops *op, ops[NFORMATS] = {
31 [COFF32] = {
32 .dumpsyms = coff32syms,
33 .dumpsecs = coff32scns,
34 .dumpfhdr = coff32fhdr,
35 .hasrelloc = coff32hasrelloc,
36 },
37 [ELF] = {
38 .dumpsyms = elfsyms,
39 .dumpsecs = elfscns,
40 .dumpfhdr = elffhdr,
41 .hasrelloc = elfhasrelloc,
42 },
43 };
44
45 void
46 error(char *fmt, ...)
47 {
48 va_list va;
49
50 va_start(va, fmt);
51 fprintf(stderr, "objdump: %s: ", filename);
52 if (membname)
53 fprintf(stderr, "%s: ", membname);
54 vfprintf(stderr, fmt, va);
55 putc('\n', stderr);
56 va_end(va);
57
58 status = EXIT_FAILURE;
59 }
60
61 void
62 setflag(Flags *f, int cond, int flag)
63 {
64 if (cond)
65 f->flags |= 1 << flag;
66 }
67
68 void
69 printflags(Flags *f)
70 {
71 int i, first;
72 unsigned long flags = f->flags;
73
74 first = 1;
75 for (i = 0; i < f->nr; i++) {
76 if (flags & 1) {
77 if (!first)
78 fputs(", ", stdout);
79 first = 0;
80 fputs(f->text[i], stdout);
81 }
82 flags >>= 1;
83 }
84
85 putchar('\n');
86 }
87
88 static void
89 dumpfhdr(Obj *obj, char *fmt)
90 {
91 unsigned long long start = 0;
92 static Flags f = {
93 .nr = NR_FILE_FLAGS,
94 .text = {
95 [HAS_RELOC] = "HAS_RELOC",
96 [EXEC_P] = "EXEC_P",
97 [HAS_LINENO] = "HAS_LINENO",
98 [HAS_DEBUG] = "HAS_DEBUG",
99 [HAS_SYMS] = "HAS_SYMS",
100 [HAS_LOCALS] = "HAS_LOCALS",
101 [DYNAMIC] = "DYNAMIC",
102 }
103 };
104
105 printf("architecture: %s, flags: 0x%08x\n",
106 strchr(fmt, '-') + 1,
107 obj->type);
108
109 f.flags = 0;
110
111 (*op->dumpfhdr)(obj, &start, &f);
112 printflags(&f);
113 printf("start address 0x%08llx\n", start);
114 }
115
116 static int
117 logb2(unsigned val)
118 {
119 int n;
120
121 if (val == 0)
122 return 0;
123
124 for (n = 0; (val & 1) == 0; n++)
125 val >>= 1;
126 return n;
127 }
128
129 int
130 selected(char *secname)
131 {
132 int i;
133
134 if (nsecs == 0)
135 return 1;
136
137 for (i = 0; i < nsecs; i++) {
138 if (strcmp(secname, secs[i]) == 0)
139 return 1;
140 }
141
142 return 0;
143 }
144
145 static void
146 dumpscns(Obj *obj)
147 {
148 int i, debug;
149 unsigned flags;
150 Section sec;
151 static Flags f = {
152 .nr = NR_SEC_FLAGS,
153 .text = {
154 [SEC_HAS_CONTENTS] = "CONTENTS",
155 [SEC_ALLOC] = "ALLOC",
156 [SEC_LOAD] = "LOAD",
157 [SEC_RELOC] = "RELOC",
158 [SEC_READONLY] = "READONLY",
159 [SEC_CODE] = "CODE",
160 [SEC_DATA] = "DATA",
161 [SEC_DEBUGGING] = "DEBUGGING",
162 }
163 };
164
165 puts("Sections:");
166 puts("Idx Name Size VMA LMA File off Algn");
167 for (i = 0; getsec(obj, &i, &sec); i++) {
168 if (!selected(sec.name))
169 continue;
170
171 printf("%3d %-13s %08llx %08llx %08llx %08llx 2**%d\n",
172 sec.index,
173 sec.name,
174 sec.size,
175 sec.base,
176 sec.load,
177 sec.offset,
178 logb2(sec.align));
179
180 f.flags = 0;
181 flags = sec.flags;
182 debug = sec.type == 'N';
183 setflag(&f, flags & SALLOC, SEC_ALLOC);
184 setflag(&f, flags & SLOAD, SEC_LOAD);
185 setflag(&f, (*op->hasrelloc)(obj, &sec), SEC_RELOC);
186 setflag(&f, (flags & SWRITE) == 0 && !debug, SEC_READONLY);
187 setflag(&f, flags & SEXEC, SEC_CODE);
188 setflag(&f, (flags & (SEXEC|SLOAD)) == SLOAD, SEC_DATA);
189 setflag(&f, debug, SEC_DEBUGGING);
190 setflag(&f, (flags & SALLOC) && sec.size > 0, SEC_HAS_CONTENTS);
191 fputs(" ", stdout);
192 printflags(&f);
193 }
194
195 if (!pflag)
196 return;
197 (*op->dumpsecs)(obj);
198 }
199
200 static void
201 dumpdata(Obj *obj, FILE *fp)
202 {
203 int i, j, c;
204 char buf[19];
205 Section sec;
206 unsigned long long n;
207
208 buf[0] = '|';
209 buf[17] = '|';
210 buf[18] = '\0';
211
212 for (i = 0; getsec(obj, &i, &sec); i++) {
213 if (!selected(sec.name))
214 continue;
215 if ((sec.flags & SALLOC) == 0 || sec.size == 0)
216 continue;
217
218 printf("Contents of section %s\n", sec.name);
219
220 if (!objpos(obj, fp, sec.offset))
221 goto errno_error;
222
223 for (n = 0; n < sec.size; ) {
224 memset(buf+1, '.', 16);
225 printf(" %04llx ", sec.base + n);
226 for (j = 0; j < 16 && n < sec.size; j++, n++) {
227 if ((c = getc(fp)) == EOF) {
228 if (ferror(fp))
229 goto errno_error;
230 error("section %s: end of file found before end of section",
231 sec.name);
232 goto next_section;
233 }
234
235 if (c < CHAR_MAX && c > 0 && isprint(c))
236 buf[j] = c;
237
238 printf("%02x ", (unsigned) c & 0xFF);
239 }
240
241 for ( ; j < 16; j++)
242 fputs(" ", stdout);
243 puts(buf);
244 }
245
246 next_section:
247 continue;
248
249 errno_error:
250 error("section %s: %s", sec.name, strerror(errno));
251 }
252 }
253
254
255 static void
256 dumpobj(FILE *fp, int type, char *fmt)
257 {
258 int id;
259 Obj *obj;
260
261 printf("\n%s", filename);
262 if (membname)
263 printf("(%s)", membname);
264 printf(":\tfile format %s\n", fmt);
265
266 if ((obj = newobj(type)) == NULL) {
267 error("failed object allocation");
268 return;
269 }
270
271 if (readobj(obj, fp) < 0) {
272 error("object file corrupted");
273 goto err;
274 }
275
276 id = objfmt(obj);
277 if (id >= NFORMATS) {
278 error("unknown symbol binary format");
279 return;
280 }
281 op = &ops[id];
282
283 if (fflag)
284 dumpfhdr(obj, fmt);
285 if (hflag)
286 dumpscns(obj);
287 if (sflag)
288 dumpdata(obj, fp);
289 if (tflag)
290 (*op->dumpsyms)(obj);
291
292 err:
293 delobj(obj);
294 }
295
296 static void
297 dumprights(unsigned r)
298 {
299 putchar((r & 4) ? 'r' : '-');
300 putchar((r & 2) ? 'w' : '-');
301 putchar((r & 1) ? 'x' : '-');
302 }
303
304 static void
305 dumpar(char *fname, struct ar_hdr *hdr, char *fmt)
306 {
307 time_t t;
308 int n;
309 struct tm *tm;
310 char buf[60];
311 unsigned long mode;
312
313 printf("%s: file format %s\n", fname, fmt);
314
315 mode = strtol(hdr->ar_mode, NULL, 8);
316 dumprights((mode >> 6) & 7);
317 dumprights((mode >> 3) & 7);
318 dumprights(mode & 7);
319
320 t = fromepoch(atoll(hdr->ar_date));
321 strftime(buf, sizeof(buf), "%c", gmtime(&t));
322 printf(" %d/%d %lld %s %s\n\n",
323 atoi(hdr->ar_uid),
324 atoi(hdr->ar_gid),
325 atoll(hdr->ar_size),
326 buf,
327 fname);
328 }
329
330 static void
331 dumplib(FILE *fp)
332 {
333 int t;
334 char *fmt;
335 long off, cur;
336 struct ar_hdr hdr;
337 char memb[SARNAM+1];
338
339 for (;;) {
340 cur = ftell(fp);
341
342 off = armember(fp, memb, &hdr);
343 switch (off) {
344 case -1:
345 error("library corrupted");
346 if (ferror(fp))
347 error(strerror(errno));
348 case 0:
349 return;
350 default:
351 membname = memb;
352 if ((t = objprobe(fp, &fmt)) != -1) {
353 if (aflag)
354 dumpar(memb, &hdr, fmt);
355 dumpobj(fp, t, fmt);
356 }
357 membname = NULL;
358 fseek(fp, cur, SEEK_SET);
359 fseek(fp, off, SEEK_CUR);
360 break;
361 }
362 }
363 }
364
365 static void
366 objdump(char *fname)
367 {
368 int t;
369 char *fmt;
370 FILE *fp;
371
372 membname = NULL;
373 filename = fname;
374 if ((fp = fopen(fname, "rb")) == NULL) {
375 error(strerror(errno));
376 return;
377 }
378
379 if ((t = objprobe(fp, &fmt)) != -1)
380 dumpobj(fp, t, fmt);
381 else if (archive(fp))
382 dumplib(fp);
383 else
384 error("bad format");
385
386 fclose(fp);
387 }
388
389 static void
390 usage(void)
391 {
392 fputs("usage: objdump [-afhpts][-j section] file...\n", stderr);
393 exit(EXIT_FAILURE);
394 }
395
396 int
397 main(int argc, char *argv[])
398 {
399 char *s;
400
401 ARGBEGIN {
402 case 'a':
403 aflag = 1;
404 break;
405 case 'f':
406 fflag = 1;
407 break;
408 case 'h':
409 hflag = 1;
410 break;
411 case 'p':
412 pflag = 1;
413 break;
414 case 's':
415 sflag = 1;
416 break;
417 case 't':
418 tflag = 1;
419 break;
420 case 'j':
421 s = EARGF(usage());
422 secs = xrealloc(secs, (nsecs + 1) * sizeof(char *));
423 secs[nsecs++] = s;
424 break;
425 default:
426 usage();
427 } ARGEND
428
429 if (!aflag && !fflag && !hflag
430 && !tflag && !sflag) {
431 fputs("objdump: At lest one of [afhts] flags must be used\n",
432 stderr);
433 usage();
434 }
435
436 if (argc == 0) {
437 objdump("a.out");
438 } else {
439 for ( ; *argv; ++argv)
440 objdump(*argv);
441 }
442
443 if (fflush(stdout)) {
444 fprintf(stderr,
445 "size: error writing in output:%s\n",
446 strerror(errno));
447 status = 1;
448 }
449
450 return status;
451 }