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