OSDN Git Service

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