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