19990502 sourceware import
[external/binutils.git] / binutils / readelf.c
1 /* readelf.c -- display contents of an ELF format file
2    Copyright (C) 1998, 1999 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 #include "elf/dwarf2.h"
36
37 /* The following headers use the elf/reloc-macros.h file to
38    automatically generate relocation recognition functions
39    such as elf_mips_reloc_type()  */
40
41 #define RELOC_MACROS_GEN_FUNC
42
43 #include "elf/i386.h"
44 #include "elf/v850.h"
45 #include "elf/ppc.h"
46 #include "elf/mips.h"
47 #include "elf/alpha.h"
48 #include "elf/arm.h"
49 #include "elf/m68k.h"
50 #include "elf/sparc.h"
51 #include "elf/m32r.h"
52 #include "elf/d10v.h"
53 #include "elf/d30v.h"
54 #include "elf/sh.h"
55 #include "elf/mn10200.h"
56 #include "elf/mn10300.h"
57 #include "elf/hppa.h"
58 #include "elf/arc.h"
59 #include "elf/fr30.h"
60 #include "elf/mcore.h"
61
62 #include "bucomm.h"
63 #include "getopt.h"
64
65 #ifdef ANSI_PROTOTYPES
66 #include <stdarg.h>
67 #else
68 #include <varargs.h>
69 #endif
70
71 char *                  program_name = "readelf";
72 unsigned int            dynamic_addr;
73 unsigned int            dynamic_size;
74 unsigned int            rela_addr;
75 unsigned int            rela_size;
76 char *                  dynamic_strings;
77 char *                  string_table;
78 Elf_Internal_Sym *      dynamic_symbols;
79 Elf_Internal_Syminfo *  dynamic_syminfo;
80 unsigned long           dynamic_syminfo_offset;
81 unsigned int            dynamic_syminfo_nent;
82 char                    program_interpreter [64];
83 int                     dynamic_info[DT_JMPREL + 1];
84 int                     version_info[16];
85 int                     loadaddr = 0;
86 Elf_Internal_Ehdr       elf_header;
87 Elf_Internal_Shdr *     section_headers;
88 Elf_Internal_Dyn *      dynamic_segment;
89 int                     show_name;
90 int                     do_dynamic;
91 int                     do_syms;
92 int                     do_reloc;
93 int                     do_sections;
94 int                     do_segments;
95 int                     do_using_dynamic;
96 int                     do_header;
97 int                     do_dump;
98 int                     do_version;
99 int                     do_histogram;
100 int                     do_debugging;
101 int                     do_debug_info;
102 int                     do_debug_abbrevs;
103 int                     do_debug_lines;
104 int                     do_debug_pubnames;
105 int                     do_debug_aranges;
106 int                     binary_class;
107
108 /* A dynamic array of flags indicating which sections require dumping.  */
109 char *                  dump_sects = NULL;
110 unsigned int            num_dump_sects = 0;
111
112 #define HEX_DUMP        (1 << 0)
113 #define DISASS_DUMP     (1 << 1)
114 #define DEBUG_DUMP      (1 << 2)
115
116 /* Forward declarations for dumb compilers.  */
117 static unsigned long (*   byte_get)                   PARAMS ((unsigned char *, int));
118 static const char *       get_mips_dynamic_type       PARAMS ((unsigned long type));
119 static const char *       get_dynamic_type            PARAMS ((unsigned long type));
120 static int                dump_relocations            PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, char *));
121 static char *             get_file_type               PARAMS ((unsigned e_type));
122 static char *             get_machine_name            PARAMS ((unsigned e_machine));
123 static char *             get_machine_data            PARAMS ((unsigned e_data));
124 static char *             get_machine_flags           PARAMS ((unsigned, unsigned e_machine));
125 static const char *       get_mips_segment_type       PARAMS ((unsigned long type));
126 static const char *       get_segment_type            PARAMS ((unsigned long p_type));
127 static const char *       get_mips_section_type_name  PARAMS ((unsigned int sh_type));
128 static const char *       get_section_type_name       PARAMS ((unsigned int sh_type));
129 static char *             get_symbol_binding          PARAMS ((unsigned int binding));
130 static char *             get_symbol_type             PARAMS ((unsigned int type));
131 static void               usage                       PARAMS ((void));
132 static void               parse_args                  PARAMS ((int argc, char ** argv));
133 static int                process_file_header         PARAMS ((void));
134 static int                process_program_headers     PARAMS ((FILE *));
135 static int                process_section_headers     PARAMS ((FILE *));
136 static void               dynamic_segment_mips_val    PARAMS ((Elf_Internal_Dyn *entry));
137 static int                process_dynamic_segment     PARAMS ((FILE *));
138 static int                process_symbol_table        PARAMS ((FILE *));
139 static int                process_section_contents    PARAMS ((FILE *));
140 static void               process_file                PARAMS ((char * file_name));
141 static int                process_relocs              PARAMS ((FILE *));
142 static int                process_version_sections    PARAMS ((FILE *));
143 static char *             get_ver_flags               PARAMS ((unsigned int flags));
144 static char *             get_symbol_index_type       PARAMS ((unsigned int type));
145 static int                get_section_headers         PARAMS ((FILE * file));
146 static int                get_file_header             PARAMS ((FILE * file));
147 static Elf_Internal_Sym * get_elf_symbols             PARAMS ((FILE * file, unsigned long offset, unsigned long number));
148 static int *              get_dynamic_data            PARAMS ((FILE * file, unsigned int number));
149 #ifdef SUPPORT_DISASSEMBLY
150 static int                disassemble_section         PARAMS ((Elf32_Internal_Shdr *, FILE *));
151 #endif
152 static int                dump_section                PARAMS ((Elf32_Internal_Shdr *, FILE *));
153 static int                display_debug_section       PARAMS ((Elf32_Internal_Shdr *, FILE *));
154 static int                display_debug_info          PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
155 static int                display_debug_not_supported PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
156 static int                display_debug_lines         PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
157 static int                display_debug_abbrev        PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
158 static int                display_debug_aranges       PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
159 static unsigned char *    process_abbrev_section      PARAMS ((unsigned char *, unsigned char *));
160 static unsigned long      read_leb128                 PARAMS ((unsigned char *, int *, int));
161 static int                process_extended_line_op    PARAMS ((unsigned char *, int));
162 static void               reset_state_machine         PARAMS ((int));
163 static char *             get_TAG_name                PARAMS ((unsigned long));
164 static char *             get_AT_name                 PARAMS ((unsigned long));
165 static char *             get_FORM_name               PARAMS ((unsigned long));
166 static void               free_abbrevs                PARAMS ((void));
167 static void               add_abbrev                  PARAMS ((unsigned long, unsigned long, int));
168 static void               add_abbrev_attr             PARAMS ((unsigned long, unsigned long));
169 static unsigned char *    read_and_display_attr       PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long));
170 static unsigned char *    display_block               PARAMS ((unsigned char *, unsigned long));
171 static void               decode_location_expression  PARAMS ((unsigned char *, unsigned int));
172 static void               request_dump                PARAMS ((unsigned int, char));
173 static const char *       get_elf_class               PARAMS ((unsigned char));
174 static const char *       get_data_encoding           PARAMS ((unsigned char));
175 static const char *       get_osabi_name              PARAMS ((unsigned char));
176
177 typedef int Elf32_Word;
178
179 #define SECTION_NAME(X)         (string_table + (X)->sh_name)
180
181 #define DT_VERSIONTAGIDX(tag)   (DT_VERNEEDNUM - (tag)) /* Reverse order! */
182
183 #define BYTE_GET(field)         byte_get (field, sizeof (field))
184
185 #define NUM_ELEM(array)         (sizeof (array) / sizeof ((array)[0]))
186
187 #define GET_DATA_ALLOC(offset, size, var, type, reason)                 \
188   if (fseek (file, offset, SEEK_SET))                                   \
189     {                                                                   \
190       error (_("Unable to seek to start of %s at %x\n"), reason, offset); \
191       return 0;                                                         \
192     }                                                                   \
193                                                                         \
194   var = (type) malloc (size);                                           \
195                                                                         \
196   if (var == NULL)                                                      \
197     {                                                                   \
198       error (_("Out of memory allocating %d bytes for %s\n"), size, reason); \
199       return 0;                                                         \
200     }                                                                   \
201                                                                         \
202   if (fread (var, size, 1, file) != 1)                                  \
203     {                                                                   \
204       error (_("Unable to read in %d bytes of %s\n"), size, reason);    \
205       free (var);                                                       \
206       var = NULL;                                                       \
207       return 0;                                                         \
208     }
209
210
211 #define GET_DATA(offset, var, reason)                                   \
212   if (fseek (file, offset, SEEK_SET))                                   \
213     {                                                                   \
214       error (_("Unable to seek to %x for %s\n"), offset, reason);       \
215       return 0;                                                         \
216     }                                                                   \
217   else if (fread (& var, sizeof (var), 1, file) != 1)                   \
218     {                                                                   \
219       error (_("Unable to read data at %x for %s\n"), offset, reason);  \
220       return 0;                                                         \
221     }
222
223 #ifdef ANSI_PROTOTYPES
224 static void
225 error (const char * message, ...)
226 {
227   va_list args;
228
229   fprintf (stderr, _("%s: Error: "), program_name);
230   va_start (args, message);
231   vfprintf (stderr, message, args);
232   va_end (args);
233   return;
234 }
235
236 static void
237 warn (const char * message, ...)
238 {
239   va_list args;
240
241   fprintf (stderr, _("%s: Warning: "), program_name);
242   va_start (args, message);
243   vfprintf (stderr, message, args);
244   va_end (args);
245   return;
246 }
247 #else
248 static void
249 error (va_alist)
250      va_dcl
251 {
252   char * message;
253   va_list args;
254
255   fprintf (stderr, _("%s: Error: "), program_name);
256   va_start (args);
257   message = va_arg (args, char *);
258   vfprintf (stderr, message, args);
259   va_end (args);
260   return;
261 }
262
263 static void
264 warn (va_alist)
265      va_dcl
266 {
267   char * message;
268   va_list args;
269
270   fprintf (stderr, _("%s: Warning: "), program_name);
271   va_start (args);
272   message = va_arg (args, char *);
273   vfprintf (stderr, message, args);
274   va_end (args);
275   return;
276 }
277 #endif
278
279 static unsigned long int
280 byte_get_little_endian (field, size)
281      unsigned char * field;
282      int             size;
283 {
284   switch (size)
285     {
286     case 1:
287       return * field;
288
289     case 2:
290       return  ((unsigned int) (field [0]))
291         |    (((unsigned int) (field [1])) << 8);
292
293     case 4:
294       return  ((unsigned long) (field [0]))
295         |    (((unsigned long) (field [1])) << 8)
296         |    (((unsigned long) (field [2])) << 16)
297         |    (((unsigned long) (field [3])) << 24);
298
299     default:
300       error (_("Unhandled data length: %d\n"), size);
301       abort();
302     }
303 }
304
305 static unsigned long int
306 byte_get_big_endian (field, size)
307      unsigned char * field;
308      int             size;
309 {
310   switch (size)
311     {
312     case 1:
313       return * field;
314
315     case 2:
316       return ((unsigned int) (field [1])) | (((int) (field [0])) << 8);
317
318     case 4:
319       return ((unsigned long) (field [3]))
320         |   (((unsigned long) (field [2])) << 8)
321         |   (((unsigned long) (field [1])) << 16)
322         |   (((unsigned long) (field [0])) << 24);
323
324     default:
325       error (_("Unhandled data length: %d\n"), size);
326       abort();
327     }
328 }
329
330
331 /* Display the contents of the relocation data
332    found at the specified offset.  */
333 static int
334 dump_relocations (file, rel_offset, rel_size, symtab, strtab)
335      FILE *                 file;
336      unsigned long          rel_offset;
337      unsigned long          rel_size;
338      Elf_Internal_Sym *     symtab;
339      char *                 strtab;
340 {
341   unsigned int        i;
342   int                 is_rela;
343   Elf_Internal_Rel *  rels;
344   Elf_Internal_Rela * relas;
345
346
347   /* Compute number of relocations and read them in.  */
348   switch (elf_header.e_machine)
349     {
350       /* Targets that use REL relocations.  */
351     case EM_ARM:
352     case EM_386:
353     case EM_486:
354     case EM_CYGNUS_M32R:
355     case EM_CYGNUS_D10V:
356     case EM_MIPS:
357     case EM_MIPS_RS4_BE:
358       {
359         Elf32_External_Rel * erels;
360
361         GET_DATA_ALLOC (rel_offset, rel_size, erels,
362                         Elf32_External_Rel *, "relocs");
363
364         rel_size = rel_size / sizeof (Elf32_External_Rel);
365
366         rels = (Elf_Internal_Rel *) malloc (rel_size *
367                                             sizeof (Elf_Internal_Rel));
368
369         for (i = 0; i < rel_size; i++)
370           {
371             rels[i].r_offset = BYTE_GET (erels[i].r_offset);
372             rels[i].r_info   = BYTE_GET (erels[i].r_info);
373           }
374
375         free (erels);
376
377         is_rela = 0;
378         relas   = (Elf_Internal_Rela *) rels;
379       }
380     break;
381
382       /* Targets that use RELA relocations.  */
383     case EM_68K:
384     case EM_SPARC:
385     case EM_PPC:
386     case EM_CYGNUS_V850:
387     case EM_CYGNUS_D30V:
388     case EM_CYGNUS_MN10200:
389     case EM_CYGNUS_MN10300:
390     case EM_CYGNUS_FR30:
391     case EM_SH:
392     case EM_ALPHA:
393     case EM_MCORE:
394       {
395         Elf32_External_Rela * erelas;
396
397         GET_DATA_ALLOC (rel_offset, rel_size, erelas,
398                         Elf32_External_Rela *, "relocs");
399
400         rel_size = rel_size / sizeof (Elf32_External_Rela);
401
402         relas = (Elf_Internal_Rela *) malloc (rel_size *
403                                               sizeof (Elf_Internal_Rela));
404
405         for (i = 0; i < rel_size; i++)
406           {
407             relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
408             relas[i].r_info   = BYTE_GET (erelas[i].r_info);
409             relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
410           }
411
412         free (erelas);
413
414         is_rela = 1;
415         rels    = (Elf_Internal_Rel *) relas;
416       }
417     break;
418
419     default:
420       warn (_("Don't know about relocations on this machine architecture\n"));
421       return 0;
422     }
423
424   if (is_rela)
425     printf
426       (_("  Offset    Info  Type            Symbol's Value  Symbol's Name          Addend\n"));
427   else
428     printf
429       (_("  Offset    Info  Type            Symbol's Value  Symbol's Name\n"));
430
431   for (i = 0; i < rel_size; i++)
432     {
433       const char *  rtype;
434       unsigned long offset;
435       unsigned long info;
436       int           symtab_index;
437
438       if (is_rela)
439         {
440           offset = relas [i].r_offset;
441           info   = relas [i].r_info;
442         }
443       else
444         {
445           offset = rels [i].r_offset;
446           info   = rels [i].r_info;
447         }
448
449       printf ("  %8.8lx  %5.5lx ", offset, info);
450
451       switch (elf_header.e_machine)
452         {
453         default:
454           rtype = NULL;
455           break;
456
457         case EM_CYGNUS_M32R:
458           rtype = elf_m32r_reloc_type (ELF32_R_TYPE (info));
459           break;
460
461         case EM_386:
462         case EM_486:
463           rtype = elf_i386_reloc_type (ELF32_R_TYPE (info));
464           break;
465
466         case EM_68K:
467           rtype = elf_m68k_reloc_type (ELF32_R_TYPE (info));
468           break;
469
470         case EM_SPARC:
471           rtype = elf_sparc_reloc_type (ELF32_R_TYPE (info));
472           break;
473
474         case EM_CYGNUS_V850:
475           rtype = v850_reloc_type (ELF32_R_TYPE (info));
476           break;
477
478         case EM_CYGNUS_D10V:
479           rtype = elf_d10v_reloc_type (ELF32_R_TYPE (info));
480           break;
481
482         case EM_CYGNUS_D30V:
483           rtype = elf_d30v_reloc_type (ELF32_R_TYPE (info));
484           break;
485
486         case EM_SH:
487           rtype = elf_sh_reloc_type (ELF32_R_TYPE (info));
488           break;
489
490         case EM_CYGNUS_MN10300:
491           rtype = elf_mn10300_reloc_type (ELF32_R_TYPE (info));
492           break;
493
494         case EM_CYGNUS_MN10200:
495           rtype = elf_mn10200_reloc_type (ELF32_R_TYPE (info));
496           break;
497
498         case EM_CYGNUS_FR30:
499           rtype = elf_fr30_reloc_type (ELF32_R_TYPE (info));
500           break;
501
502         case EM_MCORE:
503           rtype = elf_mcore_reloc_type (ELF32_R_TYPE (info));
504           break;
505
506         case EM_PPC:
507           rtype = elf_ppc_reloc_type (ELF32_R_TYPE (info));
508           break;
509
510         case EM_MIPS:
511         case EM_MIPS_RS4_BE:
512           rtype = elf_mips_reloc_type (ELF32_R_TYPE (info));
513           break;
514
515         case EM_ALPHA:
516           rtype = elf_alpha_reloc_type (ELF32_R_TYPE (info));
517           break;
518
519         case EM_ARM:
520           rtype = elf_arm_reloc_type (ELF32_R_TYPE (info));
521           break;
522
523         case EM_CYGNUS_ARC:
524           rtype = elf_arc_reloc_type (ELF32_R_TYPE (info));
525           break;
526
527         case EM_PARISC:
528           rtype = elf32_hppa_reloc_type (ELF32_R_TYPE (info));
529           break;
530         }
531
532       if (rtype == NULL)
533         printf (_("unrecognised: %-7lx"), ELF32_R_TYPE (info));
534       else
535         printf ("%-21.21s", rtype);
536
537       symtab_index = ELF32_R_SYM (info);
538
539       if (symtab_index && symtab != NULL)
540         {
541           Elf_Internal_Sym * psym;
542
543           psym = symtab + symtab_index;
544
545           printf (" %08lx  ", (unsigned long) psym->st_value);
546
547           if (psym->st_name == 0)
548             printf ("%-25.25s",
549                     SECTION_NAME (section_headers + psym->st_shndx));
550           else if (strtab == NULL)
551             printf (_("<string table index %3ld>"), psym->st_name);
552           else
553             printf ("%-25.25s", strtab + psym->st_name);
554
555           if (is_rela)
556             printf (" + %lx", (unsigned long) relas [i].r_addend);
557         }
558
559       putchar ('\n');
560     }
561
562   free (relas);
563
564   return 1;
565 }
566
567 static const char *
568 get_mips_dynamic_type (type)
569      unsigned long type;
570 {
571   switch (type)
572     {
573     case DT_MIPS_RLD_VERSION: return "MIPS_RLD_VERSION";
574     case DT_MIPS_TIME_STAMP: return "MIPS_TIME_STAMP";
575     case DT_MIPS_ICHECKSUM: return "MIPS_ICHECKSUM";
576     case DT_MIPS_IVERSION: return "MIPS_IVERSION";
577     case DT_MIPS_FLAGS: return "MIPS_FLAGS";
578     case DT_MIPS_BASE_ADDRESS: return "MIPS_BASE_ADDRESS";
579     case DT_MIPS_MSYM: return "MIPS_MSYM";
580     case DT_MIPS_CONFLICT: return "MIPS_CONFLICT";
581     case DT_MIPS_LIBLIST: return "MIPS_LIBLIST";
582     case DT_MIPS_LOCAL_GOTNO: return "MIPS_LOCAL_GOTNO";
583     case DT_MIPS_CONFLICTNO: return "MIPS_CONFLICTNO";
584     case DT_MIPS_LIBLISTNO: return "MIPS_LIBLISTNO";
585     case DT_MIPS_SYMTABNO: return "MIPS_SYMTABNO";
586     case DT_MIPS_UNREFEXTNO: return "MIPS_UNREFEXTNO";
587     case DT_MIPS_GOTSYM: return "MIPS_GOTSYM";
588     case DT_MIPS_HIPAGENO: return "MIPS_HIPAGENO";
589     case DT_MIPS_RLD_MAP: return "MIPS_RLD_MAP";
590     case DT_MIPS_DELTA_CLASS: return "MIPS_DELTA_CLASS";
591     case DT_MIPS_DELTA_CLASS_NO: return "MIPS_DELTA_CLASS_NO";
592     case DT_MIPS_DELTA_INSTANCE: return "MIPS_DELTA_INSTANCE";
593     case DT_MIPS_DELTA_INSTANCE_NO: return "MIPS_DELTA_INSTANCE_NO";
594     case DT_MIPS_DELTA_RELOC: return "MIPS_DELTA_RELOC";
595     case DT_MIPS_DELTA_RELOC_NO: return "MIPS_DELTA_RELOC_NO";
596     case DT_MIPS_DELTA_SYM: return "MIPS_DELTA_SYM";
597     case DT_MIPS_DELTA_SYM_NO: return "MIPS_DELTA_SYM_NO";
598     case DT_MIPS_DELTA_CLASSSYM: return "MIPS_DELTA_CLASSSYM";
599     case DT_MIPS_DELTA_CLASSSYM_NO: return "MIPS_DELTA_CLASSSYM_NO";
600     case DT_MIPS_CXX_FLAGS: return "MIPS_CXX_FLAGS";
601     case DT_MIPS_PIXIE_INIT: return "MIPS_PIXIE_INIT";
602     case DT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB";
603     case DT_MIPS_LOCALPAGE_GOTIDX: return "MIPS_LOCALPAGE_GOTIDX";
604     case DT_MIPS_LOCAL_GOTIDX: return "MIPS_LOCAL_GOTIDX";
605     case DT_MIPS_HIDDEN_GOTIDX: return "MIPS_HIDDEN_GOTIDX";
606     case DT_MIPS_PROTECTED_GOTIDX: return "MIPS_PROTECTED_GOTIDX";
607     case DT_MIPS_OPTIONS: return "MIPS_OPTIONS";
608     case DT_MIPS_INTERFACE: return "MIPS_INTERFACE";
609     case DT_MIPS_DYNSTR_ALIGN: return "MIPS_DYNSTR_ALIGN";
610     case DT_MIPS_INTERFACE_SIZE: return "MIPS_INTERFACE_SIZE";
611     case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: return "MIPS_RLD_TEXT_RESOLVE_ADDR";
612     case DT_MIPS_PERF_SUFFIX: return "MIPS_PERF_SUFFIX";
613     case DT_MIPS_COMPACT_SIZE: return "MIPS_COMPACT_SIZE";
614     case DT_MIPS_GP_VALUE: return "MIPS_GP_VALUE";
615     case DT_MIPS_AUX_DYNAMIC: return "MIPS_AUX_DYNAMIC";
616     default:
617       return NULL;
618     }
619 }
620
621 static const char *
622 get_dynamic_type (type)
623      unsigned long type;
624 {
625   static char buff [32];
626
627   switch (type)
628     {
629     case DT_NULL:       return "NULL";
630     case DT_NEEDED:     return "NEEDED";
631     case DT_PLTRELSZ:   return "PLTRELSZ";
632     case DT_PLTGOT:     return "PLTGOT";
633     case DT_HASH:       return "HASH";
634     case DT_STRTAB:     return "STRTAB";
635     case DT_SYMTAB:     return "SYMTAB";
636     case DT_RELA:       return "RELA";
637     case DT_RELASZ:     return "RELASZ";
638     case DT_RELAENT:    return "RELAENT";
639     case DT_STRSZ:      return "STRSZ";
640     case DT_SYMENT:     return "SYMENT";
641     case DT_INIT:       return "INIT";
642     case DT_FINI:       return "FINI";
643     case DT_SONAME:     return "SONAME";
644     case DT_RPATH:      return "RPATH";
645     case DT_SYMBOLIC:   return "SYMBOLIC";
646     case DT_REL:        return "REL";
647     case DT_RELSZ:      return "RELSZ";
648     case DT_RELENT:     return "RELENT";
649     case DT_PLTREL:     return "PLTREL";
650     case DT_DEBUG:      return "DEBUG";
651     case DT_TEXTREL:    return "TEXTREL";
652     case DT_JMPREL:     return "JMPREL";
653     case DT_BIND_NOW:   return "BIND_NOW";
654     case DT_INIT_ARRAY: return "INIT_ARRAY";
655     case DT_FINI_ARRAY: return "FINI_ARRAY";
656     case DT_INIT_ARRAYSZ: return "INIT_ARRAYSZ";
657     case DT_FINI_ARRAYSZ: return "FINI_ARRAYSZ";
658       
659     case DT_PLTPADSZ:   return "PLTPADSZ";
660     case DT_MOVEENT:    return "MOVEENT";
661     case DT_MOVESZ:     return "MOVESZ";
662     case DT_FEATURE_1:  return "FEATURE_1";
663     case DT_POSFLAG_1:  return "POSFLAG_1";
664     case DT_SYMINSZ:    return "SYMINSZ";
665     case DT_SYMINENT:   return "SYMINENT"; /* aka VALRNGHI */
666       
667     case DT_ADDRRNGLO:  return "ADDRRNGLO";
668     case DT_SYMINFO:    return "SYMINFO"; /* aka ADDRRNGHI */
669       
670     case DT_VERSYM:     return "VERSYM";
671       
672     case DT_RELACOUNT:  return "RELACOUNT";
673     case DT_RELCOUNT:   return "RELCOUNT";
674     case DT_FLAGS_1:    return "FLAGS_1";
675     case DT_VERDEF:     return "VERDEF";
676     case DT_VERDEFNUM:  return "VERDEFNUM";
677     case DT_VERNEED:    return "VERNEED";
678     case DT_VERNEEDNUM: return "VERNEEDNUM";
679       
680     case DT_AUXILIARY:  return "AUXILARY";
681     case DT_USED:       return "USED";
682     case DT_FILTER:     return "FILTER";
683       
684     default:
685       if ((type >= DT_LOPROC) && (type <= DT_HIPROC))
686         {
687           const char * result;
688           
689           switch (elf_header.e_machine)
690             {
691             case EM_MIPS:
692             case EM_MIPS_RS4_BE:
693               result = get_mips_dynamic_type (type);
694               break;
695             default:
696               result = NULL;
697               break;
698             }
699
700           if (result != NULL)
701             return result;
702
703           sprintf (buff, _("Processor Specific: %lx"), type);
704         }
705       else if ((type >= DT_LOOS) && (type <= DT_HIOS))
706         sprintf (buff, _("Operating System specific: %lx"), type);
707       else
708         sprintf (buff, _("<unknown>: %lx"), type);
709       
710       return buff;
711     }
712 }
713
714 static char *
715 get_file_type (e_type)
716      unsigned e_type;
717 {
718   static char buff [32];
719
720   switch (e_type)
721     {
722     case ET_NONE:       return _("NONE (None)");
723     case ET_REL:        return _("REL (Relocatable file)");
724     case ET_EXEC:       return _("EXEC (Executable file)");
725     case ET_DYN:        return _("DYN (Shared object file)");
726     case ET_CORE:       return _("CORE (Core file)");
727
728     default:
729       if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC))
730         sprintf (buff, _("Processor Specific: (%x)"), e_type);
731       else if ((e_type >= ET_LOOS) && (e_type <= ET_HIOS))
732         sprintf (buff, _("OS Specific: (%x)"), e_type);
733       else
734         sprintf (buff, _("<unknown>: %x"), e_type);
735       return buff;
736     }
737 }
738
739 static char *
740 get_machine_name (e_machine)
741      unsigned e_machine;
742 {
743   static char buff [32];
744
745   switch (e_machine)
746     {
747     case EM_NONE:               return _("None");
748     case EM_M32:                return "WE32100";
749     case EM_SPARC:              return "Sparc";
750     case EM_386:                return "Intel 80386";
751     case EM_68K:                return "MC68000";
752     case EM_88K:                return "MC88000";
753     case EM_486:                return "Intel 80486";
754     case EM_860:                return "Intel 80860";
755     case EM_MIPS:               return "MIPS R3000 big-endian";
756     case EM_S370:               return "Amdahl";
757     case EM_MIPS_RS4_BE:        return "MIPS R4000 big-endian";
758     case EM_OLD_SPARCV9:        return "Sparc v9 (old)";
759     case EM_PARISC:             return "HPPA";
760     case EM_PPC_OLD:            return "Power PC (old)";
761     case EM_SPARC32PLUS:        return "Sparc v8+" ;
762     case EM_960:                return "Intel 90860";
763     case EM_PPC:                return "PowerPC";
764     case EM_V800:               return "NEC V800";
765     case EM_FR20:               return "Fujitsu FR20";
766     case EM_RH32:               return "TRW RH32";
767     case EM_MCORE:              return "MCORE";
768     case EM_ARM:                return "ARM";
769     case EM_OLD_ALPHA:          return "Digital Alpha (old)";
770     case EM_SH:                 return "Hitachi SH";
771     case EM_SPARCV9:            return "Sparc v9";
772     case EM_TRICORE:            return "Siemens Tricore";
773     case EM_ARC:                return "Argonaut RISC Core";
774     case EM_H8_300:             return "Hitachi H8/300";
775     case EM_H8_300H:            return "Hitachi H8/300H";
776     case EM_H8S:                return "Hitachi H8S";
777     case EM_H8_500:             return "Hitachi H8/500";
778     case EM_IA_64:              return "Intel Merced";
779     case EM_MIPS_X:             return "Stanford MIPS-X";
780     case EM_COLDFIRE:           return "Motorola Coldfire";
781     case EM_68HC12:             return "Motorola M68HC12";
782     case EM_ALPHA:              return "Alpha";
783     case EM_CYGNUS_D10V:        return "d10v";
784     case EM_CYGNUS_D30V:        return "d30v";
785     case EM_CYGNUS_ARC:         return "Arc";
786     case EM_CYGNUS_M32R:        return "Mitsubishi M32r";
787     case EM_CYGNUS_V850:        return "NEC v850";
788     case EM_CYGNUS_MN10300:     return "mn10300";
789     case EM_CYGNUS_MN10200:     return "mn10200";
790     case EM_CYGNUS_FR30:        return "Fujitsu FR30";
791
792     default:
793       sprintf (buff, _("<unknown>: %x"), e_machine);
794       return buff;
795     }
796 }
797
798 static char *
799 get_machine_flags (e_flags, e_machine)
800      unsigned e_flags;
801      unsigned e_machine;
802 {
803   static char buf [1024];
804
805   buf[0] = '\0';
806   if (e_flags)
807     {
808       switch (e_machine)
809         {
810         default:
811           break;
812
813         case EM_PPC:
814           if (e_flags & EF_PPC_EMB)
815             strcat (buf, ", emb");
816
817           if (e_flags & EF_PPC_RELOCATABLE)
818             strcat (buf, ", relocatable");
819
820           if (e_flags & EF_PPC_RELOCATABLE_LIB)
821             strcat (buf, ", relocatable-lib");
822           break;
823
824         case EM_CYGNUS_V850:
825           switch (e_flags & EF_V850_ARCH)
826             {
827             case E_V850E_ARCH:
828               strcat (buf, ", v850e");
829               break;
830             case E_V850EA_ARCH:
831               strcat (buf, ", v850ea");
832               break;
833             case E_V850_ARCH:
834               strcat (buf, ", v850");
835               break;
836             default:
837               strcat (buf, ", unknown v850 architecture variant");
838               break;
839             }
840           break;
841
842         case EM_CYGNUS_M32R:
843           if ((e_flags & EF_M32R_ARCH) == E_M32R_ARCH)
844             strcat (buf, ", m32r");
845
846           break;
847
848         case EM_MIPS:
849         case EM_MIPS_RS4_BE:
850           if (e_flags & EF_MIPS_NOREORDER)
851             strcat (buf, ", noreorder");
852
853           if (e_flags & EF_MIPS_PIC)
854             strcat (buf, ", pic");
855
856           if (e_flags & EF_MIPS_CPIC)
857             strcat (buf, ", cpic");
858
859           if (e_flags & EF_MIPS_ABI2)
860             strcat (buf, ", abi2");
861
862           if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1)
863             strcat (buf, ", mips1");
864
865           if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2)
866             strcat (buf, ", mips2");
867
868           if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_3)
869             strcat (buf, ", mips3");
870
871           if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_4)
872             strcat (buf, ", mips4");
873           break;
874         }
875     }
876
877   return buf;
878 }
879
880 static char *
881 get_machine_data (e_data)
882      unsigned e_data;
883 {
884   static char buff [32];
885
886   switch (e_data)
887     {
888     case ELFDATA2LSB: return _("ELFDATA2LSB (little endian)");
889     case ELFDATA2MSB: return _("ELFDATA2MSB (big endian)");
890     default:
891       sprintf (buff, _("<unknown>: %x"), e_data);
892       return buff;
893     }
894 }
895
896 static const char *
897 get_mips_segment_type (type)
898      unsigned long type;
899 {
900   switch (type)
901     {
902     case PT_MIPS_REGINFO:
903       return "REGINFO";
904     case PT_MIPS_RTPROC:
905       return "RTPROC";
906     case PT_MIPS_OPTIONS:
907       return "OPTIONS";
908     default:
909       break;
910     }
911
912   return NULL;
913 }
914
915 static const char *
916 get_segment_type (p_type)
917      unsigned long p_type;
918 {
919   static char buff [32];
920
921   switch (p_type)
922     {
923     case PT_NULL:       return "NULL";
924     case PT_LOAD:       return "LOAD";
925     case PT_DYNAMIC:    return "DYNAMIC";
926     case PT_INTERP:     return "INTERP";
927     case PT_NOTE:       return "NOTE";
928     case PT_SHLIB:      return "SHLIB";
929     case PT_PHDR:       return "PHDR";
930
931     default:
932       if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
933         {
934           const char * result;
935           
936           switch (elf_header.e_machine)
937             {
938             case EM_MIPS:
939             case EM_MIPS_RS4_BE:
940               result = get_mips_segment_type (p_type);
941               break;
942             default:
943               result = NULL;
944               break;
945             }
946           
947           if (result != NULL)
948             return result;
949           
950           sprintf (buff, "LOPROC+%lx", p_type - PT_LOPROC);
951         }
952       else if ((p_type >= PT_LOOS) && (p_type <= PT_HIOS))
953         sprintf (buff, "LOOS+%lx", p_type - PT_LOOS);
954       else
955         sprintf (buff, _("<unknown>: %lx"), p_type);
956
957       return buff;
958     }
959 }
960
961 static const char *
962 get_mips_section_type_name (sh_type)
963      unsigned int sh_type;
964 {
965   switch (sh_type)
966     {
967     case SHT_MIPS_LIBLIST:       return "MIPS_LIBLIST";
968     case SHT_MIPS_MSYM:          return "MIPS_MSYM";
969     case SHT_MIPS_CONFLICT:      return "MIPS_CONFLICT";
970     case SHT_MIPS_GPTAB:         return "MIPS_GPTAB";
971     case SHT_MIPS_UCODE:         return "MIPS_UCODE";
972     case SHT_MIPS_DEBUG:         return "MIPS_DEBUG";
973     case SHT_MIPS_REGINFO:       return "MIPS_REGINFO";
974     case SHT_MIPS_PACKAGE:       return "MIPS_PACKAGE";
975     case SHT_MIPS_PACKSYM:       return "MIPS_PACKSYM";
976     case SHT_MIPS_RELD:          return "MIPS_RELD";
977     case SHT_MIPS_IFACE:         return "MIPS_IFACE";
978     case SHT_MIPS_CONTENT:       return "MIPS_CONTENT";
979     case SHT_MIPS_OPTIONS:       return "MIPS_OPTIONS";
980     case SHT_MIPS_SHDR:          return "MIPS_SHDR";
981     case SHT_MIPS_FDESC:         return "MIPS_FDESC";
982     case SHT_MIPS_EXTSYM:        return "MIPS_EXTSYM";
983     case SHT_MIPS_DENSE:         return "MIPS_DENSE";
984     case SHT_MIPS_PDESC:         return "MIPS_PDESC";
985     case SHT_MIPS_LOCSYM:        return "MIPS_LOCSYM";
986     case SHT_MIPS_AUXSYM:        return "MIPS_AUXSYM";
987     case SHT_MIPS_OPTSYM:        return "MIPS_OPTSYM";
988     case SHT_MIPS_LOCSTR:        return "MIPS_LOCSTR";
989     case SHT_MIPS_LINE:          return "MIPS_LINE";
990     case SHT_MIPS_RFDESC:        return "MIPS_RFDESC";
991     case SHT_MIPS_DELTASYM:      return "MIPS_DELTASYM";
992     case SHT_MIPS_DELTAINST:     return "MIPS_DELTAINST";
993     case SHT_MIPS_DELTACLASS:    return "MIPS_DELTACLASS";
994     case SHT_MIPS_DWARF:         return "MIPS_DWARF";
995     case SHT_MIPS_DELTADECL:     return "MIPS_DELTADECL";
996     case SHT_MIPS_SYMBOL_LIB:    return "MIPS_SYMBOL_LIB";
997     case SHT_MIPS_EVENTS:        return "MIPS_EVENTS";
998     case SHT_MIPS_TRANSLATE:     return "MIPS_TRANSLATE";
999     case SHT_MIPS_PIXIE:         return "MIPS_PIXIE";
1000     case SHT_MIPS_XLATE:         return "MIPS_XLATE";
1001     case SHT_MIPS_XLATE_DEBUG:   return "MIPS_XLATE_DEBUG";
1002     case SHT_MIPS_WHIRL:         return "MIPS_WHIRL";
1003     case SHT_MIPS_EH_REGION:     return "MIPS_EH_REGION";
1004     case SHT_MIPS_XLATE_OLD:     return "MIPS_XLATE_OLD";
1005     case SHT_MIPS_PDR_EXCEPTION: return "MIPS_PDR_EXCEPTION";
1006     default:
1007       break;
1008     }
1009   return NULL;
1010 }
1011
1012 static const char *
1013 get_section_type_name (sh_type)
1014      unsigned int sh_type;
1015 {
1016   static char buff [32];
1017
1018   switch (sh_type)
1019     {
1020     case SHT_NULL:              return "NULL";
1021     case SHT_PROGBITS:          return "PROGBITS";
1022     case SHT_SYMTAB:            return "SYMTAB";
1023     case SHT_STRTAB:            return "STRTAB";
1024     case SHT_RELA:              return "RELA";
1025     case SHT_HASH:              return "HASH";
1026     case SHT_DYNAMIC:           return "DYNAMIC";
1027     case SHT_NOTE:              return "NOTE";
1028     case SHT_NOBITS:            return "NOBITS";
1029     case SHT_REL:               return "REL";
1030     case SHT_SHLIB:             return "SHLIB";
1031     case SHT_DYNSYM:            return "DYNSYM";
1032     case SHT_GNU_verdef:        return "VERDEF";
1033     case SHT_GNU_verneed:       return "VERNEED";
1034     case SHT_GNU_versym:        return "VERSYM";
1035     case 0x6ffffff0:            return "VERSYM";
1036     case 0x6ffffffc:            return "VERDEF";
1037     case 0x7ffffffd:            return "AUXILIARY";
1038     case 0x7fffffff:            return "FILTER";
1039
1040     default:
1041       if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC))
1042         {
1043           const char * result;
1044
1045           switch (elf_header.e_machine)
1046             {
1047             case EM_MIPS:
1048             case EM_MIPS_RS4_BE:
1049               result = get_mips_section_type_name (sh_type);
1050               break;
1051             default:
1052               result = NULL;
1053               break;
1054             }
1055
1056           if (result != NULL)
1057             return result;
1058
1059           sprintf (buff, "SHT_LOPROC+%x", sh_type - SHT_LOPROC);
1060         }
1061       else if ((sh_type >= SHT_LOOS) && (sh_type <= SHT_HIOS))
1062         sprintf (buff, "SHT_LOOS+%x", sh_type - SHT_LOOS);
1063       else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER))
1064         sprintf (buff, "SHT_LOUSER+%x", sh_type - SHT_LOUSER);
1065       else
1066         sprintf (buff, _("<unknown>: %x"), sh_type);
1067       
1068       return buff;
1069     }
1070 }
1071
1072 struct option options [] =
1073 {
1074   {"all",              no_argument, 0, 'a'},
1075   {"file-header",      no_argument, 0, 'h'},
1076   {"program-headers",  no_argument, 0, 'l'},
1077   {"headers",          no_argument, 0, 'e'},
1078   {"histogram",        no_argument, & do_histogram, 1},
1079   {"segments",         no_argument, 0, 'l'},
1080   {"sections",         no_argument, 0, 'S'},
1081   {"section-headers",  no_argument, 0, 'S'},
1082   {"symbols",          no_argument, 0, 's'},
1083   {"syms",             no_argument, 0, 's'},
1084   {"relocs",           no_argument, 0, 'r'},
1085   {"dynamic",          no_argument, 0, 'd'},
1086   {"version-info",     no_argument, 0, 'V'},
1087   {"use-dynamic",      no_argument, 0, 'D'},
1088   {"hex-dump",         required_argument, 0, 'x'},
1089   {"debug-dump",       optional_argument, 0, 'w'},
1090 #ifdef SUPPORT_DISASSEMBLY
1091   {"instruction-dump", required_argument, 0, 'i'},
1092 #endif
1093
1094   {"version",          no_argument, 0, 'v'},
1095   {"help",             no_argument, 0, 'H'},
1096   {0,                  no_argument, 0, 0}
1097 };
1098
1099 static void
1100 usage ()
1101 {
1102   fprintf (stdout, _("Usage: readelf {options} elf-file(s)\n"));
1103   fprintf (stdout, _("  Options are:\n"));
1104   fprintf (stdout, _("  -a or --all               Equivalent to: -h -l -S -s -r -d -V --histogram\n"));
1105   fprintf (stdout, _("  -h or --file-header       Display the ELF file header\n"));
1106   fprintf (stdout, _("  -l or --program-headers or --segments\n"));
1107   fprintf (stdout, _("                            Display the program headers\n"));
1108   fprintf (stdout, _("  -S or --section-headers or --sections\n"));
1109   fprintf (stdout, _("                            Display the sections' header\n"));
1110   fprintf (stdout, _("  -e or --headers           Equivalent to: -h -l -S\n"));
1111   fprintf (stdout, _("  -s or --syms or --symbols Display the symbol table\n"));
1112   fprintf (stdout, _("  -r or --relocs            Display the relocations (if present)\n"));
1113   fprintf (stdout, _("  -d or --dynamic           Display the dynamic segment (if present)\n"));
1114   fprintf (stdout, _("  -V or --version-info      Display the version sections (if present)\n"));
1115   fprintf (stdout, _("  -D or --use-dynamic       Use the dynamic section info when displaying symbols\n"));
1116   fprintf (stdout, _("  -x <number> or --hex-dump=<number>\n"));
1117   fprintf (stdout, _("                            Dump the contents of section <number>\n"));
1118   fprintf (stdout, _("  -w[liapr] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges]\n"));
1119   fprintf (stdout, _("                            Display the contents of DWARF2 debug sections\n"));
1120 #ifdef SUPPORT_DISASSEMBLY
1121   fprintf (stdout, _("  -i <number> or --instruction-dump=<number>\n"));
1122   fprintf (stdout, _("                            Disassemble the contents of section <number>\n"));
1123 #endif
1124   fprintf (stdout, _("        --histogram         Display histogram of bucket list lengths\n"));
1125   fprintf (stdout, _("  -v or --version           Display the version number of readelf\n"));
1126   fprintf (stdout, _("  -H or --help              Display this information\n"));
1127   fprintf (stdout, _("Report bugs to bug-gnu-utils@gnu.org\n"));
1128
1129   exit (0);
1130 }
1131
1132 static void
1133 request_dump (section, type)
1134      unsigned int section;
1135      char         type;
1136 {
1137   if (section >= num_dump_sects)
1138     {
1139       char * new_dump_sects;
1140
1141       new_dump_sects = (char *) calloc (section + 1, 1);
1142
1143       if (new_dump_sects == NULL)
1144         error (_("Out of memory allocating dump request table."));
1145       else
1146         {
1147           /* Copy current flag settings.  */
1148           memcpy (new_dump_sects, dump_sects, num_dump_sects);
1149
1150           free (dump_sects);
1151
1152           dump_sects = new_dump_sects;
1153           num_dump_sects = section + 1;
1154         }
1155     }
1156
1157   if (dump_sects)
1158     dump_sects [section] |= type;
1159
1160   return;
1161 }
1162
1163 static void
1164 parse_args (argc, argv)
1165      int argc;
1166      char ** argv;
1167 {
1168   int c;
1169
1170   if (argc < 2)
1171     usage ();
1172
1173   while ((c = getopt_long
1174           (argc, argv, "ersahldSDw::x:i:vV", options, NULL)) != EOF)
1175     {
1176       char *    cp;
1177       int       section;
1178
1179       switch (c)
1180         {
1181         case 0:
1182           /* Long options.  */
1183           break;
1184         case 'H':
1185           usage ();
1186           break;
1187
1188         case 'a':
1189           do_syms ++;
1190           do_reloc ++;
1191           do_dynamic ++;
1192           do_header ++;
1193           do_sections ++;
1194           do_segments ++;
1195           do_version ++;
1196           do_histogram ++;
1197           break;
1198         case 'e':
1199           do_header ++;
1200           do_sections ++;
1201           do_segments ++;
1202           break;
1203         case 'D':
1204           do_using_dynamic ++;
1205           break;
1206         case 'r':
1207           do_reloc ++;
1208           break;
1209         case 'h':
1210           do_header ++;
1211           break;
1212         case 'l':
1213           do_segments ++;
1214           break;
1215         case 's':
1216           do_syms ++;
1217           break;
1218         case 'S':
1219           do_sections ++;
1220           break;
1221         case 'd':
1222           do_dynamic ++;
1223           break;
1224         case 'x':
1225           do_dump ++;
1226           section = strtoul (optarg, & cp, 0);
1227           if (! * cp && section >= 0)
1228             {
1229               request_dump (section, HEX_DUMP);
1230               break;
1231             }
1232           goto oops;
1233         case 'w':
1234           do_dump ++;
1235           if (optarg == 0)
1236             do_debugging = 1;
1237           else
1238             {
1239               do_debugging = 0;
1240               switch (optarg[0])
1241                 {
1242                 case 'i':
1243                 case 'I':
1244                   do_debug_info = 1;
1245                   break;
1246
1247                 case 'a':
1248                 case 'A':
1249                   do_debug_abbrevs = 1;
1250                   break;
1251
1252                 case 'l':
1253                 case 'L':
1254                   do_debug_lines = 1;
1255                   break;
1256
1257                 case 'p':
1258                 case 'P':
1259                   do_debug_pubnames = 1;
1260                   break;
1261
1262                 case 'r':
1263                 case 'R':
1264                   do_debug_aranges = 1;
1265                   break;
1266
1267                 default:
1268                   warn (_("Unrecognised debug option '%s'\n"), optarg);
1269                   break;
1270                 }
1271             }
1272           break;
1273 #ifdef SUPPORT_DISASSEMBLY
1274         case 'i':
1275           do_dump ++;
1276           section = strtoul (optarg, & cp, 0);
1277           if (! * cp && section >= 0)
1278             {
1279               request_dump (section, DISASS_DUMP);
1280               break;
1281             }
1282           goto oops;
1283 #endif
1284         case 'v':
1285           print_version (program_name);
1286           break;
1287         case 'V':
1288           do_version ++;
1289           break;
1290         default:
1291         oops:
1292           /* xgettext:c-format */
1293           error (_("Invalid option '-%c'\n"), c);
1294           /* Drop through.  */
1295         case '?':
1296           usage ();
1297         }
1298     }
1299
1300   if (!do_dynamic && !do_syms && !do_reloc && !do_sections
1301       && !do_segments && !do_header && !do_dump && !do_version
1302       && !do_histogram && !do_debugging)
1303     usage ();
1304   else if (argc < 3)
1305     {
1306       warn (_("Nothing to do.\n"));
1307       usage();
1308     }
1309 }
1310
1311 static const char *
1312 get_elf_class (elf_class)
1313      unsigned char elf_class;
1314 {
1315   switch (elf_class)
1316     {
1317     case ELFCLASSNONE: return _("none");
1318     case ELFCLASS32:   return _("ELF32");
1319     case ELFCLASS64:   return _("ELF64");
1320     default:           return _("<unknown>");
1321     }
1322 }
1323
1324 static const char *
1325 get_data_encoding (encoding)
1326      unsigned char encoding;
1327 {
1328   switch (encoding)
1329     {
1330     case ELFDATANONE: return _("none");
1331     case ELFDATA2LSB: return _("2's compilment, little endian");
1332     case ELFDATA2MSB: return _("2's compilment, big endian");
1333     default:          return _("<unknown>");
1334     }
1335 }
1336
1337 static const char *
1338 get_osabi_name (osabi)
1339      unsigned char osabi;
1340 {
1341   switch (osabi)
1342     {
1343     case ELFOSABI_SYSV:       return _("UNIX - System V");
1344     case ELFOSABI_HPUX:       return _("UNIX - HP-UX");
1345     case ELFOSABI_STANDALONE: return _("Standalone App");
1346     default:                  return _("<unknown>");
1347     }
1348 }
1349
1350 /* Decode the data held in 'elf_header'.  */
1351 static int
1352 process_file_header ()
1353 {
1354   if (   elf_header.e_ident [EI_MAG0] != ELFMAG0
1355       || elf_header.e_ident [EI_MAG1] != ELFMAG1
1356       || elf_header.e_ident [EI_MAG2] != ELFMAG2
1357       || elf_header.e_ident [EI_MAG3] != ELFMAG3)
1358     {
1359       error
1360         (_("Not an ELF file - it has the wrong magic bytes at the start\n"));
1361       return 0;
1362     }
1363
1364   if (do_header)
1365     {
1366       int i;
1367
1368       printf (_("ELF Header:\n"));
1369       printf (_("  Magic:   "));
1370       for (i = 0; i < EI_NIDENT; i ++)
1371         printf ("%2.2x ", elf_header.e_ident [i]);
1372       printf ("\n");
1373       printf (_("  Class:                             %s\n"),
1374               get_elf_class (elf_header.e_ident [EI_CLASS]));
1375       printf (_("  Data:                              %s\n"),
1376               get_data_encoding (elf_header.e_ident [EI_DATA]));
1377       printf (_("  Version:                           %d %s\n"),
1378               elf_header.e_ident [EI_VERSION],
1379               elf_header.e_ident [EI_VERSION] == EV_CURRENT ? "(current)" :
1380               elf_header.e_ident [EI_VERSION] != EV_NONE ? "<unknown>" : "");
1381       printf (_("  OS/ABI:                            %s\n"),
1382               get_osabi_name (elf_header.e_ident [EI_OSABI]));
1383       printf (_("  ABI Version:                       %d\n"),
1384               elf_header.e_ident [EI_ABIVERSION]);
1385       printf (_("  Type:                              %s\n"),
1386               get_file_type (elf_header.e_type));
1387       printf (_("  Machine:                           %s\n"),
1388               get_machine_name (elf_header.e_machine));
1389       printf (_("  Version:                           0x%lx\n"),
1390               (unsigned long) elf_header.e_version);
1391       printf (_("  Data:                              %s\n"),
1392               get_machine_data (elf_header.e_ident [EI_DATA]));
1393       printf (_("  Entry point address:               0x%lx\n"),
1394               (unsigned long) elf_header.e_entry);
1395       printf (_("  Start of program headers:          %ld (bytes into file)\n"),
1396               (long) elf_header.e_phoff);
1397       printf (_("  Start of section headers:          %ld (bytes into file)\n"),
1398               (long) elf_header.e_shoff);
1399       printf (_("  Flags:                             0x%lx%s\n"),
1400               (unsigned long) elf_header.e_flags,
1401               get_machine_flags (elf_header.e_flags, elf_header.e_machine));
1402       printf (_("  Size of this header:               %ld (bytes)\n"),
1403               (long) elf_header.e_ehsize);
1404       printf (_("  Size of program headers:           %ld (bytes)\n"),
1405               (long) elf_header.e_phentsize);
1406       printf (_("  Number of program headers:         %ld\n"),
1407               (long) elf_header.e_phnum);
1408       printf (_("  Size of section headers:           %ld (bytes)\n"),
1409               (long) elf_header.e_shentsize);
1410       printf (_("  Number of section headers:         %ld\n"),
1411               (long) elf_header.e_shnum);
1412       printf (_("  Section header string table index: %ld\n"),
1413               (long) elf_header.e_shstrndx);
1414     }
1415
1416   /* Test class after dumping header so that at least the header can be
1417      display on 64 bit binaries.  */
1418   
1419   binary_class = elf_header.e_ident [EI_CLASS];
1420   if (binary_class != ELFCLASS32)
1421     {
1422       error (_("Not a 32 bit ELF file\n"));
1423       return 0;
1424     }
1425
1426   return 1;
1427 }
1428
1429
1430 static int
1431 process_program_headers (file)
1432      FILE * file;
1433 {
1434   Elf32_External_Phdr * phdrs;
1435   Elf32_Internal_Phdr * program_headers;
1436   Elf32_Internal_Phdr * segment;
1437   unsigned int          i;
1438
1439   if (elf_header.e_phnum == 0)
1440     {
1441       if (do_segments)
1442         printf (_("\nThere are no program headers in this file.\n"));
1443       return 1;
1444     }
1445
1446   if (do_segments && !do_header)
1447     {
1448       printf (_("\nElf file is %s\n"), get_file_type (elf_header.e_type));
1449       printf (_("Entry point 0x%lx\n"), (unsigned long) elf_header.e_entry);
1450       printf (_("There are %d program headers, starting at offset %lx:\n"),
1451               elf_header.e_phnum, (unsigned long) elf_header.e_phoff);
1452     }
1453
1454   GET_DATA_ALLOC (elf_header.e_phoff,
1455                   elf_header.e_phentsize * elf_header.e_phnum,
1456                   phdrs, Elf32_External_Phdr *, "program headers");
1457
1458   program_headers = (Elf32_Internal_Phdr *) malloc
1459     (elf_header.e_phnum * sizeof (Elf32_Internal_Phdr));
1460
1461   if (program_headers == NULL)
1462     {
1463       error (_("Out of memory\n"));
1464       return 0;
1465     }
1466
1467   for (i = 0, segment = program_headers;
1468        i < elf_header.e_phnum;
1469        i ++, segment ++)
1470     {
1471       segment->p_type   = BYTE_GET (phdrs[i].p_type);
1472       segment->p_offset = BYTE_GET (phdrs[i].p_offset);
1473       segment->p_vaddr  = BYTE_GET (phdrs[i].p_vaddr);
1474       segment->p_paddr  = BYTE_GET (phdrs[i].p_paddr);
1475       segment->p_filesz = BYTE_GET (phdrs[i].p_filesz);
1476       segment->p_memsz  = BYTE_GET (phdrs[i].p_memsz);
1477       segment->p_flags  = BYTE_GET (phdrs[i].p_flags);
1478       segment->p_align  = BYTE_GET (phdrs[i].p_align);
1479     }
1480
1481   free (phdrs);
1482
1483   if (do_segments)
1484     {
1485       printf
1486         (_("\nProgram Header%s:\n"), elf_header.e_phnum > 1 ? "s" : "");
1487       printf
1488         (_("  Type        Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align\n"));
1489     }
1490
1491   loadaddr = -1;
1492   dynamic_addr = 0;
1493
1494   for (i = 0, segment = program_headers;
1495        i < elf_header.e_phnum;
1496        i ++, segment ++)
1497     {
1498       if (do_segments)
1499         {
1500           printf ("  %-11.11s ", get_segment_type (segment->p_type));
1501           printf ("0x%6.6lx ", (unsigned long) segment->p_offset);
1502           printf ("0x%8.8lx ", (unsigned long) segment->p_vaddr);
1503           printf ("0x%8.8lx ", (unsigned long) segment->p_paddr);
1504           printf ("0x%5.5lx ", (unsigned long) segment->p_filesz);
1505           printf ("0x%5.5lx ", (unsigned long) segment->p_memsz);
1506           printf ("%c%c%c ",
1507                   (segment->p_flags & PF_R ? 'R' : ' '),
1508                   (segment->p_flags & PF_W ? 'W' : ' '),
1509                   (segment->p_flags & PF_X ? 'E' : ' '));
1510           printf ("%#lx", (unsigned long) segment->p_align);
1511         }
1512
1513       switch (segment->p_type)
1514         {
1515         case PT_LOAD:
1516           if (loadaddr == -1)
1517             loadaddr = (segment->p_vaddr & 0xfffff000)
1518               - (segment->p_offset & 0xfffff000);
1519           break;
1520
1521         case PT_DYNAMIC:
1522           if (dynamic_addr)
1523             error (_("more than one dynamic segment\n"));
1524
1525           dynamic_addr = segment->p_offset;
1526           dynamic_size = segment->p_filesz;
1527           break;
1528
1529         case PT_INTERP:
1530           if (fseek (file, segment->p_offset, SEEK_SET))
1531             error (_("Unable to find program interpreter name\n"));
1532           else
1533             {
1534               program_interpreter[0] = 0;
1535               fscanf (file, "%63s", program_interpreter);
1536
1537               if (do_segments)
1538                 printf (_("\n      [Requesting program interpreter: %s]"),
1539                     program_interpreter);
1540             }
1541           break;
1542         }
1543
1544       if (do_segments)
1545         putc ('\n', stdout);
1546     }
1547
1548   if (loadaddr == -1)
1549     {
1550       /* Very strange. */
1551       loadaddr = 0;
1552     }
1553
1554   if (do_segments && section_headers != NULL)
1555     {
1556       printf (_("\n Section to Segment mapping:\n"));
1557       printf (_("  Segment Sections...\n"));
1558
1559       assert (string_table != NULL);
1560
1561       for (i = 0; i < elf_header.e_phnum; i++)
1562         {
1563           int        j;
1564           Elf32_Internal_Shdr * section;
1565
1566           segment = program_headers + i;
1567           section = section_headers;
1568
1569           printf ("   %2.2d     ", i);
1570
1571           for (j = 0; j < elf_header.e_shnum; j++, section ++)
1572             {
1573               if (section->sh_size > 0
1574                   /* Compare allocated sections by VMA, unallocated
1575                      sections by file offset.  */
1576                   && (section->sh_flags & SHF_ALLOC
1577                       ? (section->sh_addr >= segment->p_vaddr
1578                          && section->sh_addr + section->sh_size
1579                          <= segment->p_vaddr + segment->p_memsz)
1580                       : (section->sh_offset >= segment->p_offset
1581                          && (section->sh_offset + section->sh_size
1582                              <= segment->p_offset + segment->p_filesz))))
1583                 printf ("%s ", SECTION_NAME (section));
1584             }
1585
1586           putc ('\n',stdout);
1587         }
1588     }
1589
1590   free (program_headers);
1591
1592   return 1;
1593 }
1594
1595
1596 static int
1597 get_section_headers (file)
1598      FILE * file;
1599 {
1600   Elf32_External_Shdr * shdrs;
1601   Elf32_Internal_Shdr * internal;
1602   unsigned int          i;
1603
1604   GET_DATA_ALLOC (elf_header.e_shoff,
1605                   elf_header.e_shentsize * elf_header.e_shnum,
1606                   shdrs, Elf32_External_Shdr *, "section headers");
1607
1608   section_headers = (Elf32_Internal_Shdr *) malloc
1609     (elf_header.e_shnum * sizeof (Elf32_Internal_Shdr));
1610
1611   if (section_headers == NULL)
1612     {
1613       error (_("Out of memory\n"));
1614       return 0;
1615     }
1616
1617   for (i = 0, internal = section_headers;
1618        i < elf_header.e_shnum;
1619        i ++, internal ++)
1620     {
1621       internal->sh_name      = BYTE_GET (shdrs[i].sh_name);
1622       internal->sh_type      = BYTE_GET (shdrs[i].sh_type);
1623       internal->sh_flags     = BYTE_GET (shdrs[i].sh_flags);
1624       internal->sh_addr      = BYTE_GET (shdrs[i].sh_addr);
1625       internal->sh_offset    = BYTE_GET (shdrs[i].sh_offset);
1626       internal->sh_size      = BYTE_GET (shdrs[i].sh_size);
1627       internal->sh_link      = BYTE_GET (shdrs[i].sh_link);
1628       internal->sh_info      = BYTE_GET (shdrs[i].sh_info);
1629       internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
1630       internal->sh_entsize   = BYTE_GET (shdrs[i].sh_entsize);
1631     }
1632
1633   free (shdrs);
1634
1635   return 1;
1636 }
1637
1638 static Elf_Internal_Sym *
1639 get_elf_symbols (file, offset, number)
1640      FILE * file;
1641      unsigned long offset;
1642      unsigned long number;
1643 {
1644   Elf32_External_Sym * esyms;
1645   Elf_Internal_Sym *   isyms;
1646   Elf_Internal_Sym *   psym;
1647   unsigned int         j;
1648
1649   GET_DATA_ALLOC (offset, number * sizeof (Elf32_External_Sym),
1650                   esyms, Elf32_External_Sym *, "symbols");
1651
1652   isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym));
1653
1654   if (isyms == NULL)
1655     {
1656       error (_("Out of memory\n"));
1657       free (esyms);
1658
1659       return NULL;
1660     }
1661
1662   for (j = 0, psym = isyms;
1663        j < number;
1664        j ++, psym ++)
1665     {
1666       psym->st_name  = BYTE_GET (esyms[j].st_name);
1667       psym->st_value = BYTE_GET (esyms[j].st_value);
1668       psym->st_size  = BYTE_GET (esyms[j].st_size);
1669       psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
1670       psym->st_info  = BYTE_GET (esyms[j].st_info);
1671       psym->st_other = BYTE_GET (esyms[j].st_other);
1672     }
1673
1674   free (esyms);
1675
1676   return isyms;
1677 }
1678
1679 static int
1680 process_section_headers (file)
1681      FILE * file;
1682 {
1683   Elf32_Internal_Shdr * section;
1684   int        i;
1685
1686   section_headers = NULL;
1687
1688   if (elf_header.e_shnum == 0)
1689     {
1690       if (do_sections)
1691         printf (_("\nThere are no sections in this file.\n"));
1692
1693       return 1;
1694     }
1695
1696   if (do_sections && !do_header)
1697     printf (_("There are %d section headers, starting at offset %lx:\n"),
1698             elf_header.e_shnum, (unsigned long) elf_header.e_shoff);
1699
1700   if (! get_section_headers (file))
1701     return 0;
1702
1703   /* Read in the string table, so that we have names to display.  */
1704   section = section_headers + elf_header.e_shstrndx;
1705
1706   if (section->sh_size != 0)
1707     {
1708       unsigned long string_table_offset;
1709
1710       string_table_offset = section->sh_offset;
1711
1712       GET_DATA_ALLOC (section->sh_offset, section->sh_size,
1713                       string_table, char *, "string table");
1714     }
1715
1716   /* Scan the sections for the dynamic symbol table
1717      and dynamic string table and debug sections. */
1718   dynamic_symbols = NULL;
1719   dynamic_strings = NULL;
1720   dynamic_syminfo = NULL;
1721   for (i = 0, section = section_headers;
1722        i < elf_header.e_shnum;
1723        i ++, section ++)
1724     {
1725       char * name = SECTION_NAME (section);
1726
1727       if (section->sh_type == SHT_DYNSYM)
1728         {
1729           if (dynamic_symbols != NULL)
1730             {
1731               error (_("File contains multiple dynamic symbol tables\n"));
1732               continue;
1733             }
1734
1735           dynamic_symbols = get_elf_symbols
1736             (file, section->sh_offset,
1737              section->sh_size / section->sh_entsize);
1738         }
1739       else if (section->sh_type == SHT_STRTAB
1740                && strcmp (name, ".dynstr") == 0)
1741         {
1742           if (dynamic_strings != NULL)
1743             {
1744               error (_("File contains multiple dynamic string tables\n"));
1745               continue;
1746             }
1747
1748           GET_DATA_ALLOC (section->sh_offset, section->sh_size,
1749                           dynamic_strings, char *, "dynamic strings");
1750         }
1751       else if ((do_debugging || do_debug_info || do_debug_abbrevs
1752                 || do_debug_lines || do_debug_pubnames || do_debug_aranges)
1753                && strncmp (name, ".debug_", 7) == 0)
1754         {
1755           name += 7;
1756
1757           if (do_debugging
1758               || (do_debug_info     && (strcmp (name, "info") == 0))
1759               || (do_debug_abbrevs  && (strcmp (name, "abbrev") == 0))
1760               || (do_debug_lines    && (strcmp (name, "line") == 0))
1761               || (do_debug_pubnames && (strcmp (name, "pubnames") == 0))
1762               || (do_debug_aranges  && (strcmp (name, "aranges") == 0))
1763               )
1764             request_dump (i, DEBUG_DUMP);
1765         }
1766     }
1767
1768   if (! do_sections)
1769     return 1;
1770
1771   printf (_("\nSection Header%s:\n"), elf_header.e_shnum > 1 ? "s" : "");
1772   printf
1773     (_("  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al\n"));
1774
1775   for (i = 0, section = section_headers;
1776        i < elf_header.e_shnum;
1777        i ++, section ++)
1778     {
1779       printf ("  [%2d] %-17.17s %-15.15s ",
1780               i,
1781               SECTION_NAME (section),
1782               get_section_type_name (section->sh_type));
1783
1784       printf ( "%8.8lx %6.6lx %6.6lx %2.2lx",
1785                (unsigned long) section->sh_addr,
1786                (unsigned long) section->sh_offset,
1787                (unsigned long) section->sh_size,
1788                (unsigned long) section->sh_entsize);
1789
1790       printf (" %c%c%c %2ld %3lx %ld\n",
1791               (section->sh_flags & SHF_WRITE ? 'W' : ' '),
1792               (section->sh_flags & SHF_ALLOC ? 'A' : ' '),
1793               (section->sh_flags & SHF_EXECINSTR ? 'X' : ' '),
1794               (unsigned long) section->sh_link,
1795               (unsigned long) section->sh_info,
1796               (unsigned long) section->sh_addralign);
1797     }
1798
1799   return 1;
1800 }
1801
1802 /* Process the reloc section.  */
1803 static int
1804 process_relocs (file)
1805      FILE * file;
1806 {
1807   unsigned long    rel_size;
1808   unsigned long    rel_offset;
1809
1810
1811   if (!do_reloc)
1812     return 1;
1813
1814   if (do_using_dynamic)
1815     {
1816       rel_size   = 0;
1817       rel_offset = 0;
1818
1819       if (dynamic_info[DT_REL])
1820         {
1821           rel_offset = dynamic_info[DT_REL];
1822           rel_size   = dynamic_info[DT_RELSZ];
1823         }
1824       else if (dynamic_info [DT_RELA])
1825         {
1826           rel_offset = dynamic_info[DT_RELA];
1827           rel_size   = dynamic_info[DT_RELASZ];
1828         }
1829       else if (dynamic_info[DT_JMPREL])
1830         {
1831           rel_offset = dynamic_info[DT_JMPREL];
1832           rel_size   = dynamic_info[DT_PLTRELSZ];
1833         }
1834
1835       if (rel_size)
1836         {
1837           printf
1838             (_("\nRelocation section at offset 0x%lx contains %ld bytes:\n"),
1839              rel_offset, rel_size);
1840
1841           dump_relocations (file, rel_offset - loadaddr, rel_size,
1842                             dynamic_symbols, dynamic_strings);
1843         }
1844       else
1845         printf (_("\nThere are no dynamic relocations in this file.\n"));
1846     }
1847   else
1848     {
1849       Elf32_Internal_Shdr *     section;
1850       unsigned long             i;
1851       int                       found = 0;
1852
1853       for (i = 0, section = section_headers;
1854            i < elf_header.e_shnum;
1855            i++, section ++)
1856         {
1857           if (   section->sh_type != SHT_RELA
1858               && section->sh_type != SHT_REL)
1859             continue;
1860
1861           rel_offset = section->sh_offset;
1862           rel_size   = section->sh_size;
1863
1864           if (rel_size)
1865             {
1866               Elf32_Internal_Shdr * strsec;
1867               Elf32_Internal_Shdr * symsec;
1868               Elf_Internal_Sym *    symtab;
1869               char *                strtab;
1870
1871               printf (_("\nRelocation section "));
1872
1873               if (string_table == NULL)
1874                 printf ("%d", section->sh_name);
1875               else
1876                 printf ("'%s'", SECTION_NAME (section));
1877
1878               printf (_(" at offset 0x%lx contains %lu entries:\n"),
1879                  rel_offset, (unsigned long) (rel_size / section->sh_entsize));
1880
1881               symsec = section_headers + section->sh_link;
1882
1883               symtab = get_elf_symbols (file, symsec->sh_offset,
1884                                         symsec->sh_size / symsec->sh_entsize);
1885
1886               if (symtab == NULL)
1887                 continue;
1888
1889               strsec = section_headers + symsec->sh_link;
1890
1891               GET_DATA_ALLOC (strsec->sh_offset, strsec->sh_size, strtab,
1892                               char *, "string table");
1893
1894               dump_relocations (file, rel_offset, rel_size, symtab, strtab);
1895
1896               free (strtab);
1897               free (symtab);
1898
1899               found = 1;
1900             }
1901         }
1902
1903       if (! found)
1904         printf (_("\nThere are no relocations in this file.\n"));
1905     }
1906
1907   return 1;
1908 }
1909
1910
1911 static void
1912 dynamic_segment_mips_val (entry)
1913      Elf_Internal_Dyn * entry;
1914 {
1915   switch (entry->d_tag)
1916     {
1917     case DT_MIPS_FLAGS:
1918       if (entry->d_un.d_val == 0)
1919         printf ("NONE\n");
1920       else
1921         {
1922           static const char * opts[] =
1923           {
1924             "QUICKSTART", "NOTPOT", "NO_LIBRARY_REPLACEMENT",
1925             "NO_MOVE", "SGI_ONLY", "GUARANTEE_INIT", "DELTA_C_PLUS_PLUS",
1926             "GUARANTEE_START_INIT", "PIXIE", "DEFAULT_DELAY_LOAD",
1927             "REQUICKSTART", "REQUICKSTARTED", "CORD", "NO_UNRES_UNDEF",
1928             "RLD_ORDER_SAFE"
1929           };
1930           unsigned int cnt;
1931           int first = 1;
1932           for (cnt = 0; cnt < NUM_ELEM (opts); ++ cnt)
1933             if (entry->d_un.d_val & (1 << cnt))
1934               {
1935                 printf ("%s%s", first ? "" : " ", opts[cnt]);
1936                 first = 0;
1937               }
1938           puts ("");
1939         }
1940       break;
1941       
1942     case DT_MIPS_IVERSION:
1943       if (dynamic_strings != NULL)
1944         printf ("Interface Version: %s\n",
1945                 dynamic_strings + entry->d_un.d_val);
1946       else
1947         printf ("%ld\n", (long) entry->d_un.d_ptr);
1948       break;
1949       
1950     case DT_MIPS_TIME_STAMP:
1951       {
1952         char timebuf[20];
1953         time_t time = entry->d_un.d_val;
1954         strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time));
1955         printf ("Time Stamp: %s\n", timebuf);
1956       }
1957       break;
1958       
1959     case DT_MIPS_RLD_VERSION:
1960     case DT_MIPS_LOCAL_GOTNO:
1961     case DT_MIPS_CONFLICTNO:
1962     case DT_MIPS_LIBLISTNO:
1963     case DT_MIPS_SYMTABNO:
1964     case DT_MIPS_UNREFEXTNO:
1965     case DT_MIPS_HIPAGENO:
1966     case DT_MIPS_DELTA_CLASS_NO:
1967     case DT_MIPS_DELTA_INSTANCE_NO:
1968     case DT_MIPS_DELTA_RELOC_NO:
1969     case DT_MIPS_DELTA_SYM_NO:
1970     case DT_MIPS_DELTA_CLASSSYM_NO:
1971     case DT_MIPS_COMPACT_SIZE:
1972       printf ("%ld\n", (long) entry->d_un.d_ptr);
1973       break;
1974       
1975     default:
1976       printf ("%#lx\n", (long) entry->d_un.d_ptr);
1977     }
1978 }
1979
1980 /* Parse the dynamic segment */
1981 static int
1982 process_dynamic_segment (file)
1983      FILE * file;
1984 {
1985   Elf_Internal_Dyn *    entry;
1986   Elf32_External_Dyn *  edyn;
1987   unsigned int i;
1988
1989   if (dynamic_size == 0)
1990     {
1991       if (do_dynamic)
1992         printf (_("\nThere is no dynamic segment in this file.\n"));
1993
1994       return 1;
1995     }
1996
1997   GET_DATA_ALLOC (dynamic_addr, dynamic_size,
1998                   edyn, Elf32_External_Dyn *, "dynamic segment");
1999   
2000   /* SGI's ELF has more than one section in the DYNAMIC segment.  Determine
2001      how large .dynamic is now.  We can do this even before the byte
2002      swapping since the DT_NULL tag is recognizable.  */
2003   dynamic_size = 0;
2004   while (*(Elf32_Word *) edyn[dynamic_size++].d_tag != DT_NULL)
2005     ;
2006
2007   dynamic_segment = (Elf_Internal_Dyn *)
2008     malloc (dynamic_size * sizeof (Elf_Internal_Dyn));
2009
2010   if (dynamic_segment == NULL)
2011     {
2012       error (_("Out of memory\n"));
2013       free (edyn);
2014       return 0;
2015     }
2016
2017   for (i = 0, entry = dynamic_segment;
2018        i < dynamic_size;
2019        i ++, entry ++)
2020     {
2021       entry->d_tag      = BYTE_GET (edyn [i].d_tag);
2022       entry->d_un.d_val = BYTE_GET (edyn [i].d_un.d_val);
2023     }
2024
2025   free (edyn);
2026
2027   /* Find the appropriate symbol table.  */
2028   if (dynamic_symbols == NULL)
2029     {
2030       for (i = 0, entry = dynamic_segment;
2031            i < dynamic_size;
2032            ++i, ++ entry)
2033         {
2034           unsigned long        offset;
2035           long                 num_syms;
2036
2037           if (entry->d_tag != DT_SYMTAB)
2038             continue;
2039
2040           dynamic_info[DT_SYMTAB] = entry->d_un.d_val;
2041
2042           /* Since we do not know how big the symbol table is,
2043              we default to reading in the entire file (!) and
2044              processing that.  This is overkill, I know, but it
2045              should work. */
2046
2047           offset = entry->d_un.d_val - loadaddr;
2048
2049           if (fseek (file, 0, SEEK_END))
2050             error (_("Unable to seek to end of file!"));
2051
2052           num_syms = (ftell (file) - offset) / sizeof (Elf32_External_Sym);
2053
2054           if (num_syms < 1)
2055             {
2056               error (_("Unable to determine the number of symbols to load\n"));
2057               continue;
2058             }
2059
2060           dynamic_symbols = get_elf_symbols (file, offset, num_syms);
2061         }
2062     }
2063
2064   /* Similarly find a string table.  */
2065   if (dynamic_strings == NULL)
2066     {
2067       for (i = 0, entry = dynamic_segment;
2068            i < dynamic_size;
2069            ++i, ++ entry)
2070         {
2071           unsigned long offset;
2072           long          str_tab_len;
2073
2074           if (entry->d_tag != DT_STRTAB)
2075             continue;
2076
2077           dynamic_info[DT_STRTAB] = entry->d_un.d_val;
2078
2079           /* Since we do not know how big the string table is,
2080              we default to reading in the entire file (!) and
2081              processing that.  This is overkill, I know, but it
2082              should work. */
2083
2084           offset = entry->d_un.d_val - loadaddr;
2085           if (fseek (file, 0, SEEK_END))
2086             error (_("Unable to seek to end of file\n"));
2087           str_tab_len = ftell (file) - offset;
2088
2089           if (str_tab_len < 1)
2090             {
2091               error
2092                 (_("Unable to determine the length of the dynamic string table\n"));
2093               continue;
2094             }
2095
2096           GET_DATA_ALLOC (offset, str_tab_len, dynamic_strings, char *,
2097                           "dynamic string table");
2098
2099           break;
2100         }
2101     }
2102
2103   /* And find the syminfo section if available.  */
2104   if (dynamic_syminfo == NULL)
2105     {
2106       unsigned int syminsz = 0;
2107
2108       for (i = 0, entry = dynamic_segment;
2109            i < dynamic_size;
2110            ++i, ++ entry)
2111         {
2112           if (entry->d_tag == DT_SYMINENT)
2113             {
2114               /* Note: these braces are necessary to avoid a syntax
2115                  error from the SunOS4 C compiler.  */
2116               assert (sizeof (Elf_External_Syminfo) == entry->d_un.d_val);
2117             }
2118           else if (entry->d_tag == DT_SYMINSZ)
2119             syminsz = entry->d_un.d_val;
2120           else if (entry->d_tag == DT_SYMINFO)
2121             dynamic_syminfo_offset = entry->d_un.d_val - loadaddr;
2122         }
2123
2124       if (dynamic_syminfo_offset != 0 && syminsz != 0)
2125         {
2126           Elf_External_Syminfo *extsyminfo;
2127           Elf_Internal_Syminfo *syminfo;
2128
2129           /* There is a syminfo section.  Read the data.  */
2130           GET_DATA_ALLOC (dynamic_syminfo_offset, syminsz, extsyminfo,
2131                           Elf_External_Syminfo *, "symbol information");
2132
2133           dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz);
2134           if (dynamic_syminfo == NULL)
2135             {
2136               error (_("Out of memory\n"));
2137               return 0;
2138             }
2139
2140           dynamic_syminfo_nent = syminsz / sizeof (Elf_External_Syminfo);
2141           for (i = 0, syminfo = dynamic_syminfo; i < dynamic_syminfo_nent;
2142                ++i, ++syminfo)
2143             {
2144               syminfo->si_boundto = BYTE_GET (extsyminfo[i].si_boundto);
2145               syminfo->si_flags = BYTE_GET (extsyminfo[i].si_flags);
2146             }
2147
2148           free (extsyminfo);
2149         }
2150     }
2151
2152   if (do_dynamic && dynamic_addr)
2153     printf (_("\nDynamic segment at offset 0x%x contains %d entries:\n"),
2154             dynamic_addr, dynamic_size);
2155   if (do_dynamic)
2156     printf (_("  Tag        Type                         Name/Value\n"));
2157
2158   for (i = 0, entry = dynamic_segment;
2159        i < dynamic_size;
2160        i++, entry ++)
2161     {
2162       if (do_dynamic)
2163         printf (_("  0x%-8.8lx (%s)%*s"),
2164                 (unsigned long) entry->d_tag,
2165                 get_dynamic_type (entry->d_tag),
2166                 27 - strlen (get_dynamic_type (entry->d_tag)),
2167                 " ");
2168
2169       switch (entry->d_tag)
2170         {
2171         case DT_AUXILIARY:
2172         case DT_FILTER:
2173           if (do_dynamic)
2174             {
2175               if (entry->d_tag == DT_AUXILIARY)
2176                 printf (_("Auxiliary library"));
2177               else
2178                 printf (_("Filter library"));
2179
2180               if (dynamic_strings)
2181                 printf (": [%s]\n", dynamic_strings + entry->d_un.d_val);
2182               else
2183                 printf (": %#lx\n", (long) entry->d_un.d_val);
2184             }
2185           break;
2186
2187         case DT_FEATURE_1:
2188           if (do_dynamic)
2189             {
2190               printf (_("Flags:"));
2191               if (entry->d_un.d_val == 0)
2192                 printf (_(" None\n"));
2193               else
2194                 {
2195                   unsigned long int val = entry->d_un.d_val;
2196                   if (val & DTF_1_PARINIT)
2197                     {
2198                       printf (" PARINIT");
2199                       val ^= DTF_1_PARINIT;
2200                     }
2201                   if (val != 0)
2202                     printf (" %lx", val);
2203                   puts ("");
2204                 }
2205             }
2206           break;
2207
2208         case DT_POSFLAG_1:
2209           if (do_dynamic)
2210             {
2211               printf (_("Flags:"));
2212               if (entry->d_un.d_val == 0)
2213                 printf (_(" None\n"));
2214               else
2215                 {
2216                   unsigned long int val = entry->d_un.d_val;
2217                   if (val & DF_P1_LAZYLOAD)
2218                     {
2219                       printf (" LAZYLOAD");
2220                       val ^= DF_P1_LAZYLOAD;
2221                     }
2222                   if (val & DF_P1_GROUPPERM)
2223                     {
2224                       printf (" GROUPPERM");
2225                       val ^= DF_P1_GROUPPERM;
2226                     }
2227                   if (val != 0)
2228                     printf (" %lx", val);
2229                   puts ("");
2230                 }
2231             }
2232           break;
2233
2234         case DT_FLAGS_1:
2235           if (do_dynamic)
2236             {
2237               printf (_("Flags:"));
2238               if (entry->d_un.d_val == 0)
2239                 printf (_(" None\n"));
2240               else
2241                 {
2242                   unsigned long int val = entry->d_un.d_val;
2243                   if (val & DF_1_NOW)
2244                     {
2245                       printf (" NOW");
2246                       val ^= DF_1_NOW;
2247                     }
2248                   if (val & DF_1_GLOBAL)
2249                     {
2250                       printf (" GLOBAL");
2251                       val ^= DF_1_GLOBAL;
2252                     }
2253                   if (val & DF_1_GROUP)
2254                     {
2255                       printf (" GROUP");
2256                       val ^= DF_1_GROUP;
2257                     }
2258                   if (val & DF_1_NODELETE)
2259                     {
2260                       printf (" NODELETE");
2261                       val ^= DF_1_NODELETE;
2262                     }
2263                   if (val & DF_1_LOADFLTR)
2264                     {
2265                       printf (" LOADFLTR");
2266                       val ^= DF_1_LOADFLTR;
2267                     }
2268                   if (val & DF_1_INITFIRST)
2269                     {
2270                       printf (" INITFIRST");
2271                       val ^= DF_1_INITFIRST;
2272                     }
2273                   if (val & DF_1_NOOPEN)
2274                     {
2275                       printf (" NOOPEN");
2276                       val ^= DF_1_NOOPEN;
2277                     }
2278                   if (val & DF_1_ORIGIN)
2279                     {
2280                       printf (" ORIGIN");
2281                       val ^= DF_1_ORIGIN;
2282                     }
2283                   if (val & DF_1_DIRECT)
2284                     {
2285                       printf (" DIRECT");
2286                       val ^= DF_1_DIRECT;
2287                     }
2288                   if (val & DF_1_TRANS)
2289                     {
2290                       printf (" TRANS");
2291                       val ^= DF_1_TRANS;
2292                     }
2293                   if (val & DF_1_INTERPOSE)
2294                     {
2295                       printf (" INTERPOSE");
2296                       val ^= DF_1_INTERPOSE;
2297                     }
2298                   if (val != 0)
2299                     printf (" %lx", val);
2300                   puts ("");
2301                 }
2302             }
2303           break;
2304
2305         case DT_PLTREL:
2306           if (do_dynamic)
2307             puts (get_dynamic_type (entry->d_un.d_val));
2308           break;
2309
2310         case DT_NULL    :
2311         case DT_NEEDED  :
2312         case DT_PLTGOT  :
2313         case DT_HASH    :
2314         case DT_STRTAB  :
2315         case DT_SYMTAB  :
2316         case DT_RELA    :
2317         case DT_INIT    :
2318         case DT_FINI    :
2319         case DT_SONAME  :
2320         case DT_RPATH   :
2321         case DT_SYMBOLIC:
2322         case DT_REL     :
2323         case DT_DEBUG   :
2324         case DT_TEXTREL :
2325         case DT_JMPREL  :
2326           dynamic_info[entry->d_tag] = entry->d_un.d_val;
2327
2328           if (do_dynamic)
2329             {
2330               char * name;
2331
2332               if (dynamic_strings == NULL)
2333                 name = NULL;
2334               else
2335                 name = dynamic_strings + entry->d_un.d_val;
2336
2337               if (name)
2338                 {
2339                   switch (entry->d_tag)
2340                     {
2341                     case DT_NEEDED:
2342                       printf (_("Shared library: [%s]"), name);
2343
2344                       if (strcmp (name, program_interpreter))
2345                         printf ("\n");
2346                       else
2347                         printf (_(" program interpreter\n"));
2348                       break;
2349
2350                     case DT_SONAME:
2351                       printf (_("Library soname: [%s]\n"), name);
2352                       break;
2353
2354                     case DT_RPATH:
2355                       printf (_("Library rpath: [%s]\n"), name);
2356                       break;
2357
2358                     default:
2359                       printf ("%#lx\n", (long) entry->d_un.d_val);
2360                     }
2361                 }
2362               else
2363                 printf ("%#lx\n", (long) entry->d_un.d_val);
2364             }
2365           break;
2366
2367         case DT_PLTRELSZ:
2368         case DT_RELASZ  :
2369         case DT_STRSZ   :
2370         case DT_RELSZ   :
2371         case DT_RELAENT :
2372         case DT_SYMENT  :
2373         case DT_RELENT  :
2374         case DT_PLTPADSZ:
2375         case DT_MOVEENT :
2376         case DT_MOVESZ  :
2377         case DT_INIT_ARRAYSZ:
2378         case DT_FINI_ARRAYSZ:
2379           if (do_dynamic)
2380             printf ("%lu (bytes)\n", (unsigned long) entry->d_un.d_val);
2381           break;
2382
2383         case DT_VERDEFNUM:
2384         case DT_VERNEEDNUM:
2385         case DT_RELACOUNT:
2386         case DT_RELCOUNT:
2387           if (do_dynamic)
2388             printf ("%lu\n", (unsigned long) entry->d_un.d_val);
2389           break;
2390
2391         case DT_SYMINSZ:
2392         case DT_SYMINENT:
2393         case DT_SYMINFO:
2394         case DT_USED:
2395         case DT_INIT_ARRAY:
2396         case DT_FINI_ARRAY:
2397           if (do_dynamic)
2398             {
2399               if (dynamic_strings != NULL && entry->d_tag == DT_USED)
2400                 {
2401                   char * name;
2402
2403                   name = dynamic_strings + entry->d_un.d_val;
2404
2405                   if (* name)
2406                     {
2407                       printf (_("Not needed object: [%s]\n"), name);
2408                       break;
2409                     }
2410                 }
2411               
2412               printf ("%#lx\n", (long) entry->d_un.d_val);
2413             }
2414           break;
2415
2416         case DT_BIND_NOW:
2417           /* The value of this entry is ignored.  */
2418           break;
2419           
2420         default:
2421           if ((entry->d_tag >= DT_VERSYM) && (entry->d_tag <= DT_VERNEEDNUM))
2422             version_info [DT_VERSIONTAGIDX (entry->d_tag)] =
2423               entry->d_un.d_val;
2424
2425           if (do_dynamic)
2426             {
2427               switch (elf_header.e_machine)
2428                 {
2429                 case EM_MIPS:
2430                 case EM_MIPS_RS4_BE:
2431                   dynamic_segment_mips_val (entry);
2432                   break;
2433                 default:
2434                   printf ("%#lx\n", (long) entry->d_un.d_ptr);
2435                 }
2436             }
2437           break;
2438         }
2439     }
2440
2441   return 1;
2442 }
2443
2444 static char *
2445 get_ver_flags (flags)
2446      unsigned int flags;
2447 {
2448   static char buff [32];
2449
2450   buff[0] = 0;
2451
2452   if (flags == 0)
2453     return _("none");
2454
2455   if (flags & VER_FLG_BASE)
2456     strcat (buff, "BASE ");
2457
2458   if (flags & VER_FLG_WEAK)
2459     {
2460       if (flags & VER_FLG_BASE)
2461         strcat (buff, "| ");
2462
2463       strcat (buff, "WEAK ");
2464     }
2465
2466   if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK))
2467     strcat (buff, "| <unknown>");
2468
2469   return buff;
2470 }
2471
2472 /* Display the contents of the version sections.  */
2473 static int
2474 process_version_sections (file)
2475      FILE * file;
2476 {
2477   Elf32_Internal_Shdr * section;
2478   unsigned   i;
2479   int        found = 0;
2480
2481   if (! do_version)
2482     return 1;
2483
2484   for (i = 0, section = section_headers;
2485        i < elf_header.e_shnum;
2486        i++, section ++)
2487     {
2488       switch (section->sh_type)
2489         {
2490         case SHT_GNU_verdef:
2491           {
2492             Elf_External_Verdef * edefs;
2493             unsigned int          idx;
2494             unsigned int          cnt;
2495
2496             found = 1;
2497
2498             printf
2499               (_("\nVersion definition section '%s' contains %ld entries:\n"),
2500                SECTION_NAME (section), section->sh_info);
2501
2502             printf (_("  Addr: 0x"));
2503             printf_vma (section->sh_addr);
2504             printf (_("  Offset: %#08lx  Link: %lx (%s)\n"),
2505                     section->sh_offset, section->sh_link,
2506                     SECTION_NAME (section_headers + section->sh_link));
2507
2508             GET_DATA_ALLOC (section->sh_offset, section->sh_size,
2509                             edefs, Elf_External_Verdef *,
2510                             "version definition section");
2511
2512             for (idx = cnt = 0; cnt < section->sh_info; ++ cnt)
2513               {
2514                 char *                 vstart;
2515                 Elf_External_Verdef *  edef;
2516                 Elf_Internal_Verdef    ent;
2517                 Elf_External_Verdaux * eaux;
2518                 Elf_Internal_Verdaux   aux;
2519                 int                    j;
2520                 int                    isum;
2521                 
2522                 vstart = ((char *) edefs) + idx;
2523
2524                 edef = (Elf_External_Verdef *) vstart;
2525
2526                 ent.vd_version = BYTE_GET (edef->vd_version);
2527                 ent.vd_flags   = BYTE_GET (edef->vd_flags);
2528                 ent.vd_ndx     = BYTE_GET (edef->vd_ndx);
2529                 ent.vd_cnt     = BYTE_GET (edef->vd_cnt);
2530                 ent.vd_hash    = BYTE_GET (edef->vd_hash);
2531                 ent.vd_aux     = BYTE_GET (edef->vd_aux);
2532                 ent.vd_next    = BYTE_GET (edef->vd_next);
2533
2534                 printf (_("  %#06x: Rev: %d  Flags: %s"),
2535                         idx, ent.vd_version, get_ver_flags (ent.vd_flags));
2536
2537                 printf (_("  Index: %d  Cnt: %d  "),
2538                         ent.vd_ndx, ent.vd_cnt);
2539
2540                 vstart += ent.vd_aux;
2541
2542                 eaux = (Elf_External_Verdaux *) vstart;
2543
2544                 aux.vda_name = BYTE_GET (eaux->vda_name);
2545                 aux.vda_next = BYTE_GET (eaux->vda_next);
2546
2547                 if (dynamic_strings)
2548                   printf (_("Name: %s\n"), dynamic_strings + aux.vda_name);
2549                 else
2550                   printf (_("Name index: %ld\n"), aux.vda_name);
2551
2552                 isum = idx + ent.vd_aux;
2553
2554                 for (j = 1; j < ent.vd_cnt; j ++)
2555                   {
2556                     isum   += aux.vda_next;
2557                     vstart += aux.vda_next;
2558
2559                     eaux = (Elf_External_Verdaux *) vstart;
2560
2561                     aux.vda_name = BYTE_GET (eaux->vda_name);
2562                     aux.vda_next = BYTE_GET (eaux->vda_next);
2563
2564                     if (dynamic_strings)
2565                       printf (_("  %#06x: Parent %d: %s\n"),
2566                               isum, j, dynamic_strings + aux.vda_name);
2567                     else
2568                       printf (_("  %#06x: Parent %d, name index: %ld\n"),
2569                               isum, j, aux.vda_name);
2570                   }
2571
2572                 idx += ent.vd_next;
2573               }
2574
2575             free (edefs);
2576           }
2577           break;
2578           
2579         case SHT_GNU_verneed:
2580           {
2581             Elf_External_Verneed *  eneed;
2582             unsigned int            idx;
2583             unsigned int            cnt;
2584
2585             found = 1;
2586
2587             printf (_("\nVersion needs section '%s' contains %ld entries:\n"),
2588                     SECTION_NAME (section), section->sh_info);
2589
2590             printf (_(" Addr: 0x"));
2591             printf_vma (section->sh_addr);
2592             printf (_("  Offset: %#08lx  Link to section: %ld (%s)\n"),
2593                     section->sh_offset, section->sh_link,
2594                     SECTION_NAME (section_headers + section->sh_link));
2595
2596             GET_DATA_ALLOC (section->sh_offset, section->sh_size,
2597                             eneed, Elf_External_Verneed *,
2598                             "version need section");
2599
2600             for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
2601               {
2602                 Elf_External_Verneed * entry;
2603                 Elf_Internal_Verneed     ent;
2604                 int                      j;
2605                 int                      isum;
2606                 char *                   vstart;
2607
2608                 vstart = ((char *) eneed) + idx;
2609
2610                 entry = (Elf_External_Verneed *) vstart;
2611
2612                 ent.vn_version = BYTE_GET (entry->vn_version);
2613                 ent.vn_cnt     = BYTE_GET (entry->vn_cnt);
2614                 ent.vn_file    = BYTE_GET (entry->vn_file);
2615                 ent.vn_aux     = BYTE_GET (entry->vn_aux);
2616                 ent.vn_next    = BYTE_GET (entry->vn_next);
2617
2618                 printf (_("  %#06x: Version: %d"), idx, ent.vn_version);
2619
2620                 if (dynamic_strings)
2621                   printf (_("  File: %s"), dynamic_strings + ent.vn_file);
2622                 else
2623                   printf (_("  File: %lx"), ent.vn_file);
2624
2625                 printf (_("  Cnt: %d\n"), ent.vn_cnt);
2626
2627                 vstart += ent.vn_aux;
2628
2629                 for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j)
2630                   {
2631                     Elf_External_Vernaux * eaux;
2632                     Elf_Internal_Vernaux   aux;
2633
2634                     eaux = (Elf_External_Vernaux *) vstart;
2635
2636                     aux.vna_hash  = BYTE_GET (eaux->vna_hash);
2637                     aux.vna_flags = BYTE_GET (eaux->vna_flags);
2638                     aux.vna_other = BYTE_GET (eaux->vna_other);
2639                     aux.vna_name  = BYTE_GET (eaux->vna_name);
2640                     aux.vna_next  = BYTE_GET (eaux->vna_next);
2641
2642                     if (dynamic_strings)
2643                       printf (_("  %#06x: Name: %s"),
2644                               isum, dynamic_strings + aux.vna_name);
2645                     else
2646                       printf (_("  %#06x: Name index: %lx"),
2647                               isum, aux.vna_name);
2648
2649                     printf (_("  Flags: %s  Version: %d\n"),
2650                             get_ver_flags (aux.vna_flags), aux.vna_other);
2651
2652                     isum   += aux.vna_next;
2653                     vstart += aux.vna_next;
2654                   }
2655
2656                 idx += ent.vn_next;
2657               }
2658             
2659             free (eneed);
2660           }
2661           break;
2662
2663         case SHT_GNU_versym:
2664           {
2665             Elf32_Internal_Shdr *       link_section;
2666             int                         total;
2667             int                         cnt;
2668             unsigned char *             edata;
2669             unsigned short *            data;
2670             char *                      strtab;
2671             Elf_Internal_Sym *          symbols;
2672             Elf32_Internal_Shdr *       string_sec;
2673
2674             link_section = section_headers + section->sh_link;
2675             total = section->sh_size / section->sh_entsize;
2676
2677             found = 1;
2678
2679             symbols = get_elf_symbols
2680               (file, link_section->sh_offset,
2681                link_section->sh_size / link_section->sh_entsize);
2682
2683             string_sec = section_headers + link_section->sh_link;
2684
2685             GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
2686                             strtab, char *, "version string table");
2687
2688             printf (_("\nVersion symbols section '%s' contains %d entries:\n"),
2689                     SECTION_NAME (section), total);
2690
2691             printf (_(" Addr: "));
2692             printf_vma (section->sh_addr);
2693             printf (_("  Offset: %#08lx  Link: %lx (%s)\n"),
2694                     section->sh_offset, section->sh_link,
2695                     SECTION_NAME (link_section));
2696
2697             GET_DATA_ALLOC (version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
2698                             - loadaddr,
2699                             total * sizeof (short), edata,
2700                             unsigned char *, "version symbol data");
2701
2702             data = (unsigned short *) malloc (total * sizeof (short));
2703
2704             for (cnt = total; cnt --;)
2705               data [cnt] = byte_get (edata + cnt * sizeof (short),
2706                                      sizeof (short));
2707
2708             free (edata);
2709
2710             for (cnt = 0; cnt < total; cnt += 4)
2711               {
2712                 int j, nn;
2713
2714                 printf ("  %03x:", cnt);
2715
2716                 for (j = 0; (j < 4) && (cnt + j) < total; ++j)
2717                   switch (data [cnt + j])
2718                     {
2719                     case 0:
2720                       fputs (_("   0 (*local*)    "), stdout);
2721                       break;
2722
2723                     case 1:
2724                       fputs (_("   1 (*global*)   "), stdout);
2725                       break;
2726
2727                     default:
2728                       nn = printf ("%4x%c", data [cnt + j] & 0x7fff,
2729                                    data [cnt + j] & 0x8000 ? 'h' : ' ');
2730
2731                       if (symbols [cnt + j].st_shndx < SHN_LORESERVE
2732                           && section_headers[symbols [cnt + j].st_shndx].sh_type
2733                           == SHT_NOBITS)
2734                         {
2735                           /* We must test both.  */
2736                           Elf_Internal_Verneed     ivn;
2737                           unsigned long            offset;
2738
2739                           offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
2740                             - loadaddr;
2741
2742                           do
2743                             {
2744                               Elf_External_Verneed   evn;
2745                               Elf_External_Vernaux   evna;
2746                               Elf_Internal_Vernaux     ivna;
2747                               unsigned long            vna_off;
2748
2749                               GET_DATA (offset, evn, "version need");
2750
2751                               ivn.vn_aux  = BYTE_GET (evn.vn_aux);
2752                               ivn.vn_next = BYTE_GET (evn.vn_next);
2753
2754                               vna_off = offset + ivn.vn_aux;
2755
2756                               do
2757                                 {
2758                                   GET_DATA (vna_off, evna,
2759                                             "version need aux (1)");
2760
2761                                   ivna.vna_next  = BYTE_GET (evna.vna_next);
2762                                   ivna.vna_other = BYTE_GET (evna.vna_other);
2763
2764                                   vna_off += ivna.vna_next;
2765                                 }
2766                               while (ivna.vna_other != data [cnt + j]
2767                                      && ivna.vna_next != 0);
2768
2769                               if (ivna.vna_other == data [cnt + j])
2770                                 {
2771                                   ivna.vna_name = BYTE_GET (evna.vna_name);
2772
2773                                   nn += printf ("(%s%-*s",
2774                                                 strtab + ivna.vna_name,
2775                                                 12 - strlen (strtab
2776                                                              + ivna.vna_name),
2777                                                 ")");
2778                                   break;
2779                                 }
2780                               else if (ivn.vn_next == 0)
2781                                 {
2782                                   if (data [cnt + j] != 0x8001)
2783                                     {
2784                                       Elf_Internal_Verdef  ivd;
2785                                       Elf_External_Verdef  evd;
2786
2787                                       offset = version_info
2788                                         [DT_VERSIONTAGIDX (DT_VERDEF)]
2789                                         - loadaddr;
2790
2791                                       do
2792                                         {
2793                                           GET_DATA (offset, evd,
2794                                                     "version definition");
2795
2796                                           ivd.vd_next = BYTE_GET (evd.vd_next);
2797                                           ivd.vd_ndx  = BYTE_GET (evd.vd_ndx);
2798
2799                                           offset += ivd.vd_next;
2800                                         }
2801                                       while (ivd.vd_ndx
2802                                              != (data [cnt + j] & 0x7fff)
2803                                              && ivd.vd_next != 0);
2804
2805                                       if (ivd.vd_ndx
2806                                           == (data [cnt + j] & 0x7fff))
2807                                         {
2808                                           Elf_External_Verdaux  evda;
2809                                           Elf_Internal_Verdaux  ivda;
2810
2811                                           ivd.vd_aux = BYTE_GET (evd.vd_aux);
2812
2813                                           GET_DATA (offset + ivd.vd_aux, evda,
2814                                                     "version definition aux");
2815
2816                                           ivda.vda_name =
2817                                             BYTE_GET (evda.vda_name);
2818
2819                                           nn +=
2820                                             printf ("(%s%-*s",
2821                                                     strtab + ivda.vda_name,
2822                                                     12
2823                                                     - strlen (strtab
2824                                                               + ivda.vda_name),
2825                                                     ")");
2826                                         }
2827                                     }
2828
2829                                   break;
2830                                 }
2831                               else
2832                                 offset += ivn.vn_next;
2833                             }
2834                           while (ivn.vn_next);
2835                         }
2836                       else if (symbols [cnt + j].st_shndx == SHN_UNDEF)
2837                         {
2838                           Elf_Internal_Verneed     ivn;
2839                           unsigned long            offset;
2840
2841                           offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
2842                             - loadaddr;
2843
2844                           do
2845                             {
2846                               Elf_Internal_Vernaux     ivna;
2847                               Elf_External_Verneed   evn;
2848                               Elf_External_Vernaux   evna;
2849                               unsigned long            a_off;
2850
2851                               GET_DATA (offset, evn, "version need");
2852
2853                               ivn.vn_aux  = BYTE_GET (evn.vn_aux);
2854                               ivn.vn_next = BYTE_GET (evn.vn_next);
2855
2856                               a_off = offset + ivn.vn_aux;
2857
2858                               do
2859                                 {
2860                                   GET_DATA (a_off, evna,
2861                                             "version need aux (2)");
2862
2863                                   ivna.vna_next  = BYTE_GET (evna.vna_next);
2864                                   ivna.vna_other = BYTE_GET (evna.vna_other);
2865
2866                                   a_off += ivna.vna_next;
2867                                 }
2868                               while (ivna.vna_other != data [cnt + j]
2869                                      && ivna.vna_next != 0);
2870
2871                               if (ivna.vna_other == data [cnt + j])
2872                                 {
2873                                   ivna.vna_name = BYTE_GET (evna.vna_name);
2874
2875                                   nn += printf ("(%s%-*s",
2876                                                 strtab + ivna.vna_name,
2877                                                 12 - strlen (strtab
2878                                                              + ivna.vna_name),
2879                                                 ")");
2880                                   break;
2881                                 }
2882
2883                               offset += ivn.vn_next;
2884                             }
2885                           while (ivn.vn_next);
2886                         }
2887                       else if (data [cnt + j] != 0x8001)
2888                         {
2889                           Elf_Internal_Verdef  ivd;
2890                           Elf_External_Verdef  evd;
2891                           unsigned long        offset;
2892
2893                           offset = version_info
2894                             [DT_VERSIONTAGIDX (DT_VERDEF)] - loadaddr;
2895
2896                           do
2897                             {
2898                               GET_DATA (offset, evd, "version def");
2899
2900                               ivd.vd_next = BYTE_GET (evd.vd_next);
2901                               ivd.vd_ndx  = BYTE_GET (evd.vd_ndx);
2902
2903                               offset += ivd.vd_next;
2904                             }
2905                           while (ivd.vd_ndx != (data [cnt + j] & 0x7fff)
2906                                  && ivd.vd_next != 0);
2907
2908                           if (ivd.vd_ndx == (data [cnt + j] & 0x7fff))
2909                             {
2910                               Elf_External_Verdaux  evda;
2911                               Elf_Internal_Verdaux  ivda;
2912
2913                               ivd.vd_aux = BYTE_GET (evd.vd_aux);
2914
2915                               GET_DATA (offset - ivd.vd_next + ivd.vd_aux,
2916                                         evda, "version def aux");
2917
2918                               ivda.vda_name = BYTE_GET (evda.vda_name);
2919
2920                               nn += printf ("(%s%-*s",
2921                                             strtab + ivda.vda_name,
2922                                             12 - strlen (strtab
2923                                                          + ivda.vda_name),
2924                                             ")");
2925                             }
2926                         }
2927
2928                       if (nn < 18)
2929                         printf ("%*c", 18 - nn, ' ');
2930                     }
2931
2932                 putchar ('\n');
2933               }
2934
2935             free (data);
2936             free (strtab);
2937             free (symbols);
2938           }
2939           break;
2940         
2941         default:
2942           break;
2943         }
2944     }
2945
2946   if (! found)
2947     printf (_("\nNo version information found in this file.\n"));
2948
2949   return 1;
2950 }
2951
2952 static char *
2953 get_symbol_binding (binding)
2954      unsigned int binding;
2955 {
2956   static char buff [32];
2957
2958   switch (binding)
2959     {
2960     case STB_LOCAL:  return _("LOCAL");
2961     case STB_GLOBAL: return _("GLOBAL");
2962     case STB_WEAK:   return _("WEAK");
2963     default:
2964       if (binding >= STB_LOPROC && binding <= STB_HIPROC)
2965         sprintf (buff, _("<processor specific>: %d"), binding);
2966       else if (binding >= STB_LOOS && binding <= STB_HIOS)
2967         sprintf (buff, _("<OS specific>: %d"), binding);
2968       else
2969         sprintf (buff, _("<unknown>: %d"), binding);
2970       return buff;
2971     }
2972 }
2973
2974 static char *
2975 get_symbol_type (type)
2976      unsigned int type;
2977 {
2978   static char buff [32];
2979
2980   switch (type)
2981     {
2982     case STT_NOTYPE:   return _("NOTYPE");
2983     case STT_OBJECT:   return _("OBJECT");
2984     case STT_FUNC:     return _("FUNC");
2985     case STT_SECTION:  return _("SECTION");
2986     case STT_FILE:     return _("FILE");
2987     default:
2988       if (type >= STT_LOPROC && type <= STT_HIPROC)
2989         sprintf (buff, _("<processor specific>: %d"), type);
2990       else if (type >= STT_LOOS && type <= STT_HIOS)
2991         sprintf (buff, _("<OS specific>: %d"), type);
2992       else
2993         sprintf (buff, _("<unknown>: %d"), type);
2994       return buff;
2995     }
2996 }
2997
2998 static char *
2999 get_symbol_index_type (type)
3000      unsigned int type;
3001 {
3002   switch (type)
3003     {
3004     case SHN_UNDEF:  return "UND";
3005     case SHN_ABS:    return "ABS";
3006     case SHN_COMMON: return "COM";
3007     default:
3008       if (type >= SHN_LOPROC && type <= SHN_HIPROC)
3009         return "PRC";
3010       else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE)
3011         return "RSV";
3012       else if (type >= SHN_LOOS && type <= SHN_HIOS)
3013         return "OS ";
3014       else
3015         {
3016           static char buff [32];
3017
3018           sprintf (buff, "%3d", type);
3019           return buff;
3020         }
3021     }
3022 }
3023
3024
3025 static int *
3026 get_dynamic_data (file, number)
3027      FILE *       file;
3028      unsigned int number;
3029 {
3030   char * e_data;
3031   int *  i_data;
3032
3033   e_data = (char *) malloc (number * 4);
3034
3035   if (e_data == NULL)
3036     {
3037       error (_("Out of memory\n"));
3038       return NULL;
3039     }
3040
3041   if (fread (e_data, 4, number, file) != number)
3042     {
3043       error (_("Unable to read in dynamic data\n"));
3044       return NULL;
3045     }
3046
3047   i_data = (int *) malloc (number * sizeof (* i_data));
3048
3049   if (i_data == NULL)
3050     {
3051       error (_("Out of memory\n"));
3052       free (e_data);
3053       return NULL;
3054     }
3055
3056   while (number--)
3057     i_data [number] = byte_get (e_data + number * 4, 4);
3058
3059   free (e_data);
3060
3061   return i_data;
3062 }
3063
3064 /* Dump the symbol table */
3065 static int
3066 process_symbol_table (file)
3067      FILE * file;
3068 {
3069   Elf32_Internal_Shdr *   section;
3070   char   nb [4];
3071   char   nc [4];
3072   int    nbuckets;
3073   int    nchains;
3074   int *  buckets = NULL;
3075   int *  chains = NULL;
3076
3077   if (! do_syms && !do_histogram)
3078     return 1;
3079
3080   if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL)
3081                                 || do_histogram))
3082     {
3083       if (fseek (file, dynamic_info[DT_HASH] - loadaddr, SEEK_SET))
3084         {
3085           error (_("Unable to seek to start of dynamic information"));
3086           return 0;
3087         }
3088
3089       if (fread (nb, sizeof (nb), 1, file) != 1)
3090         {
3091           error (_("Failed to read in number of buckets\n"));
3092           return 0;
3093         }
3094
3095       if (fread (nc, sizeof (nc), 1, file) != 1)
3096         {
3097           error (_("Failed to read in number of chains\n"));
3098           return 0;
3099         }
3100
3101       nbuckets = byte_get (nb, 4);
3102       nchains  = byte_get (nc, 4);
3103
3104       buckets = get_dynamic_data (file, nbuckets);
3105       chains  = get_dynamic_data (file, nchains);
3106
3107       if (buckets == NULL || chains == NULL)
3108         return 0;
3109     }
3110
3111   if (do_syms
3112       && dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL)
3113     {
3114       int    hn;
3115       int    si;
3116
3117       printf (_("\nSymbol table for image:\n"));
3118       printf (_("  Num Buc:    Value  Size   Type   Bind Ot Ndx Name\n"));
3119
3120       for (hn = 0; hn < nbuckets; hn++)
3121         {
3122           if (! buckets [hn])
3123             continue;
3124
3125           for (si = buckets [hn]; si; si = chains [si])
3126             {
3127               Elf_Internal_Sym * psym;
3128
3129               psym = dynamic_symbols + si;
3130
3131               printf ("  %3d %3d: %8lx %5ld %6s %6s %2d ",
3132                       si, hn,
3133                       (unsigned long) psym->st_value,
3134                       (unsigned long) psym->st_size,
3135                       get_symbol_type (ELF_ST_TYPE (psym->st_info)),
3136                       get_symbol_binding (ELF_ST_BIND (psym->st_info)),
3137                       psym->st_other);
3138
3139               printf ("%3.3s", get_symbol_index_type (psym->st_shndx));
3140
3141               printf (" %s\n", dynamic_strings + psym->st_name);
3142             }
3143         }
3144     }
3145   else if (do_syms && !do_using_dynamic)
3146     {
3147       unsigned int     i;
3148
3149       for (i = 0, section = section_headers;
3150            i < elf_header.e_shnum;
3151            i++, section++)
3152         {
3153           unsigned int          si;
3154           char *                strtab;
3155           Elf_Internal_Sym *    symtab;
3156           Elf_Internal_Sym *    psym;
3157
3158
3159           if (   section->sh_type != SHT_SYMTAB
3160               && section->sh_type != SHT_DYNSYM)
3161             continue;
3162
3163           printf (_("\nSymbol table '%s' contains %lu entries:\n"),
3164                   SECTION_NAME (section),
3165                   (unsigned long) (section->sh_size / section->sh_entsize));
3166           fputs (_("  Num:    Value  Size Type    Bind   Ot  Ndx Name\n"),
3167                  stdout);
3168
3169           symtab = get_elf_symbols (file, section->sh_offset,
3170                                     section->sh_size / section->sh_entsize);
3171           if (symtab == NULL)
3172             continue;
3173
3174           if (section->sh_link == elf_header.e_shstrndx)
3175             strtab = string_table;
3176           else
3177             {
3178               Elf32_Internal_Shdr * string_sec;
3179
3180               string_sec = section_headers + section->sh_link;
3181
3182               GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
3183                               strtab, char *, "string table");
3184             }
3185
3186           for (si = 0, psym = symtab;
3187                si < section->sh_size / section->sh_entsize;
3188                si ++, psym ++)
3189             {
3190               printf ("  %3d: %8lx %5ld %-7s %-6s %2d ",
3191                       si,
3192                       (unsigned long) psym->st_value,
3193                       (unsigned long) psym->st_size,
3194                       get_symbol_type (ELF_ST_TYPE (psym->st_info)),
3195                       get_symbol_binding (ELF_ST_BIND (psym->st_info)),
3196                       psym->st_other);
3197
3198               if (psym->st_shndx == 0)
3199                 fputs (" UND", stdout);
3200               else if ((psym->st_shndx & 0xffff) == 0xfff1)
3201                 fputs (" ABS", stdout);
3202               else if ((psym->st_shndx & 0xffff) == 0xfff2)
3203                 fputs (" COM", stdout);
3204               else
3205                 printf ("%4x", psym->st_shndx);
3206
3207               printf (" %s", strtab + psym->st_name);
3208
3209               if (section->sh_type == SHT_DYNSYM &&
3210                   version_info [DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
3211                 {
3212                   unsigned char   data[2];
3213                   unsigned short  vers_data;
3214                   unsigned long   offset;
3215                   int             is_nobits;
3216                   int             check_def;
3217
3218                   offset = version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
3219                     - loadaddr;
3220
3221                   GET_DATA (offset + si * sizeof (vers_data), data,
3222                             "version data");
3223
3224                   vers_data = byte_get (data, 2);
3225
3226                   is_nobits = psym->st_shndx < SHN_LORESERVE ?
3227                     (section_headers [psym->st_shndx].sh_type == SHT_NOBITS)
3228                     : 0;
3229
3230                   check_def = (psym->st_shndx != SHN_UNDEF);
3231
3232                   if ((vers_data & 0x8000) || vers_data > 1)
3233                     {
3234                       if (is_nobits || ! check_def)
3235                         {
3236                           Elf_External_Verneed  evn;
3237                           Elf_Internal_Verneed  ivn;
3238                           Elf_Internal_Vernaux  ivna;
3239
3240                           /* We must test both.  */
3241                           offset = version_info
3242                             [DT_VERSIONTAGIDX (DT_VERNEED)] - loadaddr;
3243
3244                           GET_DATA (offset, evn, "version need");
3245
3246                           ivn.vn_aux  = BYTE_GET (evn.vn_aux);
3247                           ivn.vn_next = BYTE_GET (evn.vn_next);
3248
3249                           do
3250                             {
3251                               unsigned long  vna_off;
3252
3253                               vna_off = offset + ivn.vn_aux;
3254
3255                               do
3256                                 {
3257                                   Elf_External_Vernaux  evna;
3258
3259                                   GET_DATA (vna_off, evna,
3260                                             "version need aux (3)");
3261
3262                                   ivna.vna_other = BYTE_GET (evna.vna_other);
3263                                   ivna.vna_next  = BYTE_GET (evna.vna_next);
3264                                   ivna.vna_name  = BYTE_GET (evna.vna_name);
3265
3266                                   vna_off += ivna.vna_next;
3267                                 }
3268                               while (ivna.vna_other != vers_data
3269                                      && ivna.vna_next != 0);
3270
3271                               if (ivna.vna_other == vers_data)
3272                                 break;
3273
3274                               offset += ivn.vn_next;
3275                             }
3276                           while (ivn.vn_next != 0);
3277
3278                           if (ivna.vna_other == vers_data)
3279                             {
3280                               printf ("@%s (%d)",
3281                                       strtab + ivna.vna_name, ivna.vna_other);
3282                               check_def = 0;
3283                             }
3284                           else if (! is_nobits)
3285                             error (_("bad dynamic symbol"));
3286                           else
3287                             check_def = 1;
3288                         }
3289
3290                       if (check_def)
3291                         {
3292                           if (vers_data != 0x8001)
3293                             {
3294                               Elf_Internal_Verdef     ivd;
3295                               Elf_Internal_Verdaux    ivda;
3296                               Elf_External_Verdaux  evda;
3297                               unsigned long           offset;
3298
3299                               offset =
3300                                 version_info [DT_VERSIONTAGIDX (DT_VERDEF)]
3301                                 - loadaddr;
3302
3303                               do
3304                                 {
3305                                   Elf_External_Verdef   evd;
3306
3307                                   GET_DATA (offset, evd, "version def");
3308
3309                                   ivd.vd_ndx  = BYTE_GET (evd.vd_ndx);
3310                                   ivd.vd_aux  = BYTE_GET (evd.vd_aux);
3311                                   ivd.vd_next = BYTE_GET (evd.vd_next);
3312
3313                                   offset += ivd.vd_next;
3314                                 }
3315                               while (ivd.vd_ndx != (vers_data & 0x7fff)
3316                                      && ivd.vd_next != 0);
3317
3318                               offset -= ivd.vd_next;
3319                               offset += ivd.vd_aux;
3320
3321                               GET_DATA (offset, evda, "version def aux");
3322
3323                               ivda.vda_name = BYTE_GET (evda.vda_name);
3324
3325                               if (psym->st_name != ivda.vda_name)
3326                                 printf ((vers_data & 0x8000)
3327                                         ? "@%s" : "@@%s",
3328                                         strtab + ivda.vda_name);
3329                             }
3330                         }
3331                     }
3332                 }
3333
3334               putchar ('\n');
3335             }
3336
3337           free (symtab);
3338           if (strtab != string_table)
3339             free (strtab);
3340         }
3341     }
3342   else if (do_syms)
3343     printf
3344       (_("\nDynamic symbol information is not available for displaying symbols.\n"));
3345
3346   if (do_histogram && buckets != NULL)
3347     {
3348       int *lengths;
3349       int *counts;
3350       int hn;
3351       int si;
3352       int maxlength = 0;
3353       int nzero_counts = 0;
3354       int nsyms = 0;
3355
3356       printf (_("\nHistogram for bucket list length (total of %d buckets):\n"),
3357               nbuckets);
3358       printf (_(" Length  Number     %% of total  Coverage\n"));
3359
3360       lengths = (int *) calloc (nbuckets, sizeof (int));
3361       if (lengths == NULL)
3362         {
3363           error (_("Out of memory"));
3364           return 0;
3365         }
3366       for (hn = 0; hn < nbuckets; ++hn)
3367         {
3368           if (! buckets [hn])
3369             continue;
3370
3371           for (si = buckets[hn]; si; si = chains[si])
3372             {
3373               ++nsyms;
3374               if (maxlength < ++lengths[hn])
3375                 ++maxlength;
3376             }
3377         }
3378
3379       counts = (int *) calloc (maxlength + 1, sizeof (int));
3380       if (counts == NULL)
3381         {
3382           error (_("Out of memory"));
3383           return 0;
3384         }
3385
3386       for (hn = 0; hn < nbuckets; ++hn)
3387         ++ counts [lengths [hn]];
3388
3389       printf ("      0  %-10d (%5.1f%%)\n",
3390               counts[0], (counts[0] * 100.0) / nbuckets);
3391       for (si = 1; si <= maxlength; ++si)
3392         {
3393           nzero_counts += counts[si] * si;
3394           printf ("%7d  %-10d (%5.1f%%)    %5.1f%%\n",
3395                   si, counts[si], (counts[si] * 100.0) / nbuckets,
3396                   (nzero_counts * 100.0) / nsyms);
3397         }
3398
3399       free (counts);
3400       free (lengths);
3401     }
3402
3403   if (buckets != NULL)
3404     {
3405       free (buckets);
3406       free (chains);
3407     }
3408
3409   return 1;
3410 }
3411
3412 static int
3413 process_syminfo (file)
3414      FILE * file;
3415 {
3416   int i;
3417
3418   if (dynamic_syminfo == NULL
3419       || !do_dynamic)
3420     /* No syminfo, this is ok.  */
3421     return 1;
3422
3423   /* There better should be a dynamic symbol section.  */
3424   if (dynamic_symbols == NULL || dynamic_strings == NULL)
3425     return 0;
3426
3427   if (dynamic_addr)
3428     printf (_("\nDynamic info segment at offset 0x%lx contains %d entries:\n"),
3429             dynamic_syminfo_offset, dynamic_syminfo_nent);
3430
3431   printf (_(" Num: Name                           BoundTo     Flags\n"));
3432   for (i = 0; i < dynamic_syminfo_nent; ++i)
3433     {
3434       unsigned short int flags = dynamic_syminfo[i].si_flags;
3435
3436       printf ("%4d: %-30s ", i,
3437               dynamic_strings + dynamic_symbols[i].st_name);
3438
3439       switch (dynamic_syminfo[i].si_boundto)
3440         {
3441         case SYMINFO_BT_SELF:
3442           fputs ("SELF       ", stdout);
3443           break;
3444         case SYMINFO_BT_PARENT:
3445           fputs ("PARENT     ", stdout);
3446           break;
3447         default:
3448           if (dynamic_syminfo[i].si_boundto > 0
3449               && dynamic_syminfo[i].si_boundto < dynamic_size)
3450             printf ("%-10s ",
3451                     dynamic_strings
3452                     + dynamic_segment[dynamic_syminfo[i].si_boundto].d_un.d_val);
3453           else
3454             printf ("%-10d ", dynamic_syminfo[i].si_boundto);
3455           break;
3456         }
3457
3458       if (flags & SYMINFO_FLG_DIRECT)
3459         printf (" DIRECT");
3460       if (flags & SYMINFO_FLG_PASSTHRU)
3461         printf (" PASSTHRU");
3462       if (flags & SYMINFO_FLG_COPY)
3463         printf (" COPY");
3464       if (flags & SYMINFO_FLG_LAZYLOAD)
3465         printf (" LAZYLOAD");
3466
3467       puts ("");
3468     }
3469
3470   return 1;
3471 }
3472
3473 #ifdef SUPPORT_DISASSEMBLY
3474 static void
3475 disassemble_section (section, file)
3476      Elf32_Internal_Shdr * section;
3477      FILE * file;
3478 {
3479   printf (_("\nAssembly dump of section %s\n"),
3480           SECTION_NAME (section));
3481
3482   /* XXX -- to be done --- XXX */
3483
3484   return 1;
3485 }
3486 #endif
3487
3488 static int
3489 dump_section (section, file)
3490      Elf32_Internal_Shdr * section;
3491      FILE * file;
3492 {
3493   int             bytes;
3494   int             addr;
3495   unsigned char * data;
3496   unsigned char * start;
3497
3498   bytes = section->sh_size;
3499
3500   if (bytes == 0)
3501     {
3502       printf (_("\nSection '%s' has no data to dump.\n"),
3503               SECTION_NAME (section));
3504       return 0;
3505     }
3506   else
3507     printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section));
3508
3509   addr = section->sh_addr;
3510
3511   GET_DATA_ALLOC (section->sh_offset, bytes, start, unsigned char *,
3512                   "section data");
3513
3514   data = start;
3515
3516   while (bytes)
3517     {
3518       int j;
3519       int k;
3520       int lbytes;
3521
3522       lbytes = (bytes > 16 ? 16 : bytes);
3523
3524       printf ("  0x%8.8x ", addr);
3525
3526       switch (elf_header.e_ident [EI_DATA])
3527         {
3528         case ELFDATA2LSB:
3529           for (j = 15; j >= 0; j --)
3530             {
3531               if (j < lbytes)
3532                 printf ("%2.2x", data [j]);
3533               else
3534                 printf ("  ");
3535
3536               if (!(j & 0x3))
3537                 printf (" ");
3538             }
3539           break;
3540
3541         case ELFDATA2MSB:
3542           for (j = 0; j < 16; j++)
3543             {
3544               if (j < lbytes)
3545                 printf ("%2.2x", data [j]);
3546               else
3547                 printf ("  ");
3548
3549               if ((j & 3) == 3)
3550                 printf (" ");
3551             }
3552           break;
3553         }
3554
3555       for (j = 0; j < lbytes; j++)
3556         {
3557           k = data [j];
3558           if (k >= ' ' && k < 0x80)
3559             printf ("%c", k);
3560           else
3561             printf (".");
3562         }
3563
3564       putchar ('\n');
3565
3566       data  += lbytes;
3567       addr  += lbytes;
3568       bytes -= lbytes;
3569     }
3570
3571   free (start);
3572
3573   return 1;
3574 }
3575
3576
3577 static unsigned long int
3578 read_leb128 (data, length_return, sign)
3579      unsigned char * data;
3580      int *           length_return;
3581      int             sign;
3582 {
3583   unsigned long int result = 0;
3584   unsigned int      num_read = 0;
3585   int               shift = 0;
3586   unsigned char     byte;
3587
3588   do
3589     {
3590       byte = * data ++;
3591       num_read ++;
3592
3593       result |= (byte & 0x7f) << shift;
3594
3595       shift += 7;
3596
3597     }
3598   while (byte & 0x80);
3599
3600   if (length_return != NULL)
3601     * length_return = num_read;
3602
3603   if (sign && (shift < 32) && (byte & 0x40))
3604     result |= -1 << shift;
3605
3606   return result;
3607 }
3608
3609 typedef struct State_Machine_Registers
3610 {
3611   unsigned long address;
3612   unsigned int  file;
3613   unsigned int  line;
3614   unsigned int  column;
3615   int           is_stmt;
3616   int           basic_block;
3617   int           end_sequence;
3618 /* This variable hold the number of the last entry seen
3619    in the File Table.  */
3620   unsigned int  last_file_entry;
3621 } SMR;
3622
3623 static SMR state_machine_regs;
3624
3625 static void
3626 reset_state_machine (is_stmt)
3627      int is_stmt;
3628 {
3629   state_machine_regs.address = 0;
3630   state_machine_regs.file = 1;
3631   state_machine_regs.line = 1;
3632   state_machine_regs.column = 0;
3633   state_machine_regs.is_stmt = is_stmt;
3634   state_machine_regs.basic_block = 0;
3635   state_machine_regs.end_sequence = 0;
3636   state_machine_regs.last_file_entry = 0;
3637 }
3638
3639 /* Handled an extend line op.  Returns true if this is the end
3640    of sequence.  */
3641 static int
3642 process_extended_line_op (data, is_stmt)
3643      unsigned char * data;
3644      int is_stmt;
3645 {
3646   unsigned char   op_code;
3647   int             bytes_read;
3648   unsigned int    len;
3649   unsigned char * name;
3650   unsigned long   adr;
3651   
3652   len = read_leb128 (data, & bytes_read, 0);
3653   data += bytes_read;
3654
3655   if (len == 0)
3656     {
3657       warn (_("badly formed extended line op encountered!"));
3658       return bytes_read;
3659     }
3660
3661   len += bytes_read;
3662   op_code = * data ++;
3663
3664   printf (_("  Extended opcode %d: "), op_code);
3665   
3666   switch (op_code)
3667     {
3668     case DW_LNE_end_sequence:
3669       printf (_("End of Sequence\n\n"));
3670       reset_state_machine (is_stmt);
3671       break;
3672
3673     case DW_LNE_set_address:
3674       /* XXX - assumption here that address size is 4! */
3675       adr = byte_get (data, 4);
3676       printf (_("set Address to 0x%lx\n"), adr);
3677       state_machine_regs.address = adr;
3678       break;
3679
3680     case DW_LNE_define_file:
3681       printf (_("  define new File Table entry\n"));
3682       printf (_("  Entry\tDir\tTime\tSize\tName\n"));
3683          
3684       printf (_("   %d\t"), ++ state_machine_regs.last_file_entry);
3685       name = data;
3686       data += strlen (data) + 1;
3687       printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
3688       data += bytes_read;
3689       printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
3690       data += bytes_read;
3691       printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
3692       printf (_("%s\n\n"), name);
3693       break;
3694
3695     default:
3696       printf (_("UNKNOWN: length %d\n"), len - bytes_read);
3697       break;
3698     }
3699
3700   return len;
3701 }
3702
3703
3704 static int
3705 display_debug_lines (section, start, file)
3706      Elf32_Internal_Shdr * section;
3707      unsigned char *       start;
3708      FILE *                file;
3709 {
3710   DWARF2_External_LineInfo * external;
3711   DWARF2_Internal_LineInfo   info;
3712   unsigned char *            standard_opcodes;
3713   unsigned char *            data = start;
3714   unsigned char *            end  = start + section->sh_size;
3715   unsigned char *            end_of_sequence;
3716   int                        i;
3717
3718   printf (_("\nDump of debug contents of section %s:\n\n"),
3719           SECTION_NAME (section));
3720
3721   while (data < end)
3722     {
3723       external = (DWARF2_External_LineInfo *) data;
3724
3725       /* Check the length of the block.  */
3726       info.li_length = BYTE_GET (external->li_length);
3727       if (info.li_length > section->sh_size)
3728         {
3729           warn
3730             (_("The line info appears to be corrupt - the section is too small\n"));
3731           return 0;
3732         }
3733       
3734       /* Check its version number.  */
3735       info.li_version = BYTE_GET (external->li_version);
3736       if (info.li_version != 2)
3737         {
3738           warn (_("Only DWARF version 2 line info is currently supported.\n"));
3739           return 0;
3740         }
3741       
3742       info.li_prologue_length = BYTE_GET (external->li_prologue_length);
3743       info.li_min_insn_length = BYTE_GET (external->li_min_insn_length);
3744       info.li_default_is_stmt = BYTE_GET (external->li_default_is_stmt);
3745       info.li_line_base       = BYTE_GET (external->li_line_base);
3746       info.li_line_range      = BYTE_GET (external->li_line_range);
3747       info.li_opcode_base     = BYTE_GET (external->li_opcode_base);
3748       
3749       /* Sign extend the line base field.  */
3750       info.li_line_base <<= 24;
3751       info.li_line_base >>= 24;
3752       
3753       printf (_("  Length:                      %ld\n"), info.li_length);
3754       printf (_("  DWARF Version:               %d\n"), info.li_version);
3755       printf (_("  Prolgue Length:              %d\n"), info.li_prologue_length);
3756       printf (_("  Minimum Instruction Length:  %d\n"), info.li_min_insn_length);
3757       printf (_("  Initial value of 'is_stmt':  %d\n"), info.li_default_is_stmt);
3758       printf (_("  Line Base:                   %d\n"), info.li_line_base);
3759       printf (_("  Line Range:                  %d\n"), info.li_line_range);
3760       printf (_("  Opcode Base:                 %d\n"), info.li_opcode_base);
3761
3762       end_of_sequence = data + info.li_length + sizeof (info.li_length);
3763
3764       reset_state_machine (info.li_default_is_stmt);
3765       
3766       /* Display the contents of the Opcodes table.  */
3767       standard_opcodes = data + sizeof (* external);
3768       
3769       printf (_("\n Opcodes:\n"));
3770       
3771       for (i = 1; i < info.li_opcode_base; i++)
3772         printf (_("  Opcode %d has %d args\n"), i, standard_opcodes[i]);
3773       
3774       /* Display the contents of the Directory table.  */
3775       data = standard_opcodes + info.li_opcode_base - 1;
3776       
3777       if (* data == 0)
3778         printf (_("\n The Directory Table is empty.\n"));
3779       else
3780         {
3781           printf (_("\n The Directory Table:\n"));
3782           
3783           while (* data != 0)
3784             {
3785               printf (_("  %s\n"), data);
3786               
3787               data += strlen (data) + 1;
3788             }
3789         }
3790       
3791       /* Skip the NUL at the end of the table.  */
3792       data ++;
3793       
3794       /* Display the contents of the File Name table.  */
3795       if (* data == 0)
3796         printf (_("\n The File Name Table is empty.\n"));
3797       else
3798         {
3799           printf (_("\n The File Name Table:\n"));
3800           printf (_("  Entry\tDir\tTime\tSize\tName\n"));
3801           
3802           while (* data != 0)
3803             {
3804               char * name;
3805               int bytes_read;
3806               
3807               printf (_("  %d\t"), ++ state_machine_regs.last_file_entry);
3808               name = data;
3809               
3810               data += strlen (data) + 1;
3811               
3812               printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
3813               data += bytes_read;
3814               printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
3815               data += bytes_read;
3816               printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
3817               data += bytes_read;
3818               printf (_("%s\n"), name);
3819             }
3820         }
3821       
3822       /* Skip the NUL at the end of the table.  */
3823       data ++;
3824       
3825       /* Now display the statements.  */
3826       printf (_("\n Line Number Statements:\n"));
3827       
3828       
3829       while (data < end_of_sequence)
3830         {
3831           unsigned char op_code;
3832           int           adv;
3833           int           bytes_read;
3834           
3835           op_code = * data ++;
3836           
3837           switch (op_code)
3838             {
3839             case DW_LNS_extended_op:
3840               data += process_extended_line_op (data, info.li_default_is_stmt);
3841               break;
3842               
3843             case DW_LNS_copy:
3844               printf (_("  Copy\n"));
3845               break;
3846               
3847             case DW_LNS_advance_pc:
3848               adv = info.li_min_insn_length * read_leb128 (data, & bytes_read, 0);
3849               data += bytes_read;
3850               state_machine_regs.address += adv;
3851               printf (_("  Advance PC by %d to %lx\n"), adv,
3852                       state_machine_regs.address);
3853               break;
3854               
3855             case DW_LNS_advance_line:
3856               adv = read_leb128 (data, & bytes_read, 1);
3857               data += bytes_read;
3858               state_machine_regs.line += adv;
3859               printf (_("  Advance Line by %d to %d\n"), adv,
3860                       state_machine_regs.line);
3861               break;
3862               
3863             case DW_LNS_set_file:
3864               adv = read_leb128 (data, & bytes_read, 0);
3865               data += bytes_read;
3866               printf (_("  Set File Name to entry %d in the File Name Table\n"),
3867                       adv);
3868               state_machine_regs.file = adv;
3869               break;
3870               
3871             case DW_LNS_set_column:
3872               adv = read_leb128 (data, & bytes_read, 0);
3873               data += bytes_read;
3874               printf (_("  Set column to %d\n"), adv);
3875               state_machine_regs.column = adv;
3876               break;
3877               
3878             case DW_LNS_negate_stmt:
3879               adv = state_machine_regs.is_stmt;
3880               adv = ! adv;
3881               printf (_("  Set is_stmt to %d\n"), adv);
3882               state_machine_regs.is_stmt = adv;
3883               break;
3884               
3885             case DW_LNS_set_basic_block:
3886               printf (_("  Set basic block\n"));
3887               state_machine_regs.basic_block = 1;
3888               break;
3889               
3890             case DW_LNS_const_add_pc:
3891               adv = (255 - info.li_opcode_base) / info.li_line_range;
3892               state_machine_regs.address += adv;
3893               printf (_("  Advance PC by constant %d to 0x%lx\n"), adv,
3894                       state_machine_regs.address);
3895               break;
3896               
3897             case DW_LNS_fixed_advance_pc:
3898               adv = byte_get (data, 2);
3899               data += 2;
3900               state_machine_regs.address += adv;
3901               printf (_("  Advance PC by fixed size amount %d to 0x%lx\n"),
3902                       adv, state_machine_regs.address);
3903               break;
3904               
3905             default:
3906               op_code -= info.li_opcode_base;
3907               adv      = (op_code / info.li_line_range) * info.li_min_insn_length;
3908               state_machine_regs.address += adv;
3909               printf (_("  Special opcode %d: advance Address by %d to 0x%lx"),
3910                       op_code, adv, state_machine_regs.address);
3911               adv    += (op_code % info.li_line_range) + info.li_line_base;
3912               state_machine_regs.line += adv;
3913               printf (_(" and Line by %d to %d\n"),
3914                       adv, state_machine_regs.line);
3915               break;
3916             }
3917         }
3918       printf ("\n");
3919     }
3920   
3921   return 1;
3922 }
3923
3924 static int
3925 display_debug_pubnames (section, start, file)
3926      Elf32_Internal_Shdr * section;
3927      unsigned char *       start;
3928      FILE *                file;
3929 {
3930   DWARF2_External_PubNames * external;
3931   DWARF2_Internal_PubNames   pubnames;
3932   unsigned char *            end;
3933
3934   end = start + section->sh_size;
3935
3936   printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section));
3937
3938   while (start < end)
3939     {
3940       unsigned char * data;
3941       unsigned long   offset;
3942
3943       external = (DWARF2_External_PubNames *) start;
3944
3945       pubnames.pn_length  = BYTE_GET (external->pn_length);
3946       pubnames.pn_version = BYTE_GET (external->pn_version);
3947       pubnames.pn_offset  = BYTE_GET (external->pn_offset);
3948       pubnames.pn_size    = BYTE_GET (external->pn_size);
3949
3950       data   = start + sizeof (* external);
3951       start += pubnames.pn_length + sizeof (external->pn_length);
3952
3953       if (pubnames.pn_version != 2)
3954         {
3955           warn (_("Only DWARF 2 pubnames are currently supported"));
3956           continue;
3957         }
3958
3959       printf (_("  Length:                              %ld\n"),
3960               pubnames.pn_length);
3961       printf (_("  Version:                             %d\n"),
3962               pubnames.pn_version);
3963       printf (_("  Offset into .debug_info section:     %ld\n"),
3964               pubnames.pn_offset);
3965       printf (_("  Size of area in .debug_info section: %ld\n"),
3966               pubnames.pn_size);
3967
3968       printf (_("\n    Offset\tName\n"));
3969
3970       do
3971         {
3972           offset = byte_get (data, 4);
3973
3974           if (offset != 0)
3975             {
3976               data += 4;
3977               printf ("    %ld\t\t%s\n", offset, data);
3978               data += strlen (data) + 1;
3979             }
3980         }
3981       while (offset != 0);
3982     }
3983
3984   printf ("\n");
3985   return 1;
3986 }
3987
3988 static char *
3989 get_TAG_name (tag)
3990      unsigned long tag;
3991 {
3992   switch (tag)
3993     {
3994     case DW_TAG_padding: return "DW_TAG_padding";
3995     case DW_TAG_array_type: return "DW_TAG_array_type";
3996     case DW_TAG_class_type: return "DW_TAG_class_type";
3997     case DW_TAG_entry_point: return "DW_TAG_entry_point";
3998     case DW_TAG_enumeration_type: return "DW_TAG_enumeration_type";
3999     case DW_TAG_formal_parameter: return "DW_TAG_formal_parameter";
4000     case DW_TAG_imported_declaration: return "DW_TAG_imported_declaration";
4001     case DW_TAG_label: return "DW_TAG_label";
4002     case DW_TAG_lexical_block: return "DW_TAG_lexical_block";
4003     case DW_TAG_member: return "DW_TAG_member";
4004     case DW_TAG_pointer_type: return "DW_TAG_pointer_type";
4005     case DW_TAG_reference_type: return "DW_TAG_reference_type";
4006     case DW_TAG_compile_unit: return "DW_TAG_compile_unit";
4007     case DW_TAG_string_type: return "DW_TAG_string_type";
4008     case DW_TAG_structure_type: return "DW_TAG_structure_type";
4009     case DW_TAG_subroutine_type: return "DW_TAG_subroutine_type";
4010     case DW_TAG_typedef: return "DW_TAG_typedef";
4011     case DW_TAG_union_type: return "DW_TAG_union_type";
4012     case DW_TAG_unspecified_parameters: return "DW_TAG_unspecified_parameters";
4013     case DW_TAG_variant: return "DW_TAG_variant";
4014     case DW_TAG_common_block: return "DW_TAG_common_block";
4015     case DW_TAG_common_inclusion: return "DW_TAG_common_inclusion";
4016     case DW_TAG_inheritance: return "DW_TAG_inheritance";
4017     case DW_TAG_inlined_subroutine: return "DW_TAG_inlined_subroutine";
4018     case DW_TAG_module: return "DW_TAG_module";
4019     case DW_TAG_ptr_to_member_type: return "DW_TAG_ptr_to_member_type";
4020     case DW_TAG_set_type: return "DW_TAG_set_type";
4021     case DW_TAG_subrange_type: return "DW_TAG_subrange_type";
4022     case DW_TAG_with_stmt: return "DW_TAG_with_stmt";
4023     case DW_TAG_access_declaration: return "DW_TAG_access_declaration";
4024     case DW_TAG_base_type: return "DW_TAG_base_type";
4025     case DW_TAG_catch_block: return "DW_TAG_catch_block";
4026     case DW_TAG_const_type: return "DW_TAG_const_type";
4027     case DW_TAG_constant: return "DW_TAG_constant";
4028     case DW_TAG_enumerator: return "DW_TAG_enumerator";
4029     case DW_TAG_file_type: return "DW_TAG_file_type";
4030     case DW_TAG_friend: return "DW_TAG_friend";
4031     case DW_TAG_namelist: return "DW_TAG_namelist";
4032     case DW_TAG_namelist_item: return "DW_TAG_namelist_item";
4033     case DW_TAG_packed_type: return "DW_TAG_packed_type";
4034     case DW_TAG_subprogram: return "DW_TAG_subprogram";
4035     case DW_TAG_template_type_param: return "DW_TAG_template_type_param";
4036     case DW_TAG_template_value_param: return "DW_TAG_template_value_param";
4037     case DW_TAG_thrown_type: return "DW_TAG_thrown_type";
4038     case DW_TAG_try_block: return "DW_TAG_try_block";
4039     case DW_TAG_variant_part: return "DW_TAG_variant_part";
4040     case DW_TAG_variable: return "DW_TAG_variable";
4041     case DW_TAG_volatile_type: return "DW_TAG_volatile_type";
4042     case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop";
4043     case DW_TAG_format_label: return "DW_TAG_format_label";
4044     case DW_TAG_function_template: return "DW_TAG_function_template";
4045     case DW_TAG_class_template: return "DW_TAG_class_template";
4046     default:
4047       {
4048         static char buffer [100];
4049
4050         sprintf (buffer, _("Unknown TAG value: %lx"), tag);
4051         return buffer;
4052       }
4053     }
4054 }
4055
4056 static char *
4057 get_AT_name (attribute)
4058      unsigned long attribute;
4059 {
4060   switch (attribute)
4061     {
4062     case DW_AT_sibling: return "DW_AT_sibling";
4063     case DW_AT_location: return "DW_AT_location";
4064     case DW_AT_name: return "DW_AT_name";
4065     case DW_AT_ordering: return "DW_AT_ordering";
4066     case DW_AT_subscr_data: return "DW_AT_subscr_data";
4067     case DW_AT_byte_size: return "DW_AT_byte_size";
4068     case DW_AT_bit_offset: return "DW_AT_bit_offset";
4069     case DW_AT_bit_size: return "DW_AT_bit_size";
4070     case DW_AT_element_list: return "DW_AT_element_list";
4071     case DW_AT_stmt_list: return "DW_AT_stmt_list";
4072     case DW_AT_low_pc: return "DW_AT_low_pc";
4073     case DW_AT_high_pc: return "DW_AT_high_pc";
4074     case DW_AT_language: return "DW_AT_language";
4075     case DW_AT_member: return "DW_AT_member";
4076     case DW_AT_discr: return "DW_AT_discr";
4077     case DW_AT_discr_value: return "DW_AT_discr_value";
4078     case DW_AT_visibility: return "DW_AT_visibility";
4079     case DW_AT_import: return "DW_AT_import";
4080     case DW_AT_string_length: return "DW_AT_string_length";
4081     case DW_AT_common_reference: return "DW_AT_common_reference";
4082     case DW_AT_comp_dir: return "DW_AT_comp_dir";
4083     case DW_AT_const_value: return "DW_AT_const_value";
4084     case DW_AT_containing_type: return "DW_AT_containing_type";
4085     case DW_AT_default_value: return "DW_AT_default_value";
4086     case DW_AT_inline: return "DW_AT_inline";
4087     case DW_AT_is_optional: return "DW_AT_is_optional";
4088     case DW_AT_lower_bound: return "DW_AT_lower_bound";
4089     case DW_AT_producer: return "DW_AT_producer";
4090     case DW_AT_prototyped: return "DW_AT_prototyped";
4091     case DW_AT_return_addr: return "DW_AT_return_addr";
4092     case DW_AT_start_scope: return "DW_AT_start_scope";
4093     case DW_AT_stride_size: return "DW_AT_stride_size";
4094     case DW_AT_upper_bound: return "DW_AT_upper_bound";
4095     case DW_AT_abstract_origin: return "DW_AT_abstract_origin";
4096     case DW_AT_accessibility: return "DW_AT_accessibility";
4097     case DW_AT_address_class: return "DW_AT_address_class";
4098     case DW_AT_artificial: return "DW_AT_artificial";
4099     case DW_AT_base_types: return "DW_AT_base_types";
4100     case DW_AT_calling_convention: return "DW_AT_calling_convention";
4101     case DW_AT_count: return "DW_AT_count";
4102     case DW_AT_data_member_location: return "DW_AT_data_member_location";
4103     case DW_AT_decl_column: return "DW_AT_decl_column";
4104     case DW_AT_decl_file: return "DW_AT_decl_file";
4105     case DW_AT_decl_line: return "DW_AT_decl_line";
4106     case DW_AT_declaration: return "DW_AT_declaration";
4107     case DW_AT_discr_list: return "DW_AT_discr_list";
4108     case DW_AT_encoding: return "DW_AT_encoding";
4109     case DW_AT_external: return "DW_AT_external";
4110     case DW_AT_frame_base: return "DW_AT_frame_base";
4111     case DW_AT_friend: return "DW_AT_friend";
4112     case DW_AT_identifier_case: return "DW_AT_identifier_case";
4113     case DW_AT_macro_info: return "DW_AT_macro_info";
4114     case DW_AT_namelist_items: return "DW_AT_namelist_items";
4115     case DW_AT_priority: return "DW_AT_priority";
4116     case DW_AT_segment: return "DW_AT_segment";
4117     case DW_AT_specification: return "DW_AT_specification";
4118     case DW_AT_static_link: return "DW_AT_static_link";
4119     case DW_AT_type: return "DW_AT_type";
4120     case DW_AT_use_location: return "DW_AT_use_location";
4121     case DW_AT_variable_parameter: return "DW_AT_variable_parameter";
4122     case DW_AT_virtuality: return "DW_AT_virtuality";
4123     case DW_AT_vtable_elem_location: return "DW_AT_vtable_elem_location";
4124     case DW_AT_MIPS_fde: return "DW_AT_MIPS_fde";
4125     case DW_AT_MIPS_loop_begin: return "DW_AT_MIPS_loop_begin";
4126     case DW_AT_MIPS_tail_loop_begin: return "DW_AT_MIPS_tail_loop_begin";
4127     case DW_AT_MIPS_epilog_begin: return "DW_AT_MIPS_epilog_begin";
4128     case DW_AT_MIPS_loop_unroll_factor: return "DW_AT_MIPS_loop_unroll_factor";
4129     case DW_AT_MIPS_software_pipeline_depth: return "DW_AT_MIPS_software_pipeline_depth";
4130     case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name";
4131     case DW_AT_MIPS_stride: return "DW_AT_MIPS_stride";
4132     case DW_AT_MIPS_abstract_name: return "DW_AT_MIPS_abstract_name";
4133     case DW_AT_MIPS_clone_origin: return "DW_AT_MIPS_clone_origin";
4134     case DW_AT_MIPS_has_inlines: return "DW_AT_MIPS_has_inlines";
4135     case DW_AT_sf_names: return "DW_AT_sf_names";
4136     case DW_AT_src_info: return "DW_AT_src_info";
4137     case DW_AT_mac_info: return "DW_AT_mac_info";
4138     case DW_AT_src_coords: return "DW_AT_src_coords";
4139     case DW_AT_body_begin: return "DW_AT_body_begin";
4140     case DW_AT_body_end: return "DW_AT_body_end";
4141     default:
4142       {
4143         static char buffer [100];
4144
4145         sprintf (buffer, _("Unknown AT value: %lx"), attribute);
4146         return buffer;
4147       }
4148     }
4149 }
4150
4151 static char *
4152 get_FORM_name (form)
4153      unsigned long form;
4154 {
4155   switch (form)
4156     {
4157     case DW_FORM_addr: return "DW_FORM_addr";
4158     case DW_FORM_block2: return "DW_FORM_block2";
4159     case DW_FORM_block4: return "DW_FORM_block4";
4160     case DW_FORM_data2: return "DW_FORM_data2";
4161     case DW_FORM_data4: return "DW_FORM_data4";
4162     case DW_FORM_data8: return "DW_FORM_data8";
4163     case DW_FORM_string: return "DW_FORM_string";
4164     case DW_FORM_block: return "DW_FORM_block";
4165     case DW_FORM_block1: return "DW_FORM_block1";
4166     case DW_FORM_data1: return "DW_FORM_data1";
4167     case DW_FORM_flag: return "DW_FORM_flag";
4168     case DW_FORM_sdata: return "DW_FORM_sdata";
4169     case DW_FORM_strp: return "DW_FORM_strp";
4170     case DW_FORM_udata: return "DW_FORM_udata";
4171     case DW_FORM_ref_addr: return "DW_FORM_ref_addr";
4172     case DW_FORM_ref1: return "DW_FORM_ref1";
4173     case DW_FORM_ref2: return "DW_FORM_ref2";
4174     case DW_FORM_ref4: return "DW_FORM_ref4";
4175     case DW_FORM_ref8: return "DW_FORM_ref8";
4176     case DW_FORM_ref_udata: return "DW_FORM_ref_udata";
4177     case DW_FORM_indirect: return "DW_FORM_indirect";
4178     default:
4179       {
4180         static char buffer [100];
4181
4182         sprintf (buffer, _("Unknown FORM value: %lx"), form);
4183         return buffer;
4184       }
4185     }
4186 }
4187
4188 /* FIXME:  There are better and more effiecint ways to handle
4189    these structures.  For now though, I just want something that
4190    is simple to implement.  */
4191 typedef struct abbrev_attr
4192 {
4193   unsigned long        attribute;
4194   unsigned long        form;
4195   struct abbrev_attr * next;
4196 }
4197 abbrev_attr;
4198
4199 typedef struct abbrev_entry
4200 {
4201   unsigned long          entry;
4202   unsigned long          tag;
4203   int                    children;
4204   struct abbrev_attr *   first_attr;
4205   struct abbrev_attr *   last_attr;
4206   struct abbrev_entry *  next;
4207 }
4208 abbrev_entry;
4209
4210 static abbrev_entry * first_abbrev = NULL;
4211 static abbrev_entry * last_abbrev = NULL;
4212
4213 static void
4214 free_abbrevs PARAMS ((void))
4215 {
4216   abbrev_entry * abbrev;
4217
4218   for (abbrev = first_abbrev; abbrev;)
4219     {
4220       abbrev_entry * next = abbrev->next;
4221       abbrev_attr  * attr;
4222
4223       for (attr = abbrev->first_attr; attr;)
4224         {
4225           abbrev_attr * next = attr->next;
4226
4227           free (attr);
4228           attr = next;
4229         }
4230
4231       free (abbrev);
4232       abbrev = next;
4233     }
4234
4235   last_abbrev = first_abbrev = NULL;
4236 }
4237
4238 static void
4239 add_abbrev (number, tag, children)
4240      unsigned long number;
4241      unsigned long tag;
4242      int           children;
4243 {
4244   abbrev_entry * entry;
4245
4246   entry = (abbrev_entry *) malloc (sizeof (* entry));
4247
4248   if (entry == NULL)
4249     /* ugg */
4250     return;
4251
4252   entry->entry      = number;
4253   entry->tag        = tag;
4254   entry->children   = children;
4255   entry->first_attr = NULL;
4256   entry->last_attr  = NULL;
4257   entry->next       = NULL;
4258
4259   if (first_abbrev == NULL)
4260     first_abbrev = entry;
4261   else
4262     last_abbrev->next = entry;
4263
4264   last_abbrev = entry;
4265 }
4266
4267 static void
4268 add_abbrev_attr (attribute, form)
4269      unsigned long attribute;
4270      unsigned long form;
4271 {
4272   abbrev_attr * attr;
4273
4274   attr = (abbrev_attr *) malloc (sizeof (* attr));
4275
4276   if (attr == NULL)
4277     /* ugg */
4278     return;
4279
4280   attr->attribute = attribute;
4281   attr->form      = form;
4282   attr->next      = NULL;
4283
4284   if (last_abbrev->first_attr == NULL)
4285     last_abbrev->first_attr = attr;
4286   else
4287     last_abbrev->last_attr->next = attr;
4288
4289   last_abbrev->last_attr = attr;
4290 }
4291
4292 /* Processes the (partial) contents of a .debug_abbrev section.
4293    Returns NULL if the end of the section was encountered.
4294    Returns the address after the last byte read if the end of
4295    an abbreviation set was found.  */
4296
4297 static unsigned char *
4298 process_abbrev_section (start, end)
4299      unsigned char * start;
4300      unsigned char * end;
4301 {
4302   if (first_abbrev != NULL)
4303     return NULL;
4304
4305   while (start < end)
4306     {
4307       int           bytes_read;
4308       unsigned long entry;
4309       unsigned long tag;
4310       unsigned long attribute;
4311       int           children;
4312
4313       entry = read_leb128 (start, & bytes_read, 0);
4314       start += bytes_read;
4315
4316       if (entry == 0)
4317         return start;
4318
4319       tag = read_leb128 (start, & bytes_read, 0);
4320       start += bytes_read;
4321
4322       children = * start ++;
4323
4324       add_abbrev (entry, tag, children);
4325
4326       do
4327         {
4328           unsigned long form;
4329
4330           attribute = read_leb128 (start, & bytes_read, 0);
4331           start += bytes_read;
4332
4333           form = read_leb128 (start, & bytes_read, 0);
4334           start += bytes_read;
4335
4336           if (attribute != 0)
4337             add_abbrev_attr (attribute, form);
4338         }
4339       while (attribute != 0);
4340     }
4341
4342   return NULL;
4343 }
4344
4345
4346 static int
4347 display_debug_abbrev (section, start, file)
4348      Elf32_Internal_Shdr * section;
4349      unsigned char *       start;
4350      FILE *                file;
4351 {
4352   abbrev_entry * entry;
4353   unsigned char * end = start + section->sh_size;
4354
4355   printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section));
4356
4357   do
4358     {
4359       start = process_abbrev_section (start, end);
4360
4361       printf (_("  Number TAG\n"));
4362
4363       for (entry = first_abbrev; entry; entry = entry->next)
4364         {
4365           abbrev_attr * attr;
4366
4367           printf (_("   %ld      %s    [%s]\n"),
4368                   entry->entry,
4369                   get_TAG_name (entry->tag),
4370                   entry->children ? _("has children") : _("no children"));
4371
4372           for (attr = entry->first_attr; attr; attr = attr->next)
4373             {
4374               printf (_("    %-18s %s\n"),
4375                       get_AT_name (attr->attribute),
4376                       get_FORM_name (attr->form));
4377             }
4378         }
4379     }
4380   while (start);
4381
4382   printf ("\n");
4383
4384   return 1;
4385 }
4386
4387
4388 static unsigned char *
4389 display_block (data, length)
4390      unsigned char * data;
4391      unsigned long   length;
4392 {
4393   printf (_(" %lu byte block: "), length);
4394
4395   while (length --)
4396     printf ("%lx ", byte_get (data ++, 1));
4397
4398   return data;
4399 }
4400
4401 static void
4402 decode_location_expression (data, pointer_size)
4403      unsigned char * data;
4404      unsigned int    pointer_size;
4405 {
4406   unsigned char op;
4407   int           bytes_read;
4408
4409   op = * data ++;
4410
4411   switch (op)
4412     {
4413     case DW_OP_addr:    printf ("DW_OP_addr: %lx", byte_get (data, pointer_size)); break;
4414     case DW_OP_deref:   printf ("DW_OP_deref"); break;
4415     case DW_OP_const1u: printf ("DW_OP_const1u: %lu", byte_get (data, 1)); break;
4416     case DW_OP_const1s: printf ("DW_OP_const1s: %ld", (long) byte_get (data, 1)); break;
4417     case DW_OP_const2u: printf ("DW_OP_const2u: %lu", byte_get (data, 2)); break;
4418     case DW_OP_const2s: printf ("DW_OP_const2s: %ld", (long) byte_get (data, 2)); break;
4419     case DW_OP_const4u: printf ("DW_OP_const4u: %lu", byte_get (data, 4)); break;
4420     case DW_OP_const4s: printf ("DW_OP_const4s: %ld", (long) byte_get (data, 4)); break;
4421     case DW_OP_const8u: printf ("DW_OP_const8u: %lu %lu", byte_get (data, 4), byte_get (data + 4, 4)); break;
4422     case DW_OP_const8s: printf ("DW_OP_const8s: %ld %ld", byte_get (data, 4), byte_get (data + 4, 4)); break;
4423     case DW_OP_constu:  printf ("DW_OP_constu: %lu", read_leb128 (data, NULL, 0)); break;
4424     case DW_OP_consts:  printf ("DW_OP_consts: %ld", read_leb128 (data, NULL, 1)); break;
4425     case DW_OP_dup:     printf ("DW_OP_dup"); break;
4426     case DW_OP_drop:    printf ("DW_OP_drop"); break;
4427     case DW_OP_over:    printf ("DW_OP_over"); break;
4428     case DW_OP_pick:    printf ("DW_OP_pick: %ld", byte_get (data, 1)); break;
4429     case DW_OP_swap:    printf ("DW_OP_swap"); break;
4430     case DW_OP_rot:     printf ("DW_OP_rot"); break;
4431     case DW_OP_xderef:  printf ("DW_OP_xderef"); break;
4432     case DW_OP_abs:     printf ("DW_OP_abs"); break;
4433     case DW_OP_and:     printf ("DW_OP_and"); break;
4434     case DW_OP_div:     printf ("DW_OP_div"); break;
4435     case DW_OP_minus:   printf ("DW_OP_minus"); break;
4436     case DW_OP_mod:     printf ("DW_OP_mod"); break;
4437     case DW_OP_mul:     printf ("DW_OP_mul"); break;
4438     case DW_OP_neg:     printf ("DW_OP_neg"); break;
4439     case DW_OP_not:     printf ("DW_OP_not"); break;
4440     case DW_OP_or:      printf ("DW_OP_or"); break;
4441     case DW_OP_plus:    printf ("DW_OP_plus"); break;
4442     case DW_OP_plus_uconst:     printf ("DW_OP_plus_uconst: %lu", read_leb128 (data, NULL, 0)); break;
4443     case DW_OP_shl:     printf ("DW_OP_shl"); break;
4444     case DW_OP_shr:     printf ("DW_OP_shr"); break;
4445     case DW_OP_shra:    printf ("DW_OP_shra"); break;
4446     case DW_OP_xor:     printf ("DW_OP_xor"); break;
4447     case DW_OP_bra:     printf ("DW_OP_bra: %ld", byte_get (data, 2)); break;
4448     case DW_OP_eq:      printf ("DW_OP_eq"); break;
4449     case DW_OP_ge:      printf ("DW_OP_ge"); break;
4450     case DW_OP_gt:      printf ("DW_OP_gt"); break;
4451     case DW_OP_le:      printf ("DW_OP_le"); break;
4452     case DW_OP_lt:      printf ("DW_OP_lt"); break;
4453     case DW_OP_ne:      printf ("DW_OP_ne"); break;
4454     case DW_OP_skip:    printf ("DW_OP_skip: %ld", byte_get (data, 2)); break;
4455     case DW_OP_lit0:    printf ("DW_OP_lit0"); break;
4456     case DW_OP_lit1:    printf ("DW_OP_lit1"); break;
4457     case DW_OP_lit2:    printf ("DW_OP_lit2"); break;
4458     case DW_OP_lit3:    printf ("DW_OP_lit3"); break;
4459     case DW_OP_lit4:    printf ("DW_OP_lit4"); break;
4460     case DW_OP_lit5:    printf ("DW_OP_lit5"); break;
4461     case DW_OP_lit6:    printf ("DW_OP_lit6"); break;
4462     case DW_OP_lit7:    printf ("DW_OP_lit7"); break;
4463     case DW_OP_lit8:    printf ("DW_OP_lit8"); break;
4464     case DW_OP_lit9:    printf ("DW_OP_lit9"); break;
4465     case DW_OP_lit10:   printf ("DW_OP_lit10"); break;
4466     case DW_OP_lit11:   printf ("DW_OP_lit11"); break;
4467     case DW_OP_lit12:   printf ("DW_OP_lit12"); break;
4468     case DW_OP_lit13:   printf ("DW_OP_lit13"); break;
4469     case DW_OP_lit14:   printf ("DW_OP_lit14"); break;
4470     case DW_OP_lit15:   printf ("DW_OP_lit15"); break;
4471     case DW_OP_lit16:   printf ("DW_OP_lit16"); break;
4472     case DW_OP_lit17:   printf ("DW_OP_lit17"); break;
4473     case DW_OP_lit18:   printf ("DW_OP_lit18"); break;
4474     case DW_OP_lit19:   printf ("DW_OP_lit19"); break;
4475     case DW_OP_lit20:   printf ("DW_OP_lit20"); break;
4476     case DW_OP_lit21:   printf ("DW_OP_lit21"); break;
4477     case DW_OP_lit22:   printf ("DW_OP_lit22"); break;
4478     case DW_OP_lit23:   printf ("DW_OP_lit23"); break;
4479     case DW_OP_lit24:   printf ("DW_OP_lit24"); break;
4480     case DW_OP_lit25:   printf ("DW_OP_lit25"); break;
4481     case DW_OP_lit26:   printf ("DW_OP_lit26"); break;
4482     case DW_OP_lit27:   printf ("DW_OP_lit27"); break;
4483     case DW_OP_lit28:   printf ("DW_OP_lit28"); break;
4484     case DW_OP_lit29:   printf ("DW_OP_lit29"); break;
4485     case DW_OP_lit30:   printf ("DW_OP_lit30"); break;
4486     case DW_OP_lit31:   printf ("DW_OP_lit31"); break;
4487     case DW_OP_reg0:    printf ("DW_OP_reg0"); break;
4488     case DW_OP_reg1:    printf ("DW_OP_reg1"); break;
4489     case DW_OP_reg2:    printf ("DW_OP_reg2"); break;
4490     case DW_OP_reg3:    printf ("DW_OP_reg3"); break;
4491     case DW_OP_reg4:    printf ("DW_OP_reg4"); break;
4492     case DW_OP_reg5:    printf ("DW_OP_reg5"); break;
4493     case DW_OP_reg6:    printf ("DW_OP_reg6"); break;
4494     case DW_OP_reg7:    printf ("DW_OP_reg7"); break;
4495     case DW_OP_reg8:    printf ("DW_OP_reg8"); break;
4496     case DW_OP_reg9:    printf ("DW_OP_reg9"); break;
4497     case DW_OP_reg10:   printf ("DW_OP_reg10"); break;
4498     case DW_OP_reg11:   printf ("DW_OP_reg11"); break;
4499     case DW_OP_reg12:   printf ("DW_OP_reg12"); break;
4500     case DW_OP_reg13:   printf ("DW_OP_reg13"); break;
4501     case DW_OP_reg14:   printf ("DW_OP_reg14"); break;
4502     case DW_OP_reg15:   printf ("DW_OP_reg15"); break;
4503     case DW_OP_reg16:   printf ("DW_OP_reg16"); break;
4504     case DW_OP_reg17:   printf ("DW_OP_reg17"); break;
4505     case DW_OP_reg18:   printf ("DW_OP_reg18"); break;
4506     case DW_OP_reg19:   printf ("DW_OP_reg19"); break;
4507     case DW_OP_reg20:   printf ("DW_OP_reg20"); break;
4508     case DW_OP_reg21:   printf ("DW_OP_reg21"); break;
4509     case DW_OP_reg22:   printf ("DW_OP_reg22"); break;
4510     case DW_OP_reg23:   printf ("DW_OP_reg23"); break;
4511     case DW_OP_reg24:   printf ("DW_OP_reg24"); break;
4512     case DW_OP_reg25:   printf ("DW_OP_reg25"); break;
4513     case DW_OP_reg26:   printf ("DW_OP_reg26"); break;
4514     case DW_OP_reg27:   printf ("DW_OP_reg27"); break;
4515     case DW_OP_reg28:   printf ("DW_OP_reg28"); break;
4516     case DW_OP_reg29:   printf ("DW_OP_reg29"); break;
4517     case DW_OP_reg30:   printf ("DW_OP_reg30"); break;
4518     case DW_OP_reg31:   printf ("DW_OP_reg31"); break;
4519     case DW_OP_breg0:   printf ("DW_OP_breg0: %ld", read_leb128 (data, NULL, 1)); break;
4520     case DW_OP_breg1:   printf ("DW_OP_breg1: %ld", read_leb128 (data, NULL, 1)); break;
4521     case DW_OP_breg2:   printf ("DW_OP_breg2: %ld", read_leb128 (data, NULL, 1)); break;
4522     case DW_OP_breg3:   printf ("DW_OP_breg3: %ld", read_leb128 (data, NULL, 1)); break;
4523     case DW_OP_breg4:   printf ("DW_OP_breg4: %ld", read_leb128 (data, NULL, 1)); break;
4524     case DW_OP_breg5:   printf ("DW_OP_breg5: %ld", read_leb128 (data, NULL, 1)); break;
4525     case DW_OP_breg6:   printf ("DW_OP_breg6: %ld", read_leb128 (data, NULL, 1)); break;
4526     case DW_OP_breg7:   printf ("DW_OP_breg7: %ld", read_leb128 (data, NULL, 1)); break;
4527     case DW_OP_breg8:   printf ("DW_OP_breg8: %ld", read_leb128 (data, NULL, 1)); break;
4528     case DW_OP_breg9:   printf ("DW_OP_breg9: %ld", read_leb128 (data, NULL, 1)); break;
4529     case DW_OP_breg10:  printf ("DW_OP_breg10: %ld", read_leb128 (data, NULL, 1)); break;
4530     case DW_OP_breg11:  printf ("DW_OP_breg11: %ld", read_leb128 (data, NULL, 1)); break;
4531     case DW_OP_breg12:  printf ("DW_OP_breg12: %ld", read_leb128 (data, NULL, 1)); break;
4532     case DW_OP_breg13:  printf ("DW_OP_breg13: %ld", read_leb128 (data, NULL, 1)); break;
4533     case DW_OP_breg14:  printf ("DW_OP_breg14: %ld", read_leb128 (data, NULL, 1)); break;
4534     case DW_OP_breg15:  printf ("DW_OP_breg15: %ld", read_leb128 (data, NULL, 1)); break;
4535     case DW_OP_breg16:  printf ("DW_OP_breg16: %ld", read_leb128 (data, NULL, 1)); break;
4536     case DW_OP_breg17:  printf ("DW_OP_breg17: %ld", read_leb128 (data, NULL, 1)); break;
4537     case DW_OP_breg18:  printf ("DW_OP_breg18: %ld", read_leb128 (data, NULL, 1)); break;
4538     case DW_OP_breg19:  printf ("DW_OP_breg19: %ld", read_leb128 (data, NULL, 1)); break;
4539     case DW_OP_breg20:  printf ("DW_OP_breg20: %ld", read_leb128 (data, NULL, 1)); break;
4540     case DW_OP_breg21:  printf ("DW_OP_breg21: %ld", read_leb128 (data, NULL, 1)); break;
4541     case DW_OP_breg22:  printf ("DW_OP_breg22: %ld", read_leb128 (data, NULL, 1)); break;
4542     case DW_OP_breg23:  printf ("DW_OP_breg23: %ld", read_leb128 (data, NULL, 1)); break;
4543     case DW_OP_breg24:  printf ("DW_OP_breg24: %ld", read_leb128 (data, NULL, 1)); break;
4544     case DW_OP_breg25:  printf ("DW_OP_breg25: %ld", read_leb128 (data, NULL, 1)); break;
4545     case DW_OP_breg26:  printf ("DW_OP_breg26: %ld", read_leb128 (data, NULL, 1)); break;
4546     case DW_OP_breg27:  printf ("DW_OP_breg27: %ld", read_leb128 (data, NULL, 1)); break;
4547     case DW_OP_breg28:  printf ("DW_OP_breg28: %ld", read_leb128 (data, NULL, 1)); break;
4548     case DW_OP_breg29:  printf ("DW_OP_breg29: %ld", read_leb128 (data, NULL, 1)); break;
4549     case DW_OP_breg30:  printf ("DW_OP_breg30: %ld", read_leb128 (data, NULL, 1)); break;
4550     case DW_OP_breg31:  printf ("DW_OP_breg31: %ld", read_leb128 (data, NULL, 1)); break;
4551     case DW_OP_regx:    printf ("DW_OP_regx: %lu", read_leb128 (data, NULL, 0)); break;
4552     case DW_OP_fbreg:   printf ("DW_OP_fbreg: %ld", read_leb128 (data, NULL, 1)); break;
4553     case DW_OP_bregx:   printf ("DW_OP_bregx: %lu %ld", read_leb128 (data, & bytes_read, 0), read_leb128 (data + bytes_read, NULL, 1)); break;
4554     case DW_OP_piece:   printf ("DW_OP_piece: %lu", read_leb128 (data, NULL, 0)); break;
4555     case DW_OP_deref_size:      printf ("DW_OP_deref_size: %ld", byte_get (data, 1)); break;
4556     case DW_OP_xderef_size:     printf ("DW_OP_xderef_size: %ld", byte_get (data, 1)); break;
4557     case DW_OP_nop:     printf ("DW_OP_nop"); break;
4558
4559     default:
4560       if (op >= DW_OP_lo_user
4561           && op <= DW_OP_hi_user)
4562         printf (_("(User defined location op)"));
4563       else
4564         printf (_("(Unknown location op)"));
4565       break;
4566     }
4567 }
4568
4569
4570 static unsigned char *
4571 read_and_display_attr (attribute, form, data, pointer_size)
4572      unsigned long   attribute;
4573      unsigned long   form;
4574      unsigned char * data;
4575      unsigned long   pointer_size;
4576 {
4577   unsigned long   uvalue;
4578   unsigned char * block_start;
4579   int             bytes_read;
4580   int             is_ref = 0;
4581
4582   printf ("     %-18s:", get_AT_name (attribute));
4583
4584   switch (form)
4585     {
4586     case DW_FORM_ref_addr:
4587     case DW_FORM_ref1:
4588     case DW_FORM_ref2:
4589     case DW_FORM_ref4:
4590     case DW_FORM_ref8:
4591     case DW_FORM_ref_udata:
4592       is_ref = 1;
4593     }
4594
4595   switch (form)
4596     {
4597     case DW_FORM_ref_addr:
4598     case DW_FORM_addr:
4599       uvalue = byte_get (data, pointer_size);
4600       printf (is_ref ? " <%x>" : " %#x", uvalue);
4601       data += pointer_size;
4602       break;
4603
4604     case DW_FORM_ref1:
4605     case DW_FORM_flag:
4606     case DW_FORM_data1:
4607       uvalue = byte_get (data ++, 1);
4608       printf (is_ref ? " <%x>" : " %d", uvalue);
4609       break;
4610
4611     case DW_FORM_ref2:
4612     case DW_FORM_data2:
4613       uvalue = byte_get (data, 2);
4614       data += 2;
4615       printf (is_ref ? " <%x>" : " %d", uvalue);
4616       break;
4617
4618     case DW_FORM_ref4:
4619     case DW_FORM_data4:
4620       uvalue = byte_get (data, 4);
4621       data += 4;
4622       printf (is_ref ? " <%x>" : " %d", uvalue);
4623       break;
4624
4625     case DW_FORM_ref8:
4626     case DW_FORM_data8:
4627       uvalue = byte_get (data, 4);
4628       printf (" %lx", uvalue);
4629       printf (" %lx", byte_get (data + 4, 4));
4630       data += 8;
4631       break;
4632
4633     case DW_FORM_string:
4634       printf (" %s", data);
4635       data += strlen (data) + 1;
4636       break;
4637
4638     case DW_FORM_sdata:
4639       uvalue = read_leb128 (data, & bytes_read, 1);
4640       data += bytes_read;
4641       printf (" %ld", (long) uvalue);
4642       break;
4643
4644     case DW_FORM_ref_udata:
4645     case DW_FORM_udata:
4646       uvalue = read_leb128 (data, & bytes_read, 0);
4647       data += bytes_read;
4648       printf (is_ref ? " <%lx>" : " %ld", uvalue);
4649       break;
4650
4651     case DW_FORM_block:
4652       uvalue = read_leb128 (data, & bytes_read, 0);
4653       block_start = data + bytes_read;
4654       data = display_block (block_start, uvalue);
4655       uvalue = * block_start;
4656       break;
4657
4658     case DW_FORM_block1:
4659       uvalue = byte_get (data, 1);
4660       block_start = data + 1;
4661       data = display_block (block_start, uvalue);
4662       uvalue = * block_start;
4663       break;
4664
4665     case DW_FORM_block2:
4666       uvalue = byte_get (data, 2);
4667       block_start = data + 2;
4668       data = display_block (block_start, uvalue);
4669       uvalue = * block_start;
4670       break;
4671
4672     case DW_FORM_block4:
4673       uvalue = byte_get (data, 4);
4674       block_start = data + 4;
4675       data = display_block (block_start, uvalue);
4676       uvalue = * block_start;
4677       break;
4678
4679     case DW_FORM_strp:
4680     case DW_FORM_indirect:
4681       warn (_("Unable to handle FORM: %d"), form);
4682       break;
4683
4684     default:
4685       warn (_("Unrecognised form: %d"), form);
4686       break;
4687     }
4688
4689   /* For some attributes we can display futher information.  */
4690
4691   printf ("\t");
4692
4693   switch (attribute)
4694     {
4695     case DW_AT_inline:
4696       switch (uvalue)
4697         {
4698         case DW_INL_not_inlined:          printf (_("(not inlined)")); break;
4699         case DW_INL_inlined:              printf (_("(inlined)")); break;
4700         case DW_INL_declared_not_inlined: printf (_("(declared as inline but ignored)")); break;
4701         case DW_INL_declared_inlined:     printf (_("(declared as inline and inlined)")); break;
4702         default: printf (_("  (Unknown inline attribute value: %lx)"), uvalue); break;
4703         }
4704       break;
4705
4706     case DW_AT_frame_base:
4707       if (uvalue >= DW_OP_reg0 && uvalue <= DW_OP_reg31)
4708         printf ("(reg %ld)", uvalue - DW_OP_reg0);
4709       break;
4710
4711     case DW_AT_language:
4712       switch (uvalue)
4713         {
4714         case DW_LANG_C:              printf ("(non-ANSI C)"); break;
4715         case DW_LANG_C89:            printf ("(ANSI C)"); break;
4716         case DW_LANG_C_plus_plus:    printf ("(C++)"); break;
4717         case DW_LANG_Fortran77:      printf ("(FORTRAN 77)"); break;
4718         case DW_LANG_Fortran90:      printf ("(Fortran 90)"); break;
4719         case DW_LANG_Modula2:        printf ("(Modula 2)"); break;
4720         case DW_LANG_Pascal83:       printf ("(ANSI Pascal)"); break;
4721         case DW_LANG_Ada83:          printf ("(Ada)"); break;
4722         case DW_LANG_Cobol74:        printf ("(Cobol 74)"); break;
4723         case DW_LANG_Cobol85:        printf ("(Cobol 85)"); break;
4724         case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break;
4725         default:                     printf ("(Unknown: %lx)", uvalue); break;
4726         }
4727       break;
4728
4729     case DW_AT_encoding:
4730       switch (uvalue)
4731         {
4732         case DW_ATE_void:            printf ("(void)"); break;
4733         case DW_ATE_address:         printf ("(machine address)"); break;
4734         case DW_ATE_boolean:         printf ("(boolean)"); break;
4735         case DW_ATE_complex_float:   printf ("(complex float)"); break;
4736         case DW_ATE_float:           printf ("(float)"); break;
4737         case DW_ATE_signed:          printf ("(signed)"); break;
4738         case DW_ATE_signed_char:     printf ("(signed char)"); break;
4739         case DW_ATE_unsigned:        printf ("(unsigned)"); break;
4740         case DW_ATE_unsigned_char:   printf ("(unsigned char)"); break;
4741         default:
4742           if (uvalue >= DW_ATE_lo_user
4743               && uvalue <= DW_ATE_hi_user)
4744             printf ("(user defined type)");
4745           else
4746             printf ("(unknown type)");
4747           break;
4748         }
4749       break;
4750
4751     case DW_AT_accessibility:
4752       switch (uvalue)
4753         {
4754         case DW_ACCESS_public:          printf ("(public)"); break;
4755         case DW_ACCESS_protected:       printf ("(protected)"); break;
4756         case DW_ACCESS_private:         printf ("(private)"); break;
4757         default:                        printf ("(unknown accessibility)"); break;
4758         }
4759       break;
4760
4761     case DW_AT_visibility:
4762       switch (uvalue)
4763         {
4764         case DW_VIS_local:      printf ("(local)"); break;
4765         case DW_VIS_exported:   printf ("(exported)"); break;
4766         case DW_VIS_qualified:  printf ("(qualified)"); break;
4767         default:                printf ("(unknown visibility)"); break;
4768         }
4769       break;
4770
4771     case DW_AT_virtuality:
4772       switch (uvalue)
4773         {
4774         case DW_VIRTUALITY_none:        printf ("(none)"); break;
4775         case DW_VIRTUALITY_virtual:     printf ("(virtual)"); break;
4776         case DW_VIRTUALITY_pure_virtual:printf ("(pure_virtual)"); break;
4777         default:                        printf ("(unknown virtuality)"); break;
4778         }
4779       break;
4780
4781     case DW_AT_identifier_case:
4782       switch (uvalue)
4783         {
4784         case DW_ID_case_sensitive:      printf ("(case_sensitive)"); break;
4785         case DW_ID_up_case:             printf ("(up_case)"); break;
4786         case DW_ID_down_case:           printf ("(down_case)"); break;
4787         case DW_ID_case_insensitive:    printf ("(case_insensitive)"); break;
4788         default:                        printf ("(unknown case)"); break;
4789         }
4790       break;
4791
4792     case DW_AT_calling_convention:
4793       switch (uvalue)
4794         {
4795         case DW_CC_normal:      printf ("(normal)"); break;
4796         case DW_CC_program:     printf ("(program)"); break;
4797         case DW_CC_nocall:      printf ("(nocall)"); break;
4798         default:
4799           if (uvalue >= DW_CC_lo_user
4800               && uvalue <= DW_CC_hi_user)
4801             printf ("(user defined)");
4802           else
4803             printf ("(unknown convention)");
4804         }
4805       break;
4806
4807     case DW_AT_location:
4808     case DW_AT_data_member_location:
4809     case DW_AT_vtable_elem_location:
4810       printf ("(");
4811       decode_location_expression (block_start, pointer_size);
4812       printf (")");
4813       break;
4814
4815     default:
4816       break;
4817     }
4818
4819   printf ("\n");
4820   return data;
4821 }
4822
4823 static int
4824 display_debug_info (section, start, file)
4825      Elf32_Internal_Shdr * section;
4826      unsigned char *       start;
4827      FILE *                file;
4828 {
4829   unsigned char * end = start + section->sh_size;
4830   unsigned char * section_begin = start;
4831
4832   printf (_("The section %s contains:\n\n"), SECTION_NAME (section));
4833
4834   while (start < end)
4835     {
4836       DWARF2_External_CompUnit * external;
4837       DWARF2_Internal_CompUnit   compunit;
4838       unsigned char *            tags;
4839       int                        i;
4840       int                        level;
4841
4842       external = (DWARF2_External_CompUnit *) start;
4843
4844       compunit.cu_length        = BYTE_GET (external->cu_length);
4845       compunit.cu_version       = BYTE_GET (external->cu_version);
4846       compunit.cu_abbrev_offset = BYTE_GET (external->cu_abbrev_offset);
4847       compunit.cu_pointer_size  = BYTE_GET (external->cu_pointer_size);
4848
4849       tags = start + sizeof (* external);
4850       start += compunit.cu_length + sizeof (external->cu_length);
4851
4852       if (compunit.cu_version != 2)
4853         {
4854           warn (_("Only version 2 DWARF debug information is currently supported.\n"));
4855           continue;
4856         }
4857
4858       printf (_("  Compilation Unit:\n"));
4859       printf (_("   Length:        %ld\n"), compunit.cu_length);
4860       printf (_("   Version:       %d\n"), compunit.cu_version);
4861       printf (_("   Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset);
4862       printf (_("   Pointer Size:  %d\n"), compunit.cu_pointer_size);
4863
4864       if (first_abbrev != NULL)
4865         free_abbrevs ();
4866
4867       /* Read in the abbrevs used by this compilation unit.  */
4868
4869       {
4870         Elf32_Internal_Shdr * sec;
4871         unsigned char *       begin;
4872
4873         /* Locate the .debug_abbrev section and process it.  */
4874         for (i = 0, sec = section_headers;
4875              i < elf_header.e_shnum;
4876              i ++, sec ++)
4877           if (strcmp (SECTION_NAME (sec), ".debug_abbrev") == 0)
4878             break;
4879
4880         if (i == -1 || sec->sh_size == 0)
4881           {
4882             warn (_("Unable to locate .debug_abbrev section!\n"));
4883             return 0;
4884           }
4885
4886         GET_DATA_ALLOC (sec->sh_offset, sec->sh_size, begin, unsigned char *,
4887                         "debug_abbrev section data");
4888
4889         process_abbrev_section (begin + compunit.cu_abbrev_offset,
4890                                 begin + sec->sh_size);
4891
4892         free (begin);
4893       }
4894
4895       level = 0;
4896       while (tags < start)
4897         {
4898           int            bytes_read;
4899           int            abbrev_number;
4900           abbrev_entry * entry;
4901           abbrev_attr  * attr;
4902
4903           abbrev_number = read_leb128 (tags, & bytes_read, 0);
4904           tags += bytes_read;
4905
4906           /* A null DIE marks the end of a list of children.  */
4907           if (abbrev_number == 0)
4908             {
4909               --level;
4910               continue;
4911             }
4912
4913           /* Scan through the abbreviation list until we reach the
4914              correct entry.  */
4915           for (entry = first_abbrev;
4916                entry && entry->entry != abbrev_number;
4917                entry = entry->next)
4918             continue;
4919
4920           if (entry == NULL)
4921             {
4922               warn (_("Unable to locate entry %d in the abbreviation table\n"),
4923                     abbrev_number);
4924               return 0;
4925             }
4926
4927           printf (_(" <%d><%x>: Abbrev Number: %d (%s)\n"),
4928                   level, tags - section_begin - bytes_read,
4929                   abbrev_number,
4930                   get_TAG_name (entry->tag));
4931
4932           for (attr = entry->first_attr; attr; attr = attr->next)
4933             tags = read_and_display_attr (attr->attribute,
4934                                           attr->form,
4935                                           tags,
4936                                           compunit.cu_pointer_size);
4937
4938           if (entry->children)
4939             ++level;
4940         }
4941     }
4942
4943   printf ("\n");
4944
4945   return 1;
4946 }
4947
4948 static int
4949 display_debug_aranges (section, start, file)
4950      Elf32_Internal_Shdr * section;
4951      unsigned char *       start;
4952      FILE *                file;
4953 {
4954   unsigned char * end = start + section->sh_size;
4955
4956   printf (_("The section %s contains:\n\n"), SECTION_NAME (section));
4957
4958   while (start < end)
4959     {
4960       DWARF2_External_ARange * external;
4961       DWARF2_Internal_ARange   arange;
4962       unsigned char *          ranges;
4963       unsigned long            length;
4964       unsigned long            address;
4965
4966       external = (DWARF2_External_ARange *) start;
4967
4968       arange.ar_length       = BYTE_GET (external->ar_length);
4969       arange.ar_version      = BYTE_GET (external->ar_version);
4970       arange.ar_info_offset  = BYTE_GET (external->ar_info_offset);
4971       arange.ar_pointer_size = BYTE_GET (external->ar_pointer_size);
4972       arange.ar_segment_size = BYTE_GET (external->ar_segment_size);
4973
4974       printf (_("  Length:                   %ld\n"), arange.ar_length);
4975       printf (_("  Version:                  %d\n"), arange.ar_version);
4976       printf (_("  Offset into .debug_info:  %lx\n"), arange.ar_info_offset);
4977       printf (_("  Pointer Size:             %d\n"), arange.ar_pointer_size);
4978       printf (_("  Segment Size:             %d\n"), arange.ar_segment_size);
4979
4980       printf (_("\n    Address  Length\n"));
4981
4982       ranges = start + sizeof (* external);
4983
4984       for (;;)
4985         {
4986           address = byte_get (ranges, arange.ar_pointer_size);
4987
4988           if (address == 0)
4989             break;
4990
4991           ranges += arange.ar_pointer_size;
4992
4993           length  = byte_get (ranges, arange.ar_pointer_size);
4994
4995           ranges += arange.ar_pointer_size;
4996
4997           printf ("    %8.8lx %lu\n", address, length);
4998         }
4999
5000       start += arange.ar_length + sizeof (external->ar_length);
5001     }
5002
5003   printf ("\n");
5004
5005   return 1;
5006 }
5007
5008
5009 static int
5010 display_debug_not_supported (section, start, file)
5011      Elf32_Internal_Shdr * section;
5012      unsigned char *       start;
5013      FILE *                file;
5014 {
5015   printf (_("Displaying the debug contents of section %s is not yet supported.\n"),
5016             SECTION_NAME (section));
5017
5018   return 1;
5019 }
5020
5021   /* A structure containing the name of a debug section and a pointer
5022      to a function that can decode it.  */
5023 struct
5024 {
5025   char * name;
5026   int (* display) PARAMS((Elf32_Internal_Shdr *, unsigned char *, FILE *));
5027 }
5028 debug_displays[] =
5029 {
5030   { ".debug_info",        display_debug_info },
5031   { ".debug_abbrev",      display_debug_abbrev },
5032   { ".debug_line",        display_debug_lines },
5033   { ".debug_aranges",     display_debug_aranges },
5034   { ".debug_pubnames",    display_debug_pubnames },
5035   { ".debug_macinfo",     display_debug_not_supported },
5036   { ".debug_frame",       display_debug_not_supported },
5037   { ".debug_str",         display_debug_not_supported },
5038   { ".debug_static_func", display_debug_not_supported },
5039   { ".debug_static_vars", display_debug_not_supported },
5040   { ".debug_types",       display_debug_not_supported },
5041   { ".debug_weaknames",   display_debug_not_supported }
5042 };
5043
5044 static int
5045 display_debug_section (section, file)
5046      Elf32_Internal_Shdr * section;
5047      FILE * file;
5048 {
5049   char *          name = SECTION_NAME (section);
5050   bfd_size_type   length;
5051   unsigned char * start;
5052   int             i;
5053
5054   length = section->sh_size;
5055   if (length == 0)
5056     {
5057       printf (_("\nSection '%s' has no debugging data.\n"), name);
5058       return 0;
5059     }
5060
5061   GET_DATA_ALLOC (section->sh_offset, length, start, unsigned char *,
5062                   "debug section data");
5063
5064   /* See if we know how to display the contents of this section.  */
5065   for (i = NUM_ELEM (debug_displays); i--;)
5066     if (strcmp (debug_displays[i].name, name) == 0)
5067       {
5068         debug_displays[i].display (section, start, file);
5069         break;
5070       }
5071
5072   if (i == -1)
5073     printf (_("Unrecognised debug section: %s\n"), name);
5074
5075   free (start);
5076
5077   /* If we loaded in the abbrev section at some point,
5078      we must release it here.  */
5079   if (first_abbrev != NULL)
5080     free_abbrevs ();
5081
5082   return 1;
5083 }
5084
5085 static int
5086 process_section_contents (file)
5087      FILE * file;
5088 {
5089   Elf32_Internal_Shdr *    section;
5090   unsigned int  i;
5091
5092   if (! do_dump)
5093     return 1;
5094
5095   for (i = 0, section = section_headers;
5096        i < elf_header.e_shnum
5097        && i < num_dump_sects;
5098        i ++, section ++)
5099     {
5100 #ifdef SUPPORT_DISASSEMBLY
5101       if (dump_sects[i] & DISASS_DUMP)
5102         disassemble_section (section, file);
5103 #endif
5104       if (dump_sects[i] & HEX_DUMP)
5105         dump_section (section, file);
5106
5107       if (dump_sects[i] & DEBUG_DUMP)
5108         display_debug_section (section, file);
5109     }
5110
5111   if (i < num_dump_sects)
5112     warn (_("Some sections were not dumped because they do not exist!\n"));
5113
5114   return 1;
5115 }
5116
5117 static void
5118 process_mips_fpe_exception (mask)
5119      int mask;
5120 {
5121   if (mask)
5122     {
5123       int first = 1;
5124       if (mask & OEX_FPU_INEX)
5125         fputs ("INEX", stdout), first = 0;
5126       if (mask & OEX_FPU_UFLO)
5127         printf ("%sUFLO", first ? "" : "|"), first = 0;
5128       if (mask & OEX_FPU_OFLO)
5129         printf ("%sOFLO", first ? "" : "|"), first = 0;
5130       if (mask & OEX_FPU_DIV0)
5131         printf ("%sDIV0", first ? "" : "|"), first = 0;
5132       if (mask & OEX_FPU_INVAL)
5133         printf ("%sINVAL", first ? "" : "|");
5134     }
5135   else
5136     fputs ("0", stdout);
5137 }
5138
5139 static int
5140 process_mips_specific (file)
5141      FILE *file;
5142 {
5143   Elf_Internal_Dyn *entry;
5144   size_t liblist_offset = 0;
5145   size_t liblistno = 0;
5146   size_t conflictsno = 0;
5147   size_t options_offset = 0;
5148   size_t conflicts_offset = 0;
5149
5150   /* We have a lot of special sections.  Thanks SGI!  */
5151   if (dynamic_segment == NULL)
5152     /* No information available.  */
5153     return 0;
5154
5155   for (entry = dynamic_segment; entry->d_tag != DT_NULL; ++entry)
5156     switch (entry->d_tag)
5157       {
5158       case DT_MIPS_LIBLIST:
5159         liblist_offset = entry->d_un.d_val - loadaddr;
5160         break;
5161       case DT_MIPS_LIBLISTNO:
5162         liblistno = entry->d_un.d_val;
5163         break;
5164       case DT_MIPS_OPTIONS:
5165         options_offset = entry->d_un.d_val - loadaddr;
5166         break;
5167       case DT_MIPS_CONFLICT:
5168         conflicts_offset = entry->d_un.d_val - loadaddr;
5169         break;
5170       case DT_MIPS_CONFLICTNO:
5171         conflictsno = entry->d_un.d_val;
5172         break;
5173       default:
5174         break;
5175       }
5176
5177   if (liblist_offset != 0 && liblistno != 0 && do_dynamic)
5178     {
5179       Elf32_External_Lib *elib;
5180       size_t cnt;
5181
5182       GET_DATA_ALLOC (liblist_offset, liblistno * sizeof (Elf32_External_Lib),
5183                       elib, Elf32_External_Lib *, "liblist");
5184
5185       printf ("\nSection '.liblist' contains %d entries:\n", liblistno);
5186       fputs ("     Library              Time Stamp          Checksum   Version Flags\n",
5187              stdout);
5188
5189       for (cnt = 0; cnt < liblistno; ++cnt)
5190         {
5191           Elf32_Lib liblist;
5192           time_t time;
5193           char timebuf[20];
5194
5195           liblist.l_name = BYTE_GET (elib[cnt].l_name);
5196           time = BYTE_GET (elib[cnt].l_time_stamp);
5197           liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum);
5198           liblist.l_version = BYTE_GET (elib[cnt].l_version);
5199           liblist.l_flags = BYTE_GET (elib[cnt].l_flags);
5200
5201           strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time));
5202
5203           printf ("%3d: %-20s %s %#10lx %-7ld", cnt,
5204                   dynamic_strings + liblist.l_name, timebuf,
5205                   liblist.l_checksum, liblist.l_version);
5206
5207           if (liblist.l_flags == 0)
5208             puts (" NONE");
5209           else
5210             {
5211               static const struct
5212               {
5213                 const char *name;
5214                 int bit;
5215               } l_flags_vals[] =
5216                 {
5217                   { " EXACT_MATCH", LL_EXACT_MATCH },
5218                   { " IGNORE_INT_VER", LL_IGNORE_INT_VER },
5219                   { " REQUIRE_MINOR", LL_REQUIRE_MINOR },
5220                   { " EXPORTS", LL_EXPORTS },
5221                   { " DELAY_LOAD", LL_DELAY_LOAD },
5222                   { " DELTA", LL_DELTA }
5223                 };
5224               int flags = liblist.l_flags;
5225               int fcnt;
5226
5227               for (fcnt = 0;
5228                    fcnt < sizeof (l_flags_vals) / sizeof (l_flags_vals[0]);
5229                    ++fcnt)
5230                 if ((flags & l_flags_vals[fcnt].bit) != 0)
5231                   {
5232                     fputs (l_flags_vals[fcnt].name, stdout);
5233                     flags ^= l_flags_vals[fcnt].bit;
5234                   }
5235               if (flags != 0)
5236                 printf (" %#x", (unsigned int) flags);
5237
5238               puts ("");
5239             }
5240         }
5241
5242       free (elib);
5243     }
5244
5245   if (options_offset != 0)
5246     {
5247       Elf_External_Options *eopt;
5248       Elf_Internal_Shdr *sect = section_headers;
5249       Elf_Internal_Options *iopt;
5250       Elf_Internal_Options *option;
5251       size_t offset;
5252       int cnt;
5253
5254       /* Find the section header so that we get the size.  */
5255       while (sect->sh_type != SHT_MIPS_OPTIONS)
5256         ++sect;
5257
5258       GET_DATA_ALLOC (options_offset, sect->sh_size, eopt,
5259                       Elf_External_Options *, "options");
5260
5261       iopt = (Elf_Internal_Options *) malloc ((sect->sh_size / sizeof (eopt))
5262                                               * sizeof (*iopt));
5263       if (iopt == NULL)
5264         {
5265           error (_("Out of memory"));
5266           return 0;
5267         }
5268
5269       offset = cnt = 0;
5270       option = iopt;
5271       while (offset < sect->sh_size)
5272         {
5273           Elf_External_Options *eoption;
5274
5275           eoption = (Elf_External_Options *) ((char *) eopt + offset);
5276
5277           option->kind = BYTE_GET (eoption->kind);
5278           option->size = BYTE_GET (eoption->size);
5279           option->section = BYTE_GET (eoption->section);
5280           option->info = BYTE_GET (eoption->info);
5281
5282           offset += option->size;
5283           ++option;
5284           ++cnt;
5285         }
5286
5287       printf (_("\nSection '%s' contains %d entries:\n"),
5288               string_table + sect->sh_name, cnt);
5289
5290       option = iopt;
5291       while (cnt-- > 0)
5292         {
5293           size_t len;
5294
5295           switch (option->kind)
5296             {
5297             case ODK_NULL:
5298               /* This shouldn't happen.  */
5299               printf (" NULL       %d %lx", option->section, option->info);
5300               break;
5301             case ODK_REGINFO:
5302               printf (" REGINFO    ");
5303               if (elf_header.e_machine == EM_MIPS)
5304                 {
5305                   /* 32bit form.  */
5306                   Elf32_External_RegInfo *ereg;
5307                   Elf32_RegInfo reginfo;
5308
5309                   ereg = (Elf32_External_RegInfo *) (option + 1);
5310                   reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
5311                   reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
5312                   reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
5313                   reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
5314                   reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
5315                   reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
5316
5317                   printf ("GPR %08lx  GP 0x%lx\n",
5318                           reginfo.ri_gprmask,
5319                           (unsigned long) reginfo.ri_gp_value);
5320                   printf ("            CPR0 %08lx  CPR1 %08lx  CPR2 %08lx  CPR3 %08lx\n",
5321                           reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
5322                           reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
5323                 }
5324               else
5325                 {
5326                   /* 64 bit form.  */
5327                   Elf64_External_RegInfo *ereg;
5328                   Elf64_Internal_RegInfo reginfo;
5329
5330                   ereg = (Elf64_External_RegInfo *) (option + 1);
5331                   reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
5332                   reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
5333                   reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
5334                   reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
5335                   reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
5336                   reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
5337
5338                   printf ("GPR %08lx  GP 0x",
5339                           reginfo.ri_gprmask);
5340                   printf_vma (reginfo.ri_gp_value);
5341                   printf ("\n");
5342
5343                   printf ("            CPR0 %08lx  CPR1 %08lx  CPR2 %08lx  CPR3 %08lx\n",
5344                           reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
5345                           reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
5346                 }
5347               ++option;
5348               continue;
5349             case ODK_EXCEPTIONS:
5350               fputs (" EXCEPTIONS fpe_min(", stdout);
5351               process_mips_fpe_exception (option->info & OEX_FPU_MIN);
5352               fputs (") fpe_max(", stdout);
5353               process_mips_fpe_exception ((option->info & OEX_FPU_MAX) >> 8);
5354               fputs (")", stdout);
5355
5356               if (option->info & OEX_PAGE0)
5357                 fputs (" PAGE0", stdout);
5358               if (option->info & OEX_SMM)
5359                 fputs (" SMM", stdout);
5360               if (option->info & OEX_FPDBUG)
5361                 fputs (" FPDBUG", stdout);
5362               if (option->info & OEX_DISMISS)
5363                 fputs (" DISMISS", stdout);
5364               break;
5365             case ODK_PAD:
5366               fputs (" PAD       ", stdout);
5367               if (option->info & OPAD_PREFIX)
5368                 fputs (" PREFIX", stdout);
5369               if (option->info & OPAD_POSTFIX)
5370                 fputs (" POSTFIX", stdout);
5371               if (option->info & OPAD_SYMBOL)
5372                 fputs (" SYMBOL", stdout);
5373               break;
5374             case ODK_HWPATCH:
5375               fputs (" HWPATCH   ", stdout);
5376               if (option->info & OHW_R4KEOP)
5377                 fputs (" R4KEOP", stdout);
5378               if (option->info & OHW_R8KPFETCH)
5379                 fputs (" R8KPFETCH", stdout);
5380               if (option->info & OHW_R5KEOP)
5381                 fputs (" R5KEOP", stdout);
5382               if (option->info & OHW_R5KCVTL)
5383                 fputs (" R5KCVTL", stdout);
5384               break;
5385             case ODK_FILL:
5386               fputs (" FILL       ", stdout);
5387               /* XXX Print content of info word?  */
5388               break;
5389             case ODK_TAGS:
5390               fputs (" TAGS       ", stdout);
5391               /* XXX Print content of info word?  */
5392               break;
5393             case ODK_HWAND:
5394               fputs (" HWAND     ", stdout);
5395               if (option->info & OHWA0_R4KEOP_CHECKED)
5396                 fputs (" R4KEOP_CHECKED", stdout);
5397               if (option->info & OHWA0_R4KEOP_CLEAN)
5398                 fputs (" R4KEOP_CLEAN", stdout);
5399               break;
5400             case ODK_HWOR:
5401               fputs (" HWOR      ", stdout);
5402               if (option->info & OHWA0_R4KEOP_CHECKED)
5403                 fputs (" R4KEOP_CHECKED", stdout);
5404               if (option->info & OHWA0_R4KEOP_CLEAN)
5405                 fputs (" R4KEOP_CLEAN", stdout);
5406               break;
5407             case ODK_GP_GROUP:
5408               printf (" GP_GROUP  %#06lx  self-contained %#06lx",
5409                       option->info & OGP_GROUP,
5410                       (option->info & OGP_SELF) >> 16);
5411               break;
5412             case ODK_IDENT:
5413               printf (" IDENT     %#06lx  self-contained %#06lx",
5414                       option->info & OGP_GROUP,
5415                       (option->info & OGP_SELF) >> 16);
5416               break;
5417             default:
5418               /* This shouldn't happen.  */
5419               printf (" %3d ???     %d %lx",
5420                       option->kind, option->section, option->info);
5421               break;
5422             }
5423
5424           len = sizeof (*eopt);
5425           while (len < option->size)
5426             if (((char *) option)[len] >= ' '
5427                 && ((char *) option)[len] < 0x7f)
5428               printf ("%c", ((char *) option)[len++]);
5429             else
5430               printf ("\\%03o", ((char *) option)[len++]);
5431
5432           fputs ("\n", stdout);
5433           ++option;
5434         }
5435
5436       free (eopt);
5437     }
5438
5439   if (conflicts_offset != 0 && conflictsno != 0)
5440     {
5441       Elf32_External_Conflict *econf32;
5442       Elf64_External_Conflict *econf64;
5443       Elf32_Conflict *iconf;
5444       size_t cnt;
5445
5446       if (dynamic_symbols == NULL)
5447         {
5448           error (_("conflict list with without table"));
5449           return 0;
5450         }
5451
5452       iconf = (Elf32_Conflict *) malloc (conflictsno * sizeof (*iconf));
5453       if (iconf == NULL)
5454         {
5455           error (_("Out of memory"));
5456           return 0;
5457         }
5458
5459       if (binary_class == ELFCLASS32)
5460         {
5461           GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (*econf32),
5462                           econf32, Elf32_External_Conflict *, "conflict");
5463
5464           for (cnt = 0; cnt < conflictsno; ++cnt)
5465             iconf[cnt] = BYTE_GET (econf32[cnt]);
5466         }
5467       else
5468         {
5469           GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (*econf64),
5470                           econf64, Elf64_External_Conflict *, "conflict");
5471
5472           for (cnt = 0; cnt < conflictsno; ++cnt)
5473             iconf[cnt] = BYTE_GET (econf64[cnt]);
5474         }
5475
5476       printf (_("\nSection '.conflict' contains %d entries:\n"), conflictsno);
5477       puts (_("  Num:    Index       Value  Name"));
5478
5479       for (cnt = 0; cnt < conflictsno; ++cnt)
5480         {
5481           Elf_Internal_Sym *psym = &dynamic_symbols[iconf[cnt]];
5482
5483           printf ("%5u: %8lu  %#10lx  %s\n",
5484                   cnt, iconf[cnt], (unsigned long) psym->st_value,
5485                   dynamic_strings + psym->st_name);
5486         }
5487
5488
5489       free (iconf);
5490     }
5491
5492   return 1;
5493 }
5494
5495 static int
5496 process_arch_specific (file)
5497      FILE *file;
5498 {
5499   switch (elf_header.e_machine)
5500     {
5501     case EM_MIPS:
5502     case EM_MIPS_RS4_BE:
5503       return process_mips_specific (file);
5504       break;
5505     default:
5506       break;
5507     }
5508   return 1;
5509 }
5510
5511 static int
5512 get_file_header (file)
5513      FILE * file;
5514 {
5515   Elf32_External_Ehdr ehdr;
5516
5517   if (fread (& ehdr, sizeof (ehdr), 1, file) != 1)
5518     return 0;
5519
5520   memcpy (elf_header.e_ident, ehdr.e_ident, EI_NIDENT);
5521
5522   if (elf_header.e_ident [EI_DATA] == ELFDATA2LSB)
5523     byte_get = byte_get_little_endian;
5524   else
5525     byte_get = byte_get_big_endian;
5526
5527   elf_header.e_entry     = BYTE_GET (ehdr.e_entry);
5528   elf_header.e_phoff     = BYTE_GET (ehdr.e_phoff);
5529   elf_header.e_shoff     = BYTE_GET (ehdr.e_shoff);
5530   elf_header.e_version   = BYTE_GET (ehdr.e_version);
5531   elf_header.e_flags     = BYTE_GET (ehdr.e_flags);
5532   elf_header.e_type      = BYTE_GET (ehdr.e_type);
5533   elf_header.e_machine   = BYTE_GET (ehdr.e_machine);
5534   elf_header.e_ehsize    = BYTE_GET (ehdr.e_ehsize);
5535   elf_header.e_phentsize = BYTE_GET (ehdr.e_phentsize);
5536   elf_header.e_phnum     = BYTE_GET (ehdr.e_phnum);
5537   elf_header.e_shentsize = BYTE_GET (ehdr.e_shentsize);
5538   elf_header.e_shnum     = BYTE_GET (ehdr.e_shnum);
5539   elf_header.e_shstrndx  = BYTE_GET (ehdr.e_shstrndx);
5540
5541   return 1;
5542 }
5543
5544 static void
5545 process_file (file_name)
5546      char * file_name;
5547 {
5548   FILE *       file;
5549   struct stat  statbuf;
5550   unsigned int i;
5551
5552   if (stat (file_name, & statbuf) < 0)
5553     {
5554       error (_("Cannot stat input file %s.\n"), file_name);
5555       return;
5556     }
5557
5558   file = fopen (file_name, "rb");
5559   if (file == NULL)
5560     {
5561       error (_("Input file %s not found.\n"), file_name);
5562       return;
5563     }
5564
5565   if (! get_file_header (file))
5566     {
5567       error (_("%s: Failed to read file header\n"), file_name);
5568       fclose (file);
5569       return;
5570     }
5571
5572   /* Initialise per file variables.  */
5573   for (i = NUM_ELEM (version_info); i--;)
5574     version_info[i] = 0;
5575
5576   for (i = NUM_ELEM (dynamic_info); i--;)
5577     dynamic_info[i] = 0;
5578
5579   /* Process the file.  */
5580   if (show_name)
5581     printf (_("\nFile: %s\n"), file_name);
5582
5583   if (! process_file_header ())
5584     {
5585       fclose (file);
5586       return;
5587     }
5588
5589   process_section_headers (file);
5590
5591   process_program_headers (file);
5592
5593   process_dynamic_segment (file);
5594
5595   process_relocs (file);
5596
5597   process_symbol_table (file);
5598
5599   process_syminfo (file);
5600
5601   process_version_sections (file);
5602
5603   process_section_contents (file);
5604
5605   process_arch_specific (file);
5606
5607   fclose (file);
5608
5609   if (section_headers)
5610     {
5611       free (section_headers);
5612       section_headers = NULL;
5613     }
5614
5615   if (string_table)
5616     {
5617       free (string_table);
5618       string_table = NULL;
5619     }
5620
5621   if (dynamic_strings)
5622     {
5623       free (dynamic_strings);
5624       dynamic_strings = NULL;
5625     }
5626
5627   if (dynamic_symbols)
5628     {
5629       free (dynamic_symbols);
5630       dynamic_symbols = NULL;
5631     }
5632
5633   if (dynamic_syminfo)
5634     {
5635       free (dynamic_syminfo);
5636       dynamic_syminfo = NULL;
5637     }
5638 }
5639
5640 #ifdef SUPPORT_DISASSEMBLY
5641 /* Needed by the i386 disassembler.  For extra credit, someone could
5642 fix this so that we insert symbolic addresses here, esp for GOT/PLT
5643 symbols */
5644
5645 void
5646 print_address (unsigned int addr, FILE * outfile)
5647 {
5648   fprintf (outfile,"0x%8.8x", addr);
5649 }
5650
5651 /* Needed by the i386 disassembler. */
5652 void
5653 db_task_printsym (unsigned int addr)
5654 {
5655   print_address (addr, stderr);
5656 }
5657 #endif
5658
5659 int
5660 main (argc, argv)
5661      int     argc;
5662      char ** argv;
5663 {
5664 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
5665   setlocale (LC_MESSAGES, "");
5666 #endif
5667   bindtextdomain (PACKAGE, LOCALEDIR);
5668   textdomain (PACKAGE);
5669
5670   parse_args (argc, argv);
5671
5672   if (optind < (argc - 1))
5673     show_name = 1;
5674
5675   while (optind < argc)
5676     process_file (argv [optind ++]);
5677
5678   if (dump_sects != NULL)
5679     free (dump_sects);
5680
5681   return 0;
5682 }