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