do not try to dump empty sections
[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 {"syms", no_argument, 0, 's'},
1027 {"relocs", no_argument, 0, 'r'},
1028 {"dynamic", no_argument, 0, 'd'},
1029 {"version-info", no_argument, 0, 'V'},
1030 {"use-dynamic", no_argument, 0, 'D'},
1031
1032 {"hex-dump", required_argument, 0, 'x'},
1033 #ifdef SUPPORT_DISASSEMBLY
1034 {"instruction-dump", required_argument, 0, 'i'},
1035 #endif
1036
1037 {"version", no_argument, 0, 'v'},
1038 {"help", no_argument, 0, 'H'},
1039
1040 {0, no_argument, 0, 0}
1041 };
1042
1043 static void
1044 usage ()
1045 {
1046 fprintf (stdout, _("Usage: readelf {options} elf-file(s)\n"));
1047 fprintf (stdout, _(" Options are:\n"));
1048 fprintf (stdout, _(" -a or --all Equivalent to: -h -l -S -s -r -d -V --histogram\n"));
1049 fprintf (stdout, _(" -h or --file-header Display the ELF file header\n"));
1050 fprintf (stdout, _(" -l or --program-headers or --segments\n"));
1051 fprintf (stdout, _(" Display the program headers\n"));
1052 fprintf (stdout, _(" -S or --section-headers or --sections\n"));
1053 fprintf (stdout, _(" Display the sections' header\n"));
1054 fprintf (stdout, _(" -e or --headers Equivalent to: -h -l -S\n"));
1055 fprintf (stdout, _(" -s or --syms or --symbols Display the symbol table\n"));
1056 fprintf (stdout, _(" -r or --relocs Display the relocations (if present)\n"));
1057 fprintf (stdout, _(" -d or --dynamic Display the dynamic segment (if present)\n"));
1058 fprintf (stdout, _(" -V or --version-info Display the version sections (if present)\n"));
1059 fprintf (stdout, _(" -D or --use-dynamic Use the dynamic section info when displaying symbols\n"));
1060 fprintf (stdout, _(" -x <number> or --hex-dump=<number>\n"));
1061 fprintf (stdout, _(" Dump the contents of section <number>\n"));
1062 #ifdef SUPPORT_DISASSEMBLY
1063 fprintf (stdout, _(" -i <number> or --instruction-dump=<number>\n"));
1064 fprintf (stdout, _(" Disassemble the contents of section <number>\n"));
1065 #endif
1066 fprintf (stdout, _(" --histogram Display histogram of bucket list lengths\n"));
1067 fprintf (stdout, _(" -v or --version Display the version number of readelf\n"));
1068 fprintf (stdout, _(" -H or --help Display this information\n"));
1069 fprintf (stdout, _("Report bugs to bug-gnu-utils@gnu.org\n"));
1070
1071 exit (0);
1072 }
1073
1074 static void
1075 parse_args (argc, argv)
1076 int argc;
1077 char ** argv;
1078 {
1079 int c;
1080
1081 if (argc < 2)
1082 usage ();
1083
1084 while ((c = getopt_long
1085 (argc, argv, "ersahldSDx:i:vV", options, NULL)) != EOF)
1086 {
1087 char * cp;
1088 int section;
1089
1090 switch (c)
1091 {
1092 case 0:
1093 /* Long options. */
1094 break;
1095 case 'H':
1096 usage ();
1097 break;
1098
1099 case 'a':
1100 do_syms ++;
1101 do_reloc ++;
1102 do_dynamic ++;
1103 do_header ++;
1104 do_sections ++;
1105 do_segments ++;
1106 do_version ++;
1107 do_histogram ++;
1108 break;
1109 case 'e':
1110 do_header ++;
1111 do_sections ++;
1112 do_segments ++;
1113 break;
1114 case 'D':
1115 do_using_dynamic ++;
1116 break;
1117 case 'r':
1118 do_reloc ++;
1119 break;
1120 case 'h':
1121 do_header ++;
1122 break;
1123 case 'l':
1124 do_segments ++;
1125 break;
1126 case 's':
1127 do_syms ++;
1128 break;
1129 case 'S':
1130 do_sections ++;
1131 break;
1132 case 'd':
1133 do_dynamic ++;
1134 break;
1135 case 'x':
1136 do_dump ++;
1137 section = strtoul (optarg, & cp, 0);
1138 if (! * cp && section >= 0 && section < NUM_DUMP_SECTS)
1139 {
1140 dump_sects [section] |= HEX_DUMP;
1141 break;
1142 }
1143 goto oops;
1144 #ifdef SUPPORT_DISASSEMBLY
1145 case 'i':
1146 do_dump ++;
1147 section = strtoul (optarg, & cp, 0);
1148 if (! * cp && section >= 0 && section < NUM_DUMP_SECTS)
1149 {
1150 dump_sects [section] |= DISASS_DUMP;
1151 break;
1152 }
1153 goto oops;
1154 #endif
1155 case 'v':
1156 print_version (program_name);
1157 break;
1158 case 'V':
1159 do_version ++;
1160 break;
1161 default:
1162 oops:
1163 /* xgettext:c-format */
1164 error (_("Invalid option '-%c'\n"), c);
1165 /* Drop through. */
1166 case '?':
1167 usage ();
1168 }
1169 }
1170
1171 if (!do_dynamic && !do_syms && !do_reloc && !do_sections
1172 && !do_segments && !do_header && !do_dump && !do_version
1173 && !do_histogram)
1174 usage ();
1175 else if (argc < 3)
1176 {
1177 warn (_("Nothing to do.\n"));
1178 usage();
1179 }
1180 }
1181
1182 /* Decode the data held in 'elf_header'. */
1183 static int
1184 process_file_header ()
1185 {
1186 if ( elf_header.e_ident [EI_MAG0] != ELFMAG0
1187 || elf_header.e_ident [EI_MAG1] != ELFMAG1
1188 || elf_header.e_ident [EI_MAG2] != ELFMAG2
1189 || elf_header.e_ident [EI_MAG3] != ELFMAG3)
1190 {
1191 error
1192 (_("Not an ELF file - it has the wrong magic bytes at the start\n"));
1193 return 0;
1194 }
1195
1196 if (elf_header.e_ident [EI_CLASS] != ELFCLASS32)
1197 {
1198 error (_("Not a 32 bit ELF file\n"));
1199 return 0;
1200 }
1201
1202 if (do_header)
1203 {
1204 int i;
1205
1206 printf (_("ELF Header:\n"));
1207 printf (_(" Magic: "));
1208 for (i = 0; i < EI_NIDENT; i ++)
1209 printf ("%2.2x ", elf_header.e_ident [i]);
1210 printf ("\n");
1211 printf (_(" Type: %s\n"),
1212 get_file_type (elf_header.e_type));
1213 printf (_(" Machine: %s\n"),
1214 get_machine_name (elf_header.e_machine));
1215 printf (_(" Version: 0x%lx\n"),
1216 (unsigned long) elf_header.e_version);
1217 printf (_(" Data: %s\n"),
1218 get_machine_data (elf_header.e_ident [EI_DATA]));
1219 printf (_(" Entry point address: 0x%lx\n"),
1220 (unsigned long) elf_header.e_entry);
1221 printf (_(" Start of program headers: %ld (bytes into file)\n"),
1222 (long) elf_header.e_phoff);
1223 printf (_(" Start of section headers: %ld (bytes into file)\n"),
1224 (long) elf_header.e_shoff);
1225 printf (_(" Flags: 0x%lx%s\n"),
1226 (unsigned long) elf_header.e_flags,
1227 get_machine_flags (elf_header.e_flags, elf_header.e_machine));
1228 printf (_(" Size of this header: %ld (bytes)\n"),
1229 (long) elf_header.e_ehsize);
1230 printf (_(" Size of program headers: %ld (bytes)\n"),
1231 (long) elf_header.e_phentsize);
1232 printf (_(" Number of program headers: %ld\n"),
1233 (long) elf_header.e_phnum);
1234 printf (_(" Size of section headers: %ld (bytes)\n"),
1235 (long) elf_header.e_shentsize);
1236 printf (_(" Number of section headers: %ld\n"),
1237 (long) elf_header.e_shnum);
1238 printf (_(" Section header string table index: %ld\n"),
1239 (long) elf_header.e_shstrndx);
1240 }
1241
1242 return 1;
1243 }
1244
1245
1246 static int
1247 process_program_headers (file)
1248 FILE * file;
1249 {
1250 Elf32_External_Phdr * phdrs;
1251 Elf32_Internal_Phdr * program_headers;
1252 Elf32_Internal_Phdr * segment;
1253 unsigned int i;
1254
1255 if (elf_header.e_phnum == 0)
1256 {
1257 if (do_segments)
1258 printf (_("\nThere are no program headers in this file.\n"));
1259 return 1;
1260 }
1261
1262 if (do_segments && !do_header)
1263 {
1264 printf (_("\nElf file is %s\n"), get_file_type (elf_header.e_type));
1265 printf (_("Entry point 0x%lx\n"), (unsigned long) elf_header.e_entry);
1266 printf (_("There are %d program headers, starting at offset %lx:\n"),
1267 elf_header.e_phnum, (unsigned long) elf_header.e_phoff);
1268 }
1269
1270 GET_DATA_ALLOC (elf_header.e_phoff,
1271 elf_header.e_phentsize * elf_header.e_phnum,
1272 phdrs, Elf32_External_Phdr *, "program headers");
1273
1274 program_headers = (Elf32_Internal_Phdr *) malloc
1275 (elf_header.e_phnum * sizeof (Elf32_Internal_Phdr));
1276
1277 if (program_headers == NULL)
1278 {
1279 error (_("Out of memory\n"));
1280 return 0;
1281 }
1282
1283 for (i = 0, segment = program_headers;
1284 i < elf_header.e_phnum;
1285 i ++, segment ++)
1286 {
1287 segment->p_type = BYTE_GET (phdrs[i].p_type);
1288 segment->p_offset = BYTE_GET (phdrs[i].p_offset);
1289 segment->p_vaddr = BYTE_GET (phdrs[i].p_vaddr);
1290 segment->p_paddr = BYTE_GET (phdrs[i].p_paddr);
1291 segment->p_filesz = BYTE_GET (phdrs[i].p_filesz);
1292 segment->p_memsz = BYTE_GET (phdrs[i].p_memsz);
1293 segment->p_flags = BYTE_GET (phdrs[i].p_flags);
1294 segment->p_align = BYTE_GET (phdrs[i].p_align);
1295 }
1296
1297 free (phdrs);
1298
1299 if (do_segments)
1300 {
1301 printf
1302 (_("\nProgram Header%s:\n"), elf_header.e_phnum > 1 ? "s" : "");
1303 printf
1304 (_(" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n"));
1305 }
1306
1307 loadaddr = -1;
1308 dynamic_addr = 0;
1309
1310 for (i = 0, segment = program_headers;
1311 i < elf_header.e_phnum;
1312 i ++, segment ++)
1313 {
1314 if (do_segments)
1315 {
1316 printf (" %-11.11s ", get_segment_type (segment->p_type));
1317 printf ("0x%6.6lx ", (unsigned long) segment->p_offset);
1318 printf ("0x%8.8lx ", (unsigned long) segment->p_vaddr);
1319 printf ("0x%8.8lx ", (unsigned long) segment->p_paddr);
1320 printf ("0x%5.5lx ", (unsigned long) segment->p_filesz);
1321 printf ("0x%5.5lx ", (unsigned long) segment->p_memsz);
1322 printf ("%c%c%c ",
1323 (segment->p_flags & PF_R ? 'R' : ' '),
1324 (segment->p_flags & PF_W ? 'W' : ' '),
1325 (segment->p_flags & PF_X ? 'E' : ' '));
1326 printf ("%#lx", (unsigned long) segment->p_align);
1327 }
1328
1329 switch (segment->p_type)
1330 {
1331 case PT_LOAD:
1332 if (loadaddr == -1)
1333 loadaddr = (segment->p_vaddr & 0xfffff000)
1334 - (segment->p_offset & 0xfffff000);
1335 break;
1336
1337 case PT_DYNAMIC:
1338 if (dynamic_addr)
1339 error (_("more than one dynamic segment\n"));
1340
1341 dynamic_addr = segment->p_offset;
1342 dynamic_size = segment->p_filesz;
1343 break;
1344
1345 case PT_INTERP:
1346 if (fseek (file, segment->p_offset, SEEK_SET))
1347 error (_("Unable to find program interpreter name\n"));
1348 else
1349 {
1350 program_interpreter[0] = 0;
1351 fscanf (file, "%63s", program_interpreter);
1352
1353 if (do_segments)
1354 printf (_("\n [Requesting program interpreter: %s]"),
1355 program_interpreter);
1356 }
1357 break;
1358 }
1359
1360 if (do_segments)
1361 putc ('\n', stdout);
1362 }
1363
1364 if (loadaddr == -1)
1365 {
1366 /* Very strange. */
1367 loadaddr = 0;
1368 }
1369
1370 if (do_segments && section_headers != NULL)
1371 {
1372 printf (_("\n Section to Segment mapping:\n"));
1373 printf (_(" Segment Sections...\n"));
1374
1375 assert (string_table != NULL);
1376
1377 for (i = 0; i < elf_header.e_phnum; i++)
1378 {
1379 int j;
1380 Elf32_Internal_Shdr * section;
1381
1382 segment = program_headers + i;
1383 section = section_headers;
1384
1385 printf (" %2.2d ", i);
1386
1387 for (j = 0; j < elf_header.e_shnum; j++, section ++)
1388 {
1389 if (section->sh_size > 0
1390 /* Compare allocated sections by VMA, unallocated
1391 sections by file offset. */
1392 && (section->sh_flags & SHF_ALLOC
1393 ? (section->sh_addr >= segment->p_vaddr
1394 && section->sh_addr + section->sh_size
1395 <= segment->p_vaddr + segment->p_memsz)
1396 : (section->sh_offset >= segment->p_offset
1397 && (section->sh_offset + section->sh_size
1398 <= segment->p_offset + segment->p_filesz))))
1399 printf ("%s ", SECTION_NAME (section));
1400 }
1401
1402 putc ('\n',stdout);
1403 }
1404 }
1405
1406 free (program_headers);
1407
1408 return 1;
1409 }
1410
1411
1412 static int
1413 get_section_headers (file)
1414 FILE * file;
1415 {
1416 Elf32_External_Shdr * shdrs;
1417 Elf32_Internal_Shdr * internal;
1418 unsigned int i;
1419
1420 GET_DATA_ALLOC (elf_header.e_shoff,
1421 elf_header.e_shentsize * elf_header.e_shnum,
1422 shdrs, Elf32_External_Shdr *, "section headers");
1423
1424 section_headers = (Elf32_Internal_Shdr *) malloc
1425 (elf_header.e_shnum * sizeof (Elf32_Internal_Shdr));
1426
1427 if (section_headers == NULL)
1428 {
1429 error (_("Out of memory\n"));
1430 return 0;
1431 }
1432
1433 for (i = 0, internal = section_headers;
1434 i < elf_header.e_shnum;
1435 i ++, internal ++)
1436 {
1437 internal->sh_name = BYTE_GET (shdrs[i].sh_name);
1438 internal->sh_type = BYTE_GET (shdrs[i].sh_type);
1439 internal->sh_flags = BYTE_GET (shdrs[i].sh_flags);
1440 internal->sh_addr = BYTE_GET (shdrs[i].sh_addr);
1441 internal->sh_offset = BYTE_GET (shdrs[i].sh_offset);
1442 internal->sh_size = BYTE_GET (shdrs[i].sh_size);
1443 internal->sh_link = BYTE_GET (shdrs[i].sh_link);
1444 internal->sh_info = BYTE_GET (shdrs[i].sh_info);
1445 internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
1446 internal->sh_entsize = BYTE_GET (shdrs[i].sh_entsize);
1447 }
1448
1449 free (shdrs);
1450
1451 return 1;
1452 }
1453
1454 static Elf_Internal_Sym *
1455 get_elf_symbols (file, offset, number)
1456 FILE * file;
1457 unsigned long offset;
1458 unsigned long number;
1459 {
1460 Elf32_External_Sym * esyms;
1461 Elf_Internal_Sym * isyms;
1462 Elf_Internal_Sym * psym;
1463 unsigned int j;
1464
1465 GET_DATA_ALLOC (offset, number * sizeof (Elf32_External_Sym),
1466 esyms, Elf32_External_Sym *, "symbols");
1467
1468 isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym));
1469
1470 if (isyms == NULL)
1471 {
1472 error (_("Out of memory\n"));
1473 free (esyms);
1474
1475 return NULL;
1476 }
1477
1478 for (j = 0, psym = isyms;
1479 j < number;
1480 j ++, psym ++)
1481 {
1482 psym->st_name = BYTE_GET (esyms[j].st_name);
1483 psym->st_value = BYTE_GET (esyms[j].st_value);
1484 psym->st_size = BYTE_GET (esyms[j].st_size);
1485 psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
1486 psym->st_info = BYTE_GET (esyms[j].st_info);
1487 psym->st_other = BYTE_GET (esyms[j].st_other);
1488 }
1489
1490 free (esyms);
1491
1492 return isyms;
1493 }
1494
1495 static int
1496 process_section_headers (file)
1497 FILE * file;
1498 {
1499 Elf32_Internal_Shdr * section;
1500 int i;
1501
1502 section_headers = NULL;
1503
1504 if (elf_header.e_shnum == 0)
1505 {
1506 if (do_sections)
1507 printf (_("\nThere are no sections in this file.\n"));
1508
1509 return 1;
1510 }
1511
1512 if (do_sections && !do_header)
1513 printf (_("There are %d section headers, starting at offset %x:\n"),
1514 elf_header.e_shnum, elf_header.e_shoff);
1515
1516 if (! get_section_headers (file))
1517 return 0;
1518
1519 /* Read in the string table, so that we have names to display. */
1520 section = section_headers + elf_header.e_shstrndx;
1521
1522 if (section->sh_size != 0)
1523 {
1524 unsigned long string_table_offset;
1525
1526 string_table_offset = section->sh_offset;
1527
1528 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
1529 string_table, char *, "string table");
1530 }
1531
1532 /* Scan the sections for the dynamic symbol table
1533 and dynamic string table. */
1534 dynamic_symbols = NULL;
1535 dynamic_strings = NULL;
1536 dynamic_syminfo = NULL;
1537 for (i = 0, section = section_headers;
1538 i < elf_header.e_shnum;
1539 i ++, section ++)
1540 {
1541 if (section->sh_type == SHT_DYNSYM)
1542 {
1543 if (dynamic_symbols != NULL)
1544 {
1545 error (_("File contains multiple dynamic symbol tables\n"));
1546 continue;
1547 }
1548
1549 dynamic_symbols = get_elf_symbols
1550 (file, section->sh_offset, section->sh_size / section->sh_entsize);
1551 }
1552 else if (section->sh_type == SHT_STRTAB
1553 && strcmp (SECTION_NAME (section), ".dynstr") == 0)
1554 {
1555 if (dynamic_strings != NULL)
1556 {
1557 error (_("File contains multiple dynamic string tables\n"));
1558 continue;
1559 }
1560
1561 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
1562 dynamic_strings, char *, "dynamic strings");
1563 }
1564 }
1565
1566 if (! do_sections)
1567 return 1;
1568
1569 printf (_("\nSection Header%s:\n"), elf_header.e_shnum > 1 ? "s" : "");
1570 printf
1571 (_(" [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n"));
1572
1573 for (i = 0, section = section_headers;
1574 i < elf_header.e_shnum;
1575 i ++, section ++)
1576 {
1577 printf (" [%2d] %-17.17s %-15.15s ",
1578 i,
1579 SECTION_NAME (section),
1580 get_section_type_name (section->sh_type));
1581
1582 printf ( "%8.8lx %6.6lx %6.6lx %2.2lx",
1583 (unsigned long) section->sh_addr,
1584 (unsigned long) section->sh_offset,
1585 (unsigned long) section->sh_size,
1586 (unsigned long) section->sh_entsize);
1587
1588 printf (" %c%c%c %2ld %3lx %ld \n",
1589 (section->sh_flags & SHF_WRITE ? 'W' : ' '),
1590 (section->sh_flags & SHF_ALLOC ? 'A' : ' '),
1591 (section->sh_flags & SHF_EXECINSTR ? 'X' : ' '),
1592 (unsigned long) section->sh_link,
1593 (unsigned long) section->sh_info,
1594 (unsigned long) section->sh_addralign);
1595 }
1596
1597 return 1;
1598 }
1599
1600 /* Process the reloc section. */
1601 static int
1602 process_relocs (file)
1603 FILE * file;
1604 {
1605 unsigned long rel_size;
1606 unsigned long rel_offset;
1607
1608
1609 if (!do_reloc)
1610 return 1;
1611
1612 if (do_using_dynamic)
1613 {
1614 rel_size = 0;
1615 rel_offset = 0;
1616
1617 if (dynamic_info[DT_REL])
1618 {
1619 rel_offset = dynamic_info[DT_REL];
1620 rel_size = dynamic_info[DT_RELSZ];
1621 }
1622 else if (dynamic_info [DT_RELA])
1623 {
1624 rel_offset = dynamic_info[DT_RELA];
1625 rel_size = dynamic_info[DT_RELASZ];
1626 }
1627 else if (dynamic_info[DT_JMPREL])
1628 {
1629 rel_offset = dynamic_info[DT_JMPREL];
1630 rel_size = dynamic_info[DT_PLTRELSZ];
1631 }
1632
1633 if (rel_size)
1634 {
1635 printf
1636 (_("\nRelocation section at offset 0x%x contains %d bytes:\n"),
1637 rel_offset, rel_size);
1638
1639 dump_relocations (file, rel_offset - loadaddr, rel_size,
1640 dynamic_symbols, dynamic_strings);
1641 }
1642 else
1643 printf (_("\nThere are no dynamic relocations in this file.\n"));
1644 }
1645 else
1646 {
1647 Elf32_Internal_Shdr * section;
1648 unsigned long i;
1649 int found = 0;
1650
1651 for (i = 0, section = section_headers;
1652 i < elf_header.e_shnum;
1653 i++, section ++)
1654 {
1655 if ( section->sh_type != SHT_RELA
1656 && section->sh_type != SHT_REL)
1657 continue;
1658
1659 rel_offset = section->sh_offset;
1660 rel_size = section->sh_size;
1661
1662 if (rel_size)
1663 {
1664 Elf32_Internal_Shdr * strsec;
1665 Elf32_Internal_Shdr * symsec;
1666 Elf_Internal_Sym * symtab;
1667 char * strtab;
1668
1669 printf (_("\nRelocation section "));
1670
1671 if (string_table == NULL)
1672 printf ("%d", section->sh_name);
1673 else
1674 printf ("'%s'", SECTION_NAME (section));
1675
1676 printf (_(" at offset 0x%x contains %d entries:\n"),
1677 rel_offset, rel_size / section->sh_entsize);
1678
1679 symsec = section_headers + section->sh_link;
1680
1681 symtab = get_elf_symbols (file, symsec->sh_offset,
1682 symsec->sh_size / symsec->sh_entsize);
1683
1684 if (symtab == NULL)
1685 continue;
1686
1687 strsec = section_headers + symsec->sh_link;
1688
1689 GET_DATA_ALLOC (strsec->sh_offset, strsec->sh_size, strtab,
1690 char *, "string table");
1691
1692 dump_relocations (file, rel_offset, rel_size, symtab, strtab);
1693
1694 free (strtab);
1695 free (symtab);
1696
1697 found = 1;
1698 }
1699 }
1700
1701 if (! found)
1702 printf (_("\nThere are no relocations in this file.\n"));
1703 }
1704
1705 return 1;
1706 }
1707
1708
1709 static void
1710 dynamic_segment_mips_val (entry)
1711 Elf_Internal_Dyn *entry;
1712 {
1713 if (do_dynamic)
1714 switch (entry->d_tag)
1715 {
1716 case DT_MIPS_FLAGS:
1717 if (entry->d_un.d_val == 0)
1718 printf ("NONE\n");
1719 else
1720 {
1721 static const char *opts[] =
1722 {
1723 "QUICKSTART", "NOTPOT", "NO_LIBRARY_REPLACEMENT",
1724 "NO_MOVE", "SGI_ONLY", "GUARANTEE_INIT", "DELTA_C_PLUS_PLUS",
1725 "GUARANTEE_START_INIT", "PIXIE", "DEFAULT_DELAY_LOAD",
1726 "REQUICKSTART", "REQUICKSTARTED", "CORD", "NO_UNRES_UNDEF",
1727 "RLD_ORDER_SAFE"
1728 };
1729 unsigned int cnt;
1730 int first = 1;
1731 for (cnt = 0; cnt < sizeof (opts) / sizeof (opts[0]); ++cnt)
1732 if (entry->d_un.d_val & (1 << cnt))
1733 {
1734 printf ("%s%s", first ? "" : " ", opts[cnt]);
1735 first = 0;
1736 }
1737 puts ("");
1738 }
1739 break;
1740
1741 case DT_MIPS_IVERSION:
1742 if (dynamic_strings != NULL)
1743 printf ("Interface Version: %s\n",
1744 dynamic_strings + entry->d_un.d_val);
1745 else
1746 printf ("%#ld\n", (long) entry->d_un.d_ptr);
1747 break;
1748
1749 case DT_MIPS_TIME_STAMP:
1750 {
1751 char timebuf[20];
1752 time_t time = entry->d_un.d_val;
1753 strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time));
1754 printf ("Time Stamp: %s\n", timebuf);
1755 }
1756 break;
1757
1758 case DT_MIPS_RLD_VERSION:
1759 case DT_MIPS_LOCAL_GOTNO:
1760 case DT_MIPS_CONFLICTNO:
1761 case DT_MIPS_LIBLISTNO:
1762 case DT_MIPS_SYMTABNO:
1763 case DT_MIPS_UNREFEXTNO:
1764 case DT_MIPS_HIPAGENO:
1765 case DT_MIPS_DELTA_CLASS_NO:
1766 case DT_MIPS_DELTA_INSTANCE_NO:
1767 case DT_MIPS_DELTA_RELOC_NO:
1768 case DT_MIPS_DELTA_SYM_NO:
1769 case DT_MIPS_DELTA_CLASSSYM_NO:
1770 case DT_MIPS_COMPACT_SIZE:
1771 printf ("%#ld\n", (long) entry->d_un.d_ptr);
1772 break;
1773
1774 default:
1775 printf ("%#lx\n", (long) entry->d_un.d_ptr);
1776 }
1777 }
1778
1779 /* Parse the dynamic segment */
1780 static int
1781 process_dynamic_segment (file)
1782 FILE * file;
1783 {
1784 Elf_Internal_Dyn * entry;
1785 Elf32_External_Dyn * edyn;
1786 unsigned int i;
1787
1788 if (dynamic_size == 0)
1789 {
1790 if (do_dynamic)
1791 printf (_("\nThere is no dynamic segment in this file.\n"));
1792
1793 return 1;
1794 }
1795
1796 GET_DATA_ALLOC (dynamic_addr, dynamic_size,
1797 edyn, Elf32_External_Dyn *, "dynamic segment");
1798
1799 /* SGI's ELF has more than one section in the DYNAMIC segment. Determine
1800 how large .dynamic is now. We can do this even before the byte
1801 swapping since the DT_NULL tag is recognizable. */
1802 dynamic_size = 0;
1803 while (*(Elf32_Word *) edyn[dynamic_size++].d_tag != DT_NULL)
1804 ;
1805
1806 dynamic_segment = (Elf_Internal_Dyn *)
1807 malloc (dynamic_size * sizeof (Elf_Internal_Dyn));
1808
1809 if (dynamic_segment == NULL)
1810 {
1811 error (_("Out of memory\n"));
1812 free (edyn);
1813 return 0;
1814 }
1815
1816 for (i = 0, entry = dynamic_segment;
1817 i < dynamic_size;
1818 i ++, entry ++)
1819 {
1820 entry->d_tag = BYTE_GET (edyn [i].d_tag);
1821 entry->d_un.d_val = BYTE_GET (edyn [i].d_un.d_val);
1822 }
1823
1824 free (edyn);
1825
1826 /* Find the appropriate symbol table. */
1827 if (dynamic_symbols == NULL)
1828 {
1829 for (i = 0, entry = dynamic_segment;
1830 i < dynamic_size;
1831 ++i, ++ entry)
1832 {
1833 unsigned long offset;
1834 long num_syms;
1835
1836 if (entry->d_tag != DT_SYMTAB)
1837 continue;
1838
1839 dynamic_info[DT_SYMTAB] = entry->d_un.d_val;
1840
1841 /* Since we do not know how big the symbol table is,
1842 we default to reading in the entire file (!) and
1843 processing that. This is overkill, I know, but it
1844 should work. */
1845
1846 offset = entry->d_un.d_val - loadaddr;
1847
1848 if (fseek (file, 0, SEEK_END))
1849 error (_("Unable to seek to end of file!"));
1850
1851 num_syms = (ftell (file) - offset) / sizeof (Elf32_External_Sym);
1852
1853 if (num_syms < 1)
1854 {
1855 error (_("Unable to determine the number of symbols to load\n"));
1856 continue;
1857 }
1858
1859 dynamic_symbols = get_elf_symbols (file, offset, num_syms);
1860 }
1861 }
1862
1863 /* Similarly find a string table. */
1864 if (dynamic_strings == NULL)
1865 {
1866 for (i = 0, entry = dynamic_segment;
1867 i < dynamic_size;
1868 ++i, ++ entry)
1869 {
1870 unsigned long offset;
1871 long str_tab_len;
1872
1873 if (entry->d_tag != DT_STRTAB)
1874 continue;
1875
1876 dynamic_info[DT_STRTAB] = entry->d_un.d_val;
1877
1878 /* Since we do not know how big the string table is,
1879 we default to reading in the entire file (!) and
1880 processing that. This is overkill, I know, but it
1881 should work. */
1882
1883 offset = entry->d_un.d_val - loadaddr;
1884 if (fseek (file, 0, SEEK_END))
1885 error (_("Unable to seek to end of file\n"));
1886 str_tab_len = ftell (file) - offset;
1887
1888 if (str_tab_len < 1)
1889 {
1890 error
1891 (_("Unable to determine the length of the dynamic string table\n"));
1892 continue;
1893 }
1894
1895 GET_DATA_ALLOC (offset, str_tab_len, dynamic_strings, char *,
1896 "dynamic string table");
1897
1898 break;
1899 }
1900 }
1901
1902 /* And find the syminfo section if available. */
1903 if (dynamic_syminfo == NULL)
1904 {
1905 unsigned int syminsz = 0;
1906
1907 for (i = 0, entry = dynamic_segment;
1908 i < dynamic_size;
1909 ++i, ++ entry)
1910 {
1911 if (entry->d_tag == DT_SYMINENT)
1912 assert (sizeof (Elf_External_Syminfo) == entry->d_un.d_val);
1913 else if (entry->d_tag == DT_SYMINSZ)
1914 syminsz = entry->d_un.d_val;
1915 else if (entry->d_tag == DT_SYMINFO)
1916 dynamic_syminfo_offset = entry->d_un.d_val - loadaddr;
1917 }
1918
1919 if (dynamic_syminfo_offset != 0 && syminsz != 0)
1920 {
1921 Elf_External_Syminfo *extsyminfo;
1922 Elf_Internal_Syminfo *syminfo;
1923
1924 /* There is a syminfo section. Read the data. */
1925 GET_DATA_ALLOC (dynamic_syminfo_offset, syminsz, extsyminfo,
1926 Elf_External_Syminfo *, "symbol information");
1927
1928 dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz);
1929 if (dynamic_syminfo == NULL)
1930 {
1931 error (_("Out of memory\n"));
1932 return 0;
1933 }
1934
1935 dynamic_syminfo_nent = syminsz / sizeof (Elf_External_Syminfo);
1936 for (i = 0, syminfo = dynamic_syminfo; i < dynamic_syminfo_nent;
1937 ++i, ++syminfo)
1938 {
1939 syminfo->si_boundto = BYTE_GET (extsyminfo[i].si_boundto);
1940 syminfo->si_flags = BYTE_GET (extsyminfo[i].si_flags);
1941 }
1942
1943 free (extsyminfo);
1944 }
1945 }
1946
1947 if (do_dynamic && dynamic_addr)
1948 printf (_("\nDynamic segment at offset 0x%x contains %d entries:\n"),
1949 dynamic_addr, dynamic_size);
1950 if (do_dynamic)
1951 printf (_(" Tag Type Name/Value\n"));
1952
1953 for (i = 0, entry = dynamic_segment;
1954 i < dynamic_size;
1955 i++, entry ++)
1956 {
1957 if (do_dynamic)
1958 printf (_(" 0x%-8.8lx (%s)%*s"),
1959 (unsigned long) entry->d_tag,
1960 get_dynamic_type (entry->d_tag),
1961 27 - strlen (get_dynamic_type (entry->d_tag)),
1962 " ");
1963
1964 switch (entry->d_tag)
1965 {
1966 case DT_AUXILIARY:
1967 case DT_FILTER:
1968 if (do_dynamic)
1969 {
1970 if (entry->d_tag == DT_AUXILIARY)
1971 printf (_("Auxiliary library"));
1972 else
1973 printf (_("Filter library"));
1974
1975 if (dynamic_strings)
1976 printf (": [%s]\n", dynamic_strings + entry->d_un.d_val);
1977 else
1978 printf (": %#lx\n", (long) entry->d_un.d_val);
1979 }
1980 break;
1981
1982 case DT_POSFLAG_1:
1983 if (do_dynamic)
1984 {
1985 printf (_("Flags:"));
1986 if (entry->d_un.d_val == 0)
1987 printf (_(" None\n"));
1988 else
1989 {
1990 if (entry->d_un.d_val & DF_P1_LAZYLOAD)
1991 printf (" LAZYLOAD");
1992 if (entry->d_un.d_val & DF_P1_LAZYLOAD)
1993 printf (" GROUPPERM");
1994 puts ("");
1995 }
1996 }
1997 break;
1998
1999 case DT_FLAGS_1:
2000 if (do_dynamic)
2001 {
2002 printf (_("Flags:"));
2003 if (entry->d_un.d_val == 0)
2004 printf (_(" None\n"));
2005 else
2006 {
2007 if (entry->d_un.d_val & DF_1_NOW)
2008 printf (" NOW");
2009 if (entry->d_un.d_val & DF_1_GLOBAL)
2010 printf (" GLOBAL");
2011 if (entry->d_un.d_val & DF_1_GROUP)
2012 printf (" GROUP");
2013 if (entry->d_un.d_val & DF_1_NODELETE)
2014 printf (" NODELETE");
2015 if (entry->d_un.d_val & DF_1_LOADFLTR)
2016 printf (" LOADFLTR");
2017 if (entry->d_un.d_val & DF_1_INITFIRST)
2018 printf (" INITFIRST");
2019 if (entry->d_un.d_val & DF_1_NOOPEN)
2020 printf (" NOOPEN");
2021 if (entry->d_un.d_val & DF_1_ORIGIN)
2022 printf (" ORIGIN");
2023 if (entry->d_un.d_val & DF_1_DIRECT)
2024 printf (" DIRECT");
2025 if (entry->d_un.d_val & DF_1_TRANS)
2026 printf (" TRANS");
2027 if (entry->d_un.d_val & DF_1_INTERPOSE)
2028 printf (" INTERPOSE");
2029 puts ("");
2030 }
2031 }
2032 break;
2033
2034 case DT_NULL :
2035 case DT_NEEDED :
2036 case DT_PLTRELSZ:
2037 case DT_PLTGOT :
2038 case DT_HASH :
2039 case DT_STRTAB :
2040 case DT_SYMTAB :
2041 case DT_RELA :
2042 case DT_INIT :
2043 case DT_FINI :
2044 case DT_SONAME :
2045 case DT_RPATH :
2046 case DT_SYMBOLIC:
2047 case DT_REL :
2048 case DT_PLTREL :
2049 case DT_DEBUG :
2050 case DT_TEXTREL :
2051 case DT_JMPREL :
2052 dynamic_info[entry->d_tag] = entry->d_un.d_val;
2053
2054 if (do_dynamic)
2055 {
2056 char * name;
2057
2058 if (dynamic_strings == NULL)
2059 name = NULL;
2060 else
2061 name = dynamic_strings + entry->d_un.d_val;
2062
2063 if (name)
2064 {
2065 switch (entry->d_tag)
2066 {
2067 case DT_NEEDED:
2068 printf (_("Shared library: [%s]"), name);
2069
2070 if (strcmp (name, program_interpreter))
2071 printf ("\n");
2072 else
2073 printf (_(" program interpreter\n"));
2074 break;
2075
2076 case DT_SONAME:
2077 printf (_("Library soname: [%s]\n"), name);
2078 break;
2079
2080 case DT_RPATH:
2081 printf (_("Library rpath: [%s]\n"), name);
2082 break;
2083
2084 default:
2085 printf ("%#lx\n", (long) entry->d_un.d_val);
2086 }
2087 }
2088 else
2089 printf ("%#lx\n", (long) entry->d_un.d_val);
2090 }
2091 break;
2092
2093 case DT_RELASZ :
2094 case DT_RELAENT :
2095 case DT_STRSZ :
2096 case DT_SYMENT :
2097 case DT_RELSZ :
2098 case DT_RELENT :
2099 case DT_VERDEFNUM:
2100 case DT_VERNEEDNUM:
2101 case DT_RELACOUNT:
2102 case DT_RELCOUNT:
2103 if (do_dynamic)
2104 printf ("%ld\n", entry->d_un.d_val);
2105 break;
2106
2107 case DT_SYMINSZ :
2108 case DT_SYMINENT:
2109 case DT_SYMINFO :
2110 case DT_USED:
2111 if (do_dynamic)
2112 {
2113 char * name;
2114
2115 if (dynamic_strings == NULL)
2116 name = NULL;
2117 else
2118 name = dynamic_strings + entry->d_un.d_val;
2119
2120
2121
2122 if (name)
2123 {
2124 switch (entry->d_tag)
2125 {
2126 case DT_USED:
2127 printf (_("Not needed object: [%s]\n"), name);
2128 break;
2129
2130 default:
2131 printf ("%#lx\n", (long) entry->d_un.d_val);
2132 }
2133 }
2134 else
2135 printf ("%#lx\n", (long) entry->d_un.d_val);
2136 }
2137 break;
2138
2139 default:
2140 if ((entry->d_tag >= DT_VERSYM) && (entry->d_tag <= DT_VERNEEDNUM))
2141 {
2142 version_info [DT_VERSIONTAGIDX (entry->d_tag)] =
2143 entry->d_un.d_val;
2144
2145 if (do_dynamic)
2146 printf ("%#lx\n", (long) entry->d_un.d_ptr);
2147 }
2148 else
2149 switch (elf_header.e_machine)
2150 {
2151 case EM_MIPS:
2152 case EM_MIPS_RS4_BE:
2153 dynamic_segment_mips_val (entry);
2154 break;
2155 default:
2156 if (do_dynamic)
2157 printf ("%#lx\n", (long) entry->d_un.d_ptr);
2158 }
2159 break;
2160 }
2161 }
2162
2163 return 1;
2164 }
2165
2166 static char *
2167 get_ver_flags (flags)
2168 unsigned int flags;
2169 {
2170 static char buff [32];
2171
2172 buff[0] = 0;
2173
2174 if (flags == 0)
2175 return _("none");
2176
2177 if (flags & VER_FLG_BASE)
2178 strcat (buff, "BASE ");
2179
2180 if (flags & VER_FLG_WEAK)
2181 {
2182 if (flags & VER_FLG_BASE)
2183 strcat (buff, "| ");
2184
2185 strcat (buff, "WEAK ");
2186 }
2187
2188 if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK))
2189 strcat (buff, "| <unknown>");
2190
2191 return buff;
2192 }
2193
2194 /* Display the contents of the version sections. */
2195 static int
2196 process_version_sections (file)
2197 FILE * file;
2198 {
2199 Elf32_Internal_Shdr * section;
2200 unsigned i;
2201 int found = 0;
2202
2203 if (! do_version)
2204 return 1;
2205
2206 for (i = 0, section = section_headers;
2207 i < elf_header.e_shnum;
2208 i++, section ++)
2209 {
2210 switch (section->sh_type)
2211 {
2212 case SHT_GNU_verdef:
2213 {
2214 Elf_External_Verdef * edefs;
2215 unsigned int idx;
2216 unsigned int cnt;
2217
2218 found = 1;
2219
2220 printf
2221 (_("\nVersion definition section '%s' contains %d entries:\n"),
2222 SECTION_NAME (section), section->sh_info);
2223
2224 printf (_(" Addr: %#08x Offset: %#08x Link: %x (%s)\n"),
2225 section->sh_addr, section->sh_offset, section->sh_link,
2226 SECTION_NAME (section_headers + section->sh_link));
2227
2228 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
2229 edefs, Elf_External_Verdef *,
2230 "version definition section");
2231
2232 for (idx = cnt = 0; cnt < section->sh_info; ++ cnt)
2233 {
2234 char * vstart;
2235 Elf_External_Verdef * edef;
2236 Elf_Internal_Verdef ent;
2237 Elf_External_Verdaux * eaux;
2238 Elf_Internal_Verdaux aux;
2239 int j;
2240 int isum;
2241
2242 vstart = ((char *) edefs) + idx;
2243
2244 edef = (Elf_External_Verdef *) vstart;
2245
2246 ent.vd_version = BYTE_GET (edef->vd_version);
2247 ent.vd_flags = BYTE_GET (edef->vd_flags);
2248 ent.vd_ndx = BYTE_GET (edef->vd_ndx);
2249 ent.vd_cnt = BYTE_GET (edef->vd_cnt);
2250 ent.vd_hash = BYTE_GET (edef->vd_hash);
2251 ent.vd_aux = BYTE_GET (edef->vd_aux);
2252 ent.vd_next = BYTE_GET (edef->vd_next);
2253
2254 printf (_(" %#06x: Rev: %d Flags: %s"),
2255 idx, ent.vd_version, get_ver_flags (ent.vd_flags));
2256
2257 printf (_(" Index: %ld Cnt: %ld "), ent.vd_ndx, ent.vd_cnt);
2258
2259 vstart += ent.vd_aux;
2260
2261 eaux = (Elf_External_Verdaux *) vstart;
2262
2263 aux.vda_name = BYTE_GET (eaux->vda_name);
2264 aux.vda_next = BYTE_GET (eaux->vda_next);
2265
2266 if (dynamic_strings)
2267 printf (_("Name: %s\n"), dynamic_strings + aux.vda_name);
2268 else
2269 printf (_("Name index: %ld\n"), aux.vda_name);
2270
2271 isum = idx + ent.vd_aux;
2272
2273 for (j = 1; j < ent.vd_cnt; j ++)
2274 {
2275 isum += aux.vda_next;
2276 vstart += aux.vda_next;
2277
2278 eaux = (Elf_External_Verdaux *) vstart;
2279
2280 aux.vda_name = BYTE_GET (eaux->vda_name);
2281 aux.vda_next = BYTE_GET (eaux->vda_next);
2282
2283 if (dynamic_strings)
2284 printf (_(" %#06x: Parent %d: %s\n"),
2285 isum, j, dynamic_strings + aux.vda_name);
2286 else
2287 printf (_(" %#06x: Parent %d, name index: %ld\n"),
2288 isum, j, aux.vda_name);
2289 }
2290
2291 idx += ent.vd_next;
2292 }
2293
2294 free (edefs);
2295 }
2296 break;
2297
2298 case SHT_GNU_verneed:
2299 {
2300 Elf_External_Verneed * eneed;
2301 unsigned int idx;
2302 unsigned int cnt;
2303
2304 found = 1;
2305
2306 printf (_("\nVersion needs section '%s' contains %d entries:\n"),
2307 SECTION_NAME (section), section->sh_info);
2308
2309 printf
2310 (_(" Addr: %#08x Offset: %#08x Link to section: %d (%s)\n"),
2311 section->sh_addr, section->sh_offset, section->sh_link,
2312 SECTION_NAME (section_headers + section->sh_link));
2313
2314 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
2315 eneed, Elf_External_Verneed *,
2316 "version need section");
2317
2318 for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
2319 {
2320 Elf_External_Verneed * entry;
2321 Elf_Internal_Verneed ent;
2322 int j;
2323 int isum;
2324 char * vstart;
2325
2326 vstart = ((char *) eneed) + idx;
2327
2328 entry = (Elf_External_Verneed *) vstart;
2329
2330 ent.vn_version = BYTE_GET (entry->vn_version);
2331 ent.vn_cnt = BYTE_GET (entry->vn_cnt);
2332 ent.vn_file = BYTE_GET (entry->vn_file);
2333 ent.vn_aux = BYTE_GET (entry->vn_aux);
2334 ent.vn_next = BYTE_GET (entry->vn_next);
2335
2336 printf (_(" %#06x: Version: %d"), idx, ent.vn_version);
2337
2338 if (dynamic_strings)
2339 printf (_(" File: %s"), dynamic_strings + ent.vn_file);
2340 else
2341 printf (_(" File: %lx"), ent.vn_file);
2342
2343 printf (_(" Cnt: %d\n"), ent.vn_cnt);
2344
2345 vstart += ent.vn_aux;
2346
2347 for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j)
2348 {
2349 Elf_External_Vernaux * eaux;
2350 Elf_Internal_Vernaux aux;
2351
2352 eaux = (Elf_External_Vernaux *) vstart;
2353
2354 aux.vna_hash = BYTE_GET (eaux->vna_hash);
2355 aux.vna_flags = BYTE_GET (eaux->vna_flags);
2356 aux.vna_other = BYTE_GET (eaux->vna_other);
2357 aux.vna_name = BYTE_GET (eaux->vna_name);
2358 aux.vna_next = BYTE_GET (eaux->vna_next);
2359
2360 if (dynamic_strings)
2361 printf (_(" %#06x: Name: %s"),
2362 isum, dynamic_strings + aux.vna_name);
2363 else
2364 printf (_(" %#06x: Name index: %lx"),
2365 isum, aux.vna_name);
2366
2367 printf (_(" Flags: %s Version: %d\n"),
2368 get_ver_flags (aux.vna_flags), aux.vna_other);
2369
2370 isum += aux.vna_next;
2371 vstart += aux.vna_next;
2372 }
2373
2374 idx += ent.vn_next;
2375 }
2376
2377 free (eneed);
2378 }
2379 break;
2380
2381 case SHT_GNU_versym:
2382 {
2383 Elf32_Internal_Shdr * link_section;
2384 int total;
2385 int cnt;
2386 unsigned char * edata;
2387 unsigned short * data;
2388 char * strtab;
2389 Elf_Internal_Sym * symbols;
2390 Elf32_Internal_Shdr * string_sec;
2391
2392 link_section = section_headers + section->sh_link;
2393 total = section->sh_size / section->sh_entsize;
2394
2395 found = 1;
2396
2397 symbols = get_elf_symbols
2398 (file, link_section->sh_offset,
2399 link_section->sh_size / link_section->sh_entsize);
2400
2401 string_sec = section_headers + link_section->sh_link;
2402
2403 GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
2404 strtab, char *, "version string table");
2405
2406 printf (_("\nVersion symbols section '%s' contains %d entries:\n"),
2407 SECTION_NAME (section), total);
2408
2409 printf (_(" Addr: %#08x Offset: %#08x Link: %x (%s)\n"),
2410 section->sh_addr, section->sh_offset, section->sh_link,
2411 SECTION_NAME (link_section));
2412
2413 GET_DATA_ALLOC (version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
2414 - loadaddr,
2415 total * sizeof (short), edata,
2416 char *, "version symbol data");
2417
2418 data = (unsigned short *) malloc (total * sizeof (short));
2419
2420 for (cnt = total; cnt --;)
2421 data [cnt] = byte_get (edata + cnt * sizeof (short), sizeof (short));
2422
2423 free (edata);
2424
2425 for (cnt = 0; cnt < total; cnt += 4)
2426 {
2427 int j, nn;
2428
2429 printf (" %03x:", cnt);
2430
2431 for (j = 0; (j < 4) && (cnt + j) < total; ++j)
2432 switch (data [cnt + j])
2433 {
2434 case 0:
2435 fputs (_(" 0 (*local*) "), stdout);
2436 break;
2437
2438 case 1:
2439 fputs (_(" 1 (*global*) "), stdout);
2440 break;
2441
2442 default:
2443 nn = printf ("%4x%c", data [cnt + j] & 0x7fff,
2444 data [cnt + j] & 0x8000 ? 'h' : ' ');
2445
2446 if (symbols [cnt + j].st_shndx < SHN_LORESERVE
2447 && section_headers[symbols [cnt + j].st_shndx].sh_type
2448 == SHT_NOBITS)
2449 {
2450 /* We must test both. */
2451 Elf_Internal_Verneed ivn;
2452 unsigned long offset;
2453
2454 offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
2455 - loadaddr;
2456
2457 do
2458 {
2459 Elf_External_Verneed evn;
2460 Elf_External_Vernaux evna;
2461 Elf_Internal_Vernaux ivna;
2462 unsigned long vna_off;
2463
2464 GET_DATA (offset, evn, "version need");
2465
2466 ivn.vn_aux = BYTE_GET (evn.vn_aux);
2467 ivn.vn_next = BYTE_GET (evn.vn_next);
2468
2469 vna_off = offset + ivn.vn_aux;
2470
2471 do
2472 {
2473 GET_DATA (vna_off, evna,
2474 "version need aux (1)");
2475
2476 ivna.vna_next = BYTE_GET (evna.vna_next);
2477 ivna.vna_other = BYTE_GET (evna.vna_other);
2478
2479 vna_off += ivna.vna_next;
2480 }
2481 while (ivna.vna_other != data [cnt + j]
2482 && ivna.vna_next != 0);
2483
2484 if (ivna.vna_other == data [cnt + j])
2485 {
2486 ivna.vna_name = BYTE_GET (evna.vna_name);
2487
2488 nn += printf ("(%s%-*s",
2489 strtab + ivna.vna_name,
2490 12 - strlen (strtab
2491 + ivna.vna_name),
2492 ")");
2493 break;
2494 }
2495 else if (ivn.vn_next == 0)
2496 {
2497 if (data [cnt + j] != 0x8001)
2498 {
2499 Elf_Internal_Verdef ivd;
2500 Elf_External_Verdef evd;
2501
2502 offset = version_info
2503 [DT_VERSIONTAGIDX (DT_VERDEF)]
2504 - loadaddr;
2505
2506 do
2507 {
2508 GET_DATA (offset, evd,
2509 "version definition");
2510
2511 ivd.vd_next = BYTE_GET (evd.vd_next);
2512 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
2513
2514 offset += ivd.vd_next;
2515 }
2516 while (ivd.vd_ndx
2517 != (data [cnt + j] & 0x7fff)
2518 && ivd.vd_next != 0);
2519
2520 if (ivd.vd_ndx
2521 == (data [cnt + j] & 0x7fff))
2522 {
2523 Elf_External_Verdaux evda;
2524 Elf_Internal_Verdaux ivda;
2525
2526 ivd.vd_aux = BYTE_GET (evd.vd_aux);
2527
2528 GET_DATA (offset + ivd.vd_aux, evda,
2529 "version definition aux");
2530
2531 ivda.vda_name =
2532 BYTE_GET (evda.vda_name);
2533
2534 nn +=
2535 printf ("(%s%-*s",
2536 strtab + ivda.vda_name,
2537 12
2538 - strlen (strtab
2539 + ivda.vda_name),
2540 ")");
2541 }
2542 }
2543
2544 break;
2545 }
2546 else
2547 offset += ivn.vn_next;
2548 }
2549 while (ivn.vn_next);
2550 }
2551 else if (symbols [cnt + j].st_shndx == SHN_UNDEF)
2552 {
2553 Elf_Internal_Verneed ivn;
2554 unsigned long offset;
2555
2556 offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
2557 - loadaddr;
2558
2559 do
2560 {
2561 Elf_Internal_Vernaux ivna;
2562 Elf_External_Verneed evn;
2563 Elf_External_Vernaux evna;
2564 unsigned long a_off;
2565
2566 GET_DATA (offset, evn, "version need");
2567
2568 ivn.vn_aux = BYTE_GET (evn.vn_aux);
2569 ivn.vn_next = BYTE_GET (evn.vn_next);
2570
2571 a_off = offset + ivn.vn_aux;
2572
2573 do
2574 {
2575 GET_DATA (a_off, evna,
2576 "version need aux (2)");
2577
2578 ivna.vna_next = BYTE_GET (evna.vna_next);
2579 ivna.vna_other = BYTE_GET (evna.vna_other);
2580
2581 a_off += ivna.vna_next;
2582 }
2583 while (ivna.vna_other != data [cnt + j]
2584 && ivna.vna_next != 0);
2585
2586 if (ivna.vna_other == data [cnt + j])
2587 {
2588 ivna.vna_name = BYTE_GET (evna.vna_name);
2589
2590 nn += printf ("(%s%-*s",
2591 strtab + ivna.vna_name,
2592 12 - strlen (strtab
2593 + ivna.vna_name),
2594 ")");
2595 break;
2596 }
2597
2598 offset += ivn.vn_next;
2599 }
2600 while (ivn.vn_next);
2601 }
2602 else if (data [cnt + j] != 0x8001)
2603 {
2604 Elf_Internal_Verdef ivd;
2605 Elf_External_Verdef evd;
2606 unsigned long offset;
2607
2608 offset = version_info
2609 [DT_VERSIONTAGIDX (DT_VERDEF)] - loadaddr;
2610
2611 do
2612 {
2613 GET_DATA (offset, evd, "version def");
2614
2615 ivd.vd_next = BYTE_GET (evd.vd_next);
2616 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
2617
2618 offset += ivd.vd_next;
2619 }
2620 while (ivd.vd_ndx != (data [cnt + j] & 0x7fff)
2621 && ivd.vd_next != 0);
2622
2623 if (ivd.vd_ndx == (data [cnt + j] & 0x7fff))
2624 {
2625 Elf_External_Verdaux evda;
2626 Elf_Internal_Verdaux ivda;
2627
2628 ivd.vd_aux = BYTE_GET (evd.vd_aux);
2629
2630 GET_DATA (offset - ivd.vd_next + ivd.vd_aux,
2631 evda, "version def aux");
2632
2633 ivda.vda_name = BYTE_GET (evda.vda_name);
2634
2635 nn += printf ("(%s%-*s",
2636 strtab + ivda.vda_name,
2637 12 - strlen (strtab
2638 + ivda.vda_name),
2639 ")");
2640 }
2641 }
2642
2643 if (nn < 18)
2644 printf ("%*c", 18 - nn, ' ');
2645 }
2646
2647 putchar ('\n');
2648 }
2649
2650 free (data);
2651 free (strtab);
2652 free (symbols);
2653 }
2654 break;
2655
2656 default:
2657 break;
2658 }
2659 }
2660
2661 if (! found)
2662 printf (_("\nNo version information found in this file.\n"));
2663
2664 return 1;
2665 }
2666
2667 static char *
2668 get_symbol_binding (binding)
2669 unsigned int binding;
2670 {
2671 static char buff [32];
2672
2673 switch (binding)
2674 {
2675 case STB_LOCAL: return _("LOCAL");
2676 case STB_GLOBAL: return _("GLOBAL");
2677 case STB_WEAK: return _("WEAK");
2678 default:
2679 if (binding >= STB_LOPROC && binding <= STB_HIPROC)
2680 sprintf (buff, _("<processor specific>: %d"), binding);
2681 else
2682 sprintf (buff, _("<unknown>: %d"), binding);
2683 return buff;
2684 }
2685 }
2686
2687 static char *
2688 get_symbol_type (type)
2689 unsigned int type;
2690 {
2691 static char buff [32];
2692
2693 switch (type)
2694 {
2695 case STT_NOTYPE: return _("NOTYPE");
2696 case STT_OBJECT: return _("OBJECT");
2697 case STT_FUNC: return _("FUNC");
2698 case STT_SECTION: return _("SECTION");
2699 case STT_FILE: return _("FILE");
2700 default:
2701 if (type >= STT_LOPROC && type <= STT_HIPROC)
2702 sprintf (buff, _("<processor specific>: %d"), type);
2703 else
2704 sprintf (buff, _("<unknown>: %d"), type);
2705 return buff;
2706 }
2707 }
2708
2709 static char *
2710 get_symbol_index_type (type)
2711 unsigned int type;
2712 {
2713 switch (type)
2714 {
2715 case SHN_UNDEF: return "UND";
2716 case SHN_ABS: return "ABS";
2717 case SHN_COMMON: return "COM";
2718 default:
2719 if (type >= SHN_LOPROC && type <= SHN_HIPROC)
2720 return "PRC";
2721 else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE)
2722 return "RSV";
2723 else
2724 {
2725 static char buff [32];
2726
2727 sprintf (buff, "%3d", type);
2728 return buff;
2729 }
2730 }
2731 }
2732
2733
2734 static int *
2735 get_dynamic_data (file, number)
2736 FILE * file;
2737 unsigned int number;
2738 {
2739 char * e_data;
2740 int * i_data;
2741
2742 e_data = (char *) malloc (number * 4);
2743
2744 if (e_data == NULL)
2745 {
2746 error (_("Out of memory\n"));
2747 return NULL;
2748 }
2749
2750 if (fread (e_data, 4, number, file) != number)
2751 {
2752 error (_("Unable to read in dynamic data\n"));
2753 return NULL;
2754 }
2755
2756 i_data = (int *) malloc (number * sizeof (* i_data));
2757
2758 if (i_data == NULL)
2759 {
2760 error (_("Out of memory\n"));
2761 free (e_data);
2762 return NULL;
2763 }
2764
2765 while (number--)
2766 i_data [number] = byte_get (e_data + number * 4, 4);
2767
2768 free (e_data);
2769
2770 return i_data;
2771 }
2772
2773 /* Dump the symbol table */
2774 static int
2775 process_symbol_table (file)
2776 FILE * file;
2777 {
2778 Elf32_Internal_Shdr * section;
2779 char nb [4];
2780 char nc [4];
2781 int nbuckets;
2782 int nchains;
2783 int * buckets = NULL;
2784 int * chains = NULL;
2785
2786 if (! do_syms && !do_histogram)
2787 return 1;
2788
2789 if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL)
2790 || do_histogram))
2791 {
2792 if (fseek (file, dynamic_info[DT_HASH] - loadaddr, SEEK_SET))
2793 {
2794 error (_("Unable to seek to start of dynamic information"));
2795 return 0;
2796 }
2797
2798 if (fread (& nb, sizeof (nb), 1, file) != 1)
2799 {
2800 error (_("Failed to read in number of buckets\n"));
2801 return 0;
2802 }
2803
2804 if (fread (& nc, sizeof (nc), 1, file) != 1)
2805 {
2806 error (_("Failed to read in number of chains\n"));
2807 return 0;
2808 }
2809
2810 nbuckets = byte_get (nb, 4);
2811 nchains = byte_get (nc, 4);
2812
2813 buckets = get_dynamic_data (file, nbuckets);
2814 chains = get_dynamic_data (file, nchains);
2815
2816 if (buckets == NULL || chains == NULL)
2817 return 0;
2818 }
2819
2820 if (do_syms
2821 && dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL)
2822 {
2823 int hn;
2824 int si;
2825
2826 printf (_("\nSymbol table for image:\n"));
2827 printf (_(" Num Buc: Value Size Type Bind Ot Ndx Name\n"));
2828
2829 for (hn = 0; hn < nbuckets; hn++)
2830 {
2831 if (! buckets [hn])
2832 continue;
2833
2834 for (si = buckets [hn]; si; si = chains [si])
2835 {
2836 Elf_Internal_Sym * psym;
2837
2838 psym = dynamic_symbols + si;
2839
2840 printf (" %3d %3d: %8lx %5ld %6s %6s %2d ",
2841 si, hn,
2842 (unsigned long) psym->st_value,
2843 (unsigned long) psym->st_size,
2844 get_symbol_type (ELF_ST_TYPE (psym->st_info)),
2845 get_symbol_binding (ELF_ST_BIND (psym->st_info)),
2846 psym->st_other);
2847
2848 printf ("%3.3s", get_symbol_index_type (psym->st_shndx));
2849
2850 printf (" %s\n", dynamic_strings + psym->st_name);
2851 }
2852 }
2853 }
2854 else if (do_syms && !do_using_dynamic)
2855 {
2856 unsigned int i;
2857
2858 for (i = 0, section = section_headers;
2859 i < elf_header.e_shnum;
2860 i++, section++)
2861 {
2862 unsigned int si;
2863 char * strtab;
2864 Elf_Internal_Sym * symtab;
2865 Elf_Internal_Sym * psym;
2866
2867
2868 if ( section->sh_type != SHT_SYMTAB
2869 && section->sh_type != SHT_DYNSYM)
2870 continue;
2871
2872 printf (_("\nSymbol table '%s' contains %d entries:\n"),
2873 SECTION_NAME (section),
2874 section->sh_size / section->sh_entsize);
2875 fputs (_(" Num: Value Size Type Bind Ot Ndx Name\n"),
2876 stdout);
2877
2878 symtab = get_elf_symbols (file, section->sh_offset,
2879 section->sh_size / section->sh_entsize);
2880 if (symtab == NULL)
2881 continue;
2882
2883 if (section->sh_link == elf_header.e_shstrndx)
2884 strtab = string_table;
2885 else
2886 {
2887 Elf32_Internal_Shdr * string_sec;
2888
2889 string_sec = section_headers + section->sh_link;
2890
2891 GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
2892 strtab, char *, "string table");
2893 }
2894
2895 for (si = 0, psym = symtab;
2896 si < section->sh_size / section->sh_entsize;
2897 si ++, psym ++)
2898 {
2899 printf (" %3d: %8lx %5ld %-7s %-6s %2d ",
2900 si,
2901 (unsigned long) psym->st_value,
2902 (unsigned long) psym->st_size,
2903 get_symbol_type (ELF_ST_TYPE (psym->st_info)),
2904 get_symbol_binding (ELF_ST_BIND (psym->st_info)),
2905 psym->st_other);
2906
2907 if (psym->st_shndx == 0)
2908 fputs (" UND", stdout);
2909 else if ((psym->st_shndx & 0xffff) == 0xfff1)
2910 fputs (" ABS", stdout);
2911 else if ((psym->st_shndx & 0xffff) == 0xfff2)
2912 fputs (" COM", stdout);
2913 else
2914 printf ("%4x", psym->st_shndx);
2915
2916 printf (" %s", strtab + psym->st_name);
2917
2918 if (section->sh_type == SHT_DYNSYM &&
2919 version_info [DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
2920 {
2921 unsigned char data[2];
2922 unsigned short vers_data;
2923 unsigned long offset;
2924 int is_nobits;
2925 int check_def;
2926
2927 offset = version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
2928 - loadaddr;
2929
2930 GET_DATA (offset + si * sizeof (vers_data), data,
2931 "version data");
2932
2933 vers_data = byte_get (data, 2);
2934
2935 is_nobits = psym->st_shndx < SHN_LORESERVE ?
2936 (section_headers [psym->st_shndx].sh_type == SHT_NOBITS)
2937 : 0;
2938
2939 check_def = (psym->st_shndx != SHN_UNDEF);
2940
2941 if ((vers_data & 0x8000) || vers_data > 1)
2942 {
2943 if (is_nobits || ! check_def)
2944 {
2945 Elf_External_Verneed evn;
2946 Elf_Internal_Verneed ivn;
2947 Elf_Internal_Vernaux ivna;
2948
2949 /* We must test both. */
2950 offset = version_info
2951 [DT_VERSIONTAGIDX (DT_VERNEED)] - loadaddr;
2952
2953 GET_DATA (offset, evn, "version need");
2954
2955 ivn.vn_aux = BYTE_GET (evn.vn_aux);
2956 ivn.vn_next = BYTE_GET (evn.vn_next);
2957
2958 do
2959 {
2960 unsigned long vna_off;
2961
2962 vna_off = offset + ivn.vn_aux;
2963
2964 do
2965 {
2966 Elf_External_Vernaux evna;
2967
2968 GET_DATA (vna_off, evna,
2969 "version need aux (3)");
2970
2971 ivna.vna_other = BYTE_GET (evna.vna_other);
2972 ivna.vna_next = BYTE_GET (evna.vna_next);
2973 ivna.vna_name = BYTE_GET (evna.vna_name);
2974
2975 vna_off += ivna.vna_next;
2976 }
2977 while (ivna.vna_other != vers_data
2978 && ivna.vna_next != 0);
2979
2980 if (ivna.vna_other == vers_data)
2981 break;
2982
2983 offset += ivn.vn_next;
2984 }
2985 while (ivn.vn_next != 0);
2986
2987 if (ivna.vna_other == vers_data)
2988 {
2989 printf ("@%s (%d)",
2990 strtab + ivna.vna_name, ivna.vna_other);
2991 check_def = 0;
2992 }
2993 else if (! is_nobits)
2994 error (_("bad dynamic symbol"));
2995 else
2996 check_def = 1;
2997 }
2998
2999 if (check_def)
3000 {
3001 if (vers_data != 0x8001)
3002 {
3003 Elf_Internal_Verdef ivd;
3004 Elf_Internal_Verdaux ivda;
3005 Elf_External_Verdaux evda;
3006 unsigned long offset;
3007
3008 offset =
3009 version_info [DT_VERSIONTAGIDX (DT_VERDEF)]
3010 - loadaddr;
3011
3012 do
3013 {
3014 Elf_External_Verdef evd;
3015
3016 GET_DATA (offset, evd, "version def");
3017
3018 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
3019 ivd.vd_aux = BYTE_GET (evd.vd_aux);
3020 ivd.vd_next = BYTE_GET (evd.vd_next);
3021
3022 offset += ivd.vd_next;
3023 }
3024 while (ivd.vd_ndx != (vers_data & 0x7fff)
3025 && ivd.vd_next != 0);
3026
3027 offset -= ivd.vd_next;
3028 offset += ivd.vd_aux;
3029
3030 GET_DATA (offset, evda, "version def aux");
3031
3032 ivda.vda_name = BYTE_GET (evda.vda_name);
3033
3034 if (psym->st_name != ivda.vda_name)
3035 printf ((vers_data & 0x8000)
3036 ? "@%s" : "@@%s",
3037 strtab + ivda.vda_name);
3038 }
3039 }
3040 }
3041 }
3042
3043 putchar ('\n');
3044 }
3045
3046 free (symtab);
3047 if (strtab != string_table)
3048 free (strtab);
3049 }
3050 }
3051 else if (do_syms)
3052 printf
3053 (_("\nDynamic symbol information is not available for displaying symbols.\n"));
3054
3055 if (do_histogram)
3056 {
3057 int *lengths;
3058 int *counts;
3059 int hn;
3060 int si;
3061 int maxlength = 0;
3062
3063 printf (_("\nHistogram for bucket list length (total of %d buckets):\n"),
3064 nbuckets);
3065 printf (_(" Length Number\n"));
3066
3067 lengths = (int *) calloc (nbuckets, sizeof (int));
3068 if (lengths == NULL)
3069 {
3070 error (_("Out of memory"));
3071 return 0;
3072 }
3073 for (hn = 0; hn < nbuckets; ++hn)
3074 {
3075 if (! buckets [hn])
3076 continue;
3077
3078 for (si = buckets[hn]; si; si = chains[si])
3079 if (maxlength < ++lengths[hn])
3080 maxlength = lengths[hn];
3081 }
3082
3083 counts = (int *) calloc (maxlength + 1, sizeof (int));
3084 if (counts == NULL)
3085 {
3086 error (_("Out of memory"));
3087 return 0;
3088 }
3089
3090 for (hn = 0; hn < nbuckets; ++hn)
3091 ++counts[lengths[hn]];
3092
3093 for (si = 0; si <= maxlength; ++si)
3094 printf ("%7d %-10d (%5.1f%%)\n",
3095 si, counts[si], (counts[si] * 100.0) / nbuckets);
3096
3097 free (counts);
3098 free (lengths);
3099 }
3100
3101 if (buckets != NULL)
3102 {
3103 free (buckets);
3104 free (chains);
3105 }
3106
3107 return 1;
3108 }
3109
3110 static int
3111 process_syminfo (file)
3112 FILE * file;
3113 {
3114 int i;
3115
3116 if (dynamic_syminfo == NULL
3117 || !do_dynamic)
3118 /* No syminfo, this is ok. */
3119 return 1;
3120
3121 /* There better should be a dynamic symbol section. */
3122 if (dynamic_symbols == NULL || dynamic_strings == NULL)
3123 return 0;
3124
3125 if (dynamic_addr)
3126 printf (_("\nDynamic info segment at offset 0x%x contains %d entries:\n"),
3127 dynamic_syminfo_offset, dynamic_syminfo_nent);
3128
3129 printf (_(" Num: Name BoundTo Flags\n"));
3130 for (i = 0; i < dynamic_syminfo_nent; ++i)
3131 {
3132 unsigned short int flags = dynamic_syminfo[i].si_flags;
3133
3134 printf ("%4d: %-30s ", i,
3135 dynamic_strings + dynamic_symbols[i].st_name);
3136
3137 switch (dynamic_syminfo[i].si_boundto)
3138 {
3139 case SYMINFO_BT_SELF:
3140 fputs ("SELF ", stdout);
3141 break;
3142 case SYMINFO_BT_PARENT:
3143 fputs ("PARENT ", stdout);
3144 break;
3145 default:
3146 if (dynamic_syminfo[i].si_boundto > 0
3147 && dynamic_syminfo[i].si_boundto < dynamic_size)
3148 printf ("%-10s ",
3149 dynamic_strings
3150 + dynamic_segment[dynamic_syminfo[i].si_boundto].d_un.d_val);
3151 else
3152 printf ("%-10d ", dynamic_syminfo[i].si_boundto);
3153 break;
3154 }
3155
3156 if (flags & SYMINFO_FLG_DIRECT)
3157 printf (" DIRECT");
3158 if (flags & SYMINFO_FLG_PASSTHRU)
3159 printf (" PASSTHRU");
3160 if (flags & SYMINFO_FLG_COPY)
3161 printf (" COPY");
3162 if (flags & SYMINFO_FLG_LAZYLOAD)
3163 printf (" LAZYLOAD");
3164
3165 puts ("");
3166 }
3167
3168 return 1;
3169 }
3170
3171 static int
3172 process_section_contents (file)
3173 FILE * file;
3174 {
3175 Elf32_Internal_Shdr * section;
3176 unsigned int i;
3177
3178 if (! do_dump)
3179 return 1;
3180
3181 for (i = 0, section = section_headers;
3182 i < elf_header.e_shnum;
3183 i ++, section ++)
3184 {
3185 #ifdef SUPPORT_DISASSEMBLY
3186 /* See if we need an assembly dump of this section */
3187
3188 if ((i < NUM_DUMP_SECTS) && (dump_sects[i] & DISASS_DUMP))
3189 {
3190 printf (_("\nAssembly dump of section %s\n"),
3191 SECTION_NAME (section));
3192
3193 /* XXX -- to be done --- XXX */
3194 }
3195 #endif
3196 /* See if we need a hex dump of this section. */
3197 if ((i < NUM_DUMP_SECTS) && (dump_sects[i] & HEX_DUMP))
3198 {
3199 int bytes;
3200 int addr;
3201 unsigned char * data;
3202 char * start;
3203
3204 bytes = section->sh_size;
3205
3206 if (bytes == 0)
3207 {
3208 printf (_("\nSection %d has no data to dump.\n"), i);
3209 continue;
3210 }
3211 else
3212 printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section));
3213
3214 addr = section->sh_addr;
3215
3216 GET_DATA_ALLOC (section->sh_offset, bytes, start, char *,
3217 "section data");
3218
3219 data = start;
3220
3221 while (bytes)
3222 {
3223 int j;
3224 int k;
3225 int lbytes;
3226
3227 lbytes = (bytes > 16 ? 16 : bytes);
3228
3229 printf (" 0x%8.8x ", addr);
3230
3231 switch (elf_header.e_ident [EI_DATA])
3232 {
3233 case ELFDATA2LSB:
3234 for (j = 15; j >= 0; j --)
3235 {
3236 if (j < lbytes)
3237 printf ("%2.2x", data [j]);
3238 else
3239 printf (" ");
3240
3241 if (!(j & 0x3))
3242 printf (" ");
3243 }
3244 break;
3245
3246 case ELFDATA2MSB:
3247 for (j = 0; j < 16; j++)
3248 {
3249 if (j < lbytes)
3250 printf ("%2.2x", data [j]);
3251 else
3252 printf (" ");
3253
3254 if ((j & 3) == 3)
3255 printf (" ");
3256 }
3257 break;
3258 }
3259
3260 for (j = 0; j < lbytes; j++)
3261 {
3262 k = data [j];
3263 if (k >= ' ' && k < 0x80)
3264 printf ("%c", k);
3265 else
3266 printf (".");
3267 }
3268
3269 putchar ('\n');
3270
3271 data += lbytes;
3272 addr += lbytes;
3273 bytes -= lbytes;
3274 }
3275
3276 free (start);
3277 }
3278 }
3279
3280 return 1;
3281 }
3282
3283 static void
3284 process_mips_fpe_exception (mask)
3285 int mask;
3286 {
3287 if (mask)
3288 {
3289 int first = 1;
3290 if (mask & OEX_FPU_INEX)
3291 fputs ("INEX", stdout), first = 0;
3292 if (mask & OEX_FPU_UFLO)
3293 printf ("%sUFLO", first ? "" : "|"), first = 0;
3294 if (mask & OEX_FPU_OFLO)
3295 printf ("%sOFLO", first ? "" : "|"), first = 0;
3296 if (mask & OEX_FPU_DIV0)
3297 printf ("%sDIV0", first ? "" : "|"), first = 0;
3298 if (mask & OEX_FPU_INVAL)
3299 printf ("%sINVAL", first ? "" : "|");
3300 }
3301 else
3302 fputs ("0", stdout);
3303 }
3304
3305 static int
3306 process_mips_specific (file)
3307 FILE *file;
3308 {
3309 Elf_Internal_Dyn * entry;
3310 size_t liblist_offset = 0;
3311 size_t liblistno = 0;
3312 size_t options_offset = 0;
3313
3314 /* We have a lot of special sections. Thanks SGI! */
3315 if (dynamic_segment == NULL)
3316 /* No information available. */
3317 return 0;
3318
3319 for (entry = dynamic_segment; entry->d_tag != DT_NULL; ++entry)
3320 switch (entry->d_tag)
3321 {
3322 case DT_MIPS_LIBLIST:
3323 liblist_offset = entry->d_un.d_val - loadaddr;
3324 break;
3325 case DT_MIPS_LIBLISTNO:
3326 liblistno = entry->d_un.d_val;
3327 break;
3328 case DT_MIPS_OPTIONS:
3329 options_offset = entry->d_un.d_val - loadaddr;
3330 break;
3331 default:
3332 break;
3333 }
3334
3335 if (liblist_offset != 0 && liblistno != 0 && do_dynamic)
3336 {
3337 Elf32_External_Lib *elib;
3338 size_t cnt;
3339
3340 GET_DATA_ALLOC (liblist_offset, liblistno * sizeof (Elf32_External_Lib),
3341 elib, Elf32_External_Lib *, "liblist");
3342
3343 printf ("\nSection '.liblist' contains %d entries:\n", liblistno);
3344 fputs (" Library Time Stamp Checksum Version Flags\n",
3345 stdout);
3346
3347 for (cnt = 0; cnt < liblistno; ++cnt)
3348 {
3349 Elf32_Lib liblist;
3350 time_t time;
3351 char timebuf[20];
3352
3353 liblist.l_name = BYTE_GET (elib[cnt].l_name);
3354 time = BYTE_GET (elib[cnt].l_time_stamp);
3355 liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum);
3356 liblist.l_version = BYTE_GET (elib[cnt].l_version);
3357 liblist.l_flags = BYTE_GET (elib[cnt].l_flags);
3358
3359 strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time));
3360
3361 printf ("%3d: %-20s %s %#10lx %-7ld %#lx\n", cnt,
3362 dynamic_strings + liblist.l_name, timebuf,
3363 liblist.l_checksum, liblist.l_version, liblist.l_flags);
3364 }
3365
3366 free (elib);
3367 }
3368
3369 if (options_offset != 0)
3370 {
3371 Elf_External_Options *eopt;
3372 Elf_Internal_Shdr *sect = section_headers;
3373 Elf_Internal_Options *iopt;
3374 Elf_Internal_Options *option;
3375 size_t offset;
3376 int cnt;
3377
3378 /* Find the section header so that we get the size. */
3379 while (sect->sh_type != SHT_MIPS_OPTIONS)
3380 ++sect;
3381
3382 GET_DATA_ALLOC (options_offset, sect->sh_size, eopt,
3383 Elf_External_Options *, "options");
3384
3385 iopt = (Elf_Internal_Options *) malloc ((sect->sh_size / sizeof (eopt))
3386 * sizeof (*iopt));
3387 if (iopt == NULL)
3388 {
3389 error (_("Out of memory"));
3390 return 0;
3391 }
3392
3393 offset = cnt = 0;
3394 option = iopt;
3395 while (offset < sect->sh_size)
3396 {
3397 Elf_External_Options *eoption;
3398
3399 eoption = (Elf_External_Options *) ((char *) eopt + offset);
3400
3401 option->kind = BYTE_GET (eoption->kind);
3402 option->size = BYTE_GET (eoption->size);
3403 option->section = BYTE_GET (eoption->section);
3404 option->info = BYTE_GET (eoption->info);
3405
3406 offset += option->size;
3407 ++option;
3408 ++cnt;
3409 }
3410
3411 printf (_("\nSection '%s' contains %d entries:\n"),
3412 string_table + sect->sh_name, cnt);
3413
3414 option = iopt;
3415 while (cnt-- > 0)
3416 {
3417 size_t len;
3418
3419 switch (option->kind)
3420 {
3421 case ODK_NULL:
3422 /* This shouldn't happen. */
3423 printf (" NULL %d %x", option->section, option->info);
3424 break;
3425 case ODK_REGINFO:
3426 printf (" REGINFO ");
3427 if (elf_header.e_machine == EM_MIPS)
3428 {
3429 /* 32bit form. */
3430 Elf32_External_RegInfo *ereg;
3431 Elf32_RegInfo reginfo;
3432
3433 ereg = (Elf32_External_RegInfo *) (option + 1);
3434 reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
3435 reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
3436 reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
3437 reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
3438 reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
3439 reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
3440
3441 printf ("GPR %08lx GP %ld\n",
3442 reginfo.ri_gprmask, reginfo.ri_gp_value);
3443 printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n",
3444 reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
3445 reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
3446 }
3447 else
3448 {
3449 /* 64 bit form. */
3450 Elf64_External_RegInfo *ereg;
3451 Elf64_Internal_RegInfo reginfo;
3452
3453 ereg = (Elf64_External_RegInfo *) (option + 1);
3454 reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
3455 reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
3456 reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
3457 reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
3458 reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
3459 reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
3460
3461 printf ("GPR %08lx GP %ld\n",
3462 reginfo.ri_gprmask, reginfo.ri_gp_value);
3463 printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n",
3464 reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
3465 reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
3466 }
3467 ++option;
3468 continue;
3469 case ODK_EXCEPTIONS:
3470 fputs (" EXCEPTIONS fpe_min(", stdout);
3471 process_mips_fpe_exception (option->info & OEX_FPU_MIN);
3472 fputs (") fpe_max(", stdout);
3473 process_mips_fpe_exception ((option->info & OEX_FPU_MAX) >> 8);
3474 fputs (")", stdout);
3475
3476 if (option->info & OEX_PAGE0)
3477 fputs (" PAGE0", stdout);
3478 if (option->info & OEX_SMM)
3479 fputs (" SMM", stdout);
3480 if (option->info & OEX_FPDBUG)
3481 fputs (" FPDBUG", stdout);
3482 if (option->info & OEX_DISMISS)
3483 fputs (" DISMISS", stdout);
3484 break;
3485 case ODK_PAD:
3486 fputs (" PAD ", stdout);
3487 if (option->info & OPAD_PREFIX)
3488 fputs (" PREFIX", stdout);
3489 if (option->info & OPAD_POSTFIX)
3490 fputs (" POSTFIX", stdout);
3491 if (option->info & OPAD_SYMBOL)
3492 fputs (" SYMBOL", stdout);
3493 break;
3494 case ODK_HWPATCH:
3495 fputs (" HWPATCH ", stdout);
3496 if (option->info & OHW_R4KEOP)
3497 fputs (" R4KEOP", stdout);
3498 if (option->info & OHW_R8KPFETCH)
3499 fputs (" R8KPFETCH", stdout);
3500 if (option->info & OHW_R5KEOP)
3501 fputs (" R5KEOP", stdout);
3502 if (option->info & OHW_R5KCVTL)
3503 fputs (" R5KCVTL", stdout);
3504 break;
3505 case ODK_FILL:
3506 fputs (" FILL ", stdout);
3507 /* XXX Print content of info word? */
3508 break;
3509 case ODK_TAGS:
3510 fputs (" TAGS ", stdout);
3511 /* XXX Print content of info word? */
3512 break;
3513 case ODK_HWAND:
3514 fputs (" HWAND ", stdout);
3515 if (option->info & OHWA0_R4KEOP_CHECKED)
3516 fputs (" R4KEOP_CHECKED", stdout);
3517 if (option->info & OHWA0_R4KEOP_CLEAN)
3518 fputs (" R4KEOP_CLEAN", stdout);
3519 break;
3520 case ODK_HWOR:
3521 fputs (" HWOR ", stdout);
3522 if (option->info & OHWA0_R4KEOP_CHECKED)
3523 fputs (" R4KEOP_CHECKED", stdout);
3524 if (option->info & OHWA0_R4KEOP_CLEAN)
3525 fputs (" R4KEOP_CLEAN", stdout);
3526 break;
3527 case ODK_GP_GROUP:
3528 printf (" GP_GROUP %#06x self-contained %#06x",
3529 option->info & OGP_GROUP,
3530 (option->info & OGP_SELF) >> 16);
3531 break;
3532 case ODK_IDENT:
3533 printf (" IDENT %#06x self-contained %#06x",
3534 option->info & OGP_GROUP,
3535 (option->info & OGP_SELF) >> 16);
3536 break;
3537 default:
3538 /* This shouldn't happen. */
3539 printf (" %3d ??? %d %x",
3540 option->kind, option->section, option->info);
3541 break;
3542 }
3543
3544 len = sizeof (*eopt);
3545 while (len < option->size)
3546 if (((char *) option)[len] >= ' '
3547 && ((char *) option)[len] < 0x7f)
3548 printf ("%c", ((char *) option)[len++]);
3549 else
3550 printf ("\\%03o", ((char *) option)[len++]);
3551
3552 fputs ("\n", stdout);
3553 ++option;
3554 }
3555
3556 free (eopt);
3557 }
3558
3559 return 1;
3560 }
3561
3562 static int
3563 process_arch_specific (file)
3564 FILE *file;
3565 {
3566 switch (elf_header.e_machine)
3567 {
3568 case EM_MIPS:
3569 case EM_MIPS_RS4_BE:
3570 return process_mips_specific (file);
3571 break;
3572 default:
3573 break;
3574 }
3575 return 1;
3576 }
3577
3578 static int
3579 get_file_header (file)
3580 FILE * file;
3581 {
3582 Elf32_External_Ehdr ehdr;
3583
3584 if (fread (& ehdr, sizeof (ehdr), 1, file) != 1)
3585 return 0;
3586
3587 memcpy (elf_header.e_ident, ehdr.e_ident, EI_NIDENT);
3588
3589 if (elf_header.e_ident [EI_DATA] == ELFDATA2LSB)
3590 byte_get = byte_get_little_endian;
3591 else
3592 byte_get = byte_get_big_endian;
3593
3594 elf_header.e_entry = BYTE_GET (ehdr.e_entry);
3595 elf_header.e_phoff = BYTE_GET (ehdr.e_phoff);
3596 elf_header.e_shoff = BYTE_GET (ehdr.e_shoff);
3597 elf_header.e_version = BYTE_GET (ehdr.e_version);
3598 elf_header.e_flags = BYTE_GET (ehdr.e_flags);
3599 elf_header.e_type = BYTE_GET (ehdr.e_type);
3600 elf_header.e_machine = BYTE_GET (ehdr.e_machine);
3601 elf_header.e_ehsize = BYTE_GET (ehdr.e_ehsize);
3602 elf_header.e_phentsize = BYTE_GET (ehdr.e_phentsize);
3603 elf_header.e_phnum = BYTE_GET (ehdr.e_phnum);
3604 elf_header.e_shentsize = BYTE_GET (ehdr.e_shentsize);
3605 elf_header.e_shnum = BYTE_GET (ehdr.e_shnum);
3606 elf_header.e_shstrndx = BYTE_GET (ehdr.e_shstrndx);
3607
3608 return 1;
3609 }
3610
3611 static void
3612 process_file (file_name)
3613 char * file_name;
3614 {
3615 FILE * file;
3616 struct stat statbuf;
3617 unsigned int i;
3618
3619 if (stat (file_name, & statbuf) < 0)
3620 {
3621 error (_("Cannot stat input file %s.\n"), file_name);
3622 return;
3623 }
3624
3625 file = fopen (file_name, "rb");
3626 if (file == NULL)
3627 {
3628 error (_("Input file %s not found.\n"), file_name);
3629 return;
3630 }
3631
3632 if (! get_file_header (file))
3633 {
3634 error (_("%s: Failed to read file header\n"), file_name);
3635 fclose (file);
3636 return;
3637 }
3638
3639 /* Initialise per file variables. */
3640 for (i = NUM_ELEM (version_info); i--;)
3641 version_info[i] = 0;
3642
3643 for (i = NUM_ELEM (dynamic_info); i--;)
3644 dynamic_info[i] = 0;
3645
3646 /* Process the file. */
3647 if (show_name)
3648 printf (_("\nFile: %s\n"), file_name);
3649
3650 if (! process_file_header ())
3651 {
3652 fclose (file);
3653 return;
3654 }
3655
3656 process_section_headers (file);
3657
3658 process_program_headers (file);
3659
3660 process_dynamic_segment (file);
3661
3662 process_relocs (file);
3663
3664 process_symbol_table (file);
3665
3666 process_syminfo (file);
3667
3668 process_version_sections (file);
3669
3670 process_section_contents (file);
3671
3672 process_arch_specific (file);
3673
3674 fclose (file);
3675
3676 if (section_headers)
3677 {
3678 free (section_headers);
3679 section_headers = NULL;
3680 }
3681
3682 if (string_table)
3683 {
3684 free (string_table);
3685 string_table = NULL;
3686 }
3687
3688 if (dynamic_strings)
3689 {
3690 free (dynamic_strings);
3691 dynamic_strings = NULL;
3692 }
3693
3694 if (dynamic_symbols)
3695 {
3696 free (dynamic_symbols);
3697 dynamic_symbols = NULL;
3698 }
3699
3700 if (dynamic_syminfo)
3701 {
3702 free (dynamic_syminfo);
3703 dynamic_syminfo = NULL;
3704 }
3705 }
3706
3707 #ifdef SUPPORT_DISASSEMBLY
3708 /* Needed by the i386 disassembler. For extra credit, someone could
3709 fix this so that we insert symbolic addresses here, esp for GOT/PLT
3710 symbols */
3711
3712 void
3713 print_address (unsigned int addr, FILE * outfile)
3714 {
3715 fprintf (outfile,"0x%8.8x", addr);
3716 }
3717
3718 /* Needed by the i386 disassembler. */
3719 void
3720 db_task_printsym (unsigned int addr)
3721 {
3722 print_address (addr, stderr);
3723 }
3724 #endif
3725
3726 int
3727 main (argc, argv)
3728 int argc;
3729 char ** argv;
3730 {
3731 parse_args (argc, argv);
3732
3733 if (optind < (argc - 1))
3734 show_name = 1;
3735
3736 while (optind < argc)
3737 process_file (argv [optind ++]);
3738
3739 return 0;
3740 }
This page took 0.121927 seconds and 5 git commands to generate.