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