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