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