(process_syminfo): Print names of files symbols are bound to, not the index.
[deliverable/binutils-gdb.git] / binutils / readelf.c
1 /* readelf.c -- display contents of an ELF format file
2 Copyright (C) 1998 Free Software Foundation, Inc.
3
4 Originally developed by Eric Youngdale <eric@andante.jic.com>
5 Modifications by Nick Clifton <nickc@cygnus.com>
6
7 This file is part of GNU Binutils.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 02111-1307, USA. */
23 \f
24
25 #include <assert.h>
26 #include <sys/stat.h>
27 #include <stdio.h>
28 #include <time.h>
29
30 #include "bfd.h"
31
32 #include "elf/common.h"
33 #include "elf/external.h"
34 #include "elf/internal.h"
35
36 /* The following headers use the elf/reloc-macros.h file to
37 automatically generate relocation recognition functions
38 such as elf_mips_reloc_type() */
39
40 #define RELOC_MACROS_GEN_FUNC
41
42 #include "elf/i386.h"
43 #include "elf/v850.h"
44 #include "elf/ppc.h"
45 #include "elf/mips.h"
46 #include "elf/alpha.h"
47 #include "elf/arm.h"
48 #include "elf/m68k.h"
49 #include "elf/sparc.h"
50 #include "elf/m32r.h"
51 #include "elf/d10v.h"
52 #include "elf/d30v.h"
53 #include "elf/sh.h"
54 #include "elf/mn10200.h"
55 #include "elf/mn10300.h"
56 #include "elf/hppa.h"
57 #include "elf/arc.h"
58
59 #include "bucomm.h"
60 #include "getopt.h"
61
62 #ifdef ANSI_PROTOTYPES
63 #include <stdarg.h>
64 #else
65 #include <varargs.h>
66 #endif
67
68 char * program_name = "readelf";
69 unsigned int dynamic_addr;
70 unsigned int dynamic_size;
71 unsigned int rela_addr;
72 unsigned int rela_size;
73 char * dynamic_strings;
74 char * string_table;
75 Elf_Internal_Sym * dynamic_symbols;
76 Elf_Internal_Syminfo * dynamic_syminfo;
77 unsigned long int dynamic_syminfo_offset;
78 unsigned int dynamic_syminfo_nent;
79 char program_interpreter [64];
80 int dynamic_info[DT_JMPREL + 1];
81 int version_info[16];
82 int loadaddr = 0;
83 Elf_Internal_Ehdr elf_header;
84 Elf_Internal_Shdr * section_headers;
85 Elf_Internal_Dyn * dynamic_segment;
86 int show_name;
87 int do_dynamic;
88 int do_syms;
89 int do_reloc;
90 int do_sections;
91 int do_segments;
92 int do_using_dynamic;
93 int do_header;
94 int do_dump;
95 int do_version;
96
97 static unsigned long int (* byte_get) PARAMS ((unsigned char *, int));
98
99 #define NUM_DUMP_SECTS 100
100 char dump_sects [NUM_DUMP_SECTS];
101
102 #define HEX_DUMP 1
103 #define DISASS_DUMP 2
104
105 /* Forward declarations for dumb compilers. */
106 static const char * get_mips_dynamic_type PARAMS ((unsigned long type));
107 static const char * get_dynamic_type PARAMS ((unsigned long type));
108 static int dump_relocations
109 PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, char *));
110 static char * get_file_type PARAMS ((unsigned e_type));
111 static char * get_machine_name PARAMS ((unsigned e_machine));
112 static char * get_machine_data PARAMS ((unsigned e_data));
113 static char * get_machine_flags PARAMS ((unsigned, unsigned e_machine));
114 static const char * get_mips_segment_type PARAMS ((unsigned long type));
115 static const char * get_segment_type PARAMS ((unsigned long p_type));
116 static const char * get_mips_section_type_name PARAMS ((unsigned int sh_type));
117 static const char * get_section_type_name PARAMS ((unsigned int sh_type));
118 static char * get_symbol_binding PARAMS ((unsigned int binding));
119 static char * get_symbol_type PARAMS ((unsigned int type));
120 static void usage PARAMS ((void));
121 static void parse_args PARAMS ((int argc, char ** argv));
122 static int process_file_header PARAMS ((void));
123 static int process_program_headers PARAMS ((FILE *));
124 static int process_section_headers PARAMS ((FILE *));
125 static void dynamic_segment_mips_val PARAMS ((Elf_Internal_Dyn *entry));
126 static int process_dynamic_segment PARAMS ((FILE *));
127 static int process_symbol_table PARAMS ((FILE *));
128 static int process_section_contents PARAMS ((FILE *));
129 static void process_file PARAMS ((char * file_name));
130 static int process_relocs PARAMS ((FILE *));
131 static int process_version_sections PARAMS ((FILE *));
132 static char * get_ver_flags PARAMS ((unsigned int flags));
133 static char * get_symbol_index_type PARAMS ((unsigned int type));
134 static int get_section_headers PARAMS ((FILE * file));
135 static int get_file_header PARAMS ((FILE * file));
136 static Elf_Internal_Sym * get_elf_symbols
137 PARAMS ((FILE * file, unsigned long offset, unsigned long number));
138 static int * get_dynamic_data PARAMS ((FILE * file, unsigned int number));
139
140 typedef int Elf32_Word;
141
142 #define SECTION_NAME(X) (string_table + (X)->sh_name)
143
144 #define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
145
146 #define BYTE_GET(field) byte_get (field, sizeof (field))
147
148 #define NUM_ELEM(array) (sizeof (array) / sizeof ((array)[0]))
149
150 #define GET_DATA_ALLOC(offset, size, var, type, reason) \
151 if (fseek (file, offset, SEEK_SET)) \
152 { \
153 error (_("Unable to seek to start of %s at %x\n"), reason, offset); \
154 return 0; \
155 } \
156 \
157 var = (type) malloc (size); \
158 \
159 if (var == NULL) \
160 { \
161 error (_("Out of memory allocating %d bytes for %s\n"), size, reason); \
162 return 0; \
163 } \
164 \
165 if (fread (var, size, 1, file) != 1) \
166 { \
167 error (_("Unable to read in %d bytes of %s\n"), size, reason); \
168 free (var); \
169 var = NULL; \
170 return 0; \
171 }
172
173
174 #define GET_DATA(offset, var, reason) \
175 if (fseek (file, offset, SEEK_SET)) \
176 { \
177 error (_("Unable to seek to %x for %s\n"), offset, reason); \
178 return 0; \
179 } \
180 else if (fread (& var, sizeof (var), 1, file) != 1) \
181 { \
182 error (_("Unable to read data at %x for %s\n"), offset, reason); \
183 return 0; \
184 }
185
186 #ifdef ANSI_PROTOTYPES
187 static void
188 error (const char * message, ...)
189 {
190 va_list args;
191
192 fprintf (stderr, _("%s: Error: "), program_name);
193 va_start (args, message);
194 vfprintf (stderr, message, args);
195 va_end (args);
196 return;
197 }
198
199 static void
200 warn (const char * message, ...)
201 {
202 va_list args;
203
204 fprintf (stderr, _("%s: Warning: "), program_name);
205 va_start (args, message);
206 vfprintf (stderr, message, args);
207 va_end (args);
208 return;
209 }
210 #else
211 static void
212 error (va_alist)
213 va_dcl
214 {
215 char * message;
216 va_list args;
217
218 fprintf (stderr, _("%s: Error: "), program_name);
219 va_start (args);
220 message = va_arg (args, char *);
221 vfprintf (stderr, message, args);
222 va_end (args);
223 return;
224 }
225
226 static void
227 warn (va_alist)
228 va_dcl
229 {
230 char * message;
231 va_list args;
232
233 fprintf (stderr, _("%s: Warning: "), program_name);
234 va_start (args);
235 message = va_arg (args, char *);
236 vfprintf (stderr, message, args);
237 va_end (args);
238 return;
239 }
240 #endif
241
242 static unsigned long int
243 byte_get_little_endian (field, size)
244 unsigned char * field;
245 int size;
246 {
247 switch (size)
248 {
249 case 1:
250 return * field;
251
252 case 2:
253 return ((unsigned int) (field [0]))
254 | (((unsigned int) (field [1])) << 8);
255
256 case 4:
257 return ((unsigned long) (field [0]))
258 | (((unsigned long) (field [1])) << 8)
259 | (((unsigned long) (field [2])) << 16)
260 | (((unsigned long) (field [3])) << 24);
261
262 default:
263 error (_("Unhandled data length: %d\n"), size);
264 abort();
265 }
266 }
267
268 static unsigned long int
269 byte_get_big_endian (field, size)
270 unsigned char * field;
271 int size;
272 {
273 switch (size)
274 {
275 case 1:
276 return * field;
277
278 case 2:
279 return ((unsigned int) (field [1])) | (((int) (field [0])) << 8);
280
281 case 4:
282 return ((unsigned long) (field [3]))
283 | (((unsigned long) (field [2])) << 8)
284 | (((unsigned long) (field [1])) << 16)
285 | (((unsigned long) (field [0])) << 24);
286
287 default:
288 error (_("Unhandled data length: %d\n"), size);
289 abort();
290 }
291 }
292
293
294 /* Display the contents of the relocation data
295 found at the specified offset. */
296 static int
297 dump_relocations (file, rel_offset, rel_size, symtab, strtab)
298 FILE * file;
299 unsigned long rel_offset;
300 unsigned long rel_size;
301 Elf_Internal_Sym * symtab;
302 char * strtab;
303 {
304 unsigned int i;
305 int is_rela;
306 Elf_Internal_Rel * rels;
307 Elf_Internal_Rela * relas;
308
309
310 /* Compute number of relocations and read them in. */
311 switch (elf_header.e_machine)
312 {
313 case EM_386:
314 case EM_486:
315 case EM_CYGNUS_M32R:
316 case EM_CYGNUS_D10V:
317 case EM_MIPS:
318 case EM_MIPS_RS4_BE:
319 {
320 Elf32_External_Rel * erels;
321
322 GET_DATA_ALLOC (rel_offset, rel_size, erels,
323 Elf32_External_Rel *, "relocs");
324
325 rel_size = rel_size / sizeof (Elf32_External_Rel);
326
327 rels = (Elf_Internal_Rel *) malloc (rel_size *
328 sizeof (Elf_Internal_Rel));
329
330 for (i = 0; i < rel_size; i++)
331 {
332 rels[i].r_offset = BYTE_GET (erels[i].r_offset);
333 rels[i].r_info = BYTE_GET (erels[i].r_info);
334 }
335
336 free (erels);
337
338 is_rela = 0;
339 relas = (Elf_Internal_Rela *) rels;
340 }
341 break;
342
343 case EM_ARM:
344 case EM_68K:
345 case EM_SPARC:
346 case EM_PPC:
347 case EM_CYGNUS_V850:
348 case EM_CYGNUS_D30V:
349 case EM_CYGNUS_MN10200:
350 case EM_CYGNUS_MN10300:
351 case EM_SH:
352 case EM_ALPHA:
353 {
354 Elf32_External_Rela * erelas;
355
356 GET_DATA_ALLOC (rel_offset, rel_size, erelas,
357 Elf32_External_Rela *, "relocs");
358
359 rel_size = rel_size / sizeof (Elf32_External_Rela);
360
361 relas = (Elf_Internal_Rela *) malloc (rel_size *
362 sizeof (Elf_Internal_Rela));
363
364 for (i = 0; i < rel_size; i++)
365 {
366 relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
367 relas[i].r_info = BYTE_GET (erelas[i].r_info);
368 relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
369 }
370
371 free (erelas);
372
373 is_rela = 1;
374 rels = (Elf_Internal_Rel *) relas;
375 }
376 break;
377
378 default:
379 warn (_("Don't know about relocations on this machine architecture\n"));
380 return 0;
381 }
382
383 if (is_rela)
384 printf
385 (_(" Offset Value Type Symbol's Value Symbol's Name Addend\n"));
386 else
387 printf
388 (_(" Offset Value Type Symbol's Value Symbol's Name\n"));
389
390 for (i = 0; i < rel_size; i++)
391 {
392 const char * rtype;
393 unsigned long offset;
394 unsigned long info;
395 int symtab_index;
396
397 if (is_rela)
398 {
399 offset = relas [i].r_offset;
400 info = relas [i].r_info;
401 }
402 else
403 {
404 offset = rels [i].r_offset;
405 info = rels [i].r_info;
406 }
407
408 printf (" %8.8lx %5.5lx ", offset, info);
409
410 switch (elf_header.e_machine)
411 {
412 default:
413 rtype = NULL;
414 break;
415
416 case EM_CYGNUS_M32R:
417 rtype = elf_m32r_reloc_type (ELF32_R_TYPE (info));
418 break;
419
420 case EM_386:
421 case EM_486:
422 rtype = elf_i386_reloc_type (ELF32_R_TYPE (info));
423 break;
424
425 case EM_68K:
426 rtype = elf_m68k_reloc_type (ELF32_R_TYPE (info));
427 break;
428
429 case EM_SPARC:
430 rtype = elf_sparc_reloc_type (ELF32_R_TYPE (info));
431 break;
432
433 case EM_CYGNUS_V850:
434 rtype = v850_reloc_type (ELF32_R_TYPE (info));
435 break;
436
437 case EM_CYGNUS_D10V:
438 rtype = elf_d10v_reloc_type (ELF32_R_TYPE (info));
439 break;
440
441 case EM_CYGNUS_D30V:
442 rtype = elf_d30v_reloc_type (ELF32_R_TYPE (info));
443 break;
444
445 case EM_SH:
446 rtype = elf_sh_reloc_type (ELF32_R_TYPE (info));
447 break;
448
449 case EM_CYGNUS_MN10300:
450 rtype = elf_mn10300_reloc_type (ELF32_R_TYPE (info));
451 break;
452
453 case EM_CYGNUS_MN10200:
454 rtype = elf_mn10200_reloc_type (ELF32_R_TYPE (info));
455 break;
456
457 case EM_PPC:
458 rtype = elf_ppc_reloc_type (ELF32_R_TYPE (info));
459 break;
460
461 case EM_MIPS:
462 case EM_MIPS_RS4_BE:
463 rtype = elf_mips_reloc_type (ELF32_R_TYPE (info));
464 break;
465
466 case EM_ALPHA:
467 rtype = elf_alpha_reloc_type (ELF32_R_TYPE (info));
468 break;
469
470 case EM_ARM:
471 rtype = elf_arm_reloc_type (ELF32_R_TYPE (info));
472 break;
473
474 case EM_CYGNUS_ARC:
475 rtype = elf_arc_reloc_type (ELF32_R_TYPE (info));
476 break;
477
478 case EM_PARISC:
479 rtype = elf32_hppa_reloc_type (ELF32_R_TYPE (info));
480 break;
481 }
482
483 if (rtype == NULL)
484 printf (_("unrecognised: %-7x"), ELF32_R_TYPE (info));
485 else
486 printf ("%-21.21s", rtype);
487
488 symtab_index = ELF32_R_SYM (info);
489
490 if (symtab_index && symtab != NULL)
491 {
492 Elf_Internal_Sym * psym;
493
494 psym = symtab + symtab_index;
495
496 printf (" %08lx ", (unsigned long) psym->st_value);
497
498 if (psym->st_name == 0)
499 printf ("%-25.25s",
500 SECTION_NAME (section_headers + psym->st_shndx));
501 else if (strtab == NULL)
502 printf (_("<string table index %3d>"), psym->st_name);
503 else
504 printf ("%-25.25s", strtab + psym->st_name);
505
506 if (is_rela)
507 printf (" + %lx", (unsigned long) relas [i].r_addend);
508 }
509
510 putchar ('\n');
511 }
512
513 free (relas);
514
515 return 1;
516 }
517
518 static const char *
519 get_mips_dynamic_type (type)
520 unsigned long type;
521 {
522 switch (type)
523 {
524 case DT_MIPS_RLD_VERSION: return "MIPS_RLD_VERSION";
525 case DT_MIPS_TIME_STAMP: return "MIPS_TIME_STAMP";
526 case DT_MIPS_ICHECKSUM: return "MIPS_ICHECKSUM";
527 case DT_MIPS_IVERSION: return "MIPS_IVERSION";
528 case DT_MIPS_FLAGS: return "MIPS_FLAGS";
529 case DT_MIPS_BASE_ADDRESS: return "MIPS_BASE_ADDRESS";
530 case DT_MIPS_MSYM: return "MIPS_MSYM";
531 case DT_MIPS_CONFLICT: return "MIPS_CONFLICT";
532 case DT_MIPS_LIBLIST: return "MIPS_LIBLIST";
533 case DT_MIPS_LOCAL_GOTNO: return "MIPS_LOCAL_GOTNO";
534 case DT_MIPS_CONFLICTNO: return "MIPS_CONFLICTNO";
535 case DT_MIPS_LIBLISTNO: return "MIPS_LIBLISTNO";
536 case DT_MIPS_SYMTABNO: return "MIPS_SYMTABNO";
537 case DT_MIPS_UNREFEXTNO: return "MIPS_UNREFEXTNO";
538 case DT_MIPS_GOTSYM: return "MIPS_GOTSYM";
539 case DT_MIPS_HIPAGENO: return "MIPS_HIPAGENO";
540 case DT_MIPS_RLD_MAP: return "MIPS_RLD_MAP";
541 case DT_MIPS_DELTA_CLASS: return "MIPS_DELTA_CLASS";
542 case DT_MIPS_DELTA_CLASS_NO: return "MIPS_DELTA_CLASS_NO";
543 case DT_MIPS_DELTA_INSTANCE: return "MIPS_DELTA_INSTANCE";
544 case DT_MIPS_DELTA_INSTANCE_NO: return "MIPS_DELTA_INSTANCE_NO";
545 case DT_MIPS_DELTA_RELOC: return "MIPS_DELTA_RELOC";
546 case DT_MIPS_DELTA_RELOC_NO: return "MIPS_DELTA_RELOC_NO";
547 case DT_MIPS_DELTA_SYM: return "MIPS_DELTA_SYM";
548 case DT_MIPS_DELTA_SYM_NO: return "MIPS_DELTA_SYM_NO";
549 case DT_MIPS_DELTA_CLASSSYM: return "MIPS_DELTA_CLASSSYM";
550 case DT_MIPS_DELTA_CLASSSYM_NO: return "MIPS_DELTA_CLASSSYM_NO";
551 case DT_MIPS_CXX_FLAGS: return "MIPS_CXX_FLAGS";
552 case DT_MIPS_PIXIE_INIT: return "MIPS_PIXIE_INIT";
553 case DT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB";
554 case DT_MIPS_LOCALPAGE_GOTIDX: return "MIPS_LOCALPAGE_GOTIDX";
555 case DT_MIPS_LOCAL_GOTIDX: return "MIPS_LOCAL_GOTIDX";
556 case DT_MIPS_HIDDEN_GOTIDX: return "MIPS_HIDDEN_GOTIDX";
557 case DT_MIPS_PROTECTED_GOTIDX: return "MIPS_PROTECTED_GOTIDX";
558 case DT_MIPS_OPTIONS: return "MIPS_OPTIONS";
559 case DT_MIPS_INTERFACE: return "MIPS_INTERFACE";
560 case DT_MIPS_DYNSTR_ALIGN: return "MIPS_DYNSTR_ALIGN";
561 case DT_MIPS_INTERFACE_SIZE: return "MIPS_INTERFACE_SIZE";
562 case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: return "MIPS_RLD_TEXT_RESOLVE_ADDR";
563 case DT_MIPS_PERF_SUFFIX: return "MIPS_PERF_SUFFIX";
564 case DT_MIPS_COMPACT_SIZE: return "MIPS_COMPACT_SIZE";
565 case DT_MIPS_GP_VALUE: return "MIPS_GP_VALUE";
566 case DT_MIPS_AUX_DYNAMIC: return "MIPS_AUX_DYNAMIC";
567 default:
568 return NULL;
569 }
570 }
571
572 static const char *
573 get_dynamic_type (type)
574 unsigned long type;
575 {
576 static char buff [32];
577
578 switch (type)
579 {
580 case DT_NULL: return "NULL";
581 case DT_NEEDED: return "NEEDED";
582 case DT_PLTRELSZ: return "PLTRELSZ";
583 case DT_PLTGOT: return "PLTGOT";
584 case DT_HASH: return "HASH";
585 case DT_STRTAB: return "STRTAB";
586 case DT_SYMTAB: return "SYMTAB";
587 case DT_RELA: return "RELA";
588 case DT_RELASZ: return "RELASZ";
589 case DT_RELAENT: return "RELAENT";
590 case DT_STRSZ: return "STRSZ";
591 case DT_SYMENT: return "SYMENT";
592 case DT_INIT: return "INIT";
593 case DT_FINI: return "FINI";
594 case DT_SONAME: return "SONAME";
595 case DT_RPATH: return "RPATH";
596 case DT_SYMBOLIC: return "SYMBOLIC";
597 case DT_REL: return "REL";
598 case DT_RELSZ: return "RELSZ";
599 case DT_RELENT: return "RELENT";
600 case DT_PLTREL: return "PLTREL";
601 case DT_DEBUG: return "DEBUG";
602 case DT_TEXTREL: return "TEXTREL";
603 case DT_JMPREL: return "JMPREL";
604 case DT_VERDEF: return "VERDEF";
605 case DT_VERDEFNUM: return "VERDEFNUM";
606 case DT_VERNEED: return "VERNEED";
607 case DT_VERNEEDNUM: return "VERNEEDNUM";
608 case DT_VERSYM: return "VERSYN";
609 case DT_AUXILIARY: return "AUXILARY";
610 case DT_FILTER: return "FILTER";
611 case DT_POSFLAG_1: return "POSFLAG_1";
612 case DT_SYMINSZ: return "SYMINSZ";
613 case DT_SYMINENT: return "SYMINENT";
614 case DT_SYMINFO: return "SYMINFO";
615 case DT_RELACOUNT: return "RELACOUNT";
616 case DT_RELCOUNT: return "RELCOUNT";
617 case DT_FLAGS_1: return "FLAGS_1";
618 case DT_USED: return "USED";
619
620 default:
621 if ((type >= DT_LOPROC) && (type <= DT_HIPROC))
622 {
623 const char *result = NULL;
624 switch (elf_header.e_machine)
625 {
626 case EM_MIPS:
627 case EM_MIPS_RS4_BE:
628 result = get_mips_dynamic_type (type);
629 }
630
631 if (result == NULL)
632 {
633 sprintf (buff, _("Processor Specific"), type);
634 result = buff;
635 }
636 return result;
637 }
638 else
639 sprintf (buff, _("<unknown>: %x"), type);
640 return buff;
641 }
642 }
643
644 static char *
645 get_file_type (e_type)
646 unsigned e_type;
647 {
648 static char buff [32];
649
650 switch (e_type)
651 {
652 case ET_NONE: return _("NONE (None)");
653 case ET_REL: return _("REL (Relocatable file)");
654 case ET_EXEC: return _("EXEC (Executable file)");
655 case ET_DYN: return _("DYN (Shared object file)");
656 case ET_CORE: return _("CORE (Core file)");
657
658 default:
659 if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC))
660 sprintf (buff, _("Processor Specific: (%x)"), e_type);
661 else
662 sprintf (buff, _("<unknown>: %x"), e_type);
663 return buff;
664 }
665 }
666
667 static char *
668 get_machine_name (e_machine)
669 unsigned e_machine;
670 {
671 static char buff [32];
672
673 switch (e_machine)
674 {
675 case EM_NONE: return _("None");
676 case EM_M32: return "WE32100";
677 case EM_SPARC: return "Sparc";
678 case EM_386: return "Intel 80386";
679 case EM_68K: return "MC68000";
680 case EM_88K: return "MC88000";
681 case EM_486: return "Intel 80486";
682 case EM_860: return "Intel 80860";
683 case EM_MIPS: return "MIPS R3000 big-endian";
684 case EM_S370: return "Amdahl";
685 case EM_MIPS_RS4_BE: return "MIPS R4000 big-endian";
686 case EM_OLD_SPARCV9: return "Sparc v9 (old)";
687 case EM_PARISC: return "HPPA";
688 case EM_PPC_OLD: return "Power PC (old)";
689 case EM_SPARC32PLUS: return "Sparc v8+" ;
690 case EM_960: return "Intel 90860";
691 case EM_PPC: return "PowerPC";
692 case EM_V800: return "NEC V800";
693 case EM_FR20: return "Fujitsu FR20";
694 case EM_RH32: return "TRW RH32";
695 case EM_MMA: return "Fujitsu MMA";
696 case EM_ARM: return "ARM";
697 case EM_OLD_ALPHA: return "Digital Alpha (old)";
698 case EM_SH: return "Hitachi SH";
699 case EM_SPARCV9: return "Sparc v9";
700 case EM_ALPHA: return "Alpha";
701 case EM_CYGNUS_D10V: return "d10v";
702 case EM_CYGNUS_D30V: return "d30v";
703 case EM_CYGNUS_ARC: return "Arc";
704 case EM_CYGNUS_M32R: return "M32r";
705 case EM_CYGNUS_V850: return "v850";
706 case EM_CYGNUS_MN10300: return "mn10300";
707 case EM_CYGNUS_MN10200: return "mn10200";
708
709 default:
710 sprintf (buff, _("<unknown>: %x"), e_machine);
711 return buff;
712 }
713 }
714
715 static char *
716 get_machine_flags (e_flags, e_machine)
717 unsigned e_flags;
718 unsigned e_machine;
719 {
720 static char buf [1024];
721
722 buf[0] = '\0';
723 if (e_flags)
724 {
725 switch (e_machine)
726 {
727 default:
728 break;
729
730 case EM_PPC:
731 if (e_flags & EF_PPC_EMB)
732 strcat (buf, ", emb");
733
734 if (e_flags & EF_PPC_RELOCATABLE)
735 strcat (buf, ", relocatable");
736
737 if (e_flags & EF_PPC_RELOCATABLE_LIB)
738 strcat (buf, ", relocatable-lib");
739 break;
740
741 case EM_CYGNUS_M32R:
742 if ((e_flags & EF_M32R_ARCH) == E_M32R_ARCH)
743 strcat (buf, ", m32r");
744
745 /* start-sanitize-m32rx */
746 #ifdef E_M32RX_ARCH
747 if ((e_flags & EF_M32R_ARCH) == E_M32RX_ARCH)
748 strcat (buf, ", m32rx");
749 #endif
750 /* end-sanitize-m32rx */
751 break;
752
753 case EM_MIPS:
754 case EM_MIPS_RS4_BE:
755 if (e_flags & EF_MIPS_NOREORDER)
756 strcat (buf, ", noreorder");
757
758 if (e_flags & EF_MIPS_PIC)
759 strcat (buf, ", pic");
760
761 if (e_flags & EF_MIPS_CPIC)
762 strcat (buf, ", cpic");
763
764 if (e_flags & EF_MIPS_ABI2)
765 strcat (buf, ", abi2");
766
767 if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1)
768 strcat (buf, ", mips1");
769
770 if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2)
771 strcat (buf, ", mips2");
772
773 if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_3)
774 strcat (buf, ", mips3");
775
776 if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_4)
777 strcat (buf, ", mips4");
778 break;
779 }
780 }
781
782 return buf;
783 }
784
785 static char *
786 get_machine_data (e_data)
787 unsigned e_data;
788 {
789 static char buff [32];
790
791 switch (e_data)
792 {
793 case ELFDATA2LSB: return _("ELFDATA2LSB (little endian)");
794 case ELFDATA2MSB: return _("ELFDATA2MSB (big endian)");
795 default:
796 sprintf (buff, _("<unknown>: %x"), e_data);
797 return buff;
798 }
799 }
800
801 static const char *
802 get_mips_segment_type (type)
803 unsigned long type;
804 {
805 switch (type)
806 {
807 case PT_MIPS_REGINFO:
808 return "REGINFO";
809 case PT_MIPS_RTPROC:
810 return "RTPROC";
811 case PT_MIPS_OPTIONS:
812 return "OPTIONS";
813 default:
814 break;
815 }
816
817 return NULL;
818 }
819
820 static const char *
821 get_segment_type (p_type)
822 unsigned long p_type;
823 {
824 static char buff [32];
825
826 switch (p_type)
827 {
828 case PT_NULL: return "NULL";
829 case PT_LOAD: return "LOAD";
830 case PT_DYNAMIC: return "DYNAMIC";
831 case PT_INTERP: return "INTERP";
832 case PT_NOTE: return "NOTE";
833 case PT_SHLIB: return "SHLIB";
834 case PT_PHDR: return "PHDR";
835
836 default:
837 if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
838 {
839 const char *result;
840 switch (elf_header.e_machine)
841 {
842 case EM_MIPS:
843 case EM_MIPS_RS4_BE:
844 result = get_mips_segment_type (p_type);
845 break;
846 default:
847 result = NULL;
848 break;
849 }
850 if (result == NULL)
851 {
852 sprintf (buff, "LOPROC+%d", p_type - PT_LOPROC);
853 result = buff;
854 }
855 return result;
856 }
857 else
858 {
859 sprintf (buff, _("<unknown>: %x"), p_type);
860 return buff;
861 }
862 }
863 }
864
865 static const char *
866 get_mips_section_type_name (sh_type)
867 unsigned int sh_type;
868 {
869 switch (sh_type)
870 {
871 case SHT_MIPS_LIBLIST:
872 return "MIPS_LIBLIST";
873 case SHT_MIPS_MSYM:
874 return "MIPS_MSYM";
875 case SHT_MIPS_CONFLICT:
876 return "MIPS_CONFLICT";
877 case SHT_MIPS_GPTAB:
878 return "MIPS_GPTAB";
879 case SHT_MIPS_UCODE:
880 return "MIPS_UCODE";
881 case SHT_MIPS_DEBUG:
882 return "MIPS_DEBUG";
883 case SHT_MIPS_REGINFO:
884 return "MIPS_REGINFO";
885 case SHT_MIPS_PACKAGE:
886 return "MIPS_PACKAGE";
887 case SHT_MIPS_PACKSYM:
888 return "MIPS_PACKSYM";
889 case SHT_MIPS_RELD:
890 return "MIPS_RELD";
891 case SHT_MIPS_IFACE:
892 return "MIPS_IFACE";
893 case SHT_MIPS_CONTENT:
894 return "MIPS_CONTENT";
895 case SHT_MIPS_OPTIONS:
896 return "MIPS_OPTIONS";
897 case SHT_MIPS_SHDR:
898 return "MIPS_SHDR";
899 case SHT_MIPS_FDESC:
900 return "MIPS_FDESC";
901 case SHT_MIPS_EXTSYM:
902 return "MIPS_EXTSYM";
903 case SHT_MIPS_DENSE:
904 return "MIPS_DENSE";
905 case SHT_MIPS_PDESC:
906 return "MIPS_PDESC";
907 case SHT_MIPS_LOCSYM:
908 return "MIPS_LOCSYM";
909 case SHT_MIPS_AUXSYM:
910 return "MIPS_AUXSYM";
911 case SHT_MIPS_OPTSYM:
912 return "MIPS_OPTSYM";
913 case SHT_MIPS_LOCSTR:
914 return "MIPS_LOCSTR";
915 case SHT_MIPS_LINE:
916 return "MIPS_LINE";
917 case SHT_MIPS_RFDESC:
918 return "MIPS_RFDESC";
919 case SHT_MIPS_DELTASYM:
920 return "MIPS_DELTASYM";
921 case SHT_MIPS_DELTAINST:
922 return "MIPS_DELTAINST";
923 case SHT_MIPS_DELTACLASS:
924 return "MIPS_DELTACLASS";
925 case SHT_MIPS_DWARF:
926 return "MIPS_DWARF";
927 case SHT_MIPS_DELTADECL:
928 return "MIPS_DELTADECL";
929 case SHT_MIPS_SYMBOL_LIB:
930 return "MIPS_SYMBOL_LIB";
931 case SHT_MIPS_EVENTS:
932 return "MIPS_EVENTS";
933 case SHT_MIPS_TRANSLATE:
934 return "MIPS_TRANSLATE";
935 case SHT_MIPS_PIXIE:
936 return "MIPS_PIXIE";
937 case SHT_MIPS_XLATE:
938 return "MIPS_XLATE";
939 case SHT_MIPS_XLATE_DEBUG:
940 return "MIPS_XLATE_DEBUG";
941 case SHT_MIPS_WHIRL:
942 return "MIPS_WHIRL";
943 case SHT_MIPS_EH_REGION:
944 return "MIPS_EH_REGION";
945 case SHT_MIPS_XLATE_OLD:
946 return "MIPS_XLATE_OLD";
947 case SHT_MIPS_PDR_EXCEPTION:
948 return "MIPS_PDR_EXCEPTION";
949 default:
950 break;
951 }
952 return NULL;
953 }
954
955 static const char *
956 get_section_type_name (sh_type)
957 unsigned int sh_type;
958 {
959 static char buff [32];
960
961 switch (sh_type)
962 {
963 case SHT_NULL: return "NULL";
964 case SHT_PROGBITS: return "PROGBITS";
965 case SHT_SYMTAB: return "SYMTAB";
966 case SHT_STRTAB: return "STRTAB";
967 case SHT_RELA: return "RELA";
968 case SHT_HASH: return "HASH";
969 case SHT_DYNAMIC: return "DYNAMIC";
970 case SHT_NOTE: return "NOTE";
971 case SHT_NOBITS: return "NOBITS";
972 case SHT_REL: return "REL";
973 case SHT_SHLIB: return "SHLIB";
974 case SHT_DYNSYM: return "DYNSYM";
975 case SHT_GNU_verdef: return "VERDEF";
976 case SHT_GNU_verneed: return "VERNEED";
977 case SHT_GNU_versym: return "VERSYM";
978 case 0x6ffffff0: return "VERSYM";
979 case 0x6ffffffc: return "VERDEF";
980 case 0x7ffffffd: return "AUXILIARY";
981 case 0x7fffffff: return "FILTER";
982
983 default:
984 if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC))
985 {
986 const char *result;
987
988 switch (elf_header.e_machine)
989 {
990 case EM_MIPS:
991 case EM_MIPS_RS4_BE:
992 result = get_mips_section_type_name (sh_type);
993 break;
994 default:
995 result = NULL;
996 break;
997 }
998
999 if (result == NULL)
1000 {
1001 sprintf (buff, _("SHT_LOPROC+%d"), sh_type - SHT_LOPROC);
1002 result = buff;
1003 }
1004 return result;
1005 }
1006 else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER))
1007 sprintf (buff, _("SHT_LOUSER+%d"), sh_type - SHT_LOUSER);
1008 else
1009 sprintf (buff, _("<unknown>: %x"), sh_type);
1010 return buff;
1011 }
1012 }
1013
1014 struct option options [] =
1015 {
1016 {"all", no_argument, 0, 'a'},
1017 {"file-header", no_argument, 0, 'h'},
1018 {"program-headers", no_argument, 0, 'l'},
1019 {"headers", no_argument, 0, 'e'},
1020 {"segments", no_argument, 0, 'l'},
1021 {"sections", no_argument, 0, 'S'},
1022 {"section-headers", no_argument, 0, 'S'},
1023 {"symbols", no_argument, 0, 's'},
1024 {"relocs", no_argument, 0, 'r'},
1025 {"dynamic", no_argument, 0, 'd'},
1026 {"version-info", no_argument, 0, 'V'},
1027 {"use-dynamic", no_argument, 0, 'D'},
1028
1029 {"hex-dump", required_argument, 0, 'x'},
1030 #ifdef SUPPORT_DISASSEMBLY
1031 {"instruction-dump", required_argument, 0, 'i'},
1032 #endif
1033
1034 {"version", no_argument, 0, 'v'},
1035 {"help", no_argument, 0, 'H'},
1036
1037 {0, no_argument, 0, 0}
1038 };
1039
1040 static void
1041 usage ()
1042 {
1043 fprintf (stdout, _("Usage: readelf {options} elf-file(s)\n"));
1044 fprintf (stdout, _(" Options are:\n"));
1045 fprintf (stdout, _(" -a or --all Equivalent to: -h -l -S -s -r -d -V\n"));
1046 fprintf (stdout, _(" -h or --file-header Display the ELF file header\n"));
1047 fprintf (stdout, _(" -l or --program-headers or --segments\n"));
1048 fprintf (stdout, _(" Display the program headers\n"));
1049 fprintf (stdout, _(" -S or --section-headers or --sections\n"));
1050 fprintf (stdout, _(" Display the sections' header\n"));
1051 fprintf (stdout, _(" -e or --headers Equivalent to: -h -l -S\n"));
1052 fprintf (stdout, _(" -s or --symbols Display the symbol table\n"));
1053 fprintf (stdout, _(" -r or --relocs Display the relocations (if present)\n"));
1054 fprintf (stdout, _(" -d or --dynamic Display the dynamic segment (if present)\n"));
1055 fprintf (stdout, _(" -V or --version-info Display the version sections (if present)\n"));
1056 fprintf (stdout, _(" -D or --use-dynamic Use the dynamic section info when displaying symbols\n"));
1057 fprintf (stdout, _(" -x <number> or --hex-dump=<number>\n"));
1058 fprintf (stdout, _(" Dump the contents of section <number>\n"));
1059 #ifdef SUPPORT_DISASSEMBLY
1060 fprintf (stdout, _(" -i <number> or --instruction-dump=<number>\n"));
1061 fprintf (stdout, _(" Disassemble the contents of section <number>\n"));
1062 #endif
1063 fprintf (stdout, _(" -v or --version Display the version number of readelf\n"));
1064 fprintf (stdout, _(" -H or --help Display this information\n"));
1065 fprintf (stdout, _("Report bugs to bug-gnu-utils@gnu.org\n"));
1066
1067 exit (0);
1068 }
1069
1070 static void
1071 parse_args (argc, argv)
1072 int argc;
1073 char ** argv;
1074 {
1075 int c;
1076
1077 if (argc < 2)
1078 usage ();
1079
1080 while ((c = getopt_long
1081 (argc, argv, "ersahldSDx:i:vV", options, NULL)) != EOF)
1082 {
1083 char * cp;
1084 int section;
1085
1086 switch (c)
1087 {
1088 case 'H':
1089 usage ();
1090 break;
1091
1092 case 'a':
1093 do_syms ++;
1094 do_reloc ++;
1095 do_dynamic ++;
1096 do_header ++;
1097 do_sections ++;
1098 do_segments ++;
1099 do_version ++;
1100 break;
1101 case 'e':
1102 do_header ++;
1103 do_sections ++;
1104 do_segments ++;
1105 break;
1106 case 'D':
1107 do_using_dynamic ++;
1108 break;
1109 case 'r':
1110 do_reloc ++;
1111 break;
1112 case 'h':
1113 do_header ++;
1114 break;
1115 case 'l':
1116 do_segments ++;
1117 break;
1118 case 's':
1119 do_syms ++;
1120 break;
1121 case 'S':
1122 do_sections ++;
1123 break;
1124 case 'd':
1125 do_dynamic ++;
1126 break;
1127 case 'x':
1128 do_dump ++;
1129 section = strtoul (optarg, & cp, 0);
1130 if (! * cp && section >= 0 && section < NUM_DUMP_SECTS)
1131 {
1132 dump_sects [section] |= HEX_DUMP;
1133 break;
1134 }
1135 goto oops;
1136 #ifdef SUPPORT_DISASSEMBLY
1137 case 'i':
1138 do_dump ++;
1139 section = strtoul (optarg, & cp, 0);
1140 if (! * cp && section >= 0 && section < NUM_DUMP_SECTS)
1141 {
1142 dump_sects [section] |= DISASS_DUMP;
1143 break;
1144 }
1145 goto oops;
1146 #endif
1147 case 'v':
1148 print_version (program_name);
1149 break;
1150 case 'V':
1151 do_version ++;
1152 break;
1153 default:
1154 oops:
1155 /* xgettext:c-format */
1156 error (_("Invalid option '-%c'\n"), c);
1157 /* Drop through. */
1158 case '?':
1159 usage ();
1160 }
1161 }
1162
1163 if (!do_dynamic && !do_syms && !do_reloc && !do_sections
1164 && !do_segments && !do_header && !do_dump && !do_version)
1165 usage ();
1166 else if (argc < 3)
1167 {
1168 warn (_("Nothing to do.\n"));
1169 usage();
1170 }
1171 }
1172
1173 /* Decode the data held in 'elf_header'. */
1174 static int
1175 process_file_header ()
1176 {
1177 if ( elf_header.e_ident [EI_MAG0] != ELFMAG0
1178 || elf_header.e_ident [EI_MAG1] != ELFMAG1
1179 || elf_header.e_ident [EI_MAG2] != ELFMAG2
1180 || elf_header.e_ident [EI_MAG3] != ELFMAG3)
1181 {
1182 error
1183 (_("Not an ELF file - it has the wrong magic bytes at the start\n"));
1184 return 0;
1185 }
1186
1187 if (elf_header.e_ident [EI_CLASS] != ELFCLASS32)
1188 {
1189 error (_("Not a 32 bit ELF file\n"));
1190 return 0;
1191 }
1192
1193 if (do_header)
1194 {
1195 int i;
1196
1197 printf (_("ELF Header:\n"));
1198 printf (_(" Magic: "));
1199 for (i = 0; i < EI_NIDENT; i ++)
1200 printf ("%2.2x ", elf_header.e_ident [i]);
1201 printf ("\n");
1202 printf (_(" Type: %s\n"),
1203 get_file_type (elf_header.e_type));
1204 printf (_(" Machine: %s\n"),
1205 get_machine_name (elf_header.e_machine));
1206 printf (_(" Version: 0x%lx\n"),
1207 (unsigned long) elf_header.e_version);
1208 printf (_(" Data: %s\n"),
1209 get_machine_data (elf_header.e_ident [EI_DATA]));
1210 printf (_(" Entry point address: 0x%lx\n"),
1211 (unsigned long) elf_header.e_entry);
1212 printf (_(" Start of program headers: %ld (bytes into file)\n"),
1213 (long) elf_header.e_phoff);
1214 printf (_(" Start of section headers: %ld (bytes into file)\n"),
1215 (long) elf_header.e_shoff);
1216 printf (_(" Flags: 0x%lx%s\n"),
1217 (unsigned long) elf_header.e_flags,
1218 get_machine_flags (elf_header.e_flags, elf_header.e_machine));
1219 printf (_(" Size of this header: %ld (bytes)\n"),
1220 (long) elf_header.e_ehsize);
1221 printf (_(" Size of program headers: %ld (bytes)\n"),
1222 (long) elf_header.e_phentsize);
1223 printf (_(" Number of program headers: %ld\n"),
1224 (long) elf_header.e_phnum);
1225 printf (_(" Size of section headers: %ld (bytes)\n"),
1226 (long) elf_header.e_shentsize);
1227 printf (_(" Number of section headers: %ld\n"),
1228 (long) elf_header.e_shnum);
1229 printf (_(" Section header string table index: %ld\n"),
1230 (long) elf_header.e_shstrndx);
1231 }
1232
1233 return 1;
1234 }
1235
1236
1237 static int
1238 process_program_headers (file)
1239 FILE * file;
1240 {
1241 Elf32_External_Phdr * phdrs;
1242 Elf32_Internal_Phdr * program_headers;
1243 Elf32_Internal_Phdr * segment;
1244 unsigned int i;
1245
1246 if (elf_header.e_phnum == 0)
1247 {
1248 if (do_segments)
1249 printf (_("\nThere are no program headers in this file.\n"));
1250 return 1;
1251 }
1252
1253 if (do_segments && !do_header)
1254 {
1255 printf (_("\nElf file is %s\n"), get_file_type (elf_header.e_type));
1256 printf (_("Entry point 0x%lx\n"), (unsigned long) elf_header.e_entry);
1257 printf (_("There are %d program headers, starting at offset %lx:\n"),
1258 elf_header.e_phnum, (unsigned long) elf_header.e_phoff);
1259 }
1260
1261 GET_DATA_ALLOC (elf_header.e_phoff,
1262 elf_header.e_phentsize * elf_header.e_phnum,
1263 phdrs, Elf32_External_Phdr *, "program headers");
1264
1265 program_headers = (Elf32_Internal_Phdr *) malloc
1266 (elf_header.e_phnum * sizeof (Elf32_Internal_Phdr));
1267
1268 if (program_headers == NULL)
1269 {
1270 error (_("Out of memory\n"));
1271 return 0;
1272 }
1273
1274 for (i = 0, segment = program_headers;
1275 i < elf_header.e_phnum;
1276 i ++, segment ++)
1277 {
1278 segment->p_type = BYTE_GET (phdrs[i].p_type);
1279 segment->p_offset = BYTE_GET (phdrs[i].p_offset);
1280 segment->p_vaddr = BYTE_GET (phdrs[i].p_vaddr);
1281 segment->p_paddr = BYTE_GET (phdrs[i].p_paddr);
1282 segment->p_filesz = BYTE_GET (phdrs[i].p_filesz);
1283 segment->p_memsz = BYTE_GET (phdrs[i].p_memsz);
1284 segment->p_flags = BYTE_GET (phdrs[i].p_flags);
1285 segment->p_align = BYTE_GET (phdrs[i].p_align);
1286 }
1287
1288 free (phdrs);
1289
1290 if (do_segments)
1291 {
1292 printf
1293 (_("\nProgram Header%s:\n"), elf_header.e_phnum > 1 ? "s" : "");
1294 printf
1295 (_(" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n"));
1296 }
1297
1298 loadaddr = -1;
1299 dynamic_addr = 0;
1300
1301 for (i = 0, segment = program_headers;
1302 i < elf_header.e_phnum;
1303 i ++, segment ++)
1304 {
1305 if (do_segments)
1306 {
1307 printf (" %-11.11s ", get_segment_type (segment->p_type));
1308 printf ("0x%6.6lx ", (unsigned long) segment->p_offset);
1309 printf ("0x%8.8lx ", (unsigned long) segment->p_vaddr);
1310 printf ("0x%8.8lx ", (unsigned long) segment->p_paddr);
1311 printf ("0x%5.5lx ", (unsigned long) segment->p_filesz);
1312 printf ("0x%5.5lx ", (unsigned long) segment->p_memsz);
1313 printf ("%c%c%c ",
1314 (segment->p_flags & PF_R ? 'R' : ' '),
1315 (segment->p_flags & PF_W ? 'W' : ' '),
1316 (segment->p_flags & PF_X ? 'E' : ' '));
1317 printf ("%#lx", (unsigned long) segment->p_align);
1318 }
1319
1320 switch (segment->p_type)
1321 {
1322 case PT_LOAD:
1323 if (loadaddr == -1)
1324 loadaddr = (segment->p_vaddr & 0xfffff000)
1325 - (segment->p_offset & 0xfffff000);
1326 break;
1327
1328 case PT_DYNAMIC:
1329 if (dynamic_addr)
1330 error (_("more than one dynamic segment\n"));
1331
1332 dynamic_addr = segment->p_offset;
1333 dynamic_size = segment->p_filesz;
1334 break;
1335
1336 case PT_INTERP:
1337 if (fseek (file, segment->p_offset, SEEK_SET))
1338 error (_("Unable to find program interpreter name\n"));
1339 else
1340 {
1341 program_interpreter[0] = 0;
1342 fscanf (file, "%63s", program_interpreter);
1343
1344 if (do_segments)
1345 printf (_("\n [Requesting program interpreter: %s]"),
1346 program_interpreter);
1347 }
1348 break;
1349 }
1350
1351 if (do_segments)
1352 putc ('\n', stdout);
1353 }
1354
1355 if (loadaddr == -1)
1356 {
1357 /* Very strange. */
1358 loadaddr = 0;
1359 }
1360
1361 if (do_segments && section_headers != NULL)
1362 {
1363 printf (_("\n Section to Segment mapping:\n"));
1364 printf (_(" Segment Sections...\n"));
1365
1366 assert (string_table != NULL);
1367
1368 for (i = 0; i < elf_header.e_phnum; i++)
1369 {
1370 int j;
1371 Elf32_Internal_Shdr * section;
1372
1373 segment = program_headers + i;
1374 section = section_headers;
1375
1376 printf (" %2.2d ", i);
1377
1378 for (j = 0; j < elf_header.e_shnum; j++, section ++)
1379 {
1380 if (section->sh_size > 0
1381 /* Compare allocated sections by VMA, unallocated
1382 sections by file offset. */
1383 && (section->sh_flags & SHF_ALLOC
1384 ? (section->sh_addr >= segment->p_vaddr
1385 && section->sh_addr + section->sh_size
1386 <= segment->p_vaddr + segment->p_memsz)
1387 : (section->sh_offset >= segment->p_offset
1388 && (section->sh_offset + section->sh_size
1389 <= segment->p_offset + segment->p_filesz))))
1390 printf ("%s ", SECTION_NAME (section));
1391 }
1392
1393 putc ('\n',stdout);
1394 }
1395 }
1396
1397 free (program_headers);
1398
1399 return 1;
1400 }
1401
1402
1403 static int
1404 get_section_headers (file)
1405 FILE * file;
1406 {
1407 Elf32_External_Shdr * shdrs;
1408 Elf32_Internal_Shdr * internal;
1409 unsigned int i;
1410
1411 GET_DATA_ALLOC (elf_header.e_shoff,
1412 elf_header.e_shentsize * elf_header.e_shnum,
1413 shdrs, Elf32_External_Shdr *, "section headers");
1414
1415 section_headers = (Elf32_Internal_Shdr *) malloc
1416 (elf_header.e_shnum * sizeof (Elf32_Internal_Shdr));
1417
1418 if (section_headers == NULL)
1419 {
1420 error (_("Out of memory\n"));
1421 return 0;
1422 }
1423
1424 for (i = 0, internal = section_headers;
1425 i < elf_header.e_shnum;
1426 i ++, internal ++)
1427 {
1428 internal->sh_name = BYTE_GET (shdrs[i].sh_name);
1429 internal->sh_type = BYTE_GET (shdrs[i].sh_type);
1430 internal->sh_flags = BYTE_GET (shdrs[i].sh_flags);
1431 internal->sh_addr = BYTE_GET (shdrs[i].sh_addr);
1432 internal->sh_offset = BYTE_GET (shdrs[i].sh_offset);
1433 internal->sh_size = BYTE_GET (shdrs[i].sh_size);
1434 internal->sh_link = BYTE_GET (shdrs[i].sh_link);
1435 internal->sh_info = BYTE_GET (shdrs[i].sh_info);
1436 internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
1437 internal->sh_entsize = BYTE_GET (shdrs[i].sh_entsize);
1438 }
1439
1440 free (shdrs);
1441
1442 return 1;
1443 }
1444
1445 static Elf_Internal_Sym *
1446 get_elf_symbols (file, offset, number)
1447 FILE * file;
1448 unsigned long offset;
1449 unsigned long number;
1450 {
1451 Elf32_External_Sym * esyms;
1452 Elf_Internal_Sym * isyms;
1453 Elf_Internal_Sym * psym;
1454 unsigned int j;
1455
1456 GET_DATA_ALLOC (offset, number * sizeof (Elf32_External_Sym),
1457 esyms, Elf32_External_Sym *, "symbols");
1458
1459 isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym));
1460
1461 if (isyms == NULL)
1462 {
1463 error (_("Out of memory\n"));
1464 free (esyms);
1465
1466 return NULL;
1467 }
1468
1469 for (j = 0, psym = isyms;
1470 j < number;
1471 j ++, psym ++)
1472 {
1473 psym->st_name = BYTE_GET (esyms[j].st_name);
1474 psym->st_value = BYTE_GET (esyms[j].st_value);
1475 psym->st_size = BYTE_GET (esyms[j].st_size);
1476 psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
1477 psym->st_info = BYTE_GET (esyms[j].st_info);
1478 psym->st_other = BYTE_GET (esyms[j].st_other);
1479 }
1480
1481 free (esyms);
1482
1483 return isyms;
1484 }
1485
1486 static int
1487 process_section_headers (file)
1488 FILE * file;
1489 {
1490 Elf32_Internal_Shdr * section;
1491 int i;
1492
1493 section_headers = NULL;
1494
1495 if (elf_header.e_shnum == 0)
1496 {
1497 if (do_sections)
1498 printf (_("\nThere are no sections in this file.\n"));
1499
1500 return 1;
1501 }
1502
1503 if (do_sections && !do_header)
1504 printf (_("There are %d section headers, starting at offset %x:\n"),
1505 elf_header.e_shnum, elf_header.e_shoff);
1506
1507 if (! get_section_headers (file))
1508 return 0;
1509
1510 /* Read in the string table, so that we have names to display. */
1511 section = section_headers + elf_header.e_shstrndx;
1512
1513 if (section->sh_size != 0)
1514 {
1515 unsigned long string_table_offset;
1516
1517 string_table_offset = section->sh_offset;
1518
1519 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
1520 string_table, char *, "string table");
1521 }
1522
1523 /* Scan the sections for the dynamic symbol table
1524 and dynamic string table. */
1525 dynamic_symbols = NULL;
1526 dynamic_strings = NULL;
1527 dynamic_syminfo = NULL;
1528 for (i = 0, section = section_headers;
1529 i < elf_header.e_shnum;
1530 i ++, section ++)
1531 {
1532 if (section->sh_type == SHT_DYNSYM)
1533 {
1534 if (dynamic_symbols != NULL)
1535 {
1536 error (_("File contains multiple dynamic symbol tables\n"));
1537 continue;
1538 }
1539
1540 dynamic_symbols = get_elf_symbols
1541 (file, section->sh_offset, section->sh_size / section->sh_entsize);
1542 }
1543 else if (section->sh_type == SHT_STRTAB
1544 && strcmp (SECTION_NAME (section), ".dynstr") == 0)
1545 {
1546 if (dynamic_strings != NULL)
1547 {
1548 error (_("File contains multiple dynamic string tables\n"));
1549 continue;
1550 }
1551
1552 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
1553 dynamic_strings, char *, "dynamic strings");
1554 }
1555 }
1556
1557 if (! do_sections)
1558 return 1;
1559
1560 printf (_("\nSection Header%s:\n"), elf_header.e_shnum > 1 ? "s" : "");
1561 printf
1562 (_(" [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n"));
1563
1564 for (i = 0, section = section_headers;
1565 i < elf_header.e_shnum;
1566 i ++, section ++)
1567 {
1568 printf (" [%2d] %-17.17s %-15.15s ",
1569 i,
1570 SECTION_NAME (section),
1571 get_section_type_name (section->sh_type));
1572
1573 printf ( "%8.8lx %6.6lx %6.6lx %2.2lx",
1574 (unsigned long) section->sh_addr,
1575 (unsigned long) section->sh_offset,
1576 (unsigned long) section->sh_size,
1577 (unsigned long) section->sh_entsize);
1578
1579 printf (" %c%c%c %2ld %3lx %ld \n",
1580 (section->sh_flags & SHF_WRITE ? 'W' : ' '),
1581 (section->sh_flags & SHF_ALLOC ? 'A' : ' '),
1582 (section->sh_flags & SHF_EXECINSTR ? 'X' : ' '),
1583 (unsigned long) section->sh_link,
1584 (unsigned long) section->sh_info,
1585 (unsigned long) section->sh_addralign);
1586 }
1587
1588 return 1;
1589 }
1590
1591 /* Process the reloc section. */
1592 static int
1593 process_relocs (file)
1594 FILE * file;
1595 {
1596 unsigned long rel_size;
1597 unsigned long rel_offset;
1598
1599
1600 if (!do_reloc)
1601 return 1;
1602
1603 if (do_using_dynamic)
1604 {
1605 rel_size = 0;
1606 rel_offset = 0;
1607
1608 if (dynamic_info[DT_REL])
1609 {
1610 rel_offset = dynamic_info[DT_REL];
1611 rel_size = dynamic_info[DT_RELSZ];
1612 }
1613 else if (dynamic_info [DT_RELA])
1614 {
1615 rel_offset = dynamic_info[DT_RELA];
1616 rel_size = dynamic_info[DT_RELASZ];
1617 }
1618 else if (dynamic_info[DT_JMPREL])
1619 {
1620 rel_offset = dynamic_info[DT_JMPREL];
1621 rel_size = dynamic_info[DT_PLTRELSZ];
1622 }
1623
1624 if (rel_size)
1625 {
1626 printf
1627 (_("\nRelocation section at offset 0x%x contains %d bytes:\n"),
1628 rel_offset, rel_size);
1629
1630 dump_relocations (file, rel_offset - loadaddr, rel_size,
1631 dynamic_symbols, dynamic_strings);
1632 }
1633 else
1634 printf (_("\nThere are no dynamic relocations in this file.\n"));
1635 }
1636 else
1637 {
1638 Elf32_Internal_Shdr * section;
1639 unsigned long i;
1640 int found = 0;
1641
1642 for (i = 0, section = section_headers;
1643 i < elf_header.e_shnum;
1644 i++, section ++)
1645 {
1646 if ( section->sh_type != SHT_RELA
1647 && section->sh_type != SHT_REL)
1648 continue;
1649
1650 rel_offset = section->sh_offset;
1651 rel_size = section->sh_size;
1652
1653 if (rel_size)
1654 {
1655 Elf32_Internal_Shdr * strsec;
1656 Elf32_Internal_Shdr * symsec;
1657 Elf_Internal_Sym * symtab;
1658 char * strtab;
1659
1660 printf (_("\nRelocation section "));
1661
1662 if (string_table == NULL)
1663 printf ("%d", section->sh_name);
1664 else
1665 printf ("'%s'", SECTION_NAME (section));
1666
1667 printf (_(" at offset 0x%x contains %d entries:\n"),
1668 rel_offset, rel_size / section->sh_entsize);
1669
1670 symsec = section_headers + section->sh_link;
1671
1672 symtab = get_elf_symbols (file, symsec->sh_offset,
1673 symsec->sh_size / symsec->sh_entsize);
1674
1675 if (symtab == NULL)
1676 continue;
1677
1678 strsec = section_headers + symsec->sh_link;
1679
1680 GET_DATA_ALLOC (strsec->sh_offset, strsec->sh_size, strtab,
1681 char *, "string table");
1682
1683 dump_relocations (file, rel_offset, rel_size, symtab, strtab);
1684
1685 free (strtab);
1686 free (symtab);
1687
1688 found = 1;
1689 }
1690 }
1691
1692 if (! found)
1693 printf (_("\nThere are no relocations in this file.\n"));
1694 }
1695
1696 return 1;
1697 }
1698
1699
1700 static void
1701 dynamic_segment_mips_val (entry)
1702 Elf_Internal_Dyn *entry;
1703 {
1704 if (do_dynamic)
1705 switch (entry->d_tag)
1706 {
1707 case DT_MIPS_FLAGS:
1708 if (entry->d_un.d_val == 0)
1709 printf ("NONE\n");
1710 else
1711 {
1712 static const char *opts[] =
1713 {
1714 "QUICKSTART", "NOTPOT", "NO_LIBRARY_REPLACEMENT",
1715 "NO_MOVE", "SGI_ONLY", "GUARANTEE_INIT", "DELTA_C_PLUS_PLUS",
1716 "GUARANTEE_START_INIT", "PIXIE", "DEFAULT_DELAY_LOAD",
1717 "REQUICKSTART", "REQUICKSTARTED", "CORD", "NO_UNRES_UNDEF",
1718 "RLD_ORDER_SAFE"
1719 };
1720 unsigned int cnt;
1721 int first = 1;
1722 for (cnt = 0; cnt < sizeof (opts) / sizeof (opts[0]); ++cnt)
1723 if (entry->d_un.d_val & (1 << cnt))
1724 {
1725 printf ("%s%s", first ? "" : " ", opts[cnt]);
1726 first = 0;
1727 }
1728 puts ("");
1729 }
1730 break;
1731
1732 case DT_MIPS_IVERSION:
1733 if (dynamic_strings != NULL)
1734 printf ("Interface Version: %s\n",
1735 dynamic_strings + entry->d_un.d_val);
1736 else
1737 printf ("%#ld\n", (long) entry->d_un.d_ptr);
1738 break;
1739
1740 case DT_MIPS_TIME_STAMP:
1741 {
1742 char timebuf[20];
1743 time_t time = entry->d_un.d_val;
1744 strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time));
1745 printf ("Time Stamp: %s\n", timebuf);
1746 }
1747 break;
1748
1749 case DT_MIPS_RLD_VERSION:
1750 case DT_MIPS_LOCAL_GOTNO:
1751 case DT_MIPS_CONFLICTNO:
1752 case DT_MIPS_LIBLISTNO:
1753 case DT_MIPS_SYMTABNO:
1754 case DT_MIPS_UNREFEXTNO:
1755 case DT_MIPS_HIPAGENO:
1756 case DT_MIPS_DELTA_CLASS_NO:
1757 case DT_MIPS_DELTA_INSTANCE_NO:
1758 case DT_MIPS_DELTA_RELOC_NO:
1759 case DT_MIPS_DELTA_SYM_NO:
1760 case DT_MIPS_DELTA_CLASSSYM_NO:
1761 case DT_MIPS_COMPACT_SIZE:
1762 printf ("%#ld\n", (long) entry->d_un.d_ptr);
1763 break;
1764
1765 default:
1766 printf ("%#lx\n", (long) entry->d_un.d_ptr);
1767 }
1768 }
1769
1770 /* Parse the dynamic segment */
1771 static int
1772 process_dynamic_segment (file)
1773 FILE * file;
1774 {
1775 Elf_Internal_Dyn * entry;
1776 Elf32_External_Dyn * edyn;
1777 unsigned int i;
1778
1779 if (dynamic_size == 0)
1780 {
1781 if (do_dynamic)
1782 printf (_("\nThere is no dynamic segment in this file.\n"));
1783
1784 return 1;
1785 }
1786
1787 GET_DATA_ALLOC (dynamic_addr, dynamic_size,
1788 edyn, Elf32_External_Dyn *, "dynamic segment");
1789
1790 /* SGI's ELF has more than one section in the DYNAMIC segment. Determine
1791 how large .dynamic is now. We can do this even before the byte
1792 swapping since the DT_NULL tag is recognizable. */
1793 dynamic_size = 0;
1794 while (*(Elf32_Word *) edyn[dynamic_size++].d_tag != DT_NULL)
1795 ;
1796
1797 dynamic_segment = (Elf_Internal_Dyn *)
1798 malloc (dynamic_size * sizeof (Elf_Internal_Dyn));
1799
1800 if (dynamic_segment == NULL)
1801 {
1802 error (_("Out of memory\n"));
1803 free (edyn);
1804 return 0;
1805 }
1806
1807 for (i = 0, entry = dynamic_segment;
1808 i < dynamic_size;
1809 i ++, entry ++)
1810 {
1811 entry->d_tag = BYTE_GET (edyn [i].d_tag);
1812 entry->d_un.d_val = BYTE_GET (edyn [i].d_un.d_val);
1813 }
1814
1815 free (edyn);
1816
1817 /* Find the appropriate symbol table. */
1818 if (dynamic_symbols == NULL)
1819 {
1820 for (i = 0, entry = dynamic_segment;
1821 i < dynamic_size;
1822 ++i, ++ entry)
1823 {
1824 unsigned long offset;
1825 long num_syms;
1826
1827 if (entry->d_tag != DT_SYMTAB)
1828 continue;
1829
1830 dynamic_info[DT_SYMTAB] = entry->d_un.d_val;
1831
1832 /* Since we do not know how big the symbol table is,
1833 we default to reading in the entire file (!) and
1834 processing that. This is overkill, I know, but it
1835 should work. */
1836
1837 offset = entry->d_un.d_val - loadaddr;
1838
1839 if (fseek (file, 0, SEEK_END))
1840 error (_("Unable to seek to end of file!"));
1841
1842 num_syms = (ftell (file) - offset) / sizeof (Elf32_External_Sym);
1843
1844 if (num_syms < 1)
1845 {
1846 error (_("Unable to determine the number of symbols to load\n"));
1847 continue;
1848 }
1849
1850 dynamic_symbols = get_elf_symbols (file, offset, num_syms);
1851 }
1852 }
1853
1854 /* Similarly find a string table. */
1855 if (dynamic_strings == NULL)
1856 {
1857 for (i = 0, entry = dynamic_segment;
1858 i < dynamic_size;
1859 ++i, ++ entry)
1860 {
1861 unsigned long offset;
1862 long str_tab_len;
1863
1864 if (entry->d_tag != DT_STRTAB)
1865 continue;
1866
1867 dynamic_info[DT_STRTAB] = entry->d_un.d_val;
1868
1869 /* Since we do not know how big the string table is,
1870 we default to reading in the entire file (!) and
1871 processing that. This is overkill, I know, but it
1872 should work. */
1873
1874 offset = entry->d_un.d_val - loadaddr;
1875 if (fseek (file, 0, SEEK_END))
1876 error (_("Unable to seek to end of file\n"));
1877 str_tab_len = ftell (file) - offset;
1878
1879 if (str_tab_len < 1)
1880 {
1881 error
1882 (_("Unable to determine the length of the dynamic string table\n"));
1883 continue;
1884 }
1885
1886 GET_DATA_ALLOC (offset, str_tab_len, dynamic_strings, char *,
1887 "dynamic string table");
1888
1889 break;
1890 }
1891 }
1892
1893 /* And find the syminfo section if available. */
1894 if (dynamic_syminfo == NULL)
1895 {
1896 unsigned int syminsz = 0;
1897
1898 for (i = 0, entry = dynamic_segment;
1899 i < dynamic_size;
1900 ++i, ++ entry)
1901 {
1902 if (entry->d_tag == DT_SYMINENT)
1903 assert (sizeof (Elf_External_Syminfo) == entry->d_un.d_val);
1904 else if (entry->d_tag == DT_SYMINSZ)
1905 syminsz = entry->d_un.d_val;
1906 else if (entry->d_tag == DT_SYMINFO)
1907 dynamic_syminfo_offset = entry->d_un.d_val - loadaddr;
1908 }
1909
1910 if (dynamic_syminfo_offset != 0 && syminsz != 0)
1911 {
1912 Elf_External_Syminfo *extsyminfo;
1913 Elf_Internal_Syminfo *syminfo;
1914
1915 /* There is a syminfo section. Read the data. */
1916 GET_DATA_ALLOC (dynamic_syminfo_offset, syminsz, extsyminfo,
1917 Elf_External_Syminfo *, "symbol information");
1918
1919 dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz);
1920 if (dynamic_syminfo == NULL)
1921 {
1922 error (_("Out of memory\n"));
1923 return 0;
1924 }
1925
1926 dynamic_syminfo_nent = syminsz / sizeof (Elf_External_Syminfo);
1927 for (i = 0, syminfo = dynamic_syminfo; i < dynamic_syminfo_nent;
1928 ++i, ++syminfo)
1929 {
1930 syminfo->si_boundto = BYTE_GET (extsyminfo[i].si_boundto);
1931 syminfo->si_flags = BYTE_GET (extsyminfo[i].si_flags);
1932 }
1933
1934 free (extsyminfo);
1935 }
1936 }
1937
1938 if (do_dynamic && dynamic_addr)
1939 printf (_("\nDynamic segment at offset 0x%x contains %d entries:\n"),
1940 dynamic_addr, dynamic_size);
1941 if (do_dynamic)
1942 printf (_(" Tag Type Name/Value\n"));
1943
1944 for (i = 0, entry = dynamic_segment;
1945 i < dynamic_size;
1946 i++, entry ++)
1947 {
1948 if (do_dynamic)
1949 printf (_(" 0x%-8.8lx (%s)%*s"),
1950 (unsigned long) entry->d_tag,
1951 get_dynamic_type (entry->d_tag),
1952 27 - strlen (get_dynamic_type (entry->d_tag)),
1953 " ");
1954
1955 switch (entry->d_tag)
1956 {
1957 case DT_AUXILIARY:
1958 case DT_FILTER:
1959 if (do_dynamic)
1960 {
1961 if (entry->d_tag == DT_AUXILIARY)
1962 printf (_("Auxiliary library"));
1963 else
1964 printf (_("Filter library"));
1965
1966 if (dynamic_strings)
1967 printf (": [%s]\n", dynamic_strings + entry->d_un.d_val);
1968 else
1969 printf (": %#lx\n", (long) entry->d_un.d_val);
1970 }
1971 break;
1972
1973 case DT_POSFLAG_1:
1974 if (do_dynamic)
1975 {
1976 printf (_("Flags:"));
1977 if (entry->d_un.d_val == 0)
1978 printf (_(" None\n"));
1979 else
1980 {
1981 if (entry->d_un.d_val & DF_P1_LAZYLOAD)
1982 printf (" LAZYLOAD");
1983 if (entry->d_un.d_val & DF_P1_LAZYLOAD)
1984 printf (" GROUPPERM");
1985 puts ("");
1986 }
1987 }
1988 break;
1989
1990 case DT_FLAGS_1:
1991 if (do_dynamic)
1992 {
1993 printf (_("Flags:"));
1994 if (entry->d_un.d_val == 0)
1995 printf (_(" None\n"));
1996 else
1997 {
1998 if (entry->d_un.d_val & DF_1_NOW)
1999 printf (" NOW");
2000 if (entry->d_un.d_val & DF_1_GLOBAL)
2001 printf (" GLOBAL");
2002 if (entry->d_un.d_val & DF_1_GROUP)
2003 printf (" GROUP");
2004 if (entry->d_un.d_val & DF_1_NODELETE)
2005 printf (" NODELETE");
2006 if (entry->d_un.d_val & DF_1_LOADFLTR)
2007 printf (" LOADFLTR");
2008 if (entry->d_un.d_val & DF_1_INITFIRST)
2009 printf (" INITFIRST");
2010 if (entry->d_un.d_val & DF_1_NOOPEN)
2011 printf (" NOOPEN");
2012 if (entry->d_un.d_val & DF_1_ORIGIN)
2013 printf (" ORIGIN");
2014 if (entry->d_un.d_val & DF_1_DIRECT)
2015 printf (" DIRECT");
2016 if (entry->d_un.d_val & DF_1_TRANS)
2017 printf (" TRANS");
2018 if (entry->d_un.d_val & DF_1_INTERPOSE)
2019 printf (" INTERPOSE");
2020 puts ("");
2021 }
2022 }
2023 break;
2024
2025 case DT_NULL :
2026 case DT_NEEDED :
2027 case DT_PLTRELSZ:
2028 case DT_PLTGOT :
2029 case DT_HASH :
2030 case DT_STRTAB :
2031 case DT_SYMTAB :
2032 case DT_RELA :
2033 case DT_INIT :
2034 case DT_FINI :
2035 case DT_SONAME :
2036 case DT_RPATH :
2037 case DT_SYMBOLIC:
2038 case DT_REL :
2039 case DT_PLTREL :
2040 case DT_DEBUG :
2041 case DT_TEXTREL :
2042 case DT_JMPREL :
2043 dynamic_info[entry->d_tag] = entry->d_un.d_val;
2044
2045 if (do_dynamic)
2046 {
2047 char * name;
2048
2049 if (dynamic_strings == NULL)
2050 name = NULL;
2051 else
2052 name = dynamic_strings + entry->d_un.d_val;
2053
2054 if (name)
2055 {
2056 switch (entry->d_tag)
2057 {
2058 case DT_NEEDED:
2059 printf (_("Shared library: [%s]"), name);
2060
2061 if (strcmp (name, program_interpreter))
2062 printf ("\n");
2063 else
2064 printf (_(" program interpreter\n"));
2065 break;
2066
2067 case DT_SONAME:
2068 printf (_("Library soname: [%s]\n"), name);
2069 break;
2070
2071 case DT_RPATH:
2072 printf (_("Library rpath: [%s]\n"), name);
2073 break;
2074
2075 default:
2076 printf ("%#lx\n", (long) entry->d_un.d_val);
2077 }
2078 }
2079 else
2080 printf ("%#lx\n", (long) entry->d_un.d_val);
2081 }
2082 break;
2083
2084 case DT_RELASZ :
2085 case DT_RELAENT :
2086 case DT_STRSZ :
2087 case DT_SYMENT :
2088 case DT_RELSZ :
2089 case DT_RELENT :
2090 case DT_VERDEFNUM:
2091 case DT_VERNEEDNUM:
2092 case DT_RELACOUNT:
2093 case DT_RELCOUNT:
2094 printf ("%ld\n", entry->d_un.d_val);
2095 break;
2096
2097 case DT_SYMINSZ :
2098 case DT_SYMINENT:
2099 case DT_SYMINFO :
2100 case DT_USED:
2101 if (do_dynamic)
2102 {
2103 char * name;
2104
2105 if (dynamic_strings == NULL)
2106 name = NULL;
2107 else
2108 name = dynamic_strings + entry->d_un.d_val;
2109
2110
2111
2112 if (name)
2113 {
2114 switch (entry->d_tag)
2115 {
2116 case DT_USED:
2117 printf (_("Not needed object: [%s]\n"), name);
2118 break;
2119
2120 default:
2121 printf ("%#lx\n", (long) entry->d_un.d_val);
2122 }
2123 }
2124 else
2125 printf ("%#lx\n", (long) entry->d_un.d_val);
2126 }
2127 break;
2128
2129 default:
2130 if ((entry->d_tag >= DT_VERSYM) && (entry->d_tag <= DT_VERNEEDNUM))
2131 {
2132 version_info [DT_VERSIONTAGIDX (entry->d_tag)] =
2133 entry->d_un.d_val;
2134
2135 if (do_dynamic)
2136 printf ("%#lx\n", (long) entry->d_un.d_ptr);
2137 }
2138 else
2139 switch (elf_header.e_machine)
2140 {
2141 case EM_MIPS:
2142 case EM_MIPS_RS4_BE:
2143 dynamic_segment_mips_val (entry);
2144 break;
2145 default:
2146 if (do_dynamic)
2147 printf ("%#lx\n", (long) entry->d_un.d_ptr);
2148 }
2149 break;
2150 }
2151 }
2152
2153 return 1;
2154 }
2155
2156 static char *
2157 get_ver_flags (flags)
2158 unsigned int flags;
2159 {
2160 static char buff [32];
2161
2162 buff[0] = 0;
2163
2164 if (flags == 0)
2165 return _("none");
2166
2167 if (flags & VER_FLG_BASE)
2168 strcat (buff, "BASE ");
2169
2170 if (flags & VER_FLG_WEAK)
2171 {
2172 if (flags & VER_FLG_BASE)
2173 strcat (buff, "| ");
2174
2175 strcat (buff, "WEAK ");
2176 }
2177
2178 if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK))
2179 strcat (buff, "| <unknown>");
2180
2181 return buff;
2182 }
2183
2184 /* Display the contents of the version sections. */
2185 static int
2186 process_version_sections (file)
2187 FILE * file;
2188 {
2189 Elf32_Internal_Shdr * section;
2190 unsigned i;
2191 int found = 0;
2192
2193 if (! do_version)
2194 return 1;
2195
2196 for (i = 0, section = section_headers;
2197 i < elf_header.e_shnum;
2198 i++, section ++)
2199 {
2200 switch (section->sh_type)
2201 {
2202 case SHT_GNU_verdef:
2203 {
2204 Elf_External_Verdef * edefs;
2205 unsigned int idx;
2206 unsigned int cnt;
2207
2208 found = 1;
2209
2210 printf
2211 (_("\nVersion definition section '%s' contains %d entries:\n"),
2212 SECTION_NAME (section), section->sh_info);
2213
2214 printf (_(" Addr: %#08x Offset: %#08x Link: %x (%s)\n"),
2215 section->sh_addr, section->sh_offset, section->sh_link,
2216 SECTION_NAME (section_headers + section->sh_link));
2217
2218 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
2219 edefs, Elf_External_Verdef *,
2220 "version definition section");
2221
2222 for (idx = cnt = 0; cnt < section->sh_info; ++ cnt)
2223 {
2224 char * vstart;
2225 Elf_External_Verdef * edef;
2226 Elf_Internal_Verdef ent;
2227 Elf_External_Verdaux * eaux;
2228 Elf_Internal_Verdaux aux;
2229 int j;
2230 int isum;
2231
2232 vstart = ((char *) edefs) + idx;
2233
2234 edef = (Elf_External_Verdef *) vstart;
2235
2236 ent.vd_version = BYTE_GET (edef->vd_version);
2237 ent.vd_flags = BYTE_GET (edef->vd_flags);
2238 ent.vd_ndx = BYTE_GET (edef->vd_ndx);
2239 ent.vd_cnt = BYTE_GET (edef->vd_cnt);
2240 ent.vd_hash = BYTE_GET (edef->vd_hash);
2241 ent.vd_aux = BYTE_GET (edef->vd_aux);
2242 ent.vd_next = BYTE_GET (edef->vd_next);
2243
2244 printf (_(" %#06x: Rev: %d Flags: %s"),
2245 idx, ent.vd_version, get_ver_flags (ent.vd_flags));
2246
2247 printf (_(" Index: %ld Cnt: %ld "), ent.vd_ndx, ent.vd_cnt);
2248
2249 vstart += ent.vd_aux;
2250
2251 eaux = (Elf_External_Verdaux *) vstart;
2252
2253 aux.vda_name = BYTE_GET (eaux->vda_name);
2254 aux.vda_next = BYTE_GET (eaux->vda_next);
2255
2256 if (dynamic_strings)
2257 printf (_("Name: %s\n"), dynamic_strings + aux.vda_name);
2258 else
2259 printf (_("Name index: %ld\n"), aux.vda_name);
2260
2261 isum = idx + ent.vd_aux;
2262
2263 for (j = 1; j < ent.vd_cnt; j ++)
2264 {
2265 isum += aux.vda_next;
2266 vstart += aux.vda_next;
2267
2268 eaux = (Elf_External_Verdaux *) vstart;
2269
2270 aux.vda_name = BYTE_GET (eaux->vda_name);
2271 aux.vda_next = BYTE_GET (eaux->vda_next);
2272
2273 if (dynamic_strings)
2274 printf (_(" %#06x: Parent %d: %s\n"),
2275 isum, j, dynamic_strings + aux.vda_name);
2276 else
2277 printf (_(" %#06x: Parent %d, name index: %ld\n"),
2278 isum, j, aux.vda_name);
2279 }
2280
2281 idx += ent.vd_next;
2282 }
2283
2284 free (edefs);
2285 }
2286 break;
2287
2288 case SHT_GNU_verneed:
2289 {
2290 Elf_External_Verneed * eneed;
2291 unsigned int idx;
2292 unsigned int cnt;
2293
2294 found = 1;
2295
2296 printf (_("\nVersion needs section '%s' contains %d entries:\n"),
2297 SECTION_NAME (section), section->sh_info);
2298
2299 printf
2300 (_(" Addr: %#08x Offset: %#08x Link to section: %d (%s)\n"),
2301 section->sh_addr, section->sh_offset, section->sh_link,
2302 SECTION_NAME (section_headers + section->sh_link));
2303
2304 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
2305 eneed, Elf_External_Verneed *,
2306 "version need section");
2307
2308 for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
2309 {
2310 Elf_External_Verneed * entry;
2311 Elf_Internal_Verneed ent;
2312 int j;
2313 int isum;
2314 char * vstart;
2315
2316 vstart = ((char *) eneed) + idx;
2317
2318 entry = (Elf_External_Verneed *) vstart;
2319
2320 ent.vn_version = BYTE_GET (entry->vn_version);
2321 ent.vn_cnt = BYTE_GET (entry->vn_cnt);
2322 ent.vn_file = BYTE_GET (entry->vn_file);
2323 ent.vn_aux = BYTE_GET (entry->vn_aux);
2324 ent.vn_next = BYTE_GET (entry->vn_next);
2325
2326 printf (_(" %#06x: Version: %d"), idx, ent.vn_version);
2327
2328 if (dynamic_strings)
2329 printf (_(" File: %s"), dynamic_strings + ent.vn_file);
2330 else
2331 printf (_(" File: %lx"), ent.vn_file);
2332
2333 printf (_(" Cnt: %d\n"), ent.vn_cnt);
2334
2335 vstart += ent.vn_aux;
2336
2337 for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j)
2338 {
2339 Elf_External_Vernaux * eaux;
2340 Elf_Internal_Vernaux aux;
2341
2342 eaux = (Elf_External_Vernaux *) vstart;
2343
2344 aux.vna_hash = BYTE_GET (eaux->vna_hash);
2345 aux.vna_flags = BYTE_GET (eaux->vna_flags);
2346 aux.vna_other = BYTE_GET (eaux->vna_other);
2347 aux.vna_name = BYTE_GET (eaux->vna_name);
2348 aux.vna_next = BYTE_GET (eaux->vna_next);
2349
2350 if (dynamic_strings)
2351 printf (_(" %#06x: Name: %s"),
2352 isum, dynamic_strings + aux.vna_name);
2353 else
2354 printf (_(" %#06x: Name index: %lx"),
2355 isum, aux.vna_name);
2356
2357 printf (_(" Flags: %s Version: %d\n"),
2358 get_ver_flags (aux.vna_flags), aux.vna_other);
2359
2360 isum += aux.vna_next;
2361 vstart += aux.vna_next;
2362 }
2363
2364 idx += ent.vn_next;
2365 }
2366
2367 free (eneed);
2368 }
2369 break;
2370
2371 case SHT_GNU_versym:
2372 {
2373 Elf32_Internal_Shdr * link_section;
2374 int total;
2375 int cnt;
2376 unsigned char * edata;
2377 unsigned short * data;
2378 char * strtab;
2379 Elf_Internal_Sym * symbols;
2380 Elf32_Internal_Shdr * string_sec;
2381
2382 link_section = section_headers + section->sh_link;
2383 total = section->sh_size / section->sh_entsize;
2384
2385 found = 1;
2386
2387 symbols = get_elf_symbols
2388 (file, link_section->sh_offset,
2389 link_section->sh_size / link_section->sh_entsize);
2390
2391 string_sec = section_headers + link_section->sh_link;
2392
2393 GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
2394 strtab, char *, "version string table");
2395
2396 printf (_("\nVersion symbols section '%s' contains %d entries:\n"),
2397 SECTION_NAME (section), total);
2398
2399 printf (_(" Addr: %#08x Offset: %#08x Link: %x (%s)\n"),
2400 section->sh_addr, section->sh_offset, section->sh_link,
2401 SECTION_NAME (link_section));
2402
2403 GET_DATA_ALLOC (version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
2404 - loadaddr,
2405 total * sizeof (short), edata,
2406 char *, "version symbol data");
2407
2408 data = (unsigned short *) malloc (total * sizeof (short));
2409
2410 for (cnt = total; cnt --;)
2411 data [cnt] = byte_get (edata + cnt * sizeof (short), sizeof (short));
2412
2413 free (edata);
2414
2415 for (cnt = 0; cnt < total; cnt += 4)
2416 {
2417 int j, nn;
2418
2419 printf (" %03x:", cnt);
2420
2421 for (j = 0; (j < 4) && (cnt + j) < total; ++j)
2422 switch (data [cnt + j])
2423 {
2424 case 0:
2425 fputs (_(" 0 (*local*) "), stdout);
2426 break;
2427
2428 case 1:
2429 fputs (_(" 1 (*global*) "), stdout);
2430 break;
2431
2432 default:
2433 nn = printf ("%4x%c", data [cnt + j] & 0x7fff,
2434 data [cnt + j] & 0x8000 ? 'h' : ' ');
2435
2436 if (symbols [cnt + j].st_shndx < SHN_LORESERVE
2437 && section_headers[symbols [cnt + j].st_shndx].sh_type
2438 == SHT_NOBITS)
2439 {
2440 /* We must test both. */
2441 Elf_Internal_Verneed ivn;
2442 unsigned long offset;
2443
2444 offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
2445 - loadaddr;
2446
2447 do
2448 {
2449 Elf_External_Verneed evn;
2450 Elf_External_Vernaux evna;
2451 Elf_Internal_Vernaux ivna;
2452 unsigned long vna_off;
2453
2454 GET_DATA (offset, evn, "version need");
2455
2456 ivn.vn_aux = BYTE_GET (evn.vn_aux);
2457 ivn.vn_next = BYTE_GET (evn.vn_next);
2458
2459 vna_off = offset + ivn.vn_aux;
2460
2461 do
2462 {
2463 GET_DATA (vna_off, evna,
2464 "version need aux (1)");
2465
2466 ivna.vna_next = BYTE_GET (evna.vna_next);
2467 ivna.vna_other = BYTE_GET (evna.vna_other);
2468
2469 vna_off += ivna.vna_next;
2470 }
2471 while (ivna.vna_other != data [cnt + j]
2472 && ivna.vna_next != 0);
2473
2474 if (ivna.vna_other == data [cnt + j])
2475 {
2476 ivna.vna_name = BYTE_GET (evna.vna_name);
2477
2478 nn += printf ("(%s%-*s",
2479 strtab + ivna.vna_name,
2480 12 - strlen (strtab
2481 + ivna.vna_name),
2482 ")");
2483 break;
2484 }
2485 else if (ivn.vn_next == 0)
2486 {
2487 if (data [cnt + j] != 0x8001)
2488 {
2489 Elf_Internal_Verdef ivd;
2490 Elf_External_Verdef evd;
2491
2492 offset = version_info
2493 [DT_VERSIONTAGIDX (DT_VERDEF)]
2494 - loadaddr;
2495
2496 do
2497 {
2498 GET_DATA (offset, evd,
2499 "version definition");
2500
2501 ivd.vd_next = BYTE_GET (evd.vd_next);
2502 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
2503
2504 offset += ivd.vd_next;
2505 }
2506 while (ivd.vd_ndx
2507 != (data [cnt + j] & 0x7fff)
2508 && ivd.vd_next != 0);
2509
2510 if (ivd.vd_ndx
2511 == (data [cnt + j] & 0x7fff))
2512 {
2513 Elf_External_Verdaux evda;
2514 Elf_Internal_Verdaux ivda;
2515
2516 ivd.vd_aux = BYTE_GET (evd.vd_aux);
2517
2518 GET_DATA (offset + ivd.vd_aux, evda,
2519 "version definition aux");
2520
2521 ivda.vda_name =
2522 BYTE_GET (evda.vda_name);
2523
2524 nn +=
2525 printf ("(%s%-*s",
2526 strtab + ivda.vda_name,
2527 12
2528 - strlen (strtab
2529 + ivda.vda_name),
2530 ")");
2531 }
2532 }
2533
2534 break;
2535 }
2536 else
2537 offset += ivn.vn_next;
2538 }
2539 while (ivn.vn_next);
2540 }
2541 else if (symbols [cnt + j].st_shndx == SHN_UNDEF)
2542 {
2543 Elf_Internal_Verneed ivn;
2544 unsigned long offset;
2545
2546 offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
2547 - loadaddr;
2548
2549 do
2550 {
2551 Elf_Internal_Vernaux ivna;
2552 Elf_External_Verneed evn;
2553 Elf_External_Vernaux evna;
2554 unsigned long a_off;
2555
2556 GET_DATA (offset, evn, "version need");
2557
2558 ivn.vn_aux = BYTE_GET (evn.vn_aux);
2559 ivn.vn_next = BYTE_GET (evn.vn_next);
2560
2561 a_off = offset + ivn.vn_aux;
2562
2563 do
2564 {
2565 GET_DATA (a_off, evna,
2566 "version need aux (2)");
2567
2568 ivna.vna_next = BYTE_GET (evna.vna_next);
2569 ivna.vna_other = BYTE_GET (evna.vna_other);
2570
2571 a_off += ivna.vna_next;
2572 }
2573 while (ivna.vna_other != data [cnt + j]
2574 && ivna.vna_next != 0);
2575
2576 if (ivna.vna_other == data [cnt + j])
2577 {
2578 ivna.vna_name = BYTE_GET (evna.vna_name);
2579
2580 nn += printf ("(%s%-*s",
2581 strtab + ivna.vna_name,
2582 12 - strlen (strtab
2583 + ivna.vna_name),
2584 ")");
2585 break;
2586 }
2587
2588 offset += ivn.vn_next;
2589 }
2590 while (ivn.vn_next);
2591 }
2592 else if (data [cnt + j] != 0x8001)
2593 {
2594 Elf_Internal_Verdef ivd;
2595 Elf_External_Verdef evd;
2596 unsigned long offset;
2597
2598 offset = version_info
2599 [DT_VERSIONTAGIDX (DT_VERDEF)] - loadaddr;
2600
2601 do
2602 {
2603 GET_DATA (offset, evd, "version def");
2604
2605 ivd.vd_next = BYTE_GET (evd.vd_next);
2606 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
2607
2608 offset += ivd.vd_next;
2609 }
2610 while (ivd.vd_ndx != (data [cnt + j] & 0x7fff)
2611 && ivd.vd_next != 0);
2612
2613 if (ivd.vd_ndx == (data [cnt + j] & 0x7fff))
2614 {
2615 Elf_External_Verdaux evda;
2616 Elf_Internal_Verdaux ivda;
2617
2618 ivd.vd_aux = BYTE_GET (evd.vd_aux);
2619
2620 GET_DATA (offset - ivd.vd_next + ivd.vd_aux,
2621 evda, "version def aux");
2622
2623 ivda.vda_name = BYTE_GET (evda.vda_name);
2624
2625 nn += printf ("(%s%-*s",
2626 strtab + ivda.vda_name,
2627 12 - strlen (strtab
2628 + ivda.vda_name),
2629 ")");
2630 }
2631 }
2632
2633 if (nn < 18)
2634 printf ("%*c", 18 - nn, ' ');
2635 }
2636
2637 putchar ('\n');
2638 }
2639
2640 free (data);
2641 free (strtab);
2642 free (symbols);
2643 }
2644 break;
2645
2646 default:
2647 break;
2648 }
2649 }
2650
2651 if (! found)
2652 printf (_("\nNo version information found in this file.\n"));
2653
2654 return 1;
2655 }
2656
2657 static char *
2658 get_symbol_binding (binding)
2659 unsigned int binding;
2660 {
2661 static char buff [32];
2662
2663 switch (binding)
2664 {
2665 case STB_LOCAL: return _("LOCAL");
2666 case STB_GLOBAL: return _("GLOBAL");
2667 case STB_WEAK: return _("WEAK");
2668 default:
2669 if (binding >= STB_LOPROC && binding <= STB_HIPROC)
2670 sprintf (buff, _("<processor specific>: %d"), binding);
2671 else
2672 sprintf (buff, _("<unknown>: %d"), binding);
2673 return buff;
2674 }
2675 }
2676
2677 static char *
2678 get_symbol_type (type)
2679 unsigned int type;
2680 {
2681 static char buff [32];
2682
2683 switch (type)
2684 {
2685 case STT_NOTYPE: return _("NOTYPE");
2686 case STT_OBJECT: return _("OBJECT");
2687 case STT_FUNC: return _("FUNC");
2688 case STT_SECTION: return _("SECTION");
2689 case STT_FILE: return _("FILE");
2690 default:
2691 if (type >= STT_LOPROC && type <= STT_HIPROC)
2692 sprintf (buff, _("<processor specific>: %d"), type);
2693 else
2694 sprintf (buff, _("<unknown>: %d"), type);
2695 return buff;
2696 }
2697 }
2698
2699 static char *
2700 get_symbol_index_type (type)
2701 unsigned int type;
2702 {
2703 switch (type)
2704 {
2705 case SHN_UNDEF: return "UND";
2706 case SHN_ABS: return "ABS";
2707 case SHN_COMMON: return "COM";
2708 default:
2709 if (type >= SHN_LOPROC && type <= SHN_HIPROC)
2710 return "PRC";
2711 else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE)
2712 return "RSV";
2713 else
2714 {
2715 static char buff [32];
2716
2717 sprintf (buff, "%3d", type);
2718 return buff;
2719 }
2720 }
2721 }
2722
2723
2724 static int *
2725 get_dynamic_data (file, number)
2726 FILE * file;
2727 unsigned int number;
2728 {
2729 char * e_data;
2730 int * i_data;
2731
2732 e_data = (char *) malloc (number * 4);
2733
2734 if (e_data == NULL)
2735 {
2736 error (_("Out of memory\n"));
2737 return NULL;
2738 }
2739
2740 if (fread (e_data, 4, number, file) != number)
2741 {
2742 error (_("Unable to read in dynamic data\n"));
2743 return NULL;
2744 }
2745
2746 i_data = (int *) malloc (number * sizeof (* i_data));
2747
2748 if (i_data == NULL)
2749 {
2750 error (_("Out of memory\n"));
2751 free (e_data);
2752 return NULL;
2753 }
2754
2755 while (number--)
2756 i_data [number] = byte_get (e_data + number * 4, 4);
2757
2758 free (e_data);
2759
2760 return i_data;
2761 }
2762
2763 /* Dump the symbol table */
2764 static int
2765 process_symbol_table (file)
2766 FILE * file;
2767 {
2768 Elf32_Internal_Shdr * section;
2769
2770 if (! do_syms)
2771 return 1;
2772
2773 if (dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL)
2774 {
2775 char nb [4];
2776 char nc [4];
2777 int nbuckets;
2778 int nchains;
2779 int * buckets;
2780 int * chains;
2781 int hn;
2782 int si;
2783
2784 if (fseek (file, dynamic_info[DT_HASH] - loadaddr, SEEK_SET))
2785 {
2786 error (_("Unable to seek to start of dynamic information"));
2787 return 0;
2788 }
2789
2790 if (fread (& nb, sizeof (nb), 1, file) != 1)
2791 {
2792 error (_("Failed to read in number of buckets\n"));
2793 return 0;
2794 }
2795
2796 if (fread (& nc, sizeof (nc), 1, file) != 1)
2797 {
2798 error (_("Failed to read in number of chains\n"));
2799 return 0;
2800 }
2801
2802 nbuckets = byte_get (nb, 4);
2803 nchains = byte_get (nc, 4);
2804
2805 buckets = get_dynamic_data (file, nbuckets);
2806 chains = get_dynamic_data (file, nchains);
2807
2808 if (buckets == NULL || chains == NULL)
2809 return 0;
2810
2811 printf (_("\nSymbol table for image:\n"));
2812 printf (_(" Num Buc: Value Size Type Bind Ot Ndx Name\n"));
2813
2814 for (hn = 0; hn < nbuckets; hn++)
2815 {
2816 if (! buckets [hn])
2817 continue;
2818
2819 for (si = buckets [hn]; si; si = chains [si])
2820 {
2821 Elf_Internal_Sym * psym;
2822
2823 psym = dynamic_symbols + si;
2824
2825 printf (" %3d %3d: %8lx %5ld %6s %6s %2d ",
2826 si, hn,
2827 (unsigned long) psym->st_value,
2828 (unsigned long) psym->st_size,
2829 get_symbol_type (ELF_ST_TYPE (psym->st_info)),
2830 get_symbol_binding (ELF_ST_BIND (psym->st_info)),
2831 psym->st_other);
2832
2833 printf ("%3.3s", get_symbol_index_type (psym->st_shndx));
2834
2835 printf (" %s\n", dynamic_strings + psym->st_name);
2836 }
2837 }
2838
2839 free (buckets);
2840 free (chains);
2841 }
2842 else if (!do_using_dynamic)
2843 {
2844 unsigned int i;
2845
2846 for (i = 0, section = section_headers;
2847 i < elf_header.e_shnum;
2848 i++, section++)
2849 {
2850 unsigned int si;
2851 char * strtab;
2852 Elf_Internal_Sym * symtab;
2853 Elf_Internal_Sym * psym;
2854
2855
2856 if ( section->sh_type != SHT_SYMTAB
2857 && section->sh_type != SHT_DYNSYM)
2858 continue;
2859
2860 printf (_("\nSymbol table '%s' contains %d entries:\n"),
2861 SECTION_NAME (section),
2862 section->sh_size / section->sh_entsize);
2863 fputs (_(" Num: Value Size Type Bind Ot Ndx Name\n"),
2864 stdout);
2865
2866 symtab = get_elf_symbols (file, section->sh_offset,
2867 section->sh_size / section->sh_entsize);
2868 if (symtab == NULL)
2869 continue;
2870
2871 if (section->sh_link == elf_header.e_shstrndx)
2872 strtab = string_table;
2873 else
2874 {
2875 Elf32_Internal_Shdr * string_sec;
2876
2877 string_sec = section_headers + section->sh_link;
2878
2879 GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
2880 strtab, char *, "string table");
2881 }
2882
2883 for (si = 0, psym = symtab;
2884 si < section->sh_size / section->sh_entsize;
2885 si ++, psym ++)
2886 {
2887 printf (" %3d: %8lx %5ld %-7s %-6s %2d ",
2888 si,
2889 (unsigned long) psym->st_value,
2890 (unsigned long) psym->st_size,
2891 get_symbol_type (ELF_ST_TYPE (psym->st_info)),
2892 get_symbol_binding (ELF_ST_BIND (psym->st_info)),
2893 psym->st_other);
2894
2895 if (psym->st_shndx == 0)
2896 fputs (" UND", stdout);
2897 else if ((psym->st_shndx & 0xffff) == 0xfff1)
2898 fputs (" ABS", stdout);
2899 else if ((psym->st_shndx & 0xffff) == 0xfff2)
2900 fputs (" COM", stdout);
2901 else
2902 printf ("%4x", psym->st_shndx);
2903
2904 printf (" %s", strtab + psym->st_name);
2905
2906 if (section->sh_type == SHT_DYNSYM &&
2907 version_info [DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
2908 {
2909 unsigned char data[2];
2910 unsigned short vers_data;
2911 unsigned long offset;
2912 int is_nobits;
2913 int check_def;
2914
2915 offset = version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
2916 - loadaddr;
2917
2918 GET_DATA (offset + si * sizeof (vers_data), data,
2919 "version data");
2920
2921 vers_data = byte_get (data, 2);
2922
2923 is_nobits = psym->st_shndx < SHN_LORESERVE ?
2924 (section_headers [psym->st_shndx].sh_type == SHT_NOBITS)
2925 : 0;
2926
2927 check_def = (psym->st_shndx != SHN_UNDEF);
2928
2929 if ((vers_data & 0x8000) || vers_data > 1)
2930 {
2931 if (is_nobits || ! check_def)
2932 {
2933 Elf_External_Verneed evn;
2934 Elf_Internal_Verneed ivn;
2935 Elf_Internal_Vernaux ivna;
2936
2937 /* We must test both. */
2938 offset = version_info
2939 [DT_VERSIONTAGIDX (DT_VERNEED)] - loadaddr;
2940
2941 GET_DATA (offset, evn, "version need");
2942
2943 ivn.vn_aux = BYTE_GET (evn.vn_aux);
2944 ivn.vn_next = BYTE_GET (evn.vn_next);
2945
2946 do
2947 {
2948 unsigned long vna_off;
2949
2950 vna_off = offset + ivn.vn_aux;
2951
2952 do
2953 {
2954 Elf_External_Vernaux evna;
2955
2956 GET_DATA (vna_off, evna,
2957 "version need aux (3)");
2958
2959 ivna.vna_other = BYTE_GET (evna.vna_other);
2960 ivna.vna_next = BYTE_GET (evna.vna_next);
2961 ivna.vna_name = BYTE_GET (evna.vna_name);
2962
2963 vna_off += ivna.vna_next;
2964 }
2965 while (ivna.vna_other != vers_data
2966 && ivna.vna_next != 0);
2967
2968 if (ivna.vna_other == vers_data)
2969 break;
2970
2971 offset += ivn.vn_next;
2972 }
2973 while (ivn.vn_next != 0);
2974
2975 if (ivna.vna_other == vers_data)
2976 {
2977 printf ("@%s (%d)",
2978 strtab + ivna.vna_name, ivna.vna_other);
2979 check_def = 0;
2980 }
2981 else if (! is_nobits)
2982 error (_("bad dynamic symbol"));
2983 else
2984 check_def = 1;
2985 }
2986
2987 if (check_def)
2988 {
2989 if (vers_data != 0x8001)
2990 {
2991 Elf_Internal_Verdef ivd;
2992 Elf_Internal_Verdaux ivda;
2993 Elf_External_Verdaux evda;
2994 unsigned long offset;
2995
2996 offset =
2997 version_info [DT_VERSIONTAGIDX (DT_VERDEF)]
2998 - loadaddr;
2999
3000 do
3001 {
3002 Elf_External_Verdef evd;
3003
3004 GET_DATA (offset, evd, "version def");
3005
3006 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
3007 ivd.vd_aux = BYTE_GET (evd.vd_aux);
3008 ivd.vd_next = BYTE_GET (evd.vd_next);
3009
3010 offset += ivd.vd_next;
3011 }
3012 while (ivd.vd_ndx != (vers_data & 0x7fff)
3013 && ivd.vd_next != 0);
3014
3015 offset -= ivd.vd_next;
3016 offset += ivd.vd_aux;
3017
3018 GET_DATA (offset, evda, "version def aux");
3019
3020 ivda.vda_name = BYTE_GET (evda.vda_name);
3021
3022 if (psym->st_name != ivda.vda_name)
3023 printf ((vers_data & 0x8000)
3024 ? "@%s" : "@@%s",
3025 strtab + ivda.vda_name);
3026 }
3027 }
3028 }
3029 }
3030
3031 putchar ('\n');
3032 }
3033
3034 free (symtab);
3035 if (strtab != string_table)
3036 free (strtab);
3037 }
3038 }
3039 else
3040 printf
3041 (_("\nDynamic symbol information is not available for displaying symbols.\n"));
3042
3043 return 1;
3044 }
3045
3046 static int
3047 process_syminfo (file)
3048 FILE * file;
3049 {
3050 int i;
3051
3052 if (dynamic_syminfo == NULL
3053 || !do_dynamic)
3054 /* No syminfo, this is ok. */
3055 return 1;
3056
3057 /* There better should be a dynamic symbol section. */
3058 if (dynamic_symbols == NULL || dynamic_strings == NULL)
3059 return 0;
3060
3061 if (dynamic_addr)
3062 printf (_("\nDynamic info segment at offset 0x%x contains %d entries:\n"),
3063 dynamic_syminfo_offset, dynamic_syminfo_nent);
3064
3065 printf (_(" Num: Name BoundTo Flags\n"));
3066 for (i = 0; i < dynamic_syminfo_nent; ++i)
3067 {
3068 unsigned short int flags = dynamic_syminfo[i].si_flags;
3069
3070 printf ("%4d: %-30s ", i,
3071 dynamic_strings + dynamic_symbols[i].st_name);
3072
3073 switch (dynamic_syminfo[i].si_boundto)
3074 {
3075 case SYMINFO_BT_SELF:
3076 fputs ("SELF ", stdout);
3077 break;
3078 case SYMINFO_BT_PARENT:
3079 fputs ("PARENT ", stdout);
3080 break;
3081 default:
3082 if (dynamic_syminfo[i].si_boundto > 0
3083 && dynamic_syminfo[i].si_boundto < dynamic_size)
3084 printf ("%-10s ",
3085 dynamic_strings
3086 + dynamic_segment[dynamic_syminfo[i].si_boundto].d_un.d_val);
3087 else
3088 printf ("%-10d ", dynamic_syminfo[i].si_boundto);
3089 break;
3090 }
3091
3092 if (flags & SYMINFO_FLG_DIRECT)
3093 printf (" DIRECT");
3094 if (flags & SYMINFO_FLG_PASSTHRU)
3095 printf (" PASSTHRU");
3096 if (flags & SYMINFO_FLG_COPY)
3097 printf (" COPY");
3098 if (flags & SYMINFO_FLG_LAZYLOAD)
3099 printf (" LAZYLOAD");
3100
3101 puts ("");
3102 }
3103
3104 return 1;
3105 }
3106
3107 static int
3108 process_section_contents (file)
3109 FILE * file;
3110 {
3111 Elf32_Internal_Shdr * section;
3112 unsigned int i;
3113
3114 if (! do_dump)
3115 return 1;
3116
3117 for (i = 0, section = section_headers;
3118 i < elf_header.e_shnum;
3119 i ++, section ++)
3120 {
3121 #ifdef SUPPORT_DISASSEMBLY
3122 /* See if we need an assembly dump of this section */
3123
3124 if ((i < NUM_DUMP_SECTS) && (dump_sects[i] & DISASS_DUMP))
3125 {
3126 printf (_("\nAssembly dump of section %s\n"),
3127 SECTION_NAME (section));
3128
3129 /* XXX -- to be done --- XXX */
3130 }
3131 #endif
3132 /* See if we need a hex dump of this section. */
3133 if ((i < NUM_DUMP_SECTS) && (dump_sects[i] & HEX_DUMP))
3134 {
3135 int bytes;
3136 int addr;
3137 unsigned char * data;
3138 char * start;
3139
3140 printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section));
3141
3142 bytes = section->sh_size;
3143 addr = section->sh_addr;
3144
3145 GET_DATA_ALLOC (section->sh_offset, bytes, start, char *,
3146 "section data");
3147
3148 data = start;
3149
3150 while (bytes)
3151 {
3152 int j;
3153 int k;
3154 int lbytes;
3155
3156 lbytes = (bytes > 16 ? 16 : bytes);
3157
3158 printf (" 0x%8.8x ", addr);
3159
3160 switch (elf_header.e_ident [EI_DATA])
3161 {
3162 case ELFDATA2LSB:
3163 for (j = 15; j >= 0; j --)
3164 {
3165 if (j < lbytes)
3166 printf ("%2.2x", data [j]);
3167 else
3168 printf (" ");
3169
3170 if (!(j & 0x3))
3171 printf (" ");
3172 }
3173 break;
3174
3175 case ELFDATA2MSB:
3176 for (j = 0; j < 16; j++)
3177 {
3178 if (j < lbytes)
3179 printf ("%2.2x", data [j]);
3180 else
3181 printf (" ");
3182
3183 if ((j & 3) == 3)
3184 printf (" ");
3185 }
3186 break;
3187 }
3188
3189 for (j = 0; j < lbytes; j++)
3190 {
3191 k = data [j];
3192 if (k >= ' ' && k < 0x80)
3193 printf ("%c", k);
3194 else
3195 printf (".");
3196 }
3197
3198 putchar ('\n');
3199
3200 data += lbytes;
3201 addr += lbytes;
3202 bytes -= lbytes;
3203 }
3204
3205 free (start);
3206 }
3207 }
3208
3209 return 1;
3210 }
3211
3212 static void
3213 process_mips_fpe_exception (mask)
3214 int mask;
3215 {
3216 if (mask)
3217 {
3218 int first = 1;
3219 if (mask & OEX_FPU_INEX)
3220 fputs ("INEX", stdout), first = 0;
3221 if (mask & OEX_FPU_UFLO)
3222 printf ("%sUFLO", first ? "" : "|"), first = 0;
3223 if (mask & OEX_FPU_OFLO)
3224 printf ("%sOFLO", first ? "" : "|"), first = 0;
3225 if (mask & OEX_FPU_DIV0)
3226 printf ("%sDIV0", first ? "" : "|"), first = 0;
3227 if (mask & OEX_FPU_INVAL)
3228 printf ("%sINVAL", first ? "" : "|");
3229 }
3230 else
3231 fputs ("0", stdout);
3232 }
3233
3234 static int
3235 process_mips_specific (file)
3236 FILE *file;
3237 {
3238 Elf_Internal_Dyn * entry;
3239 size_t liblist_offset = 0;
3240 size_t liblistno = 0;
3241 size_t options_offset = 0;
3242
3243 /* We have a lot of special sections. Thanks SGI! */
3244 if (dynamic_segment == NULL)
3245 /* No information available. */
3246 return 0;
3247
3248 for (entry = dynamic_segment; entry->d_tag != DT_NULL; ++entry)
3249 switch (entry->d_tag)
3250 {
3251 case DT_MIPS_LIBLIST:
3252 liblist_offset = entry->d_un.d_val - loadaddr;
3253 break;
3254 case DT_MIPS_LIBLISTNO:
3255 liblistno = entry->d_un.d_val;
3256 break;
3257 case DT_MIPS_OPTIONS:
3258 options_offset = entry->d_un.d_val - loadaddr;
3259 break;
3260 default:
3261 break;
3262 }
3263
3264 if (liblist_offset != 0 && liblistno != 0 && do_dynamic)
3265 {
3266 Elf32_External_Lib *elib;
3267 size_t cnt;
3268
3269 GET_DATA_ALLOC (liblist_offset, liblistno * sizeof (Elf32_External_Lib),
3270 elib, Elf32_External_Lib *, "liblist");
3271
3272 printf ("\nSection '.liblist' contains %d entries:\n", liblistno);
3273 fputs (" Library Time Stamp Checksum Version Flags\n",
3274 stdout);
3275
3276 for (cnt = 0; cnt < liblistno; ++cnt)
3277 {
3278 Elf32_Lib liblist;
3279 time_t time;
3280 char timebuf[20];
3281
3282 liblist.l_name = BYTE_GET (elib[cnt].l_name);
3283 time = BYTE_GET (elib[cnt].l_time_stamp);
3284 liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum);
3285 liblist.l_version = BYTE_GET (elib[cnt].l_version);
3286 liblist.l_flags = BYTE_GET (elib[cnt].l_flags);
3287
3288 strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time));
3289
3290 printf ("%3d: %-20s %s %#10lx %-7ld %#lx\n", cnt,
3291 dynamic_strings + liblist.l_name, timebuf,
3292 liblist.l_checksum, liblist.l_version, liblist.l_flags);
3293 }
3294
3295 free (elib);
3296 }
3297
3298 if (options_offset != 0)
3299 {
3300 Elf_External_Options *eopt;
3301 Elf_Internal_Shdr *sect = section_headers;
3302 Elf_Internal_Options *iopt;
3303 Elf_Internal_Options *option;
3304 size_t offset;
3305 int cnt;
3306
3307 /* Find the section header so that we get the size. */
3308 while (sect->sh_type != SHT_MIPS_OPTIONS)
3309 ++sect;
3310
3311 GET_DATA_ALLOC (options_offset, sect->sh_size, eopt,
3312 Elf_External_Options *, "options");
3313
3314 iopt = (Elf_Internal_Options *) malloc ((sect->sh_size / sizeof (eopt))
3315 * sizeof (*iopt));
3316 if (iopt == NULL)
3317 {
3318 error (_("Out of memory"));
3319 return 0;
3320 }
3321
3322 offset = cnt = 0;
3323 option = iopt;
3324 while (offset < sect->sh_size)
3325 {
3326 Elf_External_Options *eoption;
3327
3328 eoption = (Elf_External_Options *) ((char *) eopt + offset);
3329
3330 option->kind = BYTE_GET (eoption->kind);
3331 option->size = BYTE_GET (eoption->size);
3332 option->section = BYTE_GET (eoption->section);
3333 option->info = BYTE_GET (eoption->info);
3334
3335 offset += option->size;
3336 ++option;
3337 ++cnt;
3338 }
3339
3340 printf (_("\nSection '%s' contains %d entries:\n"),
3341 string_table + sect->sh_name, cnt);
3342
3343 option = iopt;
3344 while (cnt-- > 0)
3345 {
3346 size_t len;
3347
3348 switch (option->kind)
3349 {
3350 case ODK_NULL:
3351 /* This shouldn't happen. */
3352 printf (" NULL %d %x", option->section, option->info);
3353 break;
3354 case ODK_REGINFO:
3355 printf (" REGINFO ");
3356 if (elf_header.e_machine == EM_MIPS)
3357 {
3358 /* 32bit form. */
3359 Elf32_External_RegInfo *ereg;
3360 Elf32_RegInfo reginfo;
3361
3362 ereg = (Elf32_External_RegInfo *) (option + 1);
3363 reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
3364 reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
3365 reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
3366 reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
3367 reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
3368 reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
3369
3370 printf ("GPR %08lx GP %ld\n",
3371 reginfo.ri_gprmask, reginfo.ri_gp_value);
3372 printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n",
3373 reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
3374 reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
3375 }
3376 else
3377 {
3378 /* 64 bit form. */
3379 Elf64_External_RegInfo *ereg;
3380 Elf64_Internal_RegInfo reginfo;
3381
3382 ereg = (Elf64_External_RegInfo *) (option + 1);
3383 reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
3384 reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
3385 reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
3386 reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
3387 reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
3388 reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
3389
3390 printf ("GPR %08lx GP %ld\n",
3391 reginfo.ri_gprmask, reginfo.ri_gp_value);
3392 printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n",
3393 reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
3394 reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
3395 }
3396 ++option;
3397 continue;
3398 case ODK_EXCEPTIONS:
3399 fputs (" EXCEPTIONS fpe_min(", stdout);
3400 process_mips_fpe_exception (option->info & OEX_FPU_MIN);
3401 fputs (") fpe_max(", stdout);
3402 process_mips_fpe_exception ((option->info & OEX_FPU_MAX) >> 8);
3403 fputs (")", stdout);
3404
3405 if (option->info & OEX_PAGE0)
3406 fputs (" PAGE0", stdout);
3407 if (option->info & OEX_SMM)
3408 fputs (" SMM", stdout);
3409 if (option->info & OEX_FPDBUG)
3410 fputs (" FPDBUG", stdout);
3411 if (option->info & OEX_DISMISS)
3412 fputs (" DISMISS", stdout);
3413 break;
3414 case ODK_PAD:
3415 fputs (" PAD ", stdout);
3416 if (option->info & OPAD_PREFIX)
3417 fputs (" PREFIX", stdout);
3418 if (option->info & OPAD_POSTFIX)
3419 fputs (" POSTFIX", stdout);
3420 if (option->info & OPAD_SYMBOL)
3421 fputs (" SYMBOL", stdout);
3422 break;
3423 case ODK_HWPATCH:
3424 fputs (" HWPATCH ", stdout);
3425 if (option->info & OHW_R4KEOP)
3426 fputs (" R4KEOP", stdout);
3427 if (option->info & OHW_R8KPFETCH)
3428 fputs (" R8KPFETCH", stdout);
3429 if (option->info & OHW_R5KEOP)
3430 fputs (" R5KEOP", stdout);
3431 if (option->info & OHW_R5KCVTL)
3432 fputs (" R5KCVTL", stdout);
3433 break;
3434 case ODK_FILL:
3435 fputs (" FILL ", stdout);
3436 /* XXX Print content of info word? */
3437 break;
3438 case ODK_TAGS:
3439 fputs (" TAGS ", stdout);
3440 /* XXX Print content of info word? */
3441 break;
3442 case ODK_HWAND:
3443 fputs (" HWAND ", stdout);
3444 if (option->info & OHWA0_R4KEOP_CHECKED)
3445 fputs (" R4KEOP_CHECKED", stdout);
3446 if (option->info & OHWA0_R4KEOP_CLEAN)
3447 fputs (" R4KEOP_CLEAN", stdout);
3448 break;
3449 case ODK_HWOR:
3450 fputs (" HWOR ", stdout);
3451 if (option->info & OHWA0_R4KEOP_CHECKED)
3452 fputs (" R4KEOP_CHECKED", stdout);
3453 if (option->info & OHWA0_R4KEOP_CLEAN)
3454 fputs (" R4KEOP_CLEAN", stdout);
3455 break;
3456 case ODK_GP_GROUP:
3457 printf (" GP_GROUP %#06x self-contained %#06x",
3458 option->info & OGP_GROUP,
3459 (option->info & OGP_SELF) >> 16);
3460 break;
3461 case ODK_IDENT:
3462 printf (" IDENT %#06x self-contained %#06x",
3463 option->info & OGP_GROUP,
3464 (option->info & OGP_SELF) >> 16);
3465 break;
3466 default:
3467 /* This shouldn't happen. */
3468 printf (" %3d ??? %d %x",
3469 option->kind, option->section, option->info);
3470 break;
3471 }
3472
3473 len = sizeof (*eopt);
3474 while (len < option->size)
3475 if (((char *) option)[len] >= ' '
3476 && ((char *) option)[len] < 0x7f)
3477 printf ("%c", ((char *) option)[len++]);
3478 else
3479 printf ("\\%03o", ((char *) option)[len++]);
3480
3481 fputs ("\n", stdout);
3482 ++option;
3483 }
3484
3485 free (eopt);
3486 }
3487
3488 return 1;
3489 }
3490
3491 static int
3492 process_arch_specific (file)
3493 FILE *file;
3494 {
3495 switch (elf_header.e_machine)
3496 {
3497 case EM_MIPS:
3498 case EM_MIPS_RS4_BE:
3499 return process_mips_specific (file);
3500 break;
3501 default:
3502 break;
3503 }
3504 return 1;
3505 }
3506
3507 static int
3508 get_file_header (file)
3509 FILE * file;
3510 {
3511 Elf32_External_Ehdr ehdr;
3512
3513 if (fread (& ehdr, sizeof (ehdr), 1, file) != 1)
3514 return 0;
3515
3516 memcpy (elf_header.e_ident, ehdr.e_ident, EI_NIDENT);
3517
3518 if (elf_header.e_ident [EI_DATA] == ELFDATA2LSB)
3519 byte_get = byte_get_little_endian;
3520 else
3521 byte_get = byte_get_big_endian;
3522
3523 elf_header.e_entry = BYTE_GET (ehdr.e_entry);
3524 elf_header.e_phoff = BYTE_GET (ehdr.e_phoff);
3525 elf_header.e_shoff = BYTE_GET (ehdr.e_shoff);
3526 elf_header.e_version = BYTE_GET (ehdr.e_version);
3527 elf_header.e_flags = BYTE_GET (ehdr.e_flags);
3528 elf_header.e_type = BYTE_GET (ehdr.e_type);
3529 elf_header.e_machine = BYTE_GET (ehdr.e_machine);
3530 elf_header.e_ehsize = BYTE_GET (ehdr.e_ehsize);
3531 elf_header.e_phentsize = BYTE_GET (ehdr.e_phentsize);
3532 elf_header.e_phnum = BYTE_GET (ehdr.e_phnum);
3533 elf_header.e_shentsize = BYTE_GET (ehdr.e_shentsize);
3534 elf_header.e_shnum = BYTE_GET (ehdr.e_shnum);
3535 elf_header.e_shstrndx = BYTE_GET (ehdr.e_shstrndx);
3536
3537 return 1;
3538 }
3539
3540 static void
3541 process_file (file_name)
3542 char * file_name;
3543 {
3544 FILE * file;
3545 struct stat statbuf;
3546 unsigned int i;
3547
3548 if (stat (file_name, & statbuf) < 0)
3549 {
3550 error (_("Cannot stat input file %s.\n"), file_name);
3551 return;
3552 }
3553
3554 file = fopen (file_name, "rb");
3555 if (file == NULL)
3556 {
3557 error (_("Input file %s not found.\n"), file_name);
3558 return;
3559 }
3560
3561 if (! get_file_header (file))
3562 {
3563 error (_("%s: Failed to read file header\n"), file_name);
3564 fclose (file);
3565 return;
3566 }
3567
3568 /* Initialise per file variables. */
3569 for (i = NUM_ELEM (version_info); i--;)
3570 version_info[i] = 0;
3571
3572 for (i = NUM_ELEM (dynamic_info); i--;)
3573 dynamic_info[i] = 0;
3574
3575 /* Process the file. */
3576 if (show_name)
3577 printf (_("\nFile: %s\n"), file_name);
3578
3579 if (! process_file_header ())
3580 {
3581 fclose (file);
3582 return;
3583 }
3584
3585 process_section_headers (file);
3586
3587 process_program_headers (file);
3588
3589 process_dynamic_segment (file);
3590
3591 process_relocs (file);
3592
3593 process_symbol_table (file);
3594
3595 process_syminfo (file);
3596
3597 process_version_sections (file);
3598
3599 process_section_contents (file);
3600
3601 process_arch_specific (file);
3602
3603 fclose (file);
3604
3605 if (section_headers)
3606 {
3607 free (section_headers);
3608 section_headers = NULL;
3609 }
3610
3611 if (string_table)
3612 {
3613 free (string_table);
3614 string_table = NULL;
3615 }
3616
3617 if (dynamic_strings)
3618 {
3619 free (dynamic_strings);
3620 dynamic_strings = NULL;
3621 }
3622
3623 if (dynamic_symbols)
3624 {
3625 free (dynamic_symbols);
3626 dynamic_symbols = NULL;
3627 }
3628
3629 if (dynamic_syminfo)
3630 {
3631 free (dynamic_syminfo);
3632 dynamic_syminfo = NULL;
3633 }
3634 }
3635
3636 #ifdef SUPPORT_DISASSEMBLY
3637 /* Needed by the i386 disassembler. For extra credit, someone could
3638 fix this so that we insert symbolic addresses here, esp for GOT/PLT
3639 symbols */
3640
3641 void
3642 print_address (unsigned int addr, FILE * outfile)
3643 {
3644 fprintf (outfile,"0x%8.8x", addr);
3645 }
3646
3647 /* Needed by the i386 disassembler. */
3648 void
3649 db_task_printsym (unsigned int addr)
3650 {
3651 print_address (addr, stderr);
3652 }
3653 #endif
3654
3655 int
3656 main (argc, argv)
3657 int argc;
3658 char ** argv;
3659 {
3660 parse_args (argc, argv);
3661
3662 if (optind < (argc - 1))
3663 show_name = 1;
3664
3665 while (optind < argc)
3666 process_file (argv [optind ++]);
3667
3668 return 0;
3669 }
This page took 0.109211 seconds and 4 git commands to generate.