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