Mon Nov 9 12:00:36 1998 Dave Brolley <brolley@cygnus.com>
[deliverable/binutils-gdb.git] / binutils / readelf.c
CommitLineData
76466873
NC
1/* readelf.c -- display contents of an ELF format file
2 Copyright (C) 1998 Free Software Foundation, Inc.
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"
35
f97d05dc
NC
36/* The following headers use the elf/reloc-macros.h file to
37 automatically generate relocation recognition functions
38 such as elf_mips_reloc_type() */
39
40#define RELOC_MACROS_GEN_FUNC
41
42#include "elf/i386.h"
43#include "elf/v850.h"
44#include "elf/ppc.h"
45#include "elf/mips.h"
46#include "elf/alpha.h"
47#include "elf/arm.h"
48#include "elf/m68k.h"
49#include "elf/sparc.h"
50#include "elf/m32r.h"
51#include "elf/d10v.h"
f97d05dc 52#include "elf/d30v.h"
f97d05dc
NC
53#include "elf/sh.h"
54#include "elf/mn10200.h"
55#include "elf/mn10300.h"
56#include "elf/hppa.h"
57#include "elf/arc.h"
58
ebb64169 59#include "bucomm.h"
c18f8aef 60#include "getopt.h"
76466873
NC
61
62#ifdef ANSI_PROTOTYPES
63#include <stdarg.h>
64#else
65#include <varargs.h>
66#endif
67
cb436f39
NC
68char * program_name = "readelf";
69unsigned int dynamic_addr;
70unsigned int dynamic_size;
71unsigned int rela_addr;
72unsigned int rela_size;
73char * dynamic_strings;
74char * string_table;
75Elf_Internal_Sym * dynamic_symbols;
fdf959dd
UD
76Elf_Internal_Syminfo * dynamic_syminfo;
77unsigned long int dynamic_syminfo_offset;
78unsigned int dynamic_syminfo_nent;
cb436f39 79char program_interpreter [64];
be5b92f9
CM
80int dynamic_info[DT_JMPREL + 1];
81int version_info[16];
cb436f39 82int loadaddr = 0;
6c4b8d0f
UD
83Elf_Internal_Ehdr elf_header;
84Elf_Internal_Shdr * section_headers;
85Elf_Internal_Dyn * dynamic_segment;
cb436f39
NC
86int show_name;
87int do_dynamic;
88int do_syms;
89int do_reloc;
90int do_sections;
91int do_segments;
92int do_using_dynamic;
93int do_header;
94int do_dump;
95int do_version;
e5a32b17 96int do_histogram;
cb436f39 97
d76c93e6 98static unsigned long int (* byte_get) PARAMS ((unsigned char *, int));
76466873
NC
99
100#define NUM_DUMP_SECTS 100
cb436f39
NC
101char dump_sects [NUM_DUMP_SECTS];
102
76466873
NC
103#define HEX_DUMP 1
104#define DISASS_DUMP 2
105
106/* Forward declarations for dumb compilers. */
5821de31
UD
107static const char * get_mips_dynamic_type PARAMS ((unsigned long type));
108static const char * get_dynamic_type PARAMS ((unsigned long type));
cb436f39
NC
109static int dump_relocations
110 PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, char *));
ebb64169
NC
111static char * get_file_type PARAMS ((unsigned e_type));
112static char * get_machine_name PARAMS ((unsigned e_machine));
113static char * get_machine_data PARAMS ((unsigned e_data));
114static char * get_machine_flags PARAMS ((unsigned, unsigned e_machine));
5821de31
UD
115static const char * get_mips_segment_type PARAMS ((unsigned long type));
116static const char * get_segment_type PARAMS ((unsigned long p_type));
5892b099
UD
117static const char * get_mips_section_type_name PARAMS ((unsigned int sh_type));
118static const char * get_section_type_name PARAMS ((unsigned int sh_type));
ebb64169
NC
119static char * get_symbol_binding PARAMS ((unsigned int binding));
120static char * get_symbol_type PARAMS ((unsigned int type));
76466873
NC
121static void usage PARAMS ((void));
122static void parse_args PARAMS ((int argc, char ** argv));
ebb64169 123static int process_file_header PARAMS ((void));
cb436f39
NC
124static int process_program_headers PARAMS ((FILE *));
125static int process_section_headers PARAMS ((FILE *));
5821de31 126static void dynamic_segment_mips_val PARAMS ((Elf_Internal_Dyn *entry));
cb436f39
NC
127static int process_dynamic_segment PARAMS ((FILE *));
128static int process_symbol_table PARAMS ((FILE *));
129static int process_section_contents PARAMS ((FILE *));
76466873 130static void process_file PARAMS ((char * file_name));
cb436f39
NC
131static int process_relocs PARAMS ((FILE *));
132static int process_version_sections PARAMS ((FILE *));
19808d3f
UD
133static char * get_ver_flags PARAMS ((unsigned int flags));
134static char * get_symbol_index_type PARAMS ((unsigned int type));
cb436f39
NC
135static int get_section_headers PARAMS ((FILE * file));
136static int get_file_header PARAMS ((FILE * file));
137static Elf_Internal_Sym * get_elf_symbols
138 PARAMS ((FILE * file, unsigned long offset, unsigned long number));
139static int * get_dynamic_data PARAMS ((FILE * file, unsigned int number));
140
6c4b8d0f
UD
141typedef int Elf32_Word;
142
cb436f39
NC
143#define SECTION_NAME(X) (string_table + (X)->sh_name)
144
145#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
146
147#define BYTE_GET(field) byte_get (field, sizeof (field))
148
149#define NUM_ELEM(array) (sizeof (array) / sizeof ((array)[0]))
76466873 150
ebb64169
NC
151#define GET_DATA_ALLOC(offset, size, var, type, reason) \
152 if (fseek (file, offset, SEEK_SET)) \
153 { \
154 error (_("Unable to seek to start of %s at %x\n"), reason, offset); \
cb436f39 155 return 0; \
ebb64169
NC
156 } \
157 \
158 var = (type) malloc (size); \
159 \
160 if (var == NULL) \
161 { \
162 error (_("Out of memory allocating %d bytes for %s\n"), size, reason); \
cb436f39 163 return 0; \
ebb64169
NC
164 } \
165 \
166 if (fread (var, size, 1, file) != 1) \
167 { \
168 error (_("Unable to read in %d bytes of %s\n"), size, reason); \
169 free (var); \
170 var = NULL; \
cb436f39 171 return 0; \
19808d3f
UD
172 }
173
ebb64169
NC
174
175#define GET_DATA(offset, var, reason) \
176 if (fseek (file, offset, SEEK_SET)) \
177 { \
178 error (_("Unable to seek to %x for %s\n"), offset, reason); \
cb436f39 179 return 0; \
ebb64169
NC
180 } \
181 else if (fread (& var, sizeof (var), 1, file) != 1) \
182 { \
183 error (_("Unable to read data at %x for %s\n"), offset, reason); \
cb436f39 184 return 0; \
ebb64169 185 }
76466873
NC
186
187#ifdef ANSI_PROTOTYPES
188static void
189error (const char * message, ...)
190{
191 va_list args;
192
193 fprintf (stderr, _("%s: Error: "), program_name);
194 va_start (args, message);
195 vfprintf (stderr, message, args);
196 va_end (args);
197 return;
198}
19808d3f 199
76466873
NC
200static void
201warn (const char * message, ...)
202{
203 va_list args;
204
205 fprintf (stderr, _("%s: Warning: "), program_name);
206 va_start (args, message);
207 vfprintf (stderr, message, args);
208 va_end (args);
209 return;
210}
211#else
212static void
213error (va_alist)
d76c93e6 214 va_dcl
76466873
NC
215{
216 char * message;
217 va_list args;
218
219 fprintf (stderr, _("%s: Error: "), program_name);
220 va_start (args);
221 message = va_arg (args, char *);
222 vfprintf (stderr, message, args);
223 va_end (args);
224 return;
225}
226
227static void
228warn (va_alist)
d76c93e6 229 va_dcl
76466873
NC
230{
231 char * message;
232 va_list args;
233
234 fprintf (stderr, _("%s: Warning: "), program_name);
235 va_start (args);
236 message = va_arg (args, char *);
237 vfprintf (stderr, message, args);
238 va_end (args);
239 return;
240}
241#endif
242
cb436f39
NC
243static unsigned long int
244byte_get_little_endian (field, size)
245 unsigned char * field;
246 int size;
247{
248 switch (size)
249 {
250 case 1:
251 return * field;
252
253 case 2:
254 return ((unsigned int) (field [0]))
255 | (((unsigned int) (field [1])) << 8);
256
257 case 4:
258 return ((unsigned long) (field [0]))
259 | (((unsigned long) (field [1])) << 8)
260 | (((unsigned long) (field [2])) << 16)
261 | (((unsigned long) (field [3])) << 24);
262
263 default:
264 error (_("Unhandled data length: %d\n"), size);
265 abort();
266 }
267}
268
269static unsigned long int
270byte_get_big_endian (field, size)
271 unsigned char * field;
272 int size;
273{
274 switch (size)
275 {
276 case 1:
277 return * field;
278
279 case 2:
280 return ((unsigned int) (field [1])) | (((int) (field [0])) << 8);
281
282 case 4:
283 return ((unsigned long) (field [3]))
284 | (((unsigned long) (field [2])) << 8)
285 | (((unsigned long) (field [1])) << 16)
286 | (((unsigned long) (field [0])) << 24);
287
288 default:
289 error (_("Unhandled data length: %d\n"), size);
290 abort();
291 }
292}
76466873 293
133a451e 294
ebb64169
NC
295/* Display the contents of the relocation data
296 found at the specified offset. */
cb436f39 297static int
ebb64169 298dump_relocations (file, rel_offset, rel_size, symtab, strtab)
cb436f39
NC
299 FILE * file;
300 unsigned long rel_offset;
301 unsigned long rel_size;
302 Elf_Internal_Sym * symtab;
303 char * strtab;
76466873 304{
cb436f39
NC
305 unsigned int i;
306 int is_rela;
307 Elf_Internal_Rel * rels;
308 Elf_Internal_Rela * relas;
76466873 309
19808d3f 310
ebb64169
NC
311 /* Compute number of relocations and read them in. */
312 switch (elf_header.e_machine)
76466873
NC
313 {
314 case EM_386:
315 case EM_486:
316 case EM_CYGNUS_M32R:
317 case EM_CYGNUS_D10V:
5892b099
UD
318 case EM_MIPS:
319 case EM_MIPS_RS4_BE:
cb436f39
NC
320 {
321 Elf32_External_Rel * erels;
19808d3f 322
cb436f39
NC
323 GET_DATA_ALLOC (rel_offset, rel_size, erels,
324 Elf32_External_Rel *, "relocs");
19808d3f 325
cb436f39
NC
326 rel_size = rel_size / sizeof (Elf32_External_Rel);
327
328 rels = (Elf_Internal_Rel *) malloc (rel_size *
329 sizeof (Elf_Internal_Rel));
19808d3f 330
cb436f39
NC
331 for (i = 0; i < rel_size; i++)
332 {
333 rels[i].r_offset = BYTE_GET (erels[i].r_offset);
334 rels[i].r_info = BYTE_GET (erels[i].r_info);
335 }
76466873 336
cb436f39 337 free (erels);
19808d3f 338
cb436f39
NC
339 is_rela = 0;
340 relas = (Elf_Internal_Rela *) rels;
341 }
342 break;
19808d3f 343
be5b92f9 344 case EM_ARM:
76466873
NC
345 case EM_68K:
346 case EM_SPARC:
a09db9ba 347 case EM_PPC:
76466873
NC
348 case EM_CYGNUS_V850:
349 case EM_CYGNUS_D30V:
350 case EM_CYGNUS_MN10200:
351 case EM_CYGNUS_MN10300:
352 case EM_SH:
5892b099 353 case EM_ALPHA:
cb436f39
NC
354 {
355 Elf32_External_Rela * erelas;
19808d3f 356
cb436f39
NC
357 GET_DATA_ALLOC (rel_offset, rel_size, erelas,
358 Elf32_External_Rela *, "relocs");
19808d3f 359
cb436f39
NC
360 rel_size = rel_size / sizeof (Elf32_External_Rela);
361
362 relas = (Elf_Internal_Rela *) malloc (rel_size *
363 sizeof (Elf_Internal_Rela));
19808d3f 364
cb436f39
NC
365 for (i = 0; i < rel_size; i++)
366 {
367 relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
368 relas[i].r_info = BYTE_GET (erelas[i].r_info);
369 relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
370 }
371
372 free (erelas);
19808d3f 373
cb436f39
NC
374 is_rela = 1;
375 rels = (Elf_Internal_Rel *) relas;
376 }
377 break;
19808d3f 378
76466873
NC
379 default:
380 warn (_("Don't know about relocations on this machine architecture\n"));
cb436f39 381 return 0;
76466873
NC
382 }
383
384 if (is_rela)
ebb64169 385 printf
5892b099 386 (_(" Offset Value Type Symbol's Value Symbol's Name Addend\n"));
76466873 387 else
ebb64169
NC
388 printf
389 (_(" Offset Value Type Symbol's Value Symbol's Name\n"));
19808d3f 390
76466873
NC
391 for (i = 0; i < rel_size; i++)
392 {
5892b099 393 const char * rtype;
cb436f39
NC
394 unsigned long offset;
395 unsigned long info;
396 int symtab_index;
ebb64169 397
76466873 398 if (is_rela)
ebb64169
NC
399 {
400 offset = relas [i].r_offset;
401 info = relas [i].r_info;
402 }
403 else
404 {
405 offset = rels [i].r_offset;
406 info = rels [i].r_info;
407 }
19808d3f 408
ebb64169 409 printf (" %8.8lx %5.5lx ", offset, info);
19808d3f 410
ebb64169 411 switch (elf_header.e_machine)
76466873 412 {
c18f8aef 413 default:
e293b096 414 rtype = NULL;
c18f8aef 415 break;
19808d3f 416
76466873 417 case EM_CYGNUS_M32R:
133a451e 418 rtype = elf_m32r_reloc_type (ELF32_R_TYPE (info));
76466873 419 break;
19808d3f 420
76466873
NC
421 case EM_386:
422 case EM_486:
133a451e 423 rtype = elf_i386_reloc_type (ELF32_R_TYPE (info));
76466873 424 break;
19808d3f 425
76466873 426 case EM_68K:
133a451e 427 rtype = elf_m68k_reloc_type (ELF32_R_TYPE (info));
76466873 428 break;
19808d3f 429
76466873 430 case EM_SPARC:
133a451e 431 rtype = elf_sparc_reloc_type (ELF32_R_TYPE (info));
76466873 432 break;
19808d3f 433
76466873 434 case EM_CYGNUS_V850:
f97d05dc 435 rtype = v850_reloc_type (ELF32_R_TYPE (info));
76466873 436 break;
19808d3f 437
76466873 438 case EM_CYGNUS_D10V:
133a451e 439 rtype = elf_d10v_reloc_type (ELF32_R_TYPE (info));
76466873 440 break;
19808d3f 441
76466873 442 case EM_CYGNUS_D30V:
133a451e 443 rtype = elf_d30v_reloc_type (ELF32_R_TYPE (info));
76466873 444 break;
19808d3f 445
76466873 446 case EM_SH:
133a451e 447 rtype = elf_sh_reloc_type (ELF32_R_TYPE (info));
76466873 448 break;
19808d3f 449
76466873 450 case EM_CYGNUS_MN10300:
133a451e 451 rtype = elf_mn10300_reloc_type (ELF32_R_TYPE (info));
76466873 452 break;
19808d3f 453
76466873 454 case EM_CYGNUS_MN10200:
133a451e 455 rtype = elf_mn10200_reloc_type (ELF32_R_TYPE (info));
76466873 456 break;
a09db9ba
MM
457
458 case EM_PPC:
3b9f0cb6 459 rtype = elf_ppc_reloc_type (ELF32_R_TYPE (info));
a09db9ba 460 break;
5892b099
UD
461
462 case EM_MIPS:
463 case EM_MIPS_RS4_BE:
133a451e 464 rtype = elf_mips_reloc_type (ELF32_R_TYPE (info));
5892b099
UD
465 break;
466
467 case EM_ALPHA:
133a451e 468 rtype = elf_alpha_reloc_type (ELF32_R_TYPE (info));
5892b099
UD
469 break;
470
471 case EM_ARM:
133a451e 472 rtype = elf_arm_reloc_type (ELF32_R_TYPE (info));
5892b099 473 break;
3b9f0cb6 474
f97d05dc
NC
475 case EM_CYGNUS_ARC:
476 rtype = elf_arc_reloc_type (ELF32_R_TYPE (info));
477 break;
3b9f0cb6 478
f97d05dc
NC
479 case EM_PARISC:
480 rtype = elf32_hppa_reloc_type (ELF32_R_TYPE (info));
481 break;
76466873 482 }
19808d3f 483
e293b096 484 if (rtype == NULL)
f5d660b6 485 printf (_("unrecognised: %-7x"), ELF32_R_TYPE (info));
e293b096
NC
486 else
487 printf ("%-21.21s", rtype);
19808d3f 488
ebb64169 489 symtab_index = ELF32_R_SYM (info);
19808d3f 490
ebb64169 491 if (symtab_index && symtab != NULL)
76466873 492 {
cb436f39 493 Elf_Internal_Sym * psym;
ebb64169 494
76466873 495 psym = symtab + symtab_index;
19808d3f 496
cb436f39 497 printf (" %08lx ", (unsigned long) psym->st_value);
19808d3f 498
76466873 499 if (psym->st_name == 0)
5892b099 500 printf ("%-25.25s",
ebb64169
NC
501 SECTION_NAME (section_headers + psym->st_shndx));
502 else if (strtab == NULL)
5892b099 503 printf (_("<string table index %3d>"), psym->st_name);
76466873 504 else
5892b099 505 printf ("%-25.25s", strtab + psym->st_name);
19808d3f 506
76466873 507 if (is_rela)
cb436f39 508 printf (" + %lx", (unsigned long) relas [i].r_addend);
76466873 509 }
19808d3f 510
76466873 511 putchar ('\n');
76466873
NC
512 }
513
ebb64169 514 free (relas);
cb436f39
NC
515
516 return 1;
ebb64169
NC
517}
518
5821de31
UD
519static const char *
520get_mips_dynamic_type (type)
521 unsigned long type;
522{
523 switch (type)
524 {
525 case DT_MIPS_RLD_VERSION: return "MIPS_RLD_VERSION";
526 case DT_MIPS_TIME_STAMP: return "MIPS_TIME_STAMP";
527 case DT_MIPS_ICHECKSUM: return "MIPS_ICHECKSUM";
528 case DT_MIPS_IVERSION: return "MIPS_IVERSION";
529 case DT_MIPS_FLAGS: return "MIPS_FLAGS";
530 case DT_MIPS_BASE_ADDRESS: return "MIPS_BASE_ADDRESS";
531 case DT_MIPS_MSYM: return "MIPS_MSYM";
532 case DT_MIPS_CONFLICT: return "MIPS_CONFLICT";
533 case DT_MIPS_LIBLIST: return "MIPS_LIBLIST";
534 case DT_MIPS_LOCAL_GOTNO: return "MIPS_LOCAL_GOTNO";
535 case DT_MIPS_CONFLICTNO: return "MIPS_CONFLICTNO";
536 case DT_MIPS_LIBLISTNO: return "MIPS_LIBLISTNO";
537 case DT_MIPS_SYMTABNO: return "MIPS_SYMTABNO";
538 case DT_MIPS_UNREFEXTNO: return "MIPS_UNREFEXTNO";
539 case DT_MIPS_GOTSYM: return "MIPS_GOTSYM";
540 case DT_MIPS_HIPAGENO: return "MIPS_HIPAGENO";
541 case DT_MIPS_RLD_MAP: return "MIPS_RLD_MAP";
542 case DT_MIPS_DELTA_CLASS: return "MIPS_DELTA_CLASS";
543 case DT_MIPS_DELTA_CLASS_NO: return "MIPS_DELTA_CLASS_NO";
544 case DT_MIPS_DELTA_INSTANCE: return "MIPS_DELTA_INSTANCE";
545 case DT_MIPS_DELTA_INSTANCE_NO: return "MIPS_DELTA_INSTANCE_NO";
546 case DT_MIPS_DELTA_RELOC: return "MIPS_DELTA_RELOC";
547 case DT_MIPS_DELTA_RELOC_NO: return "MIPS_DELTA_RELOC_NO";
548 case DT_MIPS_DELTA_SYM: return "MIPS_DELTA_SYM";
549 case DT_MIPS_DELTA_SYM_NO: return "MIPS_DELTA_SYM_NO";
550 case DT_MIPS_DELTA_CLASSSYM: return "MIPS_DELTA_CLASSSYM";
551 case DT_MIPS_DELTA_CLASSSYM_NO: return "MIPS_DELTA_CLASSSYM_NO";
552 case DT_MIPS_CXX_FLAGS: return "MIPS_CXX_FLAGS";
553 case DT_MIPS_PIXIE_INIT: return "MIPS_PIXIE_INIT";
554 case DT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB";
555 case DT_MIPS_LOCALPAGE_GOTIDX: return "MIPS_LOCALPAGE_GOTIDX";
556 case DT_MIPS_LOCAL_GOTIDX: return "MIPS_LOCAL_GOTIDX";
557 case DT_MIPS_HIDDEN_GOTIDX: return "MIPS_HIDDEN_GOTIDX";
558 case DT_MIPS_PROTECTED_GOTIDX: return "MIPS_PROTECTED_GOTIDX";
559 case DT_MIPS_OPTIONS: return "MIPS_OPTIONS";
560 case DT_MIPS_INTERFACE: return "MIPS_INTERFACE";
561 case DT_MIPS_DYNSTR_ALIGN: return "MIPS_DYNSTR_ALIGN";
562 case DT_MIPS_INTERFACE_SIZE: return "MIPS_INTERFACE_SIZE";
563 case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: return "MIPS_RLD_TEXT_RESOLVE_ADDR";
564 case DT_MIPS_PERF_SUFFIX: return "MIPS_PERF_SUFFIX";
565 case DT_MIPS_COMPACT_SIZE: return "MIPS_COMPACT_SIZE";
566 case DT_MIPS_GP_VALUE: return "MIPS_GP_VALUE";
567 case DT_MIPS_AUX_DYNAMIC: return "MIPS_AUX_DYNAMIC";
568 default:
569 return NULL;
570 }
571}
572
573static const char *
ebb64169
NC
574get_dynamic_type (type)
575 unsigned long type;
576{
577 static char buff [32];
19808d3f 578
ebb64169
NC
579 switch (type)
580 {
be5b92f9
CM
581 case DT_NULL: return "NULL";
582 case DT_NEEDED: return "NEEDED";
583 case DT_PLTRELSZ: return "PLTRELSZ";
584 case DT_PLTGOT: return "PLTGOT";
585 case DT_HASH: return "HASH";
586 case DT_STRTAB: return "STRTAB";
587 case DT_SYMTAB: return "SYMTAB";
588 case DT_RELA: return "RELA";
589 case DT_RELASZ: return "RELASZ";
590 case DT_RELAENT: return "RELAENT";
591 case DT_STRSZ: return "STRSZ";
592 case DT_SYMENT: return "SYMENT";
593 case DT_INIT: return "INIT";
594 case DT_FINI: return "FINI";
595 case DT_SONAME: return "SONAME";
596 case DT_RPATH: return "RPATH";
597 case DT_SYMBOLIC: return "SYMBOLIC";
598 case DT_REL: return "REL";
599 case DT_RELSZ: return "RELSZ";
600 case DT_RELENT: return "RELENT";
601 case DT_PLTREL: return "PLTREL";
602 case DT_DEBUG: return "DEBUG";
603 case DT_TEXTREL: return "TEXTREL";
604 case DT_JMPREL: return "JMPREL";
605 case DT_VERDEF: return "VERDEF";
606 case DT_VERDEFNUM: return "VERDEFNUM";
607 case DT_VERNEED: return "VERNEED";
608 case DT_VERNEEDNUM: return "VERNEEDNUM";
609 case DT_VERSYM: return "VERSYN";
610 case DT_AUXILIARY: return "AUXILARY";
611 case DT_FILTER: return "FILTER";
612 case DT_POSFLAG_1: return "POSFLAG_1";
613 case DT_SYMINSZ: return "SYMINSZ";
614 case DT_SYMINENT: return "SYMINENT";
615 case DT_SYMINFO: return "SYMINFO";
616 case DT_RELACOUNT: return "RELACOUNT";
617 case DT_RELCOUNT: return "RELCOUNT";
618 case DT_FLAGS_1: return "FLAGS_1";
619 case DT_USED: return "USED";
19808d3f 620
ebb64169
NC
621 default:
622 if ((type >= DT_LOPROC) && (type <= DT_HIPROC))
5821de31
UD
623 {
624 const char *result = NULL;
625 switch (elf_header.e_machine)
626 {
627 case EM_MIPS:
628 case EM_MIPS_RS4_BE:
629 result = get_mips_dynamic_type (type);
5821de31
UD
630 }
631
632 if (result == NULL)
633 {
be5b92f9 634 sprintf (buff, _("Processor Specific"), type);
5821de31
UD
635 result = buff;
636 }
637 return result;
638 }
ebb64169
NC
639 else
640 sprintf (buff, _("<unknown>: %x"), type);
641 return buff;
642 }
76466873
NC
643}
644
645static char *
646get_file_type (e_type)
a09db9ba 647 unsigned e_type;
76466873
NC
648{
649 static char buff [32];
19808d3f 650
76466873
NC
651 switch (e_type)
652 {
5892b099
UD
653 case ET_NONE: return _("NONE (None)");
654 case ET_REL: return _("REL (Relocatable file)");
655 case ET_EXEC: return _("EXEC (Executable file)");
656 case ET_DYN: return _("DYN (Shared object file)");
657 case ET_CORE: return _("CORE (Core file)");
19808d3f 658
76466873
NC
659 default:
660 if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC))
661 sprintf (buff, _("Processor Specific: (%x)"), e_type);
662 else
663 sprintf (buff, _("<unknown>: %x"), e_type);
664 return buff;
665 }
666}
667
668static char *
669get_machine_name (e_machine)
a09db9ba 670 unsigned e_machine;
76466873
NC
671{
672 static char buff [32];
19808d3f 673
76466873
NC
674 switch (e_machine)
675 {
676 case EM_NONE: return _("None");
677 case EM_M32: return "WE32100";
678 case EM_SPARC: return "Sparc";
5892b099 679 case EM_386: return "Intel 80386";
76466873
NC
680 case EM_68K: return "MC68000";
681 case EM_88K: return "MC88000";
682 case EM_486: return "Intel 80486";
683 case EM_860: return "Intel 80860";
684 case EM_MIPS: return "MIPS R3000 big-endian";
685 case EM_S370: return "Amdahl";
5892b099 686 case EM_MIPS_RS4_BE: return "MIPS R4000 big-endian";
ebb64169 687 case EM_OLD_SPARCV9: return "Sparc v9 (old)";
76466873 688 case EM_PARISC: return "HPPA";
19808d3f 689 case EM_PPC_OLD: return "Power PC (old)";
76466873 690 case EM_SPARC32PLUS: return "Sparc v8+" ;
ebb64169 691 case EM_960: return "Intel 90860";
a09db9ba 692 case EM_PPC: return "PowerPC";
ebb64169
NC
693 case EM_V800: return "NEC V800";
694 case EM_FR20: return "Fujitsu FR20";
695 case EM_RH32: return "TRW RH32";
696 case EM_MMA: return "Fujitsu MMA";
76466873 697 case EM_ARM: return "ARM";
ebb64169 698 case EM_OLD_ALPHA: return "Digital Alpha (old)";
76466873 699 case EM_SH: return "Hitachi SH";
ebb64169 700 case EM_SPARCV9: return "Sparc v9";
76466873
NC
701 case EM_ALPHA: return "Alpha";
702 case EM_CYGNUS_D10V: return "d10v";
703 case EM_CYGNUS_D30V: return "d30v";
f97d05dc 704 case EM_CYGNUS_ARC: return "Arc";
76466873
NC
705 case EM_CYGNUS_M32R: return "M32r";
706 case EM_CYGNUS_V850: return "v850";
707 case EM_CYGNUS_MN10300: return "mn10300";
708 case EM_CYGNUS_MN10200: return "mn10200";
19808d3f 709
76466873
NC
710 default:
711 sprintf (buff, _("<unknown>: %x"), e_machine);
712 return buff;
713 }
714}
715
a09db9ba
MM
716static char *
717get_machine_flags (e_flags, e_machine)
718 unsigned e_flags;
719 unsigned e_machine;
720{
721 static char buf [1024];
19808d3f 722
a09db9ba
MM
723 buf[0] = '\0';
724 if (e_flags)
725 {
726 switch (e_machine)
727 {
728 default:
729 break;
730
731 case EM_PPC:
732 if (e_flags & EF_PPC_EMB)
733 strcat (buf, ", emb");
734
735 if (e_flags & EF_PPC_RELOCATABLE)
736 strcat (buf, ", relocatable");
737
738 if (e_flags & EF_PPC_RELOCATABLE_LIB)
739 strcat (buf, ", relocatable-lib");
740 break;
741
742 case EM_CYGNUS_M32R:
743 if ((e_flags & EF_M32R_ARCH) == E_M32R_ARCH)
744 strcat (buf, ", m32r");
745
746 /* start-sanitize-m32rx */
747#ifdef E_M32RX_ARCH
748 if ((e_flags & EF_M32R_ARCH) == E_M32RX_ARCH)
749 strcat (buf, ", m32rx");
750#endif
751 /* end-sanitize-m32rx */
752 break;
753
754 case EM_MIPS:
755 case EM_MIPS_RS4_BE:
756 if (e_flags & EF_MIPS_NOREORDER)
757 strcat (buf, ", noreorder");
758
759 if (e_flags & EF_MIPS_PIC)
760 strcat (buf, ", pic");
761
762 if (e_flags & EF_MIPS_CPIC)
763 strcat (buf, ", cpic");
764
765 if (e_flags & EF_MIPS_ABI2)
766 strcat (buf, ", abi2");
767
768 if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1)
769 strcat (buf, ", mips1");
770
771 if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2)
772 strcat (buf, ", mips2");
773
774 if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_3)
775 strcat (buf, ", mips3");
776
777 if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_4)
778 strcat (buf, ", mips4");
779 break;
780 }
781 }
782
783 return buf;
784}
785
786static char *
787get_machine_data (e_data)
788 unsigned e_data;
789{
790 static char buff [32];
19808d3f 791
a09db9ba
MM
792 switch (e_data)
793 {
794 case ELFDATA2LSB: return _("ELFDATA2LSB (little endian)");
795 case ELFDATA2MSB: return _("ELFDATA2MSB (big endian)");
796 default:
797 sprintf (buff, _("<unknown>: %x"), e_data);
798 return buff;
799 }
800}
801
5821de31
UD
802static const char *
803get_mips_segment_type (type)
804 unsigned long type;
805{
806 switch (type)
807 {
808 case PT_MIPS_REGINFO:
5892b099 809 return "REGINFO";
5821de31 810 case PT_MIPS_RTPROC:
5892b099 811 return "RTPROC";
5821de31 812 case PT_MIPS_OPTIONS:
5892b099 813 return "OPTIONS";
5821de31 814 default:
5892b099 815 break;
5821de31 816 }
5892b099
UD
817
818 return NULL;
5821de31
UD
819}
820
821static const char *
76466873
NC
822get_segment_type (p_type)
823 unsigned long p_type;
824{
825 static char buff [32];
19808d3f 826
76466873
NC
827 switch (p_type)
828 {
5892b099
UD
829 case PT_NULL: return "NULL";
830 case PT_LOAD: return "LOAD";
831 case PT_DYNAMIC: return "DYNAMIC";
832 case PT_INTERP: return "INTERP";
833 case PT_NOTE: return "NOTE";
834 case PT_SHLIB: return "SHLIB";
835 case PT_PHDR: return "PHDR";
76466873
NC
836
837 default:
838 if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
5892b099
UD
839 {
840 const char *result;
841 switch (elf_header.e_machine)
842 {
843 case EM_MIPS:
844 case EM_MIPS_RS4_BE:
845 result = get_mips_segment_type (p_type);
846 break;
847 default:
848 result = NULL;
849 break;
850 }
851 if (result == NULL)
852 {
853 sprintf (buff, "LOPROC+%d", p_type - PT_LOPROC);
854 result = buff;
855 }
856 return result;
857 }
76466873
NC
858 else
859 {
860 sprintf (buff, _("<unknown>: %x"), p_type);
861 return buff;
862 }
863 }
864}
865
5892b099
UD
866static const char *
867get_mips_section_type_name (sh_type)
868 unsigned int sh_type;
869{
870 switch (sh_type)
871 {
872 case SHT_MIPS_LIBLIST:
873 return "MIPS_LIBLIST";
874 case SHT_MIPS_MSYM:
875 return "MIPS_MSYM";
876 case SHT_MIPS_CONFLICT:
877 return "MIPS_CONFLICT";
878 case SHT_MIPS_GPTAB:
879 return "MIPS_GPTAB";
880 case SHT_MIPS_UCODE:
881 return "MIPS_UCODE";
882 case SHT_MIPS_DEBUG:
883 return "MIPS_DEBUG";
884 case SHT_MIPS_REGINFO:
885 return "MIPS_REGINFO";
886 case SHT_MIPS_PACKAGE:
887 return "MIPS_PACKAGE";
888 case SHT_MIPS_PACKSYM:
889 return "MIPS_PACKSYM";
890 case SHT_MIPS_RELD:
891 return "MIPS_RELD";
892 case SHT_MIPS_IFACE:
893 return "MIPS_IFACE";
894 case SHT_MIPS_CONTENT:
895 return "MIPS_CONTENT";
896 case SHT_MIPS_OPTIONS:
897 return "MIPS_OPTIONS";
898 case SHT_MIPS_SHDR:
899 return "MIPS_SHDR";
900 case SHT_MIPS_FDESC:
901 return "MIPS_FDESC";
902 case SHT_MIPS_EXTSYM:
903 return "MIPS_EXTSYM";
904 case SHT_MIPS_DENSE:
905 return "MIPS_DENSE";
906 case SHT_MIPS_PDESC:
907 return "MIPS_PDESC";
908 case SHT_MIPS_LOCSYM:
909 return "MIPS_LOCSYM";
910 case SHT_MIPS_AUXSYM:
911 return "MIPS_AUXSYM";
912 case SHT_MIPS_OPTSYM:
913 return "MIPS_OPTSYM";
914 case SHT_MIPS_LOCSTR:
915 return "MIPS_LOCSTR";
916 case SHT_MIPS_LINE:
917 return "MIPS_LINE";
918 case SHT_MIPS_RFDESC:
919 return "MIPS_RFDESC";
920 case SHT_MIPS_DELTASYM:
921 return "MIPS_DELTASYM";
922 case SHT_MIPS_DELTAINST:
923 return "MIPS_DELTAINST";
924 case SHT_MIPS_DELTACLASS:
925 return "MIPS_DELTACLASS";
926 case SHT_MIPS_DWARF:
927 return "MIPS_DWARF";
928 case SHT_MIPS_DELTADECL:
929 return "MIPS_DELTADECL";
930 case SHT_MIPS_SYMBOL_LIB:
931 return "MIPS_SYMBOL_LIB";
932 case SHT_MIPS_EVENTS:
933 return "MIPS_EVENTS";
934 case SHT_MIPS_TRANSLATE:
935 return "MIPS_TRANSLATE";
936 case SHT_MIPS_PIXIE:
937 return "MIPS_PIXIE";
938 case SHT_MIPS_XLATE:
939 return "MIPS_XLATE";
940 case SHT_MIPS_XLATE_DEBUG:
941 return "MIPS_XLATE_DEBUG";
942 case SHT_MIPS_WHIRL:
943 return "MIPS_WHIRL";
944 case SHT_MIPS_EH_REGION:
945 return "MIPS_EH_REGION";
946 case SHT_MIPS_XLATE_OLD:
947 return "MIPS_XLATE_OLD";
948 case SHT_MIPS_PDR_EXCEPTION:
949 return "MIPS_PDR_EXCEPTION";
950 default:
951 break;
952 }
953 return NULL;
954}
955
956static const char *
76466873
NC
957get_section_type_name (sh_type)
958 unsigned int sh_type;
959{
960 static char buff [32];
19808d3f 961
76466873
NC
962 switch (sh_type)
963 {
5892b099
UD
964 case SHT_NULL: return "NULL";
965 case SHT_PROGBITS: return "PROGBITS";
966 case SHT_SYMTAB: return "SYMTAB";
967 case SHT_STRTAB: return "STRTAB";
968 case SHT_RELA: return "RELA";
969 case SHT_HASH: return "HASH";
970 case SHT_DYNAMIC: return "DYNAMIC";
971 case SHT_NOTE: return "NOTE";
972 case SHT_NOBITS: return "NOBITS";
973 case SHT_REL: return "REL";
974 case SHT_SHLIB: return "SHLIB";
975 case SHT_DYNSYM: return "DYNSYM";
976 case SHT_GNU_verdef: return "VERDEF";
977 case SHT_GNU_verneed: return "VERNEED";
978 case SHT_GNU_versym: return "VERSYM";
76466873
NC
979 case 0x6ffffff0: return "VERSYM";
980 case 0x6ffffffc: return "VERDEF";
981 case 0x7ffffffd: return "AUXILIARY";
982 case 0x7fffffff: return "FILTER";
983
984 default:
985 if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC))
5892b099
UD
986 {
987 const char *result;
988
989 switch (elf_header.e_machine)
990 {
991 case EM_MIPS:
992 case EM_MIPS_RS4_BE:
993 result = get_mips_section_type_name (sh_type);
994 break;
995 default:
996 result = NULL;
997 break;
998 }
999
1000 if (result == NULL)
1001 {
1002 sprintf (buff, _("SHT_LOPROC+%d"), sh_type - SHT_LOPROC);
1003 result = buff;
1004 }
1005 return result;
1006 }
76466873 1007 else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER))
5892b099 1008 sprintf (buff, _("SHT_LOUSER+%d"), sh_type - SHT_LOUSER);
76466873 1009 else
ebb64169
NC
1010 sprintf (buff, _("<unknown>: %x"), sh_type);
1011 return buff;
76466873
NC
1012 }
1013}
1014
1015struct option options [] =
1016{
1017 {"all", no_argument, 0, 'a'},
1018 {"file-header", no_argument, 0, 'h'},
1019 {"program-headers", no_argument, 0, 'l'},
ebb64169 1020 {"headers", no_argument, 0, 'e'},
e5a32b17 1021 {"histogram", no_argument, &do_histogram, 1},
76466873
NC
1022 {"segments", no_argument, 0, 'l'},
1023 {"sections", no_argument, 0, 'S'},
ebb64169 1024 {"section-headers", no_argument, 0, 'S'},
19808d3f 1025 {"symbols", no_argument, 0, 's'},
c80944f2 1026 {"syms", no_argument, 0, 's'},
76466873
NC
1027 {"relocs", no_argument, 0, 'r'},
1028 {"dynamic", no_argument, 0, 'd'},
1029 {"version-info", no_argument, 0, 'V'},
1030 {"use-dynamic", no_argument, 0, 'D'},
1031
1032 {"hex-dump", required_argument, 0, 'x'},
1033#ifdef SUPPORT_DISASSEMBLY
1034 {"instruction-dump", required_argument, 0, 'i'},
1035#endif
19808d3f 1036
76466873
NC
1037 {"version", no_argument, 0, 'v'},
1038 {"help", no_argument, 0, 'H'},
1039
1040 {0, no_argument, 0, 0}
1041};
1042
1043static void
1044usage ()
1045{
59bbaa19
ILT
1046 fprintf (stdout, _("Usage: readelf {options} elf-file(s)\n"));
1047 fprintf (stdout, _(" Options are:\n"));
e5a32b17 1048 fprintf (stdout, _(" -a or --all Equivalent to: -h -l -S -s -r -d -V --histogram\n"));
59bbaa19
ILT
1049 fprintf (stdout, _(" -h or --file-header Display the ELF file header\n"));
1050 fprintf (stdout, _(" -l or --program-headers or --segments\n"));
1051 fprintf (stdout, _(" Display the program headers\n"));
ebb64169
NC
1052 fprintf (stdout, _(" -S or --section-headers or --sections\n"));
1053 fprintf (stdout, _(" Display the sections' header\n"));
1054 fprintf (stdout, _(" -e or --headers Equivalent to: -h -l -S\n"));
c80944f2 1055 fprintf (stdout, _(" -s or --syms or --symbols Display the symbol table\n"));
59bbaa19 1056 fprintf (stdout, _(" -r or --relocs Display the relocations (if present)\n"));
ebb64169 1057 fprintf (stdout, _(" -d or --dynamic Display the dynamic segment (if present)\n"));
59bbaa19
ILT
1058 fprintf (stdout, _(" -V or --version-info Display the version sections (if present)\n"));
1059 fprintf (stdout, _(" -D or --use-dynamic Use the dynamic section info when displaying symbols\n"));
1060 fprintf (stdout, _(" -x <number> or --hex-dump=<number>\n"));
1061 fprintf (stdout, _(" Dump the contents of section <number>\n"));
19808d3f 1062#ifdef SUPPORT_DISASSEMBLY
59bbaa19
ILT
1063 fprintf (stdout, _(" -i <number> or --instruction-dump=<number>\n"));
1064 fprintf (stdout, _(" Disassemble the contents of section <number>\n"));
19808d3f 1065#endif
e5a32b17 1066 fprintf (stdout, _(" --histogram Display histogram of bucket list lengths\n"));
59bbaa19
ILT
1067 fprintf (stdout, _(" -v or --version Display the version number of readelf\n"));
1068 fprintf (stdout, _(" -H or --help Display this information\n"));
1069 fprintf (stdout, _("Report bugs to bug-gnu-utils@gnu.org\n"));
19808d3f 1070
76466873
NC
1071 exit (0);
1072}
1073
1074static void
1075parse_args (argc, argv)
1076 int argc;
1077 char ** argv;
1078{
59bbaa19 1079 int c;
19808d3f 1080
76466873
NC
1081 if (argc < 2)
1082 usage ();
1083
1084 while ((c = getopt_long
ebb64169 1085 (argc, argv, "ersahldSDx:i:vV", options, NULL)) != EOF)
76466873
NC
1086 {
1087 char * cp;
1088 int section;
19808d3f 1089
76466873
NC
1090 switch (c)
1091 {
e5a32b17
UD
1092 case 0:
1093 /* Long options. */
1094 break;
76466873
NC
1095 case 'H':
1096 usage ();
1097 break;
19808d3f 1098
76466873 1099 case 'a':
ebb64169
NC
1100 do_syms ++;
1101 do_reloc ++;
1102 do_dynamic ++;
1103 do_header ++;
1104 do_sections ++;
1105 do_segments ++;
1106 do_version ++;
e5a32b17 1107 do_histogram ++;
ebb64169
NC
1108 break;
1109 case 'e':
1110 do_header ++;
1111 do_sections ++;
1112 do_segments ++;
76466873
NC
1113 break;
1114 case 'D':
ebb64169 1115 do_using_dynamic ++;
76466873
NC
1116 break;
1117 case 'r':
ebb64169 1118 do_reloc ++;
76466873
NC
1119 break;
1120 case 'h':
ebb64169 1121 do_header ++;
76466873
NC
1122 break;
1123 case 'l':
ebb64169 1124 do_segments ++;
76466873
NC
1125 break;
1126 case 's':
ebb64169 1127 do_syms ++;
76466873
NC
1128 break;
1129 case 'S':
ebb64169 1130 do_sections ++;
76466873
NC
1131 break;
1132 case 'd':
ebb64169 1133 do_dynamic ++;
76466873
NC
1134 break;
1135 case 'x':
1136 do_dump ++;
1137 section = strtoul (optarg, & cp, 0);
1138 if (! * cp && section >= 0 && section < NUM_DUMP_SECTS)
1139 {
1140 dump_sects [section] |= HEX_DUMP;
1141 break;
1142 }
1143 goto oops;
19808d3f 1144#ifdef SUPPORT_DISASSEMBLY
76466873
NC
1145 case 'i':
1146 do_dump ++;
1147 section = strtoul (optarg, & cp, 0);
1148 if (! * cp && section >= 0 && section < NUM_DUMP_SECTS)
1149 {
1150 dump_sects [section] |= DISASS_DUMP;
1151 break;
1152 }
1153 goto oops;
1154#endif
1155 case 'v':
1156 print_version (program_name);
1157 break;
1158 case 'V':
1159 do_version ++;
1160 break;
1161 default:
1162 oops:
1163 /* xgettext:c-format */
1164 error (_("Invalid option '-%c'\n"), c);
1165 /* Drop through. */
1166 case '?':
1167 usage ();
1168 }
1169 }
1170
ebb64169 1171 if (!do_dynamic && !do_syms && !do_reloc && !do_sections
e5a32b17
UD
1172 && !do_segments && !do_header && !do_dump && !do_version
1173 && !do_histogram)
76466873
NC
1174 usage ();
1175 else if (argc < 3)
59bbaa19
ILT
1176 {
1177 warn (_("Nothing to do.\n"));
1178 usage();
1179 }
76466873
NC
1180}
1181
ebb64169 1182/* Decode the data held in 'elf_header'. */
76466873 1183static int
ebb64169 1184process_file_header ()
76466873 1185{
ebb64169
NC
1186 if ( elf_header.e_ident [EI_MAG0] != ELFMAG0
1187 || elf_header.e_ident [EI_MAG1] != ELFMAG1
1188 || elf_header.e_ident [EI_MAG2] != ELFMAG2
1189 || elf_header.e_ident [EI_MAG3] != ELFMAG3)
76466873 1190 {
ebb64169
NC
1191 error
1192 (_("Not an ELF file - it has the wrong magic bytes at the start\n"));
76466873
NC
1193 return 0;
1194 }
19808d3f 1195
ebb64169 1196 if (elf_header.e_ident [EI_CLASS] != ELFCLASS32)
76466873
NC
1197 {
1198 error (_("Not a 32 bit ELF file\n"));
1199 return 0;
1200 }
19808d3f 1201
76466873
NC
1202 if (do_header)
1203 {
1204 int i;
19808d3f 1205
ebb64169
NC
1206 printf (_("ELF Header:\n"));
1207 printf (_(" Magic: "));
76466873 1208 for (i = 0; i < EI_NIDENT; i ++)
ebb64169 1209 printf ("%2.2x ", elf_header.e_ident [i]);
19808d3f 1210 printf ("\n");
ebb64169
NC
1211 printf (_(" Type: %s\n"),
1212 get_file_type (elf_header.e_type));
1213 printf (_(" Machine: %s\n"),
1214 get_machine_name (elf_header.e_machine));
1215 printf (_(" Version: 0x%lx\n"),
1216 (unsigned long) elf_header.e_version);
cb436f39 1217 printf (_(" Data: %s\n"),
ebb64169 1218 get_machine_data (elf_header.e_ident [EI_DATA]));
ebb64169
NC
1219 printf (_(" Entry point address: 0x%lx\n"),
1220 (unsigned long) elf_header.e_entry);
1221 printf (_(" Start of program headers: %ld (bytes into file)\n"),
1222 (long) elf_header.e_phoff);
1223 printf (_(" Start of section headers: %ld (bytes into file)\n"),
1224 (long) elf_header.e_shoff);
1225 printf (_(" Flags: 0x%lx%s\n"),
1226 (unsigned long) elf_header.e_flags,
1227 get_machine_flags (elf_header.e_flags, elf_header.e_machine));
1228 printf (_(" Size of this header: %ld (bytes)\n"),
1229 (long) elf_header.e_ehsize);
1230 printf (_(" Size of program headers: %ld (bytes)\n"),
1231 (long) elf_header.e_phentsize);
1232 printf (_(" Number of program headers: %ld\n"),
1233 (long) elf_header.e_phnum);
1234 printf (_(" Size of section headers: %ld (bytes)\n"),
1235 (long) elf_header.e_shentsize);
1236 printf (_(" Number of section headers: %ld\n"),
1237 (long) elf_header.e_shnum);
1238 printf (_(" Section header string table index: %ld\n"),
1239 (long) elf_header.e_shstrndx);
76466873 1240 }
19808d3f 1241
76466873
NC
1242 return 1;
1243}
1244
1245
cb436f39 1246static int
ebb64169
NC
1247process_program_headers (file)
1248 FILE * file;
76466873 1249{
cb436f39
NC
1250 Elf32_External_Phdr * phdrs;
1251 Elf32_Internal_Phdr * program_headers;
1252 Elf32_Internal_Phdr * segment;
1253 unsigned int i;
19808d3f 1254
ebb64169 1255 if (elf_header.e_phnum == 0)
76466873 1256 {
ebb64169
NC
1257 if (do_segments)
1258 printf (_("\nThere are no program headers in this file.\n"));
cb436f39 1259 return 1;
76466873 1260 }
19808d3f 1261
ebb64169 1262 if (do_segments && !do_header)
76466873 1263 {
ebb64169 1264 printf (_("\nElf file is %s\n"), get_file_type (elf_header.e_type));
cb436f39
NC
1265 printf (_("Entry point 0x%lx\n"), (unsigned long) elf_header.e_entry);
1266 printf (_("There are %d program headers, starting at offset %lx:\n"),
1267 elf_header.e_phnum, (unsigned long) elf_header.e_phoff);
76466873
NC
1268 }
1269
cb436f39
NC
1270 GET_DATA_ALLOC (elf_header.e_phoff,
1271 elf_header.e_phentsize * elf_header.e_phnum,
1272 phdrs, Elf32_External_Phdr *, "program headers");
19808d3f 1273
cb436f39
NC
1274 program_headers = (Elf32_Internal_Phdr *) malloc
1275 (elf_header.e_phnum * sizeof (Elf32_Internal_Phdr));
1276
1277 if (program_headers == NULL)
76466873 1278 {
cb436f39
NC
1279 error (_("Out of memory\n"));
1280 return 0;
76466873 1281 }
19808d3f 1282
cb436f39
NC
1283 for (i = 0, segment = program_headers;
1284 i < elf_header.e_phnum;
1285 i ++, segment ++)
1286 {
1287 segment->p_type = BYTE_GET (phdrs[i].p_type);
1288 segment->p_offset = BYTE_GET (phdrs[i].p_offset);
1289 segment->p_vaddr = BYTE_GET (phdrs[i].p_vaddr);
1290 segment->p_paddr = BYTE_GET (phdrs[i].p_paddr);
1291 segment->p_filesz = BYTE_GET (phdrs[i].p_filesz);
1292 segment->p_memsz = BYTE_GET (phdrs[i].p_memsz);
1293 segment->p_flags = BYTE_GET (phdrs[i].p_flags);
1294 segment->p_align = BYTE_GET (phdrs[i].p_align);
1295 }
1296
1297 free (phdrs);
19808d3f 1298
ebb64169 1299 if (do_segments)
76466873 1300 {
ebb64169
NC
1301 printf
1302 (_("\nProgram Header%s:\n"), elf_header.e_phnum > 1 ? "s" : "");
1303 printf
fdf959dd 1304 (_(" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n"));
76466873
NC
1305 }
1306
1307 loadaddr = -1;
1308 dynamic_addr = 0;
1309
cb436f39
NC
1310 for (i = 0, segment = program_headers;
1311 i < elf_header.e_phnum;
1312 i ++, segment ++)
76466873 1313 {
ebb64169 1314 if (do_segments)
76466873 1315 {
5892b099 1316 printf (" %-11.11s ", get_segment_type (segment->p_type));
fdf959dd 1317 printf ("0x%6.6lx ", (unsigned long) segment->p_offset);
cb436f39
NC
1318 printf ("0x%8.8lx ", (unsigned long) segment->p_vaddr);
1319 printf ("0x%8.8lx ", (unsigned long) segment->p_paddr);
1320 printf ("0x%5.5lx ", (unsigned long) segment->p_filesz);
1321 printf ("0x%5.5lx ", (unsigned long) segment->p_memsz);
76466873 1322 printf ("%c%c%c ",
ebb64169
NC
1323 (segment->p_flags & PF_R ? 'R' : ' '),
1324 (segment->p_flags & PF_W ? 'W' : ' '),
1325 (segment->p_flags & PF_X ? 'E' : ' '));
cb436f39 1326 printf ("%#lx", (unsigned long) segment->p_align);
76466873 1327 }
ebb64169
NC
1328
1329 switch (segment->p_type)
76466873 1330 {
ebb64169
NC
1331 case PT_LOAD:
1332 if (loadaddr == -1)
1333 loadaddr = (segment->p_vaddr & 0xfffff000)
1334 - (segment->p_offset & 0xfffff000);
1335 break;
1336
1337 case PT_DYNAMIC:
76466873 1338 if (dynamic_addr)
ebb64169 1339 error (_("more than one dynamic segment\n"));
19808d3f 1340
ebb64169
NC
1341 dynamic_addr = segment->p_offset;
1342 dynamic_size = segment->p_filesz;
1343 break;
1344
1345 case PT_INTERP:
1346 if (fseek (file, segment->p_offset, SEEK_SET))
1347 error (_("Unable to find program interpreter name\n"));
1348 else
1349 {
1350 program_interpreter[0] = 0;
1351 fscanf (file, "%63s", program_interpreter);
19808d3f 1352
ebb64169
NC
1353 if (do_segments)
1354 printf (_("\n [Requesting program interpreter: %s]"),
1355 program_interpreter);
1356 }
1357 break;
76466873 1358 }
19808d3f 1359
ebb64169 1360 if (do_segments)
76466873 1361 putc ('\n', stdout);
76466873
NC
1362 }
1363
ebb64169
NC
1364 if (loadaddr == -1)
1365 {
1366 /* Very strange. */
1367 loadaddr = 0;
1368 }
1369
1370 if (do_segments && section_headers != NULL)
76466873
NC
1371 {
1372 printf (_("\n Section to Segment mapping:\n"));
1373 printf (_(" Segment Sections...\n"));
1374
ebb64169 1375 assert (string_table != NULL);
19808d3f 1376
ebb64169 1377 for (i = 0; i < elf_header.e_phnum; i++)
76466873 1378 {
ebb64169 1379 int j;
cb436f39 1380 Elf32_Internal_Shdr * section;
19808d3f 1381
ebb64169
NC
1382 segment = program_headers + i;
1383 section = section_headers;
19808d3f 1384
76466873 1385 printf (" %2.2d ", i);
19808d3f 1386
ebb64169 1387 for (j = 0; j < elf_header.e_shnum; j++, section ++)
76466873 1388 {
ebb64169
NC
1389 if (section->sh_size > 0
1390 /* Compare allocated sections by VMA, unallocated
1391 sections by file offset. */
1392 && (section->sh_flags & SHF_ALLOC
1393 ? (section->sh_addr >= segment->p_vaddr
1394 && section->sh_addr + section->sh_size
1395 <= segment->p_vaddr + segment->p_memsz)
1396 : (section->sh_offset >= segment->p_offset
1397 && (section->sh_offset + section->sh_size
1398 <= segment->p_offset + segment->p_filesz))))
1399 printf ("%s ", SECTION_NAME (section));
76466873
NC
1400 }
1401
1402 putc ('\n',stdout);
1403 }
1404 }
19808d3f 1405
ebb64169 1406 free (program_headers);
cb436f39
NC
1407
1408 return 1;
76466873
NC
1409}
1410
1411
cb436f39
NC
1412static int
1413get_section_headers (file)
1414 FILE * file;
1415{
1416 Elf32_External_Shdr * shdrs;
1417 Elf32_Internal_Shdr * internal;
1418 unsigned int i;
19808d3f 1419
cb436f39
NC
1420 GET_DATA_ALLOC (elf_header.e_shoff,
1421 elf_header.e_shentsize * elf_header.e_shnum,
1422 shdrs, Elf32_External_Shdr *, "section headers");
1423
1424 section_headers = (Elf32_Internal_Shdr *) malloc
1425 (elf_header.e_shnum * sizeof (Elf32_Internal_Shdr));
1426
1427 if (section_headers == NULL)
1428 {
1429 error (_("Out of memory\n"));
1430 return 0;
1431 }
19808d3f 1432
cb436f39
NC
1433 for (i = 0, internal = section_headers;
1434 i < elf_header.e_shnum;
1435 i ++, internal ++)
1436 {
1437 internal->sh_name = BYTE_GET (shdrs[i].sh_name);
1438 internal->sh_type = BYTE_GET (shdrs[i].sh_type);
1439 internal->sh_flags = BYTE_GET (shdrs[i].sh_flags);
1440 internal->sh_addr = BYTE_GET (shdrs[i].sh_addr);
1441 internal->sh_offset = BYTE_GET (shdrs[i].sh_offset);
1442 internal->sh_size = BYTE_GET (shdrs[i].sh_size);
1443 internal->sh_link = BYTE_GET (shdrs[i].sh_link);
1444 internal->sh_info = BYTE_GET (shdrs[i].sh_info);
1445 internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
1446 internal->sh_entsize = BYTE_GET (shdrs[i].sh_entsize);
1447 }
1448
1449 free (shdrs);
1450
1451 return 1;
1452}
1453
1454static Elf_Internal_Sym *
1455get_elf_symbols (file, offset, number)
1456 FILE * file;
1457 unsigned long offset;
1458 unsigned long number;
1459{
1460 Elf32_External_Sym * esyms;
1461 Elf_Internal_Sym * isyms;
1462 Elf_Internal_Sym * psym;
1463 unsigned int j;
19808d3f 1464
cb436f39
NC
1465 GET_DATA_ALLOC (offset, number * sizeof (Elf32_External_Sym),
1466 esyms, Elf32_External_Sym *, "symbols");
19808d3f 1467
cb436f39 1468 isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym));
19808d3f 1469
cb436f39
NC
1470 if (isyms == NULL)
1471 {
1472 error (_("Out of memory\n"));
1473 free (esyms);
19808d3f 1474
cb436f39
NC
1475 return NULL;
1476 }
19808d3f 1477
cb436f39
NC
1478 for (j = 0, psym = isyms;
1479 j < number;
1480 j ++, psym ++)
1481 {
1482 psym->st_name = BYTE_GET (esyms[j].st_name);
1483 psym->st_value = BYTE_GET (esyms[j].st_value);
1484 psym->st_size = BYTE_GET (esyms[j].st_size);
1485 psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
1486 psym->st_info = BYTE_GET (esyms[j].st_info);
1487 psym->st_other = BYTE_GET (esyms[j].st_other);
1488 }
1489
1490 free (esyms);
1491
1492 return isyms;
1493}
1494
1495static int
ebb64169
NC
1496process_section_headers (file)
1497 FILE * file;
76466873 1498{
cb436f39 1499 Elf32_Internal_Shdr * section;
ebb64169 1500 int i;
76466873 1501
cb436f39 1502 section_headers = NULL;
19808d3f 1503
ebb64169
NC
1504 if (elf_header.e_shnum == 0)
1505 {
1506 if (do_sections)
1507 printf (_("\nThere are no sections in this file.\n"));
1508
cb436f39 1509 return 1;
ebb64169 1510 }
19808d3f 1511
ebb64169
NC
1512 if (do_sections && !do_header)
1513 printf (_("There are %d section headers, starting at offset %x:\n"),
1514 elf_header.e_shnum, elf_header.e_shoff);
1515
cb436f39
NC
1516 if (! get_section_headers (file))
1517 return 0;
ebb64169
NC
1518
1519 /* Read in the string table, so that we have names to display. */
1520 section = section_headers + elf_header.e_shstrndx;
19808d3f 1521
ebb64169
NC
1522 if (section->sh_size != 0)
1523 {
1524 unsigned long string_table_offset;
19808d3f 1525
ebb64169
NC
1526 string_table_offset = section->sh_offset;
1527
1528 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
1529 string_table, char *, "string table");
1530 }
1531
1532 /* Scan the sections for the dynamic symbol table
1533 and dynamic string table. */
1534 dynamic_symbols = NULL;
1535 dynamic_strings = NULL;
fdf959dd 1536 dynamic_syminfo = NULL;
ebb64169
NC
1537 for (i = 0, section = section_headers;
1538 i < elf_header.e_shnum;
1539 i ++, section ++)
1540 {
1541 if (section->sh_type == SHT_DYNSYM)
1542 {
1543 if (dynamic_symbols != NULL)
1544 {
1545 error (_("File contains multiple dynamic symbol tables\n"));
1546 continue;
1547 }
1548
cb436f39
NC
1549 dynamic_symbols = get_elf_symbols
1550 (file, section->sh_offset, section->sh_size / section->sh_entsize);
ebb64169
NC
1551 }
1552 else if (section->sh_type == SHT_STRTAB
1553 && strcmp (SECTION_NAME (section), ".dynstr") == 0)
76466873 1554 {
ebb64169
NC
1555 if (dynamic_strings != NULL)
1556 {
1557 error (_("File contains multiple dynamic string tables\n"));
1558 continue;
1559 }
19808d3f 1560
ebb64169
NC
1561 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
1562 dynamic_strings, char *, "dynamic strings");
76466873
NC
1563 }
1564 }
ebb64169
NC
1565
1566 if (! do_sections)
cb436f39 1567 return 1;
19808d3f 1568
ebb64169
NC
1569 printf (_("\nSection Header%s:\n"), elf_header.e_shnum > 1 ? "s" : "");
1570 printf
9eaac302 1571 (_(" [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n"));
19808d3f 1572
ebb64169
NC
1573 for (i = 0, section = section_headers;
1574 i < elf_header.e_shnum;
1575 i ++, section ++)
76466873 1576 {
cb436f39
NC
1577 printf (" [%2d] %-17.17s %-15.15s ",
1578 i,
1579 SECTION_NAME (section),
1580 get_section_type_name (section->sh_type));
19808d3f 1581
c18f8aef 1582 printf ( "%8.8lx %6.6lx %6.6lx %2.2lx",
cb436f39
NC
1583 (unsigned long) section->sh_addr,
1584 (unsigned long) section->sh_offset,
1585 (unsigned long) section->sh_size,
1586 (unsigned long) section->sh_entsize);
19808d3f 1587
cb436f39 1588 printf (" %c%c%c %2ld %3lx %ld \n",
ebb64169
NC
1589 (section->sh_flags & SHF_WRITE ? 'W' : ' '),
1590 (section->sh_flags & SHF_ALLOC ? 'A' : ' '),
1591 (section->sh_flags & SHF_EXECINSTR ? 'X' : ' '),
cb436f39
NC
1592 (unsigned long) section->sh_link,
1593 (unsigned long) section->sh_info,
1594 (unsigned long) section->sh_addralign);
76466873 1595 }
cb436f39
NC
1596
1597 return 1;
76466873
NC
1598}
1599
ebb64169 1600/* Process the reloc section. */
cb436f39 1601static int
ebb64169
NC
1602process_relocs (file)
1603 FILE * file;
76466873 1604{
ebb64169
NC
1605 unsigned long rel_size;
1606 unsigned long rel_offset;
76466873 1607
19808d3f 1608
ebb64169 1609 if (!do_reloc)
cb436f39 1610 return 1;
19808d3f 1611
ebb64169 1612 if (do_using_dynamic)
76466873 1613 {
ebb64169
NC
1614 rel_size = 0;
1615 rel_offset = 0;
19808d3f 1616
be5b92f9 1617 if (dynamic_info[DT_REL])
76466873 1618 {
be5b92f9
CM
1619 rel_offset = dynamic_info[DT_REL];
1620 rel_size = dynamic_info[DT_RELSZ];
76466873 1621 }
ebb64169 1622 else if (dynamic_info [DT_RELA])
76466873 1623 {
be5b92f9
CM
1624 rel_offset = dynamic_info[DT_RELA];
1625 rel_size = dynamic_info[DT_RELASZ];
19808d3f 1626 }
be5b92f9 1627 else if (dynamic_info[DT_JMPREL])
ebb64169 1628 {
be5b92f9
CM
1629 rel_offset = dynamic_info[DT_JMPREL];
1630 rel_size = dynamic_info[DT_PLTRELSZ];
ebb64169
NC
1631 }
1632
1633 if (rel_size)
1634 {
cb436f39
NC
1635 printf
1636 (_("\nRelocation section at offset 0x%x contains %d bytes:\n"),
1637 rel_offset, rel_size);
19808d3f 1638
ebb64169
NC
1639 dump_relocations (file, rel_offset - loadaddr, rel_size,
1640 dynamic_symbols, dynamic_strings);
76466873 1641 }
ebb64169
NC
1642 else
1643 printf (_("\nThere are no dynamic relocations in this file.\n"));
76466873
NC
1644 }
1645 else
1646 {
f97d05dc
NC
1647 Elf32_Internal_Shdr * section;
1648 unsigned long i;
1649 int found = 0;
19808d3f 1650
ebb64169
NC
1651 for (i = 0, section = section_headers;
1652 i < elf_header.e_shnum;
1653 i++, section ++)
1654 {
1655 if ( section->sh_type != SHT_RELA
1656 && section->sh_type != SHT_REL)
1657 continue;
19808d3f 1658
ebb64169
NC
1659 rel_offset = section->sh_offset;
1660 rel_size = section->sh_size;
19808d3f 1661
ebb64169
NC
1662 if (rel_size)
1663 {
cb436f39
NC
1664 Elf32_Internal_Shdr * strsec;
1665 Elf32_Internal_Shdr * symsec;
1666 Elf_Internal_Sym * symtab;
1667 char * strtab;
19808d3f 1668
f97d05dc 1669 printf (_("\nRelocation section "));
3b9f0cb6 1670
f97d05dc
NC
1671 if (string_table == NULL)
1672 printf ("%d", section->sh_name);
1673 else
1674 printf ("'%s'", SECTION_NAME (section));
3b9f0cb6 1675
f97d05dc
NC
1676 printf (_(" at offset 0x%x contains %d entries:\n"),
1677 rel_offset, rel_size / section->sh_entsize);
ebb64169
NC
1678
1679 symsec = section_headers + section->sh_link;
1680
cb436f39
NC
1681 symtab = get_elf_symbols (file, symsec->sh_offset,
1682 symsec->sh_size / symsec->sh_entsize);
19808d3f 1683
cb436f39
NC
1684 if (symtab == NULL)
1685 continue;
19808d3f 1686
ebb64169
NC
1687 strsec = section_headers + symsec->sh_link;
1688
1689 GET_DATA_ALLOC (strsec->sh_offset, strsec->sh_size, strtab,
1690 char *, "string table");
19808d3f 1691
ebb64169
NC
1692 dump_relocations (file, rel_offset, rel_size, symtab, strtab);
1693
1694 free (strtab);
1695 free (symtab);
1696
1697 found = 1;
1698 }
1699 }
19808d3f 1700
ebb64169
NC
1701 if (! found)
1702 printf (_("\nThere are no relocations in this file.\n"));
76466873 1703 }
cb436f39
NC
1704
1705 return 1;
ebb64169 1706}
76466873 1707
ebb64169 1708
5821de31
UD
1709static void
1710dynamic_segment_mips_val (entry)
1711 Elf_Internal_Dyn *entry;
1712{
fdf959dd
UD
1713 if (do_dynamic)
1714 switch (entry->d_tag)
1715 {
1716 case DT_MIPS_FLAGS:
1717 if (entry->d_un.d_val == 0)
1718 printf ("NONE\n");
1719 else
1720 {
1721 static const char *opts[] =
1722 {
1723 "QUICKSTART", "NOTPOT", "NO_LIBRARY_REPLACEMENT",
1724 "NO_MOVE", "SGI_ONLY", "GUARANTEE_INIT", "DELTA_C_PLUS_PLUS",
1725 "GUARANTEE_START_INIT", "PIXIE", "DEFAULT_DELAY_LOAD",
1726 "REQUICKSTART", "REQUICKSTARTED", "CORD", "NO_UNRES_UNDEF",
1727 "RLD_ORDER_SAFE"
1728 };
1729 unsigned int cnt;
1730 int first = 1;
1731 for (cnt = 0; cnt < sizeof (opts) / sizeof (opts[0]); ++cnt)
1732 if (entry->d_un.d_val & (1 << cnt))
1733 {
1734 printf ("%s%s", first ? "" : " ", opts[cnt]);
1735 first = 0;
1736 }
1737 puts ("");
1738 }
1739 break;
1740
1741 case DT_MIPS_IVERSION:
1742 if (dynamic_strings != NULL)
1743 printf ("Interface Version: %s\n",
1744 dynamic_strings + entry->d_un.d_val);
1745 else
1746 printf ("%#ld\n", (long) entry->d_un.d_ptr);
1747 break;
1748
1749 case DT_MIPS_TIME_STAMP:
1750 {
1751 char timebuf[20];
1752 time_t time = entry->d_un.d_val;
1753 strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time));
1754 printf ("Time Stamp: %s\n", timebuf);
1755 }
1756 break;
1757
1758 case DT_MIPS_RLD_VERSION:
1759 case DT_MIPS_LOCAL_GOTNO:
1760 case DT_MIPS_CONFLICTNO:
1761 case DT_MIPS_LIBLISTNO:
1762 case DT_MIPS_SYMTABNO:
1763 case DT_MIPS_UNREFEXTNO:
1764 case DT_MIPS_HIPAGENO:
1765 case DT_MIPS_DELTA_CLASS_NO:
1766 case DT_MIPS_DELTA_INSTANCE_NO:
1767 case DT_MIPS_DELTA_RELOC_NO:
1768 case DT_MIPS_DELTA_SYM_NO:
1769 case DT_MIPS_DELTA_CLASSSYM_NO:
1770 case DT_MIPS_COMPACT_SIZE:
5821de31 1771 printf ("%#ld\n", (long) entry->d_un.d_ptr);
fdf959dd
UD
1772 break;
1773
1774 default:
5821de31 1775 printf ("%#lx\n", (long) entry->d_un.d_ptr);
fdf959dd 1776 }
5821de31
UD
1777}
1778
ebb64169 1779/* Parse the dynamic segment */
cb436f39 1780static int
ebb64169
NC
1781process_dynamic_segment (file)
1782 FILE * file;
1783{
cb436f39
NC
1784 Elf_Internal_Dyn * entry;
1785 Elf32_External_Dyn * edyn;
ebb64169 1786 unsigned int i;
19808d3f 1787
ebb64169 1788 if (dynamic_size == 0)
76466873 1789 {
ebb64169
NC
1790 if (do_dynamic)
1791 printf (_("\nThere is no dynamic segment in this file.\n"));
1792
cb436f39 1793 return 1;
ebb64169
NC
1794 }
1795
1796 GET_DATA_ALLOC (dynamic_addr, dynamic_size,
cb436f39 1797 edyn, Elf32_External_Dyn *, "dynamic segment");
19808d3f 1798
6c4b8d0f
UD
1799 /* SGI's ELF has more than one section in the DYNAMIC segment. Determine
1800 how large .dynamic is now. We can do this even before the byte
1801 swapping since the DT_NULL tag is recognizable. */
1802 dynamic_size = 0;
1803 while (*(Elf32_Word *) edyn[dynamic_size++].d_tag != DT_NULL)
1804 ;
76466873 1805
cb436f39
NC
1806 dynamic_segment = (Elf_Internal_Dyn *)
1807 malloc (dynamic_size * sizeof (Elf_Internal_Dyn));
1808
1809 if (dynamic_segment == NULL)
76466873 1810 {
cb436f39
NC
1811 error (_("Out of memory\n"));
1812 free (edyn);
1813 return 0;
1814 }
19808d3f 1815
cb436f39
NC
1816 for (i = 0, entry = dynamic_segment;
1817 i < dynamic_size;
1818 i ++, entry ++)
1819 {
1820 entry->d_tag = BYTE_GET (edyn [i].d_tag);
1821 entry->d_un.d_val = BYTE_GET (edyn [i].d_un.d_val);
ebb64169 1822 }
76466873 1823
cb436f39 1824 free (edyn);
19808d3f 1825
ebb64169
NC
1826 /* Find the appropriate symbol table. */
1827 if (dynamic_symbols == NULL)
1828 {
1829 for (i = 0, entry = dynamic_segment;
1830 i < dynamic_size;
1831 ++i, ++ entry)
1832 {
cb436f39
NC
1833 unsigned long offset;
1834 long num_syms;
19808d3f 1835
ebb64169
NC
1836 if (entry->d_tag != DT_SYMTAB)
1837 continue;
1838
be5b92f9 1839 dynamic_info[DT_SYMTAB] = entry->d_un.d_val;
ebb64169
NC
1840
1841 /* Since we do not know how big the symbol table is,
1842 we default to reading in the entire file (!) and
1843 processing that. This is overkill, I know, but it
1844 should work. */
19808d3f 1845
ebb64169 1846 offset = entry->d_un.d_val - loadaddr;
19808d3f 1847
ebb64169
NC
1848 if (fseek (file, 0, SEEK_END))
1849 error (_("Unable to seek to end of file!"));
19808d3f 1850
cb436f39 1851 num_syms = (ftell (file) - offset) / sizeof (Elf32_External_Sym);
ebb64169
NC
1852
1853 if (num_syms < 1)
1854 {
1855 error (_("Unable to determine the number of symbols to load\n"));
1856 continue;
1857 }
1858
cb436f39 1859 dynamic_symbols = get_elf_symbols (file, offset, num_syms);
ebb64169
NC
1860 }
1861 }
1862
1863 /* Similarly find a string table. */
1864 if (dynamic_strings == NULL)
1865 {
1866 for (i = 0, entry = dynamic_segment;
1867 i < dynamic_size;
1868 ++i, ++ entry)
1869 {
1870 unsigned long offset;
1871 long str_tab_len;
19808d3f 1872
ebb64169
NC
1873 if (entry->d_tag != DT_STRTAB)
1874 continue;
1875
be5b92f9 1876 dynamic_info[DT_STRTAB] = entry->d_un.d_val;
19808d3f 1877
ebb64169
NC
1878 /* Since we do not know how big the string table is,
1879 we default to reading in the entire file (!) and
1880 processing that. This is overkill, I know, but it
1881 should work. */
19808d3f 1882
ebb64169
NC
1883 offset = entry->d_un.d_val - loadaddr;
1884 if (fseek (file, 0, SEEK_END))
1885 error (_("Unable to seek to end of file\n"));
1886 str_tab_len = ftell (file) - offset;
1887
1888 if (str_tab_len < 1)
1889 {
cb436f39
NC
1890 error
1891 (_("Unable to determine the length of the dynamic string table\n"));
ebb64169
NC
1892 continue;
1893 }
1894
1895 GET_DATA_ALLOC (offset, str_tab_len, dynamic_strings, char *,
1896 "dynamic string table");
1897
1898 break;
1899 }
1900 }
19808d3f 1901
fdf959dd
UD
1902 /* And find the syminfo section if available. */
1903 if (dynamic_syminfo == NULL)
1904 {
1905 unsigned int syminsz = 0;
1906
1907 for (i = 0, entry = dynamic_segment;
1908 i < dynamic_size;
1909 ++i, ++ entry)
1910 {
1911 if (entry->d_tag == DT_SYMINENT)
1912 assert (sizeof (Elf_External_Syminfo) == entry->d_un.d_val);
1913 else if (entry->d_tag == DT_SYMINSZ)
1914 syminsz = entry->d_un.d_val;
1915 else if (entry->d_tag == DT_SYMINFO)
1916 dynamic_syminfo_offset = entry->d_un.d_val - loadaddr;
1917 }
1918
1919 if (dynamic_syminfo_offset != 0 && syminsz != 0)
1920 {
1921 Elf_External_Syminfo *extsyminfo;
1922 Elf_Internal_Syminfo *syminfo;
1923
1924 /* There is a syminfo section. Read the data. */
1925 GET_DATA_ALLOC (dynamic_syminfo_offset, syminsz, extsyminfo,
1926 Elf_External_Syminfo *, "symbol information");
1927
1928 dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz);
1929 if (dynamic_syminfo == NULL)
1930 {
1931 error (_("Out of memory\n"));
1932 return 0;
1933 }
1934
1935 dynamic_syminfo_nent = syminsz / sizeof (Elf_External_Syminfo);
1936 for (i = 0, syminfo = dynamic_syminfo; i < dynamic_syminfo_nent;
1937 ++i, ++syminfo)
1938 {
1939 syminfo->si_boundto = BYTE_GET (extsyminfo[i].si_boundto);
1940 syminfo->si_flags = BYTE_GET (extsyminfo[i].si_flags);
1941 }
1942
1943 free (extsyminfo);
1944 }
1945 }
1946
ebb64169 1947 if (do_dynamic && dynamic_addr)
19808d3f 1948 printf (_("\nDynamic segment at offset 0x%x contains %d entries:\n"),
6c4b8d0f 1949 dynamic_addr, dynamic_size);
ebb64169 1950 if (do_dynamic)
5821de31 1951 printf (_(" Tag Type Name/Value\n"));
19808d3f 1952
ebb64169 1953 for (i = 0, entry = dynamic_segment;
6c4b8d0f 1954 i < dynamic_size;
ebb64169
NC
1955 i++, entry ++)
1956 {
1957 if (do_dynamic)
19808d3f 1958 printf (_(" 0x%-8.8lx (%s)%*s"),
cb436f39 1959 (unsigned long) entry->d_tag,
19808d3f 1960 get_dynamic_type (entry->d_tag),
5821de31 1961 27 - strlen (get_dynamic_type (entry->d_tag)),
19808d3f
UD
1962 " ");
1963
ebb64169
NC
1964 switch (entry->d_tag)
1965 {
1966 case DT_AUXILIARY:
1967 case DT_FILTER:
1968 if (do_dynamic)
1969 {
1970 if (entry->d_tag == DT_AUXILIARY)
1971 printf (_("Auxiliary library"));
1972 else
1973 printf (_("Filter library"));
1974
1975 if (dynamic_strings)
19808d3f 1976 printf (": [%s]\n", dynamic_strings + entry->d_un.d_val);
ebb64169 1977 else
cb436f39 1978 printf (": %#lx\n", (long) entry->d_un.d_val);
ebb64169
NC
1979 }
1980 break;
19808d3f 1981
be5b92f9
CM
1982 case DT_POSFLAG_1:
1983 if (do_dynamic)
1984 {
1985 printf (_("Flags:"));
1986 if (entry->d_un.d_val == 0)
1987 printf (_(" None\n"));
1988 else
1989 {
1990 if (entry->d_un.d_val & DF_P1_LAZYLOAD)
1991 printf (" LAZYLOAD");
1992 if (entry->d_un.d_val & DF_P1_LAZYLOAD)
1993 printf (" GROUPPERM");
1994 puts ("");
1995 }
1996 }
1997 break;
1998
1999 case DT_FLAGS_1:
2000 if (do_dynamic)
2001 {
2002 printf (_("Flags:"));
2003 if (entry->d_un.d_val == 0)
2004 printf (_(" None\n"));
2005 else
2006 {
2007 if (entry->d_un.d_val & DF_1_NOW)
2008 printf (" NOW");
2009 if (entry->d_un.d_val & DF_1_GLOBAL)
2010 printf (" GLOBAL");
2011 if (entry->d_un.d_val & DF_1_GROUP)
2012 printf (" GROUP");
2013 if (entry->d_un.d_val & DF_1_NODELETE)
2014 printf (" NODELETE");
2015 if (entry->d_un.d_val & DF_1_LOADFLTR)
2016 printf (" LOADFLTR");
2017 if (entry->d_un.d_val & DF_1_INITFIRST)
2018 printf (" INITFIRST");
2019 if (entry->d_un.d_val & DF_1_NOOPEN)
2020 printf (" NOOPEN");
2021 if (entry->d_un.d_val & DF_1_ORIGIN)
2022 printf (" ORIGIN");
2023 if (entry->d_un.d_val & DF_1_DIRECT)
2024 printf (" DIRECT");
2025 if (entry->d_un.d_val & DF_1_TRANS)
2026 printf (" TRANS");
2027 if (entry->d_un.d_val & DF_1_INTERPOSE)
2028 printf (" INTERPOSE");
2029 puts ("");
2030 }
2031 }
2032 break;
2033
76466873
NC
2034 case DT_NULL :
2035 case DT_NEEDED :
2036 case DT_PLTRELSZ:
2037 case DT_PLTGOT :
2038 case DT_HASH :
2039 case DT_STRTAB :
2040 case DT_SYMTAB :
2041 case DT_RELA :
76466873
NC
2042 case DT_INIT :
2043 case DT_FINI :
2044 case DT_SONAME :
2045 case DT_RPATH :
2046 case DT_SYMBOLIC:
2047 case DT_REL :
76466873
NC
2048 case DT_PLTREL :
2049 case DT_DEBUG :
2050 case DT_TEXTREL :
2051 case DT_JMPREL :
be5b92f9 2052 dynamic_info[entry->d_tag] = entry->d_un.d_val;
19808d3f 2053
76466873
NC
2054 if (do_dynamic)
2055 {
ebb64169
NC
2056 char * name;
2057
2058 if (dynamic_strings == NULL)
2059 name = NULL;
2060 else
2061 name = dynamic_strings + entry->d_un.d_val;
19808d3f 2062
ebb64169 2063 if (name)
76466873 2064 {
ebb64169 2065 switch (entry->d_tag)
76466873
NC
2066 {
2067 case DT_NEEDED:
ebb64169 2068 printf (_("Shared library: [%s]"), name);
19808d3f 2069
ebb64169 2070 if (strcmp (name, program_interpreter))
76466873
NC
2071 printf ("\n");
2072 else
2073 printf (_(" program interpreter\n"));
2074 break;
2075
2076 case DT_SONAME:
ebb64169 2077 printf (_("Library soname: [%s]\n"), name);
76466873
NC
2078 break;
2079
2080 case DT_RPATH:
ebb64169 2081 printf (_("Library rpath: [%s]\n"), name);
76466873
NC
2082 break;
2083
2084 default:
cb436f39 2085 printf ("%#lx\n", (long) entry->d_un.d_val);
76466873
NC
2086 }
2087 }
2088 else
cb436f39 2089 printf ("%#lx\n", (long) entry->d_un.d_val);
76466873
NC
2090 }
2091 break;
2092
be5b92f9
CM
2093 case DT_RELASZ :
2094 case DT_RELAENT :
2095 case DT_STRSZ :
2096 case DT_SYMENT :
2097 case DT_RELSZ :
2098 case DT_RELENT :
2099 case DT_VERDEFNUM:
2100 case DT_VERNEEDNUM:
2101 case DT_RELACOUNT:
2102 case DT_RELCOUNT:
e5a32b17
UD
2103 if (do_dynamic)
2104 printf ("%ld\n", entry->d_un.d_val);
be5b92f9
CM
2105 break;
2106
2107 case DT_SYMINSZ :
2108 case DT_SYMINENT:
2109 case DT_SYMINFO :
2110 case DT_USED:
2111 if (do_dynamic)
2112 {
2113 char * name;
2114
2115 if (dynamic_strings == NULL)
2116 name = NULL;
2117 else
2118 name = dynamic_strings + entry->d_un.d_val;
2119
2120
2121
2122 if (name)
2123 {
2124 switch (entry->d_tag)
2125 {
2126 case DT_USED:
2127 printf (_("Not needed object: [%s]\n"), name);
2128 break;
2129
2130 default:
2131 printf ("%#lx\n", (long) entry->d_un.d_val);
2132 }
2133 }
2134 else
2135 printf ("%#lx\n", (long) entry->d_un.d_val);
2136 }
2137 break;
2138
76466873 2139 default:
ebb64169 2140 if ((entry->d_tag >= DT_VERSYM) && (entry->d_tag <= DT_VERNEEDNUM))
76466873 2141 {
ebb64169
NC
2142 version_info [DT_VERSIONTAGIDX (entry->d_tag)] =
2143 entry->d_un.d_val;
76466873
NC
2144
2145 if (do_dynamic)
cb436f39 2146 printf ("%#lx\n", (long) entry->d_un.d_ptr);
76466873 2147 }
5821de31
UD
2148 else
2149 switch (elf_header.e_machine)
2150 {
2151 case EM_MIPS:
2152 case EM_MIPS_RS4_BE:
2153 dynamic_segment_mips_val (entry);
2154 break;
2155 default:
2156 if (do_dynamic)
2157 printf ("%#lx\n", (long) entry->d_un.d_ptr);
2158 }
76466873
NC
2159 break;
2160 }
ebb64169 2161 }
19808d3f 2162
cb436f39 2163 return 1;
ebb64169
NC
2164}
2165
2166static char *
d76c93e6 2167get_ver_flags (flags)
19808d3f 2168 unsigned int flags;
ebb64169
NC
2169{
2170 static char buff [32];
2171
2172 buff[0] = 0;
2173
2174 if (flags == 0)
2175 return _("none");
19808d3f 2176
ebb64169
NC
2177 if (flags & VER_FLG_BASE)
2178 strcat (buff, "BASE ");
2179
2180 if (flags & VER_FLG_WEAK)
2181 {
2182 if (flags & VER_FLG_BASE)
2183 strcat (buff, "| ");
19808d3f 2184
ebb64169 2185 strcat (buff, "WEAK ");
76466873
NC
2186 }
2187
ebb64169
NC
2188 if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK))
2189 strcat (buff, "| <unknown>");
2190
2191 return buff;
2192}
2193
2194/* Display the contents of the version sections. */
cb436f39 2195static int
ebb64169
NC
2196process_version_sections (file)
2197 FILE * file;
2198{
cb436f39 2199 Elf32_Internal_Shdr * section;
ebb64169
NC
2200 unsigned i;
2201 int found = 0;
19808d3f 2202
ebb64169 2203 if (! do_version)
cb436f39 2204 return 1;
19808d3f 2205
ebb64169
NC
2206 for (i = 0, section = section_headers;
2207 i < elf_header.e_shnum;
2208 i++, section ++)
76466873 2209 {
ebb64169 2210 switch (section->sh_type)
76466873 2211 {
ebb64169
NC
2212 case SHT_GNU_verdef:
2213 {
cb436f39
NC
2214 Elf_External_Verdef * edefs;
2215 unsigned int idx;
2216 unsigned int cnt;
19808d3f 2217
cb436f39 2218 found = 1;
19808d3f 2219
cb436f39
NC
2220 printf
2221 (_("\nVersion definition section '%s' contains %d entries:\n"),
2222 SECTION_NAME (section), section->sh_info);
19808d3f 2223
ebb64169
NC
2224 printf (_(" Addr: %#08x Offset: %#08x Link: %x (%s)\n"),
2225 section->sh_addr, section->sh_offset, section->sh_link,
2226 SECTION_NAME (section_headers + section->sh_link));
76466873 2227
ebb64169 2228 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
cb436f39 2229 edefs, Elf_External_Verdef *,
ebb64169 2230 "version definition section");
19808d3f 2231
ebb64169
NC
2232 for (idx = cnt = 0; cnt < section->sh_info; ++ cnt)
2233 {
cb436f39
NC
2234 char * vstart;
2235 Elf_External_Verdef * edef;
2236 Elf_Internal_Verdef ent;
2237 Elf_External_Verdaux * eaux;
2238 Elf_Internal_Verdaux aux;
2239 int j;
2240 int isum;
2241
2242 vstart = ((char *) edefs) + idx;
19808d3f 2243
cb436f39
NC
2244 edef = (Elf_External_Verdef *) vstart;
2245
2246 ent.vd_version = BYTE_GET (edef->vd_version);
2247 ent.vd_flags = BYTE_GET (edef->vd_flags);
2248 ent.vd_ndx = BYTE_GET (edef->vd_ndx);
2249 ent.vd_cnt = BYTE_GET (edef->vd_cnt);
2250 ent.vd_hash = BYTE_GET (edef->vd_hash);
2251 ent.vd_aux = BYTE_GET (edef->vd_aux);
2252 ent.vd_next = BYTE_GET (edef->vd_next);
19808d3f 2253
ebb64169 2254 printf (_(" %#06x: Rev: %d Flags: %s"),
cb436f39 2255 idx, ent.vd_version, get_ver_flags (ent.vd_flags));
19808d3f 2256
cb436f39 2257 printf (_(" Index: %ld Cnt: %ld "), ent.vd_ndx, ent.vd_cnt);
ebb64169 2258
cb436f39 2259 vstart += ent.vd_aux;
19808d3f 2260
cb436f39 2261 eaux = (Elf_External_Verdaux *) vstart;
19808d3f 2262
cb436f39
NC
2263 aux.vda_name = BYTE_GET (eaux->vda_name);
2264 aux.vda_next = BYTE_GET (eaux->vda_next);
19808d3f 2265
ebb64169 2266 if (dynamic_strings)
cb436f39 2267 printf (_("Name: %s\n"), dynamic_strings + aux.vda_name);
ebb64169 2268 else
cb436f39 2269 printf (_("Name index: %ld\n"), aux.vda_name);
19808d3f 2270
cb436f39 2271 isum = idx + ent.vd_aux;
19808d3f 2272
cb436f39 2273 for (j = 1; j < ent.vd_cnt; j ++)
ebb64169 2274 {
cb436f39
NC
2275 isum += aux.vda_next;
2276 vstart += aux.vda_next;
19808d3f 2277
cb436f39 2278 eaux = (Elf_External_Verdaux *) vstart;
19808d3f 2279
cb436f39
NC
2280 aux.vda_name = BYTE_GET (eaux->vda_name);
2281 aux.vda_next = BYTE_GET (eaux->vda_next);
19808d3f 2282
ebb64169
NC
2283 if (dynamic_strings)
2284 printf (_(" %#06x: Parent %d: %s\n"),
cb436f39 2285 isum, j, dynamic_strings + aux.vda_name);
ebb64169 2286 else
cb436f39
NC
2287 printf (_(" %#06x: Parent %d, name index: %ld\n"),
2288 isum, j, aux.vda_name);
ebb64169
NC
2289 }
2290
cb436f39 2291 idx += ent.vd_next;
ebb64169 2292 }
19808d3f 2293
cb436f39 2294 free (edefs);
ebb64169
NC
2295 }
2296 break;
19808d3f 2297
ebb64169
NC
2298 case SHT_GNU_verneed:
2299 {
cb436f39
NC
2300 Elf_External_Verneed * eneed;
2301 unsigned int idx;
2302 unsigned int cnt;
19808d3f 2303
ebb64169 2304 found = 1;
19808d3f 2305
ebb64169
NC
2306 printf (_("\nVersion needs section '%s' contains %d entries:\n"),
2307 SECTION_NAME (section), section->sh_info);
19808d3f 2308
cb436f39
NC
2309 printf
2310 (_(" Addr: %#08x Offset: %#08x Link to section: %d (%s)\n"),
2311 section->sh_addr, section->sh_offset, section->sh_link,
2312 SECTION_NAME (section_headers + section->sh_link));
ebb64169
NC
2313
2314 GET_DATA_ALLOC (section->sh_offset, section->sh_size,
cb436f39 2315 eneed, Elf_External_Verneed *,
ebb64169 2316 "version need section");
19808d3f 2317
ebb64169
NC
2318 for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
2319 {
cb436f39
NC
2320 Elf_External_Verneed * entry;
2321 Elf_Internal_Verneed ent;
2322 int j;
2323 int isum;
2324 char * vstart;
19808d3f 2325
cb436f39 2326 vstart = ((char *) eneed) + idx;
19808d3f 2327
cb436f39 2328 entry = (Elf_External_Verneed *) vstart;
19808d3f 2329
cb436f39
NC
2330 ent.vn_version = BYTE_GET (entry->vn_version);
2331 ent.vn_cnt = BYTE_GET (entry->vn_cnt);
2332 ent.vn_file = BYTE_GET (entry->vn_file);
2333 ent.vn_aux = BYTE_GET (entry->vn_aux);
2334 ent.vn_next = BYTE_GET (entry->vn_next);
19808d3f 2335
cb436f39 2336 printf (_(" %#06x: Version: %d"), idx, ent.vn_version);
ebb64169
NC
2337
2338 if (dynamic_strings)
cb436f39 2339 printf (_(" File: %s"), dynamic_strings + ent.vn_file);
ebb64169 2340 else
cb436f39 2341 printf (_(" File: %lx"), ent.vn_file);
19808d3f 2342
cb436f39
NC
2343 printf (_(" Cnt: %d\n"), ent.vn_cnt);
2344
2345 vstart += ent.vn_aux;
19808d3f 2346
cb436f39 2347 for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j)
ebb64169 2348 {
cb436f39
NC
2349 Elf_External_Vernaux * eaux;
2350 Elf_Internal_Vernaux aux;
19808d3f 2351
cb436f39 2352 eaux = (Elf_External_Vernaux *) vstart;
19808d3f 2353
cb436f39
NC
2354 aux.vna_hash = BYTE_GET (eaux->vna_hash);
2355 aux.vna_flags = BYTE_GET (eaux->vna_flags);
2356 aux.vna_other = BYTE_GET (eaux->vna_other);
2357 aux.vna_name = BYTE_GET (eaux->vna_name);
2358 aux.vna_next = BYTE_GET (eaux->vna_next);
ebb64169
NC
2359
2360 if (dynamic_strings)
2361 printf (_(" %#06x: Name: %s"),
cb436f39 2362 isum, dynamic_strings + aux.vna_name);
ebb64169 2363 else
cb436f39
NC
2364 printf (_(" %#06x: Name index: %lx"),
2365 isum, aux.vna_name);
19808d3f 2366
ebb64169 2367 printf (_(" Flags: %s Version: %d\n"),
cb436f39 2368 get_ver_flags (aux.vna_flags), aux.vna_other);
19808d3f 2369
cb436f39
NC
2370 isum += aux.vna_next;
2371 vstart += aux.vna_next;
ebb64169 2372 }
19808d3f 2373
cb436f39 2374 idx += ent.vn_next;
ebb64169 2375 }
cb436f39
NC
2376
2377 free (eneed);
ebb64169
NC
2378 }
2379 break;
19808d3f 2380
ebb64169
NC
2381 case SHT_GNU_versym:
2382 {
cb436f39
NC
2383 Elf32_Internal_Shdr * link_section;
2384 int total;
2385 int cnt;
2386 unsigned char * edata;
2387 unsigned short * data;
2388 char * strtab;
2389 Elf_Internal_Sym * symbols;
2390 Elf32_Internal_Shdr * string_sec;
2391
2392 link_section = section_headers + section->sh_link;
2393 total = section->sh_size / section->sh_entsize;
19808d3f 2394
ebb64169
NC
2395 found = 1;
2396
cb436f39
NC
2397 symbols = get_elf_symbols
2398 (file, link_section->sh_offset,
2399 link_section->sh_size / link_section->sh_entsize);
19808d3f 2400
ebb64169
NC
2401 string_sec = section_headers + link_section->sh_link;
2402
2403 GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
2404 strtab, char *, "version string table");
19808d3f 2405
ebb64169
NC
2406 printf (_("\nVersion symbols section '%s' contains %d entries:\n"),
2407 SECTION_NAME (section), total);
19808d3f 2408
ebb64169
NC
2409 printf (_(" Addr: %#08x Offset: %#08x Link: %x (%s)\n"),
2410 section->sh_addr, section->sh_offset, section->sh_link,
2411 SECTION_NAME (link_section));
2412
cb436f39
NC
2413 GET_DATA_ALLOC (version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
2414 - loadaddr,
2415 total * sizeof (short), edata,
2416 char *, "version symbol data");
ebb64169 2417
cb436f39 2418 data = (unsigned short *) malloc (total * sizeof (short));
19808d3f 2419
cb436f39
NC
2420 for (cnt = total; cnt --;)
2421 data [cnt] = byte_get (edata + cnt * sizeof (short), sizeof (short));
2422
2423 free (edata);
19808d3f 2424
ebb64169
NC
2425 for (cnt = 0; cnt < total; cnt += 4)
2426 {
2427 int j, nn;
19808d3f 2428
ebb64169 2429 printf (" %03x:", cnt);
19808d3f 2430
ebb64169 2431 for (j = 0; (j < 4) && (cnt + j) < total; ++j)
cb436f39 2432 switch (data [cnt + j])
ebb64169
NC
2433 {
2434 case 0:
19808d3f 2435 fputs (_(" 0 (*local*) "), stdout);
ebb64169 2436 break;
19808d3f 2437
ebb64169 2438 case 1:
19808d3f 2439 fputs (_(" 1 (*global*) "), stdout);
ebb64169 2440 break;
19808d3f 2441
ebb64169 2442 default:
cb436f39
NC
2443 nn = printf ("%4x%c", data [cnt + j] & 0x7fff,
2444 data [cnt + j] & 0x8000 ? 'h' : ' ');
ebb64169
NC
2445
2446 if (symbols [cnt + j].st_shndx < SHN_LORESERVE
2447 && section_headers[symbols [cnt + j].st_shndx].sh_type
2448 == SHT_NOBITS)
2449 {
2450 /* We must test both. */
cb436f39
NC
2451 Elf_Internal_Verneed ivn;
2452 unsigned long offset;
ebb64169
NC
2453
2454 offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
2455 - loadaddr;
19808d3f 2456
ebb64169
NC
2457 do
2458 {
cb436f39
NC
2459 Elf_External_Verneed evn;
2460 Elf_External_Vernaux evna;
2461 Elf_Internal_Vernaux ivna;
2462 unsigned long vna_off;
ebb64169 2463
cb436f39 2464 GET_DATA (offset, evn, "version need");
ebb64169 2465
cb436f39
NC
2466 ivn.vn_aux = BYTE_GET (evn.vn_aux);
2467 ivn.vn_next = BYTE_GET (evn.vn_next);
19808d3f 2468
cb436f39 2469 vna_off = offset + ivn.vn_aux;
ebb64169
NC
2470
2471 do
2472 {
cb436f39 2473 GET_DATA (vna_off, evna,
ebb64169
NC
2474 "version need aux (1)");
2475
cb436f39
NC
2476 ivna.vna_next = BYTE_GET (evna.vna_next);
2477 ivna.vna_other = BYTE_GET (evna.vna_other);
19808d3f 2478
cb436f39 2479 vna_off += ivna.vna_next;
ebb64169 2480 }
cb436f39
NC
2481 while (ivna.vna_other != data [cnt + j]
2482 && ivna.vna_next != 0);
19808d3f 2483
cb436f39 2484 if (ivna.vna_other == data [cnt + j])
ebb64169 2485 {
cb436f39 2486 ivna.vna_name = BYTE_GET (evna.vna_name);
19808d3f
UD
2487
2488 nn += printf ("(%s%-*s",
2489 strtab + ivna.vna_name,
2490 12 - strlen (strtab
2491 + ivna.vna_name),
2492 ")");
ebb64169
NC
2493 break;
2494 }
cb436f39 2495 else if (ivn.vn_next == 0)
ebb64169 2496 {
cb436f39 2497 if (data [cnt + j] != 0x8001)
ebb64169 2498 {
cb436f39
NC
2499 Elf_Internal_Verdef ivd;
2500 Elf_External_Verdef evd;
ebb64169
NC
2501
2502 offset = version_info
2503 [DT_VERSIONTAGIDX (DT_VERDEF)]
2504 - loadaddr;
19808d3f 2505
ebb64169
NC
2506 do
2507 {
cb436f39 2508 GET_DATA (offset, evd,
ebb64169
NC
2509 "version definition");
2510
cb436f39
NC
2511 ivd.vd_next = BYTE_GET (evd.vd_next);
2512 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
19808d3f 2513
cb436f39 2514 offset += ivd.vd_next;
ebb64169 2515 }
cb436f39
NC
2516 while (ivd.vd_ndx
2517 != (data [cnt + j] & 0x7fff)
2518 && ivd.vd_next != 0);
ebb64169 2519
cb436f39
NC
2520 if (ivd.vd_ndx
2521 == (data [cnt + j] & 0x7fff))
ebb64169 2522 {
cb436f39
NC
2523 Elf_External_Verdaux evda;
2524 Elf_Internal_Verdaux ivda;
19808d3f 2525
cb436f39 2526 ivd.vd_aux = BYTE_GET (evd.vd_aux);
ebb64169 2527
cb436f39 2528 GET_DATA (offset + ivd.vd_aux, evda,
ebb64169 2529 "version definition aux");
19808d3f 2530
cb436f39
NC
2531 ivda.vda_name =
2532 BYTE_GET (evda.vda_name);
19808d3f 2533
cb436f39 2534 nn +=
19808d3f
UD
2535 printf ("(%s%-*s",
2536 strtab + ivda.vda_name,
2537 12
2538 - strlen (strtab
2539 + ivda.vda_name),
2540 ")");
ebb64169
NC
2541 }
2542 }
19808d3f 2543
ebb64169
NC
2544 break;
2545 }
2546 else
cb436f39 2547 offset += ivn.vn_next;
ebb64169 2548 }
cb436f39 2549 while (ivn.vn_next);
ebb64169
NC
2550 }
2551 else if (symbols [cnt + j].st_shndx == SHN_UNDEF)
2552 {
cb436f39
NC
2553 Elf_Internal_Verneed ivn;
2554 unsigned long offset;
19808d3f 2555
ebb64169
NC
2556 offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
2557 - loadaddr;
2558
2559 do
2560 {
cb436f39
NC
2561 Elf_Internal_Vernaux ivna;
2562 Elf_External_Verneed evn;
2563 Elf_External_Vernaux evna;
2564 unsigned long a_off;
ebb64169 2565
cb436f39 2566 GET_DATA (offset, evn, "version need");
ebb64169 2567
cb436f39
NC
2568 ivn.vn_aux = BYTE_GET (evn.vn_aux);
2569 ivn.vn_next = BYTE_GET (evn.vn_next);
19808d3f 2570
cb436f39 2571 a_off = offset + ivn.vn_aux;
19808d3f 2572
ebb64169
NC
2573 do
2574 {
cb436f39
NC
2575 GET_DATA (a_off, evna,
2576 "version need aux (2)");
2577
2578 ivna.vna_next = BYTE_GET (evna.vna_next);
2579 ivna.vna_other = BYTE_GET (evna.vna_other);
19808d3f 2580
cb436f39 2581 a_off += ivna.vna_next;
ebb64169 2582 }
cb436f39
NC
2583 while (ivna.vna_other != data [cnt + j]
2584 && ivna.vna_next != 0);
19808d3f 2585
cb436f39 2586 if (ivna.vna_other == data [cnt + j])
ebb64169 2587 {
cb436f39 2588 ivna.vna_name = BYTE_GET (evna.vna_name);
19808d3f
UD
2589
2590 nn += printf ("(%s%-*s",
2591 strtab + ivna.vna_name,
2592 12 - strlen (strtab
2593 + ivna.vna_name),
2594 ")");
ebb64169
NC
2595 break;
2596 }
2597
cb436f39 2598 offset += ivn.vn_next;
ebb64169 2599 }
cb436f39 2600 while (ivn.vn_next);
ebb64169 2601 }
cb436f39 2602 else if (data [cnt + j] != 0x8001)
ebb64169 2603 {
cb436f39
NC
2604 Elf_Internal_Verdef ivd;
2605 Elf_External_Verdef evd;
2606 unsigned long offset;
19808d3f 2607
cb436f39
NC
2608 offset = version_info
2609 [DT_VERSIONTAGIDX (DT_VERDEF)] - loadaddr;
19808d3f 2610
cb436f39 2611 do
ebb64169 2612 {
cb436f39 2613 GET_DATA (offset, evd, "version def");
ebb64169 2614
cb436f39
NC
2615 ivd.vd_next = BYTE_GET (evd.vd_next);
2616 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
19808d3f 2617
cb436f39
NC
2618 offset += ivd.vd_next;
2619 }
2620 while (ivd.vd_ndx != (data [cnt + j] & 0x7fff)
2621 && ivd.vd_next != 0);
19808d3f 2622
cb436f39
NC
2623 if (ivd.vd_ndx == (data [cnt + j] & 0x7fff))
2624 {
2625 Elf_External_Verdaux evda;
2626 Elf_Internal_Verdaux ivda;
19808d3f 2627
cb436f39 2628 ivd.vd_aux = BYTE_GET (evd.vd_aux);
19808d3f 2629
cb436f39
NC
2630 GET_DATA (offset - ivd.vd_next + ivd.vd_aux,
2631 evda, "version def aux");
19808d3f 2632
cb436f39 2633 ivda.vda_name = BYTE_GET (evda.vda_name);
19808d3f
UD
2634
2635 nn += printf ("(%s%-*s",
2636 strtab + ivda.vda_name,
2637 12 - strlen (strtab
2638 + ivda.vda_name),
2639 ")");
ebb64169
NC
2640 }
2641 }
19808d3f 2642
ebb64169
NC
2643 if (nn < 18)
2644 printf ("%*c", 18 - nn, ' ');
2645 }
19808d3f 2646
ebb64169
NC
2647 putchar ('\n');
2648 }
2649
cb436f39 2650 free (data);
ebb64169
NC
2651 free (strtab);
2652 free (symbols);
2653 }
2654 break;
19808d3f 2655
ebb64169 2656 default:
4775a8a5 2657 break;
76466873
NC
2658 }
2659 }
19808d3f 2660
ebb64169
NC
2661 if (! found)
2662 printf (_("\nNo version information found in this file.\n"));
cb436f39
NC
2663
2664 return 1;
ebb64169
NC
2665}
2666
2667static char *
2668get_symbol_binding (binding)
2669 unsigned int binding;
2670{
2671 static char buff [32];
19808d3f 2672
ebb64169
NC
2673 switch (binding)
2674 {
2675 case STB_LOCAL: return _("LOCAL");
2676 case STB_GLOBAL: return _("GLOBAL");
2677 case STB_WEAK: return _("WEAK");
2678 default:
2679 if (binding >= STB_LOPROC && binding <= STB_HIPROC)
2680 sprintf (buff, _("<processor specific>: %d"), binding);
2681 else
2682 sprintf (buff, _("<unknown>: %d"), binding);
2683 return buff;
2684 }
2685}
2686
2687static char *
2688get_symbol_type (type)
2689 unsigned int type;
2690{
2691 static char buff [32];
19808d3f 2692
ebb64169
NC
2693 switch (type)
2694 {
2695 case STT_NOTYPE: return _("NOTYPE");
2696 case STT_OBJECT: return _("OBJECT");
2697 case STT_FUNC: return _("FUNC");
2698 case STT_SECTION: return _("SECTION");
2699 case STT_FILE: return _("FILE");
2700 default:
2701 if (type >= STT_LOPROC && type <= STT_HIPROC)
2702 sprintf (buff, _("<processor specific>: %d"), type);
2703 else
2704 sprintf (buff, _("<unknown>: %d"), type);
2705 return buff;
2706 }
2707}
2708
2709static char *
2710get_symbol_index_type (type)
19808d3f 2711 unsigned int type;
ebb64169
NC
2712{
2713 switch (type)
2714 {
2715 case SHN_UNDEF: return "UND";
2716 case SHN_ABS: return "ABS";
2717 case SHN_COMMON: return "COM";
2718 default:
2719 if (type >= SHN_LOPROC && type <= SHN_HIPROC)
2720 return "PRC";
2721 else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE)
2722 return "RSV";
2723 else
2724 {
2725 static char buff [32];
19808d3f 2726
ebb64169
NC
2727 sprintf (buff, "%3d", type);
2728 return buff;
2729 }
2730 }
76466873
NC
2731}
2732
ebb64169 2733
cb436f39
NC
2734static int *
2735get_dynamic_data (file, number)
2736 FILE * file;
2737 unsigned int number;
2738{
2739 char * e_data;
2740 int * i_data;
19808d3f 2741
cb436f39 2742 e_data = (char *) malloc (number * 4);
19808d3f 2743
cb436f39
NC
2744 if (e_data == NULL)
2745 {
2746 error (_("Out of memory\n"));
2747 return NULL;
2748 }
19808d3f 2749
cb436f39
NC
2750 if (fread (e_data, 4, number, file) != number)
2751 {
2752 error (_("Unable to read in dynamic data\n"));
2753 return NULL;
2754 }
19808d3f 2755
cb436f39
NC
2756 i_data = (int *) malloc (number * sizeof (* i_data));
2757
2758 if (i_data == NULL)
2759 {
2760 error (_("Out of memory\n"));
2761 free (e_data);
2762 return NULL;
2763 }
19808d3f 2764
cb436f39
NC
2765 while (number--)
2766 i_data [number] = byte_get (e_data + number * 4, 4);
19808d3f 2767
cb436f39
NC
2768 free (e_data);
2769
2770 return i_data;
2771}
2772
76466873 2773/* Dump the symbol table */
cb436f39 2774static int
ebb64169
NC
2775process_symbol_table (file)
2776 FILE * file;
76466873 2777{
cb436f39 2778 Elf32_Internal_Shdr * section;
e5a32b17
UD
2779 char nb [4];
2780 char nc [4];
2781 int nbuckets;
2782 int nchains;
2783 int * buckets = NULL;
2784 int * chains = NULL;
2785
2786 if (! do_syms && !do_histogram)
cb436f39 2787 return 1;
19808d3f 2788
e5a32b17
UD
2789 if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL)
2790 || do_histogram))
76466873 2791 {
be5b92f9 2792 if (fseek (file, dynamic_info[DT_HASH] - loadaddr, SEEK_SET))
ebb64169
NC
2793 {
2794 error (_("Unable to seek to start of dynamic information"));
cb436f39 2795 return 0;
ebb64169
NC
2796 }
2797
cb436f39 2798 if (fread (& nb, sizeof (nb), 1, file) != 1)
ebb64169
NC
2799 {
2800 error (_("Failed to read in number of buckets\n"));
cb436f39 2801 return 0;
ebb64169 2802 }
19808d3f 2803
cb436f39 2804 if (fread (& nc, sizeof (nc), 1, file) != 1)
ebb64169
NC
2805 {
2806 error (_("Failed to read in number of chains\n"));
cb436f39 2807 return 0;
ebb64169
NC
2808 }
2809
cb436f39
NC
2810 nbuckets = byte_get (nb, 4);
2811 nchains = byte_get (nc, 4);
19808d3f 2812
cb436f39
NC
2813 buckets = get_dynamic_data (file, nbuckets);
2814 chains = get_dynamic_data (file, nchains);
ebb64169 2815
cb436f39
NC
2816 if (buckets == NULL || chains == NULL)
2817 return 0;
e5a32b17
UD
2818 }
2819
2820 if (do_syms
2821 && dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL)
2822 {
2823 int hn;
2824 int si;
19808d3f 2825
ebb64169 2826 printf (_("\nSymbol table for image:\n"));
76466873 2827 printf (_(" Num Buc: Value Size Type Bind Ot Ndx Name\n"));
19808d3f 2828
ebb64169 2829 for (hn = 0; hn < nbuckets; hn++)
76466873 2830 {
ebb64169 2831 if (! buckets [hn])
76466873 2832 continue;
19808d3f 2833
ebb64169 2834 for (si = buckets [hn]; si; si = chains [si])
76466873 2835 {
cb436f39 2836 Elf_Internal_Sym * psym;
ebb64169
NC
2837
2838 psym = dynamic_symbols + si;
19808d3f 2839
cb436f39
NC
2840 printf (" %3d %3d: %8lx %5ld %6s %6s %2d ",
2841 si, hn,
2842 (unsigned long) psym->st_value,
2843 (unsigned long) psym->st_size,
ebb64169
NC
2844 get_symbol_type (ELF_ST_TYPE (psym->st_info)),
2845 get_symbol_binding (ELF_ST_BIND (psym->st_info)),
2846 psym->st_other);
2847
2848 printf ("%3.3s", get_symbol_index_type (psym->st_shndx));
19808d3f 2849
ebb64169 2850 printf (" %s\n", dynamic_strings + psym->st_name);
76466873
NC
2851 }
2852 }
2853 }
e5a32b17 2854 else if (do_syms && !do_using_dynamic)
76466873 2855 {
ebb64169 2856 unsigned int i;
19808d3f 2857
ebb64169
NC
2858 for (i = 0, section = section_headers;
2859 i < elf_header.e_shnum;
2860 i++, section++)
76466873 2861 {
cb436f39
NC
2862 unsigned int si;
2863 char * strtab;
2864 Elf_Internal_Sym * symtab;
2865 Elf_Internal_Sym * psym;
ebb64169 2866
19808d3f 2867
ebb64169
NC
2868 if ( section->sh_type != SHT_SYMTAB
2869 && section->sh_type != SHT_DYNSYM)
76466873 2870 continue;
19808d3f 2871
ebb64169
NC
2872 printf (_("\nSymbol table '%s' contains %d entries:\n"),
2873 SECTION_NAME (section),
2874 section->sh_size / section->sh_entsize);
5892b099 2875 fputs (_(" Num: Value Size Type Bind Ot Ndx Name\n"),
19808d3f 2876 stdout);
76466873 2877
cb436f39
NC
2878 symtab = get_elf_symbols (file, section->sh_offset,
2879 section->sh_size / section->sh_entsize);
2880 if (symtab == NULL)
2881 continue;
19808d3f 2882
ebb64169
NC
2883 if (section->sh_link == elf_header.e_shstrndx)
2884 strtab = string_table;
2885 else
2886 {
cb436f39 2887 Elf32_Internal_Shdr * string_sec;
19808d3f 2888
cb436f39 2889 string_sec = section_headers + section->sh_link;
19808d3f 2890
ebb64169
NC
2891 GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
2892 strtab, char *, "string table");
2893 }
19808d3f 2894
ebb64169
NC
2895 for (si = 0, psym = symtab;
2896 si < section->sh_size / section->sh_entsize;
2897 si ++, psym ++)
2898 {
cb436f39
NC
2899 printf (" %3d: %8lx %5ld %-7s %-6s %2d ",
2900 si,
2901 (unsigned long) psym->st_value,
2902 (unsigned long) psym->st_size,
ebb64169
NC
2903 get_symbol_type (ELF_ST_TYPE (psym->st_info)),
2904 get_symbol_binding (ELF_ST_BIND (psym->st_info)),
76466873 2905 psym->st_other);
19808d3f 2906
76466873 2907 if (psym->st_shndx == 0)
5892b099 2908 fputs (" UND", stdout);
76466873 2909 else if ((psym->st_shndx & 0xffff) == 0xfff1)
5892b099 2910 fputs (" ABS", stdout);
76466873 2911 else if ((psym->st_shndx & 0xffff) == 0xfff2)
5892b099 2912 fputs (" COM", stdout);
76466873 2913 else
5892b099 2914 printf ("%4x", psym->st_shndx);
19808d3f 2915
ebb64169 2916 printf (" %s", strtab + psym->st_name);
19808d3f 2917
ebb64169
NC
2918 if (section->sh_type == SHT_DYNSYM &&
2919 version_info [DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
76466873 2920 {
cb436f39 2921 unsigned char data[2];
ebb64169
NC
2922 unsigned short vers_data;
2923 unsigned long offset;
2924 int is_nobits;
2925 int check_def;
19808d3f 2926
ebb64169
NC
2927 offset = version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
2928 - loadaddr;
2929
cb436f39 2930 GET_DATA (offset + si * sizeof (vers_data), data,
ebb64169
NC
2931 "version data");
2932
cb436f39 2933 vers_data = byte_get (data, 2);
ebb64169
NC
2934
2935 is_nobits = psym->st_shndx < SHN_LORESERVE ?
2936 (section_headers [psym->st_shndx].sh_type == SHT_NOBITS)
2937 : 0;
19808d3f 2938
ebb64169 2939 check_def = (psym->st_shndx != SHN_UNDEF);
19808d3f 2940
ebb64169 2941 if ((vers_data & 0x8000) || vers_data > 1)
76466873 2942 {
ebb64169 2943 if (is_nobits || ! check_def)
76466873 2944 {
cb436f39
NC
2945 Elf_External_Verneed evn;
2946 Elf_Internal_Verneed ivn;
2947 Elf_Internal_Vernaux ivna;
19808d3f 2948
ebb64169
NC
2949 /* We must test both. */
2950 offset = version_info
2951 [DT_VERSIONTAGIDX (DT_VERNEED)] - loadaddr;
2952
cb436f39 2953 GET_DATA (offset, evn, "version need");
76466873 2954
cb436f39
NC
2955 ivn.vn_aux = BYTE_GET (evn.vn_aux);
2956 ivn.vn_next = BYTE_GET (evn.vn_next);
19808d3f 2957
ebb64169
NC
2958 do
2959 {
2960 unsigned long vna_off;
19808d3f 2961
cb436f39 2962 vna_off = offset + ivn.vn_aux;
ebb64169
NC
2963
2964 do
2965 {
cb436f39 2966 Elf_External_Vernaux evna;
19808d3f 2967
cb436f39 2968 GET_DATA (vna_off, evna,
ebb64169
NC
2969 "version need aux (3)");
2970
cb436f39
NC
2971 ivna.vna_other = BYTE_GET (evna.vna_other);
2972 ivna.vna_next = BYTE_GET (evna.vna_next);
19808d3f 2973 ivna.vna_name = BYTE_GET (evna.vna_name);
ebb64169 2974
cb436f39 2975 vna_off += ivna.vna_next;
ebb64169 2976 }
cb436f39
NC
2977 while (ivna.vna_other != vers_data
2978 && ivna.vna_next != 0);
19808d3f 2979
cb436f39 2980 if (ivna.vna_other == vers_data)
ebb64169 2981 break;
19808d3f 2982
cb436f39 2983 offset += ivn.vn_next;
76466873 2984 }
cb436f39 2985 while (ivn.vn_next != 0);
19808d3f 2986
cb436f39 2987 if (ivna.vna_other == vers_data)
19808d3f
UD
2988 {
2989 printf ("@%s (%d)",
2990 strtab + ivna.vna_name, ivna.vna_other);
2991 check_def = 0;
2992 }
ebb64169
NC
2993 else if (! is_nobits)
2994 error (_("bad dynamic symbol"));
2995 else
2996 check_def = 1;
76466873 2997 }
19808d3f 2998
ebb64169 2999 if (check_def)
76466873 3000 {
ebb64169
NC
3001 if (vers_data != 0x8001)
3002 {
cb436f39
NC
3003 Elf_Internal_Verdef ivd;
3004 Elf_Internal_Verdaux ivda;
3005 Elf_External_Verdaux evda;
3006 unsigned long offset;
ebb64169
NC
3007
3008 offset =
3009 version_info [DT_VERSIONTAGIDX (DT_VERDEF)]
3010 - loadaddr;
3011
3012 do
3013 {
cb436f39 3014 Elf_External_Verdef evd;
19808d3f 3015
cb436f39 3016 GET_DATA (offset, evd, "version def");
ebb64169 3017
cb436f39
NC
3018 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
3019 ivd.vd_aux = BYTE_GET (evd.vd_aux);
3020 ivd.vd_next = BYTE_GET (evd.vd_next);
19808d3f 3021
cb436f39 3022 offset += ivd.vd_next;
ebb64169 3023 }
cb436f39
NC
3024 while (ivd.vd_ndx != (vers_data & 0x7fff)
3025 && ivd.vd_next != 0);
ebb64169 3026
cb436f39
NC
3027 offset -= ivd.vd_next;
3028 offset += ivd.vd_aux;
ebb64169 3029
cb436f39 3030 GET_DATA (offset, evda, "version def aux");
19808d3f 3031
cb436f39 3032 ivda.vda_name = BYTE_GET (evda.vda_name);
19808d3f 3033
cb436f39 3034 if (psym->st_name != ivda.vda_name)
ebb64169
NC
3035 printf ((vers_data & 0x8000)
3036 ? "@%s" : "@@%s",
cb436f39 3037 strtab + ivda.vda_name);
ebb64169 3038 }
76466873 3039 }
76466873
NC
3040 }
3041 }
19808d3f 3042
ebb64169 3043 putchar ('\n');
76466873 3044 }
76466873 3045
ebb64169
NC
3046 free (symtab);
3047 if (strtab != string_table)
3048 free (strtab);
76466873
NC
3049 }
3050 }
e5a32b17 3051 else if (do_syms)
ebb64169
NC
3052 printf
3053 (_("\nDynamic symbol information is not available for displaying symbols.\n"));
cb436f39 3054
e5a32b17
UD
3055 if (do_histogram)
3056 {
3057 int *lengths;
3058 int *counts;
3059 int hn;
3060 int si;
3061 int maxlength = 0;
3062
3063 printf (_("\nHistogram for bucket list length (total of %d buckets):\n"),
3064 nbuckets);
3065 printf (_(" Length Number\n"));
3066
3067 lengths = (int *) calloc (nbuckets, sizeof (int));
3068 if (lengths == NULL)
3069 {
3070 error (_("Out of memory"));
3071 return 0;
3072 }
3073 for (hn = 0; hn < nbuckets; ++hn)
3074 {
3075 if (! buckets [hn])
3076 continue;
3077
3078 for (si = buckets[hn]; si; si = chains[si])
3079 if (maxlength < ++lengths[hn])
3080 maxlength = lengths[hn];
3081 }
3082
3083 counts = (int *) calloc (maxlength + 1, sizeof (int));
3084 if (counts == NULL)
3085 {
3086 error (_("Out of memory"));
3087 return 0;
3088 }
3089
3090 for (hn = 0; hn < nbuckets; ++hn)
3091 ++counts[lengths[hn]];
3092
3093 for (si = 0; si <= maxlength; ++si)
3094 printf ("%7d %-10d (%5.1f%%)\n",
3095 si, counts[si], (counts[si] * 100.0) / nbuckets);
3096
3097 free (counts);
3098 free (lengths);
3099 }
3100
3101 if (buckets != NULL)
3102 {
3103 free (buckets);
3104 free (chains);
3105 }
3106
cb436f39 3107 return 1;
76466873
NC
3108}
3109
fdf959dd
UD
3110static int
3111process_syminfo (file)
3112 FILE * file;
3113{
3114 int i;
3115
3116 if (dynamic_syminfo == NULL
3117 || !do_dynamic)
3118 /* No syminfo, this is ok. */
3119 return 1;
3120
3121 /* There better should be a dynamic symbol section. */
3122 if (dynamic_symbols == NULL || dynamic_strings == NULL)
3123 return 0;
3124
3125 if (dynamic_addr)
3126 printf (_("\nDynamic info segment at offset 0x%x contains %d entries:\n"),
3127 dynamic_syminfo_offset, dynamic_syminfo_nent);
3128
7c71c3ea 3129 printf (_(" Num: Name BoundTo Flags\n"));
fdf959dd
UD
3130 for (i = 0; i < dynamic_syminfo_nent; ++i)
3131 {
3132 unsigned short int flags = dynamic_syminfo[i].si_flags;
3133
7c71c3ea 3134 printf ("%4d: %-30s ", i,
fdf959dd
UD
3135 dynamic_strings + dynamic_symbols[i].st_name);
3136
3137 switch (dynamic_syminfo[i].si_boundto)
3138 {
3139 case SYMINFO_BT_SELF:
7c71c3ea 3140 fputs ("SELF ", stdout);
fdf959dd
UD
3141 break;
3142 case SYMINFO_BT_PARENT:
7c71c3ea 3143 fputs ("PARENT ", stdout);
fdf959dd
UD
3144 break;
3145 default:
7c71c3ea
UD
3146 if (dynamic_syminfo[i].si_boundto > 0
3147 && dynamic_syminfo[i].si_boundto < dynamic_size)
3148 printf ("%-10s ",
3149 dynamic_strings
3150 + dynamic_segment[dynamic_syminfo[i].si_boundto].d_un.d_val);
3151 else
3152 printf ("%-10d ", dynamic_syminfo[i].si_boundto);
fdf959dd
UD
3153 break;
3154 }
3155
3156 if (flags & SYMINFO_FLG_DIRECT)
3157 printf (" DIRECT");
3158 if (flags & SYMINFO_FLG_PASSTHRU)
3159 printf (" PASSTHRU");
3160 if (flags & SYMINFO_FLG_COPY)
3161 printf (" COPY");
3162 if (flags & SYMINFO_FLG_LAZYLOAD)
3163 printf (" LAZYLOAD");
3164
3165 puts ("");
3166 }
3167
3168 return 1;
3169}
3170
cb436f39 3171static int
ebb64169
NC
3172process_section_contents (file)
3173 FILE * file;
76466873 3174{
cb436f39 3175 Elf32_Internal_Shdr * section;
ebb64169 3176 unsigned int i;
76466873
NC
3177
3178 if (! do_dump)
cb436f39 3179 return 1;
76466873 3180
ebb64169
NC
3181 for (i = 0, section = section_headers;
3182 i < elf_header.e_shnum;
3183 i ++, section ++)
76466873 3184 {
76466873
NC
3185#ifdef SUPPORT_DISASSEMBLY
3186 /* See if we need an assembly dump of this section */
19808d3f 3187
76466873
NC
3188 if ((i < NUM_DUMP_SECTS) && (dump_sects[i] & DISASS_DUMP))
3189 {
ebb64169
NC
3190 printf (_("\nAssembly dump of section %s\n"),
3191 SECTION_NAME (section));
19808d3f 3192
ebb64169
NC
3193 /* XXX -- to be done --- XXX */
3194 }
3195#endif
3196 /* See if we need a hex dump of this section. */
3197 if ((i < NUM_DUMP_SECTS) && (dump_sects[i] & HEX_DUMP))
3198 {
cb436f39
NC
3199 int bytes;
3200 int addr;
ebb64169 3201 unsigned char * data;
cb436f39 3202 char * start;
19808d3f 3203
ebb64169 3204 bytes = section->sh_size;
c80944f2
NC
3205
3206 if (bytes == 0)
3207 {
3208 printf (_("\nSection %d has no data to dump.\n"), i);
3209 continue;
3210 }
3211 else
3212 printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section));
3213
ebb64169
NC
3214 addr = section->sh_addr;
3215
3216 GET_DATA_ALLOC (section->sh_offset, bytes, start, char *,
3217 "section data");
3218
3219 data = start;
19808d3f 3220
ebb64169 3221 while (bytes)
76466873 3222 {
ebb64169
NC
3223 int j;
3224 int k;
3225 int lbytes;
19808d3f 3226
ebb64169 3227 lbytes = (bytes > 16 ? 16 : bytes);
19808d3f 3228
ebb64169 3229 printf (" 0x%8.8x ", addr);
19808d3f 3230
ebb64169 3231 switch (elf_header.e_ident [EI_DATA])
76466873 3232 {
ebb64169
NC
3233 case ELFDATA2LSB:
3234 for (j = 15; j >= 0; j --)
3235 {
3236 if (j < lbytes)
3237 printf ("%2.2x", data [j]);
3238 else
3239 printf (" ");
19808d3f 3240
ebb64169
NC
3241 if (!(j & 0x3))
3242 printf (" ");
3243 }
3244 break;
19808d3f 3245
ebb64169
NC
3246 case ELFDATA2MSB:
3247 for (j = 0; j < 16; j++)
3248 {
3249 if (j < lbytes)
3250 printf ("%2.2x", data [j]);
3251 else
3252 printf (" ");
19808d3f 3253
ebb64169
NC
3254 if ((j & 3) == 3)
3255 printf (" ");
3256 }
3257 break;
3258 }
19808d3f 3259
ebb64169
NC
3260 for (j = 0; j < lbytes; j++)
3261 {
3262 k = data [j];
3263 if (k >= ' ' && k < 0x80)
3264 printf ("%c", k);
3265 else
3266 printf (".");
3267 }
19808d3f 3268
ebb64169 3269 putchar ('\n');
19808d3f 3270
ebb64169
NC
3271 data += lbytes;
3272 addr += lbytes;
3273 bytes -= lbytes;
3274 }
3275
3276 free (start);
3277 }
76466873 3278 }
cb436f39
NC
3279
3280 return 1;
3281}
3282
6c4b8d0f
UD
3283static void
3284process_mips_fpe_exception (mask)
3285 int mask;
3286{
3287 if (mask)
3288 {
3289 int first = 1;
3290 if (mask & OEX_FPU_INEX)
3291 fputs ("INEX", stdout), first = 0;
3292 if (mask & OEX_FPU_UFLO)
3293 printf ("%sUFLO", first ? "" : "|"), first = 0;
3294 if (mask & OEX_FPU_OFLO)
3295 printf ("%sOFLO", first ? "" : "|"), first = 0;
3296 if (mask & OEX_FPU_DIV0)
3297 printf ("%sDIV0", first ? "" : "|"), first = 0;
3298 if (mask & OEX_FPU_INVAL)
3299 printf ("%sINVAL", first ? "" : "|");
3300 }
3301 else
3302 fputs ("0", stdout);
3303}
3304
3305static int
3306process_mips_specific (file)
3307 FILE *file;
3308{
3309 Elf_Internal_Dyn * entry;
3310 size_t liblist_offset = 0;
3311 size_t liblistno = 0;
3312 size_t options_offset = 0;
3313
3314 /* We have a lot of special sections. Thanks SGI! */
3315 if (dynamic_segment == NULL)
3316 /* No information available. */
3317 return 0;
3318
3319 for (entry = dynamic_segment; entry->d_tag != DT_NULL; ++entry)
3320 switch (entry->d_tag)
3321 {
3322 case DT_MIPS_LIBLIST:
3323 liblist_offset = entry->d_un.d_val - loadaddr;
3324 break;
3325 case DT_MIPS_LIBLISTNO:
3326 liblistno = entry->d_un.d_val;
3327 break;
3328 case DT_MIPS_OPTIONS:
3329 options_offset = entry->d_un.d_val - loadaddr;
3330 break;
3331 default:
3332 break;
3333 }
3334
3335 if (liblist_offset != 0 && liblistno != 0 && do_dynamic)
3336 {
3337 Elf32_External_Lib *elib;
3338 size_t cnt;
3339
3340 GET_DATA_ALLOC (liblist_offset, liblistno * sizeof (Elf32_External_Lib),
3341 elib, Elf32_External_Lib *, "liblist");
3342
3343 printf ("\nSection '.liblist' contains %d entries:\n", liblistno);
fdf959dd 3344 fputs (" Library Time Stamp Checksum Version Flags\n",
6c4b8d0f
UD
3345 stdout);
3346
3347 for (cnt = 0; cnt < liblistno; ++cnt)
3348 {
3349 Elf32_Lib liblist;
3350 time_t time;
fdf959dd 3351 char timebuf[20];
6c4b8d0f
UD
3352
3353 liblist.l_name = BYTE_GET (elib[cnt].l_name);
3354 time = BYTE_GET (elib[cnt].l_time_stamp);
3355 liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum);
3356 liblist.l_version = BYTE_GET (elib[cnt].l_version);
3357 liblist.l_flags = BYTE_GET (elib[cnt].l_flags);
3358
fdf959dd 3359 strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time));
6c4b8d0f
UD
3360
3361 printf ("%3d: %-20s %s %#10lx %-7ld %#lx\n", cnt,
3362 dynamic_strings + liblist.l_name, timebuf,
3363 liblist.l_checksum, liblist.l_version, liblist.l_flags);
3364 }
3365
3366 free (elib);
3367 }
3368
3369 if (options_offset != 0)
3370 {
3371 Elf_External_Options *eopt;
3372 Elf_Internal_Shdr *sect = section_headers;
3373 Elf_Internal_Options *iopt;
3374 Elf_Internal_Options *option;
3375 size_t offset;
3376 int cnt;
3377
3378 /* Find the section header so that we get the size. */
3379 while (sect->sh_type != SHT_MIPS_OPTIONS)
3380 ++sect;
3381
3382 GET_DATA_ALLOC (options_offset, sect->sh_size, eopt,
3383 Elf_External_Options *, "options");
3384
3385 iopt = (Elf_Internal_Options *) malloc ((sect->sh_size / sizeof (eopt))
3386 * sizeof (*iopt));
3387 if (iopt == NULL)
3388 {
3389 error (_("Out of memory"));
3390 return 0;
3391 }
3392
3393 offset = cnt = 0;
3394 option = iopt;
3395 while (offset < sect->sh_size)
3396 {
3397 Elf_External_Options *eoption;
3398
3399 eoption = (Elf_External_Options *) ((char *) eopt + offset);
3400
3401 option->kind = BYTE_GET (eoption->kind);
3402 option->size = BYTE_GET (eoption->size);
3403 option->section = BYTE_GET (eoption->section);
3404 option->info = BYTE_GET (eoption->info);
3405
3406 offset += option->size;
3407 ++option;
3408 ++cnt;
3409 }
3410
3411 printf (_("\nSection '%s' contains %d entries:\n"),
3412 string_table + sect->sh_name, cnt);
3413
3414 option = iopt;
3415 while (cnt-- > 0)
3416 {
3417 size_t len;
3418
3419 switch (option->kind)
3420 {
3421 case ODK_NULL:
3422 /* This shouldn't happen. */
3423 printf (" NULL %d %x", option->section, option->info);
3424 break;
3425 case ODK_REGINFO:
3426 printf (" REGINFO ");
3427 if (elf_header.e_machine == EM_MIPS)
3428 {
3429 /* 32bit form. */
3430 Elf32_External_RegInfo *ereg;
3431 Elf32_RegInfo reginfo;
3432
3433 ereg = (Elf32_External_RegInfo *) (option + 1);
3434 reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
3435 reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
3436 reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
3437 reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
3438 reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
3439 reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
3440
3441 printf ("GPR %08lx GP %ld\n",
3442 reginfo.ri_gprmask, reginfo.ri_gp_value);
3443 printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n",
3444 reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
3445 reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
3446 }
3447 else
3448 {
3449 /* 64 bit form. */
3450 Elf64_External_RegInfo *ereg;
3451 Elf64_Internal_RegInfo reginfo;
3452
3453 ereg = (Elf64_External_RegInfo *) (option + 1);
3454 reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
3455 reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
3456 reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
3457 reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
3458 reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
3459 reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
3460
3461 printf ("GPR %08lx GP %ld\n",
3462 reginfo.ri_gprmask, reginfo.ri_gp_value);
3463 printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n",
3464 reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
3465 reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
3466 }
3467 ++option;
3468 continue;
3469 case ODK_EXCEPTIONS:
3470 fputs (" EXCEPTIONS fpe_min(", stdout);
3471 process_mips_fpe_exception (option->info & OEX_FPU_MIN);
3472 fputs (") fpe_max(", stdout);
3473 process_mips_fpe_exception ((option->info & OEX_FPU_MAX) >> 8);
3474 fputs (")", stdout);
3475
3476 if (option->info & OEX_PAGE0)
3477 fputs (" PAGE0", stdout);
3478 if (option->info & OEX_SMM)
3479 fputs (" SMM", stdout);
3480 if (option->info & OEX_FPDBUG)
3481 fputs (" FPDBUG", stdout);
3482 if (option->info & OEX_DISMISS)
3483 fputs (" DISMISS", stdout);
3484 break;
3485 case ODK_PAD:
3486 fputs (" PAD ", stdout);
3487 if (option->info & OPAD_PREFIX)
3488 fputs (" PREFIX", stdout);
3489 if (option->info & OPAD_POSTFIX)
3490 fputs (" POSTFIX", stdout);
3491 if (option->info & OPAD_SYMBOL)
3492 fputs (" SYMBOL", stdout);
3493 break;
3494 case ODK_HWPATCH:
3495 fputs (" HWPATCH ", stdout);
3496 if (option->info & OHW_R4KEOP)
3497 fputs (" R4KEOP", stdout);
3498 if (option->info & OHW_R8KPFETCH)
3499 fputs (" R8KPFETCH", stdout);
3500 if (option->info & OHW_R5KEOP)
3501 fputs (" R5KEOP", stdout);
3502 if (option->info & OHW_R5KCVTL)
3503 fputs (" R5KCVTL", stdout);
3504 break;
3505 case ODK_FILL:
3506 fputs (" FILL ", stdout);
3507 /* XXX Print content of info word? */
3508 break;
3509 case ODK_TAGS:
3510 fputs (" TAGS ", stdout);
3511 /* XXX Print content of info word? */
3512 break;
3513 case ODK_HWAND:
3514 fputs (" HWAND ", stdout);
3515 if (option->info & OHWA0_R4KEOP_CHECKED)
3516 fputs (" R4KEOP_CHECKED", stdout);
3517 if (option->info & OHWA0_R4KEOP_CLEAN)
3518 fputs (" R4KEOP_CLEAN", stdout);
3519 break;
3520 case ODK_HWOR:
3521 fputs (" HWOR ", stdout);
3522 if (option->info & OHWA0_R4KEOP_CHECKED)
3523 fputs (" R4KEOP_CHECKED", stdout);
3524 if (option->info & OHWA0_R4KEOP_CLEAN)
3525 fputs (" R4KEOP_CLEAN", stdout);
3526 break;
3527 case ODK_GP_GROUP:
3528 printf (" GP_GROUP %#06x self-contained %#06x",
3529 option->info & OGP_GROUP,
3530 (option->info & OGP_SELF) >> 16);
3531 break;
3532 case ODK_IDENT:
3533 printf (" IDENT %#06x self-contained %#06x",
3534 option->info & OGP_GROUP,
3535 (option->info & OGP_SELF) >> 16);
3536 break;
3537 default:
3538 /* This shouldn't happen. */
3539 printf (" %3d ??? %d %x",
3540 option->kind, option->section, option->info);
3541 break;
3542 }
3543
3544 len = sizeof (*eopt);
3545 while (len < option->size)
3546 if (((char *) option)[len] >= ' '
5892b099 3547 && ((char *) option)[len] < 0x7f)
6c4b8d0f
UD
3548 printf ("%c", ((char *) option)[len++]);
3549 else
3550 printf ("\\%03o", ((char *) option)[len++]);
3551
3552 fputs ("\n", stdout);
3553 ++option;
3554 }
3555
3556 free (eopt);
3557 }
3558
3559 return 1;
3560}
3561
3562static int
3563process_arch_specific (file)
3564 FILE *file;
3565{
3566 switch (elf_header.e_machine)
3567 {
3568 case EM_MIPS:
3569 case EM_MIPS_RS4_BE:
3570 return process_mips_specific (file);
3571 break;
3572 default:
3573 break;
3574 }
3575 return 1;
3576}
3577
cb436f39
NC
3578static int
3579get_file_header (file)
3580 FILE * file;
3581{
3582 Elf32_External_Ehdr ehdr;
3583
3584 if (fread (& ehdr, sizeof (ehdr), 1, file) != 1)
3585 return 0;
3586
3587 memcpy (elf_header.e_ident, ehdr.e_ident, EI_NIDENT);
3588
3589 if (elf_header.e_ident [EI_DATA] == ELFDATA2LSB)
3590 byte_get = byte_get_little_endian;
3591 else
3592 byte_get = byte_get_big_endian;
3593
3594 elf_header.e_entry = BYTE_GET (ehdr.e_entry);
3595 elf_header.e_phoff = BYTE_GET (ehdr.e_phoff);
3596 elf_header.e_shoff = BYTE_GET (ehdr.e_shoff);
3597 elf_header.e_version = BYTE_GET (ehdr.e_version);
3598 elf_header.e_flags = BYTE_GET (ehdr.e_flags);
3599 elf_header.e_type = BYTE_GET (ehdr.e_type);
3600 elf_header.e_machine = BYTE_GET (ehdr.e_machine);
3601 elf_header.e_ehsize = BYTE_GET (ehdr.e_ehsize);
3602 elf_header.e_phentsize = BYTE_GET (ehdr.e_phentsize);
3603 elf_header.e_phnum = BYTE_GET (ehdr.e_phnum);
3604 elf_header.e_shentsize = BYTE_GET (ehdr.e_shentsize);
3605 elf_header.e_shnum = BYTE_GET (ehdr.e_shnum);
3606 elf_header.e_shstrndx = BYTE_GET (ehdr.e_shstrndx);
3607
3608 return 1;
76466873
NC
3609}
3610
3611static void
3612process_file (file_name)
3613 char * file_name;
3614{
ebb64169 3615 FILE * file;
76466873 3616 struct stat statbuf;
ebb64169 3617 unsigned int i;
19808d3f 3618
ebb64169
NC
3619 if (stat (file_name, & statbuf) < 0)
3620 {
3621 error (_("Cannot stat input file %s.\n"), file_name);
3622 return;
3623 }
3624
3625 file = fopen (file_name, "rb");
3626 if (file == NULL)
76466873
NC
3627 {
3628 error (_("Input file %s not found.\n"), file_name);
3629 return;
3630 }
cb436f39
NC
3631
3632 if (! get_file_header (file))
76466873 3633 {
ebb64169
NC
3634 error (_("%s: Failed to read file header\n"), file_name);
3635 fclose (file);
76466873
NC
3636 return;
3637 }
19808d3f 3638
ebb64169 3639 /* Initialise per file variables. */
ebb64169 3640 for (i = NUM_ELEM (version_info); i--;)
be5b92f9 3641 version_info[i] = 0;
19808d3f 3642
ebb64169 3643 for (i = NUM_ELEM (dynamic_info); i--;)
be5b92f9 3644 dynamic_info[i] = 0;
19808d3f 3645
ebb64169 3646 /* Process the file. */
76466873
NC
3647 if (show_name)
3648 printf (_("\nFile: %s\n"), file_name);
19808d3f 3649
ebb64169 3650 if (! process_file_header ())
76466873 3651 {
ebb64169 3652 fclose (file);
76466873
NC
3653 return;
3654 }
76466873 3655
ebb64169 3656 process_section_headers (file);
76466873 3657
ebb64169 3658 process_program_headers (file);
19808d3f 3659
ebb64169
NC
3660 process_dynamic_segment (file);
3661
3662 process_relocs (file);
19808d3f 3663
ebb64169 3664 process_symbol_table (file);
76466873 3665
fdf959dd
UD
3666 process_syminfo (file);
3667
ebb64169 3668 process_version_sections (file);
76466873 3669
ebb64169 3670 process_section_contents (file);
19808d3f 3671
6c4b8d0f
UD
3672 process_arch_specific (file);
3673
ebb64169 3674 fclose (file);
19808d3f 3675
ebb64169
NC
3676 if (section_headers)
3677 {
3678 free (section_headers);
3679 section_headers = NULL;
3680 }
76466873 3681
ebb64169 3682 if (string_table)
76466873 3683 {
ebb64169
NC
3684 free (string_table);
3685 string_table = NULL;
3686 }
76466873 3687
ebb64169
NC
3688 if (dynamic_strings)
3689 {
3690 free (dynamic_strings);
3691 dynamic_strings = NULL;
3692 }
3693
3694 if (dynamic_symbols)
3695 {
3696 free (dynamic_symbols);
3697 dynamic_symbols = NULL;
76466873 3698 }
fdf959dd
UD
3699
3700 if (dynamic_syminfo)
3701 {
3702 free (dynamic_syminfo);
3703 dynamic_syminfo = NULL;
3704 }
76466873
NC
3705}
3706
3707#ifdef SUPPORT_DISASSEMBLY
3708/* Needed by the i386 disassembler. For extra credit, someone could
3709fix this so that we insert symbolic addresses here, esp for GOT/PLT
3710symbols */
3711
3712void
3713print_address (unsigned int addr, FILE * outfile)
3714{
3715 fprintf (outfile,"0x%8.8x", addr);
3716}
3717
3718/* Needed by the i386 disassembler. */
3719void
3720db_task_printsym (unsigned int addr)
3721{
3722 print_address (addr, stderr);
3723}
3724#endif
3725
3726int
3727main (argc, argv)
3728 int argc;
3729 char ** argv;
3730{
3731 parse_args (argc, argv);
3732
76466873
NC
3733 if (optind < (argc - 1))
3734 show_name = 1;
19808d3f 3735
76466873
NC
3736 while (optind < argc)
3737 process_file (argv [optind ++]);
3738
3739 return 0;
3740}
This page took 0.301697 seconds and 4 git commands to generate.