Commit | Line | Data |
---|---|---|
d20f480f SC |
1 | /* objdump.c -- dump information about an object file. |
2 | Copyright (C) 1990, 1991 Free Software Foundation, Inc. | |
2fa0b342 DHW |
3 | |
4 | This file is part of BFD, the Binary File Diddler. | |
5 | ||
6 | BFD is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
d20f480f | 8 | the Free Software Foundation; either version 2, or (at your option) |
2fa0b342 DHW |
9 | any later version. |
10 | ||
11 | BFD is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with BFD; see the file COPYING. If not, write to | |
18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
19 | ||
2fa0b342 DHW |
20 | /* |
21 | * Until there is other documentation, refer to the manual page dump(1) in | |
22 | * the system 5 program's reference manual | |
23 | */ | |
24 | ||
2fa0b342 | 25 | #include "bfd.h" |
d20f480f | 26 | #include "sysdep.h" |
2fa0b342 DHW |
27 | #include "getopt.h" |
28 | #include <stdio.h> | |
29 | #include <ctype.h> | |
30 | ||
bf661056 SC |
31 | |
32 | ||
aa0a709a | 33 | char *xmalloc (); |
2fa0b342 DHW |
34 | |
35 | char *default_target = NULL; /* default at runtime */ | |
36 | ||
37 | char *program_name = NULL; | |
38 | ||
39 | int dump_section_contents; /* -s */ | |
40 | int dump_section_headers; /* -h */ | |
41 | boolean dump_file_header; /* -f */ | |
42 | int dump_symtab; /* -t */ | |
43 | int dump_reloc_info; /* -r */ | |
44 | int dump_ar_hdrs; /* -a */ | |
aa0a709a SC |
45 | int with_line_numbers; /* -l */ |
46 | boolean disassemble; /* -d */ | |
47 | boolean info; /* -i */ | |
2fa0b342 DHW |
48 | char *only; |
49 | ||
50 | PROTO (void, display_file, (char *filename, char *target)); | |
aa0a709a SC |
51 | PROTO (void, dump_data, (bfd * abfd)); |
52 | PROTO (void, dump_relocs, (bfd * abfd)); | |
53 | PROTO (void, dump_symbols, (bfd * abfd)); | |
54 | PROTO (void, print_arelt_descr, (FILE *, bfd * abfd, boolean verbose)); | |
55 | \f | |
2fa0b342 DHW |
56 | |
57 | ||
58 | ||
59 | ||
60 | ||
61 | ||
aa0a709a SC |
62 | char *machine = (char *) NULL; |
63 | asymbol **syms; | |
64 | asymbol **syms2; | |
2fa0b342 DHW |
65 | |
66 | ||
67 | unsigned int storage; | |
68 | ||
69 | unsigned int symcount = 0; | |
70 | ||
71 | void | |
72 | usage () | |
73 | { | |
74 | fprintf (stderr, | |
aa0a709a | 75 | "usage: %s [-ahifdrtxsl] [-m machine] [-j section_name] obj ...\n", |
2fa0b342 DHW |
76 | program_name); |
77 | exit (1); | |
78 | } | |
79 | ||
aa0a709a SC |
80 | static struct option long_options[]= |
81 | { | |
82 | {"syms", no_argument, &dump_symtab, 1}, | |
83 | {"reloc", no_argument, &dump_reloc_info, 1}, | |
84 | {"header", no_argument, &dump_section_headers, 1}, | |
85 | {0, no_argument, 0, 0}}; | |
2fa0b342 DHW |
86 | |
87 | ||
88 | ||
89 | static void | |
aa0a709a SC |
90 | dump_headers (abfd) |
91 | bfd *abfd; | |
2fa0b342 DHW |
92 | { |
93 | asection *section; | |
aa0a709a | 94 | |
2fa0b342 DHW |
95 | for (section = abfd->sections; |
96 | section != (asection *) NULL; | |
aa0a709a SC |
97 | section = section->next) |
98 | { | |
99 | char *comma = ""; | |
100 | ||
2fa0b342 | 101 | #define PF(x,y) \ |
e779a58c JG |
102 | if (section->flags & x) { printf("%s%s",comma,y); comma = ", "; } |
103 | ||
104 | ||
aa0a709a SC |
105 | printf ("SECTION %d [%s]\t: size %08x", |
106 | section->index, | |
107 | section->name, | |
108 | (unsigned) bfd_get_section_size_before_reloc (section)); | |
109 | printf (" vma "); | |
110 | printf_vma (section->vma); | |
111 | printf (" align 2**%u\n ", | |
112 | section->alignment_power); | |
113 | PF (SEC_ALLOC, "ALLOC"); | |
114 | PF (SEC_CONSTRUCTOR, "CONSTRUCTOR"); | |
115 | PF (SEC_CONSTRUCTOR_TEXT, "CONSTRUCTOR TEXT"); | |
116 | PF (SEC_CONSTRUCTOR_DATA, "CONSTRUCTOR DATA"); | |
117 | PF (SEC_CONSTRUCTOR_BSS, "CONSTRUCTOR BSS"); | |
118 | PF (SEC_LOAD, "LOAD"); | |
119 | PF (SEC_RELOC, "RELOC"); | |
120 | PF (SEC_BALIGN, "BALIGN"); | |
121 | PF (SEC_READONLY, "READONLY"); | |
122 | PF (SEC_CODE, "CODE"); | |
123 | PF (SEC_DATA, "DATA"); | |
124 | PF (SEC_ROM, "ROM"); | |
125 | printf ("\n"); | |
2fa0b342 | 126 | #undef PF |
aa0a709a | 127 | } |
2fa0b342 DHW |
128 | } |
129 | ||
130 | static asymbol ** | |
aa0a709a SC |
131 | DEFUN (slurp_symtab, (abfd), |
132 | bfd * abfd) | |
2fa0b342 | 133 | { |
aa0a709a | 134 | asymbol **sy = (asymbol **) NULL; |
2fa0b342 | 135 | |
aa0a709a SC |
136 | if (!(bfd_get_file_flags (abfd) & HAS_SYMS)) |
137 | { | |
138 | (void) printf ("No symbols in \"%s\".\n", bfd_get_filename (abfd)); | |
139 | return (NULL); | |
140 | } | |
141 | ||
142 | storage = get_symtab_upper_bound (abfd); | |
143 | if (storage) | |
144 | { | |
145 | sy = (asymbol **) malloc (storage); | |
146 | if (sy == NULL) | |
147 | { | |
148 | fprintf (stderr, "%s: out of memory.\n", program_name); | |
149 | exit (1); | |
d20f480f | 150 | } |
aa0a709a SC |
151 | } |
152 | symcount = bfd_canonicalize_symtab (abfd, sy); | |
153 | return sy; | |
2fa0b342 | 154 | } |
aa0a709a | 155 | |
2fa0b342 | 156 | /* Sort symbols into value order */ |
aa0a709a SC |
157 | static int |
158 | comp (ap, bp) | |
159 | asymbol **ap; | |
160 | asymbol **bp; | |
2fa0b342 DHW |
161 | { |
162 | asymbol *a = *ap; | |
163 | asymbol *b = *bp; | |
164 | int diff; | |
165 | ||
aa0a709a | 166 | if (a->name == (char *) NULL || (a->flags & (BSF_DEBUGGING))) |
2fa0b342 | 167 | a->the_bfd = 0; |
aa0a709a SC |
168 | if (b->name == (char *) NULL || (b->flags & (BSF_DEBUGGING))) |
169 | b->the_bfd = 0; | |
2fa0b342 DHW |
170 | |
171 | diff = a->the_bfd - b->the_bfd; | |
aa0a709a SC |
172 | if (diff) |
173 | { | |
174 | return -diff; | |
175 | } | |
2fa0b342 | 176 | diff = a->value - b->value; |
aa0a709a SC |
177 | if (diff) |
178 | { | |
179 | return diff; | |
180 | } | |
181 | return a->section - b->section; | |
2fa0b342 DHW |
182 | } |
183 | ||
184 | /* Print the supplied address symbolically if possible */ | |
185 | void | |
aa0a709a SC |
186 | print_address (vma, stream) |
187 | bfd_vma vma; | |
188 | FILE *stream; | |
2fa0b342 DHW |
189 | { |
190 | /* Perform a binary search looking for the closest symbol to | |
191 | the required value */ | |
192 | ||
193 | unsigned int min = 0; | |
194 | unsigned int max = symcount; | |
195 | ||
196 | unsigned int thisplace = 1; | |
aa0a709a | 197 | unsigned int oldthisplace; |
2fa0b342 DHW |
198 | |
199 | int vardiff; | |
2fa0b342 | 200 | |
aa0a709a SC |
201 | if (symcount == 0) |
202 | { | |
203 | fprintf_vma (stream, vma); | |
2fa0b342 | 204 | } |
aa0a709a SC |
205 | else |
206 | { | |
207 | while (true) | |
208 | { | |
209 | oldthisplace = thisplace; | |
210 | thisplace = (max + min) / 2; | |
211 | if (thisplace == oldthisplace) | |
212 | break; | |
213 | vardiff = syms[thisplace]->value - vma; | |
214 | ||
215 | if (vardiff) | |
216 | { | |
217 | if (vardiff > 0) | |
218 | { | |
219 | max = thisplace; | |
220 | } | |
221 | else | |
222 | { | |
223 | min = thisplace; | |
224 | } | |
225 | } | |
226 | else | |
227 | { | |
228 | /* Totally awesome! the exact right symbol */ | |
229 | CONST char *match_name = syms[thisplace]->name; | |
230 | int sym_len = strlen (match_name); | |
231 | ||
232 | /* Avoid "filename.o" as a match */ | |
233 | if (sym_len > 2 | |
234 | && match_name[sym_len - 2] == '.' | |
235 | && match_name[sym_len - 1] == 'o' | |
236 | && thisplace + 1 < symcount | |
237 | && syms[thisplace + 1]->value == vma) | |
238 | match_name = syms[thisplace + 1]->name; | |
239 | /* Totally awesome! the exact right symbol */ | |
240 | fprintf_vma (stream, vma); | |
241 | fprintf (stream, " (%s+)0000", syms[thisplace]->name); | |
242 | return; | |
243 | } | |
244 | } | |
245 | /* We've run out of places to look, print the symbol before this one | |
246 | see if this or the symbol before describes this location the best */ | |
fc5d6074 | 247 | |
aa0a709a SC |
248 | if (thisplace != 0) |
249 | { | |
250 | if (syms[thisplace - 1]->value - vma > | |
251 | syms[thisplace]->value - vma) | |
252 | { | |
253 | /* Previous symbol is in correct section and is closer */ | |
254 | thisplace--; | |
255 | } | |
256 | } | |
fc5d6074 | 257 | |
aa0a709a SC |
258 | fprintf_vma (stream, vma); |
259 | if (syms[thisplace]->value > vma) | |
260 | { | |
261 | fprintf (stream, " (%s-)", syms[thisplace]->name); | |
262 | fprintf (stream, "%04x", syms[thisplace]->value - vma); | |
263 | } | |
264 | else | |
265 | { | |
266 | fprintf (stream, " (%s+)", syms[thisplace]->name); | |
267 | fprintf (stream, "%04x", vma - syms[thisplace]->value); | |
268 | } | |
2fa0b342 | 269 | } |
2fa0b342 DHW |
270 | } |
271 | ||
272 | void | |
aa0a709a SC |
273 | disassemble_data (abfd) |
274 | bfd *abfd; | |
2fa0b342 DHW |
275 | { |
276 | bfd_byte *data = NULL; | |
aa0a709a | 277 | bfd_arch_info_type *info; |
fc5d6074 SC |
278 | bfd_size_type datasize = 0; |
279 | bfd_size_type i; | |
aa0a709a SC |
280 | unsigned int (*print) ()= 0; |
281 | unsigned int print_insn_m68k (); | |
282 | unsigned int print_insn_a29k (); | |
283 | unsigned int print_insn_i960 (); | |
284 | unsigned int print_insn_sparc (); | |
285 | unsigned int print_insn_i386 (); | |
286 | unsigned int print_insn_h8300 (); | |
2fa0b342 | 287 | enum bfd_architecture a; |
d20f480f | 288 | |
2fa0b342 | 289 | asection *section; |
aa0a709a | 290 | |
2fa0b342 | 291 | /* Replace symbol section relative values with abs values */ |
96d7950b | 292 | boolean done_dot = false; |
aa0a709a SC |
293 | |
294 | for (i = 0; i < symcount; i++) | |
295 | { | |
2fa0b342 | 296 | syms[i]->value += syms[i]->section->vma; |
aa0a709a | 297 | } |
2fa0b342 DHW |
298 | |
299 | /* We keep a copy of the symbols in the original order */ | |
aa0a709a | 300 | syms2 = slurp_symtab (abfd); |
2fa0b342 DHW |
301 | |
302 | /* Sort the symbols into section and symbol order */ | |
aa0a709a | 303 | (void) qsort (syms, symcount, sizeof (asymbol *), comp); |
2fa0b342 DHW |
304 | |
305 | /* Find the first useless symbol */ | |
aa0a709a SC |
306 | { |
307 | unsigned int i; | |
2fa0b342 | 308 | |
aa0a709a SC |
309 | for (i = 0; i < symcount; i++) |
310 | { | |
311 | if (syms[i]->the_bfd == 0) | |
312 | { | |
313 | symcount = i; | |
314 | break; | |
315 | } | |
316 | } | |
317 | } | |
e779a58c JG |
318 | |
319 | ||
aa0a709a SC |
320 | if (machine != (char *) NULL) |
321 | { | |
322 | info = bfd_scan_arch (machine); | |
323 | if (info == 0) | |
324 | { | |
325 | fprintf (stderr, "%s: Can't use supplied machine %s\n", | |
326 | program_name, | |
327 | machine); | |
328 | exit (1); | |
329 | } | |
330 | abfd->arch_info = info; | |
2fa0b342 | 331 | } |
e779a58c JG |
332 | |
333 | /* See if we can disassemble using bfd */ | |
334 | ||
aa0a709a SC |
335 | if (abfd->arch_info->disassemble) |
336 | { | |
337 | print = abfd->arch_info->disassemble; | |
e779a58c | 338 | } |
aa0a709a SC |
339 | else |
340 | { | |
341 | a = bfd_get_arch (abfd); | |
342 | switch (a) | |
343 | { | |
344 | case bfd_arch_sparc: | |
345 | print = print_insn_sparc; | |
346 | break; | |
347 | case bfd_arch_i386: | |
348 | print = print_insn_i386; | |
349 | break; | |
350 | case bfd_arch_m68k: | |
351 | print = print_insn_m68k; | |
352 | break; | |
353 | case bfd_arch_a29k: | |
354 | print = print_insn_a29k; | |
355 | break; | |
356 | case bfd_arch_i960: | |
357 | print = print_insn_i960; | |
358 | break; | |
359 | default: | |
360 | fprintf (stderr, "%s: Can't disassemble for architecture %s\n", | |
361 | program_name, | |
362 | bfd_printable_arch_mach (bfd_get_arch (abfd), 0)); | |
363 | exit (1); | |
364 | } | |
2fa0b342 | 365 | |
aa0a709a | 366 | } |
2fa0b342 DHW |
367 | |
368 | for (section = abfd->sections; | |
aa0a709a SC |
369 | section != (asection *) NULL; |
370 | section = section->next) | |
65cceb78 | 371 | { |
2fa0b342 | 372 | |
aa0a709a SC |
373 | if ((section->flags & SEC_LOAD) |
374 | && (only == (char *) NULL || strcmp (only, section->name) == 0)) | |
375 | { | |
376 | printf ("Disassembly of section %s:\n", section->name); | |
2fa0b342 | 377 | |
aa0a709a SC |
378 | if (bfd_get_section_size_before_reloc (section) == 0) |
379 | continue; | |
2fa0b342 | 380 | |
aa0a709a | 381 | data = (bfd_byte *) malloc (bfd_get_section_size_before_reloc (section)); |
2fa0b342 | 382 | |
aa0a709a SC |
383 | if (data == (bfd_byte *) NULL) |
384 | { | |
385 | fprintf (stderr, "%s: memory exhausted.\n", program_name); | |
386 | exit (1); | |
387 | } | |
388 | datasize = bfd_get_section_size_before_reloc (section); | |
2fa0b342 | 389 | |
aa0a709a | 390 | bfd_get_section_contents (abfd, section, data, 0, bfd_get_section_size_before_reloc (section)); |
2fa0b342 | 391 | |
aa0a709a SC |
392 | i = 0; |
393 | while (i < bfd_get_section_size_before_reloc (section)) | |
394 | { | |
395 | if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && | |
396 | data[i + 3] == 0) | |
397 | { | |
398 | if (done_dot == false) | |
399 | { | |
400 | printf ("...\n"); | |
401 | done_dot = true; | |
65cceb78 | 402 | } |
aa0a709a | 403 | i += 4; |
65cceb78 | 404 | } |
aa0a709a SC |
405 | else |
406 | { | |
407 | done_dot = false; | |
408 | if (with_line_numbers) | |
409 | { | |
410 | static prevline; | |
411 | CONST char *filename; | |
412 | CONST char *functionname; | |
413 | unsigned int line; | |
414 | ||
415 | bfd_find_nearest_line (abfd, | |
416 | section, | |
417 | syms, | |
418 | section->vma + i, | |
419 | &filename, | |
420 | &functionname, | |
421 | &line); | |
422 | ||
423 | if (filename && functionname && line && line != prevline) | |
424 | { | |
425 | printf ("%s:%u\n", filename, line); | |
426 | prevline = line; | |
427 | } | |
428 | } | |
429 | print_address (section->vma + i, stdout); | |
430 | printf (" "); | |
65cceb78 | 431 | |
aa0a709a SC |
432 | i += print (section->vma + i, |
433 | data + i, | |
434 | stdout); | |
435 | putchar ('\n'); | |
436 | } | |
96d7950b | 437 | } |
aa0a709a | 438 | free (data); |
96d7950b | 439 | } |
2fa0b342 | 440 | } |
2fa0b342 DHW |
441 | } |
442 | ||
443 | void | |
444 | display_bfd (abfd) | |
445 | bfd *abfd; | |
446 | { | |
447 | ||
aa0a709a SC |
448 | if (!bfd_check_format (abfd, bfd_object)) |
449 | { | |
450 | fprintf (stderr, "%s: %s not an object file\n", program_name, | |
451 | abfd->filename); | |
452 | return; | |
453 | } | |
2fa0b342 | 454 | printf ("\n%s: file format %s\n", abfd->filename, abfd->xvec->name); |
aa0a709a SC |
455 | if (dump_ar_hdrs) |
456 | print_arelt_descr (stdout, abfd, true); | |
2fa0b342 | 457 | |
aa0a709a SC |
458 | if (dump_file_header) |
459 | { | |
460 | char *comma = ""; | |
461 | ||
462 | printf ("architecture: %s, ", | |
463 | bfd_printable_arch_mach (bfd_get_arch (abfd), | |
464 | bfd_get_mach (abfd))); | |
465 | printf ("flags 0x%08x:\n", abfd->flags); | |
2fa0b342 | 466 | |
2fa0b342 | 467 | #define PF(x, y) if (abfd->flags & x) {printf("%s%s", comma, y); comma=", ";} |
aa0a709a SC |
468 | PF (HAS_RELOC, "HAS_RELOC"); |
469 | PF (EXEC_P, "EXEC_P"); | |
470 | PF (HAS_LINENO, "HAS_LINENO"); | |
471 | PF (HAS_DEBUG, "HAS_DEBUG"); | |
472 | PF (HAS_SYMS, "HAS_SYMS"); | |
473 | PF (HAS_LOCALS, "HAS_LOCALS"); | |
474 | PF (DYNAMIC, "DYNAMIC"); | |
475 | PF (WP_TEXT, "WP_TEXT"); | |
476 | PF (D_PAGED, "D_PAGED"); | |
477 | printf ("\nstart address 0x"); | |
478 | printf_vma (abfd->start_address); | |
479 | } | |
480 | printf ("\n"); | |
2fa0b342 DHW |
481 | |
482 | if (dump_section_headers) | |
aa0a709a SC |
483 | dump_headers (abfd); |
484 | if (dump_symtab || dump_reloc_info || disassemble) | |
485 | { | |
486 | syms = slurp_symtab (abfd); | |
487 | } | |
488 | if (dump_symtab) | |
489 | dump_symbols (abfd); | |
490 | if (dump_reloc_info) | |
491 | dump_relocs (abfd); | |
492 | if (dump_section_contents) | |
493 | dump_data (abfd); | |
494 | if (disassemble) | |
495 | disassemble_data (abfd); | |
2fa0b342 DHW |
496 | } |
497 | ||
498 | void | |
499 | display_file (filename, target) | |
500 | char *filename; | |
501 | char *target; | |
502 | { | |
503 | bfd *file, *arfile = (bfd *) NULL; | |
504 | ||
505 | file = bfd_openr (filename, target); | |
aa0a709a SC |
506 | if (file == NULL) |
507 | { | |
508 | bfd_perror (filename); | |
509 | return; | |
510 | } | |
2fa0b342 | 511 | |
aa0a709a SC |
512 | if (bfd_check_format (file, bfd_archive) == true) |
513 | { | |
514 | printf ("In archive %s:\n", bfd_get_filename (file)); | |
515 | for (;;) | |
516 | { | |
517 | bfd_error = no_error; | |
518 | ||
519 | arfile = bfd_openr_next_archived_file (file, arfile); | |
520 | if (arfile == NULL) | |
521 | { | |
522 | if (bfd_error != no_more_archived_files) | |
523 | bfd_perror (bfd_get_filename (file)); | |
524 | return; | |
525 | } | |
2fa0b342 | 526 | |
aa0a709a SC |
527 | display_bfd (arfile); |
528 | /* Don't close the archive elements; we need them for next_archive */ | |
529 | } | |
2fa0b342 | 530 | } |
2fa0b342 | 531 | else |
aa0a709a | 532 | display_bfd (file); |
2fa0b342 | 533 | |
aa0a709a | 534 | bfd_close (file); |
2fa0b342 DHW |
535 | } |
536 | \f | |
537 | /* Actually display the various requested regions */ | |
538 | ||
2fa0b342 DHW |
539 | void |
540 | dump_data (abfd) | |
541 | bfd *abfd; | |
542 | { | |
543 | asection *section; | |
aa0a709a | 544 | bfd_byte *data = 0; |
fc5d6074 SC |
545 | bfd_size_type datasize = 0; |
546 | bfd_size_type i; | |
2fa0b342 DHW |
547 | |
548 | for (section = abfd->sections; section != NULL; section = | |
aa0a709a SC |
549 | section->next) |
550 | { | |
551 | int onaline = 16; | |
2fa0b342 | 552 | |
aa0a709a SC |
553 | if (only == (char *) NULL || |
554 | strcmp (only, section->name) == 0) | |
60c80016 | 555 | { |
aa0a709a SC |
556 | if (section->flags & SEC_HAS_CONTENTS) |
557 | { | |
558 | printf ("Contents of section %s:\n", section->name); | |
559 | ||
560 | if (bfd_get_section_size_before_reloc (section) == 0) | |
561 | continue; | |
562 | data = (bfd_byte *) malloc (bfd_get_section_size_before_reloc (section)); | |
563 | if (data == (bfd_byte *) NULL) | |
564 | { | |
565 | fprintf (stderr, "%s: memory exhausted.\n", program_name); | |
566 | exit (1); | |
567 | } | |
568 | datasize = bfd_get_section_size_before_reloc (section); | |
2fa0b342 | 569 | |
2fa0b342 | 570 | |
aa0a709a | 571 | bfd_get_section_contents (abfd, section, (PTR) data, 0, bfd_get_section_size_before_reloc (section)); |
2fa0b342 | 572 | |
aa0a709a SC |
573 | for (i = 0; i < bfd_get_section_size_before_reloc (section); i += onaline) |
574 | { | |
575 | bfd_size_type j; | |
576 | ||
577 | printf (" %04lx ", (unsigned long int) (i + section->vma)); | |
578 | for (j = i; j < i + onaline; j++) | |
579 | { | |
580 | if (j < bfd_get_section_size_before_reloc (section)) | |
581 | printf ("%02x", (unsigned) (data[j])); | |
582 | else | |
583 | printf (" "); | |
584 | if ((j & 3) == 3) | |
585 | printf (" "); | |
586 | } | |
2fa0b342 | 587 | |
aa0a709a SC |
588 | printf (" "); |
589 | for (j = i; j < i + onaline; j++) | |
590 | { | |
591 | if (j >= bfd_get_section_size_before_reloc (section)) | |
592 | printf (" "); | |
593 | else | |
594 | printf ("%c", isprint (data[j]) ? data[j] : '.'); | |
595 | } | |
596 | putchar ('\n'); | |
597 | } | |
60c80016 | 598 | } |
2fa0b342 | 599 | } |
aa0a709a | 600 | free (data); |
2fa0b342 | 601 | } |
2fa0b342 DHW |
602 | } |
603 | ||
2fa0b342 DHW |
604 | /* Should perhaps share code and display with nm? */ |
605 | void | |
606 | dump_symbols (abfd) | |
607 | bfd *abfd; | |
608 | { | |
609 | ||
610 | unsigned int count; | |
611 | asymbol **current = syms; | |
2fa0b342 | 612 | |
aa0a709a | 613 | printf ("SYMBOL TABLE:\n"); |
e779a58c | 614 | |
aa0a709a SC |
615 | for (count = 0; count < symcount; count++) |
616 | { | |
2fa0b342 | 617 | |
aa0a709a SC |
618 | if (*current && (*current)->the_bfd) |
619 | { | |
620 | bfd_print_symbol ((*current)->the_bfd, | |
621 | stdout, | |
622 | *current, bfd_print_symbol_all); | |
e779a58c | 623 | |
aa0a709a SC |
624 | printf ("\n"); |
625 | ||
626 | } | |
627 | current++; | |
2fa0b342 | 628 | } |
aa0a709a SC |
629 | printf ("\n"); |
630 | printf ("\n"); | |
2fa0b342 DHW |
631 | } |
632 | ||
2fa0b342 | 633 | void |
aa0a709a SC |
634 | dump_relocs (abfd) |
635 | bfd *abfd; | |
2fa0b342 DHW |
636 | { |
637 | arelent **relpp; | |
638 | unsigned int relcount; | |
639 | asection *a; | |
aa0a709a SC |
640 | |
641 | for (a = abfd->sections; a != (asection *) NULL; a = a->next) | |
642 | { | |
643 | if (a == &bfd_abs_section) | |
644 | continue; | |
645 | if (a == &bfd_und_section) | |
646 | continue; | |
647 | if (a == &bfd_com_section) | |
648 | continue; | |
649 | ||
650 | printf ("RELOCATION RECORDS FOR [%s]:", a->name); | |
651 | ||
652 | if (bfd_get_reloc_upper_bound (abfd, a) == 0) | |
653 | { | |
654 | printf (" (none)\n\n"); | |
d20f480f | 655 | } |
aa0a709a SC |
656 | else |
657 | { | |
d20f480f SC |
658 | arelent **p; |
659 | ||
aa0a709a SC |
660 | relpp = (arelent **) xmalloc (bfd_get_reloc_upper_bound (abfd, a)); |
661 | relcount = bfd_canonicalize_reloc (abfd, a, relpp, syms); | |
662 | if (relcount == 0) | |
663 | { | |
664 | printf (" (none)\n\n"); | |
d20f480f | 665 | } |
aa0a709a SC |
666 | else |
667 | { | |
668 | printf ("\n"); | |
669 | printf ("OFFSET TYPE VALUE \n"); | |
d20f480f | 670 | |
aa0a709a SC |
671 | for (p = relpp; relcount && *p != (arelent *) NULL; p++, |
672 | relcount--) | |
673 | { | |
d20f480f SC |
674 | arelent *q = *p; |
675 | CONST char *sym_name; | |
aa0a709a | 676 | |
d20f480f SC |
677 | /* CONST char *section_name = q->section == (asection *)NULL ? "*abs" :*/ |
678 | /* q->section->name;*/ | |
aa0a709a SC |
679 | CONST char *section_name = (*(q->sym_ptr_ptr))->section->name; |
680 | ||
681 | if (q->sym_ptr_ptr && *q->sym_ptr_ptr) | |
682 | { | |
683 | sym_name = (*(q->sym_ptr_ptr))->name; | |
d20f480f | 684 | } |
aa0a709a SC |
685 | else |
686 | { | |
d20f480f SC |
687 | sym_name = 0; |
688 | } | |
aa0a709a SC |
689 | if (sym_name) |
690 | { | |
691 | printf_vma (q->address); | |
692 | printf (" %-8s %s", | |
693 | q->howto->name, | |
694 | sym_name); | |
d20f480f | 695 | } |
aa0a709a SC |
696 | else |
697 | { | |
698 | printf_vma (q->address); | |
699 | printf (" %-8s [%s]", | |
700 | q->howto->name, | |
701 | section_name); | |
d20f480f | 702 | } |
aa0a709a SC |
703 | if (q->addend) |
704 | { | |
705 | printf ("+0x"); | |
706 | printf_vma (q->addend); | |
d20f480f | 707 | } |
aa0a709a | 708 | printf ("\n"); |
d20f480f | 709 | } |
aa0a709a SC |
710 | printf ("\n\n"); |
711 | free (relpp); | |
d20f480f | 712 | } |
2fa0b342 | 713 | } |
2fa0b342 | 714 | |
d20f480f | 715 | } |
2fa0b342 DHW |
716 | } |
717 | ||
aa0a709a SC |
718 | #ifdef unix |
719 | #define _DUMMY_NAME_ "/dev/null" | |
720 | #else | |
721 | #define _DUMMY_NAME_ "##dummy" | |
722 | #endif | |
9872a49c | 723 | static void |
aa0a709a SC |
724 | DEFUN (display_info_table, (first, last), |
725 | int first AND int last) | |
9872a49c | 726 | { |
3fdbfe8d | 727 | unsigned int i, j; |
9872a49c SC |
728 | extern bfd_target *target_vector[]; |
729 | ||
aa0a709a SC |
730 | printf ("\n%12s", " "); |
731 | for (i = first; i++ < last && target_vector[i];) | |
732 | printf ("%s ", target_vector[i]->name); | |
733 | printf ("\n"); | |
9872a49c | 734 | |
aa0a709a SC |
735 | for (j = (int) bfd_arch_obscure + 1; (int) j < (int) bfd_arch_last; j++) |
736 | if (strcmp (bfd_printable_arch_mach (j, 0), "UNKNOWN!") != 0) | |
e779a58c | 737 | { |
aa0a709a SC |
738 | printf ("%11s ", bfd_printable_arch_mach (j, 0)); |
739 | for (i = first; i++ < last && target_vector[i];) | |
740 | { | |
741 | bfd_target *p = target_vector[i]; | |
742 | bfd *abfd = bfd_openw (_DUMMY_NAME_, p->name); | |
743 | int l = strlen (p->name); | |
744 | int ok = bfd_set_arch_mach (abfd, j, 0); | |
745 | ||
746 | if (ok) | |
747 | printf ("%s ", p->name); | |
748 | else | |
e779a58c | 749 | { |
aa0a709a SC |
750 | while (l--) |
751 | printf ("%c", ok ? '*' : '-'); | |
752 | printf (" "); | |
e779a58c | 753 | } |
e779a58c | 754 | } |
aa0a709a | 755 | printf ("\n"); |
e779a58c | 756 | } |
9872a49c | 757 | } |
aa0a709a SC |
758 | |
759 | static void | |
760 | DEFUN_VOID (display_info) | |
761 | { | |
762 | char *colum; | |
763 | unsigned int i, j, columns; | |
764 | extern bfd_target *target_vector[]; | |
765 | extern char *getenv (); | |
766 | ||
767 | printf ("BFD header file version %s\n", BFD_VERSION); | |
768 | for (i = 0; target_vector[i]; i++) | |
769 | { | |
770 | bfd_target *p = target_vector[i]; | |
771 | bfd *abfd = bfd_openw (_DUMMY_NAME_, p->name); | |
772 | ||
773 | printf ("%s\n (header %s, data %s)\n", p->name, | |
774 | p->header_byteorder_big_p ? "big endian" : "little endian", | |
775 | p->byteorder_big_p ? "big endian" : "little endian"); | |
776 | for (j = (int) bfd_arch_obscure + 1; j < (int) bfd_arch_last; j++) | |
777 | if (bfd_set_arch_mach (abfd, (enum bfd_architecture) j, 0)) | |
778 | printf (" %s\n", | |
779 | bfd_printable_arch_mach ((enum bfd_architecture) j, 0)); | |
780 | } | |
781 | columns = 0; | |
782 | if (colum = getenv ("COLUMNS")) | |
783 | columns = atoi (colum); | |
784 | if (!columns) | |
785 | columns = 80; | |
786 | for (i = 0; target_vector[i];) | |
787 | { | |
788 | int old; | |
789 | old = i; | |
790 | for (j = 12; target_vector[i] && j < columns; i++) | |
791 | j += strlen (target_vector[i]->name) + 1; | |
792 | i--; | |
793 | if (old == i) | |
794 | break; | |
795 | display_info_table (old, i); | |
796 | } | |
797 | } | |
798 | ||
2fa0b342 DHW |
799 | /** main and like trivia */ |
800 | int | |
801 | main (argc, argv) | |
802 | int argc; | |
803 | char **argv; | |
804 | { | |
805 | int c; | |
806 | extern int optind; | |
807 | extern char *optarg; | |
808 | char *target = default_target; | |
809 | boolean seenflag = false; | |
810 | int ind = 0; | |
811 | ||
aa0a709a | 812 | bfd_init (); |
2fa0b342 DHW |
813 | program_name = *argv; |
814 | ||
3fdbfe8d | 815 | while ((c = getopt_long (argc, argv, "ib:m:dlfahrtxsj:", long_options, &ind)) |
aa0a709a SC |
816 | != EOF) |
817 | { | |
818 | seenflag = true; | |
819 | switch (c) | |
820 | { | |
821 | case 'm': | |
822 | machine = optarg; | |
823 | break; | |
824 | case 'j': | |
825 | only = optarg; | |
826 | break; | |
827 | case 'l': | |
828 | with_line_numbers = 1; | |
829 | break; | |
830 | case 'b': | |
831 | target = optarg; | |
832 | break; | |
833 | case 'f': | |
834 | dump_file_header = true; | |
835 | break; | |
836 | case 'i': | |
837 | info = true; | |
838 | break; | |
839 | case 'x': | |
840 | dump_symtab = 1; | |
841 | dump_reloc_info = 1; | |
842 | dump_file_header = true; | |
843 | dump_ar_hdrs = 1; | |
844 | dump_section_headers = 1; | |
845 | break; | |
846 | case 0: | |
847 | break; /* we've been given a long option */ | |
848 | case 't': | |
849 | dump_symtab = 1; | |
850 | break; | |
851 | case 'd': | |
852 | disassemble = true; | |
853 | break; | |
854 | case 's': | |
855 | dump_section_contents = 1; | |
856 | break; | |
857 | case 'r': | |
858 | dump_reloc_info = 1; | |
859 | break; | |
860 | case 'a': | |
861 | dump_ar_hdrs = 1; | |
862 | break; | |
863 | case 'h': | |
864 | dump_section_headers = 1; | |
865 | break; | |
866 | default: | |
867 | usage (); | |
868 | } | |
2fa0b342 | 869 | } |
2fa0b342 DHW |
870 | |
871 | if (seenflag == false) | |
872 | usage (); | |
873 | ||
aa0a709a SC |
874 | if (info) |
875 | { | |
876 | display_info (); | |
877 | } | |
878 | else | |
879 | { | |
880 | if (optind == argc) | |
881 | display_file ("a.out", target); | |
882 | else | |
883 | for (; optind < argc;) | |
884 | display_file (argv[optind++], target); | |
885 | } | |
2fa0b342 DHW |
886 | return 0; |
887 | } |