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