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