OSDN Git Service

fix typo.
[pf3gnuchains/pf3gnuchains3x.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   switch (elf_class)
1357     {
1358     case ELFCLASSNONE: return _("none");
1359     case ELFCLASS32:   return _("ELF32");
1360     case ELFCLASS64:   return _("ELF64");
1361     default:           return _("<unknown>");
1362     }
1363 }
1364
1365 static const char *
1366 get_data_encoding (encoding)
1367      unsigned char encoding;
1368 {
1369   switch (encoding)
1370     {
1371     case ELFDATANONE: return _("none");
1372     case ELFDATA2LSB: return _("2's complement, little endian");
1373     case ELFDATA2MSB: return _("2's complement, big endian");
1374     default:          return _("<unknown>");
1375     }
1376 }
1377
1378 static const char *
1379 get_osabi_name (osabi)
1380      unsigned char osabi;
1381 {
1382   switch (osabi)
1383     {
1384     case ELFOSABI_SYSV:       return _("UNIX - System V");
1385     case ELFOSABI_HPUX:       return _("UNIX - HP-UX");
1386     case ELFOSABI_STANDALONE: return _("Standalone App");
1387     default:                  return _("<unknown>");
1388     }
1389 }
1390
1391 /* Decode the data held in 'elf_header'.  */
1392 static int
1393 process_file_header ()
1394 {
1395   if (   elf_header.e_ident [EI_MAG0] != ELFMAG0
1396       || elf_header.e_ident [EI_MAG1] != ELFMAG1
1397       || elf_header.e_ident [EI_MAG2] != ELFMAG2
1398       || elf_header.e_ident [EI_MAG3] != ELFMAG3)
1399     {
1400       error
1401         (_("Not an ELF file - it has the wrong magic bytes at the start\n"));
1402       return 0;
1403     }
1404
1405   if (do_header)
1406     {
1407       int i;
1408
1409       printf (_("ELF Header:\n"));
1410       printf (_("  Magic:   "));
1411       for (i = 0; i < EI_NIDENT; i ++)
1412         printf ("%2.2x ", elf_header.e_ident [i]);
1413       printf ("\n");
1414       printf (_("  Class:                             %s\n"),
1415               get_elf_class (elf_header.e_ident [EI_CLASS]));
1416       printf (_("  Data:                              %s\n"),
1417               get_data_encoding (elf_header.e_ident [EI_DATA]));
1418       printf (_("  Version:                           %d %s\n"),
1419               elf_header.e_ident [EI_VERSION],
1420               elf_header.e_ident [EI_VERSION] == EV_CURRENT ? "(current)" :
1421               elf_header.e_ident [EI_VERSION] != EV_NONE ? "<unknown>" : "");
1422       printf (_("  OS/ABI:                            %s\n"),
1423               get_osabi_name (elf_header.e_ident [EI_OSABI]));
1424       printf (_("  ABI Version:                       %d\n"),
1425               elf_header.e_ident [EI_ABIVERSION]);
1426       printf (_("  Type:                              %s\n"),
1427               get_file_type (elf_header.e_type));
1428       printf (_("  Machine:                           %s\n"),
1429               get_machine_name (elf_header.e_machine));
1430       printf (_("  Version:                           0x%lx\n"),
1431               (unsigned long) elf_header.e_version);
1432       printf (_("  Data:                              %s\n"),
1433               get_machine_data (elf_header.e_ident [EI_DATA]));
1434       printf (_("  Entry point address:               0x%lx\n"),
1435               (unsigned long) elf_header.e_entry);
1436       printf (_("  Start of program headers:          %ld (bytes into file)\n"),
1437               (long) elf_header.e_phoff);
1438       printf (_("  Start of section headers:          %ld (bytes into file)\n"),
1439               (long) elf_header.e_shoff);
1440       printf (_("  Flags:                             0x%lx%s\n"),
1441               (unsigned long) elf_header.e_flags,
1442               get_machine_flags (elf_header.e_flags, elf_header.e_machine));
1443       printf (_("  Size of this header:               %ld (bytes)\n"),
1444               (long) elf_header.e_ehsize);
1445       printf (_("  Size of program headers:           %ld (bytes)\n"),
1446               (long) elf_header.e_phentsize);
1447       printf (_("  Number of program headers:         %ld\n"),
1448               (long) elf_header.e_phnum);
1449       printf (_("  Size of section headers:           %ld (bytes)\n"),
1450               (long) elf_header.e_shentsize);
1451       printf (_("  Number of section headers:         %ld\n"),
1452               (long) elf_header.e_shnum);
1453       printf (_("  Section header string table index: %ld\n"),
1454               (long) elf_header.e_shstrndx);
1455     }
1456
1457   /* Test class after dumping header so that at least the header can be
1458      display on 64 bit binaries.  */
1459   
1460   binary_class = elf_header.e_ident [EI_CLASS];
1461   if (binary_class != ELFCLASS32)
1462     {
1463       error (_("Not a 32 bit ELF file\n"));
1464       return 0;
1465     }
1466
1467   return 1;
1468 }
1469
1470
1471 static int
1472 process_program_headers (file)
1473      FILE * file;
1474 {
1475   Elf32_External_Phdr * phdrs;
1476   Elf32_Internal_Phdr * program_headers;
1477   Elf32_Internal_Phdr * segment;
1478   unsigned int          i;
1479
1480   if (elf_header.e_phnum == 0)
1481     {
1482       if (do_segments)
1483         printf (_("\nThere are no program headers in this file.\n"));
1484       return 1;
1485     }
1486
1487   if (do_segments && !do_header)
1488     {
1489       printf (_("\nElf file is %s\n"), get_file_type (elf_header.e_type));
1490       printf (_("Entry point 0x%lx\n"), (unsigned long) elf_header.e_entry);
1491       printf (_("There are %d program headers, starting at offset %lx:\n"),
1492               elf_header.e_phnum, (unsigned long) elf_header.e_phoff);
1493     }
1494
1495   GET_DATA_ALLOC (elf_header.e_phoff,
1496                   elf_header.e_phentsize * elf_header.e_phnum,
1497                   phdrs, Elf32_External_Phdr *, "program headers");
1498
1499   program_headers = (Elf32_Internal_Phdr *) malloc
1500     (elf_header.e_phnum * sizeof (Elf32_Internal_Phdr));
1501
1502   if (program_headers == NULL)
1503     {
1504       error (_("Out of memory\n"));
1505       return 0;
1506     }
1507
1508   for (i = 0, segment = program_headers;
1509        i < elf_header.e_phnum;
1510        i ++, segment ++)
1511     {
1512       segment->p_type   = BYTE_GET (phdrs[i].p_type);
1513       segment->p_offset = BYTE_GET (phdrs[i].p_offset);
1514       segment->p_vaddr  = BYTE_GET (phdrs[i].p_vaddr);
1515       segment->p_paddr  = BYTE_GET (phdrs[i].p_paddr);
1516       segment->p_filesz = BYTE_GET (phdrs[i].p_filesz);
1517       segment->p_memsz  = BYTE_GET (phdrs[i].p_memsz);
1518       segment->p_flags  = BYTE_GET (phdrs[i].p_flags);
1519       segment->p_align  = BYTE_GET (phdrs[i].p_align);
1520     }
1521
1522   free (phdrs);
1523
1524   if (do_segments)
1525     {
1526       printf
1527         (_("\nProgram Header%s:\n"), elf_header.e_phnum > 1 ? "s" : "");
1528       printf
1529         (_("  Type        Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align\n"));
1530     }
1531
1532   loadaddr = -1;
1533   dynamic_addr = 0;
1534   dynamic_size = 0;
1535
1536   for (i = 0, segment = program_headers;
1537        i < elf_header.e_phnum;
1538        i ++, segment ++)
1539     {
1540       if (do_segments)
1541         {
1542           printf ("  %-11.11s ", get_segment_type (segment->p_type));
1543           printf ("0x%6.6lx ", (unsigned long) segment->p_offset);
1544           printf ("0x%8.8lx ", (unsigned long) segment->p_vaddr);
1545           printf ("0x%8.8lx ", (unsigned long) segment->p_paddr);
1546           printf ("0x%5.5lx ", (unsigned long) segment->p_filesz);
1547           printf ("0x%5.5lx ", (unsigned long) segment->p_memsz);
1548           printf ("%c%c%c ",
1549                   (segment->p_flags & PF_R ? 'R' : ' '),
1550                   (segment->p_flags & PF_W ? 'W' : ' '),
1551                   (segment->p_flags & PF_X ? 'E' : ' '));
1552           printf ("%#lx", (unsigned long) segment->p_align);
1553         }
1554
1555       switch (segment->p_type)
1556         {
1557         case PT_LOAD:
1558           if (loadaddr == -1)
1559             loadaddr = (segment->p_vaddr & 0xfffff000)
1560               - (segment->p_offset & 0xfffff000);
1561           break;
1562
1563         case PT_DYNAMIC:
1564           if (dynamic_addr)
1565             error (_("more than one dynamic segment\n"));
1566
1567           dynamic_addr = segment->p_offset;
1568           dynamic_size = segment->p_filesz;
1569           break;
1570
1571         case PT_INTERP:
1572           if (fseek (file, segment->p_offset, SEEK_SET))
1573             error (_("Unable to find program interpreter name\n"));
1574           else
1575             {
1576               program_interpreter[0] = 0;
1577               fscanf (file, "%63s", program_interpreter);
1578
1579               if (do_segments)
1580                 printf (_("\n      [Requesting program interpreter: %s]"),
1581                     program_interpreter);
1582             }
1583           break;
1584         }
1585
1586       if (do_segments)
1587         putc ('\n', stdout);
1588     }
1589
1590   if (loadaddr == -1)
1591     {
1592       /* Very strange. */
1593       loadaddr = 0;
1594     }
1595
1596   if (do_segments && section_headers != NULL)
1597     {
1598       printf (_("\n Section to Segment mapping:\n"));
1599       printf (_("  Segment Sections...\n"));
1600
1601       assert (string_table != NULL);
1602
1603       for (i = 0; i < elf_header.e_phnum; i++)
1604         {
1605           int        j;
1606           Elf32_Internal_Shdr * section;
1607
1608           segment = program_headers + i;
1609           section = section_headers;
1610
1611           printf ("   %2.2d     ", i);
1612
1613           for (j = 0; j < elf_header.e_shnum; j++, section ++)
1614             {
1615               if (section->sh_size > 0
1616                   /* Compare allocated sections by VMA, unallocated
1617                      sections by file offset.  */
1618                   && (section->sh_flags & SHF_ALLOC
1619                       ? (section->sh_addr >= segment->p_vaddr
1620                          && section->sh_addr + section->sh_size
1621                          <= segment->p_vaddr + segment->p_memsz)
1622                       : (section->sh_offset >= segment->p_offset
1623                          && (section->sh_offset + section->sh_size
1624                              <= segment->p_offset + segment->p_filesz))))
1625                 printf ("%s ", SECTION_NAME (section));
1626             }
1627
1628           putc ('\n',stdout);
1629         }
1630     }
1631
1632   free (program_headers);
1633
1634   return 1;
1635 }
1636
1637
1638 static int
1639 get_section_headers (file)
1640      FILE * file;
1641 {
1642   Elf32_External_Shdr * shdrs;
1643   Elf32_Internal_Shdr * internal;
1644   unsigned int          i;
1645
1646   GET_DATA_ALLOC (elf_header.e_shoff,
1647                   elf_header.e_shentsize * elf_header.e_shnum,
1648                   shdrs, Elf32_External_Shdr *, "section headers");
1649
1650   section_headers = (Elf32_Internal_Shdr *) malloc
1651     (elf_header.e_shnum * sizeof (Elf32_Internal_Shdr));
1652
1653   if (section_headers == NULL)
1654     {
1655       error (_("Out of memory\n"));
1656       return 0;
1657     }
1658
1659   for (i = 0, internal = section_headers;
1660        i < elf_header.e_shnum;
1661        i ++, internal ++)
1662     {
1663       internal->sh_name      = BYTE_GET (shdrs[i].sh_name);
1664       internal->sh_type      = BYTE_GET (shdrs[i].sh_type);
1665       internal->sh_flags     = BYTE_GET (shdrs[i].sh_flags);
1666       internal->sh_addr      = BYTE_GET (shdrs[i].sh_addr);
1667       internal->sh_offset    = BYTE_GET (shdrs[i].sh_offset);
1668       internal->sh_size      = BYTE_GET (shdrs[i].sh_size);
1669       internal->sh_link      = BYTE_GET (shdrs[i].sh_link);
1670       internal->sh_info      = BYTE_GET (shdrs[i].sh_info);
1671       internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
1672       internal->sh_entsize   = BYTE_GET (shdrs[i].sh_entsize);
1673     }
1674
1675   free (shdrs);
1676
1677   return 1;
1678 }
1679
1680 static Elf_Internal_Sym *
1681 get_elf_symbols (file, offset, number)
1682      FILE * file;
1683      unsigned long offset;
1684      unsigned long number;
1685 {
1686   Elf32_External_Sym * esyms;
1687   Elf_Internal_Sym *   isyms;
1688   Elf_Internal_Sym *   psym;
1689   unsigned int         j;
1690
1691   GET_DATA_ALLOC (offset, number * sizeof (Elf32_External_Sym),
1692                   esyms, Elf32_External_Sym *, "symbols");
1693
1694   isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym));
1695
1696   if (isyms == NULL)
1697     {
1698       error (_("Out of memory\n"));
1699       free (esyms);
1700
1701       return NULL;
1702     }
1703
1704   for (j = 0, psym = isyms;
1705        j < number;
1706        j ++, psym ++)
1707     {
1708       psym->st_name  = BYTE_GET (esyms[j].st_name);
1709       psym->st_value = BYTE_GET (esyms[j].st_value);
1710       psym->st_size  = BYTE_GET (esyms[j].st_size);
1711       psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
1712       psym->st_info  = BYTE_GET (esyms[j].st_info);
1713       psym->st_other = BYTE_GET (esyms[j].st_other);
1714     }
1715
1716   free (esyms);
1717
1718   return isyms;
1719 }
1720
1721 static int
1722 process_section_headers (file)
1723      FILE * file;
1724 {
1725   Elf32_Internal_Shdr * section;
1726   int        i;
1727
1728   section_headers = NULL;
1729
1730   if (elf_header.e_shnum == 0)
1731     {
1732       if (do_sections)
1733         printf (_("\nThere are no sections in this file.\n"));
1734
1735       return 1;
1736     }
1737
1738   if (do_sections && !do_header)
1739     printf (_("There are %d section headers, starting at offset %lx:\n"),
1740             elf_header.e_shnum, (unsigned long) elf_header.e_shoff);
1741
1742   if (! get_section_headers (file))
1743     return 0;
1744
1745   /* Read in the string table, so that we have names to display.  */
1746   section = section_headers + elf_header.e_shstrndx;
1747
1748   if (section->sh_size != 0)
1749     {
1750       unsigned long string_table_offset;
1751
1752       string_table_offset = section->sh_offset;
1753
1754       GET_DATA_ALLOC (section->sh_offset, section->sh_size,
1755                       string_table, char *, "string table");
1756     }
1757
1758   /* Scan the sections for the dynamic symbol table
1759      and dynamic string table and debug sections. */
1760   dynamic_symbols = NULL;
1761   dynamic_strings = NULL;
1762   dynamic_syminfo = NULL;
1763   for (i = 0, section = section_headers;
1764        i < elf_header.e_shnum;
1765        i ++, section ++)
1766     {
1767       char * name = SECTION_NAME (section);
1768
1769       if (section->sh_type == SHT_DYNSYM)
1770         {
1771           if (dynamic_symbols != NULL)
1772             {
1773               error (_("File contains multiple dynamic symbol tables\n"));
1774               continue;
1775             }
1776
1777           dynamic_symbols = get_elf_symbols
1778             (file, section->sh_offset,
1779              section->sh_size / section->sh_entsize);
1780         }
1781       else if (section->sh_type == SHT_STRTAB
1782                && strcmp (name, ".dynstr") == 0)
1783         {
1784           if (dynamic_strings != NULL)
1785             {
1786               error (_("File contains multiple dynamic string tables\n"));
1787               continue;
1788             }
1789
1790           GET_DATA_ALLOC (section->sh_offset, section->sh_size,
1791                           dynamic_strings, char *, "dynamic strings");
1792         }
1793       else if ((do_debugging || do_debug_info || do_debug_abbrevs
1794                 || do_debug_lines || do_debug_pubnames || do_debug_aranges)
1795                && strncmp (name, ".debug_", 7) == 0)
1796         {
1797           name += 7;
1798
1799           if (do_debugging
1800               || (do_debug_info     && (strcmp (name, "info") == 0))
1801               || (do_debug_abbrevs  && (strcmp (name, "abbrev") == 0))
1802               || (do_debug_lines    && (strcmp (name, "line") == 0))
1803               || (do_debug_pubnames && (strcmp (name, "pubnames") == 0))
1804               || (do_debug_aranges  && (strcmp (name, "aranges") == 0))
1805               )
1806             request_dump (i, DEBUG_DUMP);
1807         }
1808     }
1809
1810   if (! do_sections)
1811     return 1;
1812
1813   printf (_("\nSection Header%s:\n"), elf_header.e_shnum > 1 ? "s" : "");
1814   printf
1815     (_("  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al\n"));
1816
1817   for (i = 0, section = section_headers;
1818        i < elf_header.e_shnum;
1819        i ++, section ++)
1820     {
1821       printf ("  [%2d] %-17.17s %-15.15s ",
1822               i,
1823               SECTION_NAME (section),
1824               get_section_type_name (section->sh_type));
1825
1826       printf ( "%8.8lx %6.6lx %6.6lx %2.2lx",
1827                (unsigned long) section->sh_addr,
1828                (unsigned long) section->sh_offset,
1829                (unsigned long) section->sh_size,
1830                (unsigned long) section->sh_entsize);
1831
1832       printf (" %c%c%c %2ld %3lx %ld\n",
1833               (section->sh_flags & SHF_WRITE ? 'W' : ' '),
1834               (section->sh_flags & SHF_ALLOC ? 'A' : ' '),
1835               (section->sh_flags & SHF_EXECINSTR ? 'X' : ' '),
1836               (unsigned long) section->sh_link,
1837               (unsigned long) section->sh_info,
1838               (unsigned long) section->sh_addralign);
1839     }
1840
1841   return 1;
1842 }
1843
1844 /* Process the reloc section.  */
1845 static int
1846 process_relocs (file)
1847      FILE * file;
1848 {
1849   unsigned long    rel_size;
1850   unsigned long    rel_offset;
1851
1852
1853   if (!do_reloc)
1854     return 1;
1855
1856   if (do_using_dynamic)
1857     {
1858       int is_rela;
1859
1860       rel_size   = 0;
1861       rel_offset = 0;
1862
1863       if (dynamic_info[DT_REL])
1864         {
1865           rel_offset = dynamic_info[DT_REL];
1866           rel_size   = dynamic_info[DT_RELSZ];
1867           is_rela    = FALSE;
1868         }
1869       else if (dynamic_info [DT_RELA])
1870         {
1871           rel_offset = dynamic_info[DT_RELA];
1872           rel_size   = dynamic_info[DT_RELASZ];
1873           is_rela    = TRUE;
1874         }
1875       else if (dynamic_info[DT_JMPREL])
1876         {
1877           rel_offset = dynamic_info[DT_JMPREL];
1878           rel_size   = dynamic_info[DT_PLTRELSZ];
1879           is_rela    = UNKNOWN;
1880         }
1881
1882       if (rel_size)
1883         {
1884           printf
1885             (_("\nRelocation section at offset 0x%lx contains %ld bytes:\n"),
1886              rel_offset, rel_size);
1887
1888           dump_relocations (file, rel_offset - loadaddr, rel_size,
1889                             dynamic_symbols, dynamic_strings, is_rela);
1890         }
1891       else
1892         printf (_("\nThere are no dynamic relocations in this file.\n"));
1893     }
1894   else
1895     {
1896       Elf32_Internal_Shdr *     section;
1897       unsigned long             i;
1898       int                       found = 0;
1899
1900       for (i = 0, section = section_headers;
1901            i < elf_header.e_shnum;
1902            i++, section ++)
1903         {
1904           if (   section->sh_type != SHT_RELA
1905               && section->sh_type != SHT_REL)
1906             continue;
1907
1908           rel_offset = section->sh_offset;
1909           rel_size   = section->sh_size;
1910
1911           if (rel_size)
1912             {
1913               Elf32_Internal_Shdr * strsec;
1914               Elf32_Internal_Shdr * symsec;
1915               Elf_Internal_Sym *    symtab;
1916               char *                strtab;
1917               int                   is_rela;
1918               
1919               printf (_("\nRelocation section "));
1920
1921               if (string_table == NULL)
1922                 {
1923                   printf ("%d", section->sh_name);
1924                   is_rela = UNKNOWN;
1925                 }
1926               else
1927                 {
1928                   printf ("'%s'", SECTION_NAME (section));
1929
1930                   if (strncmp (".rela.", SECTION_NAME (section), 6) == 0)
1931                     is_rela = TRUE;
1932                   else if (strncmp (".rel.", SECTION_NAME (section), 5) == 0)
1933                     is_rela = FALSE;
1934                   else
1935                     is_rela = UNKNOWN;
1936                 }
1937
1938               printf (_(" at offset 0x%lx contains %lu entries:\n"),
1939                  rel_offset, (unsigned long) (rel_size / section->sh_entsize));
1940
1941               symsec = section_headers + section->sh_link;
1942
1943               symtab = get_elf_symbols (file, symsec->sh_offset,
1944                                         symsec->sh_size / symsec->sh_entsize);
1945
1946               if (symtab == NULL)
1947                 continue;
1948
1949               strsec = section_headers + symsec->sh_link;
1950
1951               GET_DATA_ALLOC (strsec->sh_offset, strsec->sh_size, strtab,
1952                               char *, "string table");
1953
1954               dump_relocations (file, rel_offset, rel_size, symtab, strtab, is_rela);
1955
1956               free (strtab);
1957               free (symtab);
1958
1959               found = 1;
1960             }
1961         }
1962
1963       if (! found)
1964         printf (_("\nThere are no relocations in this file.\n"));
1965     }
1966
1967   return 1;
1968 }
1969
1970
1971 static void
1972 dynamic_segment_mips_val (entry)
1973      Elf_Internal_Dyn * entry;
1974 {
1975   switch (entry->d_tag)
1976     {
1977     case DT_MIPS_FLAGS:
1978       if (entry->d_un.d_val == 0)
1979         printf ("NONE\n");
1980       else
1981         {
1982           static const char * opts[] =
1983           {
1984             "QUICKSTART", "NOTPOT", "NO_LIBRARY_REPLACEMENT",
1985             "NO_MOVE", "SGI_ONLY", "GUARANTEE_INIT", "DELTA_C_PLUS_PLUS",
1986             "GUARANTEE_START_INIT", "PIXIE", "DEFAULT_DELAY_LOAD",
1987             "REQUICKSTART", "REQUICKSTARTED", "CORD", "NO_UNRES_UNDEF",
1988             "RLD_ORDER_SAFE"
1989           };
1990           unsigned int cnt;
1991           int first = 1;
1992           for (cnt = 0; cnt < NUM_ELEM (opts); ++ cnt)
1993             if (entry->d_un.d_val & (1 << cnt))
1994               {
1995                 printf ("%s%s", first ? "" : " ", opts[cnt]);
1996                 first = 0;
1997               }
1998           puts ("");
1999         }
2000       break;
2001       
2002     case DT_MIPS_IVERSION:
2003       if (dynamic_strings != NULL)
2004         printf ("Interface Version: %s\n",
2005                 dynamic_strings + entry->d_un.d_val);
2006       else
2007         printf ("%ld\n", (long) entry->d_un.d_ptr);
2008       break;
2009       
2010     case DT_MIPS_TIME_STAMP:
2011       {
2012         char timebuf[20];
2013         time_t time = entry->d_un.d_val;
2014         strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time));
2015         printf ("Time Stamp: %s\n", timebuf);
2016       }
2017       break;
2018       
2019     case DT_MIPS_RLD_VERSION:
2020     case DT_MIPS_LOCAL_GOTNO:
2021     case DT_MIPS_CONFLICTNO:
2022     case DT_MIPS_LIBLISTNO:
2023     case DT_MIPS_SYMTABNO:
2024     case DT_MIPS_UNREFEXTNO:
2025     case DT_MIPS_HIPAGENO:
2026     case DT_MIPS_DELTA_CLASS_NO:
2027     case DT_MIPS_DELTA_INSTANCE_NO:
2028     case DT_MIPS_DELTA_RELOC_NO:
2029     case DT_MIPS_DELTA_SYM_NO:
2030     case DT_MIPS_DELTA_CLASSSYM_NO:
2031     case DT_MIPS_COMPACT_SIZE:
2032       printf ("%ld\n", (long) entry->d_un.d_ptr);
2033       break;
2034       
2035     default:
2036       printf ("%#lx\n", (long) entry->d_un.d_ptr);
2037     }
2038 }
2039
2040 /* Parse the dynamic segment */
2041 static int
2042 process_dynamic_segment (file)
2043      FILE * file;
2044 {
2045   Elf_Internal_Dyn *    entry;
2046   Elf32_External_Dyn *  edyn;
2047   unsigned int i;
2048
2049   if (dynamic_size == 0)
2050     {
2051       if (do_dynamic)
2052         printf (_("\nThere is no dynamic segment in this file.\n"));
2053
2054       return 1;
2055     }
2056
2057   GET_DATA_ALLOC (dynamic_addr, dynamic_size,
2058                   edyn, Elf32_External_Dyn *, "dynamic segment");
2059   
2060   /* SGI's ELF has more than one section in the DYNAMIC segment.  Determine
2061      how large .dynamic is now.  We can do this even before the byte
2062      swapping since the DT_NULL tag is recognizable.  */
2063   dynamic_size = 0;
2064   while (*(Elf32_Word *) edyn[dynamic_size++].d_tag != DT_NULL)
2065     ;
2066
2067   dynamic_segment = (Elf_Internal_Dyn *)
2068     malloc (dynamic_size * sizeof (Elf_Internal_Dyn));
2069
2070   if (dynamic_segment == NULL)
2071     {
2072       error (_("Out of memory\n"));
2073       free (edyn);
2074       return 0;
2075     }
2076
2077   for (i = 0, entry = dynamic_segment;
2078        i < dynamic_size;
2079        i ++, entry ++)
2080     {
2081       entry->d_tag      = BYTE_GET (edyn [i].d_tag);
2082       entry->d_un.d_val = BYTE_GET (edyn [i].d_un.d_val);
2083     }
2084
2085   free (edyn);
2086
2087   /* Find the appropriate symbol table.  */
2088   if (dynamic_symbols == NULL)
2089     {
2090       for (i = 0, entry = dynamic_segment;
2091            i < dynamic_size;
2092            ++i, ++ entry)
2093         {
2094           unsigned long        offset;
2095           long                 num_syms;
2096
2097           if (entry->d_tag != DT_SYMTAB)
2098             continue;
2099
2100           dynamic_info[DT_SYMTAB] = entry->d_un.d_val;
2101
2102           /* Since we do not know how big the symbol table is,
2103              we default to reading in the entire file (!) and
2104              processing that.  This is overkill, I know, but it
2105              should work. */
2106
2107           offset = entry->d_un.d_val - loadaddr;
2108
2109           if (fseek (file, 0, SEEK_END))
2110             error (_("Unable to seek to end of file!"));
2111
2112           num_syms = (ftell (file) - offset) / sizeof (Elf32_External_Sym);
2113
2114           if (num_syms < 1)
2115             {
2116               error (_("Unable to determine the number of symbols to load\n"));
2117               continue;
2118             }
2119
2120           dynamic_symbols = get_elf_symbols (file, offset, num_syms);
2121         }
2122     }
2123
2124   /* Similarly find a string table.  */
2125   if (dynamic_strings == NULL)
2126     {
2127       for (i = 0, entry = dynamic_segment;
2128            i < dynamic_size;
2129            ++i, ++ entry)
2130         {
2131           unsigned long offset;
2132           long          str_tab_len;
2133
2134           if (entry->d_tag != DT_STRTAB)
2135             continue;
2136
2137           dynamic_info[DT_STRTAB] = entry->d_un.d_val;
2138
2139           /* Since we do not know how big the string table is,
2140              we default to reading in the entire file (!) and
2141              processing that.  This is overkill, I know, but it
2142              should work. */
2143
2144           offset = entry->d_un.d_val - loadaddr;
2145           if (fseek (file, 0, SEEK_END))
2146             error (_("Unable to seek to end of file\n"));
2147           str_tab_len = ftell (file) - offset;
2148
2149           if (str_tab_len < 1)
2150             {
2151               error
2152                 (_("Unable to determine the length of the dynamic string table\n"));
2153               continue;
2154             }
2155
2156           GET_DATA_ALLOC (offset, str_tab_len, dynamic_strings, char *,
2157                           "dynamic string table");
2158
2159           break;
2160         }
2161     }
2162
2163   /* And find the syminfo section if available.  */
2164   if (dynamic_syminfo == NULL)
2165     {
2166       unsigned int syminsz = 0;
2167
2168       for (i = 0, entry = dynamic_segment;
2169            i < dynamic_size;
2170            ++i, ++ entry)
2171         {
2172           if (entry->d_tag == DT_SYMINENT)
2173             {
2174               /* Note: these braces are necessary to avoid a syntax
2175                  error from the SunOS4 C compiler.  */
2176               assert (sizeof (Elf_External_Syminfo) == entry->d_un.d_val);
2177             }
2178           else if (entry->d_tag == DT_SYMINSZ)
2179             syminsz = entry->d_un.d_val;
2180           else if (entry->d_tag == DT_SYMINFO)
2181             dynamic_syminfo_offset = entry->d_un.d_val - loadaddr;
2182         }
2183
2184       if (dynamic_syminfo_offset != 0 && syminsz != 0)
2185         {
2186           Elf_External_Syminfo *extsyminfo;
2187           Elf_Internal_Syminfo *syminfo;
2188
2189           /* There is a syminfo section.  Read the data.  */
2190           GET_DATA_ALLOC (dynamic_syminfo_offset, syminsz, extsyminfo,
2191                           Elf_External_Syminfo *, "symbol information");
2192
2193           dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz);
2194           if (dynamic_syminfo == NULL)
2195             {
2196               error (_("Out of memory\n"));
2197               return 0;
2198             }
2199
2200           dynamic_syminfo_nent = syminsz / sizeof (Elf_External_Syminfo);
2201           for (i = 0, syminfo = dynamic_syminfo; i < dynamic_syminfo_nent;
2202                ++i, ++syminfo)
2203             {
2204               syminfo->si_boundto = BYTE_GET (extsyminfo[i].si_boundto);
2205               syminfo->si_flags = BYTE_GET (extsyminfo[i].si_flags);
2206             }
2207
2208           free (extsyminfo);
2209         }
2210     }
2211
2212   if (do_dynamic && dynamic_addr)
2213     printf (_("\nDynamic segment at offset 0x%x contains %d entries:\n"),
2214             dynamic_addr, dynamic_size);
2215   if (do_dynamic)
2216     printf (_("  Tag        Type                         Name/Value\n"));
2217
2218   for (i = 0, entry = dynamic_segment;
2219        i < dynamic_size;
2220        i++, entry ++)
2221     {
2222       if (do_dynamic)
2223         printf (_("  0x%-8.8lx (%s)%*s"),
2224                 (unsigned long) entry->d_tag,
2225                 get_dynamic_type (entry->d_tag),
2226                 27 - strlen (get_dynamic_type (entry->d_tag)),
2227                 " ");
2228
2229       switch (entry->d_tag)
2230         {
2231         case DT_AUXILIARY:
2232         case DT_FILTER:
2233           if (do_dynamic)
2234             {
2235               if (entry->d_tag == DT_AUXILIARY)
2236                 printf (_("Auxiliary library"));
2237               else
2238                 printf (_("Filter library"));
2239
2240               if (dynamic_strings)
2241                 printf (": [%s]\n", dynamic_strings + entry->d_un.d_val);
2242               else
2243                 printf (": %#lx\n", (long) entry->d_un.d_val);
2244             }
2245           break;
2246
2247         case DT_FEATURE_1:
2248           if (do_dynamic)
2249             {
2250               printf (_("Flags:"));
2251               if (entry->d_un.d_val == 0)
2252                 printf (_(" None\n"));
2253               else
2254                 {
2255                   unsigned long int val = entry->d_un.d_val;
2256                   if (val & DTF_1_PARINIT)
2257                     {
2258                       printf (" PARINIT");
2259                       val ^= DTF_1_PARINIT;
2260                     }
2261                   if (val != 0)
2262                     printf (" %lx", val);
2263                   puts ("");
2264                 }
2265             }
2266           break;
2267
2268         case DT_POSFLAG_1:
2269           if (do_dynamic)
2270             {
2271               printf (_("Flags:"));
2272               if (entry->d_un.d_val == 0)
2273                 printf (_(" None\n"));
2274               else
2275                 {
2276                   unsigned long int val = entry->d_un.d_val;
2277                   if (val & DF_P1_LAZYLOAD)
2278                     {
2279                       printf (" LAZYLOAD");
2280                       val ^= DF_P1_LAZYLOAD;
2281                     }
2282                   if (val & DF_P1_GROUPPERM)
2283                     {
2284                       printf (" GROUPPERM");
2285                       val ^= DF_P1_GROUPPERM;
2286                     }
2287                   if (val != 0)
2288                     printf (" %lx", val);
2289                   puts ("");
2290                 }
2291             }
2292           break;
2293
2294         case DT_FLAGS_1:
2295           if (do_dynamic)
2296             {
2297               printf (_("Flags:"));
2298               if (entry->d_un.d_val == 0)
2299                 printf (_(" None\n"));
2300               else
2301                 {
2302                   unsigned long int val = entry->d_un.d_val;
2303                   if (val & DF_1_NOW)
2304                     {
2305                       printf (" NOW");
2306                       val ^= DF_1_NOW;
2307                     }
2308                   if (val & DF_1_GLOBAL)
2309                     {
2310                       printf (" GLOBAL");
2311                       val ^= DF_1_GLOBAL;
2312                     }
2313                   if (val & DF_1_GROUP)
2314                     {
2315                       printf (" GROUP");
2316                       val ^= DF_1_GROUP;
2317                     }
2318                   if (val & DF_1_NODELETE)
2319                     {
2320                       printf (" NODELETE");
2321                       val ^= DF_1_NODELETE;
2322                     }
2323                   if (val & DF_1_LOADFLTR)
2324                     {
2325                       printf (" LOADFLTR");
2326                       val ^= DF_1_LOADFLTR;
2327                     }
2328                   if (val & DF_1_INITFIRST)
2329                     {
2330                       printf (" INITFIRST");
2331                       val ^= DF_1_INITFIRST;
2332                     }
2333                   if (val & DF_1_NOOPEN)
2334                     {
2335                       printf (" NOOPEN");
2336                       val ^= DF_1_NOOPEN;
2337                     }
2338                   if (val & DF_1_ORIGIN)
2339                     {
2340                       printf (" ORIGIN");
2341                       val ^= DF_1_ORIGIN;
2342                     }
2343                   if (val & DF_1_DIRECT)
2344                     {
2345                       printf (" DIRECT");
2346                       val ^= DF_1_DIRECT;
2347                     }
2348                   if (val & DF_1_TRANS)
2349                     {
2350                       printf (" TRANS");
2351                       val ^= DF_1_TRANS;
2352                     }
2353                   if (val & DF_1_INTERPOSE)
2354                     {
2355                       printf (" INTERPOSE");
2356                       val ^= DF_1_INTERPOSE;
2357                     }
2358                   if (val != 0)
2359                     printf (" %lx", val);
2360                   puts ("");
2361                 }
2362             }
2363           break;
2364
2365         case DT_PLTREL:
2366           if (do_dynamic)
2367             puts (get_dynamic_type (entry->d_un.d_val));
2368           break;
2369
2370         case DT_NULL    :
2371         case DT_NEEDED  :
2372         case DT_PLTGOT  :
2373         case DT_HASH    :
2374         case DT_STRTAB  :
2375         case DT_SYMTAB  :
2376         case DT_RELA    :
2377         case DT_INIT    :
2378         case DT_FINI    :
2379         case DT_SONAME  :
2380         case DT_RPATH   :
2381         case DT_SYMBOLIC:
2382         case DT_REL     :
2383         case DT_DEBUG   :
2384         case DT_TEXTREL :
2385         case DT_JMPREL  :
2386           dynamic_info[entry->d_tag] = entry->d_un.d_val;
2387
2388           if (do_dynamic)
2389             {
2390               char * name;
2391
2392               if (dynamic_strings == NULL)
2393                 name = NULL;
2394               else
2395                 name = dynamic_strings + entry->d_un.d_val;
2396
2397               if (name)
2398                 {
2399                   switch (entry->d_tag)
2400                     {
2401                     case DT_NEEDED:
2402                       printf (_("Shared library: [%s]"), name);
2403
2404                       if (strcmp (name, program_interpreter))
2405                         printf ("\n");
2406                       else
2407                         printf (_(" program interpreter\n"));
2408                       break;
2409
2410                     case DT_SONAME:
2411                       printf (_("Library soname: [%s]\n"), name);
2412                       break;
2413
2414                     case DT_RPATH:
2415                       printf (_("Library rpath: [%s]\n"), name);
2416                       break;
2417
2418                     default:
2419                       printf ("%#lx\n", (long) entry->d_un.d_val);
2420                     }
2421                 }
2422               else
2423                 printf ("%#lx\n", (long) entry->d_un.d_val);
2424             }
2425           break;
2426
2427         case DT_PLTRELSZ:
2428         case DT_RELASZ  :
2429         case DT_STRSZ   :
2430         case DT_RELSZ   :
2431         case DT_RELAENT :
2432         case DT_SYMENT  :
2433         case DT_RELENT  :
2434         case DT_PLTPADSZ:
2435         case DT_MOVEENT :
2436         case DT_MOVESZ  :
2437         case DT_INIT_ARRAYSZ:
2438         case DT_FINI_ARRAYSZ:
2439           if (do_dynamic)
2440             printf ("%lu (bytes)\n", (unsigned long) entry->d_un.d_val);
2441           break;
2442
2443         case DT_VERDEFNUM:
2444         case DT_VERNEEDNUM:
2445         case DT_RELACOUNT:
2446         case DT_RELCOUNT:
2447           if (do_dynamic)
2448             printf ("%lu\n", (unsigned long) entry->d_un.d_val);
2449           break;
2450
2451         case DT_SYMINSZ:
2452         case DT_SYMINENT:
2453         case DT_SYMINFO:
2454         case DT_USED:
2455         case DT_INIT_ARRAY:
2456         case DT_FINI_ARRAY:
2457           if (do_dynamic)
2458             {
2459               if (dynamic_strings != NULL && entry->d_tag == DT_USED)
2460                 {
2461                   char * name;
2462
2463                   name = dynamic_strings + entry->d_un.d_val;
2464
2465                   if (* name)
2466                     {
2467                       printf (_("Not needed object: [%s]\n"), name);
2468                       break;
2469                     }
2470                 }
2471               
2472               printf ("%#lx\n", (long) entry->d_un.d_val);
2473             }
2474           break;
2475
2476         case DT_BIND_NOW:
2477           /* The value of this entry is ignored.  */
2478           break;
2479           
2480         default:
2481           if ((entry->d_tag >= DT_VERSYM) && (entry->d_tag <= DT_VERNEEDNUM))
2482             version_info [DT_VERSIONTAGIDX (entry->d_tag)] =
2483               entry->d_un.d_val;
2484
2485           if (do_dynamic)
2486             {
2487               switch (elf_header.e_machine)
2488                 {
2489                 case EM_MIPS:
2490                 case EM_MIPS_RS4_BE:
2491                   dynamic_segment_mips_val (entry);
2492                   break;
2493                 default:
2494                   printf ("%#lx\n", (long) entry->d_un.d_ptr);
2495                 }
2496             }
2497           break;
2498         }
2499     }
2500
2501   return 1;
2502 }
2503
2504 static char *
2505 get_ver_flags (flags)
2506      unsigned int flags;
2507 {
2508   static char buff [32];
2509
2510   buff[0] = 0;
2511
2512   if (flags == 0)
2513     return _("none");
2514
2515   if (flags & VER_FLG_BASE)
2516     strcat (buff, "BASE ");
2517
2518   if (flags & VER_FLG_WEAK)
2519     {
2520       if (flags & VER_FLG_BASE)
2521         strcat (buff, "| ");
2522
2523       strcat (buff, "WEAK ");
2524     }
2525
2526   if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK))
2527     strcat (buff, "| <unknown>");
2528
2529   return buff;
2530 }
2531
2532 /* Display the contents of the version sections.  */
2533 static int
2534 process_version_sections (file)
2535      FILE * file;
2536 {
2537   Elf32_Internal_Shdr * section;
2538   unsigned   i;
2539   int        found = 0;
2540
2541   if (! do_version)
2542     return 1;
2543
2544   for (i = 0, section = section_headers;
2545        i < elf_header.e_shnum;
2546        i++, section ++)
2547     {
2548       switch (section->sh_type)
2549         {
2550         case SHT_GNU_verdef:
2551           {
2552             Elf_External_Verdef * edefs;
2553             unsigned int          idx;
2554             unsigned int          cnt;
2555
2556             found = 1;
2557
2558             printf
2559               (_("\nVersion definition section '%s' contains %ld entries:\n"),
2560                SECTION_NAME (section), section->sh_info);
2561
2562             printf (_("  Addr: 0x"));
2563             printf_vma (section->sh_addr);
2564             printf (_("  Offset: %#08lx  Link: %lx (%s)\n"),
2565                     (unsigned long) section->sh_offset, section->sh_link,
2566                     SECTION_NAME (section_headers + section->sh_link));
2567
2568             GET_DATA_ALLOC (section->sh_offset, section->sh_size,
2569                             edefs, Elf_External_Verdef *,
2570                             "version definition section");
2571
2572             for (idx = cnt = 0; cnt < section->sh_info; ++ cnt)
2573               {
2574                 char *                 vstart;
2575                 Elf_External_Verdef *  edef;
2576                 Elf_Internal_Verdef    ent;
2577                 Elf_External_Verdaux * eaux;
2578                 Elf_Internal_Verdaux   aux;
2579                 int                    j;
2580                 int                    isum;
2581                 
2582                 vstart = ((char *) edefs) + idx;
2583
2584                 edef = (Elf_External_Verdef *) vstart;
2585
2586                 ent.vd_version = BYTE_GET (edef->vd_version);
2587                 ent.vd_flags   = BYTE_GET (edef->vd_flags);
2588                 ent.vd_ndx     = BYTE_GET (edef->vd_ndx);
2589                 ent.vd_cnt     = BYTE_GET (edef->vd_cnt);
2590                 ent.vd_hash    = BYTE_GET (edef->vd_hash);
2591                 ent.vd_aux     = BYTE_GET (edef->vd_aux);
2592                 ent.vd_next    = BYTE_GET (edef->vd_next);
2593
2594                 printf (_("  %#06x: Rev: %d  Flags: %s"),
2595                         idx, ent.vd_version, get_ver_flags (ent.vd_flags));
2596
2597                 printf (_("  Index: %d  Cnt: %d  "),
2598                         ent.vd_ndx, ent.vd_cnt);
2599
2600                 vstart += ent.vd_aux;
2601
2602                 eaux = (Elf_External_Verdaux *) vstart;
2603
2604                 aux.vda_name = BYTE_GET (eaux->vda_name);
2605                 aux.vda_next = BYTE_GET (eaux->vda_next);
2606
2607                 if (dynamic_strings)
2608                   printf (_("Name: %s\n"), dynamic_strings + aux.vda_name);
2609                 else
2610                   printf (_("Name index: %ld\n"), aux.vda_name);
2611
2612                 isum = idx + ent.vd_aux;
2613
2614                 for (j = 1; j < ent.vd_cnt; j ++)
2615                   {
2616                     isum   += aux.vda_next;
2617                     vstart += aux.vda_next;
2618
2619                     eaux = (Elf_External_Verdaux *) vstart;
2620
2621                     aux.vda_name = BYTE_GET (eaux->vda_name);
2622                     aux.vda_next = BYTE_GET (eaux->vda_next);
2623
2624                     if (dynamic_strings)
2625                       printf (_("  %#06x: Parent %d: %s\n"),
2626                               isum, j, dynamic_strings + aux.vda_name);
2627                     else
2628                       printf (_("  %#06x: Parent %d, name index: %ld\n"),
2629                               isum, j, aux.vda_name);
2630                   }
2631
2632                 idx += ent.vd_next;
2633               }
2634
2635             free (edefs);
2636           }
2637           break;
2638           
2639         case SHT_GNU_verneed:
2640           {
2641             Elf_External_Verneed *  eneed;
2642             unsigned int            idx;
2643             unsigned int            cnt;
2644
2645             found = 1;
2646
2647             printf (_("\nVersion needs section '%s' contains %ld entries:\n"),
2648                     SECTION_NAME (section), section->sh_info);
2649
2650             printf (_(" Addr: 0x"));
2651             printf_vma (section->sh_addr);
2652             printf (_("  Offset: %#08lx  Link to section: %ld (%s)\n"),
2653                     (unsigned long) section->sh_offset, section->sh_link,
2654                     SECTION_NAME (section_headers + section->sh_link));
2655
2656             GET_DATA_ALLOC (section->sh_offset, section->sh_size,
2657                             eneed, Elf_External_Verneed *,
2658                             "version need section");
2659
2660             for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
2661               {
2662                 Elf_External_Verneed * entry;
2663                 Elf_Internal_Verneed     ent;
2664                 int                      j;
2665                 int                      isum;
2666                 char *                   vstart;
2667
2668                 vstart = ((char *) eneed) + idx;
2669
2670                 entry = (Elf_External_Verneed *) vstart;
2671
2672                 ent.vn_version = BYTE_GET (entry->vn_version);
2673                 ent.vn_cnt     = BYTE_GET (entry->vn_cnt);
2674                 ent.vn_file    = BYTE_GET (entry->vn_file);
2675                 ent.vn_aux     = BYTE_GET (entry->vn_aux);
2676                 ent.vn_next    = BYTE_GET (entry->vn_next);
2677
2678                 printf (_("  %#06x: Version: %d"), idx, ent.vn_version);
2679
2680                 if (dynamic_strings)
2681                   printf (_("  File: %s"), dynamic_strings + ent.vn_file);
2682                 else
2683                   printf (_("  File: %lx"), ent.vn_file);
2684
2685                 printf (_("  Cnt: %d\n"), ent.vn_cnt);
2686
2687                 vstart += ent.vn_aux;
2688
2689                 for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j)
2690                   {
2691                     Elf_External_Vernaux * eaux;
2692                     Elf_Internal_Vernaux   aux;
2693
2694                     eaux = (Elf_External_Vernaux *) vstart;
2695
2696                     aux.vna_hash  = BYTE_GET (eaux->vna_hash);
2697                     aux.vna_flags = BYTE_GET (eaux->vna_flags);
2698                     aux.vna_other = BYTE_GET (eaux->vna_other);
2699                     aux.vna_name  = BYTE_GET (eaux->vna_name);
2700                     aux.vna_next  = BYTE_GET (eaux->vna_next);
2701
2702                     if (dynamic_strings)
2703                       printf (_("  %#06x: Name: %s"),
2704                               isum, dynamic_strings + aux.vna_name);
2705                     else
2706                       printf (_("  %#06x: Name index: %lx"),
2707                               isum, aux.vna_name);
2708
2709                     printf (_("  Flags: %s  Version: %d\n"),
2710                             get_ver_flags (aux.vna_flags), aux.vna_other);
2711
2712                     isum   += aux.vna_next;
2713                     vstart += aux.vna_next;
2714                   }
2715
2716                 idx += ent.vn_next;
2717               }
2718             
2719             free (eneed);
2720           }
2721           break;
2722
2723         case SHT_GNU_versym:
2724           {
2725             Elf32_Internal_Shdr *       link_section;
2726             int                         total;
2727             int                         cnt;
2728             unsigned char *             edata;
2729             unsigned short *            data;
2730             char *                      strtab;
2731             Elf_Internal_Sym *          symbols;
2732             Elf32_Internal_Shdr *       string_sec;
2733
2734             link_section = section_headers + section->sh_link;
2735             total = section->sh_size / section->sh_entsize;
2736
2737             found = 1;
2738
2739             symbols = get_elf_symbols
2740               (file, link_section->sh_offset,
2741                link_section->sh_size / link_section->sh_entsize);
2742
2743             string_sec = section_headers + link_section->sh_link;
2744
2745             GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
2746                             strtab, char *, "version string table");
2747
2748             printf (_("\nVersion symbols section '%s' contains %d entries:\n"),
2749                     SECTION_NAME (section), total);
2750
2751             printf (_(" Addr: "));
2752             printf_vma (section->sh_addr);
2753             printf (_("  Offset: %#08lx  Link: %lx (%s)\n"),
2754                     (unsigned long) section->sh_offset, section->sh_link,
2755                     SECTION_NAME (link_section));
2756
2757             GET_DATA_ALLOC (version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
2758                             - loadaddr,
2759                             total * sizeof (short), edata,
2760                             unsigned char *, "version symbol data");
2761
2762             data = (unsigned short *) malloc (total * sizeof (short));
2763
2764             for (cnt = total; cnt --;)
2765               data [cnt] = byte_get (edata + cnt * sizeof (short),
2766                                      sizeof (short));
2767
2768             free (edata);
2769
2770             for (cnt = 0; cnt < total; cnt += 4)
2771               {
2772                 int j, nn;
2773
2774                 printf ("  %03x:", cnt);
2775
2776                 for (j = 0; (j < 4) && (cnt + j) < total; ++j)
2777                   switch (data [cnt + j])
2778                     {
2779                     case 0:
2780                       fputs (_("   0 (*local*)    "), stdout);
2781                       break;
2782
2783                     case 1:
2784                       fputs (_("   1 (*global*)   "), stdout);
2785                       break;
2786
2787                     default:
2788                       nn = printf ("%4x%c", data [cnt + j] & 0x7fff,
2789                                    data [cnt + j] & 0x8000 ? 'h' : ' ');
2790
2791                       if (symbols [cnt + j].st_shndx < SHN_LORESERVE
2792                           && section_headers[symbols [cnt + j].st_shndx].sh_type
2793                           == SHT_NOBITS)
2794                         {
2795                           /* We must test both.  */
2796                           Elf_Internal_Verneed     ivn;
2797                           unsigned long            offset;
2798
2799                           offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
2800                             - loadaddr;
2801
2802                           do
2803                             {
2804                               Elf_External_Verneed   evn;
2805                               Elf_External_Vernaux   evna;
2806                               Elf_Internal_Vernaux     ivna;
2807                               unsigned long            vna_off;
2808
2809                               GET_DATA (offset, evn, "version need");
2810
2811                               ivn.vn_aux  = BYTE_GET (evn.vn_aux);
2812                               ivn.vn_next = BYTE_GET (evn.vn_next);
2813
2814                               vna_off = offset + ivn.vn_aux;
2815
2816                               do
2817                                 {
2818                                   GET_DATA (vna_off, evna,
2819                                             "version need aux (1)");
2820
2821                                   ivna.vna_next  = BYTE_GET (evna.vna_next);
2822                                   ivna.vna_other = BYTE_GET (evna.vna_other);
2823
2824                                   vna_off += ivna.vna_next;
2825                                 }
2826                               while (ivna.vna_other != data [cnt + j]
2827                                      && ivna.vna_next != 0);
2828
2829                               if (ivna.vna_other == data [cnt + j])
2830                                 {
2831                                   ivna.vna_name = BYTE_GET (evna.vna_name);
2832
2833                                   nn += printf ("(%s%-*s",
2834                                                 strtab + ivna.vna_name,
2835                                                 12 - strlen (strtab
2836                                                              + ivna.vna_name),
2837                                                 ")");
2838                                   break;
2839                                 }
2840                               else if (ivn.vn_next == 0)
2841                                 {
2842                                   if (data [cnt + j] != 0x8001)
2843                                     {
2844                                       Elf_Internal_Verdef  ivd;
2845                                       Elf_External_Verdef  evd;
2846
2847                                       offset = version_info
2848                                         [DT_VERSIONTAGIDX (DT_VERDEF)]
2849                                         - loadaddr;
2850
2851                                       do
2852                                         {
2853                                           GET_DATA (offset, evd,
2854                                                     "version definition");
2855
2856                                           ivd.vd_next = BYTE_GET (evd.vd_next);
2857                                           ivd.vd_ndx  = BYTE_GET (evd.vd_ndx);
2858
2859                                           offset += ivd.vd_next;
2860                                         }
2861                                       while (ivd.vd_ndx
2862                                              != (data [cnt + j] & 0x7fff)
2863                                              && ivd.vd_next != 0);
2864
2865                                       if (ivd.vd_ndx
2866                                           == (data [cnt + j] & 0x7fff))
2867                                         {
2868                                           Elf_External_Verdaux  evda;
2869                                           Elf_Internal_Verdaux  ivda;
2870
2871                                           ivd.vd_aux = BYTE_GET (evd.vd_aux);
2872
2873                                           GET_DATA (offset + ivd.vd_aux, evda,
2874                                                     "version definition aux");
2875
2876                                           ivda.vda_name =
2877                                             BYTE_GET (evda.vda_name);
2878
2879                                           nn +=
2880                                             printf ("(%s%-*s",
2881                                                     strtab + ivda.vda_name,
2882                                                     12
2883                                                     - strlen (strtab
2884                                                               + ivda.vda_name),
2885                                                     ")");
2886                                         }
2887                                     }
2888
2889                                   break;
2890                                 }
2891                               else
2892                                 offset += ivn.vn_next;
2893                             }
2894                           while (ivn.vn_next);
2895                         }
2896                       else if (symbols [cnt + j].st_shndx == SHN_UNDEF)
2897                         {
2898                           Elf_Internal_Verneed     ivn;
2899                           unsigned long            offset;
2900
2901                           offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
2902                             - loadaddr;
2903
2904                           do
2905                             {
2906                               Elf_Internal_Vernaux     ivna;
2907                               Elf_External_Verneed   evn;
2908                               Elf_External_Vernaux   evna;
2909                               unsigned long            a_off;
2910
2911                               GET_DATA (offset, evn, "version need");
2912
2913                               ivn.vn_aux  = BYTE_GET (evn.vn_aux);
2914                               ivn.vn_next = BYTE_GET (evn.vn_next);
2915
2916                               a_off = offset + ivn.vn_aux;
2917
2918                               do
2919                                 {
2920                                   GET_DATA (a_off, evna,
2921                                             "version need aux (2)");
2922
2923                                   ivna.vna_next  = BYTE_GET (evna.vna_next);
2924                                   ivna.vna_other = BYTE_GET (evna.vna_other);
2925
2926                                   a_off += ivna.vna_next;
2927                                 }
2928                               while (ivna.vna_other != data [cnt + j]
2929                                      && ivna.vna_next != 0);
2930
2931                               if (ivna.vna_other == data [cnt + j])
2932                                 {
2933                                   ivna.vna_name = BYTE_GET (evna.vna_name);
2934
2935                                   nn += printf ("(%s%-*s",
2936                                                 strtab + ivna.vna_name,
2937                                                 12 - strlen (strtab
2938                                                              + ivna.vna_name),
2939                                                 ")");
2940                                   break;
2941                                 }
2942
2943                               offset += ivn.vn_next;
2944                             }
2945                           while (ivn.vn_next);
2946                         }
2947                       else if (data [cnt + j] != 0x8001)
2948                         {
2949                           Elf_Internal_Verdef  ivd;
2950                           Elf_External_Verdef  evd;
2951                           unsigned long        offset;
2952
2953                           offset = version_info
2954                             [DT_VERSIONTAGIDX (DT_VERDEF)] - loadaddr;
2955
2956                           do
2957                             {
2958                               GET_DATA (offset, evd, "version def");
2959
2960                               ivd.vd_next = BYTE_GET (evd.vd_next);
2961                               ivd.vd_ndx  = BYTE_GET (evd.vd_ndx);
2962
2963                               offset += ivd.vd_next;
2964                             }
2965                           while (ivd.vd_ndx != (data [cnt + j] & 0x7fff)
2966                                  && ivd.vd_next != 0);
2967
2968                           if (ivd.vd_ndx == (data [cnt + j] & 0x7fff))
2969                             {
2970                               Elf_External_Verdaux  evda;
2971                               Elf_Internal_Verdaux  ivda;
2972
2973                               ivd.vd_aux = BYTE_GET (evd.vd_aux);
2974
2975                               GET_DATA (offset - ivd.vd_next + ivd.vd_aux,
2976                                         evda, "version def aux");
2977
2978                               ivda.vda_name = BYTE_GET (evda.vda_name);
2979
2980                               nn += printf ("(%s%-*s",
2981                                             strtab + ivda.vda_name,
2982                                             12 - strlen (strtab
2983                                                          + ivda.vda_name),
2984                                             ")");
2985                             }
2986                         }
2987
2988                       if (nn < 18)
2989                         printf ("%*c", 18 - nn, ' ');
2990                     }
2991
2992                 putchar ('\n');
2993               }
2994
2995             free (data);
2996             free (strtab);
2997             free (symbols);
2998           }
2999           break;
3000         
3001         default:
3002           break;
3003         }
3004     }
3005
3006   if (! found)
3007     printf (_("\nNo version information found in this file.\n"));
3008
3009   return 1;
3010 }
3011
3012 static char *
3013 get_symbol_binding (binding)
3014      unsigned int binding;
3015 {
3016   static char buff [32];
3017
3018   switch (binding)
3019     {
3020     case STB_LOCAL:  return _("LOCAL");
3021     case STB_GLOBAL: return _("GLOBAL");
3022     case STB_WEAK:   return _("WEAK");
3023     default:
3024       if (binding >= STB_LOPROC && binding <= STB_HIPROC)
3025         sprintf (buff, _("<processor specific>: %d"), binding);
3026       else if (binding >= STB_LOOS && binding <= STB_HIOS)
3027         sprintf (buff, _("<OS specific>: %d"), binding);
3028       else
3029         sprintf (buff, _("<unknown>: %d"), binding);
3030       return buff;
3031     }
3032 }
3033
3034 static char *
3035 get_symbol_type (type)
3036      unsigned int type;
3037 {
3038   static char buff [32];
3039
3040   switch (type)
3041     {
3042     case STT_NOTYPE:   return _("NOTYPE");
3043     case STT_OBJECT:   return _("OBJECT");
3044     case STT_FUNC:     return _("FUNC");
3045     case STT_SECTION:  return _("SECTION");
3046     case STT_FILE:     return _("FILE");
3047     default:
3048       if (type >= STT_LOPROC && type <= STT_HIPROC)
3049         sprintf (buff, _("<processor specific>: %d"), type);
3050       else if (type >= STT_LOOS && type <= STT_HIOS)
3051         sprintf (buff, _("<OS specific>: %d"), type);
3052       else
3053         sprintf (buff, _("<unknown>: %d"), type);
3054       return buff;
3055     }
3056 }
3057
3058 static char *
3059 get_symbol_index_type (type)
3060      unsigned int type;
3061 {
3062   switch (type)
3063     {
3064     case SHN_UNDEF:  return "UND";
3065     case SHN_ABS:    return "ABS";
3066     case SHN_COMMON: return "COM";
3067     default:
3068       if (type >= SHN_LOPROC && type <= SHN_HIPROC)
3069         return "PRC";
3070       else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE)
3071         return "RSV";
3072       else if (type >= SHN_LOOS && type <= SHN_HIOS)
3073         return "OS ";
3074       else
3075         {
3076           static char buff [32];
3077
3078           sprintf (buff, "%3d", type);
3079           return buff;
3080         }
3081     }
3082 }
3083
3084
3085 static int *
3086 get_dynamic_data (file, number)
3087      FILE *       file;
3088      unsigned int number;
3089 {
3090   char * e_data;
3091   int *  i_data;
3092
3093   e_data = (char *) malloc (number * 4);
3094
3095   if (e_data == NULL)
3096     {
3097       error (_("Out of memory\n"));
3098       return NULL;
3099     }
3100
3101   if (fread (e_data, 4, number, file) != number)
3102     {
3103       error (_("Unable to read in dynamic data\n"));
3104       return NULL;
3105     }
3106
3107   i_data = (int *) malloc (number * sizeof (* i_data));
3108
3109   if (i_data == NULL)
3110     {
3111       error (_("Out of memory\n"));
3112       free (e_data);
3113       return NULL;
3114     }
3115
3116   while (number--)
3117     i_data [number] = byte_get (e_data + number * 4, 4);
3118
3119   free (e_data);
3120
3121   return i_data;
3122 }
3123
3124 /* Dump the symbol table */
3125 static int
3126 process_symbol_table (file)
3127      FILE * file;
3128 {
3129   Elf32_Internal_Shdr *   section;
3130   char   nb [4];
3131   char   nc [4];
3132   int    nbuckets;
3133   int    nchains;
3134   int *  buckets = NULL;
3135   int *  chains = NULL;
3136
3137   if (! do_syms && !do_histogram)
3138     return 1;
3139
3140   if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL)
3141                                 || do_histogram))
3142     {
3143       if (fseek (file, dynamic_info[DT_HASH] - loadaddr, SEEK_SET))
3144         {
3145           error (_("Unable to seek to start of dynamic information"));
3146           return 0;
3147         }
3148
3149       if (fread (nb, sizeof (nb), 1, file) != 1)
3150         {
3151           error (_("Failed to read in number of buckets\n"));
3152           return 0;
3153         }
3154
3155       if (fread (nc, sizeof (nc), 1, file) != 1)
3156         {
3157           error (_("Failed to read in number of chains\n"));
3158           return 0;
3159         }
3160
3161       nbuckets = byte_get (nb, 4);
3162       nchains  = byte_get (nc, 4);
3163
3164       buckets = get_dynamic_data (file, nbuckets);
3165       chains  = get_dynamic_data (file, nchains);
3166
3167       if (buckets == NULL || chains == NULL)
3168         return 0;
3169     }
3170
3171   if (do_syms
3172       && dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL)
3173     {
3174       int    hn;
3175       int    si;
3176
3177       printf (_("\nSymbol table for image:\n"));
3178       printf (_("  Num Buc:    Value  Size   Type   Bind Ot Ndx Name\n"));
3179
3180       for (hn = 0; hn < nbuckets; hn++)
3181         {
3182           if (! buckets [hn])
3183             continue;
3184
3185           for (si = buckets [hn]; si; si = chains [si])
3186             {
3187               Elf_Internal_Sym * psym;
3188
3189               psym = dynamic_symbols + si;
3190
3191               printf ("  %3d %3d: %8lx %5ld %6s %6s %2d ",
3192                       si, hn,
3193                       (unsigned long) psym->st_value,
3194                       (unsigned long) psym->st_size,
3195                       get_symbol_type (ELF_ST_TYPE (psym->st_info)),
3196                       get_symbol_binding (ELF_ST_BIND (psym->st_info)),
3197                       psym->st_other);
3198
3199               printf ("%3.3s", get_symbol_index_type (psym->st_shndx));
3200
3201               printf (" %s\n", dynamic_strings + psym->st_name);
3202             }
3203         }
3204     }
3205   else if (do_syms && !do_using_dynamic)
3206     {
3207       unsigned int     i;
3208
3209       for (i = 0, section = section_headers;
3210            i < elf_header.e_shnum;
3211            i++, section++)
3212         {
3213           unsigned int          si;
3214           char *                strtab;
3215           Elf_Internal_Sym *    symtab;
3216           Elf_Internal_Sym *    psym;
3217
3218
3219           if (   section->sh_type != SHT_SYMTAB
3220               && section->sh_type != SHT_DYNSYM)
3221             continue;
3222
3223           printf (_("\nSymbol table '%s' contains %lu entries:\n"),
3224                   SECTION_NAME (section),
3225                   (unsigned long) (section->sh_size / section->sh_entsize));
3226           fputs (_("  Num:    Value  Size Type    Bind   Ot  Ndx Name\n"),
3227                  stdout);
3228
3229           symtab = get_elf_symbols (file, section->sh_offset,
3230                                     section->sh_size / section->sh_entsize);
3231           if (symtab == NULL)
3232             continue;
3233
3234           if (section->sh_link == elf_header.e_shstrndx)
3235             strtab = string_table;
3236           else
3237             {
3238               Elf32_Internal_Shdr * string_sec;
3239
3240               string_sec = section_headers + section->sh_link;
3241
3242               GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
3243                               strtab, char *, "string table");
3244             }
3245
3246           for (si = 0, psym = symtab;
3247                si < section->sh_size / section->sh_entsize;
3248                si ++, psym ++)
3249             {
3250               printf ("  %3d: %8lx %5ld %-7s %-6s %2d ",
3251                       si,
3252                       (unsigned long) psym->st_value,
3253                       (unsigned long) psym->st_size,
3254                       get_symbol_type (ELF_ST_TYPE (psym->st_info)),
3255                       get_symbol_binding (ELF_ST_BIND (psym->st_info)),
3256                       psym->st_other);
3257
3258               printf ("%4s", get_symbol_index_type (psym->st_shndx));
3259
3260               printf (" %s", strtab + psym->st_name);
3261
3262               if (section->sh_type == SHT_DYNSYM &&
3263                   version_info [DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
3264                 {
3265                   unsigned char   data[2];
3266                   unsigned short  vers_data;
3267                   unsigned long   offset;
3268                   int             is_nobits;
3269                   int             check_def;
3270
3271                   offset = version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
3272                     - loadaddr;
3273
3274                   GET_DATA (offset + si * sizeof (vers_data), data,
3275                             "version data");
3276
3277                   vers_data = byte_get (data, 2);
3278
3279                   is_nobits = psym->st_shndx < SHN_LORESERVE ?
3280                     (section_headers [psym->st_shndx].sh_type == SHT_NOBITS)
3281                     : 0;
3282
3283                   check_def = (psym->st_shndx != SHN_UNDEF);
3284
3285                   if ((vers_data & 0x8000) || vers_data > 1)
3286                     {
3287                       if (is_nobits || ! check_def)
3288                         {
3289                           Elf_External_Verneed  evn;
3290                           Elf_Internal_Verneed  ivn;
3291                           Elf_Internal_Vernaux  ivna;
3292
3293                           /* We must test both.  */
3294                           offset = version_info
3295                             [DT_VERSIONTAGIDX (DT_VERNEED)] - loadaddr;
3296
3297                           GET_DATA (offset, evn, "version need");
3298
3299                           ivn.vn_aux  = BYTE_GET (evn.vn_aux);
3300                           ivn.vn_next = BYTE_GET (evn.vn_next);
3301
3302                           do
3303                             {
3304                               unsigned long  vna_off;
3305
3306                               vna_off = offset + ivn.vn_aux;
3307
3308                               do
3309                                 {
3310                                   Elf_External_Vernaux  evna;
3311
3312                                   GET_DATA (vna_off, evna,
3313                                             "version need aux (3)");
3314
3315                                   ivna.vna_other = BYTE_GET (evna.vna_other);
3316                                   ivna.vna_next  = BYTE_GET (evna.vna_next);
3317                                   ivna.vna_name  = BYTE_GET (evna.vna_name);
3318
3319                                   vna_off += ivna.vna_next;
3320                                 }
3321                               while (ivna.vna_other != vers_data
3322                                      && ivna.vna_next != 0);
3323
3324                               if (ivna.vna_other == vers_data)
3325                                 break;
3326
3327                               offset += ivn.vn_next;
3328                             }
3329                           while (ivn.vn_next != 0);
3330
3331                           if (ivna.vna_other == vers_data)
3332                             {
3333                               printf ("@%s (%d)",
3334                                       strtab + ivna.vna_name, ivna.vna_other);
3335                               check_def = 0;
3336                             }
3337                           else if (! is_nobits)
3338                             error (_("bad dynamic symbol"));
3339                           else
3340                             check_def = 1;
3341                         }
3342
3343                       if (check_def)
3344                         {
3345                           if (vers_data != 0x8001)
3346                             {
3347                               Elf_Internal_Verdef     ivd;
3348                               Elf_Internal_Verdaux    ivda;
3349                               Elf_External_Verdaux  evda;
3350                               unsigned long           offset;
3351
3352                               offset =
3353                                 version_info [DT_VERSIONTAGIDX (DT_VERDEF)]
3354                                 - loadaddr;
3355
3356                               do
3357                                 {
3358                                   Elf_External_Verdef   evd;
3359
3360                                   GET_DATA (offset, evd, "version def");
3361
3362                                   ivd.vd_ndx  = BYTE_GET (evd.vd_ndx);
3363                                   ivd.vd_aux  = BYTE_GET (evd.vd_aux);
3364                                   ivd.vd_next = BYTE_GET (evd.vd_next);
3365
3366                                   offset += ivd.vd_next;
3367                                 }
3368                               while (ivd.vd_ndx != (vers_data & 0x7fff)
3369                                      && ivd.vd_next != 0);
3370
3371                               offset -= ivd.vd_next;
3372                               offset += ivd.vd_aux;
3373
3374                               GET_DATA (offset, evda, "version def aux");
3375
3376                               ivda.vda_name = BYTE_GET (evda.vda_name);
3377
3378                               if (psym->st_name != ivda.vda_name)
3379                                 printf ((vers_data & 0x8000)
3380                                         ? "@%s" : "@@%s",
3381                                         strtab + ivda.vda_name);
3382                             }
3383                         }
3384                     }
3385                 }
3386
3387               putchar ('\n');
3388             }
3389
3390           free (symtab);
3391           if (strtab != string_table)
3392             free (strtab);
3393         }
3394     }
3395   else if (do_syms)
3396     printf
3397       (_("\nDynamic symbol information is not available for displaying symbols.\n"));
3398
3399   if (do_histogram && buckets != NULL)
3400     {
3401       int *lengths;
3402       int *counts;
3403       int hn;
3404       int si;
3405       int maxlength = 0;
3406       int nzero_counts = 0;
3407       int nsyms = 0;
3408
3409       printf (_("\nHistogram for bucket list length (total of %d buckets):\n"),
3410               nbuckets);
3411       printf (_(" Length  Number     %% of total  Coverage\n"));
3412
3413       lengths = (int *) calloc (nbuckets, sizeof (int));
3414       if (lengths == NULL)
3415         {
3416           error (_("Out of memory"));
3417           return 0;
3418         }
3419       for (hn = 0; hn < nbuckets; ++hn)
3420         {
3421           if (! buckets [hn])
3422             continue;
3423
3424           for (si = buckets[hn]; si; si = chains[si])
3425             {
3426               ++nsyms;
3427               if (maxlength < ++lengths[hn])
3428                 ++maxlength;
3429             }
3430         }
3431
3432       counts = (int *) calloc (maxlength + 1, sizeof (int));
3433       if (counts == NULL)
3434         {
3435           error (_("Out of memory"));
3436           return 0;
3437         }
3438
3439       for (hn = 0; hn < nbuckets; ++hn)
3440         ++ counts [lengths [hn]];
3441
3442       printf ("      0  %-10d (%5.1f%%)\n",
3443               counts[0], (counts[0] * 100.0) / nbuckets);
3444       for (si = 1; si <= maxlength; ++si)
3445         {
3446           nzero_counts += counts[si] * si;
3447           printf ("%7d  %-10d (%5.1f%%)    %5.1f%%\n",
3448                   si, counts[si], (counts[si] * 100.0) / nbuckets,
3449                   (nzero_counts * 100.0) / nsyms);
3450         }
3451
3452       free (counts);
3453       free (lengths);
3454     }
3455
3456   if (buckets != NULL)
3457     {
3458       free (buckets);
3459       free (chains);
3460     }
3461
3462   return 1;
3463 }
3464
3465 static int
3466 process_syminfo (file)
3467      FILE * file;
3468 {
3469   int i;
3470
3471   if (dynamic_syminfo == NULL
3472       || !do_dynamic)
3473     /* No syminfo, this is ok.  */
3474     return 1;
3475
3476   /* There better should be a dynamic symbol section.  */
3477   if (dynamic_symbols == NULL || dynamic_strings == NULL)
3478     return 0;
3479
3480   if (dynamic_addr)
3481     printf (_("\nDynamic info segment at offset 0x%lx contains %d entries:\n"),
3482             dynamic_syminfo_offset, dynamic_syminfo_nent);
3483
3484   printf (_(" Num: Name                           BoundTo     Flags\n"));
3485   for (i = 0; i < dynamic_syminfo_nent; ++i)
3486     {
3487       unsigned short int flags = dynamic_syminfo[i].si_flags;
3488
3489       printf ("%4d: %-30s ", i,
3490               dynamic_strings + dynamic_symbols[i].st_name);
3491
3492       switch (dynamic_syminfo[i].si_boundto)
3493         {
3494         case SYMINFO_BT_SELF:
3495           fputs ("SELF       ", stdout);
3496           break;
3497         case SYMINFO_BT_PARENT:
3498           fputs ("PARENT     ", stdout);
3499           break;
3500         default:
3501           if (dynamic_syminfo[i].si_boundto > 0
3502               && dynamic_syminfo[i].si_boundto < dynamic_size)
3503             printf ("%-10s ",
3504                     dynamic_strings
3505                     + dynamic_segment[dynamic_syminfo[i].si_boundto].d_un.d_val);
3506           else
3507             printf ("%-10d ", dynamic_syminfo[i].si_boundto);
3508           break;
3509         }
3510
3511       if (flags & SYMINFO_FLG_DIRECT)
3512         printf (" DIRECT");
3513       if (flags & SYMINFO_FLG_PASSTHRU)
3514         printf (" PASSTHRU");
3515       if (flags & SYMINFO_FLG_COPY)
3516         printf (" COPY");
3517       if (flags & SYMINFO_FLG_LAZYLOAD)
3518         printf (" LAZYLOAD");
3519
3520       puts ("");
3521     }
3522
3523   return 1;
3524 }
3525
3526 #ifdef SUPPORT_DISASSEMBLY
3527 static void
3528 disassemble_section (section, file)
3529      Elf32_Internal_Shdr * section;
3530      FILE * file;
3531 {
3532   printf (_("\nAssembly dump of section %s\n"),
3533           SECTION_NAME (section));
3534
3535   /* XXX -- to be done --- XXX */
3536
3537   return 1;
3538 }
3539 #endif
3540
3541 static int
3542 dump_section (section, file)
3543      Elf32_Internal_Shdr * section;
3544      FILE * file;
3545 {
3546   int             bytes;
3547   int             addr;
3548   unsigned char * data;
3549   unsigned char * start;
3550
3551   bytes = section->sh_size;
3552
3553   if (bytes == 0)
3554     {
3555       printf (_("\nSection '%s' has no data to dump.\n"),
3556               SECTION_NAME (section));
3557       return 0;
3558     }
3559   else
3560     printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section));
3561
3562   addr = section->sh_addr;
3563
3564   GET_DATA_ALLOC (section->sh_offset, bytes, start, unsigned char *,
3565                   "section data");
3566
3567   data = start;
3568
3569   while (bytes)
3570     {
3571       int j;
3572       int k;
3573       int lbytes;
3574
3575       lbytes = (bytes > 16 ? 16 : bytes);
3576
3577       printf ("  0x%8.8x ", addr);
3578
3579       switch (elf_header.e_ident [EI_DATA])
3580         {
3581         case ELFDATA2LSB:
3582           for (j = 15; j >= 0; j --)
3583             {
3584               if (j < lbytes)
3585                 printf ("%2.2x", data [j]);
3586               else
3587                 printf ("  ");
3588
3589               if (!(j & 0x3))
3590                 printf (" ");
3591             }
3592           break;
3593
3594         case ELFDATA2MSB:
3595           for (j = 0; j < 16; j++)
3596             {
3597               if (j < lbytes)
3598                 printf ("%2.2x", data [j]);
3599               else
3600                 printf ("  ");
3601
3602               if ((j & 3) == 3)
3603                 printf (" ");
3604             }
3605           break;
3606         }
3607
3608       for (j = 0; j < lbytes; j++)
3609         {
3610           k = data [j];
3611           if (k >= ' ' && k < 0x80)
3612             printf ("%c", k);
3613           else
3614             printf (".");
3615         }
3616
3617       putchar ('\n');
3618
3619       data  += lbytes;
3620       addr  += lbytes;
3621       bytes -= lbytes;
3622     }
3623
3624   free (start);
3625
3626   return 1;
3627 }
3628
3629
3630 static unsigned long int
3631 read_leb128 (data, length_return, sign)
3632      unsigned char * data;
3633      int *           length_return;
3634      int             sign;
3635 {
3636   unsigned long int result = 0;
3637   unsigned int      num_read = 0;
3638   int               shift = 0;
3639   unsigned char     byte;
3640
3641   do
3642     {
3643       byte = * data ++;
3644       num_read ++;
3645
3646       result |= (byte & 0x7f) << shift;
3647
3648       shift += 7;
3649
3650     }
3651   while (byte & 0x80);
3652
3653   if (length_return != NULL)
3654     * length_return = num_read;
3655
3656   if (sign && (shift < 32) && (byte & 0x40))
3657     result |= -1 << shift;
3658
3659   return result;
3660 }
3661
3662 typedef struct State_Machine_Registers
3663 {
3664   unsigned long address;
3665   unsigned int  file;
3666   unsigned int  line;
3667   unsigned int  column;
3668   int           is_stmt;
3669   int           basic_block;
3670   int           end_sequence;
3671 /* This variable hold the number of the last entry seen
3672    in the File Table.  */
3673   unsigned int  last_file_entry;
3674 } SMR;
3675
3676 static SMR state_machine_regs;
3677
3678 static void
3679 reset_state_machine (is_stmt)
3680      int is_stmt;
3681 {
3682   state_machine_regs.address = 0;
3683   state_machine_regs.file = 1;
3684   state_machine_regs.line = 1;
3685   state_machine_regs.column = 0;
3686   state_machine_regs.is_stmt = is_stmt;
3687   state_machine_regs.basic_block = 0;
3688   state_machine_regs.end_sequence = 0;
3689   state_machine_regs.last_file_entry = 0;
3690 }
3691
3692 /* Handled an extend line op.  Returns true if this is the end
3693    of sequence.  */
3694 static int
3695 process_extended_line_op (data, is_stmt)
3696      unsigned char * data;
3697      int is_stmt;
3698 {
3699   unsigned char   op_code;
3700   int             bytes_read;
3701   unsigned int    len;
3702   unsigned char * name;
3703   unsigned long   adr;
3704   
3705   len = read_leb128 (data, & bytes_read, 0);
3706   data += bytes_read;
3707
3708   if (len == 0)
3709     {
3710       warn (_("badly formed extended line op encountered!"));
3711       return bytes_read;
3712     }
3713
3714   len += bytes_read;
3715   op_code = * data ++;
3716
3717   printf (_("  Extended opcode %d: "), op_code);
3718   
3719   switch (op_code)
3720     {
3721     case DW_LNE_end_sequence:
3722       printf (_("End of Sequence\n\n"));
3723       reset_state_machine (is_stmt);
3724       break;
3725
3726     case DW_LNE_set_address:
3727       /* XXX - assumption here that address size is 4! */
3728       adr = byte_get (data, 4);
3729       printf (_("set Address to 0x%lx\n"), adr);
3730       state_machine_regs.address = adr;
3731       break;
3732
3733     case DW_LNE_define_file:
3734       printf (_("  define new File Table entry\n"));
3735       printf (_("  Entry\tDir\tTime\tSize\tName\n"));
3736          
3737       printf (_("   %d\t"), ++ state_machine_regs.last_file_entry);
3738       name = data;
3739       data += strlen (data) + 1;
3740       printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
3741       data += bytes_read;
3742       printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
3743       data += bytes_read;
3744       printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
3745       printf (_("%s\n\n"), name);
3746       break;
3747
3748     default:
3749       printf (_("UNKNOWN: length %d\n"), len - bytes_read);
3750       break;
3751     }
3752
3753   return len;
3754 }
3755
3756
3757 static int
3758 display_debug_lines (section, start, file)
3759      Elf32_Internal_Shdr * section;
3760      unsigned char *       start;
3761      FILE *                file;
3762 {
3763   DWARF2_External_LineInfo * external;
3764   DWARF2_Internal_LineInfo   info;
3765   unsigned char *            standard_opcodes;
3766   unsigned char *            data = start;
3767   unsigned char *            end  = start + section->sh_size;
3768   unsigned char *            end_of_sequence;
3769   int                        i;
3770
3771   printf (_("\nDump of debug contents of section %s:\n\n"),
3772           SECTION_NAME (section));
3773
3774   while (data < end)
3775     {
3776       external = (DWARF2_External_LineInfo *) data;
3777
3778       /* Check the length of the block.  */
3779       info.li_length = BYTE_GET (external->li_length);
3780       if (info.li_length > section->sh_size)
3781         {
3782           warn
3783             (_("The line info appears to be corrupt - the section is too small\n"));
3784           return 0;
3785         }
3786       
3787       /* Check its version number.  */
3788       info.li_version = BYTE_GET (external->li_version);
3789       if (info.li_version != 2)
3790         {
3791           warn (_("Only DWARF version 2 line info is currently supported.\n"));
3792           return 0;
3793         }
3794       
3795       info.li_prologue_length = BYTE_GET (external->li_prologue_length);
3796       info.li_min_insn_length = BYTE_GET (external->li_min_insn_length);
3797       info.li_default_is_stmt = BYTE_GET (external->li_default_is_stmt);
3798       info.li_line_base       = BYTE_GET (external->li_line_base);
3799       info.li_line_range      = BYTE_GET (external->li_line_range);
3800       info.li_opcode_base     = BYTE_GET (external->li_opcode_base);
3801       
3802       /* Sign extend the line base field.  */
3803       info.li_line_base <<= 24;
3804       info.li_line_base >>= 24;
3805       
3806       printf (_("  Length:                      %ld\n"), info.li_length);
3807       printf (_("  DWARF Version:               %d\n"), info.li_version);
3808       printf (_("  Prolgue Length:              %d\n"), info.li_prologue_length);
3809       printf (_("  Minimum Instruction Length:  %d\n"), info.li_min_insn_length);
3810       printf (_("  Initial value of 'is_stmt':  %d\n"), info.li_default_is_stmt);
3811       printf (_("  Line Base:                   %d\n"), info.li_line_base);
3812       printf (_("  Line Range:                  %d\n"), info.li_line_range);
3813       printf (_("  Opcode Base:                 %d\n"), info.li_opcode_base);
3814
3815       end_of_sequence = data + info.li_length + sizeof (info.li_length);
3816
3817       reset_state_machine (info.li_default_is_stmt);
3818       
3819       /* Display the contents of the Opcodes table.  */
3820       standard_opcodes = data + sizeof (* external);
3821       
3822       printf (_("\n Opcodes:\n"));
3823       
3824       for (i = 1; i < info.li_opcode_base; i++)
3825         printf (_("  Opcode %d has %d args\n"), i, standard_opcodes[i]);
3826       
3827       /* Display the contents of the Directory table.  */
3828       data = standard_opcodes + info.li_opcode_base - 1;
3829       
3830       if (* data == 0)
3831         printf (_("\n The Directory Table is empty.\n"));
3832       else
3833         {
3834           printf (_("\n The Directory Table:\n"));
3835           
3836           while (* data != 0)
3837             {
3838               printf (_("  %s\n"), data);
3839               
3840               data += strlen (data) + 1;
3841             }
3842         }
3843       
3844       /* Skip the NUL at the end of the table.  */
3845       data ++;
3846       
3847       /* Display the contents of the File Name table.  */
3848       if (* data == 0)
3849         printf (_("\n The File Name Table is empty.\n"));
3850       else
3851         {
3852           printf (_("\n The File Name Table:\n"));
3853           printf (_("  Entry\tDir\tTime\tSize\tName\n"));
3854           
3855           while (* data != 0)
3856             {
3857               char * name;
3858               int bytes_read;
3859               
3860               printf (_("  %d\t"), ++ state_machine_regs.last_file_entry);
3861               name = data;
3862               
3863               data += strlen (data) + 1;
3864               
3865               printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
3866               data += bytes_read;
3867               printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
3868               data += bytes_read;
3869               printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
3870               data += bytes_read;
3871               printf (_("%s\n"), name);
3872             }
3873         }
3874       
3875       /* Skip the NUL at the end of the table.  */
3876       data ++;
3877       
3878       /* Now display the statements.  */
3879       printf (_("\n Line Number Statements:\n"));
3880       
3881       
3882       while (data < end_of_sequence)
3883         {
3884           unsigned char op_code;
3885           int           adv;
3886           int           bytes_read;
3887           
3888           op_code = * data ++;
3889           
3890           switch (op_code)
3891             {
3892             case DW_LNS_extended_op:
3893               data += process_extended_line_op (data, info.li_default_is_stmt);
3894               break;
3895               
3896             case DW_LNS_copy:
3897               printf (_("  Copy\n"));
3898               break;
3899               
3900             case DW_LNS_advance_pc:
3901               adv = info.li_min_insn_length * read_leb128 (data, & bytes_read, 0);
3902               data += bytes_read;
3903               state_machine_regs.address += adv;
3904               printf (_("  Advance PC by %d to %lx\n"), adv,
3905                       state_machine_regs.address);
3906               break;
3907               
3908             case DW_LNS_advance_line:
3909               adv = read_leb128 (data, & bytes_read, 1);
3910               data += bytes_read;
3911               state_machine_regs.line += adv;
3912               printf (_("  Advance Line by %d to %d\n"), adv,
3913                       state_machine_regs.line);
3914               break;
3915               
3916             case DW_LNS_set_file:
3917               adv = read_leb128 (data, & bytes_read, 0);
3918               data += bytes_read;
3919               printf (_("  Set File Name to entry %d in the File Name Table\n"),
3920                       adv);
3921               state_machine_regs.file = adv;
3922               break;
3923               
3924             case DW_LNS_set_column:
3925               adv = read_leb128 (data, & bytes_read, 0);
3926               data += bytes_read;
3927               printf (_("  Set column to %d\n"), adv);
3928               state_machine_regs.column = adv;
3929               break;
3930               
3931             case DW_LNS_negate_stmt:
3932               adv = state_machine_regs.is_stmt;
3933               adv = ! adv;
3934               printf (_("  Set is_stmt to %d\n"), adv);
3935               state_machine_regs.is_stmt = adv;
3936               break;
3937               
3938             case DW_LNS_set_basic_block:
3939               printf (_("  Set basic block\n"));
3940               state_machine_regs.basic_block = 1;
3941               break;
3942               
3943             case DW_LNS_const_add_pc:
3944               adv = (255 - info.li_opcode_base) / info.li_line_range;
3945               state_machine_regs.address += adv;
3946               printf (_("  Advance PC by constant %d to 0x%lx\n"), adv,
3947                       state_machine_regs.address);
3948               break;
3949               
3950             case DW_LNS_fixed_advance_pc:
3951               adv = byte_get (data, 2);
3952               data += 2;
3953               state_machine_regs.address += adv;
3954               printf (_("  Advance PC by fixed size amount %d to 0x%lx\n"),
3955                       adv, state_machine_regs.address);
3956               break;
3957               
3958             default:
3959               op_code -= info.li_opcode_base;
3960               adv      = (op_code / info.li_line_range) * info.li_min_insn_length;
3961               state_machine_regs.address += adv;
3962               printf (_("  Special opcode %d: advance Address by %d to 0x%lx"),
3963                       op_code, adv, state_machine_regs.address);
3964               adv    += (op_code % info.li_line_range) + info.li_line_base;
3965               state_machine_regs.line += adv;
3966               printf (_(" and Line by %d to %d\n"),
3967                       adv, state_machine_regs.line);
3968               break;
3969             }
3970         }
3971       printf ("\n");
3972     }
3973   
3974   return 1;
3975 }
3976
3977 static int
3978 display_debug_pubnames (section, start, file)
3979      Elf32_Internal_Shdr * section;
3980      unsigned char *       start;
3981      FILE *                file;
3982 {
3983   DWARF2_External_PubNames * external;
3984   DWARF2_Internal_PubNames   pubnames;
3985   unsigned char *            end;
3986
3987   end = start + section->sh_size;
3988
3989   printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section));
3990
3991   while (start < end)
3992     {
3993       unsigned char * data;
3994       unsigned long   offset;
3995
3996       external = (DWARF2_External_PubNames *) start;
3997
3998       pubnames.pn_length  = BYTE_GET (external->pn_length);
3999       pubnames.pn_version = BYTE_GET (external->pn_version);
4000       pubnames.pn_offset  = BYTE_GET (external->pn_offset);
4001       pubnames.pn_size    = BYTE_GET (external->pn_size);
4002
4003       data   = start + sizeof (* external);
4004       start += pubnames.pn_length + sizeof (external->pn_length);
4005
4006       if (pubnames.pn_version != 2)
4007         {
4008           warn (_("Only DWARF 2 pubnames are currently supported"));
4009           continue;
4010         }
4011
4012       printf (_("  Length:                              %ld\n"),
4013               pubnames.pn_length);
4014       printf (_("  Version:                             %d\n"),
4015               pubnames.pn_version);
4016       printf (_("  Offset into .debug_info section:     %ld\n"),
4017               pubnames.pn_offset);
4018       printf (_("  Size of area in .debug_info section: %ld\n"),
4019               pubnames.pn_size);
4020
4021       printf (_("\n    Offset\tName\n"));
4022
4023       do
4024         {
4025           offset = byte_get (data, 4);
4026
4027           if (offset != 0)
4028             {
4029               data += 4;
4030               printf ("    %ld\t\t%s\n", offset, data);
4031               data += strlen (data) + 1;
4032             }
4033         }
4034       while (offset != 0);
4035     }
4036
4037   printf ("\n");
4038   return 1;
4039 }
4040
4041 static char *
4042 get_TAG_name (tag)
4043      unsigned long tag;
4044 {
4045   switch (tag)
4046     {
4047     case DW_TAG_padding: return "DW_TAG_padding";
4048     case DW_TAG_array_type: return "DW_TAG_array_type";
4049     case DW_TAG_class_type: return "DW_TAG_class_type";
4050     case DW_TAG_entry_point: return "DW_TAG_entry_point";
4051     case DW_TAG_enumeration_type: return "DW_TAG_enumeration_type";
4052     case DW_TAG_formal_parameter: return "DW_TAG_formal_parameter";
4053     case DW_TAG_imported_declaration: return "DW_TAG_imported_declaration";
4054     case DW_TAG_label: return "DW_TAG_label";
4055     case DW_TAG_lexical_block: return "DW_TAG_lexical_block";
4056     case DW_TAG_member: return "DW_TAG_member";
4057     case DW_TAG_pointer_type: return "DW_TAG_pointer_type";
4058     case DW_TAG_reference_type: return "DW_TAG_reference_type";
4059     case DW_TAG_compile_unit: return "DW_TAG_compile_unit";
4060     case DW_TAG_string_type: return "DW_TAG_string_type";
4061     case DW_TAG_structure_type: return "DW_TAG_structure_type";
4062     case DW_TAG_subroutine_type: return "DW_TAG_subroutine_type";
4063     case DW_TAG_typedef: return "DW_TAG_typedef";
4064     case DW_TAG_union_type: return "DW_TAG_union_type";
4065     case DW_TAG_unspecified_parameters: return "DW_TAG_unspecified_parameters";
4066     case DW_TAG_variant: return "DW_TAG_variant";
4067     case DW_TAG_common_block: return "DW_TAG_common_block";
4068     case DW_TAG_common_inclusion: return "DW_TAG_common_inclusion";
4069     case DW_TAG_inheritance: return "DW_TAG_inheritance";
4070     case DW_TAG_inlined_subroutine: return "DW_TAG_inlined_subroutine";
4071     case DW_TAG_module: return "DW_TAG_module";
4072     case DW_TAG_ptr_to_member_type: return "DW_TAG_ptr_to_member_type";
4073     case DW_TAG_set_type: return "DW_TAG_set_type";
4074     case DW_TAG_subrange_type: return "DW_TAG_subrange_type";
4075     case DW_TAG_with_stmt: return "DW_TAG_with_stmt";
4076     case DW_TAG_access_declaration: return "DW_TAG_access_declaration";
4077     case DW_TAG_base_type: return "DW_TAG_base_type";
4078     case DW_TAG_catch_block: return "DW_TAG_catch_block";
4079     case DW_TAG_const_type: return "DW_TAG_const_type";
4080     case DW_TAG_constant: return "DW_TAG_constant";
4081     case DW_TAG_enumerator: return "DW_TAG_enumerator";
4082     case DW_TAG_file_type: return "DW_TAG_file_type";
4083     case DW_TAG_friend: return "DW_TAG_friend";
4084     case DW_TAG_namelist: return "DW_TAG_namelist";
4085     case DW_TAG_namelist_item: return "DW_TAG_namelist_item";
4086     case DW_TAG_packed_type: return "DW_TAG_packed_type";
4087     case DW_TAG_subprogram: return "DW_TAG_subprogram";
4088     case DW_TAG_template_type_param: return "DW_TAG_template_type_param";
4089     case DW_TAG_template_value_param: return "DW_TAG_template_value_param";
4090     case DW_TAG_thrown_type: return "DW_TAG_thrown_type";
4091     case DW_TAG_try_block: return "DW_TAG_try_block";
4092     case DW_TAG_variant_part: return "DW_TAG_variant_part";
4093     case DW_TAG_variable: return "DW_TAG_variable";
4094     case DW_TAG_volatile_type: return "DW_TAG_volatile_type";
4095     case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop";
4096     case DW_TAG_format_label: return "DW_TAG_format_label";
4097     case DW_TAG_function_template: return "DW_TAG_function_template";
4098     case DW_TAG_class_template: return "DW_TAG_class_template";
4099     default:
4100       {
4101         static char buffer [100];
4102
4103         sprintf (buffer, _("Unknown TAG value: %lx"), tag);
4104         return buffer;
4105       }
4106     }
4107 }
4108
4109 static char *
4110 get_AT_name (attribute)
4111      unsigned long attribute;
4112 {
4113   switch (attribute)
4114     {
4115     case DW_AT_sibling: return "DW_AT_sibling";
4116     case DW_AT_location: return "DW_AT_location";
4117     case DW_AT_name: return "DW_AT_name";
4118     case DW_AT_ordering: return "DW_AT_ordering";
4119     case DW_AT_subscr_data: return "DW_AT_subscr_data";
4120     case DW_AT_byte_size: return "DW_AT_byte_size";
4121     case DW_AT_bit_offset: return "DW_AT_bit_offset";
4122     case DW_AT_bit_size: return "DW_AT_bit_size";
4123     case DW_AT_element_list: return "DW_AT_element_list";
4124     case DW_AT_stmt_list: return "DW_AT_stmt_list";
4125     case DW_AT_low_pc: return "DW_AT_low_pc";
4126     case DW_AT_high_pc: return "DW_AT_high_pc";
4127     case DW_AT_language: return "DW_AT_language";
4128     case DW_AT_member: return "DW_AT_member";
4129     case DW_AT_discr: return "DW_AT_discr";
4130     case DW_AT_discr_value: return "DW_AT_discr_value";
4131     case DW_AT_visibility: return "DW_AT_visibility";
4132     case DW_AT_import: return "DW_AT_import";
4133     case DW_AT_string_length: return "DW_AT_string_length";
4134     case DW_AT_common_reference: return "DW_AT_common_reference";
4135     case DW_AT_comp_dir: return "DW_AT_comp_dir";
4136     case DW_AT_const_value: return "DW_AT_const_value";
4137     case DW_AT_containing_type: return "DW_AT_containing_type";
4138     case DW_AT_default_value: return "DW_AT_default_value";
4139     case DW_AT_inline: return "DW_AT_inline";
4140     case DW_AT_is_optional: return "DW_AT_is_optional";
4141     case DW_AT_lower_bound: return "DW_AT_lower_bound";
4142     case DW_AT_producer: return "DW_AT_producer";
4143     case DW_AT_prototyped: return "DW_AT_prototyped";
4144     case DW_AT_return_addr: return "DW_AT_return_addr";
4145     case DW_AT_start_scope: return "DW_AT_start_scope";
4146     case DW_AT_stride_size: return "DW_AT_stride_size";
4147     case DW_AT_upper_bound: return "DW_AT_upper_bound";
4148     case DW_AT_abstract_origin: return "DW_AT_abstract_origin";
4149     case DW_AT_accessibility: return "DW_AT_accessibility";
4150     case DW_AT_address_class: return "DW_AT_address_class";
4151     case DW_AT_artificial: return "DW_AT_artificial";
4152     case DW_AT_base_types: return "DW_AT_base_types";
4153     case DW_AT_calling_convention: return "DW_AT_calling_convention";
4154     case DW_AT_count: return "DW_AT_count";
4155     case DW_AT_data_member_location: return "DW_AT_data_member_location";
4156     case DW_AT_decl_column: return "DW_AT_decl_column";
4157     case DW_AT_decl_file: return "DW_AT_decl_file";
4158     case DW_AT_decl_line: return "DW_AT_decl_line";
4159     case DW_AT_declaration: return "DW_AT_declaration";
4160     case DW_AT_discr_list: return "DW_AT_discr_list";
4161     case DW_AT_encoding: return "DW_AT_encoding";
4162     case DW_AT_external: return "DW_AT_external";
4163     case DW_AT_frame_base: return "DW_AT_frame_base";
4164     case DW_AT_friend: return "DW_AT_friend";
4165     case DW_AT_identifier_case: return "DW_AT_identifier_case";
4166     case DW_AT_macro_info: return "DW_AT_macro_info";
4167     case DW_AT_namelist_items: return "DW_AT_namelist_items";
4168     case DW_AT_priority: return "DW_AT_priority";
4169     case DW_AT_segment: return "DW_AT_segment";
4170     case DW_AT_specification: return "DW_AT_specification";
4171     case DW_AT_static_link: return "DW_AT_static_link";
4172     case DW_AT_type: return "DW_AT_type";
4173     case DW_AT_use_location: return "DW_AT_use_location";
4174     case DW_AT_variable_parameter: return "DW_AT_variable_parameter";
4175     case DW_AT_virtuality: return "DW_AT_virtuality";
4176     case DW_AT_vtable_elem_location: return "DW_AT_vtable_elem_location";
4177     case DW_AT_MIPS_fde: return "DW_AT_MIPS_fde";
4178     case DW_AT_MIPS_loop_begin: return "DW_AT_MIPS_loop_begin";
4179     case DW_AT_MIPS_tail_loop_begin: return "DW_AT_MIPS_tail_loop_begin";
4180     case DW_AT_MIPS_epilog_begin: return "DW_AT_MIPS_epilog_begin";
4181     case DW_AT_MIPS_loop_unroll_factor: return "DW_AT_MIPS_loop_unroll_factor";
4182     case DW_AT_MIPS_software_pipeline_depth: return "DW_AT_MIPS_software_pipeline_depth";
4183     case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name";
4184     case DW_AT_MIPS_stride: return "DW_AT_MIPS_stride";
4185     case DW_AT_MIPS_abstract_name: return "DW_AT_MIPS_abstract_name";
4186     case DW_AT_MIPS_clone_origin: return "DW_AT_MIPS_clone_origin";
4187     case DW_AT_MIPS_has_inlines: return "DW_AT_MIPS_has_inlines";
4188     case DW_AT_sf_names: return "DW_AT_sf_names";
4189     case DW_AT_src_info: return "DW_AT_src_info";
4190     case DW_AT_mac_info: return "DW_AT_mac_info";
4191     case DW_AT_src_coords: return "DW_AT_src_coords";
4192     case DW_AT_body_begin: return "DW_AT_body_begin";
4193     case DW_AT_body_end: return "DW_AT_body_end";
4194     default:
4195       {
4196         static char buffer [100];
4197
4198         sprintf (buffer, _("Unknown AT value: %lx"), attribute);
4199         return buffer;
4200       }
4201     }
4202 }
4203
4204 static char *
4205 get_FORM_name (form)
4206      unsigned long form;
4207 {
4208   switch (form)
4209     {
4210     case DW_FORM_addr: return "DW_FORM_addr";
4211     case DW_FORM_block2: return "DW_FORM_block2";
4212     case DW_FORM_block4: return "DW_FORM_block4";
4213     case DW_FORM_data2: return "DW_FORM_data2";
4214     case DW_FORM_data4: return "DW_FORM_data4";
4215     case DW_FORM_data8: return "DW_FORM_data8";
4216     case DW_FORM_string: return "DW_FORM_string";
4217     case DW_FORM_block: return "DW_FORM_block";
4218     case DW_FORM_block1: return "DW_FORM_block1";
4219     case DW_FORM_data1: return "DW_FORM_data1";
4220     case DW_FORM_flag: return "DW_FORM_flag";
4221     case DW_FORM_sdata: return "DW_FORM_sdata";
4222     case DW_FORM_strp: return "DW_FORM_strp";
4223     case DW_FORM_udata: return "DW_FORM_udata";
4224     case DW_FORM_ref_addr: return "DW_FORM_ref_addr";
4225     case DW_FORM_ref1: return "DW_FORM_ref1";
4226     case DW_FORM_ref2: return "DW_FORM_ref2";
4227     case DW_FORM_ref4: return "DW_FORM_ref4";
4228     case DW_FORM_ref8: return "DW_FORM_ref8";
4229     case DW_FORM_ref_udata: return "DW_FORM_ref_udata";
4230     case DW_FORM_indirect: return "DW_FORM_indirect";
4231     default:
4232       {
4233         static char buffer [100];
4234
4235         sprintf (buffer, _("Unknown FORM value: %lx"), form);
4236         return buffer;
4237       }
4238     }
4239 }
4240
4241 /* FIXME:  There are better and more effiecint ways to handle
4242    these structures.  For now though, I just want something that
4243    is simple to implement.  */
4244 typedef struct abbrev_attr
4245 {
4246   unsigned long        attribute;
4247   unsigned long        form;
4248   struct abbrev_attr * next;
4249 }
4250 abbrev_attr;
4251
4252 typedef struct abbrev_entry
4253 {
4254   unsigned long          entry;
4255   unsigned long          tag;
4256   int                    children;
4257   struct abbrev_attr *   first_attr;
4258   struct abbrev_attr *   last_attr;
4259   struct abbrev_entry *  next;
4260 }
4261 abbrev_entry;
4262
4263 static abbrev_entry * first_abbrev = NULL;
4264 static abbrev_entry * last_abbrev = NULL;
4265
4266 static void
4267 free_abbrevs PARAMS ((void))
4268 {
4269   abbrev_entry * abbrev;
4270
4271   for (abbrev = first_abbrev; abbrev;)
4272     {
4273       abbrev_entry * next = abbrev->next;
4274       abbrev_attr  * attr;
4275
4276       for (attr = abbrev->first_attr; attr;)
4277         {
4278           abbrev_attr * next = attr->next;
4279
4280           free (attr);
4281           attr = next;
4282         }
4283
4284       free (abbrev);
4285       abbrev = next;
4286     }
4287
4288   last_abbrev = first_abbrev = NULL;
4289 }
4290
4291 static void
4292 add_abbrev (number, tag, children)
4293      unsigned long number;
4294      unsigned long tag;
4295      int           children;
4296 {
4297   abbrev_entry * entry;
4298
4299   entry = (abbrev_entry *) malloc (sizeof (* entry));
4300
4301   if (entry == NULL)
4302     /* ugg */
4303     return;
4304
4305   entry->entry      = number;
4306   entry->tag        = tag;
4307   entry->children   = children;
4308   entry->first_attr = NULL;
4309   entry->last_attr  = NULL;
4310   entry->next       = NULL;
4311
4312   if (first_abbrev == NULL)
4313     first_abbrev = entry;
4314   else
4315     last_abbrev->next = entry;
4316
4317   last_abbrev = entry;
4318 }
4319
4320 static void
4321 add_abbrev_attr (attribute, form)
4322      unsigned long attribute;
4323      unsigned long form;
4324 {
4325   abbrev_attr * attr;
4326
4327   attr = (abbrev_attr *) malloc (sizeof (* attr));
4328
4329   if (attr == NULL)
4330     /* ugg */
4331     return;
4332
4333   attr->attribute = attribute;
4334   attr->form      = form;
4335   attr->next      = NULL;
4336
4337   if (last_abbrev->first_attr == NULL)
4338     last_abbrev->first_attr = attr;
4339   else
4340     last_abbrev->last_attr->next = attr;
4341
4342   last_abbrev->last_attr = attr;
4343 }
4344
4345 /* Processes the (partial) contents of a .debug_abbrev section.
4346    Returns NULL if the end of the section was encountered.
4347    Returns the address after the last byte read if the end of
4348    an abbreviation set was found.  */
4349
4350 static unsigned char *
4351 process_abbrev_section (start, end)
4352      unsigned char * start;
4353      unsigned char * end;
4354 {
4355   if (first_abbrev != NULL)
4356     return NULL;
4357
4358   while (start < end)
4359     {
4360       int           bytes_read;
4361       unsigned long entry;
4362       unsigned long tag;
4363       unsigned long attribute;
4364       int           children;
4365
4366       entry = read_leb128 (start, & bytes_read, 0);
4367       start += bytes_read;
4368
4369       if (entry == 0)
4370         return start;
4371
4372       tag = read_leb128 (start, & bytes_read, 0);
4373       start += bytes_read;
4374
4375       children = * start ++;
4376
4377       add_abbrev (entry, tag, children);
4378
4379       do
4380         {
4381           unsigned long form;
4382
4383           attribute = read_leb128 (start, & bytes_read, 0);
4384           start += bytes_read;
4385
4386           form = read_leb128 (start, & bytes_read, 0);
4387           start += bytes_read;
4388
4389           if (attribute != 0)
4390             add_abbrev_attr (attribute, form);
4391         }
4392       while (attribute != 0);
4393     }
4394
4395   return NULL;
4396 }
4397
4398
4399 static int
4400 display_debug_abbrev (section, start, file)
4401      Elf32_Internal_Shdr * section;
4402      unsigned char *       start;
4403      FILE *                file;
4404 {
4405   abbrev_entry * entry;
4406   unsigned char * end = start + section->sh_size;
4407
4408   printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section));
4409
4410   do
4411     {
4412       start = process_abbrev_section (start, end);
4413
4414       printf (_("  Number TAG\n"));
4415
4416       for (entry = first_abbrev; entry; entry = entry->next)
4417         {
4418           abbrev_attr * attr;
4419
4420           printf (_("   %ld      %s    [%s]\n"),
4421                   entry->entry,
4422                   get_TAG_name (entry->tag),
4423                   entry->children ? _("has children") : _("no children"));
4424
4425           for (attr = entry->first_attr; attr; attr = attr->next)
4426             {
4427               printf (_("    %-18s %s\n"),
4428                       get_AT_name (attr->attribute),
4429                       get_FORM_name (attr->form));
4430             }
4431         }
4432     }
4433   while (start);
4434
4435   printf ("\n");
4436
4437   return 1;
4438 }
4439
4440
4441 static unsigned char *
4442 display_block (data, length)
4443      unsigned char * data;
4444      unsigned long   length;
4445 {
4446   printf (_(" %lu byte block: "), length);
4447
4448   while (length --)
4449     printf ("%lx ", byte_get (data ++, 1));
4450
4451   return data;
4452 }
4453
4454 static void
4455 decode_location_expression (data, pointer_size)
4456      unsigned char * data;
4457      unsigned int    pointer_size;
4458 {
4459   unsigned char op;
4460   int           bytes_read;
4461
4462   op = * data ++;
4463
4464   switch (op)
4465     {
4466     case DW_OP_addr:    printf ("DW_OP_addr: %lx", byte_get (data, pointer_size)); break;
4467     case DW_OP_deref:   printf ("DW_OP_deref"); break;
4468     case DW_OP_const1u: printf ("DW_OP_const1u: %lu", byte_get (data, 1)); break;
4469     case DW_OP_const1s: printf ("DW_OP_const1s: %ld", (long) byte_get (data, 1)); break;
4470     case DW_OP_const2u: printf ("DW_OP_const2u: %lu", byte_get (data, 2)); break;
4471     case DW_OP_const2s: printf ("DW_OP_const2s: %ld", (long) byte_get (data, 2)); break;
4472     case DW_OP_const4u: printf ("DW_OP_const4u: %lu", byte_get (data, 4)); break;
4473     case DW_OP_const4s: printf ("DW_OP_const4s: %ld", (long) byte_get (data, 4)); break;
4474     case DW_OP_const8u: printf ("DW_OP_const8u: %lu %lu", byte_get (data, 4), byte_get (data + 4, 4)); break;
4475     case DW_OP_const8s: printf ("DW_OP_const8s: %ld %ld", byte_get (data, 4), byte_get (data + 4, 4)); break;
4476     case DW_OP_constu:  printf ("DW_OP_constu: %lu", read_leb128 (data, NULL, 0)); break;
4477     case DW_OP_consts:  printf ("DW_OP_consts: %ld", read_leb128 (data, NULL, 1)); break;
4478     case DW_OP_dup:     printf ("DW_OP_dup"); break;
4479     case DW_OP_drop:    printf ("DW_OP_drop"); break;
4480     case DW_OP_over:    printf ("DW_OP_over"); break;
4481     case DW_OP_pick:    printf ("DW_OP_pick: %ld", byte_get (data, 1)); break;
4482     case DW_OP_swap:    printf ("DW_OP_swap"); break;
4483     case DW_OP_rot:     printf ("DW_OP_rot"); break;
4484     case DW_OP_xderef:  printf ("DW_OP_xderef"); break;
4485     case DW_OP_abs:     printf ("DW_OP_abs"); break;
4486     case DW_OP_and:     printf ("DW_OP_and"); break;
4487     case DW_OP_div:     printf ("DW_OP_div"); break;
4488     case DW_OP_minus:   printf ("DW_OP_minus"); break;
4489     case DW_OP_mod:     printf ("DW_OP_mod"); break;
4490     case DW_OP_mul:     printf ("DW_OP_mul"); break;
4491     case DW_OP_neg:     printf ("DW_OP_neg"); break;
4492     case DW_OP_not:     printf ("DW_OP_not"); break;
4493     case DW_OP_or:      printf ("DW_OP_or"); break;
4494     case DW_OP_plus:    printf ("DW_OP_plus"); break;
4495     case DW_OP_plus_uconst:     printf ("DW_OP_plus_uconst: %lu", read_leb128 (data, NULL, 0)); break;
4496     case DW_OP_shl:     printf ("DW_OP_shl"); break;
4497     case DW_OP_shr:     printf ("DW_OP_shr"); break;
4498     case DW_OP_shra:    printf ("DW_OP_shra"); break;
4499     case DW_OP_xor:     printf ("DW_OP_xor"); break;
4500     case DW_OP_bra:     printf ("DW_OP_bra: %ld", byte_get (data, 2)); break;
4501     case DW_OP_eq:      printf ("DW_OP_eq"); break;
4502     case DW_OP_ge:      printf ("DW_OP_ge"); break;
4503     case DW_OP_gt:      printf ("DW_OP_gt"); break;
4504     case DW_OP_le:      printf ("DW_OP_le"); break;
4505     case DW_OP_lt:      printf ("DW_OP_lt"); break;
4506     case DW_OP_ne:      printf ("DW_OP_ne"); break;
4507     case DW_OP_skip:    printf ("DW_OP_skip: %ld", byte_get (data, 2)); break;
4508     case DW_OP_lit0:    printf ("DW_OP_lit0"); break;
4509     case DW_OP_lit1:    printf ("DW_OP_lit1"); break;
4510     case DW_OP_lit2:    printf ("DW_OP_lit2"); break;
4511     case DW_OP_lit3:    printf ("DW_OP_lit3"); break;
4512     case DW_OP_lit4:    printf ("DW_OP_lit4"); break;
4513     case DW_OP_lit5:    printf ("DW_OP_lit5"); break;
4514     case DW_OP_lit6:    printf ("DW_OP_lit6"); break;
4515     case DW_OP_lit7:    printf ("DW_OP_lit7"); break;
4516     case DW_OP_lit8:    printf ("DW_OP_lit8"); break;
4517     case DW_OP_lit9:    printf ("DW_OP_lit9"); break;
4518     case DW_OP_lit10:   printf ("DW_OP_lit10"); break;
4519     case DW_OP_lit11:   printf ("DW_OP_lit11"); break;
4520     case DW_OP_lit12:   printf ("DW_OP_lit12"); break;
4521     case DW_OP_lit13:   printf ("DW_OP_lit13"); break;
4522     case DW_OP_lit14:   printf ("DW_OP_lit14"); break;
4523     case DW_OP_lit15:   printf ("DW_OP_lit15"); break;
4524     case DW_OP_lit16:   printf ("DW_OP_lit16"); break;
4525     case DW_OP_lit17:   printf ("DW_OP_lit17"); break;
4526     case DW_OP_lit18:   printf ("DW_OP_lit18"); break;
4527     case DW_OP_lit19:   printf ("DW_OP_lit19"); break;
4528     case DW_OP_lit20:   printf ("DW_OP_lit20"); break;
4529     case DW_OP_lit21:   printf ("DW_OP_lit21"); break;
4530     case DW_OP_lit22:   printf ("DW_OP_lit22"); break;
4531     case DW_OP_lit23:   printf ("DW_OP_lit23"); break;
4532     case DW_OP_lit24:   printf ("DW_OP_lit24"); break;
4533     case DW_OP_lit25:   printf ("DW_OP_lit25"); break;
4534     case DW_OP_lit26:   printf ("DW_OP_lit26"); break;
4535     case DW_OP_lit27:   printf ("DW_OP_lit27"); break;
4536     case DW_OP_lit28:   printf ("DW_OP_lit28"); break;
4537     case DW_OP_lit29:   printf ("DW_OP_lit29"); break;
4538     case DW_OP_lit30:   printf ("DW_OP_lit30"); break;
4539     case DW_OP_lit31:   printf ("DW_OP_lit31"); break;
4540     case DW_OP_reg0:    printf ("DW_OP_reg0"); break;
4541     case DW_OP_reg1:    printf ("DW_OP_reg1"); break;
4542     case DW_OP_reg2:    printf ("DW_OP_reg2"); break;
4543     case DW_OP_reg3:    printf ("DW_OP_reg3"); break;
4544     case DW_OP_reg4:    printf ("DW_OP_reg4"); break;
4545     case DW_OP_reg5:    printf ("DW_OP_reg5"); break;
4546     case DW_OP_reg6:    printf ("DW_OP_reg6"); break;
4547     case DW_OP_reg7:    printf ("DW_OP_reg7"); break;
4548     case DW_OP_reg8:    printf ("DW_OP_reg8"); break;
4549     case DW_OP_reg9:    printf ("DW_OP_reg9"); break;
4550     case DW_OP_reg10:   printf ("DW_OP_reg10"); break;
4551     case DW_OP_reg11:   printf ("DW_OP_reg11"); break;
4552     case DW_OP_reg12:   printf ("DW_OP_reg12"); break;
4553     case DW_OP_reg13:   printf ("DW_OP_reg13"); break;
4554     case DW_OP_reg14:   printf ("DW_OP_reg14"); break;
4555     case DW_OP_reg15:   printf ("DW_OP_reg15"); break;
4556     case DW_OP_reg16:   printf ("DW_OP_reg16"); break;
4557     case DW_OP_reg17:   printf ("DW_OP_reg17"); break;
4558     case DW_OP_reg18:   printf ("DW_OP_reg18"); break;
4559     case DW_OP_reg19:   printf ("DW_OP_reg19"); break;
4560     case DW_OP_reg20:   printf ("DW_OP_reg20"); break;
4561     case DW_OP_reg21:   printf ("DW_OP_reg21"); break;
4562     case DW_OP_reg22:   printf ("DW_OP_reg22"); break;
4563     case DW_OP_reg23:   printf ("DW_OP_reg23"); break;
4564     case DW_OP_reg24:   printf ("DW_OP_reg24"); break;
4565     case DW_OP_reg25:   printf ("DW_OP_reg25"); break;
4566     case DW_OP_reg26:   printf ("DW_OP_reg26"); break;
4567     case DW_OP_reg27:   printf ("DW_OP_reg27"); break;
4568     case DW_OP_reg28:   printf ("DW_OP_reg28"); break;
4569     case DW_OP_reg29:   printf ("DW_OP_reg29"); break;
4570     case DW_OP_reg30:   printf ("DW_OP_reg30"); break;
4571     case DW_OP_reg31:   printf ("DW_OP_reg31"); break;
4572     case DW_OP_breg0:   printf ("DW_OP_breg0: %ld", read_leb128 (data, NULL, 1)); break;
4573     case DW_OP_breg1:   printf ("DW_OP_breg1: %ld", read_leb128 (data, NULL, 1)); break;
4574     case DW_OP_breg2:   printf ("DW_OP_breg2: %ld", read_leb128 (data, NULL, 1)); break;
4575     case DW_OP_breg3:   printf ("DW_OP_breg3: %ld", read_leb128 (data, NULL, 1)); break;
4576     case DW_OP_breg4:   printf ("DW_OP_breg4: %ld", read_leb128 (data, NULL, 1)); break;
4577     case DW_OP_breg5:   printf ("DW_OP_breg5: %ld", read_leb128 (data, NULL, 1)); break;
4578     case DW_OP_breg6:   printf ("DW_OP_breg6: %ld", read_leb128 (data, NULL, 1)); break;
4579     case DW_OP_breg7:   printf ("DW_OP_breg7: %ld", read_leb128 (data, NULL, 1)); break;
4580     case DW_OP_breg8:   printf ("DW_OP_breg8: %ld", read_leb128 (data, NULL, 1)); break;
4581     case DW_OP_breg9:   printf ("DW_OP_breg9: %ld", read_leb128 (data, NULL, 1)); break;
4582     case DW_OP_breg10:  printf ("DW_OP_breg10: %ld", read_leb128 (data, NULL, 1)); break;
4583     case DW_OP_breg11:  printf ("DW_OP_breg11: %ld", read_leb128 (data, NULL, 1)); break;
4584     case DW_OP_breg12:  printf ("DW_OP_breg12: %ld", read_leb128 (data, NULL, 1)); break;
4585     case DW_OP_breg13:  printf ("DW_OP_breg13: %ld", read_leb128 (data, NULL, 1)); break;
4586     case DW_OP_breg14:  printf ("DW_OP_breg14: %ld", read_leb128 (data, NULL, 1)); break;
4587     case DW_OP_breg15:  printf ("DW_OP_breg15: %ld", read_leb128 (data, NULL, 1)); break;
4588     case DW_OP_breg16:  printf ("DW_OP_breg16: %ld", read_leb128 (data, NULL, 1)); break;
4589     case DW_OP_breg17:  printf ("DW_OP_breg17: %ld", read_leb128 (data, NULL, 1)); break;
4590     case DW_OP_breg18:  printf ("DW_OP_breg18: %ld", read_leb128 (data, NULL, 1)); break;
4591     case DW_OP_breg19:  printf ("DW_OP_breg19: %ld", read_leb128 (data, NULL, 1)); break;
4592     case DW_OP_breg20:  printf ("DW_OP_breg20: %ld", read_leb128 (data, NULL, 1)); break;
4593     case DW_OP_breg21:  printf ("DW_OP_breg21: %ld", read_leb128 (data, NULL, 1)); break;
4594     case DW_OP_breg22:  printf ("DW_OP_breg22: %ld", read_leb128 (data, NULL, 1)); break;
4595     case DW_OP_breg23:  printf ("DW_OP_breg23: %ld", read_leb128 (data, NULL, 1)); break;
4596     case DW_OP_breg24:  printf ("DW_OP_breg24: %ld", read_leb128 (data, NULL, 1)); break;
4597     case DW_OP_breg25:  printf ("DW_OP_breg25: %ld", read_leb128 (data, NULL, 1)); break;
4598     case DW_OP_breg26:  printf ("DW_OP_breg26: %ld", read_leb128 (data, NULL, 1)); break;
4599     case DW_OP_breg27:  printf ("DW_OP_breg27: %ld", read_leb128 (data, NULL, 1)); break;
4600     case DW_OP_breg28:  printf ("DW_OP_breg28: %ld", read_leb128 (data, NULL, 1)); break;
4601     case DW_OP_breg29:  printf ("DW_OP_breg29: %ld", read_leb128 (data, NULL, 1)); break;
4602     case DW_OP_breg30:  printf ("DW_OP_breg30: %ld", read_leb128 (data, NULL, 1)); break;
4603     case DW_OP_breg31:  printf ("DW_OP_breg31: %ld", read_leb128 (data, NULL, 1)); break;
4604     case DW_OP_regx:    printf ("DW_OP_regx: %lu", read_leb128 (data, NULL, 0)); break;
4605     case DW_OP_fbreg:   printf ("DW_OP_fbreg: %ld", read_leb128 (data, NULL, 1)); break;
4606     case DW_OP_bregx:   printf ("DW_OP_bregx: %lu %ld", read_leb128 (data, & bytes_read, 0), read_leb128 (data + bytes_read, NULL, 1)); break;
4607     case DW_OP_piece:   printf ("DW_OP_piece: %lu", read_leb128 (data, NULL, 0)); break;
4608     case DW_OP_deref_size:      printf ("DW_OP_deref_size: %ld", byte_get (data, 1)); break;
4609     case DW_OP_xderef_size:     printf ("DW_OP_xderef_size: %ld", byte_get (data, 1)); break;
4610     case DW_OP_nop:     printf ("DW_OP_nop"); break;
4611
4612     default:
4613       if (op >= DW_OP_lo_user
4614           && op <= DW_OP_hi_user)
4615         printf (_("(User defined location op)"));
4616       else
4617         printf (_("(Unknown location op)"));
4618       break;
4619     }
4620 }
4621
4622
4623 static unsigned char *
4624 read_and_display_attr (attribute, form, data, pointer_size)
4625      unsigned long   attribute;
4626      unsigned long   form;
4627      unsigned char * data;
4628      unsigned long   pointer_size;
4629 {
4630   unsigned long   uvalue;
4631   unsigned char * block_start;
4632   int             bytes_read;
4633   int             is_ref = 0;
4634
4635   printf ("     %-18s:", get_AT_name (attribute));
4636
4637   switch (form)
4638     {
4639     case DW_FORM_ref_addr:
4640     case DW_FORM_ref1:
4641     case DW_FORM_ref2:
4642     case DW_FORM_ref4:
4643     case DW_FORM_ref8:
4644     case DW_FORM_ref_udata:
4645       is_ref = 1;
4646     }
4647
4648   switch (form)
4649     {
4650     case DW_FORM_ref_addr:
4651     case DW_FORM_addr:
4652       uvalue = byte_get (data, pointer_size);
4653       printf (is_ref ? " <%x>" : " %#x", uvalue);
4654       data += pointer_size;
4655       break;
4656
4657     case DW_FORM_ref1:
4658     case DW_FORM_flag:
4659     case DW_FORM_data1:
4660       uvalue = byte_get (data ++, 1);
4661       printf (is_ref ? " <%x>" : " %d", uvalue);
4662       break;
4663
4664     case DW_FORM_ref2:
4665     case DW_FORM_data2:
4666       uvalue = byte_get (data, 2);
4667       data += 2;
4668       printf (is_ref ? " <%x>" : " %d", uvalue);
4669       break;
4670
4671     case DW_FORM_ref4:
4672     case DW_FORM_data4:
4673       uvalue = byte_get (data, 4);
4674       data += 4;
4675       printf (is_ref ? " <%x>" : " %d", uvalue);
4676       break;
4677
4678     case DW_FORM_ref8:
4679     case DW_FORM_data8:
4680       uvalue = byte_get (data, 4);
4681       printf (" %lx", uvalue);
4682       printf (" %lx", byte_get (data + 4, 4));
4683       data += 8;
4684       break;
4685
4686     case DW_FORM_string:
4687       printf (" %s", data);
4688       data += strlen (data) + 1;
4689       break;
4690
4691     case DW_FORM_sdata:
4692       uvalue = read_leb128 (data, & bytes_read, 1);
4693       data += bytes_read;
4694       printf (" %ld", (long) uvalue);
4695       break;
4696
4697     case DW_FORM_ref_udata:
4698     case DW_FORM_udata:
4699       uvalue = read_leb128 (data, & bytes_read, 0);
4700       data += bytes_read;
4701       printf (is_ref ? " <%lx>" : " %ld", uvalue);
4702       break;
4703
4704     case DW_FORM_block:
4705       uvalue = read_leb128 (data, & bytes_read, 0);
4706       block_start = data + bytes_read;
4707       data = display_block (block_start, uvalue);
4708       uvalue = * block_start;
4709       break;
4710
4711     case DW_FORM_block1:
4712       uvalue = byte_get (data, 1);
4713       block_start = data + 1;
4714       data = display_block (block_start, uvalue);
4715       uvalue = * block_start;
4716       break;
4717
4718     case DW_FORM_block2:
4719       uvalue = byte_get (data, 2);
4720       block_start = data + 2;
4721       data = display_block (block_start, uvalue);
4722       uvalue = * block_start;
4723       break;
4724
4725     case DW_FORM_block4:
4726       uvalue = byte_get (data, 4);
4727       block_start = data + 4;
4728       data = display_block (block_start, uvalue);
4729       uvalue = * block_start;
4730       break;
4731
4732     case DW_FORM_strp:
4733     case DW_FORM_indirect:
4734       warn (_("Unable to handle FORM: %d"), form);
4735       break;
4736
4737     default:
4738       warn (_("Unrecognised form: %d"), form);
4739       break;
4740     }
4741
4742   /* For some attributes we can display futher information.  */
4743
4744   printf ("\t");
4745
4746   switch (attribute)
4747     {
4748     case DW_AT_inline:
4749       switch (uvalue)
4750         {
4751         case DW_INL_not_inlined:          printf (_("(not inlined)")); break;
4752         case DW_INL_inlined:              printf (_("(inlined)")); break;
4753         case DW_INL_declared_not_inlined: printf (_("(declared as inline but ignored)")); break;
4754         case DW_INL_declared_inlined:     printf (_("(declared as inline and inlined)")); break;
4755         default: printf (_("  (Unknown inline attribute value: %lx)"), uvalue); break;
4756         }
4757       break;
4758
4759     case DW_AT_frame_base:
4760       if (uvalue >= DW_OP_reg0 && uvalue <= DW_OP_reg31)
4761         printf ("(reg %ld)", uvalue - DW_OP_reg0);
4762       break;
4763
4764     case DW_AT_language:
4765       switch (uvalue)
4766         {
4767         case DW_LANG_C:              printf ("(non-ANSI C)"); break;
4768         case DW_LANG_C89:            printf ("(ANSI C)"); break;
4769         case DW_LANG_C_plus_plus:    printf ("(C++)"); break;
4770         case DW_LANG_Fortran77:      printf ("(FORTRAN 77)"); break;
4771         case DW_LANG_Fortran90:      printf ("(Fortran 90)"); break;
4772         case DW_LANG_Modula2:        printf ("(Modula 2)"); break;
4773         case DW_LANG_Pascal83:       printf ("(ANSI Pascal)"); break;
4774         case DW_LANG_Ada83:          printf ("(Ada)"); break;
4775         case DW_LANG_Cobol74:        printf ("(Cobol 74)"); break;
4776         case DW_LANG_Cobol85:        printf ("(Cobol 85)"); break;
4777         case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break;
4778         default:                     printf ("(Unknown: %lx)", uvalue); break;
4779         }
4780       break;
4781
4782     case DW_AT_encoding:
4783       switch (uvalue)
4784         {
4785         case DW_ATE_void:            printf ("(void)"); break;
4786         case DW_ATE_address:         printf ("(machine address)"); break;
4787         case DW_ATE_boolean:         printf ("(boolean)"); break;
4788         case DW_ATE_complex_float:   printf ("(complex float)"); break;
4789         case DW_ATE_float:           printf ("(float)"); break;
4790         case DW_ATE_signed:          printf ("(signed)"); break;
4791         case DW_ATE_signed_char:     printf ("(signed char)"); break;
4792         case DW_ATE_unsigned:        printf ("(unsigned)"); break;
4793         case DW_ATE_unsigned_char:   printf ("(unsigned char)"); break;
4794         default:
4795           if (uvalue >= DW_ATE_lo_user
4796               && uvalue <= DW_ATE_hi_user)
4797             printf ("(user defined type)");
4798           else
4799             printf ("(unknown type)");
4800           break;
4801         }
4802       break;
4803
4804     case DW_AT_accessibility:
4805       switch (uvalue)
4806         {
4807         case DW_ACCESS_public:          printf ("(public)"); break;
4808         case DW_ACCESS_protected:       printf ("(protected)"); break;
4809         case DW_ACCESS_private:         printf ("(private)"); break;
4810         default:                        printf ("(unknown accessibility)"); break;
4811         }
4812       break;
4813
4814     case DW_AT_visibility:
4815       switch (uvalue)
4816         {
4817         case DW_VIS_local:      printf ("(local)"); break;
4818         case DW_VIS_exported:   printf ("(exported)"); break;
4819         case DW_VIS_qualified:  printf ("(qualified)"); break;
4820         default:                printf ("(unknown visibility)"); break;
4821         }
4822       break;
4823
4824     case DW_AT_virtuality:
4825       switch (uvalue)
4826         {
4827         case DW_VIRTUALITY_none:        printf ("(none)"); break;
4828         case DW_VIRTUALITY_virtual:     printf ("(virtual)"); break;
4829         case DW_VIRTUALITY_pure_virtual:printf ("(pure_virtual)"); break;
4830         default:                        printf ("(unknown virtuality)"); break;
4831         }
4832       break;
4833
4834     case DW_AT_identifier_case:
4835       switch (uvalue)
4836         {
4837         case DW_ID_case_sensitive:      printf ("(case_sensitive)"); break;
4838         case DW_ID_up_case:             printf ("(up_case)"); break;
4839         case DW_ID_down_case:           printf ("(down_case)"); break;
4840         case DW_ID_case_insensitive:    printf ("(case_insensitive)"); break;
4841         default:                        printf ("(unknown case)"); break;
4842         }
4843       break;
4844
4845     case DW_AT_calling_convention:
4846       switch (uvalue)
4847         {
4848         case DW_CC_normal:      printf ("(normal)"); break;
4849         case DW_CC_program:     printf ("(program)"); break;
4850         case DW_CC_nocall:      printf ("(nocall)"); break;
4851         default:
4852           if (uvalue >= DW_CC_lo_user
4853               && uvalue <= DW_CC_hi_user)
4854             printf ("(user defined)");
4855           else
4856             printf ("(unknown convention)");
4857         }
4858       break;
4859
4860     case DW_AT_location:
4861     case DW_AT_data_member_location:
4862     case DW_AT_vtable_elem_location:
4863       printf ("(");
4864       decode_location_expression (block_start, pointer_size);
4865       printf (")");
4866       break;
4867
4868     default:
4869       break;
4870     }
4871
4872   printf ("\n");
4873   return data;
4874 }
4875
4876 static int
4877 display_debug_info (section, start, file)
4878      Elf32_Internal_Shdr * section;
4879      unsigned char *       start;
4880      FILE *                file;
4881 {
4882   unsigned char * end = start + section->sh_size;
4883   unsigned char * section_begin = start;
4884
4885   printf (_("The section %s contains:\n\n"), SECTION_NAME (section));
4886
4887   while (start < end)
4888     {
4889       DWARF2_External_CompUnit * external;
4890       DWARF2_Internal_CompUnit   compunit;
4891       unsigned char *            tags;
4892       int                        i;
4893       int                        level;
4894
4895       external = (DWARF2_External_CompUnit *) start;
4896
4897       compunit.cu_length        = BYTE_GET (external->cu_length);
4898       compunit.cu_version       = BYTE_GET (external->cu_version);
4899       compunit.cu_abbrev_offset = BYTE_GET (external->cu_abbrev_offset);
4900       compunit.cu_pointer_size  = BYTE_GET (external->cu_pointer_size);
4901
4902       tags = start + sizeof (* external);
4903       start += compunit.cu_length + sizeof (external->cu_length);
4904
4905       if (compunit.cu_version != 2)
4906         {
4907           warn (_("Only version 2 DWARF debug information is currently supported.\n"));
4908           continue;
4909         }
4910
4911       printf (_("  Compilation Unit:\n"));
4912       printf (_("   Length:        %ld\n"), compunit.cu_length);
4913       printf (_("   Version:       %d\n"), compunit.cu_version);
4914       printf (_("   Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset);
4915       printf (_("   Pointer Size:  %d\n"), compunit.cu_pointer_size);
4916
4917       if (first_abbrev != NULL)
4918         free_abbrevs ();
4919
4920       /* Read in the abbrevs used by this compilation unit.  */
4921
4922       {
4923         Elf32_Internal_Shdr * sec;
4924         unsigned char *       begin;
4925
4926         /* Locate the .debug_abbrev section and process it.  */
4927         for (i = 0, sec = section_headers;
4928              i < elf_header.e_shnum;
4929              i ++, sec ++)
4930           if (strcmp (SECTION_NAME (sec), ".debug_abbrev") == 0)
4931             break;
4932
4933         if (i == -1 || sec->sh_size == 0)
4934           {
4935             warn (_("Unable to locate .debug_abbrev section!\n"));
4936             return 0;
4937           }
4938
4939         GET_DATA_ALLOC (sec->sh_offset, sec->sh_size, begin, unsigned char *,
4940                         "debug_abbrev section data");
4941
4942         process_abbrev_section (begin + compunit.cu_abbrev_offset,
4943                                 begin + sec->sh_size);
4944
4945         free (begin);
4946       }
4947
4948       level = 0;
4949       while (tags < start)
4950         {
4951           int            bytes_read;
4952           int            abbrev_number;
4953           abbrev_entry * entry;
4954           abbrev_attr  * attr;
4955
4956           abbrev_number = read_leb128 (tags, & bytes_read, 0);
4957           tags += bytes_read;
4958
4959           /* A null DIE marks the end of a list of children.  */
4960           if (abbrev_number == 0)
4961             {
4962               --level;
4963               continue;
4964             }
4965
4966           /* Scan through the abbreviation list until we reach the
4967              correct entry.  */
4968           for (entry = first_abbrev;
4969                entry && entry->entry != abbrev_number;
4970                entry = entry->next)
4971             continue;
4972
4973           if (entry == NULL)
4974             {
4975               warn (_("Unable to locate entry %d in the abbreviation table\n"),
4976                     abbrev_number);
4977               return 0;
4978             }
4979
4980           printf (_(" <%d><%x>: Abbrev Number: %d (%s)\n"),
4981                   level, tags - section_begin - bytes_read,
4982                   abbrev_number,
4983                   get_TAG_name (entry->tag));
4984
4985           for (attr = entry->first_attr; attr; attr = attr->next)
4986             tags = read_and_display_attr (attr->attribute,
4987                                           attr->form,
4988                                           tags,
4989                                           compunit.cu_pointer_size);
4990
4991           if (entry->children)
4992             ++level;
4993         }
4994     }
4995
4996   printf ("\n");
4997
4998   return 1;
4999 }
5000
5001 static int
5002 display_debug_aranges (section, start, file)
5003      Elf32_Internal_Shdr * section;
5004      unsigned char *       start;
5005      FILE *                file;
5006 {
5007   unsigned char * end = start + section->sh_size;
5008
5009   printf (_("The section %s contains:\n\n"), SECTION_NAME (section));
5010
5011   while (start < end)
5012     {
5013       DWARF2_External_ARange * external;
5014       DWARF2_Internal_ARange   arange;
5015       unsigned char *          ranges;
5016       unsigned long            length;
5017       unsigned long            address;
5018
5019       external = (DWARF2_External_ARange *) start;
5020
5021       arange.ar_length       = BYTE_GET (external->ar_length);
5022       arange.ar_version      = BYTE_GET (external->ar_version);
5023       arange.ar_info_offset  = BYTE_GET (external->ar_info_offset);
5024       arange.ar_pointer_size = BYTE_GET (external->ar_pointer_size);
5025       arange.ar_segment_size = BYTE_GET (external->ar_segment_size);
5026
5027       printf (_("  Length:                   %ld\n"), arange.ar_length);
5028       printf (_("  Version:                  %d\n"), arange.ar_version);
5029       printf (_("  Offset into .debug_info:  %lx\n"), arange.ar_info_offset);
5030       printf (_("  Pointer Size:             %d\n"), arange.ar_pointer_size);
5031       printf (_("  Segment Size:             %d\n"), arange.ar_segment_size);
5032
5033       printf (_("\n    Address  Length\n"));
5034
5035       ranges = start + sizeof (* external);
5036
5037       for (;;)
5038         {
5039           address = byte_get (ranges, arange.ar_pointer_size);
5040
5041           if (address == 0)
5042             break;
5043
5044           ranges += arange.ar_pointer_size;
5045
5046           length  = byte_get (ranges, arange.ar_pointer_size);
5047
5048           ranges += arange.ar_pointer_size;
5049
5050           printf ("    %8.8lx %lu\n", address, length);
5051         }
5052
5053       start += arange.ar_length + sizeof (external->ar_length);
5054     }
5055
5056   printf ("\n");
5057
5058   return 1;
5059 }
5060
5061
5062 static int
5063 display_debug_not_supported (section, start, file)
5064      Elf32_Internal_Shdr * section;
5065      unsigned char *       start;
5066      FILE *                file;
5067 {
5068   printf (_("Displaying the debug contents of section %s is not yet supported.\n"),
5069             SECTION_NAME (section));
5070
5071   return 1;
5072 }
5073
5074   /* A structure containing the name of a debug section and a pointer
5075      to a function that can decode it.  */
5076 struct
5077 {
5078   char * name;
5079   int (* display) PARAMS((Elf32_Internal_Shdr *, unsigned char *, FILE *));
5080 }
5081 debug_displays[] =
5082 {
5083   { ".debug_info",        display_debug_info },
5084   { ".debug_abbrev",      display_debug_abbrev },
5085   { ".debug_line",        display_debug_lines },
5086   { ".debug_aranges",     display_debug_aranges },
5087   { ".debug_pubnames",    display_debug_pubnames },
5088   { ".debug_macinfo",     display_debug_not_supported },
5089   { ".debug_frame",       display_debug_not_supported },
5090   { ".debug_str",         display_debug_not_supported },
5091   { ".debug_static_func", display_debug_not_supported },
5092   { ".debug_static_vars", display_debug_not_supported },
5093   { ".debug_types",       display_debug_not_supported },
5094   { ".debug_weaknames",   display_debug_not_supported }
5095 };
5096
5097 static int
5098 display_debug_section (section, file)
5099      Elf32_Internal_Shdr * section;
5100      FILE * file;
5101 {
5102   char *          name = SECTION_NAME (section);
5103   bfd_size_type   length;
5104   unsigned char * start;
5105   int             i;
5106
5107   length = section->sh_size;
5108   if (length == 0)
5109     {
5110       printf (_("\nSection '%s' has no debugging data.\n"), name);
5111       return 0;
5112     }
5113
5114   GET_DATA_ALLOC (section->sh_offset, length, start, unsigned char *,
5115                   "debug section data");
5116
5117   /* See if we know how to display the contents of this section.  */
5118   for (i = NUM_ELEM (debug_displays); i--;)
5119     if (strcmp (debug_displays[i].name, name) == 0)
5120       {
5121         debug_displays[i].display (section, start, file);
5122         break;
5123       }
5124
5125   if (i == -1)
5126     printf (_("Unrecognised debug section: %s\n"), name);
5127
5128   free (start);
5129
5130   /* If we loaded in the abbrev section at some point,
5131      we must release it here.  */
5132   if (first_abbrev != NULL)
5133     free_abbrevs ();
5134
5135   return 1;
5136 }
5137
5138 static int
5139 process_section_contents (file)
5140      FILE * file;
5141 {
5142   Elf32_Internal_Shdr *    section;
5143   unsigned int  i;
5144
5145   if (! do_dump)
5146     return 1;
5147
5148   for (i = 0, section = section_headers;
5149        i < elf_header.e_shnum
5150        && i < num_dump_sects;
5151        i ++, section ++)
5152     {
5153 #ifdef SUPPORT_DISASSEMBLY
5154       if (dump_sects[i] & DISASS_DUMP)
5155         disassemble_section (section, file);
5156 #endif
5157       if (dump_sects[i] & HEX_DUMP)
5158         dump_section (section, file);
5159
5160       if (dump_sects[i] & DEBUG_DUMP)
5161         display_debug_section (section, file);
5162     }
5163
5164   if (i < num_dump_sects)
5165     warn (_("Some sections were not dumped because they do not exist!\n"));
5166
5167   return 1;
5168 }
5169
5170 static void
5171 process_mips_fpe_exception (mask)
5172      int mask;
5173 {
5174   if (mask)
5175     {
5176       int first = 1;
5177       if (mask & OEX_FPU_INEX)
5178         fputs ("INEX", stdout), first = 0;
5179       if (mask & OEX_FPU_UFLO)
5180         printf ("%sUFLO", first ? "" : "|"), first = 0;
5181       if (mask & OEX_FPU_OFLO)
5182         printf ("%sOFLO", first ? "" : "|"), first = 0;
5183       if (mask & OEX_FPU_DIV0)
5184         printf ("%sDIV0", first ? "" : "|"), first = 0;
5185       if (mask & OEX_FPU_INVAL)
5186         printf ("%sINVAL", first ? "" : "|");
5187     }
5188   else
5189     fputs ("0", stdout);
5190 }
5191
5192 static int
5193 process_mips_specific (file)
5194      FILE *file;
5195 {
5196   Elf_Internal_Dyn *entry;
5197   size_t liblist_offset = 0;
5198   size_t liblistno = 0;
5199   size_t conflictsno = 0;
5200   size_t options_offset = 0;
5201   size_t conflicts_offset = 0;
5202
5203   /* We have a lot of special sections.  Thanks SGI!  */
5204   if (dynamic_segment == NULL)
5205     /* No information available.  */
5206     return 0;
5207
5208   for (entry = dynamic_segment; entry->d_tag != DT_NULL; ++entry)
5209     switch (entry->d_tag)
5210       {
5211       case DT_MIPS_LIBLIST:
5212         liblist_offset = entry->d_un.d_val - loadaddr;
5213         break;
5214       case DT_MIPS_LIBLISTNO:
5215         liblistno = entry->d_un.d_val;
5216         break;
5217       case DT_MIPS_OPTIONS:
5218         options_offset = entry->d_un.d_val - loadaddr;
5219         break;
5220       case DT_MIPS_CONFLICT:
5221         conflicts_offset = entry->d_un.d_val - loadaddr;
5222         break;
5223       case DT_MIPS_CONFLICTNO:
5224         conflictsno = entry->d_un.d_val;
5225         break;
5226       default:
5227         break;
5228       }
5229
5230   if (liblist_offset != 0 && liblistno != 0 && do_dynamic)
5231     {
5232       Elf32_External_Lib *elib;
5233       size_t cnt;
5234
5235       GET_DATA_ALLOC (liblist_offset, liblistno * sizeof (Elf32_External_Lib),
5236                       elib, Elf32_External_Lib *, "liblist");
5237
5238       printf ("\nSection '.liblist' contains %d entries:\n", liblistno);
5239       fputs ("     Library              Time Stamp          Checksum   Version Flags\n",
5240              stdout);
5241
5242       for (cnt = 0; cnt < liblistno; ++cnt)
5243         {
5244           Elf32_Lib liblist;
5245           time_t time;
5246           char timebuf[20];
5247
5248           liblist.l_name = BYTE_GET (elib[cnt].l_name);
5249           time = BYTE_GET (elib[cnt].l_time_stamp);
5250           liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum);
5251           liblist.l_version = BYTE_GET (elib[cnt].l_version);
5252           liblist.l_flags = BYTE_GET (elib[cnt].l_flags);
5253
5254           strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time));
5255
5256           printf ("%3d: %-20s %s %#10lx %-7ld", cnt,
5257                   dynamic_strings + liblist.l_name, timebuf,
5258                   liblist.l_checksum, liblist.l_version);
5259
5260           if (liblist.l_flags == 0)
5261             puts (" NONE");
5262           else
5263             {
5264               static const struct
5265               {
5266                 const char *name;
5267                 int bit;
5268               } l_flags_vals[] =
5269                 {
5270                   { " EXACT_MATCH", LL_EXACT_MATCH },
5271                   { " IGNORE_INT_VER", LL_IGNORE_INT_VER },
5272                   { " REQUIRE_MINOR", LL_REQUIRE_MINOR },
5273                   { " EXPORTS", LL_EXPORTS },
5274                   { " DELAY_LOAD", LL_DELAY_LOAD },
5275                   { " DELTA", LL_DELTA }
5276                 };
5277               int flags = liblist.l_flags;
5278               int fcnt;
5279
5280               for (fcnt = 0;
5281                    fcnt < sizeof (l_flags_vals) / sizeof (l_flags_vals[0]);
5282                    ++fcnt)
5283                 if ((flags & l_flags_vals[fcnt].bit) != 0)
5284                   {
5285                     fputs (l_flags_vals[fcnt].name, stdout);
5286                     flags ^= l_flags_vals[fcnt].bit;
5287                   }
5288               if (flags != 0)
5289                 printf (" %#x", (unsigned int) flags);
5290
5291               puts ("");
5292             }
5293         }
5294
5295       free (elib);
5296     }
5297
5298   if (options_offset != 0)
5299     {
5300       Elf_External_Options *eopt;
5301       Elf_Internal_Shdr *sect = section_headers;
5302       Elf_Internal_Options *iopt;
5303       Elf_Internal_Options *option;
5304       size_t offset;
5305       int cnt;
5306
5307       /* Find the section header so that we get the size.  */
5308       while (sect->sh_type != SHT_MIPS_OPTIONS)
5309         ++sect;
5310
5311       GET_DATA_ALLOC (options_offset, sect->sh_size, eopt,
5312                       Elf_External_Options *, "options");
5313
5314       iopt = (Elf_Internal_Options *) malloc ((sect->sh_size / sizeof (eopt))
5315                                               * sizeof (*iopt));
5316       if (iopt == NULL)
5317         {
5318           error (_("Out of memory"));
5319           return 0;
5320         }
5321
5322       offset = cnt = 0;
5323       option = iopt;
5324       while (offset < sect->sh_size)
5325         {
5326           Elf_External_Options *eoption;
5327
5328           eoption = (Elf_External_Options *) ((char *) eopt + offset);
5329
5330           option->kind = BYTE_GET (eoption->kind);
5331           option->size = BYTE_GET (eoption->size);
5332           option->section = BYTE_GET (eoption->section);
5333           option->info = BYTE_GET (eoption->info);
5334
5335           offset += option->size;
5336           ++option;
5337           ++cnt;
5338         }
5339
5340       printf (_("\nSection '%s' contains %d entries:\n"),
5341               string_table + sect->sh_name, cnt);
5342
5343       option = iopt;
5344       while (cnt-- > 0)
5345         {
5346           size_t len;
5347
5348           switch (option->kind)
5349             {
5350             case ODK_NULL:
5351               /* This shouldn't happen.  */
5352               printf (" NULL       %d %lx", option->section, option->info);
5353               break;
5354             case ODK_REGINFO:
5355               printf (" REGINFO    ");
5356               if (elf_header.e_machine == EM_MIPS)
5357                 {
5358                   /* 32bit form.  */
5359                   Elf32_External_RegInfo *ereg;
5360                   Elf32_RegInfo reginfo;
5361
5362                   ereg = (Elf32_External_RegInfo *) (option + 1);
5363                   reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
5364                   reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
5365                   reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
5366                   reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
5367                   reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
5368                   reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
5369
5370                   printf ("GPR %08lx  GP 0x%lx\n",
5371                           reginfo.ri_gprmask,
5372                           (unsigned long) reginfo.ri_gp_value);
5373                   printf ("            CPR0 %08lx  CPR1 %08lx  CPR2 %08lx  CPR3 %08lx\n",
5374                           reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
5375                           reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
5376                 }
5377               else
5378                 {
5379                   /* 64 bit form.  */
5380                   Elf64_External_RegInfo *ereg;
5381                   Elf64_Internal_RegInfo reginfo;
5382
5383                   ereg = (Elf64_External_RegInfo *) (option + 1);
5384                   reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
5385                   reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
5386                   reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
5387                   reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
5388                   reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
5389                   reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
5390
5391                   printf ("GPR %08lx  GP 0x",
5392                           reginfo.ri_gprmask);
5393                   printf_vma (reginfo.ri_gp_value);
5394                   printf ("\n");
5395
5396                   printf ("            CPR0 %08lx  CPR1 %08lx  CPR2 %08lx  CPR3 %08lx\n",
5397                           reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
5398                           reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
5399                 }
5400               ++option;
5401               continue;
5402             case ODK_EXCEPTIONS:
5403               fputs (" EXCEPTIONS fpe_min(", stdout);
5404               process_mips_fpe_exception (option->info & OEX_FPU_MIN);
5405               fputs (") fpe_max(", stdout);
5406               process_mips_fpe_exception ((option->info & OEX_FPU_MAX) >> 8);
5407               fputs (")", stdout);
5408
5409               if (option->info & OEX_PAGE0)
5410                 fputs (" PAGE0", stdout);
5411               if (option->info & OEX_SMM)
5412                 fputs (" SMM", stdout);
5413               if (option->info & OEX_FPDBUG)
5414                 fputs (" FPDBUG", stdout);
5415               if (option->info & OEX_DISMISS)
5416                 fputs (" DISMISS", stdout);
5417               break;
5418             case ODK_PAD:
5419               fputs (" PAD       ", stdout);
5420               if (option->info & OPAD_PREFIX)
5421                 fputs (" PREFIX", stdout);
5422               if (option->info & OPAD_POSTFIX)
5423                 fputs (" POSTFIX", stdout);
5424               if (option->info & OPAD_SYMBOL)
5425                 fputs (" SYMBOL", stdout);
5426               break;
5427             case ODK_HWPATCH:
5428               fputs (" HWPATCH   ", stdout);
5429               if (option->info & OHW_R4KEOP)
5430                 fputs (" R4KEOP", stdout);
5431               if (option->info & OHW_R8KPFETCH)
5432                 fputs (" R8KPFETCH", stdout);
5433               if (option->info & OHW_R5KEOP)
5434                 fputs (" R5KEOP", stdout);
5435               if (option->info & OHW_R5KCVTL)
5436                 fputs (" R5KCVTL", stdout);
5437               break;
5438             case ODK_FILL:
5439               fputs (" FILL       ", stdout);
5440               /* XXX Print content of info word?  */
5441               break;
5442             case ODK_TAGS:
5443               fputs (" TAGS       ", stdout);
5444               /* XXX Print content of info word?  */
5445               break;
5446             case ODK_HWAND:
5447               fputs (" HWAND     ", stdout);
5448               if (option->info & OHWA0_R4KEOP_CHECKED)
5449                 fputs (" R4KEOP_CHECKED", stdout);
5450               if (option->info & OHWA0_R4KEOP_CLEAN)
5451                 fputs (" R4KEOP_CLEAN", stdout);
5452               break;
5453             case ODK_HWOR:
5454               fputs (" HWOR      ", stdout);
5455               if (option->info & OHWA0_R4KEOP_CHECKED)
5456                 fputs (" R4KEOP_CHECKED", stdout);
5457               if (option->info & OHWA0_R4KEOP_CLEAN)
5458                 fputs (" R4KEOP_CLEAN", stdout);
5459               break;
5460             case ODK_GP_GROUP:
5461               printf (" GP_GROUP  %#06lx  self-contained %#06lx",
5462                       option->info & OGP_GROUP,
5463                       (option->info & OGP_SELF) >> 16);
5464               break;
5465             case ODK_IDENT:
5466               printf (" IDENT     %#06lx  self-contained %#06lx",
5467                       option->info & OGP_GROUP,
5468                       (option->info & OGP_SELF) >> 16);
5469               break;
5470             default:
5471               /* This shouldn't happen.  */
5472               printf (" %3d ???     %d %lx",
5473                       option->kind, option->section, option->info);
5474               break;
5475             }
5476
5477           len = sizeof (*eopt);
5478           while (len < option->size)
5479             if (((char *) option)[len] >= ' '
5480                 && ((char *) option)[len] < 0x7f)
5481               printf ("%c", ((char *) option)[len++]);
5482             else
5483               printf ("\\%03o", ((char *) option)[len++]);
5484
5485           fputs ("\n", stdout);
5486           ++option;
5487         }
5488
5489       free (eopt);
5490     }
5491
5492   if (conflicts_offset != 0 && conflictsno != 0)
5493     {
5494       Elf32_External_Conflict *econf32;
5495       Elf64_External_Conflict *econf64;
5496       Elf32_Conflict *iconf;
5497       size_t cnt;
5498
5499       if (dynamic_symbols == NULL)
5500         {
5501           error (_("conflict list with without table"));
5502           return 0;
5503         }
5504
5505       iconf = (Elf32_Conflict *) malloc (conflictsno * sizeof (*iconf));
5506       if (iconf == NULL)
5507         {
5508           error (_("Out of memory"));
5509           return 0;
5510         }
5511
5512       if (binary_class == ELFCLASS32)
5513         {
5514           GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (*econf32),
5515                           econf32, Elf32_External_Conflict *, "conflict");
5516
5517           for (cnt = 0; cnt < conflictsno; ++cnt)
5518             iconf[cnt] = BYTE_GET (econf32[cnt]);
5519         }
5520       else
5521         {
5522           GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (*econf64),
5523                           econf64, Elf64_External_Conflict *, "conflict");
5524
5525           for (cnt = 0; cnt < conflictsno; ++cnt)
5526             iconf[cnt] = BYTE_GET (econf64[cnt]);
5527         }
5528
5529       printf (_("\nSection '.conflict' contains %d entries:\n"), conflictsno);
5530       puts (_("  Num:    Index       Value  Name"));
5531
5532       for (cnt = 0; cnt < conflictsno; ++cnt)
5533         {
5534           Elf_Internal_Sym *psym = &dynamic_symbols[iconf[cnt]];
5535
5536           printf ("%5u: %8lu  %#10lx  %s\n",
5537                   cnt, iconf[cnt], (unsigned long) psym->st_value,
5538                   dynamic_strings + psym->st_name);
5539         }
5540
5541
5542       free (iconf);
5543     }
5544
5545   return 1;
5546 }
5547
5548 static int
5549 process_arch_specific (file)
5550      FILE *file;
5551 {
5552   switch (elf_header.e_machine)
5553     {
5554     case EM_MIPS:
5555     case EM_MIPS_RS4_BE:
5556       return process_mips_specific (file);
5557       break;
5558     default:
5559       break;
5560     }
5561   return 1;
5562 }
5563
5564 static int
5565 get_file_header (file)
5566      FILE * file;
5567 {
5568   Elf32_External_Ehdr ehdr;
5569
5570   if (fread (& ehdr, sizeof (ehdr), 1, file) != 1)
5571     return 0;
5572
5573   memcpy (elf_header.e_ident, ehdr.e_ident, EI_NIDENT);
5574
5575   if (elf_header.e_ident [EI_DATA] == ELFDATA2LSB)
5576     byte_get = byte_get_little_endian;
5577   else
5578     byte_get = byte_get_big_endian;
5579
5580   elf_header.e_entry     = BYTE_GET (ehdr.e_entry);
5581   elf_header.e_phoff     = BYTE_GET (ehdr.e_phoff);
5582   elf_header.e_shoff     = BYTE_GET (ehdr.e_shoff);
5583   elf_header.e_version   = BYTE_GET (ehdr.e_version);
5584   elf_header.e_flags     = BYTE_GET (ehdr.e_flags);
5585   elf_header.e_type      = BYTE_GET (ehdr.e_type);
5586   elf_header.e_machine   = BYTE_GET (ehdr.e_machine);
5587   elf_header.e_ehsize    = BYTE_GET (ehdr.e_ehsize);
5588   elf_header.e_phentsize = BYTE_GET (ehdr.e_phentsize);
5589   elf_header.e_phnum     = BYTE_GET (ehdr.e_phnum);
5590   elf_header.e_shentsize = BYTE_GET (ehdr.e_shentsize);
5591   elf_header.e_shnum     = BYTE_GET (ehdr.e_shnum);
5592   elf_header.e_shstrndx  = BYTE_GET (ehdr.e_shstrndx);
5593
5594   return 1;
5595 }
5596
5597 static void
5598 process_file (file_name)
5599      char * file_name;
5600 {
5601   FILE *       file;
5602   struct stat  statbuf;
5603   unsigned int i;
5604
5605   if (stat (file_name, & statbuf) < 0)
5606     {
5607       error (_("Cannot stat input file %s.\n"), file_name);
5608       return;
5609     }
5610
5611   file = fopen (file_name, "rb");
5612   if (file == NULL)
5613     {
5614       error (_("Input file %s not found.\n"), file_name);
5615       return;
5616     }
5617
5618   if (! get_file_header (file))
5619     {
5620       error (_("%s: Failed to read file header\n"), file_name);
5621       fclose (file);
5622       return;
5623     }
5624
5625   /* Initialise per file variables.  */
5626   for (i = NUM_ELEM (version_info); i--;)
5627     version_info[i] = 0;
5628
5629   for (i = NUM_ELEM (dynamic_info); i--;)
5630     dynamic_info[i] = 0;
5631
5632   /* Process the file.  */
5633   if (show_name)
5634     printf (_("\nFile: %s\n"), file_name);
5635
5636   if (! process_file_header ())
5637     {
5638       fclose (file);
5639       return;
5640     }
5641
5642   process_section_headers (file);
5643
5644   process_program_headers (file);
5645
5646   process_dynamic_segment (file);
5647
5648   process_relocs (file);
5649
5650   process_symbol_table (file);
5651
5652   process_syminfo (file);
5653
5654   process_version_sections (file);
5655
5656   process_section_contents (file);
5657
5658   process_arch_specific (file);
5659
5660   fclose (file);
5661
5662   if (section_headers)
5663     {
5664       free (section_headers);
5665       section_headers = NULL;
5666     }
5667
5668   if (string_table)
5669     {
5670       free (string_table);
5671       string_table = NULL;
5672     }
5673
5674   if (dynamic_strings)
5675     {
5676       free (dynamic_strings);
5677       dynamic_strings = NULL;
5678     }
5679
5680   if (dynamic_symbols)
5681     {
5682       free (dynamic_symbols);
5683       dynamic_symbols = NULL;
5684     }
5685
5686   if (dynamic_syminfo)
5687     {
5688       free (dynamic_syminfo);
5689       dynamic_syminfo = NULL;
5690     }
5691 }
5692
5693 #ifdef SUPPORT_DISASSEMBLY
5694 /* Needed by the i386 disassembler.  For extra credit, someone could
5695 fix this so that we insert symbolic addresses here, esp for GOT/PLT
5696 symbols */
5697
5698 void
5699 print_address (unsigned int addr, FILE * outfile)
5700 {
5701   fprintf (outfile,"0x%8.8x", addr);
5702 }
5703
5704 /* Needed by the i386 disassembler. */
5705 void
5706 db_task_printsym (unsigned int addr)
5707 {
5708   print_address (addr, stderr);
5709 }
5710 #endif
5711
5712 int
5713 main (argc, argv)
5714      int     argc;
5715      char ** argv;
5716 {
5717 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
5718   setlocale (LC_MESSAGES, "");
5719 #endif
5720   bindtextdomain (PACKAGE, LOCALEDIR);
5721   textdomain (PACKAGE);
5722
5723   parse_args (argc, argv);
5724
5725   if (optind < (argc - 1))
5726     show_name = 1;
5727
5728   while (optind < argc)
5729     process_file (argv [optind ++]);
5730
5731   if (dump_sects != NULL)
5732     free (dump_sects);
5733
5734   return 0;
5735 }