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