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