]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - binutils/readelf.c
gas/
[thirdparty/binutils-gdb.git] / binutils / readelf.c
CommitLineData
252b5132 1/* readelf.c -- display contents of an ELF format file
5b18a4bc 2 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
74013231 3 Free Software Foundation, Inc.
252b5132
RH
4
5 Originally developed by Eric Youngdale <eric@andante.jic.com>
12ab83a9 6 Modifications by Nick Clifton <nickc@redhat.com>
252b5132
RH
7
8 This file is part of GNU Binutils.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
b43b5d5f
NC
22 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
23 02110-1301, USA. */
252b5132 24\f
9eb20dd8 25/* The difference between readelf and objdump:
252b5132 26
74013231 27 Both programs are capable of displaying the contents of ELF format files,
9eb20dd8 28 so why does the binutils project have two file dumpers ?
0de14b54 29
9eb20dd8
NC
30 The reason is that objdump sees an ELF file through a BFD filter of the
31 world; if BFD has a bug where, say, it disagrees about a machine constant
32 in e_flags, then the odds are good that it will remain internally
33 consistent. The linker sees it the BFD way, objdump sees it the BFD way,
34 GAS sees it the BFD way. There was need for a tool to go find out what
35 the file actually says.
36
37 This is why the readelf program does not link against the BFD library - it
38 exists as an independent program to help verify the correct working of BFD.
39
40 There is also the case that readelf can provide more information about an
41 ELF file than is provided by objdump. In particular it can display DWARF
42 debugging information which (at the moment) objdump cannot. */
43\f
252b5132 44#include <assert.h>
00ed88bd 45#include <sys/types.h>
252b5132
RH
46#include <sys/stat.h>
47#include <stdio.h>
48#include <time.h>
49
a952a375 50#if __GNUC__ >= 2
19936277 51/* Define BFD64 here, even if our default architecture is 32 bit ELF
a952a375 52 as this will allow us to read in and parse 64bit and 32bit ELF files.
b34976b6 53 Only do this if we believe that the compiler can support a 64 bit
a952a375 54 data type. For now we only rely on GCC being able to do this. */
19936277 55#define BFD64
a952a375
NC
56#endif
57
19e6b90e 58#include "dwarf.h"
252b5132
RH
59
60#include "elf/common.h"
61#include "elf/external.h"
62#include "elf/internal.h"
252b5132
RH
63
64/* The following headers use the elf/reloc-macros.h file to
65 automatically generate relocation recognition functions
66 such as elf_mips_reloc_type() */
67
68#define RELOC_MACROS_GEN_FUNC
69
252b5132 70#include "elf/alpha.h"
3b16e843 71#include "elf/arc.h"
252b5132 72#include "elf/arm.h"
3b16e843 73#include "elf/avr.h"
1d65ded4 74#include "elf/bfin.h"
3b16e843 75#include "elf/cris.h"
252b5132
RH
76#include "elf/d10v.h"
77#include "elf/d30v.h"
d172d4ba 78#include "elf/dlx.h"
252b5132 79#include "elf/fr30.h"
5c70f934 80#include "elf/frv.h"
3b16e843
NC
81#include "elf/h8.h"
82#include "elf/hppa.h"
83#include "elf/i386.h"
35b1837e 84#include "elf/i370.h"
3b16e843
NC
85#include "elf/i860.h"
86#include "elf/i960.h"
87#include "elf/ia64.h"
1e4cf259 88#include "elf/ip2k.h"
49f58d10 89#include "elf/m32c.h"
3b16e843
NC
90#include "elf/m32r.h"
91#include "elf/m68k.h"
75751cd9 92#include "elf/m68hc11.h"
252b5132 93#include "elf/mcore.h"
3b16e843 94#include "elf/mips.h"
3c3bdf30 95#include "elf/mmix.h"
3b16e843
NC
96#include "elf/mn10200.h"
97#include "elf/mn10300.h"
4970f871 98#include "elf/mt.h"
2469cfa2 99#include "elf/msp430.h"
3b16e843 100#include "elf/or32.h"
7d466069 101#include "elf/pj.h"
3b16e843 102#include "elf/ppc.h"
c833c019 103#include "elf/ppc64.h"
a85d7ed0 104#include "elf/s390.h"
3b16e843
NC
105#include "elf/sh.h"
106#include "elf/sparc.h"
107#include "elf/v850.h"
179d3252 108#include "elf/vax.h"
3b16e843 109#include "elf/x86-64.h"
93fbbb04 110#include "elf/xstormy16.h"
1fe1f39c 111#include "elf/crx.h"
3b36097d 112#include "elf/iq2000.h"
88da6820 113#include "elf/xtensa.h"
252b5132 114
fb52b2f4
NC
115#include "aout/ar.h"
116
252b5132
RH
117#include "bucomm.h"
118#include "getopt.h"
566b0d53 119#include "libiberty.h"
252b5132 120
b34976b6 121char *program_name = "readelf";
85b1c36d
BE
122static long archive_file_offset;
123static unsigned long archive_file_size;
124static unsigned long dynamic_addr;
125static bfd_size_type dynamic_size;
126static unsigned int dynamic_nent;
127static char *dynamic_strings;
128static unsigned long dynamic_strings_length;
129static char *string_table;
130static unsigned long string_table_length;
131static unsigned long num_dynamic_syms;
132static Elf_Internal_Sym *dynamic_symbols;
133static Elf_Internal_Syminfo *dynamic_syminfo;
134static unsigned long dynamic_syminfo_offset;
135static unsigned int dynamic_syminfo_nent;
136static char program_interpreter[64];
137static bfd_vma dynamic_info[DT_JMPREL + 1];
138static bfd_vma version_info[16];
139static Elf_Internal_Ehdr elf_header;
140static Elf_Internal_Shdr *section_headers;
141static Elf_Internal_Phdr *program_headers;
142static Elf_Internal_Dyn *dynamic_section;
143static Elf_Internal_Shdr *symtab_shndx_hdr;
144static int show_name;
145static int do_dynamic;
146static int do_syms;
147static int do_reloc;
148static int do_sections;
149static int do_section_groups;
5477e8a0 150static int do_section_details;
85b1c36d
BE
151static int do_segments;
152static int do_unwind;
153static int do_using_dynamic;
154static int do_header;
155static int do_dump;
156static int do_version;
157static int do_wide;
158static int do_histogram;
159static int do_debugging;
85b1c36d
BE
160static int do_arch;
161static int do_notes;
162static int is_32bit_elf;
252b5132 163
e4b17d5c
L
164struct group_list
165{
166 struct group_list *next;
167 unsigned int section_index;
168};
169
170struct group
171{
172 struct group_list *root;
173 unsigned int group_index;
174};
175
85b1c36d
BE
176static size_t group_count;
177static struct group *section_groups;
178static struct group **section_headers_groups;
e4b17d5c 179
aef1f6d0
DJ
180/* A linked list of the section names for which dumps were requested
181 by name. */
182struct dump_list_entry
183{
184 char *name;
185 int type;
186 struct dump_list_entry *next;
187};
188static struct dump_list_entry *dump_sects_byname;
189
18bd398b
NC
190/* A dynamic array of flags indicating for which sections a hex dump
191 has been requested (via the -x switch) and/or a disassembly dump
192 (via the -i switch). */
193char *cmdline_dump_sects = NULL;
194unsigned num_cmdline_dump_sects = 0;
195
196/* A dynamic array of flags indicating for which sections a dump of
197 some kind has been requested. It is reset on a per-object file
aef1f6d0
DJ
198 basis and then initialised from the cmdline_dump_sects array,
199 the results of interpreting the -w switch, and the
200 dump_sects_byname list. */
b34976b6
AM
201char *dump_sects = NULL;
202unsigned int num_dump_sects = 0;
252b5132
RH
203
204#define HEX_DUMP (1 << 0)
205#define DISASS_DUMP (1 << 1)
206#define DEBUG_DUMP (1 << 2)
207
c256ffe7 208/* How to print a vma value. */
843dd992
NC
209typedef enum print_mode
210{
211 HEX,
212 DEC,
213 DEC_5,
214 UNSIGNED,
215 PREFIX_HEX,
216 FULL_HEX,
217 LONG_HEX
218}
219print_mode;
220
d3ba0551 221static void (*byte_put) (unsigned char *, bfd_vma, int);
252b5132 222
9c19a809
NC
223#define UNKNOWN -1
224
7036c0e1 225#define SECTION_NAME(X) ((X) == NULL ? "<none>" : \
18bd398b
NC
226 ((X)->sh_name >= string_table_length \
227 ? "<corrupt>" : string_table + (X)->sh_name))
252b5132 228
9ad5cbcf
AM
229/* Given st_shndx I, map to section_headers index. */
230#define SECTION_HEADER_INDEX(I) \
231 ((I) < SHN_LORESERVE \
232 ? (I) \
233 : ((I) <= SHN_HIRESERVE \
234 ? 0 \
235 : (I) - (SHN_HIRESERVE + 1 - SHN_LORESERVE)))
236
237/* Reverse of the above. */
238#define SECTION_HEADER_NUM(N) \
239 ((N) < SHN_LORESERVE \
240 ? (N) \
241 : (N) + (SHN_HIRESERVE + 1 - SHN_LORESERVE))
242
243#define SECTION_HEADER(I) (section_headers + SECTION_HEADER_INDEX (I))
244
ee42cf8c 245#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
252b5132 246
7036c0e1 247#define BYTE_GET(field) byte_get (field, sizeof (field))
a952a375 248
261a45ad 249#define NUM_ELEM(array) (sizeof (array) / sizeof ((array)[0]))
252b5132 250
9ad5cbcf
AM
251#define GET_ELF_SYMBOLS(file, section) \
252 (is_32bit_elf ? get_32bit_elf_symbols (file, section) \
253 : get_64bit_elf_symbols (file, section))
9ea033b2 254
d79b3d50
NC
255#define VALID_DYNAMIC_NAME(offset) ((dynamic_strings != NULL) && (offset < dynamic_strings_length))
256/* GET_DYNAMIC_NAME asssumes that VALID_DYNAMIC_NAME has
257 already been called and verified that the string exists. */
258#define GET_DYNAMIC_NAME(offset) (dynamic_strings + offset)
18bd398b
NC
259
260/* This is just a bit of syntatic sugar. */
261#define streq(a,b) (strcmp ((a), (b)) == 0)
262#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
d79b3d50 263\f
c256ffe7
JJ
264static void *
265get_data (void *var, FILE *file, long offset, size_t size, size_t nmemb,
266 const char *reason)
a6e9f9df 267{
d3ba0551 268 void *mvar;
a6e9f9df 269
c256ffe7 270 if (size == 0 || nmemb == 0)
a6e9f9df
AM
271 return NULL;
272
fb52b2f4 273 if (fseek (file, archive_file_offset + offset, SEEK_SET))
a6e9f9df 274 {
0fd3a477 275 error (_("Unable to seek to 0x%lx for %s\n"),
fb52b2f4 276 archive_file_offset + offset, reason);
a6e9f9df
AM
277 return NULL;
278 }
279
280 mvar = var;
281 if (mvar == NULL)
282 {
c256ffe7
JJ
283 /* Check for overflow. */
284 if (nmemb < (~(size_t) 0 - 1) / size)
285 /* + 1 so that we can '\0' terminate invalid string table sections. */
286 mvar = malloc (size * nmemb + 1);
a6e9f9df
AM
287
288 if (mvar == NULL)
289 {
0fd3a477
JW
290 error (_("Out of memory allocating 0x%lx bytes for %s\n"),
291 (unsigned long)(size * nmemb), reason);
a6e9f9df
AM
292 return NULL;
293 }
c256ffe7
JJ
294
295 ((char *) mvar)[size * nmemb] = '\0';
a6e9f9df
AM
296 }
297
c256ffe7 298 if (fread (mvar, size, nmemb, file) != nmemb)
a6e9f9df 299 {
0fd3a477
JW
300 error (_("Unable to read in 0x%lx bytes of %s\n"),
301 (unsigned long)(size * nmemb), reason);
a6e9f9df
AM
302 if (mvar != var)
303 free (mvar);
304 return NULL;
305 }
306
307 return mvar;
308}
309
adab8cdc 310static void
d3ba0551 311byte_put_little_endian (unsigned char *field, bfd_vma value, int size)
adab8cdc
AO
312{
313 switch (size)
314 {
315 case 8:
316 field[7] = (((value >> 24) >> 24) >> 8) & 0xff;
317 field[6] = ((value >> 24) >> 24) & 0xff;
318 field[5] = ((value >> 24) >> 16) & 0xff;
319 field[4] = ((value >> 24) >> 8) & 0xff;
320 /* Fall through. */
321 case 4:
322 field[3] = (value >> 24) & 0xff;
323 field[2] = (value >> 16) & 0xff;
324 /* Fall through. */
325 case 2:
326 field[1] = (value >> 8) & 0xff;
327 /* Fall through. */
328 case 1:
329 field[0] = value & 0xff;
330 break;
331
332 default:
333 error (_("Unhandled data length: %d\n"), size);
334 abort ();
335 }
336}
337
66543521
AM
338#if defined BFD64 && !BFD_HOST_64BIT_LONG
339static int
340print_dec_vma (bfd_vma vma, int is_signed)
341{
342 char buf[40];
343 char *bufp = buf;
344 int nc = 0;
345
346 if (is_signed && (bfd_signed_vma) vma < 0)
347 {
348 vma = -vma;
349 putchar ('-');
350 nc = 1;
351 }
352
353 do
354 {
355 *bufp++ = '0' + vma % 10;
356 vma /= 10;
357 }
358 while (vma != 0);
359 nc += bufp - buf;
360
361 while (bufp > buf)
362 putchar (*--bufp);
363 return nc;
364}
365
366static int
367print_hex_vma (bfd_vma vma)
368{
369 char buf[32];
370 char *bufp = buf;
371 int nc;
372
373 do
374 {
375 char digit = '0' + (vma & 0x0f);
376 if (digit > '9')
377 digit += 'a' - '0' - 10;
378 *bufp++ = digit;
379 vma >>= 4;
380 }
381 while (vma != 0);
382 nc = bufp - buf;
383
384 while (bufp > buf)
385 putchar (*--bufp);
386 return nc;
387}
388#endif
389
f7a99963 390/* Print a VMA value. */
66543521 391static int
d3ba0551 392print_vma (bfd_vma vma, print_mode mode)
f7a99963
NC
393{
394#ifdef BFD64
395 if (is_32bit_elf)
396#endif
397 {
398 switch (mode)
399 {
b19aac67 400 case FULL_HEX:
66543521
AM
401 return printf ("0x%8.8lx", (unsigned long) vma);
402
b19aac67 403 case LONG_HEX:
66543521 404 return printf ("%8.8lx", (unsigned long) vma);
b19aac67
NC
405
406 case DEC_5:
407 if (vma <= 99999)
66543521 408 return printf ("%5ld", (long) vma);
b19aac67 409 /* Drop through. */
66543521 410
b19aac67 411 case PREFIX_HEX:
66543521
AM
412 return printf ("0x%lx", (unsigned long) vma);
413
b19aac67 414 case HEX:
66543521 415 return printf ("%lx", (unsigned long) vma);
b19aac67
NC
416
417 case DEC:
66543521 418 return printf ("%ld", (unsigned long) vma);
b19aac67
NC
419
420 case UNSIGNED:
66543521 421 return printf ("%lu", (unsigned long) vma);
f7a99963
NC
422 }
423 }
424#ifdef BFD64
425 else
426 {
66543521
AM
427 int nc = 0;
428
f7a99963
NC
429 switch (mode)
430 {
431 case FULL_HEX:
66543521 432 nc = printf ("0x");
b19aac67 433 /* Drop through. */
76da6bbe 434
f7a99963
NC
435 case LONG_HEX:
436 printf_vma (vma);
66543521 437 return nc + 16;
76da6bbe 438
f7a99963 439 case PREFIX_HEX:
66543521 440 nc = printf ("0x");
b19aac67 441 /* Drop through. */
76da6bbe 442
f7a99963
NC
443 case HEX:
444#if BFD_HOST_64BIT_LONG
66543521 445 return nc + printf ("%lx", vma);
f7a99963 446#else
66543521 447 return nc + print_hex_vma (vma);
f7a99963 448#endif
f7a99963
NC
449
450 case DEC:
2f528887 451#if BFD_HOST_64BIT_LONG
66543521 452 return printf ("%ld", vma);
2f528887 453#else
66543521 454 return print_dec_vma (vma, 1);
76da6bbe 455#endif
f7a99963
NC
456
457 case DEC_5:
2f528887 458#if BFD_HOST_64BIT_LONG
b19aac67 459 if (vma <= 99999)
66543521 460 return printf ("%5ld", vma);
b19aac67 461 else
66543521 462 return printf ("%#lx", vma);
2f528887 463#else
66543521
AM
464 if (vma <= 99999)
465 return printf ("%5ld", _bfd_int64_low (vma));
b19aac67 466 else
66543521 467 return print_hex_vma (vma);
76da6bbe 468#endif
76da6bbe 469
f7a99963 470 case UNSIGNED:
2f528887 471#if BFD_HOST_64BIT_LONG
66543521 472 return printf ("%lu", vma);
76da6bbe 473#else
66543521 474 return print_dec_vma (vma, 0);
2f528887 475#endif
f7a99963
NC
476 }
477 }
478#endif
66543521 479 return 0;
f7a99963
NC
480}
481
31104126
NC
482/* Display a symbol on stdout. If do_wide is not true then
483 format the symbol to be at most WIDTH characters,
047b2264 484 truncating as necessary. If WIDTH is negative then
31104126
NC
485 format the string to be exactly - WIDTH characters,
486 truncating or padding as necessary. */
487
488static void
d3ba0551 489print_symbol (int width, const char *symbol)
31104126
NC
490{
491 if (do_wide)
f1ef08cb 492 printf ("%s", symbol);
31104126
NC
493 else if (width < 0)
494 printf ("%-*.*s", width, width, symbol);
53c7db4b 495 else
31104126
NC
496 printf ("%-.*s", width, symbol);
497}
498
adab8cdc 499static void
d3ba0551 500byte_put_big_endian (unsigned char *field, bfd_vma value, int size)
adab8cdc
AO
501{
502 switch (size)
503 {
504 case 8:
505 field[7] = value & 0xff;
506 field[6] = (value >> 8) & 0xff;
507 field[5] = (value >> 16) & 0xff;
508 field[4] = (value >> 24) & 0xff;
509 value >>= 16;
510 value >>= 16;
511 /* Fall through. */
512 case 4:
513 field[3] = value & 0xff;
514 field[2] = (value >> 8) & 0xff;
515 value >>= 16;
516 /* Fall through. */
517 case 2:
518 field[1] = value & 0xff;
519 value >>= 8;
520 /* Fall through. */
521 case 1:
522 field[0] = value & 0xff;
523 break;
524
525 default:
526 error (_("Unhandled data length: %d\n"), size);
527 abort ();
528 }
529}
530
89fac5e3
RS
531/* Return a pointer to section NAME, or NULL if no such section exists. */
532
533static Elf_Internal_Shdr *
534find_section (const char *name)
535{
536 unsigned int i;
537
538 for (i = 0; i < elf_header.e_shnum; i++)
539 if (streq (SECTION_NAME (section_headers + i), name))
540 return section_headers + i;
541
542 return NULL;
543}
544
bcedfee6 545/* Guess the relocation size commonly used by the specific machines. */
252b5132 546
252b5132 547static int
d3ba0551 548guess_is_rela (unsigned long e_machine)
252b5132 549{
9c19a809 550 switch (e_machine)
252b5132
RH
551 {
552 /* Targets that use REL relocations. */
553 case EM_ARM:
554 case EM_386:
555 case EM_486:
63fcb9e9 556 case EM_960:
d172d4ba 557 case EM_DLX:
3b16e843
NC
558 case EM_OPENRISC:
559 case EM_OR32:
252b5132 560 case EM_CYGNUS_M32R:
2b0337b0 561 case EM_D10V:
252b5132
RH
562 case EM_CYGNUS_D10V:
563 case EM_MIPS:
4fe85591 564 case EM_MIPS_RS3_LE:
9c19a809 565 return FALSE;
103f02d3 566
252b5132
RH
567 /* Targets that use RELA relocations. */
568 case EM_68K:
b8720f9d
JL
569 case EM_H8_300:
570 case EM_H8_300H:
571 case EM_H8S:
351b4b40
RH
572 case EM_SPARC32PLUS:
573 case EM_SPARCV9:
252b5132
RH
574 case EM_SPARC:
575 case EM_PPC:
285d1771 576 case EM_PPC64:
2b0337b0 577 case EM_V850:
252b5132 578 case EM_CYGNUS_V850:
2b0337b0 579 case EM_D30V:
252b5132 580 case EM_CYGNUS_D30V:
2b0337b0 581 case EM_MN10200:
252b5132 582 case EM_CYGNUS_MN10200:
2b0337b0 583 case EM_MN10300:
252b5132 584 case EM_CYGNUS_MN10300:
2b0337b0 585 case EM_FR30:
252b5132 586 case EM_CYGNUS_FR30:
5c70f934 587 case EM_CYGNUS_FRV:
252b5132
RH
588 case EM_SH:
589 case EM_ALPHA:
590 case EM_MCORE:
800eeca4 591 case EM_IA_64:
dff14200 592 case EM_AVR:
2b0337b0 593 case EM_AVR_OLD:
1b61cf92 594 case EM_CRIS:
535c37ff 595 case EM_860:
bcedfee6 596 case EM_X86_64:
a85d7ed0 597 case EM_S390:
b7498e0e 598 case EM_S390_OLD:
3c3bdf30 599 case EM_MMIX:
2469cfa2
NC
600 case EM_MSP430:
601 case EM_MSP430_OLD:
93fbbb04 602 case EM_XSTORMY16:
1fe1f39c 603 case EM_CRX:
179d3252 604 case EM_VAX:
1e4cf259
NC
605 case EM_IP2K:
606 case EM_IP2K_OLD:
3b36097d 607 case EM_IQ2000:
88da6820
NC
608 case EM_XTENSA:
609 case EM_XTENSA_OLD:
6edf0760 610 case EM_M32R:
49f58d10 611 case EM_M32C:
d031aafb 612 case EM_MT:
1d65ded4 613 case EM_BLACKFIN:
9c19a809 614 return TRUE;
103f02d3 615
d1133906
NC
616 case EM_MMA:
617 case EM_PCP:
618 case EM_NCPU:
619 case EM_NDR1:
620 case EM_STARCORE:
621 case EM_ME16:
622 case EM_ST100:
623 case EM_TINYJ:
624 case EM_FX66:
625 case EM_ST9PLUS:
626 case EM_ST7:
627 case EM_68HC16:
628 case EM_68HC11:
629 case EM_68HC08:
630 case EM_68HC05:
631 case EM_SVX:
632 case EM_ST19:
9c19a809
NC
633 default:
634 warn (_("Don't know about relocations on this machine architecture\n"));
635 return FALSE;
636 }
637}
252b5132 638
9c19a809 639static int
d3ba0551
AM
640slurp_rela_relocs (FILE *file,
641 unsigned long rel_offset,
642 unsigned long rel_size,
643 Elf_Internal_Rela **relasp,
644 unsigned long *nrelasp)
9c19a809 645{
4d6ed7c8
NC
646 Elf_Internal_Rela *relas;
647 unsigned long nrelas;
648 unsigned int i;
252b5132 649
4d6ed7c8
NC
650 if (is_32bit_elf)
651 {
b34976b6 652 Elf32_External_Rela *erelas;
103f02d3 653
c256ffe7 654 erelas = get_data (NULL, file, rel_offset, 1, rel_size, _("relocs"));
a6e9f9df
AM
655 if (!erelas)
656 return 0;
252b5132 657
4d6ed7c8 658 nrelas = rel_size / sizeof (Elf32_External_Rela);
103f02d3 659
c256ffe7 660 relas = cmalloc (nrelas, sizeof (Elf_Internal_Rela));
103f02d3 661
4d6ed7c8
NC
662 if (relas == NULL)
663 {
c256ffe7 664 free (erelas);
18bd398b 665 error (_("out of memory parsing relocs"));
4d6ed7c8
NC
666 return 0;
667 }
103f02d3 668
4d6ed7c8
NC
669 for (i = 0; i < nrelas; i++)
670 {
671 relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
672 relas[i].r_info = BYTE_GET (erelas[i].r_info);
673 relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
674 }
103f02d3 675
4d6ed7c8
NC
676 free (erelas);
677 }
678 else
679 {
b34976b6 680 Elf64_External_Rela *erelas;
103f02d3 681
c256ffe7 682 erelas = get_data (NULL, file, rel_offset, 1, rel_size, _("relocs"));
a6e9f9df
AM
683 if (!erelas)
684 return 0;
4d6ed7c8
NC
685
686 nrelas = rel_size / sizeof (Elf64_External_Rela);
103f02d3 687
c256ffe7 688 relas = cmalloc (nrelas, sizeof (Elf_Internal_Rela));
103f02d3 689
4d6ed7c8
NC
690 if (relas == NULL)
691 {
c256ffe7 692 free (erelas);
18bd398b 693 error (_("out of memory parsing relocs"));
4d6ed7c8 694 return 0;
9c19a809 695 }
4d6ed7c8
NC
696
697 for (i = 0; i < nrelas; i++)
9c19a809 698 {
66543521
AM
699 relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
700 relas[i].r_info = BYTE_GET (erelas[i].r_info);
701 relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
4d6ed7c8 702 }
103f02d3 703
4d6ed7c8
NC
704 free (erelas);
705 }
706 *relasp = relas;
707 *nrelasp = nrelas;
708 return 1;
709}
103f02d3 710
4d6ed7c8 711static int
d3ba0551
AM
712slurp_rel_relocs (FILE *file,
713 unsigned long rel_offset,
714 unsigned long rel_size,
715 Elf_Internal_Rela **relsp,
716 unsigned long *nrelsp)
4d6ed7c8 717{
c8286bd1 718 Elf_Internal_Rela *rels;
4d6ed7c8
NC
719 unsigned long nrels;
720 unsigned int i;
103f02d3 721
4d6ed7c8
NC
722 if (is_32bit_elf)
723 {
b34976b6 724 Elf32_External_Rel *erels;
103f02d3 725
c256ffe7 726 erels = get_data (NULL, file, rel_offset, 1, rel_size, _("relocs"));
a6e9f9df
AM
727 if (!erels)
728 return 0;
103f02d3 729
4d6ed7c8 730 nrels = rel_size / sizeof (Elf32_External_Rel);
103f02d3 731
c256ffe7 732 rels = cmalloc (nrels, sizeof (Elf_Internal_Rela));
103f02d3 733
4d6ed7c8
NC
734 if (rels == NULL)
735 {
c256ffe7 736 free (erels);
18bd398b 737 error (_("out of memory parsing relocs"));
4d6ed7c8
NC
738 return 0;
739 }
740
741 for (i = 0; i < nrels; i++)
742 {
743 rels[i].r_offset = BYTE_GET (erels[i].r_offset);
744 rels[i].r_info = BYTE_GET (erels[i].r_info);
c8286bd1 745 rels[i].r_addend = 0;
9ea033b2 746 }
4d6ed7c8
NC
747
748 free (erels);
9c19a809
NC
749 }
750 else
751 {
b34976b6 752 Elf64_External_Rel *erels;
9ea033b2 753
c256ffe7 754 erels = get_data (NULL, file, rel_offset, 1, rel_size, _("relocs"));
a6e9f9df
AM
755 if (!erels)
756 return 0;
103f02d3 757
4d6ed7c8 758 nrels = rel_size / sizeof (Elf64_External_Rel);
103f02d3 759
c256ffe7 760 rels = cmalloc (nrels, sizeof (Elf_Internal_Rela));
103f02d3 761
4d6ed7c8 762 if (rels == NULL)
9c19a809 763 {
c256ffe7 764 free (erels);
18bd398b 765 error (_("out of memory parsing relocs"));
4d6ed7c8
NC
766 return 0;
767 }
103f02d3 768
4d6ed7c8
NC
769 for (i = 0; i < nrels; i++)
770 {
66543521
AM
771 rels[i].r_offset = BYTE_GET (erels[i].r_offset);
772 rels[i].r_info = BYTE_GET (erels[i].r_info);
c8286bd1 773 rels[i].r_addend = 0;
4d6ed7c8 774 }
103f02d3 775
4d6ed7c8
NC
776 free (erels);
777 }
778 *relsp = rels;
779 *nrelsp = nrels;
780 return 1;
781}
103f02d3 782
d3ba0551
AM
783/* Display the contents of the relocation data found at the specified
784 offset. */
ee42cf8c 785
4d6ed7c8 786static int
d3ba0551
AM
787dump_relocations (FILE *file,
788 unsigned long rel_offset,
789 unsigned long rel_size,
790 Elf_Internal_Sym *symtab,
791 unsigned long nsyms,
792 char *strtab,
d79b3d50 793 unsigned long strtablen,
d3ba0551 794 int is_rela)
4d6ed7c8 795{
b34976b6
AM
796 unsigned int i;
797 Elf_Internal_Rela *rels;
103f02d3 798
103f02d3 799
4d6ed7c8
NC
800 if (is_rela == UNKNOWN)
801 is_rela = guess_is_rela (elf_header.e_machine);
103f02d3 802
4d6ed7c8
NC
803 if (is_rela)
804 {
c8286bd1 805 if (!slurp_rela_relocs (file, rel_offset, rel_size, &rels, &rel_size))
4d6ed7c8
NC
806 return 0;
807 }
808 else
809 {
810 if (!slurp_rel_relocs (file, rel_offset, rel_size, &rels, &rel_size))
811 return 0;
252b5132
RH
812 }
813
410f7a12
L
814 if (is_32bit_elf)
815 {
816 if (is_rela)
2c71103e
NC
817 {
818 if (do_wide)
819 printf (_(" Offset Info Type Sym. Value Symbol's Name + Addend\n"));
820 else
821 printf (_(" Offset Info Type Sym.Value Sym. Name + Addend\n"));
822 }
410f7a12 823 else
2c71103e
NC
824 {
825 if (do_wide)
826 printf (_(" Offset Info Type Sym. Value Symbol's Name\n"));
827 else
828 printf (_(" Offset Info Type Sym.Value Sym. Name\n"));
829 }
410f7a12 830 }
252b5132 831 else
410f7a12
L
832 {
833 if (is_rela)
2c71103e
NC
834 {
835 if (do_wide)
8beeaeb7 836 printf (_(" Offset Info Type Symbol's Value Symbol's Name + Addend\n"));
2c71103e
NC
837 else
838 printf (_(" Offset Info Type Sym. Value Sym. Name + Addend\n"));
839 }
410f7a12 840 else
2c71103e
NC
841 {
842 if (do_wide)
8beeaeb7 843 printf (_(" Offset Info Type Symbol's Value Symbol's Name\n"));
2c71103e
NC
844 else
845 printf (_(" Offset Info Type Sym. Value Sym. Name\n"));
846 }
410f7a12 847 }
252b5132
RH
848
849 for (i = 0; i < rel_size; i++)
850 {
b34976b6
AM
851 const char *rtype;
852 const char *rtype2 = NULL;
853 const char *rtype3 = NULL;
854 bfd_vma offset;
855 bfd_vma info;
856 bfd_vma symtab_index;
857 bfd_vma type;
d3ba0551
AM
858 bfd_vma type2 = 0;
859 bfd_vma type3 = 0;
103f02d3 860
b34976b6
AM
861 offset = rels[i].r_offset;
862 info = rels[i].r_info;
103f02d3 863
9ea033b2
NC
864 if (is_32bit_elf)
865 {
866 type = ELF32_R_TYPE (info);
867 symtab_index = ELF32_R_SYM (info);
868 }
869 else
870 {
1a677ea8
RS
871 /* The #ifdef BFD64 below is to prevent a compile time warning.
872 We know that if we do not have a 64 bit data type that we
873 will never execute this code anyway. */
874#ifdef BFD64
53c7db4b 875 if (elf_header.e_machine == EM_MIPS)
2c71103e 876 {
1a677ea8
RS
877 /* In little-endian objects, r_info isn't really a 64-bit
878 little-endian value: it has a 32-bit little-endian
879 symbol index followed by four individual byte fields.
880 Reorder INFO accordingly. */
881 if (elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
882 info = (((info & 0xffffffff) << 32)
883 | ((info >> 56) & 0xff)
884 | ((info >> 40) & 0xff00)
885 | ((info >> 24) & 0xff0000)
886 | ((info >> 8) & 0xff000000));
2c71103e
NC
887 type = ELF64_MIPS_R_TYPE (info);
888 type2 = ELF64_MIPS_R_TYPE2 (info);
889 type3 = ELF64_MIPS_R_TYPE3 (info);
890 }
891 else if (elf_header.e_machine == EM_SPARCV9)
892 type = ELF64_R_TYPE_ID (info);
351b4b40 893 else
2c71103e 894 type = ELF64_R_TYPE (info);
1a677ea8 895
9ea033b2 896 symtab_index = ELF64_R_SYM (info);
a952a375 897#endif
9ea033b2 898 }
252b5132 899
410f7a12
L
900 if (is_32bit_elf)
901 {
902#ifdef _bfd_int64_low
903 printf ("%8.8lx %8.8lx ", _bfd_int64_low (offset), _bfd_int64_low (info));
904#else
905 printf ("%8.8lx %8.8lx ", offset, info);
906#endif
907 }
908 else
909 {
9ea033b2 910#ifdef _bfd_int64_low
2c71103e
NC
911 printf (do_wide
912 ? "%8.8lx%8.8lx %8.8lx%8.8lx "
913 : "%4.4lx%8.8lx %4.4lx%8.8lx ",
410f7a12
L
914 _bfd_int64_high (offset),
915 _bfd_int64_low (offset),
916 _bfd_int64_high (info),
917 _bfd_int64_low (info));
9ea033b2 918#else
2c71103e 919 printf (do_wide
25345be5 920 ? "%16.16lx %16.16lx "
2c71103e
NC
921 : "%12.12lx %12.12lx ",
922 offset, info);
9ea033b2 923#endif
410f7a12 924 }
103f02d3 925
252b5132
RH
926 switch (elf_header.e_machine)
927 {
928 default:
929 rtype = NULL;
930 break;
931
2b0337b0 932 case EM_M32R:
252b5132 933 case EM_CYGNUS_M32R:
9ea033b2 934 rtype = elf_m32r_reloc_type (type);
252b5132
RH
935 break;
936
937 case EM_386:
938 case EM_486:
9ea033b2 939 rtype = elf_i386_reloc_type (type);
252b5132
RH
940 break;
941
ba2685cc
AM
942 case EM_68HC11:
943 case EM_68HC12:
944 rtype = elf_m68hc11_reloc_type (type);
945 break;
75751cd9 946
252b5132 947 case EM_68K:
9ea033b2 948 rtype = elf_m68k_reloc_type (type);
252b5132
RH
949 break;
950
63fcb9e9 951 case EM_960:
9ea033b2 952 rtype = elf_i960_reloc_type (type);
63fcb9e9
ILT
953 break;
954
adde6300 955 case EM_AVR:
2b0337b0 956 case EM_AVR_OLD:
adde6300
AM
957 rtype = elf_avr_reloc_type (type);
958 break;
959
9ea033b2
NC
960 case EM_OLD_SPARCV9:
961 case EM_SPARC32PLUS:
962 case EM_SPARCV9:
252b5132 963 case EM_SPARC:
9ea033b2 964 rtype = elf_sparc_reloc_type (type);
252b5132
RH
965 break;
966
2b0337b0 967 case EM_V850:
252b5132 968 case EM_CYGNUS_V850:
9ea033b2 969 rtype = v850_reloc_type (type);
252b5132
RH
970 break;
971
2b0337b0 972 case EM_D10V:
252b5132 973 case EM_CYGNUS_D10V:
9ea033b2 974 rtype = elf_d10v_reloc_type (type);
252b5132
RH
975 break;
976
2b0337b0 977 case EM_D30V:
252b5132 978 case EM_CYGNUS_D30V:
9ea033b2 979 rtype = elf_d30v_reloc_type (type);
252b5132
RH
980 break;
981
d172d4ba
NC
982 case EM_DLX:
983 rtype = elf_dlx_reloc_type (type);
984 break;
985
252b5132 986 case EM_SH:
9ea033b2 987 rtype = elf_sh_reloc_type (type);
252b5132
RH
988 break;
989
2b0337b0 990 case EM_MN10300:
252b5132 991 case EM_CYGNUS_MN10300:
9ea033b2 992 rtype = elf_mn10300_reloc_type (type);
252b5132
RH
993 break;
994
2b0337b0 995 case EM_MN10200:
252b5132 996 case EM_CYGNUS_MN10200:
9ea033b2 997 rtype = elf_mn10200_reloc_type (type);
252b5132
RH
998 break;
999
2b0337b0 1000 case EM_FR30:
252b5132 1001 case EM_CYGNUS_FR30:
9ea033b2 1002 rtype = elf_fr30_reloc_type (type);
252b5132
RH
1003 break;
1004
ba2685cc
AM
1005 case EM_CYGNUS_FRV:
1006 rtype = elf_frv_reloc_type (type);
1007 break;
5c70f934 1008
252b5132 1009 case EM_MCORE:
9ea033b2 1010 rtype = elf_mcore_reloc_type (type);
252b5132
RH
1011 break;
1012
3c3bdf30
NC
1013 case EM_MMIX:
1014 rtype = elf_mmix_reloc_type (type);
1015 break;
1016
2469cfa2
NC
1017 case EM_MSP430:
1018 case EM_MSP430_OLD:
1019 rtype = elf_msp430_reloc_type (type);
1020 break;
1021
252b5132 1022 case EM_PPC:
9ea033b2 1023 rtype = elf_ppc_reloc_type (type);
252b5132
RH
1024 break;
1025
c833c019
AM
1026 case EM_PPC64:
1027 rtype = elf_ppc64_reloc_type (type);
1028 break;
1029
252b5132 1030 case EM_MIPS:
4fe85591 1031 case EM_MIPS_RS3_LE:
9ea033b2 1032 rtype = elf_mips_reloc_type (type);
53c7db4b 1033 if (!is_32bit_elf)
2c71103e
NC
1034 {
1035 rtype2 = elf_mips_reloc_type (type2);
1036 rtype3 = elf_mips_reloc_type (type3);
1037 }
252b5132
RH
1038 break;
1039
1040 case EM_ALPHA:
9ea033b2 1041 rtype = elf_alpha_reloc_type (type);
252b5132
RH
1042 break;
1043
1044 case EM_ARM:
9ea033b2 1045 rtype = elf_arm_reloc_type (type);
252b5132
RH
1046 break;
1047
584da044 1048 case EM_ARC:
9ea033b2 1049 rtype = elf_arc_reloc_type (type);
252b5132
RH
1050 break;
1051
1052 case EM_PARISC:
69e617ca 1053 rtype = elf_hppa_reloc_type (type);
252b5132 1054 break;
7d466069 1055
b8720f9d
JL
1056 case EM_H8_300:
1057 case EM_H8_300H:
1058 case EM_H8S:
1059 rtype = elf_h8_reloc_type (type);
1060 break;
1061
3b16e843
NC
1062 case EM_OPENRISC:
1063 case EM_OR32:
1064 rtype = elf_or32_reloc_type (type);
1065 break;
1066
7d466069 1067 case EM_PJ:
2b0337b0 1068 case EM_PJ_OLD:
7d466069
ILT
1069 rtype = elf_pj_reloc_type (type);
1070 break;
800eeca4
JW
1071 case EM_IA_64:
1072 rtype = elf_ia64_reloc_type (type);
1073 break;
1b61cf92
HPN
1074
1075 case EM_CRIS:
1076 rtype = elf_cris_reloc_type (type);
1077 break;
535c37ff
JE
1078
1079 case EM_860:
1080 rtype = elf_i860_reloc_type (type);
1081 break;
bcedfee6
NC
1082
1083 case EM_X86_64:
1084 rtype = elf_x86_64_reloc_type (type);
1085 break;
a85d7ed0 1086
35b1837e
AM
1087 case EM_S370:
1088 rtype = i370_reloc_type (type);
1089 break;
1090
53c7db4b
KH
1091 case EM_S390_OLD:
1092 case EM_S390:
1093 rtype = elf_s390_reloc_type (type);
1094 break;
93fbbb04
GK
1095
1096 case EM_XSTORMY16:
1097 rtype = elf_xstormy16_reloc_type (type);
1098 break;
179d3252 1099
1fe1f39c
NC
1100 case EM_CRX:
1101 rtype = elf_crx_reloc_type (type);
1102 break;
1103
179d3252
JT
1104 case EM_VAX:
1105 rtype = elf_vax_reloc_type (type);
1106 break;
1e4cf259
NC
1107
1108 case EM_IP2K:
1109 case EM_IP2K_OLD:
1110 rtype = elf_ip2k_reloc_type (type);
1111 break;
3b36097d
SC
1112
1113 case EM_IQ2000:
1114 rtype = elf_iq2000_reloc_type (type);
1115 break;
88da6820
NC
1116
1117 case EM_XTENSA_OLD:
1118 case EM_XTENSA:
1119 rtype = elf_xtensa_reloc_type (type);
1120 break;
a34e3ecb 1121
49f58d10
JB
1122 case EM_M32C:
1123 rtype = elf_m32c_reloc_type (type);
1124 break;
1125
d031aafb
NS
1126 case EM_MT:
1127 rtype = elf_mt_reloc_type (type);
a34e3ecb 1128 break;
1d65ded4
CM
1129
1130 case EM_BLACKFIN:
1131 rtype = elf_bfin_reloc_type (type);
1132 break;
1133
252b5132
RH
1134 }
1135
1136 if (rtype == NULL)
103f02d3 1137#ifdef _bfd_int64_low
2c71103e 1138 printf (_("unrecognized: %-7lx"), _bfd_int64_low (type));
9ea033b2 1139#else
2c71103e 1140 printf (_("unrecognized: %-7lx"), type);
9ea033b2 1141#endif
252b5132 1142 else
8beeaeb7 1143 printf (do_wide ? "%-22.22s" : "%-17.17s", rtype);
252b5132 1144
7ace3541
RH
1145 if (elf_header.e_machine == EM_ALPHA
1146 && streq (rtype, "R_ALPHA_LITUSE")
1147 && is_rela)
1148 {
1149 switch (rels[i].r_addend)
1150 {
1151 case LITUSE_ALPHA_ADDR: rtype = "ADDR"; break;
1152 case LITUSE_ALPHA_BASE: rtype = "BASE"; break;
1153 case LITUSE_ALPHA_BYTOFF: rtype = "BYTOFF"; break;
1154 case LITUSE_ALPHA_JSR: rtype = "JSR"; break;
1155 case LITUSE_ALPHA_TLSGD: rtype = "TLSGD"; break;
1156 case LITUSE_ALPHA_TLSLDM: rtype = "TLSLDM"; break;
1157 case LITUSE_ALPHA_JSRDIRECT: rtype = "JSRDIRECT"; break;
1158 default: rtype = NULL;
1159 }
1160 if (rtype)
1161 printf (" (%s)", rtype);
1162 else
1163 {
1164 putchar (' ');
1165 printf (_("<unknown addend: %lx>"),
1166 (unsigned long) rels[i].r_addend);
1167 }
1168 }
1169 else if (symtab_index)
252b5132 1170 {
af3fc3bc
AM
1171 if (symtab == NULL || symtab_index >= nsyms)
1172 printf (" bad symbol index: %08lx", (unsigned long) symtab_index);
1173 else
19936277 1174 {
b34976b6 1175 Elf_Internal_Sym *psym;
19936277 1176
af3fc3bc 1177 psym = symtab + symtab_index;
103f02d3 1178
af3fc3bc
AM
1179 printf (" ");
1180 print_vma (psym->st_value, LONG_HEX);
2c71103e 1181 printf (is_32bit_elf ? " " : " ");
103f02d3 1182
af3fc3bc 1183 if (psym->st_name == 0)
f1ef08cb
AM
1184 {
1185 const char *sec_name = "<null>";
1186 char name_buf[40];
1187
1188 if (ELF_ST_TYPE (psym->st_info) == STT_SECTION)
1189 {
1190 bfd_vma sec_index = (bfd_vma) -1;
1191
1192 if (psym->st_shndx < SHN_LORESERVE)
1193 sec_index = psym->st_shndx;
efcb5b0e 1194 else if (psym->st_shndx > SHN_HIRESERVE)
f1ef08cb
AM
1195 sec_index = psym->st_shndx - (SHN_HIRESERVE + 1
1196 - SHN_LORESERVE);
1197
1198 if (sec_index != (bfd_vma) -1)
1199 sec_name = SECTION_NAME (section_headers + sec_index);
1200 else if (psym->st_shndx == SHN_ABS)
1201 sec_name = "ABS";
1202 else if (psym->st_shndx == SHN_COMMON)
1203 sec_name = "COMMON";
3b22753a
L
1204 else if (elf_header.e_machine == EM_X86_64
1205 && psym->st_shndx == SHN_X86_64_LCOMMON)
1206 sec_name = "LARGE_COMMON";
9ce701e2
L
1207 else if (elf_header.e_machine == EM_IA_64
1208 && elf_header.e_ident[EI_OSABI] == ELFOSABI_HPUX
1209 && psym->st_shndx == SHN_IA_64_ANSI_COMMON)
1210 sec_name = "ANSI_COM";
f1ef08cb
AM
1211 else
1212 {
1213 sprintf (name_buf, "<section 0x%x>",
1214 (unsigned int) psym->st_shndx);
1215 sec_name = name_buf;
1216 }
1217 }
1218 print_symbol (22, sec_name);
1219 }
af3fc3bc 1220 else if (strtab == NULL)
d79b3d50 1221 printf (_("<string table index: %3ld>"), psym->st_name);
c256ffe7 1222 else if (psym->st_name >= strtablen)
d79b3d50 1223 printf (_("<corrupt string table index: %3ld>"), psym->st_name);
af3fc3bc 1224 else
2c71103e 1225 print_symbol (22, strtab + psym->st_name);
103f02d3 1226
af3fc3bc 1227 if (is_rela)
b34976b6 1228 printf (" + %lx", (unsigned long) rels[i].r_addend);
19936277 1229 }
252b5132 1230 }
1b228002 1231 else if (is_rela)
f7a99963 1232 {
18bd398b
NC
1233 printf ("%*c", is_32bit_elf ?
1234 (do_wide ? 34 : 28) : (do_wide ? 26 : 20), ' ');
c8286bd1 1235 print_vma (rels[i].r_addend, LONG_HEX);
f7a99963 1236 }
252b5132 1237
7ace3541 1238 if (elf_header.e_machine == EM_SPARCV9 && streq (rtype, "R_SPARC_OLO10"))
351b4b40
RH
1239 printf (" + %lx", (unsigned long) ELF64_R_TYPE_DATA (info));
1240
252b5132 1241 putchar ('\n');
2c71103e 1242
53c7db4b 1243 if (! is_32bit_elf && elf_header.e_machine == EM_MIPS)
2c71103e
NC
1244 {
1245 printf (" Type2: ");
1246
1247 if (rtype2 == NULL)
1248#ifdef _bfd_int64_low
1249 printf (_("unrecognized: %-7lx"), _bfd_int64_low (type2));
1250#else
1251 printf (_("unrecognized: %-7lx"), type2);
1252#endif
1253 else
1254 printf ("%-17.17s", rtype2);
1255
18bd398b 1256 printf ("\n Type3: ");
2c71103e
NC
1257
1258 if (rtype3 == NULL)
1259#ifdef _bfd_int64_low
1260 printf (_("unrecognized: %-7lx"), _bfd_int64_low (type3));
1261#else
1262 printf (_("unrecognized: %-7lx"), type3);
1263#endif
1264 else
1265 printf ("%-17.17s", rtype3);
1266
53c7db4b 1267 putchar ('\n');
2c71103e 1268 }
252b5132
RH
1269 }
1270
c8286bd1 1271 free (rels);
252b5132
RH
1272
1273 return 1;
1274}
1275
1276static const char *
d3ba0551 1277get_mips_dynamic_type (unsigned long type)
252b5132
RH
1278{
1279 switch (type)
1280 {
1281 case DT_MIPS_RLD_VERSION: return "MIPS_RLD_VERSION";
1282 case DT_MIPS_TIME_STAMP: return "MIPS_TIME_STAMP";
1283 case DT_MIPS_ICHECKSUM: return "MIPS_ICHECKSUM";
1284 case DT_MIPS_IVERSION: return "MIPS_IVERSION";
1285 case DT_MIPS_FLAGS: return "MIPS_FLAGS";
1286 case DT_MIPS_BASE_ADDRESS: return "MIPS_BASE_ADDRESS";
1287 case DT_MIPS_MSYM: return "MIPS_MSYM";
1288 case DT_MIPS_CONFLICT: return "MIPS_CONFLICT";
1289 case DT_MIPS_LIBLIST: return "MIPS_LIBLIST";
1290 case DT_MIPS_LOCAL_GOTNO: return "MIPS_LOCAL_GOTNO";
1291 case DT_MIPS_CONFLICTNO: return "MIPS_CONFLICTNO";
1292 case DT_MIPS_LIBLISTNO: return "MIPS_LIBLISTNO";
1293 case DT_MIPS_SYMTABNO: return "MIPS_SYMTABNO";
1294 case DT_MIPS_UNREFEXTNO: return "MIPS_UNREFEXTNO";
1295 case DT_MIPS_GOTSYM: return "MIPS_GOTSYM";
1296 case DT_MIPS_HIPAGENO: return "MIPS_HIPAGENO";
1297 case DT_MIPS_RLD_MAP: return "MIPS_RLD_MAP";
1298 case DT_MIPS_DELTA_CLASS: return "MIPS_DELTA_CLASS";
1299 case DT_MIPS_DELTA_CLASS_NO: return "MIPS_DELTA_CLASS_NO";
1300 case DT_MIPS_DELTA_INSTANCE: return "MIPS_DELTA_INSTANCE";
1301 case DT_MIPS_DELTA_INSTANCE_NO: return "MIPS_DELTA_INSTANCE_NO";
1302 case DT_MIPS_DELTA_RELOC: return "MIPS_DELTA_RELOC";
1303 case DT_MIPS_DELTA_RELOC_NO: return "MIPS_DELTA_RELOC_NO";
1304 case DT_MIPS_DELTA_SYM: return "MIPS_DELTA_SYM";
1305 case DT_MIPS_DELTA_SYM_NO: return "MIPS_DELTA_SYM_NO";
1306 case DT_MIPS_DELTA_CLASSSYM: return "MIPS_DELTA_CLASSSYM";
1307 case DT_MIPS_DELTA_CLASSSYM_NO: return "MIPS_DELTA_CLASSSYM_NO";
1308 case DT_MIPS_CXX_FLAGS: return "MIPS_CXX_FLAGS";
1309 case DT_MIPS_PIXIE_INIT: return "MIPS_PIXIE_INIT";
1310 case DT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB";
1311 case DT_MIPS_LOCALPAGE_GOTIDX: return "MIPS_LOCALPAGE_GOTIDX";
1312 case DT_MIPS_LOCAL_GOTIDX: return "MIPS_LOCAL_GOTIDX";
1313 case DT_MIPS_HIDDEN_GOTIDX: return "MIPS_HIDDEN_GOTIDX";
1314 case DT_MIPS_PROTECTED_GOTIDX: return "MIPS_PROTECTED_GOTIDX";
1315 case DT_MIPS_OPTIONS: return "MIPS_OPTIONS";
1316 case DT_MIPS_INTERFACE: return "MIPS_INTERFACE";
1317 case DT_MIPS_DYNSTR_ALIGN: return "MIPS_DYNSTR_ALIGN";
1318 case DT_MIPS_INTERFACE_SIZE: return "MIPS_INTERFACE_SIZE";
1319 case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: return "MIPS_RLD_TEXT_RESOLVE_ADDR";
1320 case DT_MIPS_PERF_SUFFIX: return "MIPS_PERF_SUFFIX";
1321 case DT_MIPS_COMPACT_SIZE: return "MIPS_COMPACT_SIZE";
1322 case DT_MIPS_GP_VALUE: return "MIPS_GP_VALUE";
1323 case DT_MIPS_AUX_DYNAMIC: return "MIPS_AUX_DYNAMIC";
1324 default:
1325 return NULL;
1326 }
1327}
1328
9a097730 1329static const char *
d3ba0551 1330get_sparc64_dynamic_type (unsigned long type)
9a097730
RH
1331{
1332 switch (type)
1333 {
1334 case DT_SPARC_REGISTER: return "SPARC_REGISTER";
1335 default:
1336 return NULL;
1337 }
103f02d3
UD
1338}
1339
7490d522
AM
1340static const char *
1341get_ppc_dynamic_type (unsigned long type)
1342{
1343 switch (type)
1344 {
1fe44d79 1345 case DT_PPC_GOT: return "PPC_GOT";
7490d522
AM
1346 default:
1347 return NULL;
1348 }
1349}
1350
f1cb7e17 1351static const char *
d3ba0551 1352get_ppc64_dynamic_type (unsigned long type)
f1cb7e17
AM
1353{
1354 switch (type)
1355 {
1356 case DT_PPC64_GLINK: return "PPC64_GLINK";
19397422
AM
1357 case DT_PPC64_OPD: return "PPC64_OPD";
1358 case DT_PPC64_OPDSZ: return "PPC64_OPDSZ";
f1cb7e17
AM
1359 default:
1360 return NULL;
1361 }
1362}
1363
103f02d3 1364static const char *
d3ba0551 1365get_parisc_dynamic_type (unsigned long type)
103f02d3
UD
1366{
1367 switch (type)
1368 {
1369 case DT_HP_LOAD_MAP: return "HP_LOAD_MAP";
1370 case DT_HP_DLD_FLAGS: return "HP_DLD_FLAGS";
1371 case DT_HP_DLD_HOOK: return "HP_DLD_HOOK";
1372 case DT_HP_UX10_INIT: return "HP_UX10_INIT";
1373 case DT_HP_UX10_INITSZ: return "HP_UX10_INITSZ";
1374 case DT_HP_PREINIT: return "HP_PREINIT";
1375 case DT_HP_PREINITSZ: return "HP_PREINITSZ";
1376 case DT_HP_NEEDED: return "HP_NEEDED";
1377 case DT_HP_TIME_STAMP: return "HP_TIME_STAMP";
1378 case DT_HP_CHECKSUM: return "HP_CHECKSUM";
1379 case DT_HP_GST_SIZE: return "HP_GST_SIZE";
1380 case DT_HP_GST_VERSION: return "HP_GST_VERSION";
1381 case DT_HP_GST_HASHVAL: return "HP_GST_HASHVAL";
eec8f817
DA
1382 case DT_HP_EPLTREL: return "HP_GST_EPLTREL";
1383 case DT_HP_EPLTRELSZ: return "HP_GST_EPLTRELSZ";
1384 case DT_HP_FILTERED: return "HP_FILTERED";
1385 case DT_HP_FILTER_TLS: return "HP_FILTER_TLS";
1386 case DT_HP_COMPAT_FILTERED: return "HP_COMPAT_FILTERED";
1387 case DT_HP_LAZYLOAD: return "HP_LAZYLOAD";
1388 case DT_HP_BIND_NOW_COUNT: return "HP_BIND_NOW_COUNT";
1389 case DT_PLT: return "PLT";
1390 case DT_PLT_SIZE: return "PLT_SIZE";
1391 case DT_DLT: return "DLT";
1392 case DT_DLT_SIZE: return "DLT_SIZE";
103f02d3
UD
1393 default:
1394 return NULL;
1395 }
1396}
9a097730 1397
ecc51f48 1398static const char *
d3ba0551 1399get_ia64_dynamic_type (unsigned long type)
ecc51f48
NC
1400{
1401 switch (type)
1402 {
1403 case DT_IA_64_PLT_RESERVE: return "IA_64_PLT_RESERVE";
1404 default:
1405 return NULL;
1406 }
1407}
1408
fabcb361
RH
1409static const char *
1410get_alpha_dynamic_type (unsigned long type)
1411{
1412 switch (type)
1413 {
1414 case DT_ALPHA_PLTRO: return "ALPHA_PLTRO";
1415 default:
1416 return NULL;
1417 }
1418}
1419
252b5132 1420static const char *
d3ba0551 1421get_dynamic_type (unsigned long type)
252b5132 1422{
e9e44622 1423 static char buff[64];
252b5132
RH
1424
1425 switch (type)
1426 {
1427 case DT_NULL: return "NULL";
1428 case DT_NEEDED: return "NEEDED";
1429 case DT_PLTRELSZ: return "PLTRELSZ";
1430 case DT_PLTGOT: return "PLTGOT";
1431 case DT_HASH: return "HASH";
1432 case DT_STRTAB: return "STRTAB";
1433 case DT_SYMTAB: return "SYMTAB";
1434 case DT_RELA: return "RELA";
1435 case DT_RELASZ: return "RELASZ";
1436 case DT_RELAENT: return "RELAENT";
1437 case DT_STRSZ: return "STRSZ";
1438 case DT_SYMENT: return "SYMENT";
1439 case DT_INIT: return "INIT";
1440 case DT_FINI: return "FINI";
1441 case DT_SONAME: return "SONAME";
1442 case DT_RPATH: return "RPATH";
1443 case DT_SYMBOLIC: return "SYMBOLIC";
1444 case DT_REL: return "REL";
1445 case DT_RELSZ: return "RELSZ";
1446 case DT_RELENT: return "RELENT";
1447 case DT_PLTREL: return "PLTREL";
1448 case DT_DEBUG: return "DEBUG";
1449 case DT_TEXTREL: return "TEXTREL";
1450 case DT_JMPREL: return "JMPREL";
1451 case DT_BIND_NOW: return "BIND_NOW";
1452 case DT_INIT_ARRAY: return "INIT_ARRAY";
1453 case DT_FINI_ARRAY: return "FINI_ARRAY";
1454 case DT_INIT_ARRAYSZ: return "INIT_ARRAYSZ";
1455 case DT_FINI_ARRAYSZ: return "FINI_ARRAYSZ";
d1133906
NC
1456 case DT_RUNPATH: return "RUNPATH";
1457 case DT_FLAGS: return "FLAGS";
2d0e6f43 1458
d1133906
NC
1459 case DT_PREINIT_ARRAY: return "PREINIT_ARRAY";
1460 case DT_PREINIT_ARRAYSZ: return "PREINIT_ARRAYSZ";
103f02d3 1461
05107a46 1462 case DT_CHECKSUM: return "CHECKSUM";
252b5132
RH
1463 case DT_PLTPADSZ: return "PLTPADSZ";
1464 case DT_MOVEENT: return "MOVEENT";
1465 case DT_MOVESZ: return "MOVESZ";
dcefbbbd 1466 case DT_FEATURE: return "FEATURE";
252b5132
RH
1467 case DT_POSFLAG_1: return "POSFLAG_1";
1468 case DT_SYMINSZ: return "SYMINSZ";
1469 case DT_SYMINENT: return "SYMINENT"; /* aka VALRNGHI */
103f02d3 1470
252b5132 1471 case DT_ADDRRNGLO: return "ADDRRNGLO";
dcefbbbd
L
1472 case DT_CONFIG: return "CONFIG";
1473 case DT_DEPAUDIT: return "DEPAUDIT";
1474 case DT_AUDIT: return "AUDIT";
1475 case DT_PLTPAD: return "PLTPAD";
1476 case DT_MOVETAB: return "MOVETAB";
252b5132 1477 case DT_SYMINFO: return "SYMINFO"; /* aka ADDRRNGHI */
103f02d3 1478
252b5132 1479 case DT_VERSYM: return "VERSYM";
103f02d3 1480
252b5132
RH
1481 case DT_RELACOUNT: return "RELACOUNT";
1482 case DT_RELCOUNT: return "RELCOUNT";
1483 case DT_FLAGS_1: return "FLAGS_1";
1484 case DT_VERDEF: return "VERDEF";
1485 case DT_VERDEFNUM: return "VERDEFNUM";
1486 case DT_VERNEED: return "VERNEED";
1487 case DT_VERNEEDNUM: return "VERNEEDNUM";
103f02d3 1488
019148e4 1489 case DT_AUXILIARY: return "AUXILIARY";
252b5132
RH
1490 case DT_USED: return "USED";
1491 case DT_FILTER: return "FILTER";
103f02d3 1492
047b2264
JJ
1493 case DT_GNU_PRELINKED: return "GNU_PRELINKED";
1494 case DT_GNU_CONFLICT: return "GNU_CONFLICT";
1495 case DT_GNU_CONFLICTSZ: return "GNU_CONFLICTSZ";
1496 case DT_GNU_LIBLIST: return "GNU_LIBLIST";
1497 case DT_GNU_LIBLISTSZ: return "GNU_LIBLISTSZ";
1498
252b5132
RH
1499 default:
1500 if ((type >= DT_LOPROC) && (type <= DT_HIPROC))
1501 {
b34976b6 1502 const char *result;
103f02d3 1503
252b5132
RH
1504 switch (elf_header.e_machine)
1505 {
1506 case EM_MIPS:
4fe85591 1507 case EM_MIPS_RS3_LE:
252b5132
RH
1508 result = get_mips_dynamic_type (type);
1509 break;
9a097730
RH
1510 case EM_SPARCV9:
1511 result = get_sparc64_dynamic_type (type);
1512 break;
7490d522
AM
1513 case EM_PPC:
1514 result = get_ppc_dynamic_type (type);
1515 break;
f1cb7e17
AM
1516 case EM_PPC64:
1517 result = get_ppc64_dynamic_type (type);
1518 break;
ecc51f48
NC
1519 case EM_IA_64:
1520 result = get_ia64_dynamic_type (type);
1521 break;
fabcb361
RH
1522 case EM_ALPHA:
1523 result = get_alpha_dynamic_type (type);
1524 break;
252b5132
RH
1525 default:
1526 result = NULL;
1527 break;
1528 }
1529
1530 if (result != NULL)
1531 return result;
1532
e9e44622 1533 snprintf (buff, sizeof (buff), _("Processor Specific: %lx"), type);
252b5132 1534 }
eec8f817
DA
1535 else if (((type >= DT_LOOS) && (type <= DT_HIOS))
1536 || (elf_header.e_machine == EM_PARISC
1537 && (type >= OLD_DT_LOOS) && (type <= OLD_DT_HIOS)))
103f02d3 1538 {
b34976b6 1539 const char *result;
103f02d3
UD
1540
1541 switch (elf_header.e_machine)
1542 {
1543 case EM_PARISC:
1544 result = get_parisc_dynamic_type (type);
1545 break;
1546 default:
1547 result = NULL;
1548 break;
1549 }
1550
1551 if (result != NULL)
1552 return result;
1553
e9e44622
JJ
1554 snprintf (buff, sizeof (buff), _("Operating System specific: %lx"),
1555 type);
103f02d3 1556 }
252b5132 1557 else
e9e44622 1558 snprintf (buff, sizeof (buff), _("<unknown>: %lx"), type);
103f02d3 1559
252b5132
RH
1560 return buff;
1561 }
1562}
1563
1564static char *
d3ba0551 1565get_file_type (unsigned e_type)
252b5132 1566{
b34976b6 1567 static char buff[32];
252b5132
RH
1568
1569 switch (e_type)
1570 {
1571 case ET_NONE: return _("NONE (None)");
1572 case ET_REL: return _("REL (Relocatable file)");
ba2685cc
AM
1573 case ET_EXEC: return _("EXEC (Executable file)");
1574 case ET_DYN: return _("DYN (Shared object file)");
1575 case ET_CORE: return _("CORE (Core file)");
252b5132
RH
1576
1577 default:
1578 if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC))
e9e44622 1579 snprintf (buff, sizeof (buff), _("Processor Specific: (%x)"), e_type);
252b5132 1580 else if ((e_type >= ET_LOOS) && (e_type <= ET_HIOS))
e9e44622 1581 snprintf (buff, sizeof (buff), _("OS Specific: (%x)"), e_type);
252b5132 1582 else
e9e44622 1583 snprintf (buff, sizeof (buff), _("<unknown>: %x"), e_type);
252b5132
RH
1584 return buff;
1585 }
1586}
1587
1588static char *
d3ba0551 1589get_machine_name (unsigned e_machine)
252b5132 1590{
b34976b6 1591 static char buff[64]; /* XXX */
252b5132
RH
1592
1593 switch (e_machine)
1594 {
c45021f2
NC
1595 case EM_NONE: return _("None");
1596 case EM_M32: return "WE32100";
1597 case EM_SPARC: return "Sparc";
1598 case EM_386: return "Intel 80386";
1599 case EM_68K: return "MC68000";
1600 case EM_88K: return "MC88000";
1601 case EM_486: return "Intel 80486";
1602 case EM_860: return "Intel 80860";
1603 case EM_MIPS: return "MIPS R3000";
1604 case EM_S370: return "IBM System/370";
7036c0e1 1605 case EM_MIPS_RS3_LE: return "MIPS R4000 big-endian";
252b5132 1606 case EM_OLD_SPARCV9: return "Sparc v9 (old)";
c45021f2 1607 case EM_PARISC: return "HPPA";
252b5132 1608 case EM_PPC_OLD: return "Power PC (old)";
7036c0e1 1609 case EM_SPARC32PLUS: return "Sparc v8+" ;
c45021f2
NC
1610 case EM_960: return "Intel 90860";
1611 case EM_PPC: return "PowerPC";
285d1771 1612 case EM_PPC64: return "PowerPC64";
c45021f2
NC
1613 case EM_V800: return "NEC V800";
1614 case EM_FR20: return "Fujitsu FR20";
1615 case EM_RH32: return "TRW RH32";
b34976b6 1616 case EM_MCORE: return "MCORE";
7036c0e1
AJ
1617 case EM_ARM: return "ARM";
1618 case EM_OLD_ALPHA: return "Digital Alpha (old)";
ef230218 1619 case EM_SH: return "Renesas / SuperH SH";
c45021f2
NC
1620 case EM_SPARCV9: return "Sparc v9";
1621 case EM_TRICORE: return "Siemens Tricore";
584da044 1622 case EM_ARC: return "ARC";
c2dcd04e
NC
1623 case EM_H8_300: return "Renesas H8/300";
1624 case EM_H8_300H: return "Renesas H8/300H";
1625 case EM_H8S: return "Renesas H8S";
1626 case EM_H8_500: return "Renesas H8/500";
30800947 1627 case EM_IA_64: return "Intel IA-64";
252b5132
RH
1628 case EM_MIPS_X: return "Stanford MIPS-X";
1629 case EM_COLDFIRE: return "Motorola Coldfire";
1630 case EM_68HC12: return "Motorola M68HC12";
c45021f2 1631 case EM_ALPHA: return "Alpha";
2b0337b0
AO
1632 case EM_CYGNUS_D10V:
1633 case EM_D10V: return "d10v";
1634 case EM_CYGNUS_D30V:
b34976b6 1635 case EM_D30V: return "d30v";
2b0337b0 1636 case EM_CYGNUS_M32R:
26597c86 1637 case EM_M32R: return "Renesas M32R (formerly Mitsubishi M32r)";
2b0337b0
AO
1638 case EM_CYGNUS_V850:
1639 case EM_V850: return "NEC v850";
1640 case EM_CYGNUS_MN10300:
1641 case EM_MN10300: return "mn10300";
1642 case EM_CYGNUS_MN10200:
1643 case EM_MN10200: return "mn10200";
1644 case EM_CYGNUS_FR30:
1645 case EM_FR30: return "Fujitsu FR30";
b34976b6 1646 case EM_CYGNUS_FRV: return "Fujitsu FR-V";
2b0337b0 1647 case EM_PJ_OLD:
b34976b6 1648 case EM_PJ: return "picoJava";
7036c0e1
AJ
1649 case EM_MMA: return "Fujitsu Multimedia Accelerator";
1650 case EM_PCP: return "Siemens PCP";
1651 case EM_NCPU: return "Sony nCPU embedded RISC processor";
1652 case EM_NDR1: return "Denso NDR1 microprocesspr";
1653 case EM_STARCORE: return "Motorola Star*Core processor";
1654 case EM_ME16: return "Toyota ME16 processor";
1655 case EM_ST100: return "STMicroelectronics ST100 processor";
1656 case EM_TINYJ: return "Advanced Logic Corp. TinyJ embedded processor";
1657 case EM_FX66: return "Siemens FX66 microcontroller";
1658 case EM_ST9PLUS: return "STMicroelectronics ST9+ 8/16 bit microcontroller";
1659 case EM_ST7: return "STMicroelectronics ST7 8-bit microcontroller";
1660 case EM_68HC16: return "Motorola MC68HC16 Microcontroller";
1661 case EM_68HC11: return "Motorola MC68HC11 Microcontroller";
1662 case EM_68HC08: return "Motorola MC68HC08 Microcontroller";
1663 case EM_68HC05: return "Motorola MC68HC05 Microcontroller";
1664 case EM_SVX: return "Silicon Graphics SVx";
1665 case EM_ST19: return "STMicroelectronics ST19 8-bit microcontroller";
1666 case EM_VAX: return "Digital VAX";
2b0337b0 1667 case EM_AVR_OLD:
b34976b6 1668 case EM_AVR: return "Atmel AVR 8-bit microcontroller";
1b61cf92 1669 case EM_CRIS: return "Axis Communications 32-bit embedded processor";
c45021f2
NC
1670 case EM_JAVELIN: return "Infineon Technologies 32-bit embedded cpu";
1671 case EM_FIREPATH: return "Element 14 64-bit DSP processor";
1672 case EM_ZSP: return "LSI Logic's 16-bit DSP processor";
b34976b6 1673 case EM_MMIX: return "Donald Knuth's educational 64-bit processor";
c45021f2 1674 case EM_HUANY: return "Harvard Universitys's machine-independent object format";
3b36097d 1675 case EM_PRISM: return "Vitesse Prism";
bcedfee6 1676 case EM_X86_64: return "Advanced Micro Devices X86-64";
b7498e0e 1677 case EM_S390_OLD:
b34976b6 1678 case EM_S390: return "IBM S/390";
93fbbb04 1679 case EM_XSTORMY16: return "Sanyo Xstormy16 CPU core";
3b16e843
NC
1680 case EM_OPENRISC:
1681 case EM_OR32: return "OpenRISC";
1fe1f39c 1682 case EM_CRX: return "National Semiconductor CRX microprocessor";
d172d4ba 1683 case EM_DLX: return "OpenDLX";
1e4cf259 1684 case EM_IP2K_OLD:
b34976b6 1685 case EM_IP2K: return "Ubicom IP2xxx 8-bit microcontrollers";
3b36097d 1686 case EM_IQ2000: return "Vitesse IQ2000";
88da6820
NC
1687 case EM_XTENSA_OLD:
1688 case EM_XTENSA: return "Tensilica Xtensa Processor";
49f58d10 1689 case EM_M32C: return "Renesas M32c";
d031aafb 1690 case EM_MT: return "Morpho Techologies MT processor";
7bbe5bc5 1691 case EM_BLACKFIN: return "Analog Devices Blackfin";
252b5132 1692 default:
e9e44622 1693 snprintf (buff, sizeof (buff), _("<unknown>: %x"), e_machine);
252b5132
RH
1694 return buff;
1695 }
1696}
1697
f3485b74 1698static void
d3ba0551 1699decode_ARM_machine_flags (unsigned e_flags, char buf[])
f3485b74
NC
1700{
1701 unsigned eabi;
1702 int unknown = 0;
1703
1704 eabi = EF_ARM_EABI_VERSION (e_flags);
1705 e_flags &= ~ EF_ARM_EABIMASK;
1706
1707 /* Handle "generic" ARM flags. */
1708 if (e_flags & EF_ARM_RELEXEC)
1709 {
1710 strcat (buf, ", relocatable executable");
1711 e_flags &= ~ EF_ARM_RELEXEC;
1712 }
76da6bbe 1713
f3485b74
NC
1714 if (e_flags & EF_ARM_HASENTRY)
1715 {
1716 strcat (buf, ", has entry point");
1717 e_flags &= ~ EF_ARM_HASENTRY;
1718 }
76da6bbe 1719
f3485b74
NC
1720 /* Now handle EABI specific flags. */
1721 switch (eabi)
1722 {
1723 default:
2c71103e 1724 strcat (buf, ", <unrecognized EABI>");
f3485b74
NC
1725 if (e_flags)
1726 unknown = 1;
1727 break;
1728
1729 case EF_ARM_EABI_VER1:
a5bcd848 1730 strcat (buf, ", Version1 EABI");
f3485b74
NC
1731 while (e_flags)
1732 {
1733 unsigned flag;
76da6bbe 1734
f3485b74
NC
1735 /* Process flags one bit at a time. */
1736 flag = e_flags & - e_flags;
1737 e_flags &= ~ flag;
76da6bbe 1738
f3485b74
NC
1739 switch (flag)
1740 {
a5bcd848 1741 case EF_ARM_SYMSARESORTED: /* Conflicts with EF_ARM_INTERWORK. */
f3485b74
NC
1742 strcat (buf, ", sorted symbol tables");
1743 break;
76da6bbe 1744
f3485b74
NC
1745 default:
1746 unknown = 1;
1747 break;
1748 }
1749 }
1750 break;
76da6bbe 1751
a5bcd848
PB
1752 case EF_ARM_EABI_VER2:
1753 strcat (buf, ", Version2 EABI");
1754 while (e_flags)
1755 {
1756 unsigned flag;
1757
1758 /* Process flags one bit at a time. */
1759 flag = e_flags & - e_flags;
1760 e_flags &= ~ flag;
1761
1762 switch (flag)
1763 {
1764 case EF_ARM_SYMSARESORTED: /* Conflicts with EF_ARM_INTERWORK. */
1765 strcat (buf, ", sorted symbol tables");
1766 break;
1767
1768 case EF_ARM_DYNSYMSUSESEGIDX:
1769 strcat (buf, ", dynamic symbols use segment index");
1770 break;
1771
1772 case EF_ARM_MAPSYMSFIRST:
1773 strcat (buf, ", mapping symbols precede others");
1774 break;
1775
1776 default:
1777 unknown = 1;
1778 break;
1779 }
1780 }
1781 break;
1782
d507cf36
PB
1783 case EF_ARM_EABI_VER3:
1784 strcat (buf, ", Version3 EABI");
8cb51566
PB
1785 break;
1786
1787 case EF_ARM_EABI_VER4:
1788 strcat (buf, ", Version4 EABI");
d507cf36
PB
1789 while (e_flags)
1790 {
1791 unsigned flag;
1792
1793 /* Process flags one bit at a time. */
1794 flag = e_flags & - e_flags;
1795 e_flags &= ~ flag;
1796
1797 switch (flag)
1798 {
1799 case EF_ARM_BE8:
1800 strcat (buf, ", BE8");
1801 break;
1802
1803 case EF_ARM_LE8:
1804 strcat (buf, ", LE8");
1805 break;
1806
1807 default:
1808 unknown = 1;
1809 break;
1810 }
1811 }
1812 break;
1813
f3485b74 1814 case EF_ARM_EABI_UNKNOWN:
a5bcd848 1815 strcat (buf, ", GNU EABI");
f3485b74
NC
1816 while (e_flags)
1817 {
1818 unsigned flag;
76da6bbe 1819
f3485b74
NC
1820 /* Process flags one bit at a time. */
1821 flag = e_flags & - e_flags;
1822 e_flags &= ~ flag;
76da6bbe 1823
f3485b74
NC
1824 switch (flag)
1825 {
a5bcd848 1826 case EF_ARM_INTERWORK:
f3485b74
NC
1827 strcat (buf, ", interworking enabled");
1828 break;
76da6bbe 1829
a5bcd848 1830 case EF_ARM_APCS_26:
f3485b74
NC
1831 strcat (buf, ", uses APCS/26");
1832 break;
76da6bbe 1833
a5bcd848 1834 case EF_ARM_APCS_FLOAT:
f3485b74
NC
1835 strcat (buf, ", uses APCS/float");
1836 break;
76da6bbe 1837
a5bcd848 1838 case EF_ARM_PIC:
f3485b74
NC
1839 strcat (buf, ", position independent");
1840 break;
76da6bbe 1841
a5bcd848 1842 case EF_ARM_ALIGN8:
f3485b74
NC
1843 strcat (buf, ", 8 bit structure alignment");
1844 break;
76da6bbe 1845
a5bcd848 1846 case EF_ARM_NEW_ABI:
f3485b74
NC
1847 strcat (buf, ", uses new ABI");
1848 break;
76da6bbe 1849
a5bcd848 1850 case EF_ARM_OLD_ABI:
f3485b74
NC
1851 strcat (buf, ", uses old ABI");
1852 break;
76da6bbe 1853
a5bcd848 1854 case EF_ARM_SOFT_FLOAT:
f3485b74
NC
1855 strcat (buf, ", software FP");
1856 break;
76da6bbe 1857
90e01f86
ILT
1858 case EF_ARM_VFP_FLOAT:
1859 strcat (buf, ", VFP");
1860 break;
1861
fde78edd
NC
1862 case EF_ARM_MAVERICK_FLOAT:
1863 strcat (buf, ", Maverick FP");
1864 break;
1865
f3485b74
NC
1866 default:
1867 unknown = 1;
1868 break;
1869 }
1870 }
1871 }
f3485b74
NC
1872
1873 if (unknown)
1874 strcat (buf,", <unknown>");
1875}
1876
252b5132 1877static char *
d3ba0551 1878get_machine_flags (unsigned e_flags, unsigned e_machine)
252b5132 1879{
b34976b6 1880 static char buf[1024];
252b5132
RH
1881
1882 buf[0] = '\0';
76da6bbe 1883
252b5132
RH
1884 if (e_flags)
1885 {
1886 switch (e_machine)
1887 {
1888 default:
1889 break;
1890
f3485b74
NC
1891 case EM_ARM:
1892 decode_ARM_machine_flags (e_flags, buf);
1893 break;
76da6bbe 1894
ec2dfb42
AO
1895 case EM_CYGNUS_FRV:
1896 switch (e_flags & EF_FRV_CPU_MASK)
1897 {
1898 case EF_FRV_CPU_GENERIC:
1899 break;
1900
1901 default:
1902 strcat (buf, ", fr???");
1903 break;
57346661 1904
ec2dfb42
AO
1905 case EF_FRV_CPU_FR300:
1906 strcat (buf, ", fr300");
1907 break;
1908
1909 case EF_FRV_CPU_FR400:
1910 strcat (buf, ", fr400");
1911 break;
1912 case EF_FRV_CPU_FR405:
1913 strcat (buf, ", fr405");
1914 break;
1915
1916 case EF_FRV_CPU_FR450:
1917 strcat (buf, ", fr450");
1918 break;
1919
1920 case EF_FRV_CPU_FR500:
1921 strcat (buf, ", fr500");
1922 break;
1923 case EF_FRV_CPU_FR550:
1924 strcat (buf, ", fr550");
1925 break;
1926
1927 case EF_FRV_CPU_SIMPLE:
1928 strcat (buf, ", simple");
1929 break;
1930 case EF_FRV_CPU_TOMCAT:
1931 strcat (buf, ", tomcat");
1932 break;
1933 }
1c877e87 1934 break;
ec2dfb42 1935
53c7db4b
KH
1936 case EM_68K:
1937 if (e_flags & EF_CPU32)
1938 strcat (buf, ", cpu32");
76f57f3a
JT
1939 if (e_flags & EF_M68000)
1940 strcat (buf, ", m68000");
53c7db4b 1941 break;
33c63f9d 1942
252b5132
RH
1943 case EM_PPC:
1944 if (e_flags & EF_PPC_EMB)
1945 strcat (buf, ", emb");
1946
1947 if (e_flags & EF_PPC_RELOCATABLE)
1948 strcat (buf, ", relocatable");
1949
1950 if (e_flags & EF_PPC_RELOCATABLE_LIB)
1951 strcat (buf, ", relocatable-lib");
1952 break;
1953
2b0337b0 1954 case EM_V850:
252b5132
RH
1955 case EM_CYGNUS_V850:
1956 switch (e_flags & EF_V850_ARCH)
1957 {
8ad30312
NC
1958 case E_V850E1_ARCH:
1959 strcat (buf, ", v850e1");
1960 break;
252b5132
RH
1961 case E_V850E_ARCH:
1962 strcat (buf, ", v850e");
1963 break;
252b5132
RH
1964 case E_V850_ARCH:
1965 strcat (buf, ", v850");
1966 break;
1967 default:
1968 strcat (buf, ", unknown v850 architecture variant");
1969 break;
1970 }
1971 break;
1972
2b0337b0 1973 case EM_M32R:
252b5132
RH
1974 case EM_CYGNUS_M32R:
1975 if ((e_flags & EF_M32R_ARCH) == E_M32R_ARCH)
1976 strcat (buf, ", m32r");
1977
1978 break;
1979
1980 case EM_MIPS:
4fe85591 1981 case EM_MIPS_RS3_LE:
252b5132
RH
1982 if (e_flags & EF_MIPS_NOREORDER)
1983 strcat (buf, ", noreorder");
1984
1985 if (e_flags & EF_MIPS_PIC)
1986 strcat (buf, ", pic");
1987
1988 if (e_flags & EF_MIPS_CPIC)
1989 strcat (buf, ", cpic");
1990
d1bdd336
TS
1991 if (e_flags & EF_MIPS_UCODE)
1992 strcat (buf, ", ugen_reserved");
1993
252b5132
RH
1994 if (e_flags & EF_MIPS_ABI2)
1995 strcat (buf, ", abi2");
1996
43521d43
TS
1997 if (e_flags & EF_MIPS_OPTIONS_FIRST)
1998 strcat (buf, ", odk first");
1999
a5d22d2a
TS
2000 if (e_flags & EF_MIPS_32BITMODE)
2001 strcat (buf, ", 32bitmode");
2002
156c2f8b
NC
2003 switch ((e_flags & EF_MIPS_MACH))
2004 {
2005 case E_MIPS_MACH_3900: strcat (buf, ", 3900"); break;
2006 case E_MIPS_MACH_4010: strcat (buf, ", 4010"); break;
2007 case E_MIPS_MACH_4100: strcat (buf, ", 4100"); break;
156c2f8b 2008 case E_MIPS_MACH_4111: strcat (buf, ", 4111"); break;
810dfa6e
L
2009 case E_MIPS_MACH_4120: strcat (buf, ", 4120"); break;
2010 case E_MIPS_MACH_4650: strcat (buf, ", 4650"); break;
2011 case E_MIPS_MACH_5400: strcat (buf, ", 5400"); break;
2012 case E_MIPS_MACH_5500: strcat (buf, ", 5500"); break;
c6c98b38 2013 case E_MIPS_MACH_SB1: strcat (buf, ", sb1"); break;
ebcb91b7 2014 case E_MIPS_MACH_9000: strcat (buf, ", 9000"); break;
43521d43
TS
2015 case 0:
2016 /* We simply ignore the field in this case to avoid confusion:
2017 MIPS ELF does not specify EF_MIPS_MACH, it is a GNU
2018 extension. */
2019 break;
2020 default: strcat (buf, ", unknown CPU"); break;
156c2f8b 2021 }
43521d43
TS
2022
2023 switch ((e_flags & EF_MIPS_ABI))
2024 {
2025 case E_MIPS_ABI_O32: strcat (buf, ", o32"); break;
2026 case E_MIPS_ABI_O64: strcat (buf, ", o64"); break;
2027 case E_MIPS_ABI_EABI32: strcat (buf, ", eabi32"); break;
2028 case E_MIPS_ABI_EABI64: strcat (buf, ", eabi64"); break;
2029 case 0:
2030 /* We simply ignore the field in this case to avoid confusion:
2031 MIPS ELF does not specify EF_MIPS_ABI, it is a GNU extension.
2032 This means it is likely to be an o32 file, but not for
2033 sure. */
2034 break;
2035 default: strcat (buf, ", unknown ABI"); break;
2036 }
2037
2038 if (e_flags & EF_MIPS_ARCH_ASE_MDMX)
2039 strcat (buf, ", mdmx");
2040
2041 if (e_flags & EF_MIPS_ARCH_ASE_M16)
2042 strcat (buf, ", mips16");
2043
2044 switch ((e_flags & EF_MIPS_ARCH))
2045 {
2046 case E_MIPS_ARCH_1: strcat (buf, ", mips1"); break;
2047 case E_MIPS_ARCH_2: strcat (buf, ", mips2"); break;
2048 case E_MIPS_ARCH_3: strcat (buf, ", mips3"); break;
2049 case E_MIPS_ARCH_4: strcat (buf, ", mips4"); break;
2050 case E_MIPS_ARCH_5: strcat (buf, ", mips5"); break;
2051 case E_MIPS_ARCH_32: strcat (buf, ", mips32"); break;
cb44e358 2052 case E_MIPS_ARCH_32R2: strcat (buf, ", mips32r2"); break;
43521d43 2053 case E_MIPS_ARCH_64: strcat (buf, ", mips64"); break;
5f74bc13 2054 case E_MIPS_ARCH_64R2: strcat (buf, ", mips64r2"); break;
43521d43
TS
2055 default: strcat (buf, ", unknown ISA"); break;
2056 }
2057
252b5132 2058 break;
351b4b40 2059
ccde1100
AO
2060 case EM_SH:
2061 switch ((e_flags & EF_SH_MACH_MASK))
2062 {
2063 case EF_SH1: strcat (buf, ", sh1"); break;
2064 case EF_SH2: strcat (buf, ", sh2"); break;
2065 case EF_SH3: strcat (buf, ", sh3"); break;
2066 case EF_SH_DSP: strcat (buf, ", sh-dsp"); break;
2067 case EF_SH3_DSP: strcat (buf, ", sh3-dsp"); break;
2068 case EF_SH4AL_DSP: strcat (buf, ", sh4al-dsp"); break;
2069 case EF_SH3E: strcat (buf, ", sh3e"); break;
2070 case EF_SH4: strcat (buf, ", sh4"); break;
2071 case EF_SH5: strcat (buf, ", sh5"); break;
2072 case EF_SH2E: strcat (buf, ", sh2e"); break;
2073 case EF_SH4A: strcat (buf, ", sh4a"); break;
1d70c7fb 2074 case EF_SH2A: strcat (buf, ", sh2a"); break;
ccde1100
AO
2075 case EF_SH4_NOFPU: strcat (buf, ", sh4-nofpu"); break;
2076 case EF_SH4A_NOFPU: strcat (buf, ", sh4a-nofpu"); break;
1d70c7fb 2077 case EF_SH2A_NOFPU: strcat (buf, ", sh2a-nofpu"); break;
dc85a459 2078 default: strcat (buf, ", unknown ISA"); break;
ccde1100
AO
2079 }
2080
2081 break;
57346661 2082
351b4b40
RH
2083 case EM_SPARCV9:
2084 if (e_flags & EF_SPARC_32PLUS)
2085 strcat (buf, ", v8+");
2086
2087 if (e_flags & EF_SPARC_SUN_US1)
d07faca2
RH
2088 strcat (buf, ", ultrasparcI");
2089
2090 if (e_flags & EF_SPARC_SUN_US3)
2091 strcat (buf, ", ultrasparcIII");
351b4b40
RH
2092
2093 if (e_flags & EF_SPARC_HAL_R1)
2094 strcat (buf, ", halr1");
2095
2096 if (e_flags & EF_SPARC_LEDATA)
2097 strcat (buf, ", ledata");
2098
2099 if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_TSO)
2100 strcat (buf, ", tso");
2101
2102 if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_PSO)
2103 strcat (buf, ", pso");
2104
2105 if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_RMO)
2106 strcat (buf, ", rmo");
2107 break;
7d466069 2108
103f02d3
UD
2109 case EM_PARISC:
2110 switch (e_flags & EF_PARISC_ARCH)
2111 {
2112 case EFA_PARISC_1_0:
2113 strcpy (buf, ", PA-RISC 1.0");
2114 break;
2115 case EFA_PARISC_1_1:
2116 strcpy (buf, ", PA-RISC 1.1");
2117 break;
2118 case EFA_PARISC_2_0:
2119 strcpy (buf, ", PA-RISC 2.0");
2120 break;
2121 default:
2122 break;
2123 }
2124 if (e_flags & EF_PARISC_TRAPNIL)
2125 strcat (buf, ", trapnil");
2126 if (e_flags & EF_PARISC_EXT)
2127 strcat (buf, ", ext");
2128 if (e_flags & EF_PARISC_LSB)
2129 strcat (buf, ", lsb");
2130 if (e_flags & EF_PARISC_WIDE)
2131 strcat (buf, ", wide");
2132 if (e_flags & EF_PARISC_NO_KABP)
2133 strcat (buf, ", no kabp");
2134 if (e_flags & EF_PARISC_LAZYSWAP)
2135 strcat (buf, ", lazyswap");
30800947 2136 break;
76da6bbe 2137
7d466069 2138 case EM_PJ:
2b0337b0 2139 case EM_PJ_OLD:
7d466069
ILT
2140 if ((e_flags & EF_PICOJAVA_NEWCALLS) == EF_PICOJAVA_NEWCALLS)
2141 strcat (buf, ", new calling convention");
2142
2143 if ((e_flags & EF_PICOJAVA_GNUCALLS) == EF_PICOJAVA_GNUCALLS)
2144 strcat (buf, ", gnu calling convention");
2145 break;
4d6ed7c8
NC
2146
2147 case EM_IA_64:
2148 if ((e_flags & EF_IA_64_ABI64))
2149 strcat (buf, ", 64-bit");
2150 else
2151 strcat (buf, ", 32-bit");
2152 if ((e_flags & EF_IA_64_REDUCEDFP))
2153 strcat (buf, ", reduced fp model");
2154 if ((e_flags & EF_IA_64_NOFUNCDESC_CONS_GP))
2155 strcat (buf, ", no function descriptors, constant gp");
2156 else if ((e_flags & EF_IA_64_CONS_GP))
2157 strcat (buf, ", constant gp");
2158 if ((e_flags & EF_IA_64_ABSOLUTE))
2159 strcat (buf, ", absolute");
2160 break;
179d3252
JT
2161
2162 case EM_VAX:
2163 if ((e_flags & EF_VAX_NONPIC))
2164 strcat (buf, ", non-PIC");
2165 if ((e_flags & EF_VAX_DFLOAT))
2166 strcat (buf, ", D-Float");
2167 if ((e_flags & EF_VAX_GFLOAT))
2168 strcat (buf, ", G-Float");
2169 break;
252b5132
RH
2170 }
2171 }
2172
2173 return buf;
2174}
2175
252b5132 2176static const char *
d3ba0551
AM
2177get_osabi_name (unsigned int osabi)
2178{
2179 static char buff[32];
2180
2181 switch (osabi)
2182 {
2183 case ELFOSABI_NONE: return "UNIX - System V";
2184 case ELFOSABI_HPUX: return "UNIX - HP-UX";
2185 case ELFOSABI_NETBSD: return "UNIX - NetBSD";
2186 case ELFOSABI_LINUX: return "UNIX - Linux";
2187 case ELFOSABI_HURD: return "GNU/Hurd";
2188 case ELFOSABI_SOLARIS: return "UNIX - Solaris";
2189 case ELFOSABI_AIX: return "UNIX - AIX";
2190 case ELFOSABI_IRIX: return "UNIX - IRIX";
2191 case ELFOSABI_FREEBSD: return "UNIX - FreeBSD";
2192 case ELFOSABI_TRU64: return "UNIX - TRU64";
2193 case ELFOSABI_MODESTO: return "Novell - Modesto";
2194 case ELFOSABI_OPENBSD: return "UNIX - OpenBSD";
2195 case ELFOSABI_OPENVMS: return "VMS - OpenVMS";
2196 case ELFOSABI_NSK: return "HP - Non-Stop Kernel";
2197 case ELFOSABI_AROS: return "Amiga Research OS";
2198 case ELFOSABI_STANDALONE: return _("Standalone App");
2199 case ELFOSABI_ARM: return "ARM";
2200 default:
e9e44622 2201 snprintf (buff, sizeof (buff), _("<unknown: %x>"), osabi);
d3ba0551
AM
2202 return buff;
2203 }
2204}
2205
b294bdf8
MM
2206static const char *
2207get_arm_segment_type (unsigned long type)
2208{
2209 switch (type)
2210 {
2211 case PT_ARM_EXIDX:
2212 return "EXIDX";
2213 default:
2214 break;
2215 }
2216
2217 return NULL;
2218}
2219
d3ba0551
AM
2220static const char *
2221get_mips_segment_type (unsigned long type)
252b5132
RH
2222{
2223 switch (type)
2224 {
2225 case PT_MIPS_REGINFO:
2226 return "REGINFO";
2227 case PT_MIPS_RTPROC:
2228 return "RTPROC";
2229 case PT_MIPS_OPTIONS:
2230 return "OPTIONS";
2231 default:
2232 break;
2233 }
2234
2235 return NULL;
2236}
2237
103f02d3 2238static const char *
d3ba0551 2239get_parisc_segment_type (unsigned long type)
103f02d3
UD
2240{
2241 switch (type)
2242 {
2243 case PT_HP_TLS: return "HP_TLS";
2244 case PT_HP_CORE_NONE: return "HP_CORE_NONE";
2245 case PT_HP_CORE_VERSION: return "HP_CORE_VERSION";
2246 case PT_HP_CORE_KERNEL: return "HP_CORE_KERNEL";
2247 case PT_HP_CORE_COMM: return "HP_CORE_COMM";
2248 case PT_HP_CORE_PROC: return "HP_CORE_PROC";
2249 case PT_HP_CORE_LOADABLE: return "HP_CORE_LOADABLE";
2250 case PT_HP_CORE_STACK: return "HP_CORE_STACK";
2251 case PT_HP_CORE_SHM: return "HP_CORE_SHM";
2252 case PT_HP_CORE_MMF: return "HP_CORE_MMF";
2253 case PT_HP_PARALLEL: return "HP_PARALLEL";
2254 case PT_HP_FASTBIND: return "HP_FASTBIND";
eec8f817
DA
2255 case PT_HP_OPT_ANNOT: return "HP_OPT_ANNOT";
2256 case PT_HP_HSL_ANNOT: return "HP_HSL_ANNOT";
2257 case PT_HP_STACK: return "HP_STACK";
2258 case PT_HP_CORE_UTSNAME: return "HP_CORE_UTSNAME";
103f02d3
UD
2259 case PT_PARISC_ARCHEXT: return "PARISC_ARCHEXT";
2260 case PT_PARISC_UNWIND: return "PARISC_UNWIND";
61472819 2261 case PT_PARISC_WEAKORDER: return "PARISC_WEAKORDER";
103f02d3
UD
2262 default:
2263 break;
2264 }
2265
2266 return NULL;
2267}
2268
4d6ed7c8 2269static const char *
d3ba0551 2270get_ia64_segment_type (unsigned long type)
4d6ed7c8
NC
2271{
2272 switch (type)
2273 {
2274 case PT_IA_64_ARCHEXT: return "IA_64_ARCHEXT";
2275 case PT_IA_64_UNWIND: return "IA_64_UNWIND";
00428cca
AM
2276 case PT_HP_TLS: return "HP_TLS";
2277 case PT_IA_64_HP_OPT_ANOT: return "HP_OPT_ANNOT";
2278 case PT_IA_64_HP_HSL_ANOT: return "HP_HSL_ANNOT";
2279 case PT_IA_64_HP_STACK: return "HP_STACK";
4d6ed7c8
NC
2280 default:
2281 break;
2282 }
2283
2284 return NULL;
2285}
2286
252b5132 2287static const char *
d3ba0551 2288get_segment_type (unsigned long p_type)
252b5132 2289{
b34976b6 2290 static char buff[32];
252b5132
RH
2291
2292 switch (p_type)
2293 {
b34976b6
AM
2294 case PT_NULL: return "NULL";
2295 case PT_LOAD: return "LOAD";
252b5132 2296 case PT_DYNAMIC: return "DYNAMIC";
b34976b6
AM
2297 case PT_INTERP: return "INTERP";
2298 case PT_NOTE: return "NOTE";
2299 case PT_SHLIB: return "SHLIB";
2300 case PT_PHDR: return "PHDR";
13ae64f3 2301 case PT_TLS: return "TLS";
252b5132 2302
65765700
JJ
2303 case PT_GNU_EH_FRAME:
2304 return "GNU_EH_FRAME";
fb7b006e 2305 case PT_GNU_STACK: return "GNU_STACK";
8c37241b 2306 case PT_GNU_RELRO: return "GNU_RELRO";
65765700 2307
252b5132
RH
2308 default:
2309 if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
2310 {
b34976b6 2311 const char *result;
103f02d3 2312
252b5132
RH
2313 switch (elf_header.e_machine)
2314 {
b294bdf8
MM
2315 case EM_ARM:
2316 result = get_arm_segment_type (p_type);
2317 break;
252b5132 2318 case EM_MIPS:
4fe85591 2319 case EM_MIPS_RS3_LE:
252b5132
RH
2320 result = get_mips_segment_type (p_type);
2321 break;
103f02d3
UD
2322 case EM_PARISC:
2323 result = get_parisc_segment_type (p_type);
2324 break;
4d6ed7c8
NC
2325 case EM_IA_64:
2326 result = get_ia64_segment_type (p_type);
2327 break;
252b5132
RH
2328 default:
2329 result = NULL;
2330 break;
2331 }
103f02d3 2332
252b5132
RH
2333 if (result != NULL)
2334 return result;
103f02d3 2335
252b5132
RH
2336 sprintf (buff, "LOPROC+%lx", p_type - PT_LOPROC);
2337 }
2338 else if ((p_type >= PT_LOOS) && (p_type <= PT_HIOS))
103f02d3 2339 {
b34976b6 2340 const char *result;
103f02d3
UD
2341
2342 switch (elf_header.e_machine)
2343 {
2344 case EM_PARISC:
2345 result = get_parisc_segment_type (p_type);
2346 break;
00428cca
AM
2347 case EM_IA_64:
2348 result = get_ia64_segment_type (p_type);
2349 break;
103f02d3
UD
2350 default:
2351 result = NULL;
2352 break;
2353 }
2354
2355 if (result != NULL)
2356 return result;
2357
2358 sprintf (buff, "LOOS+%lx", p_type - PT_LOOS);
2359 }
252b5132 2360 else
e9e44622 2361 snprintf (buff, sizeof (buff), _("<unknown>: %lx"), p_type);
252b5132
RH
2362
2363 return buff;
2364 }
2365}
2366
2367static const char *
d3ba0551 2368get_mips_section_type_name (unsigned int sh_type)
252b5132
RH
2369{
2370 switch (sh_type)
2371 {
b34976b6
AM
2372 case SHT_MIPS_LIBLIST: return "MIPS_LIBLIST";
2373 case SHT_MIPS_MSYM: return "MIPS_MSYM";
2374 case SHT_MIPS_CONFLICT: return "MIPS_CONFLICT";
2375 case SHT_MIPS_GPTAB: return "MIPS_GPTAB";
2376 case SHT_MIPS_UCODE: return "MIPS_UCODE";
2377 case SHT_MIPS_DEBUG: return "MIPS_DEBUG";
2378 case SHT_MIPS_REGINFO: return "MIPS_REGINFO";
2379 case SHT_MIPS_PACKAGE: return "MIPS_PACKAGE";
2380 case SHT_MIPS_PACKSYM: return "MIPS_PACKSYM";
2381 case SHT_MIPS_RELD: return "MIPS_RELD";
2382 case SHT_MIPS_IFACE: return "MIPS_IFACE";
2383 case SHT_MIPS_CONTENT: return "MIPS_CONTENT";
2384 case SHT_MIPS_OPTIONS: return "MIPS_OPTIONS";
2385 case SHT_MIPS_SHDR: return "MIPS_SHDR";
2386 case SHT_MIPS_FDESC: return "MIPS_FDESC";
2387 case SHT_MIPS_EXTSYM: return "MIPS_EXTSYM";
2388 case SHT_MIPS_DENSE: return "MIPS_DENSE";
2389 case SHT_MIPS_PDESC: return "MIPS_PDESC";
2390 case SHT_MIPS_LOCSYM: return "MIPS_LOCSYM";
2391 case SHT_MIPS_AUXSYM: return "MIPS_AUXSYM";
2392 case SHT_MIPS_OPTSYM: return "MIPS_OPTSYM";
2393 case SHT_MIPS_LOCSTR: return "MIPS_LOCSTR";
2394 case SHT_MIPS_LINE: return "MIPS_LINE";
2395 case SHT_MIPS_RFDESC: return "MIPS_RFDESC";
2396 case SHT_MIPS_DELTASYM: return "MIPS_DELTASYM";
2397 case SHT_MIPS_DELTAINST: return "MIPS_DELTAINST";
2398 case SHT_MIPS_DELTACLASS: return "MIPS_DELTACLASS";
2399 case SHT_MIPS_DWARF: return "MIPS_DWARF";
2400 case SHT_MIPS_DELTADECL: return "MIPS_DELTADECL";
2401 case SHT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB";
2402 case SHT_MIPS_EVENTS: return "MIPS_EVENTS";
2403 case SHT_MIPS_TRANSLATE: return "MIPS_TRANSLATE";
2404 case SHT_MIPS_PIXIE: return "MIPS_PIXIE";
2405 case SHT_MIPS_XLATE: return "MIPS_XLATE";
2406 case SHT_MIPS_XLATE_DEBUG: return "MIPS_XLATE_DEBUG";
2407 case SHT_MIPS_WHIRL: return "MIPS_WHIRL";
2408 case SHT_MIPS_EH_REGION: return "MIPS_EH_REGION";
2409 case SHT_MIPS_XLATE_OLD: return "MIPS_XLATE_OLD";
252b5132
RH
2410 case SHT_MIPS_PDR_EXCEPTION: return "MIPS_PDR_EXCEPTION";
2411 default:
2412 break;
2413 }
2414 return NULL;
2415}
2416
103f02d3 2417static const char *
d3ba0551 2418get_parisc_section_type_name (unsigned int sh_type)
103f02d3
UD
2419{
2420 switch (sh_type)
2421 {
2422 case SHT_PARISC_EXT: return "PARISC_EXT";
2423 case SHT_PARISC_UNWIND: return "PARISC_UNWIND";
2424 case SHT_PARISC_DOC: return "PARISC_DOC";
eec8f817
DA
2425 case SHT_PARISC_ANNOT: return "PARISC_ANNOT";
2426 case SHT_PARISC_SYMEXTN: return "PARISC_SYMEXTN";
2427 case SHT_PARISC_STUBS: return "PARISC_STUBS";
61472819 2428 case SHT_PARISC_DLKM: return "PARISC_DLKM";
103f02d3
UD
2429 default:
2430 break;
2431 }
2432 return NULL;
2433}
2434
4d6ed7c8 2435static const char *
d3ba0551 2436get_ia64_section_type_name (unsigned int sh_type)
4d6ed7c8 2437{
18bd398b 2438 /* If the top 8 bits are 0x78 the next 8 are the os/abi ID. */
ecc51f48
NC
2439 if ((sh_type & 0xFF000000) == SHT_IA_64_LOPSREG)
2440 return get_osabi_name ((sh_type & 0x00FF0000) >> 16);
0de14b54 2441
4d6ed7c8
NC
2442 switch (sh_type)
2443 {
ecc51f48
NC
2444 case SHT_IA_64_EXT: return "IA_64_EXT";
2445 case SHT_IA_64_UNWIND: return "IA_64_UNWIND";
2446 case SHT_IA_64_PRIORITY_INIT: return "IA_64_PRIORITY_INIT";
4d6ed7c8
NC
2447 default:
2448 break;
2449 }
2450 return NULL;
2451}
2452
d2b2c203
DJ
2453static const char *
2454get_x86_64_section_type_name (unsigned int sh_type)
2455{
2456 switch (sh_type)
2457 {
2458 case SHT_X86_64_UNWIND: return "X86_64_UNWIND";
2459 default:
2460 break;
2461 }
2462 return NULL;
2463}
2464
40a18ebd
NC
2465static const char *
2466get_arm_section_type_name (unsigned int sh_type)
2467{
2468 switch (sh_type)
2469 {
2470 case SHT_ARM_EXIDX:
2471 return "ARM_EXIDX";
ec1c4759
RE
2472 case SHT_ARM_PREEMPTMAP:
2473 return "ARM_PREEMPTMAP";
2474 case SHT_ARM_ATTRIBUTES:
2475 return "ARM_ATTRIBUTES";
40a18ebd
NC
2476 default:
2477 break;
2478 }
2479 return NULL;
2480}
2481
252b5132 2482static const char *
d3ba0551 2483get_section_type_name (unsigned int sh_type)
252b5132 2484{
b34976b6 2485 static char buff[32];
252b5132
RH
2486
2487 switch (sh_type)
2488 {
2489 case SHT_NULL: return "NULL";
2490 case SHT_PROGBITS: return "PROGBITS";
2491 case SHT_SYMTAB: return "SYMTAB";
2492 case SHT_STRTAB: return "STRTAB";
2493 case SHT_RELA: return "RELA";
2494 case SHT_HASH: return "HASH";
2495 case SHT_DYNAMIC: return "DYNAMIC";
2496 case SHT_NOTE: return "NOTE";
2497 case SHT_NOBITS: return "NOBITS";
2498 case SHT_REL: return "REL";
2499 case SHT_SHLIB: return "SHLIB";
2500 case SHT_DYNSYM: return "DYNSYM";
d1133906
NC
2501 case SHT_INIT_ARRAY: return "INIT_ARRAY";
2502 case SHT_FINI_ARRAY: return "FINI_ARRAY";
2503 case SHT_PREINIT_ARRAY: return "PREINIT_ARRAY";
93ebe586
NC
2504 case SHT_GROUP: return "GROUP";
2505 case SHT_SYMTAB_SHNDX: return "SYMTAB SECTION INDICIES";
252b5132
RH
2506 case SHT_GNU_verdef: return "VERDEF";
2507 case SHT_GNU_verneed: return "VERNEED";
2508 case SHT_GNU_versym: return "VERSYM";
b34976b6
AM
2509 case 0x6ffffff0: return "VERSYM";
2510 case 0x6ffffffc: return "VERDEF";
252b5132
RH
2511 case 0x7ffffffd: return "AUXILIARY";
2512 case 0x7fffffff: return "FILTER";
047b2264 2513 case SHT_GNU_LIBLIST: return "GNU_LIBLIST";
252b5132
RH
2514
2515 default:
2516 if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC))
2517 {
b34976b6 2518 const char *result;
252b5132
RH
2519
2520 switch (elf_header.e_machine)
2521 {
2522 case EM_MIPS:
4fe85591 2523 case EM_MIPS_RS3_LE:
252b5132
RH
2524 result = get_mips_section_type_name (sh_type);
2525 break;
103f02d3
UD
2526 case EM_PARISC:
2527 result = get_parisc_section_type_name (sh_type);
2528 break;
4d6ed7c8
NC
2529 case EM_IA_64:
2530 result = get_ia64_section_type_name (sh_type);
2531 break;
d2b2c203
DJ
2532 case EM_X86_64:
2533 result = get_x86_64_section_type_name (sh_type);
2534 break;
40a18ebd
NC
2535 case EM_ARM:
2536 result = get_arm_section_type_name (sh_type);
2537 break;
252b5132
RH
2538 default:
2539 result = NULL;
2540 break;
2541 }
2542
2543 if (result != NULL)
2544 return result;
2545
c91d0dfb 2546 sprintf (buff, "LOPROC+%x", sh_type - SHT_LOPROC);
252b5132
RH
2547 }
2548 else if ((sh_type >= SHT_LOOS) && (sh_type <= SHT_HIOS))
c91d0dfb 2549 sprintf (buff, "LOOS+%x", sh_type - SHT_LOOS);
252b5132 2550 else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER))
c91d0dfb 2551 sprintf (buff, "LOUSER+%x", sh_type - SHT_LOUSER);
252b5132 2552 else
e9e44622 2553 snprintf (buff, sizeof (buff), _("<unknown>: %x"), sh_type);
103f02d3 2554
252b5132
RH
2555 return buff;
2556 }
2557}
2558
2979dc34
JJ
2559#define OPTION_DEBUG_DUMP 512
2560
85b1c36d 2561static struct option options[] =
252b5132 2562{
b34976b6 2563 {"all", no_argument, 0, 'a'},
252b5132
RH
2564 {"file-header", no_argument, 0, 'h'},
2565 {"program-headers", no_argument, 0, 'l'},
b34976b6
AM
2566 {"headers", no_argument, 0, 'e'},
2567 {"histogram", no_argument, 0, 'I'},
2568 {"segments", no_argument, 0, 'l'},
2569 {"sections", no_argument, 0, 'S'},
252b5132 2570 {"section-headers", no_argument, 0, 'S'},
f5842774 2571 {"section-groups", no_argument, 0, 'g'},
5477e8a0 2572 {"section-details", no_argument, 0, 't'},
595cf52e 2573 {"full-section-name",no_argument, 0, 'N'},
b34976b6
AM
2574 {"symbols", no_argument, 0, 's'},
2575 {"syms", no_argument, 0, 's'},
2576 {"relocs", no_argument, 0, 'r'},
2577 {"notes", no_argument, 0, 'n'},
2578 {"dynamic", no_argument, 0, 'd'},
a952a375 2579 {"arch-specific", no_argument, 0, 'A'},
252b5132
RH
2580 {"version-info", no_argument, 0, 'V'},
2581 {"use-dynamic", no_argument, 0, 'D'},
b34976b6 2582 {"hex-dump", required_argument, 0, 'x'},
2979dc34 2583 {"debug-dump", optional_argument, 0, OPTION_DEBUG_DUMP},
4d6ed7c8 2584 {"unwind", no_argument, 0, 'u'},
252b5132
RH
2585#ifdef SUPPORT_DISASSEMBLY
2586 {"instruction-dump", required_argument, 0, 'i'},
2587#endif
2588
b34976b6
AM
2589 {"version", no_argument, 0, 'v'},
2590 {"wide", no_argument, 0, 'W'},
2591 {"help", no_argument, 0, 'H'},
2592 {0, no_argument, 0, 0}
252b5132
RH
2593};
2594
2595static void
d3ba0551 2596usage (void)
252b5132 2597{
8b53311e
NC
2598 fprintf (stdout, _("Usage: readelf <option(s)> elf-file(s)\n"));
2599 fprintf (stdout, _(" Display information about the contents of ELF format files\n"));
2600 fprintf (stdout, _(" Options are:\n\
2601 -a --all Equivalent to: -h -l -S -s -r -d -V -A -I\n\
2602 -h --file-header Display the ELF file header\n\
2603 -l --program-headers Display the program headers\n\
2604 --segments An alias for --program-headers\n\
2605 -S --section-headers Display the sections' header\n\
2606 --sections An alias for --section-headers\n\
f5842774 2607 -g --section-groups Display the section groups\n\
5477e8a0 2608 -t --section-details Display the section details\n\
8b53311e
NC
2609 -e --headers Equivalent to: -h -l -S\n\
2610 -s --syms Display the symbol table\n\
2611 --symbols An alias for --syms\n\
2612 -n --notes Display the core notes (if present)\n\
2613 -r --relocs Display the relocations (if present)\n\
2614 -u --unwind Display the unwind info (if present)\n\
b2d38a17 2615 -d --dynamic Display the dynamic section (if present)\n\
8b53311e
NC
2616 -V --version-info Display the version sections (if present)\n\
2617 -A --arch-specific Display architecture specific information (if any).\n\
2618 -D --use-dynamic Use the dynamic section info when displaying symbols\n\
2619 -x --hex-dump=<number> Dump the contents of section <number>\n\
18bd398b
NC
2620 -w[liaprmfFsoR] or\n\
2621 --debug-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]\n\
8b53311e 2622 Display the contents of DWARF2 debug sections\n"));
252b5132 2623#ifdef SUPPORT_DISASSEMBLY
8b53311e
NC
2624 fprintf (stdout, _("\
2625 -i --instruction-dump=<number>\n\
2626 Disassemble the contents of section <number>\n"));
252b5132 2627#endif
8b53311e
NC
2628 fprintf (stdout, _("\
2629 -I --histogram Display histogram of bucket list lengths\n\
2630 -W --wide Allow output width to exceed 80 characters\n\
07012eee 2631 @<file> Read options from <file>\n\
8b53311e
NC
2632 -H --help Display this information\n\
2633 -v --version Display the version number of readelf\n"));
8ad3436c 2634 fprintf (stdout, _("Report bugs to %s\n"), REPORT_BUGS_TO);
252b5132
RH
2635
2636 exit (0);
2637}
2638
18bd398b
NC
2639/* Record the fact that the user wants the contents of section number
2640 SECTION to be displayed using the method(s) encoded as flags bits
2641 in TYPE. Note, TYPE can be zero if we are creating the array for
2642 the first time. */
2643
252b5132 2644static void
d3ba0551 2645request_dump (unsigned int section, int type)
252b5132
RH
2646{
2647 if (section >= num_dump_sects)
2648 {
b34976b6 2649 char *new_dump_sects;
252b5132 2650
d3ba0551 2651 new_dump_sects = calloc (section + 1, 1);
252b5132
RH
2652
2653 if (new_dump_sects == NULL)
2654 error (_("Out of memory allocating dump request table."));
2655 else
2656 {
2657 /* Copy current flag settings. */
2658 memcpy (new_dump_sects, dump_sects, num_dump_sects);
2659
2660 free (dump_sects);
2661
2662 dump_sects = new_dump_sects;
2663 num_dump_sects = section + 1;
2664 }
2665 }
2666
2667 if (dump_sects)
b34976b6 2668 dump_sects[section] |= type;
252b5132
RH
2669
2670 return;
2671}
2672
aef1f6d0
DJ
2673/* Request a dump by section name. */
2674
2675static void
2676request_dump_byname (const char *section, int type)
2677{
2678 struct dump_list_entry *new_request;
2679
2680 new_request = malloc (sizeof (struct dump_list_entry));
2681 if (!new_request)
2682 error (_("Out of memory allocating dump request table."));
2683
2684 new_request->name = strdup (section);
2685 if (!new_request->name)
2686 error (_("Out of memory allocating dump request table."));
2687
2688 new_request->type = type;
2689
2690 new_request->next = dump_sects_byname;
2691 dump_sects_byname = new_request;
2692}
2693
252b5132 2694static void
d3ba0551 2695parse_args (int argc, char **argv)
252b5132
RH
2696{
2697 int c;
2698
2699 if (argc < 2)
2700 usage ();
2701
2702 while ((c = getopt_long
5477e8a0 2703 (argc, argv, "ersuahnldSDAINtgw::x:i:vVWH", options, NULL)) != EOF)
252b5132 2704 {
b34976b6
AM
2705 char *cp;
2706 int section;
252b5132
RH
2707
2708 switch (c)
2709 {
2710 case 0:
2711 /* Long options. */
2712 break;
2713 case 'H':
2714 usage ();
2715 break;
2716
2717 case 'a':
b34976b6
AM
2718 do_syms++;
2719 do_reloc++;
2720 do_unwind++;
2721 do_dynamic++;
2722 do_header++;
2723 do_sections++;
f5842774 2724 do_section_groups++;
b34976b6
AM
2725 do_segments++;
2726 do_version++;
2727 do_histogram++;
2728 do_arch++;
2729 do_notes++;
252b5132 2730 break;
f5842774
L
2731 case 'g':
2732 do_section_groups++;
2733 break;
5477e8a0 2734 case 't':
595cf52e 2735 case 'N':
5477e8a0
L
2736 do_sections++;
2737 do_section_details++;
595cf52e 2738 break;
252b5132 2739 case 'e':
b34976b6
AM
2740 do_header++;
2741 do_sections++;
2742 do_segments++;
252b5132 2743 break;
a952a375 2744 case 'A':
b34976b6 2745 do_arch++;
a952a375 2746 break;
252b5132 2747 case 'D':
b34976b6 2748 do_using_dynamic++;
252b5132
RH
2749 break;
2750 case 'r':
b34976b6 2751 do_reloc++;
252b5132 2752 break;
4d6ed7c8 2753 case 'u':
b34976b6 2754 do_unwind++;
4d6ed7c8 2755 break;
252b5132 2756 case 'h':
b34976b6 2757 do_header++;
252b5132
RH
2758 break;
2759 case 'l':
b34976b6 2760 do_segments++;
252b5132
RH
2761 break;
2762 case 's':
b34976b6 2763 do_syms++;
252b5132
RH
2764 break;
2765 case 'S':
b34976b6 2766 do_sections++;
252b5132
RH
2767 break;
2768 case 'd':
b34976b6 2769 do_dynamic++;
252b5132 2770 break;
a952a375 2771 case 'I':
b34976b6 2772 do_histogram++;
a952a375 2773 break;
779fe533 2774 case 'n':
b34976b6 2775 do_notes++;
779fe533 2776 break;
252b5132 2777 case 'x':
b34976b6 2778 do_dump++;
252b5132 2779 section = strtoul (optarg, & cp, 0);
b34976b6 2780 if (! *cp && section >= 0)
aef1f6d0
DJ
2781 request_dump (section, HEX_DUMP);
2782 else
2783 request_dump_byname (optarg, HEX_DUMP);
2784 break;
252b5132 2785 case 'w':
b34976b6 2786 do_dump++;
252b5132
RH
2787 if (optarg == 0)
2788 do_debugging = 1;
2789 else
2790 {
f662939a 2791 unsigned int index = 0;
53c7db4b 2792
252b5132 2793 do_debugging = 0;
252b5132 2794
f662939a
NC
2795 while (optarg[index])
2796 switch (optarg[index++])
2797 {
2798 case 'i':
2799 case 'I':
2800 do_debug_info = 1;
2801 break;
2802
2803 case 'a':
2804 case 'A':
2805 do_debug_abbrevs = 1;
2806 break;
2807
2808 case 'l':
2809 case 'L':
2810 do_debug_lines = 1;
2811 break;
2812
2813 case 'p':
2814 case 'P':
2815 do_debug_pubnames = 1;
2816 break;
2817
2818 case 'r':
f662939a
NC
2819 do_debug_aranges = 1;
2820 break;
2821
18bd398b
NC
2822 case 'R':
2823 do_debug_ranges = 1;
2824 break;
2825
f662939a
NC
2826 case 'F':
2827 do_debug_frames_interp = 1;
2828 case 'f':
2829 do_debug_frames = 1;
2830 break;
2831
2832 case 'm':
2833 case 'M':
2834 do_debug_macinfo = 1;
2835 break;
2836
261a45ad
NC
2837 case 's':
2838 case 'S':
2839 do_debug_str = 1;
2840 break;
2841
a2f14207
DB
2842 case 'o':
2843 case 'O':
2844 do_debug_loc = 1;
2845 break;
53c7db4b 2846
f662939a 2847 default:
2c71103e 2848 warn (_("Unrecognized debug option '%s'\n"), optarg);
f662939a
NC
2849 break;
2850 }
252b5132
RH
2851 }
2852 break;
2979dc34 2853 case OPTION_DEBUG_DUMP:
b34976b6 2854 do_dump++;
2979dc34
JJ
2855 if (optarg == 0)
2856 do_debugging = 1;
2857 else
2858 {
18bd398b
NC
2859 typedef struct
2860 {
2861 const char * option;
2862 int * variable;
2863 }
2864 debug_dump_long_opts;
2865
2866 debug_dump_long_opts opts_table [] =
2867 {
2868 /* Please keep this table alpha- sorted. */
2869 { "Ranges", & do_debug_ranges },
2870 { "abbrev", & do_debug_abbrevs },
2871 { "aranges", & do_debug_aranges },
2872 { "frames", & do_debug_frames },
2873 { "frames-interp", & do_debug_frames_interp },
2874 { "info", & do_debug_info },
2875 { "line", & do_debug_lines },
2876 { "loc", & do_debug_loc },
2877 { "macro", & do_debug_macinfo },
2878 { "pubnames", & do_debug_pubnames },
2879 /* This entry is for compatability
2880 with earlier versions of readelf. */
2881 { "ranges", & do_debug_aranges },
2882 { "str", & do_debug_str },
2883 { NULL, NULL }
2884 };
2885
2979dc34
JJ
2886 const char *p;
2887
2888 do_debugging = 0;
2889
2890 p = optarg;
2891 while (*p)
2892 {
18bd398b
NC
2893 debug_dump_long_opts * entry;
2894
2895 for (entry = opts_table; entry->option; entry++)
2979dc34 2896 {
18bd398b 2897 size_t len = strlen (entry->option);
2979dc34 2898
18bd398b 2899 if (strneq (p, entry->option, len)
2979dc34
JJ
2900 && (p[len] == ',' || p[len] == '\0'))
2901 {
18bd398b
NC
2902 * entry->variable = 1;
2903
2904 /* The --debug-dump=frames-interp option also
2905 enables the --debug-dump=frames option. */
2906 if (do_debug_frames_interp)
2907 do_debug_frames = 1;
2979dc34
JJ
2908
2909 p += len;
2910 break;
2911 }
2912 }
2913
18bd398b 2914 if (entry->option == NULL)
2979dc34
JJ
2915 {
2916 warn (_("Unrecognized debug option '%s'\n"), p);
2917 p = strchr (p, ',');
2918 if (p == NULL)
2919 break;
2920 }
2921
2922 if (*p == ',')
2923 p++;
2924 }
2925 }
2926 break;
252b5132
RH
2927#ifdef SUPPORT_DISASSEMBLY
2928 case 'i':
b34976b6 2929 do_dump++;
252b5132 2930 section = strtoul (optarg, & cp, 0);
b34976b6 2931 if (! *cp && section >= 0)
252b5132
RH
2932 {
2933 request_dump (section, DISASS_DUMP);
2934 break;
2935 }
2936 goto oops;
2937#endif
2938 case 'v':
2939 print_version (program_name);
2940 break;
2941 case 'V':
b34976b6 2942 do_version++;
252b5132 2943 break;
d974e256 2944 case 'W':
b34976b6 2945 do_wide++;
d974e256 2946 break;
252b5132 2947 default:
aef1f6d0 2948#ifdef SUPPORT_DISASSEMBLY
252b5132 2949 oops:
aef1f6d0 2950#endif
252b5132
RH
2951 /* xgettext:c-format */
2952 error (_("Invalid option '-%c'\n"), c);
2953 /* Drop through. */
2954 case '?':
2955 usage ();
2956 }
2957 }
2958
4d6ed7c8 2959 if (!do_dynamic && !do_syms && !do_reloc && !do_unwind && !do_sections
252b5132 2960 && !do_segments && !do_header && !do_dump && !do_version
f5842774
L
2961 && !do_histogram && !do_debugging && !do_arch && !do_notes
2962 && !do_section_groups)
252b5132
RH
2963 usage ();
2964 else if (argc < 3)
2965 {
2966 warn (_("Nothing to do.\n"));
18bd398b 2967 usage ();
252b5132
RH
2968 }
2969}
2970
2971static const char *
d3ba0551 2972get_elf_class (unsigned int elf_class)
252b5132 2973{
b34976b6 2974 static char buff[32];
103f02d3 2975
252b5132
RH
2976 switch (elf_class)
2977 {
2978 case ELFCLASSNONE: return _("none");
e3c8793a
NC
2979 case ELFCLASS32: return "ELF32";
2980 case ELFCLASS64: return "ELF64";
ab5e7794 2981 default:
e9e44622 2982 snprintf (buff, sizeof (buff), _("<unknown: %x>"), elf_class);
ab5e7794 2983 return buff;
252b5132
RH
2984 }
2985}
2986
2987static const char *
d3ba0551 2988get_data_encoding (unsigned int encoding)
252b5132 2989{
b34976b6 2990 static char buff[32];
103f02d3 2991
252b5132
RH
2992 switch (encoding)
2993 {
2994 case ELFDATANONE: return _("none");
33c63f9d
CM
2995 case ELFDATA2LSB: return _("2's complement, little endian");
2996 case ELFDATA2MSB: return _("2's complement, big endian");
103f02d3 2997 default:
e9e44622 2998 snprintf (buff, sizeof (buff), _("<unknown: %x>"), encoding);
ab5e7794 2999 return buff;
252b5132
RH
3000 }
3001}
3002
252b5132 3003/* Decode the data held in 'elf_header'. */
ee42cf8c 3004
252b5132 3005static int
d3ba0551 3006process_file_header (void)
252b5132 3007{
b34976b6
AM
3008 if ( elf_header.e_ident[EI_MAG0] != ELFMAG0
3009 || elf_header.e_ident[EI_MAG1] != ELFMAG1
3010 || elf_header.e_ident[EI_MAG2] != ELFMAG2
3011 || elf_header.e_ident[EI_MAG3] != ELFMAG3)
252b5132
RH
3012 {
3013 error
3014 (_("Not an ELF file - it has the wrong magic bytes at the start\n"));
3015 return 0;
3016 }
3017
3018 if (do_header)
3019 {
3020 int i;
3021
3022 printf (_("ELF Header:\n"));
3023 printf (_(" Magic: "));
b34976b6
AM
3024 for (i = 0; i < EI_NIDENT; i++)
3025 printf ("%2.2x ", elf_header.e_ident[i]);
252b5132
RH
3026 printf ("\n");
3027 printf (_(" Class: %s\n"),
b34976b6 3028 get_elf_class (elf_header.e_ident[EI_CLASS]));
252b5132 3029 printf (_(" Data: %s\n"),
b34976b6 3030 get_data_encoding (elf_header.e_ident[EI_DATA]));
252b5132 3031 printf (_(" Version: %d %s\n"),
b34976b6
AM
3032 elf_header.e_ident[EI_VERSION],
3033 (elf_header.e_ident[EI_VERSION] == EV_CURRENT
789be9f7 3034 ? "(current)"
b34976b6 3035 : (elf_header.e_ident[EI_VERSION] != EV_NONE
789be9f7
ILT
3036 ? "<unknown: %lx>"
3037 : "")));
252b5132 3038 printf (_(" OS/ABI: %s\n"),
b34976b6 3039 get_osabi_name (elf_header.e_ident[EI_OSABI]));
252b5132 3040 printf (_(" ABI Version: %d\n"),
b34976b6 3041 elf_header.e_ident[EI_ABIVERSION]);
252b5132
RH
3042 printf (_(" Type: %s\n"),
3043 get_file_type (elf_header.e_type));
3044 printf (_(" Machine: %s\n"),
3045 get_machine_name (elf_header.e_machine));
3046 printf (_(" Version: 0x%lx\n"),
3047 (unsigned long) elf_header.e_version);
76da6bbe 3048
f7a99963
NC
3049 printf (_(" Entry point address: "));
3050 print_vma ((bfd_vma) elf_header.e_entry, PREFIX_HEX);
3051 printf (_("\n Start of program headers: "));
3052 print_vma ((bfd_vma) elf_header.e_phoff, DEC);
3053 printf (_(" (bytes into file)\n Start of section headers: "));
3054 print_vma ((bfd_vma) elf_header.e_shoff, DEC);
3055 printf (_(" (bytes into file)\n"));
76da6bbe 3056
252b5132
RH
3057 printf (_(" Flags: 0x%lx%s\n"),
3058 (unsigned long) elf_header.e_flags,
3059 get_machine_flags (elf_header.e_flags, elf_header.e_machine));
3060 printf (_(" Size of this header: %ld (bytes)\n"),
3061 (long) elf_header.e_ehsize);
3062 printf (_(" Size of program headers: %ld (bytes)\n"),
3063 (long) elf_header.e_phentsize);
3064 printf (_(" Number of program headers: %ld\n"),
3065 (long) elf_header.e_phnum);
3066 printf (_(" Size of section headers: %ld (bytes)\n"),
3067 (long) elf_header.e_shentsize);
560f3c1c 3068 printf (_(" Number of section headers: %ld"),
252b5132 3069 (long) elf_header.e_shnum);
560f3c1c
AM
3070 if (section_headers != NULL && elf_header.e_shnum == 0)
3071 printf (" (%ld)", (long) section_headers[0].sh_size);
3072 putc ('\n', stdout);
3073 printf (_(" Section header string table index: %ld"),
252b5132 3074 (long) elf_header.e_shstrndx);
560f3c1c
AM
3075 if (section_headers != NULL && elf_header.e_shstrndx == SHN_XINDEX)
3076 printf (" (%ld)", (long) section_headers[0].sh_link);
3077 putc ('\n', stdout);
3078 }
3079
3080 if (section_headers != NULL)
3081 {
3082 if (elf_header.e_shnum == 0)
3083 elf_header.e_shnum = section_headers[0].sh_size;
3084 if (elf_header.e_shstrndx == SHN_XINDEX)
3085 elf_header.e_shstrndx = section_headers[0].sh_link;
3086 free (section_headers);
3087 section_headers = NULL;
252b5132 3088 }
103f02d3 3089
9ea033b2
NC
3090 return 1;
3091}
3092
252b5132 3093
9ea033b2 3094static int
d3ba0551 3095get_32bit_program_headers (FILE *file, Elf_Internal_Phdr *program_headers)
9ea033b2 3096{
b34976b6
AM
3097 Elf32_External_Phdr *phdrs;
3098 Elf32_External_Phdr *external;
3099 Elf_Internal_Phdr *internal;
3100 unsigned int i;
103f02d3 3101
d3ba0551 3102 phdrs = get_data (NULL, file, elf_header.e_phoff,
c256ffe7 3103 elf_header.e_phentsize, elf_header.e_phnum,
d3ba0551 3104 _("program headers"));
a6e9f9df
AM
3105 if (!phdrs)
3106 return 0;
9ea033b2
NC
3107
3108 for (i = 0, internal = program_headers, external = phdrs;
3109 i < elf_header.e_phnum;
b34976b6 3110 i++, internal++, external++)
252b5132 3111 {
9ea033b2
NC
3112 internal->p_type = BYTE_GET (external->p_type);
3113 internal->p_offset = BYTE_GET (external->p_offset);
3114 internal->p_vaddr = BYTE_GET (external->p_vaddr);
3115 internal->p_paddr = BYTE_GET (external->p_paddr);
3116 internal->p_filesz = BYTE_GET (external->p_filesz);
3117 internal->p_memsz = BYTE_GET (external->p_memsz);
3118 internal->p_flags = BYTE_GET (external->p_flags);
3119 internal->p_align = BYTE_GET (external->p_align);
252b5132
RH
3120 }
3121
9ea033b2
NC
3122 free (phdrs);
3123
252b5132
RH
3124 return 1;
3125}
3126
9ea033b2 3127static int
d3ba0551 3128get_64bit_program_headers (FILE *file, Elf_Internal_Phdr *program_headers)
9ea033b2 3129{
b34976b6
AM
3130 Elf64_External_Phdr *phdrs;
3131 Elf64_External_Phdr *external;
3132 Elf_Internal_Phdr *internal;
3133 unsigned int i;
103f02d3 3134
d3ba0551 3135 phdrs = get_data (NULL, file, elf_header.e_phoff,
c256ffe7 3136 elf_header.e_phentsize, elf_header.e_phnum,
d3ba0551 3137 _("program headers"));
a6e9f9df
AM
3138 if (!phdrs)
3139 return 0;
9ea033b2
NC
3140
3141 for (i = 0, internal = program_headers, external = phdrs;
3142 i < elf_header.e_phnum;
b34976b6 3143 i++, internal++, external++)
9ea033b2
NC
3144 {
3145 internal->p_type = BYTE_GET (external->p_type);
3146 internal->p_flags = BYTE_GET (external->p_flags);
66543521
AM
3147 internal->p_offset = BYTE_GET (external->p_offset);
3148 internal->p_vaddr = BYTE_GET (external->p_vaddr);
3149 internal->p_paddr = BYTE_GET (external->p_paddr);
3150 internal->p_filesz = BYTE_GET (external->p_filesz);
3151 internal->p_memsz = BYTE_GET (external->p_memsz);
3152 internal->p_align = BYTE_GET (external->p_align);
9ea033b2
NC
3153 }
3154
3155 free (phdrs);
3156
3157 return 1;
3158}
252b5132 3159
d93f0186
NC
3160/* Returns 1 if the program headers were read into `program_headers'. */
3161
3162static int
d3ba0551 3163get_program_headers (FILE *file)
d93f0186
NC
3164{
3165 Elf_Internal_Phdr *phdrs;
3166
3167 /* Check cache of prior read. */
3168 if (program_headers != NULL)
3169 return 1;
3170
c256ffe7 3171 phdrs = cmalloc (elf_header.e_phnum, sizeof (Elf_Internal_Phdr));
d93f0186
NC
3172
3173 if (phdrs == NULL)
3174 {
3175 error (_("Out of memory\n"));
3176 return 0;
3177 }
3178
3179 if (is_32bit_elf
3180 ? get_32bit_program_headers (file, phdrs)
3181 : get_64bit_program_headers (file, phdrs))
3182 {
3183 program_headers = phdrs;
3184 return 1;
3185 }
3186
3187 free (phdrs);
3188 return 0;
3189}
3190
2f62977e
NC
3191/* Returns 1 if the program headers were loaded. */
3192
252b5132 3193static int
d3ba0551 3194process_program_headers (FILE *file)
252b5132 3195{
b34976b6
AM
3196 Elf_Internal_Phdr *segment;
3197 unsigned int i;
252b5132
RH
3198
3199 if (elf_header.e_phnum == 0)
3200 {
3201 if (do_segments)
3202 printf (_("\nThere are no program headers in this file.\n"));
2f62977e 3203 return 0;
252b5132
RH
3204 }
3205
3206 if (do_segments && !do_header)
3207 {
f7a99963
NC
3208 printf (_("\nElf file type is %s\n"), get_file_type (elf_header.e_type));
3209 printf (_("Entry point "));
3210 print_vma ((bfd_vma) elf_header.e_entry, PREFIX_HEX);
3211 printf (_("\nThere are %d program headers, starting at offset "),
3212 elf_header.e_phnum);
3213 print_vma ((bfd_vma) elf_header.e_phoff, DEC);
3214 printf ("\n");
252b5132
RH
3215 }
3216
d93f0186 3217 if (! get_program_headers (file))
252b5132 3218 return 0;
103f02d3 3219
252b5132
RH
3220 if (do_segments)
3221 {
3a1a2036
NC
3222 if (elf_header.e_phnum > 1)
3223 printf (_("\nProgram Headers:\n"));
3224 else
3225 printf (_("\nProgram Headers:\n"));
76da6bbe 3226
f7a99963
NC
3227 if (is_32bit_elf)
3228 printf
3229 (_(" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n"));
d974e256
JJ
3230 else if (do_wide)
3231 printf
3232 (_(" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n"));
f7a99963
NC
3233 else
3234 {
3235 printf
3236 (_(" Type Offset VirtAddr PhysAddr\n"));
3237 printf
3238 (_(" FileSiz MemSiz Flags Align\n"));
3239 }
252b5132
RH
3240 }
3241
252b5132 3242 dynamic_addr = 0;
1b228002 3243 dynamic_size = 0;
252b5132
RH
3244
3245 for (i = 0, segment = program_headers;
3246 i < elf_header.e_phnum;
b34976b6 3247 i++, segment++)
252b5132
RH
3248 {
3249 if (do_segments)
3250 {
103f02d3 3251 printf (" %-14.14s ", get_segment_type (segment->p_type));
f7a99963
NC
3252
3253 if (is_32bit_elf)
3254 {
3255 printf ("0x%6.6lx ", (unsigned long) segment->p_offset);
3256 printf ("0x%8.8lx ", (unsigned long) segment->p_vaddr);
3257 printf ("0x%8.8lx ", (unsigned long) segment->p_paddr);
3258 printf ("0x%5.5lx ", (unsigned long) segment->p_filesz);
3259 printf ("0x%5.5lx ", (unsigned long) segment->p_memsz);
3260 printf ("%c%c%c ",
3261 (segment->p_flags & PF_R ? 'R' : ' '),
3262 (segment->p_flags & PF_W ? 'W' : ' '),
3263 (segment->p_flags & PF_X ? 'E' : ' '));
3264 printf ("%#lx", (unsigned long) segment->p_align);
3265 }
d974e256
JJ
3266 else if (do_wide)
3267 {
3268 if ((unsigned long) segment->p_offset == segment->p_offset)
3269 printf ("0x%6.6lx ", (unsigned long) segment->p_offset);
3270 else
3271 {
3272 print_vma (segment->p_offset, FULL_HEX);
3273 putchar (' ');
3274 }
3275
3276 print_vma (segment->p_vaddr, FULL_HEX);
3277 putchar (' ');
3278 print_vma (segment->p_paddr, FULL_HEX);
3279 putchar (' ');
3280
3281 if ((unsigned long) segment->p_filesz == segment->p_filesz)
3282 printf ("0x%6.6lx ", (unsigned long) segment->p_filesz);
3283 else
3284 {
3285 print_vma (segment->p_filesz, FULL_HEX);
3286 putchar (' ');
3287 }
3288
3289 if ((unsigned long) segment->p_memsz == segment->p_memsz)
3290 printf ("0x%6.6lx", (unsigned long) segment->p_memsz);
3291 else
3292 {
3293 print_vma (segment->p_offset, FULL_HEX);
3294 }
3295
3296 printf (" %c%c%c ",
3297 (segment->p_flags & PF_R ? 'R' : ' '),
3298 (segment->p_flags & PF_W ? 'W' : ' '),
3299 (segment->p_flags & PF_X ? 'E' : ' '));
3300
3301 if ((unsigned long) segment->p_align == segment->p_align)
3302 printf ("%#lx", (unsigned long) segment->p_align);
3303 else
3304 {
3305 print_vma (segment->p_align, PREFIX_HEX);
3306 }
3307 }
f7a99963
NC
3308 else
3309 {
3310 print_vma (segment->p_offset, FULL_HEX);
3311 putchar (' ');
3312 print_vma (segment->p_vaddr, FULL_HEX);
3313 putchar (' ');
3314 print_vma (segment->p_paddr, FULL_HEX);
3315 printf ("\n ");
3316 print_vma (segment->p_filesz, FULL_HEX);
3317 putchar (' ');
3318 print_vma (segment->p_memsz, FULL_HEX);
3319 printf (" %c%c%c ",
3320 (segment->p_flags & PF_R ? 'R' : ' '),
3321 (segment->p_flags & PF_W ? 'W' : ' '),
3322 (segment->p_flags & PF_X ? 'E' : ' '));
3323 print_vma (segment->p_align, HEX);
3324 }
252b5132
RH
3325 }
3326
3327 switch (segment->p_type)
3328 {
252b5132
RH
3329 case PT_DYNAMIC:
3330 if (dynamic_addr)
3331 error (_("more than one dynamic segment\n"));
3332
b2d38a17
NC
3333 /* Try to locate the .dynamic section. If there is
3334 a section header table, we can easily locate it. */
3335 if (section_headers != NULL)
3336 {
3337 Elf_Internal_Shdr *sec;
b2d38a17 3338
89fac5e3
RS
3339 sec = find_section (".dynamic");
3340 if (sec == NULL || sec->sh_size == 0)
b2d38a17
NC
3341 {
3342 error (_("no .dynamic section in the dynamic segment"));
3343 break;
3344 }
3345
3346 dynamic_addr = sec->sh_offset;
3347 dynamic_size = sec->sh_size;
3348
3349 if (dynamic_addr < segment->p_offset
3350 || dynamic_addr > segment->p_offset + segment->p_filesz)
3351 warn (_("the .dynamic section is not contained within the dynamic segment"));
3352 else if (dynamic_addr > segment->p_offset)
3353 warn (_("the .dynamic section is not the first section in the dynamic segment."));
3354 }
3355 else
3356 {
3357 /* Otherwise, we can only assume that the .dynamic
3358 section is the first section in the DYNAMIC segment. */
3359 dynamic_addr = segment->p_offset;
3360 dynamic_size = segment->p_filesz;
3361 }
252b5132
RH
3362 break;
3363
3364 case PT_INTERP:
fb52b2f4
NC
3365 if (fseek (file, archive_file_offset + (long) segment->p_offset,
3366 SEEK_SET))
252b5132
RH
3367 error (_("Unable to find program interpreter name\n"));
3368 else
3369 {
3370 program_interpreter[0] = 0;
3371 fscanf (file, "%63s", program_interpreter);
3372
3373 if (do_segments)
3374 printf (_("\n [Requesting program interpreter: %s]"),
3375 program_interpreter);
3376 }
3377 break;
3378 }
3379
3380 if (do_segments)
3381 putc ('\n', stdout);
3382 }
3383
c256ffe7 3384 if (do_segments && section_headers != NULL && string_table != NULL)
252b5132
RH
3385 {
3386 printf (_("\n Section to Segment mapping:\n"));
3387 printf (_(" Segment Sections...\n"));
3388
252b5132
RH
3389 for (i = 0; i < elf_header.e_phnum; i++)
3390 {
9ad5cbcf 3391 unsigned int j;
b34976b6 3392 Elf_Internal_Shdr *section;
252b5132
RH
3393
3394 segment = program_headers + i;
3395 section = section_headers;
3396
3397 printf (" %2.2d ", i);
3398
b34976b6 3399 for (j = 1; j < elf_header.e_shnum; j++, section++)
252b5132
RH
3400 {
3401 if (section->sh_size > 0
3402 /* Compare allocated sections by VMA, unallocated
3403 sections by file offset. */
3404 && (section->sh_flags & SHF_ALLOC
3405 ? (section->sh_addr >= segment->p_vaddr
3406 && section->sh_addr + section->sh_size
3407 <= segment->p_vaddr + segment->p_memsz)
b4c96d0d 3408 : ((bfd_vma) section->sh_offset >= segment->p_offset
252b5132 3409 && (section->sh_offset + section->sh_size
cbaa0dc5
AM
3410 <= segment->p_offset + segment->p_filesz)))
3411 /* .tbss is special. It doesn't contribute memory space
3412 to normal segments. */
3413 && (!((section->sh_flags & SHF_TLS) != 0
3414 && section->sh_type == SHT_NOBITS)
3415 || segment->p_type == PT_TLS))
252b5132
RH
3416 printf ("%s ", SECTION_NAME (section));
3417 }
3418
3419 putc ('\n',stdout);
3420 }
3421 }
3422
252b5132
RH
3423 return 1;
3424}
3425
3426
d93f0186
NC
3427/* Find the file offset corresponding to VMA by using the program headers. */
3428
3429static long
d3ba0551 3430offset_from_vma (FILE *file, bfd_vma vma, bfd_size_type size)
d93f0186
NC
3431{
3432 Elf_Internal_Phdr *seg;
3433
3434 if (! get_program_headers (file))
3435 {
3436 warn (_("Cannot interpret virtual addresses without program headers.\n"));
3437 return (long) vma;
3438 }
3439
3440 for (seg = program_headers;
3441 seg < program_headers + elf_header.e_phnum;
3442 ++seg)
3443 {
3444 if (seg->p_type != PT_LOAD)
3445 continue;
3446
3447 if (vma >= (seg->p_vaddr & -seg->p_align)
3448 && vma + size <= seg->p_vaddr + seg->p_filesz)
3449 return vma - seg->p_vaddr + seg->p_offset;
3450 }
3451
3452 warn (_("Virtual address 0x%lx not located in any PT_LOAD segment.\n"),
3453 (long) vma);
3454 return (long) vma;
3455}
3456
3457
252b5132 3458static int
d3ba0551 3459get_32bit_section_headers (FILE *file, unsigned int num)
252b5132 3460{
b34976b6
AM
3461 Elf32_External_Shdr *shdrs;
3462 Elf_Internal_Shdr *internal;
3463 unsigned int i;
252b5132 3464
d3ba0551 3465 shdrs = get_data (NULL, file, elf_header.e_shoff,
c256ffe7 3466 elf_header.e_shentsize, num, _("section headers"));
a6e9f9df
AM
3467 if (!shdrs)
3468 return 0;
252b5132 3469
c256ffe7 3470 section_headers = cmalloc (num, sizeof (Elf_Internal_Shdr));
252b5132
RH
3471
3472 if (section_headers == NULL)
3473 {
3474 error (_("Out of memory\n"));
3475 return 0;
3476 }
3477
3478 for (i = 0, internal = section_headers;
560f3c1c 3479 i < num;
b34976b6 3480 i++, internal++)
252b5132
RH
3481 {
3482 internal->sh_name = BYTE_GET (shdrs[i].sh_name);
3483 internal->sh_type = BYTE_GET (shdrs[i].sh_type);
3484 internal->sh_flags = BYTE_GET (shdrs[i].sh_flags);
3485 internal->sh_addr = BYTE_GET (shdrs[i].sh_addr);
3486 internal->sh_offset = BYTE_GET (shdrs[i].sh_offset);
3487 internal->sh_size = BYTE_GET (shdrs[i].sh_size);
3488 internal->sh_link = BYTE_GET (shdrs[i].sh_link);
3489 internal->sh_info = BYTE_GET (shdrs[i].sh_info);
3490 internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
3491 internal->sh_entsize = BYTE_GET (shdrs[i].sh_entsize);
3492 }
3493
3494 free (shdrs);
3495
3496 return 1;
3497}
3498
9ea033b2 3499static int
d3ba0551 3500get_64bit_section_headers (FILE *file, unsigned int num)
9ea033b2 3501{
b34976b6
AM
3502 Elf64_External_Shdr *shdrs;
3503 Elf_Internal_Shdr *internal;
3504 unsigned int i;
9ea033b2 3505
d3ba0551 3506 shdrs = get_data (NULL, file, elf_header.e_shoff,
c256ffe7 3507 elf_header.e_shentsize, num, _("section headers"));
a6e9f9df
AM
3508 if (!shdrs)
3509 return 0;
9ea033b2 3510
c256ffe7 3511 section_headers = cmalloc (num, sizeof (Elf_Internal_Shdr));
9ea033b2
NC
3512
3513 if (section_headers == NULL)
3514 {
3515 error (_("Out of memory\n"));
3516 return 0;
3517 }
3518
3519 for (i = 0, internal = section_headers;
560f3c1c 3520 i < num;
b34976b6 3521 i++, internal++)
9ea033b2
NC
3522 {
3523 internal->sh_name = BYTE_GET (shdrs[i].sh_name);
3524 internal->sh_type = BYTE_GET (shdrs[i].sh_type);
66543521
AM
3525 internal->sh_flags = BYTE_GET (shdrs[i].sh_flags);
3526 internal->sh_addr = BYTE_GET (shdrs[i].sh_addr);
3527 internal->sh_size = BYTE_GET (shdrs[i].sh_size);
3528 internal->sh_entsize = BYTE_GET (shdrs[i].sh_entsize);
9ea033b2
NC
3529 internal->sh_link = BYTE_GET (shdrs[i].sh_link);
3530 internal->sh_info = BYTE_GET (shdrs[i].sh_info);
3531 internal->sh_offset = BYTE_GET (shdrs[i].sh_offset);
3532 internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
3533 }
3534
3535 free (shdrs);
3536
3537 return 1;
3538}
3539
252b5132 3540static Elf_Internal_Sym *
d3ba0551 3541get_32bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
252b5132 3542{
9ad5cbcf 3543 unsigned long number;
b34976b6 3544 Elf32_External_Sym *esyms;
9ad5cbcf 3545 Elf_External_Sym_Shndx *shndx;
b34976b6
AM
3546 Elf_Internal_Sym *isyms;
3547 Elf_Internal_Sym *psym;
3548 unsigned int j;
252b5132 3549
c256ffe7 3550 esyms = get_data (NULL, file, section->sh_offset, 1, section->sh_size,
d3ba0551 3551 _("symbols"));
a6e9f9df
AM
3552 if (!esyms)
3553 return NULL;
252b5132 3554
9ad5cbcf
AM
3555 shndx = NULL;
3556 if (symtab_shndx_hdr != NULL
3557 && (symtab_shndx_hdr->sh_link
3558 == (unsigned long) SECTION_HEADER_NUM (section - section_headers)))
3559 {
d3ba0551 3560 shndx = get_data (NULL, file, symtab_shndx_hdr->sh_offset,
c256ffe7 3561 1, symtab_shndx_hdr->sh_size, _("symtab shndx"));
9ad5cbcf
AM
3562 if (!shndx)
3563 {
3564 free (esyms);
3565 return NULL;
3566 }
3567 }
3568
3569 number = section->sh_size / section->sh_entsize;
c256ffe7 3570 isyms = cmalloc (number, sizeof (Elf_Internal_Sym));
252b5132
RH
3571
3572 if (isyms == NULL)
3573 {
3574 error (_("Out of memory\n"));
9ad5cbcf
AM
3575 if (shndx)
3576 free (shndx);
252b5132 3577 free (esyms);
252b5132
RH
3578 return NULL;
3579 }
3580
3581 for (j = 0, psym = isyms;
3582 j < number;
b34976b6 3583 j++, psym++)
252b5132
RH
3584 {
3585 psym->st_name = BYTE_GET (esyms[j].st_name);
3586 psym->st_value = BYTE_GET (esyms[j].st_value);
3587 psym->st_size = BYTE_GET (esyms[j].st_size);
3588 psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
9ad5cbcf
AM
3589 if (psym->st_shndx == SHN_XINDEX && shndx != NULL)
3590 psym->st_shndx
3591 = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j]));
252b5132
RH
3592 psym->st_info = BYTE_GET (esyms[j].st_info);
3593 psym->st_other = BYTE_GET (esyms[j].st_other);
3594 }
3595
9ad5cbcf
AM
3596 if (shndx)
3597 free (shndx);
252b5132
RH
3598 free (esyms);
3599
3600 return isyms;
3601}
3602
9ea033b2 3603static Elf_Internal_Sym *
d3ba0551 3604get_64bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
9ea033b2 3605{
9ad5cbcf 3606 unsigned long number;
b34976b6 3607 Elf64_External_Sym *esyms;
9ad5cbcf 3608 Elf_External_Sym_Shndx *shndx;
b34976b6
AM
3609 Elf_Internal_Sym *isyms;
3610 Elf_Internal_Sym *psym;
3611 unsigned int j;
9ea033b2 3612
c256ffe7 3613 esyms = get_data (NULL, file, section->sh_offset, 1, section->sh_size,
d3ba0551 3614 _("symbols"));
a6e9f9df
AM
3615 if (!esyms)
3616 return NULL;
9ea033b2 3617
9ad5cbcf
AM
3618 shndx = NULL;
3619 if (symtab_shndx_hdr != NULL
3620 && (symtab_shndx_hdr->sh_link
3621 == (unsigned long) SECTION_HEADER_NUM (section - section_headers)))
3622 {
d3ba0551 3623 shndx = get_data (NULL, file, symtab_shndx_hdr->sh_offset,
c256ffe7 3624 1, symtab_shndx_hdr->sh_size, _("symtab shndx"));
9ad5cbcf
AM
3625 if (!shndx)
3626 {
3627 free (esyms);
3628 return NULL;
3629 }
3630 }
3631
3632 number = section->sh_size / section->sh_entsize;
c256ffe7 3633 isyms = cmalloc (number, sizeof (Elf_Internal_Sym));
9ea033b2
NC
3634
3635 if (isyms == NULL)
3636 {
3637 error (_("Out of memory\n"));
9ad5cbcf
AM
3638 if (shndx)
3639 free (shndx);
9ea033b2 3640 free (esyms);
9ea033b2
NC
3641 return NULL;
3642 }
3643
3644 for (j = 0, psym = isyms;
3645 j < number;
b34976b6 3646 j++, psym++)
9ea033b2
NC
3647 {
3648 psym->st_name = BYTE_GET (esyms[j].st_name);
3649 psym->st_info = BYTE_GET (esyms[j].st_info);
3650 psym->st_other = BYTE_GET (esyms[j].st_other);
3651 psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
9ad5cbcf
AM
3652 if (psym->st_shndx == SHN_XINDEX && shndx != NULL)
3653 psym->st_shndx
3654 = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j]));
66543521
AM
3655 psym->st_value = BYTE_GET (esyms[j].st_value);
3656 psym->st_size = BYTE_GET (esyms[j].st_size);
9ea033b2
NC
3657 }
3658
9ad5cbcf
AM
3659 if (shndx)
3660 free (shndx);
9ea033b2
NC
3661 free (esyms);
3662
3663 return isyms;
3664}
3665
d1133906 3666static const char *
d3ba0551 3667get_elf_section_flags (bfd_vma sh_flags)
d1133906 3668{
5477e8a0 3669 static char buff[1024];
e9e44622 3670 char *p = buff;
8d5ff12c
L
3671 int field_size = is_32bit_elf ? 8 : 16;
3672 int index, size = sizeof (buff) - (field_size + 4 + 1);
3673 bfd_vma os_flags = 0;
3674 bfd_vma proc_flags = 0;
3675 bfd_vma unknown_flags = 0;
5477e8a0
L
3676 const struct
3677 {
3678 const char *str;
3679 int len;
3680 }
3681 flags [] =
3682 {
3683 { "WRITE", 5 },
3684 { "ALLOC", 5 },
3685 { "EXEC", 4 },
3686 { "MERGE", 5 },
3687 { "STRINGS", 7 },
3688 { "INFO LINK", 9 },
3689 { "LINK ORDER", 10 },
3690 { "OS NONCONF", 10 },
3691 { "GROUP", 5 },
3692 { "TLS", 3 }
3693 };
3694
3695 if (do_section_details)
3696 {
8d5ff12c
L
3697 sprintf (buff, "[%*.*lx]: ",
3698 field_size, field_size, (unsigned long) sh_flags);
3699 p += field_size + 4;
5477e8a0 3700 }
76da6bbe 3701
d1133906
NC
3702 while (sh_flags)
3703 {
3704 bfd_vma flag;
3705
3706 flag = sh_flags & - sh_flags;
3707 sh_flags &= ~ flag;
76da6bbe 3708
5477e8a0 3709 if (do_section_details)
d1133906 3710 {
5477e8a0
L
3711 switch (flag)
3712 {
3713 case SHF_WRITE: index = 0; break;
3714 case SHF_ALLOC: index = 1; break;
3715 case SHF_EXECINSTR: index = 2; break;
3716 case SHF_MERGE: index = 3; break;
3717 case SHF_STRINGS: index = 4; break;
3718 case SHF_INFO_LINK: index = 5; break;
3719 case SHF_LINK_ORDER: index = 6; break;
3720 case SHF_OS_NONCONFORMING: index = 7; break;
3721 case SHF_GROUP: index = 8; break;
3722 case SHF_TLS: index = 9; break;
76da6bbe 3723
5477e8a0
L
3724 default:
3725 index = -1;
3726 break;
3727 }
3728
5477e8a0
L
3729 if (index != -1)
3730 {
8d5ff12c
L
3731 if (p != buff + field_size + 4)
3732 {
3733 if (size < (10 + 2))
3734 abort ();
3735 size -= 2;
3736 *p++ = ',';
3737 *p++ = ' ';
3738 }
3739
5477e8a0
L
3740 size -= flags [index].len;
3741 p = stpcpy (p, flags [index].str);
3742 }
3b22753a 3743 else if (flag & SHF_MASKOS)
8d5ff12c 3744 os_flags |= flag;
d1133906 3745 else if (flag & SHF_MASKPROC)
8d5ff12c 3746 proc_flags |= flag;
d1133906 3747 else
8d5ff12c 3748 unknown_flags |= flag;
5477e8a0
L
3749 }
3750 else
3751 {
3752 switch (flag)
3753 {
3754 case SHF_WRITE: *p = 'W'; break;
3755 case SHF_ALLOC: *p = 'A'; break;
3756 case SHF_EXECINSTR: *p = 'X'; break;
3757 case SHF_MERGE: *p = 'M'; break;
3758 case SHF_STRINGS: *p = 'S'; break;
3759 case SHF_INFO_LINK: *p = 'I'; break;
3760 case SHF_LINK_ORDER: *p = 'L'; break;
3761 case SHF_OS_NONCONFORMING: *p = 'O'; break;
3762 case SHF_GROUP: *p = 'G'; break;
3763 case SHF_TLS: *p = 'T'; break;
3764
3765 default:
3766 if (elf_header.e_machine == EM_X86_64
3767 && flag == SHF_X86_64_LARGE)
3768 *p = 'l';
3769 else if (flag & SHF_MASKOS)
3770 {
3771 *p = 'o';
3772 sh_flags &= ~ SHF_MASKOS;
3773 }
3774 else if (flag & SHF_MASKPROC)
3775 {
3776 *p = 'p';
3777 sh_flags &= ~ SHF_MASKPROC;
3778 }
3779 else
3780 *p = 'x';
3781 break;
3782 }
3783 p++;
d1133906
NC
3784 }
3785 }
76da6bbe 3786
8d5ff12c
L
3787 if (do_section_details)
3788 {
3789 if (os_flags)
3790 {
3791 size -= 5 + field_size;
3792 if (p != buff + field_size + 4)
3793 {
3794 if (size < (2 + 1))
3795 abort ();
3796 size -= 2;
3797 *p++ = ',';
3798 *p++ = ' ';
3799 }
3800 sprintf (p, "OS (%*.*lx)", field_size, field_size,
3801 (unsigned long) os_flags);
3802 p += 5 + field_size;
3803 }
3804 if (proc_flags)
3805 {
3806 size -= 7 + field_size;
3807 if (p != buff + field_size + 4)
3808 {
3809 if (size < (2 + 1))
3810 abort ();
3811 size -= 2;
3812 *p++ = ',';
3813 *p++ = ' ';
3814 }
3815 sprintf (p, "PROC (%*.*lx)", field_size, field_size,
3816 (unsigned long) proc_flags);
3817 p += 7 + field_size;
3818 }
3819 if (unknown_flags)
3820 {
3821 size -= 10 + field_size;
3822 if (p != buff + field_size + 4)
3823 {
3824 if (size < (2 + 1))
3825 abort ();
3826 size -= 2;
3827 *p++ = ',';
3828 *p++ = ' ';
3829 }
3830 sprintf (p, "UNKNOWN (%*.*lx)", field_size, field_size,
3831 (unsigned long) unknown_flags);
3832 p += 10 + field_size;
3833 }
3834 }
3835
e9e44622 3836 *p = '\0';
d1133906
NC
3837 return buff;
3838}
3839
252b5132 3840static int
d3ba0551 3841process_section_headers (FILE *file)
252b5132 3842{
b34976b6
AM
3843 Elf_Internal_Shdr *section;
3844 unsigned int i;
252b5132
RH
3845
3846 section_headers = NULL;
3847
3848 if (elf_header.e_shnum == 0)
3849 {
3850 if (do_sections)
3851 printf (_("\nThere are no sections in this file.\n"));
3852
3853 return 1;
3854 }
3855
3856 if (do_sections && !do_header)
9ea033b2 3857 printf (_("There are %d section headers, starting at offset 0x%lx:\n"),
252b5132
RH
3858 elf_header.e_shnum, (unsigned long) elf_header.e_shoff);
3859
9ea033b2
NC
3860 if (is_32bit_elf)
3861 {
560f3c1c 3862 if (! get_32bit_section_headers (file, elf_header.e_shnum))
9ea033b2
NC
3863 return 0;
3864 }
560f3c1c 3865 else if (! get_64bit_section_headers (file, elf_header.e_shnum))
252b5132
RH
3866 return 0;
3867
3868 /* Read in the string table, so that we have names to display. */
c256ffe7 3869 if (SECTION_HEADER_INDEX (elf_header.e_shstrndx) < elf_header.e_shnum)
252b5132 3870 {
c256ffe7 3871 section = SECTION_HEADER (elf_header.e_shstrndx);
d40ac9bd 3872
c256ffe7
JJ
3873 if (section->sh_size != 0)
3874 {
3875 string_table = get_data (NULL, file, section->sh_offset,
3876 1, section->sh_size, _("string table"));
0de14b54 3877
c256ffe7
JJ
3878 string_table_length = string_table != NULL ? section->sh_size : 0;
3879 }
252b5132
RH
3880 }
3881
3882 /* Scan the sections for the dynamic symbol table
e3c8793a 3883 and dynamic string table and debug sections. */
252b5132
RH
3884 dynamic_symbols = NULL;
3885 dynamic_strings = NULL;
3886 dynamic_syminfo = NULL;
f1ef08cb 3887 symtab_shndx_hdr = NULL;
103f02d3 3888
89fac5e3
RS
3889 eh_addr_size = is_32bit_elf ? 4 : 8;
3890 switch (elf_header.e_machine)
3891 {
3892 case EM_MIPS:
3893 case EM_MIPS_RS3_LE:
3894 /* The 64-bit MIPS EABI uses a combination of 32-bit ELF and 64-bit
3895 FDE addresses. However, the ABI also has a semi-official ILP32
3896 variant for which the normal FDE address size rules apply.
3897
3898 GCC 4.0 marks EABI64 objects with a dummy .gcc_compiled_longXX
3899 section, where XX is the size of longs in bits. Unfortunately,
3900 earlier compilers provided no way of distinguishing ILP32 objects
3901 from LP64 objects, so if there's any doubt, we should assume that
3902 the official LP64 form is being used. */
3903 if ((elf_header.e_flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI64
3904 && find_section (".gcc_compiled_long32") == NULL)
3905 eh_addr_size = 8;
3906 break;
3907 }
3908
08d8fa11
JJ
3909#define CHECK_ENTSIZE_VALUES(section, i, size32, size64) \
3910 do \
3911 { \
3912 size_t expected_entsize \
3913 = is_32bit_elf ? size32 : size64; \
3914 if (section->sh_entsize != expected_entsize) \
3915 error (_("Section %d has invalid sh_entsize %lx (expected %lx)\n"), \
3916 i, (unsigned long int) section->sh_entsize, \
3917 (unsigned long int) expected_entsize); \
3918 section->sh_entsize = expected_entsize; \
3919 } \
3920 while (0)
3921#define CHECK_ENTSIZE(section, i, type) \
3922 CHECK_ENTSIZE_VALUES (section, i, sizeof (Elf32_External_##type), \
3923 sizeof (Elf64_External_##type))
3924
252b5132
RH
3925 for (i = 0, section = section_headers;
3926 i < elf_header.e_shnum;
b34976b6 3927 i++, section++)
252b5132 3928 {
b34976b6 3929 char *name = SECTION_NAME (section);
252b5132
RH
3930
3931 if (section->sh_type == SHT_DYNSYM)
3932 {
3933 if (dynamic_symbols != NULL)
3934 {
3935 error (_("File contains multiple dynamic symbol tables\n"));
3936 continue;
3937 }
3938
08d8fa11 3939 CHECK_ENTSIZE (section, i, Sym);
19936277 3940 num_dynamic_syms = section->sh_size / section->sh_entsize;
9ad5cbcf 3941 dynamic_symbols = GET_ELF_SYMBOLS (file, section);
252b5132
RH
3942 }
3943 else if (section->sh_type == SHT_STRTAB
18bd398b 3944 && streq (name, ".dynstr"))
252b5132
RH
3945 {
3946 if (dynamic_strings != NULL)
3947 {
3948 error (_("File contains multiple dynamic string tables\n"));
3949 continue;
3950 }
3951
d3ba0551 3952 dynamic_strings = get_data (NULL, file, section->sh_offset,
c256ffe7 3953 1, section->sh_size, _("dynamic strings"));
d79b3d50 3954 dynamic_strings_length = section->sh_size;
252b5132 3955 }
9ad5cbcf
AM
3956 else if (section->sh_type == SHT_SYMTAB_SHNDX)
3957 {
3958 if (symtab_shndx_hdr != NULL)
3959 {
3960 error (_("File contains multiple symtab shndx tables\n"));
3961 continue;
3962 }
3963 symtab_shndx_hdr = section;
3964 }
08d8fa11
JJ
3965 else if (section->sh_type == SHT_SYMTAB)
3966 CHECK_ENTSIZE (section, i, Sym);
3967 else if (section->sh_type == SHT_GROUP)
3968 CHECK_ENTSIZE_VALUES (section, i, GRP_ENTRY_SIZE, GRP_ENTRY_SIZE);
3969 else if (section->sh_type == SHT_REL)
3970 CHECK_ENTSIZE (section, i, Rel);
3971 else if (section->sh_type == SHT_RELA)
3972 CHECK_ENTSIZE (section, i, Rela);
252b5132 3973 else if ((do_debugging || do_debug_info || do_debug_abbrevs
31b6fca6 3974 || do_debug_lines || do_debug_pubnames || do_debug_aranges
a2f14207 3975 || do_debug_frames || do_debug_macinfo || do_debug_str
18bd398b
NC
3976 || do_debug_loc || do_debug_ranges)
3977 && strneq (name, ".debug_", 7))
252b5132
RH
3978 {
3979 name += 7;
3980
3981 if (do_debugging
18bd398b
NC
3982 || (do_debug_info && streq (name, "info"))
3983 || (do_debug_abbrevs && streq (name, "abbrev"))
3984 || (do_debug_lines && streq (name, "line"))
3985 || (do_debug_pubnames && streq (name, "pubnames"))
3986 || (do_debug_aranges && streq (name, "aranges"))
3987 || (do_debug_ranges && streq (name, "ranges"))
3988 || (do_debug_frames && streq (name, "frame"))
3989 || (do_debug_macinfo && streq (name, "macinfo"))
3990 || (do_debug_str && streq (name, "str"))
3991 || (do_debug_loc && streq (name, "loc"))
252b5132
RH
3992 )
3993 request_dump (i, DEBUG_DUMP);
3994 }
09fd7e38
JM
3995 /* linkonce section to be combined with .debug_info at link time. */
3996 else if ((do_debugging || do_debug_info)
18bd398b 3997 && strneq (name, ".gnu.linkonce.wi.", 17))
09fd7e38 3998 request_dump (i, DEBUG_DUMP);
18bd398b 3999 else if (do_debug_frames && streq (name, ".eh_frame"))
c47d488e 4000 request_dump (i, DEBUG_DUMP);
252b5132
RH
4001 }
4002
4003 if (! do_sections)
4004 return 1;
4005
3a1a2036
NC
4006 if (elf_header.e_shnum > 1)
4007 printf (_("\nSection Headers:\n"));
4008 else
4009 printf (_("\nSection Header:\n"));
76da6bbe 4010
f7a99963 4011 if (is_32bit_elf)
595cf52e 4012 {
5477e8a0 4013 if (do_section_details)
595cf52e
L
4014 {
4015 printf (_(" [Nr] Name\n"));
5477e8a0 4016 printf (_(" Type Addr Off Size ES Lk Inf Al\n"));
595cf52e
L
4017 }
4018 else
4019 printf
4020 (_(" [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n"));
4021 }
d974e256 4022 else if (do_wide)
595cf52e 4023 {
5477e8a0 4024 if (do_section_details)
595cf52e
L
4025 {
4026 printf (_(" [Nr] Name\n"));
5477e8a0 4027 printf (_(" Type Address Off Size ES Lk Inf Al\n"));
595cf52e
L
4028 }
4029 else
4030 printf
4031 (_(" [Nr] Name Type Address Off Size ES Flg Lk Inf Al\n"));
4032 }
f7a99963
NC
4033 else
4034 {
5477e8a0 4035 if (do_section_details)
595cf52e
L
4036 {
4037 printf (_(" [Nr] Name\n"));
5477e8a0
L
4038 printf (_(" Type Address Offset Link\n"));
4039 printf (_(" Size EntSize Info Align\n"));
595cf52e
L
4040 }
4041 else
4042 {
4043 printf (_(" [Nr] Name Type Address Offset\n"));
4044 printf (_(" Size EntSize Flags Link Info Align\n"));
4045 }
f7a99963 4046 }
252b5132 4047
5477e8a0
L
4048 if (do_section_details)
4049 printf (_(" Flags\n"));
4050
252b5132
RH
4051 for (i = 0, section = section_headers;
4052 i < elf_header.e_shnum;
b34976b6 4053 i++, section++)
252b5132 4054 {
5477e8a0 4055 if (do_section_details)
595cf52e
L
4056 {
4057 printf (" [%2u] %s\n",
4058 SECTION_HEADER_NUM (i),
4059 SECTION_NAME (section));
4060 if (is_32bit_elf || do_wide)
4061 printf (" %-15.15s ",
4062 get_section_type_name (section->sh_type));
4063 }
4064 else
4065 printf (" [%2u] %-17.17s %-15.15s ",
4066 SECTION_HEADER_NUM (i),
4067 SECTION_NAME (section),
4068 get_section_type_name (section->sh_type));
252b5132 4069
f7a99963
NC
4070 if (is_32bit_elf)
4071 {
4072 print_vma (section->sh_addr, LONG_HEX);
76da6bbe 4073
f7a99963
NC
4074 printf ( " %6.6lx %6.6lx %2.2lx",
4075 (unsigned long) section->sh_offset,
4076 (unsigned long) section->sh_size,
4077 (unsigned long) section->sh_entsize);
d1133906 4078
5477e8a0
L
4079 if (do_section_details)
4080 fputs (" ", stdout);
4081 else
4082 printf (" %3s ", get_elf_section_flags (section->sh_flags));
76da6bbe 4083
f2da459f 4084 printf ("%2ld %3lu %2ld\n",
f7a99963
NC
4085 (unsigned long) section->sh_link,
4086 (unsigned long) section->sh_info,
4087 (unsigned long) section->sh_addralign);
4088 }
d974e256
JJ
4089 else if (do_wide)
4090 {
4091 print_vma (section->sh_addr, LONG_HEX);
4092
4093 if ((long) section->sh_offset == section->sh_offset)
4094 printf (" %6.6lx", (unsigned long) section->sh_offset);
4095 else
4096 {
4097 putchar (' ');
4098 print_vma (section->sh_offset, LONG_HEX);
4099 }
4100
4101 if ((unsigned long) section->sh_size == section->sh_size)
4102 printf (" %6.6lx", (unsigned long) section->sh_size);
4103 else
4104 {
4105 putchar (' ');
4106 print_vma (section->sh_size, LONG_HEX);
4107 }
4108
4109 if ((unsigned long) section->sh_entsize == section->sh_entsize)
4110 printf (" %2.2lx", (unsigned long) section->sh_entsize);
4111 else
4112 {
4113 putchar (' ');
4114 print_vma (section->sh_entsize, LONG_HEX);
4115 }
4116
5477e8a0
L
4117 if (do_section_details)
4118 fputs (" ", stdout);
4119 else
4120 printf (" %3s ", get_elf_section_flags (section->sh_flags));
d974e256 4121
f2da459f 4122 printf ("%2ld %3lu ",
d974e256
JJ
4123 (unsigned long) section->sh_link,
4124 (unsigned long) section->sh_info);
4125
4126 if ((unsigned long) section->sh_addralign == section->sh_addralign)
4127 printf ("%2ld\n", (unsigned long) section->sh_addralign);
4128 else
4129 {
4130 print_vma (section->sh_addralign, DEC);
4131 putchar ('\n');
4132 }
4133 }
5477e8a0 4134 else if (do_section_details)
595cf52e 4135 {
5477e8a0 4136 printf (" %-15.15s ",
595cf52e 4137 get_section_type_name (section->sh_type));
595cf52e
L
4138 print_vma (section->sh_addr, LONG_HEX);
4139 if ((long) section->sh_offset == section->sh_offset)
5477e8a0 4140 printf (" %16.16lx", (unsigned long) section->sh_offset);
595cf52e
L
4141 else
4142 {
4143 printf (" ");
4144 print_vma (section->sh_offset, LONG_HEX);
4145 }
5477e8a0 4146 printf (" %ld\n ", (unsigned long) section->sh_link);
595cf52e 4147 print_vma (section->sh_size, LONG_HEX);
5477e8a0 4148 putchar (' ');
595cf52e
L
4149 print_vma (section->sh_entsize, LONG_HEX);
4150
5477e8a0 4151 printf (" %-16lu %ld\n",
595cf52e
L
4152 (unsigned long) section->sh_info,
4153 (unsigned long) section->sh_addralign);
4154 }
f7a99963
NC
4155 else
4156 {
4157 putchar (' ');
4158 print_vma (section->sh_addr, LONG_HEX);
53c7db4b
KH
4159 if ((long) section->sh_offset == section->sh_offset)
4160 printf (" %8.8lx", (unsigned long) section->sh_offset);
4161 else
4162 {
4163 printf (" ");
4164 print_vma (section->sh_offset, LONG_HEX);
4165 }
f7a99963
NC
4166 printf ("\n ");
4167 print_vma (section->sh_size, LONG_HEX);
4168 printf (" ");
4169 print_vma (section->sh_entsize, LONG_HEX);
76da6bbe 4170
d1133906 4171 printf (" %3s ", get_elf_section_flags (section->sh_flags));
76da6bbe 4172
f2da459f 4173 printf (" %2ld %3lu %ld\n",
f7a99963
NC
4174 (unsigned long) section->sh_link,
4175 (unsigned long) section->sh_info,
4176 (unsigned long) section->sh_addralign);
4177 }
5477e8a0
L
4178
4179 if (do_section_details)
4180 printf (" %s\n", get_elf_section_flags (section->sh_flags));
252b5132
RH
4181 }
4182
5477e8a0
L
4183 if (!do_section_details)
4184 printf (_("Key to Flags:\n\
e3c8793a
NC
4185 W (write), A (alloc), X (execute), M (merge), S (strings)\n\
4186 I (info), L (link order), G (group), x (unknown)\n\
4187 O (extra OS processing required) o (OS specific), p (processor specific)\n"));
d1133906 4188
252b5132
RH
4189 return 1;
4190}
4191
f5842774
L
4192static const char *
4193get_group_flags (unsigned int flags)
4194{
4195 static char buff[32];
4196 switch (flags)
4197 {
4198 case GRP_COMDAT:
4199 return "COMDAT";
4200
4201 default:
e9e44622 4202 snprintf (buff, sizeof (buff), _("[<unknown>: 0x%x]"), flags);
f5842774
L
4203 break;
4204 }
4205 return buff;
4206}
4207
4208static int
4209process_section_groups (FILE *file)
4210{
4211 Elf_Internal_Shdr *section;
4212 unsigned int i;
e4b17d5c 4213 struct group *group;
d1f5c6e3
L
4214 Elf_Internal_Shdr *symtab_sec, *strtab_sec;
4215 Elf_Internal_Sym *symtab;
4216 char *strtab;
c256ffe7 4217 size_t strtab_size;
d1f5c6e3
L
4218
4219 /* Don't process section groups unless needed. */
4220 if (!do_unwind && !do_section_groups)
4221 return 1;
f5842774
L
4222
4223 if (elf_header.e_shnum == 0)
4224 {
4225 if (do_section_groups)
d1f5c6e3 4226 printf (_("\nThere are no sections in this file.\n"));
f5842774
L
4227
4228 return 1;
4229 }
4230
4231 if (section_headers == NULL)
4232 {
4233 error (_("Section headers are not available!\n"));
4234 abort ();
4235 }
4236
e4b17d5c
L
4237 section_headers_groups = calloc (elf_header.e_shnum,
4238 sizeof (struct group *));
4239
4240 if (section_headers_groups == NULL)
4241 {
4242 error (_("Out of memory\n"));
4243 return 0;
4244 }
4245
f5842774 4246 /* Scan the sections for the group section. */
d1f5c6e3 4247 group_count = 0;
f5842774
L
4248 for (i = 0, section = section_headers;
4249 i < elf_header.e_shnum;
4250 i++, section++)
e4b17d5c
L
4251 if (section->sh_type == SHT_GROUP)
4252 group_count++;
4253
d1f5c6e3
L
4254 if (group_count == 0)
4255 {
4256 if (do_section_groups)
4257 printf (_("\nThere are no section groups in this file.\n"));
4258
4259 return 1;
4260 }
4261
e4b17d5c
L
4262 section_groups = calloc (group_count, sizeof (struct group));
4263
4264 if (section_groups == NULL)
4265 {
4266 error (_("Out of memory\n"));
4267 return 0;
4268 }
4269
d1f5c6e3
L
4270 symtab_sec = NULL;
4271 strtab_sec = NULL;
4272 symtab = NULL;
4273 strtab = NULL;
c256ffe7 4274 strtab_size = 0;
e4b17d5c
L
4275 for (i = 0, section = section_headers, group = section_groups;
4276 i < elf_header.e_shnum;
4277 i++, section++)
f5842774
L
4278 {
4279 if (section->sh_type == SHT_GROUP)
4280 {
4281 char *name = SECTION_NAME (section);
dc3c06c2
AM
4282 char *group_name;
4283 unsigned char *start, *indices;
f5842774 4284 unsigned int entry, j, size;
d1f5c6e3 4285 Elf_Internal_Shdr *sec;
f5842774 4286 Elf_Internal_Sym *sym;
f5842774
L
4287
4288 /* Get the symbol table. */
c256ffe7
JJ
4289 if (SECTION_HEADER_INDEX (section->sh_link) >= elf_header.e_shnum
4290 || ((sec = SECTION_HEADER (section->sh_link))->sh_type
4291 != SHT_SYMTAB))
f5842774
L
4292 {
4293 error (_("Bad sh_link in group section `%s'\n"), name);
4294 continue;
4295 }
d1f5c6e3
L
4296
4297 if (symtab_sec != sec)
4298 {
4299 symtab_sec = sec;
4300 if (symtab)
4301 free (symtab);
4302 symtab = GET_ELF_SYMBOLS (file, symtab_sec);
4303 }
f5842774
L
4304
4305 sym = symtab + section->sh_info;
4306
4307 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
4308 {
4309 bfd_vma sec_index = SECTION_HEADER_INDEX (sym->st_shndx);
4310 if (sec_index == 0)
4311 {
4312 error (_("Bad sh_info in group section `%s'\n"), name);
4313 continue;
4314 }
ba2685cc 4315
f5842774 4316 group_name = SECTION_NAME (section_headers + sec_index);
c256ffe7
JJ
4317 strtab_sec = NULL;
4318 if (strtab)
4319 free (strtab);
f5842774 4320 strtab = NULL;
c256ffe7 4321 strtab_size = 0;
f5842774
L
4322 }
4323 else
4324 {
4325 /* Get the string table. */
c256ffe7
JJ
4326 if (SECTION_HEADER_INDEX (symtab_sec->sh_link)
4327 >= elf_header.e_shnum)
4328 {
4329 strtab_sec = NULL;
4330 if (strtab)
4331 free (strtab);
4332 strtab = NULL;
4333 strtab_size = 0;
4334 }
4335 else if (strtab_sec
4336 != (sec = SECTION_HEADER (symtab_sec->sh_link)))
d1f5c6e3
L
4337 {
4338 strtab_sec = sec;
4339 if (strtab)
4340 free (strtab);
4341 strtab = get_data (NULL, file, strtab_sec->sh_offset,
c256ffe7 4342 1, strtab_sec->sh_size,
d1f5c6e3 4343 _("string table"));
c256ffe7 4344 strtab_size = strtab != NULL ? strtab_sec->sh_size : 0;
d1f5c6e3 4345 }
c256ffe7
JJ
4346 group_name = sym->st_name < strtab_size
4347 ? strtab + sym->st_name : "<corrupt>";
f5842774
L
4348 }
4349
4350 start = get_data (NULL, file, section->sh_offset,
c256ffe7 4351 1, section->sh_size, _("section data"));
f5842774
L
4352
4353 indices = start;
4354 size = (section->sh_size / section->sh_entsize) - 1;
4355 entry = byte_get (indices, 4);
4356 indices += 4;
e4b17d5c
L
4357
4358 if (do_section_groups)
4359 {
391cb864
L
4360 printf ("\n%s group section [%5u] `%s' [%s] contains %u sections:\n",
4361 get_group_flags (entry), i, name, group_name, size);
ba2685cc 4362
e4b17d5c
L
4363 printf (_(" [Index] Name\n"));
4364 }
4365
4366 group->group_index = i;
4367
f5842774
L
4368 for (j = 0; j < size; j++)
4369 {
e4b17d5c
L
4370 struct group_list *g;
4371
f5842774
L
4372 entry = byte_get (indices, 4);
4373 indices += 4;
4374
c256ffe7 4375 if (SECTION_HEADER_INDEX (entry) >= elf_header.e_shnum)
391cb864
L
4376 {
4377 error (_("section [%5u] in group section [%5u] > maximum section [%5u]\n"),
4378 entry, i, elf_header.e_shnum - 1);
4379 continue;
4380 }
4381 else if (entry >= SHN_LORESERVE && entry <= SHN_HIRESERVE)
4382 {
4383 error (_("invalid section [%5u] in group section [%5u]\n"),
4384 entry, i);
4385 continue;
4386 }
4387
e4b17d5c
L
4388 if (section_headers_groups [SECTION_HEADER_INDEX (entry)]
4389 != NULL)
4390 {
d1f5c6e3
L
4391 if (entry)
4392 {
391cb864
L
4393 error (_("section [%5u] in group section [%5u] already in group section [%5u]\n"),
4394 entry, i,
d1f5c6e3
L
4395 section_headers_groups [SECTION_HEADER_INDEX (entry)]->group_index);
4396 continue;
4397 }
4398 else
4399 {
4400 /* Intel C/C++ compiler may put section 0 in a
4401 section group. We just warn it the first time
4402 and ignore it afterwards. */
4403 static int warned = 0;
4404 if (!warned)
4405 {
4406 error (_("section 0 in group section [%5u]\n"),
4407 section_headers_groups [SECTION_HEADER_INDEX (entry)]->group_index);
4408 warned++;
4409 }
4410 }
e4b17d5c
L
4411 }
4412
4413 section_headers_groups [SECTION_HEADER_INDEX (entry)]
4414 = group;
4415
4416 if (do_section_groups)
4417 {
4418 sec = SECTION_HEADER (entry);
c256ffe7 4419 printf (" [%5u] %s\n", entry, SECTION_NAME (sec));
ba2685cc
AM
4420 }
4421
e4b17d5c
L
4422 g = xmalloc (sizeof (struct group_list));
4423 g->section_index = entry;
4424 g->next = group->root;
4425 group->root = g;
f5842774
L
4426 }
4427
f5842774
L
4428 if (start)
4429 free (start);
e4b17d5c
L
4430
4431 group++;
f5842774
L
4432 }
4433 }
4434
d1f5c6e3
L
4435 if (symtab)
4436 free (symtab);
4437 if (strtab)
4438 free (strtab);
f5842774
L
4439 return 1;
4440}
4441
85b1c36d 4442static struct
566b0d53
L
4443{
4444 const char *name;
4445 int reloc;
4446 int size;
4447 int rela;
4448} dynamic_relocations [] =
4449{
4450 { "REL", DT_REL, DT_RELSZ, FALSE },
4451 { "RELA", DT_RELA, DT_RELASZ, TRUE },
4452 { "PLT", DT_JMPREL, DT_PLTRELSZ, UNKNOWN }
4453};
4454
252b5132 4455/* Process the reloc section. */
18bd398b 4456
252b5132 4457static int
d3ba0551 4458process_relocs (FILE *file)
252b5132 4459{
b34976b6
AM
4460 unsigned long rel_size;
4461 unsigned long rel_offset;
252b5132
RH
4462
4463
4464 if (!do_reloc)
4465 return 1;
4466
4467 if (do_using_dynamic)
4468 {
566b0d53
L
4469 int is_rela;
4470 const char *name;
4471 int has_dynamic_reloc;
4472 unsigned int i;
0de14b54 4473
566b0d53 4474 has_dynamic_reloc = 0;
252b5132 4475
566b0d53 4476 for (i = 0; i < ARRAY_SIZE (dynamic_relocations); i++)
252b5132 4477 {
566b0d53
L
4478 is_rela = dynamic_relocations [i].rela;
4479 name = dynamic_relocations [i].name;
4480 rel_size = dynamic_info [dynamic_relocations [i].size];
4481 rel_offset = dynamic_info [dynamic_relocations [i].reloc];
103f02d3 4482
566b0d53
L
4483 has_dynamic_reloc |= rel_size;
4484
4485 if (is_rela == UNKNOWN)
aa903cfb 4486 {
566b0d53
L
4487 if (dynamic_relocations [i].reloc == DT_JMPREL)
4488 switch (dynamic_info[DT_PLTREL])
4489 {
4490 case DT_REL:
4491 is_rela = FALSE;
4492 break;
4493 case DT_RELA:
4494 is_rela = TRUE;
4495 break;
4496 }
aa903cfb 4497 }
252b5132 4498
566b0d53
L
4499 if (rel_size)
4500 {
4501 printf
4502 (_("\n'%s' relocation section at offset 0x%lx contains %ld bytes:\n"),
4503 name, rel_offset, rel_size);
252b5132 4504
d93f0186
NC
4505 dump_relocations (file,
4506 offset_from_vma (file, rel_offset, rel_size),
4507 rel_size,
566b0d53 4508 dynamic_symbols, num_dynamic_syms,
d79b3d50 4509 dynamic_strings, dynamic_strings_length, is_rela);
566b0d53 4510 }
252b5132 4511 }
566b0d53
L
4512
4513 if (! has_dynamic_reloc)
252b5132
RH
4514 printf (_("\nThere are no dynamic relocations in this file.\n"));
4515 }
4516 else
4517 {
b34976b6
AM
4518 Elf_Internal_Shdr *section;
4519 unsigned long i;
4520 int found = 0;
252b5132
RH
4521
4522 for (i = 0, section = section_headers;
4523 i < elf_header.e_shnum;
b34976b6 4524 i++, section++)
252b5132
RH
4525 {
4526 if ( section->sh_type != SHT_RELA
4527 && section->sh_type != SHT_REL)
4528 continue;
4529
4530 rel_offset = section->sh_offset;
4531 rel_size = section->sh_size;
4532
4533 if (rel_size)
4534 {
b34976b6 4535 Elf_Internal_Shdr *strsec;
b34976b6 4536 int is_rela;
103f02d3 4537
252b5132
RH
4538 printf (_("\nRelocation section "));
4539
4540 if (string_table == NULL)
19936277 4541 printf ("%d", section->sh_name);
252b5132 4542 else
3a1a2036 4543 printf (_("'%s'"), SECTION_NAME (section));
252b5132
RH
4544
4545 printf (_(" at offset 0x%lx contains %lu entries:\n"),
4546 rel_offset, (unsigned long) (rel_size / section->sh_entsize));
4547
d79b3d50
NC
4548 is_rela = section->sh_type == SHT_RELA;
4549
c256ffe7
JJ
4550 if (section->sh_link
4551 && SECTION_HEADER_INDEX (section->sh_link)
4552 < elf_header.e_shnum)
af3fc3bc 4553 {
b34976b6 4554 Elf_Internal_Shdr *symsec;
d79b3d50
NC
4555 Elf_Internal_Sym *symtab;
4556 unsigned long nsyms;
c256ffe7 4557 unsigned long strtablen = 0;
d79b3d50 4558 char *strtab = NULL;
57346661 4559
9ad5cbcf 4560 symsec = SECTION_HEADER (section->sh_link);
08d8fa11
JJ
4561 if (symsec->sh_type != SHT_SYMTAB
4562 && symsec->sh_type != SHT_DYNSYM)
4563 continue;
4564
af3fc3bc 4565 nsyms = symsec->sh_size / symsec->sh_entsize;
9ad5cbcf 4566 symtab = GET_ELF_SYMBOLS (file, symsec);
252b5132 4567
af3fc3bc
AM
4568 if (symtab == NULL)
4569 continue;
252b5132 4570
c256ffe7
JJ
4571 if (SECTION_HEADER_INDEX (symsec->sh_link)
4572 < elf_header.e_shnum)
4573 {
4574 strsec = SECTION_HEADER (symsec->sh_link);
103f02d3 4575
c256ffe7
JJ
4576 strtab = get_data (NULL, file, strsec->sh_offset,
4577 1, strsec->sh_size,
4578 _("string table"));
4579 strtablen = strtab == NULL ? 0 : strsec->sh_size;
4580 }
252b5132 4581
d79b3d50
NC
4582 dump_relocations (file, rel_offset, rel_size,
4583 symtab, nsyms, strtab, strtablen, is_rela);
4584 if (strtab)
4585 free (strtab);
4586 free (symtab);
4587 }
4588 else
4589 dump_relocations (file, rel_offset, rel_size,
4590 NULL, 0, NULL, 0, is_rela);
252b5132
RH
4591
4592 found = 1;
4593 }
4594 }
4595
4596 if (! found)
4597 printf (_("\nThere are no relocations in this file.\n"));
4598 }
4599
4600 return 1;
4601}
4602
57346661
AM
4603/* Process the unwind section. */
4604
4d6ed7c8
NC
4605#include "unwind-ia64.h"
4606
4607/* An absolute address consists of a section and an offset. If the
4608 section is NULL, the offset itself is the address, otherwise, the
4609 address equals to LOAD_ADDRESS(section) + offset. */
4610
4611struct absaddr
4612 {
4613 unsigned short section;
4614 bfd_vma offset;
4615 };
4616
1949de15
L
4617#define ABSADDR(a) \
4618 ((a).section \
4619 ? section_headers [(a).section].sh_addr + (a).offset \
4620 : (a).offset)
4621
57346661 4622struct ia64_unw_aux_info
4d6ed7c8 4623 {
57346661 4624 struct ia64_unw_table_entry
4d6ed7c8 4625 {
b34976b6
AM
4626 struct absaddr start;
4627 struct absaddr end;
4628 struct absaddr info;
4d6ed7c8 4629 }
b34976b6
AM
4630 *table; /* Unwind table. */
4631 unsigned long table_len; /* Length of unwind table. */
4632 unsigned char *info; /* Unwind info. */
4633 unsigned long info_size; /* Size of unwind info. */
4634 bfd_vma info_addr; /* starting address of unwind info. */
4635 bfd_vma seg_base; /* Starting address of segment. */
4636 Elf_Internal_Sym *symtab; /* The symbol table. */
4637 unsigned long nsyms; /* Number of symbols. */
4638 char *strtab; /* The string table. */
4639 unsigned long strtab_size; /* Size of string table. */
4d6ed7c8
NC
4640 };
4641
4d6ed7c8 4642static void
57346661
AM
4643find_symbol_for_address (Elf_Internal_Sym *symtab,
4644 unsigned long nsyms,
4645 const char *strtab,
4646 unsigned long strtab_size,
d3ba0551
AM
4647 struct absaddr addr,
4648 const char **symname,
4649 bfd_vma *offset)
4d6ed7c8 4650{
d3ba0551 4651 bfd_vma dist = 0x100000;
4d6ed7c8
NC
4652 Elf_Internal_Sym *sym, *best = NULL;
4653 unsigned long i;
4654
57346661 4655 for (i = 0, sym = symtab; i < nsyms; ++i, ++sym)
4d6ed7c8
NC
4656 {
4657 if (ELF_ST_TYPE (sym->st_info) == STT_FUNC
4658 && sym->st_name != 0
4659 && (addr.section == SHN_UNDEF || addr.section == sym->st_shndx)
4660 && addr.offset >= sym->st_value
4661 && addr.offset - sym->st_value < dist)
4662 {
4663 best = sym;
4664 dist = addr.offset - sym->st_value;
4665 if (!dist)
4666 break;
4667 }
4668 }
4669 if (best)
4670 {
57346661
AM
4671 *symname = (best->st_name >= strtab_size
4672 ? "<corrupt>" : strtab + best->st_name);
4d6ed7c8
NC
4673 *offset = dist;
4674 return;
4675 }
4676 *symname = NULL;
4677 *offset = addr.offset;
4678}
4679
4680static void
57346661 4681dump_ia64_unwind (struct ia64_unw_aux_info *aux)
4d6ed7c8 4682{
57346661 4683 struct ia64_unw_table_entry *tp;
4d6ed7c8 4684 int in_body;
7036c0e1 4685
4d6ed7c8
NC
4686 for (tp = aux->table; tp < aux->table + aux->table_len; ++tp)
4687 {
4688 bfd_vma stamp;
4689 bfd_vma offset;
b34976b6
AM
4690 const unsigned char *dp;
4691 const unsigned char *head;
4692 const char *procname;
4d6ed7c8 4693
57346661
AM
4694 find_symbol_for_address (aux->symtab, aux->nsyms, aux->strtab,
4695 aux->strtab_size, tp->start, &procname, &offset);
4d6ed7c8
NC
4696
4697 fputs ("\n<", stdout);
4698
4699 if (procname)
4700 {
4701 fputs (procname, stdout);
4702
4703 if (offset)
4704 printf ("+%lx", (unsigned long) offset);
4705 }
4706
4707 fputs (">: [", stdout);
4708 print_vma (tp->start.offset, PREFIX_HEX);
4709 fputc ('-', stdout);
4710 print_vma (tp->end.offset, PREFIX_HEX);
86f55779 4711 printf ("], info at +0x%lx\n",
4d6ed7c8
NC
4712 (unsigned long) (tp->info.offset - aux->seg_base));
4713
1949de15 4714 head = aux->info + (ABSADDR (tp->info) - aux->info_addr);
a4a00738 4715 stamp = byte_get ((unsigned char *) head, sizeof (stamp));
4d6ed7c8 4716
86f55779 4717 printf (" v%u, flags=0x%lx (%s%s), len=%lu bytes\n",
4d6ed7c8
NC
4718 (unsigned) UNW_VER (stamp),
4719 (unsigned long) ((stamp & UNW_FLAG_MASK) >> 32),
4720 UNW_FLAG_EHANDLER (stamp) ? " ehandler" : "",
4721 UNW_FLAG_UHANDLER (stamp) ? " uhandler" : "",
89fac5e3 4722 (unsigned long) (eh_addr_size * UNW_LENGTH (stamp)));
4d6ed7c8
NC
4723
4724 if (UNW_VER (stamp) != 1)
4725 {
4726 printf ("\tUnknown version.\n");
4727 continue;
4728 }
4729
4730 in_body = 0;
89fac5e3 4731 for (dp = head + 8; dp < head + 8 + eh_addr_size * UNW_LENGTH (stamp);)
4d6ed7c8
NC
4732 dp = unw_decode (dp, in_body, & in_body);
4733 }
4734}
4735
4736static int
d3ba0551 4737slurp_ia64_unwind_table (FILE *file,
57346661 4738 struct ia64_unw_aux_info *aux,
d3ba0551 4739 Elf_Internal_Shdr *sec)
4d6ed7c8 4740{
89fac5e3 4741 unsigned long size, nrelas, i;
d93f0186 4742 Elf_Internal_Phdr *seg;
57346661 4743 struct ia64_unw_table_entry *tep;
c8286bd1 4744 Elf_Internal_Shdr *relsec;
4d6ed7c8
NC
4745 Elf_Internal_Rela *rela, *rp;
4746 unsigned char *table, *tp;
4747 Elf_Internal_Sym *sym;
4748 const char *relname;
4d6ed7c8 4749
4d6ed7c8
NC
4750 /* First, find the starting address of the segment that includes
4751 this section: */
4752
4753 if (elf_header.e_phnum)
4754 {
d93f0186 4755 if (! get_program_headers (file))
4d6ed7c8 4756 return 0;
4d6ed7c8 4757
d93f0186
NC
4758 for (seg = program_headers;
4759 seg < program_headers + elf_header.e_phnum;
4760 ++seg)
4d6ed7c8
NC
4761 {
4762 if (seg->p_type != PT_LOAD)
4763 continue;
4764
4765 if (sec->sh_addr >= seg->p_vaddr
4766 && (sec->sh_addr + sec->sh_size <= seg->p_vaddr + seg->p_memsz))
4767 {
4768 aux->seg_base = seg->p_vaddr;
4769 break;
4770 }
4771 }
4d6ed7c8
NC
4772 }
4773
4774 /* Second, build the unwind table from the contents of the unwind section: */
4775 size = sec->sh_size;
c256ffe7 4776 table = get_data (NULL, file, sec->sh_offset, 1, size, _("unwind table"));
a6e9f9df
AM
4777 if (!table)
4778 return 0;
4d6ed7c8 4779
c256ffe7 4780 aux->table = xcmalloc (size / (3 * eh_addr_size), sizeof (aux->table[0]));
89fac5e3
RS
4781 tep = aux->table;
4782 for (tp = table; tp < table + size; tp += 3 * eh_addr_size, ++tep)
4d6ed7c8
NC
4783 {
4784 tep->start.section = SHN_UNDEF;
4785 tep->end.section = SHN_UNDEF;
4786 tep->info.section = SHN_UNDEF;
4787 if (is_32bit_elf)
4788 {
4789 tep->start.offset = byte_get ((unsigned char *) tp + 0, 4);
4790 tep->end.offset = byte_get ((unsigned char *) tp + 4, 4);
4791 tep->info.offset = byte_get ((unsigned char *) tp + 8, 4);
4792 }
4793 else
4794 {
66543521
AM
4795 tep->start.offset = BYTE_GET ((unsigned char *) tp + 0);
4796 tep->end.offset = BYTE_GET ((unsigned char *) tp + 8);
4797 tep->info.offset = BYTE_GET ((unsigned char *) tp + 16);
4d6ed7c8
NC
4798 }
4799 tep->start.offset += aux->seg_base;
4800 tep->end.offset += aux->seg_base;
4801 tep->info.offset += aux->seg_base;
4802 }
4803 free (table);
4804
4805 /* Third, apply any relocations to the unwind table: */
4806
4807 for (relsec = section_headers;
4808 relsec < section_headers + elf_header.e_shnum;
4809 ++relsec)
4810 {
4811 if (relsec->sh_type != SHT_RELA
c256ffe7 4812 || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
9ad5cbcf 4813 || SECTION_HEADER (relsec->sh_info) != sec)
4d6ed7c8
NC
4814 continue;
4815
4816 if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
4817 & rela, & nrelas))
4818 return 0;
4819
4820 for (rp = rela; rp < rela + nrelas; ++rp)
4821 {
4822 if (is_32bit_elf)
4823 {
4824 relname = elf_ia64_reloc_type (ELF32_R_TYPE (rp->r_info));
4825 sym = aux->symtab + ELF32_R_SYM (rp->r_info);
4d6ed7c8
NC
4826 }
4827 else
4828 {
4829 relname = elf_ia64_reloc_type (ELF64_R_TYPE (rp->r_info));
4830 sym = aux->symtab + ELF64_R_SYM (rp->r_info);
4d6ed7c8
NC
4831 }
4832
18bd398b 4833 if (! strneq (relname, "R_IA64_SEGREL", 13))
4d6ed7c8 4834 {
e5fb9629 4835 warn (_("Skipping unexpected relocation type %s\n"), relname);
4d6ed7c8
NC
4836 continue;
4837 }
4838
89fac5e3 4839 i = rp->r_offset / (3 * eh_addr_size);
4d6ed7c8 4840
89fac5e3 4841 switch (rp->r_offset/eh_addr_size % 3)
4d6ed7c8
NC
4842 {
4843 case 0:
4844 aux->table[i].start.section = sym->st_shndx;
1ffa9a18 4845 aux->table[i].start.offset += rp->r_addend + sym->st_value;
4d6ed7c8
NC
4846 break;
4847 case 1:
4848 aux->table[i].end.section = sym->st_shndx;
1ffa9a18 4849 aux->table[i].end.offset += rp->r_addend + sym->st_value;
4d6ed7c8
NC
4850 break;
4851 case 2:
4852 aux->table[i].info.section = sym->st_shndx;
1ffa9a18 4853 aux->table[i].info.offset += rp->r_addend + sym->st_value;
4d6ed7c8
NC
4854 break;
4855 default:
4856 break;
4857 }
4858 }
4859
4860 free (rela);
4861 }
4862
89fac5e3 4863 aux->table_len = size / (3 * eh_addr_size);
4d6ed7c8
NC
4864 return 1;
4865}
4866
4867static int
57346661 4868ia64_process_unwind (FILE *file)
4d6ed7c8 4869{
c8286bd1 4870 Elf_Internal_Shdr *sec, *unwsec = NULL, *strsec;
89fac5e3 4871 unsigned long i, unwcount = 0, unwstart = 0;
57346661 4872 struct ia64_unw_aux_info aux;
f1467e33 4873
4d6ed7c8
NC
4874 memset (& aux, 0, sizeof (aux));
4875
4d6ed7c8
NC
4876 for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
4877 {
c256ffe7
JJ
4878 if (sec->sh_type == SHT_SYMTAB
4879 && SECTION_HEADER_INDEX (sec->sh_link) < elf_header.e_shnum)
4d6ed7c8
NC
4880 {
4881 aux.nsyms = sec->sh_size / sec->sh_entsize;
9ad5cbcf 4882 aux.symtab = GET_ELF_SYMBOLS (file, sec);
4d6ed7c8 4883
9ad5cbcf 4884 strsec = SECTION_HEADER (sec->sh_link);
d3ba0551 4885 aux.strtab = get_data (NULL, file, strsec->sh_offset,
c256ffe7
JJ
4886 1, strsec->sh_size, _("string table"));
4887 aux.strtab_size = aux.strtab != NULL ? strsec->sh_size : 0;
4d6ed7c8
NC
4888 }
4889 else if (sec->sh_type == SHT_IA_64_UNWIND)
579f31ac
JJ
4890 unwcount++;
4891 }
4892
4893 if (!unwcount)
4894 printf (_("\nThere are no unwind sections in this file.\n"));
4895
4896 while (unwcount-- > 0)
4897 {
4898 char *suffix;
4899 size_t len, len2;
4900
4901 for (i = unwstart, sec = section_headers + unwstart;
4902 i < elf_header.e_shnum; ++i, ++sec)
4903 if (sec->sh_type == SHT_IA_64_UNWIND)
4904 {
4905 unwsec = sec;
4906 break;
4907 }
4908
4909 unwstart = i + 1;
4910 len = sizeof (ELF_STRING_ia64_unwind_once) - 1;
4911
e4b17d5c
L
4912 if ((unwsec->sh_flags & SHF_GROUP) != 0)
4913 {
4914 /* We need to find which section group it is in. */
4915 struct group_list *g = section_headers_groups [i]->root;
4916
4917 for (; g != NULL; g = g->next)
4918 {
4919 sec = SECTION_HEADER (g->section_index);
18bd398b
NC
4920
4921 if (streq (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info))
57346661 4922 break;
e4b17d5c
L
4923 }
4924
4925 if (g == NULL)
4926 i = elf_header.e_shnum;
4927 }
18bd398b 4928 else if (strneq (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind_once, len))
579f31ac 4929 {
18bd398b 4930 /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.ia64unwi.FOO. */
579f31ac
JJ
4931 len2 = sizeof (ELF_STRING_ia64_unwind_info_once) - 1;
4932 suffix = SECTION_NAME (unwsec) + len;
4933 for (i = 0, sec = section_headers; i < elf_header.e_shnum;
4934 ++i, ++sec)
18bd398b
NC
4935 if (strneq (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info_once, len2)
4936 && streq (SECTION_NAME (sec) + len2, suffix))
579f31ac
JJ
4937 break;
4938 }
4939 else
4940 {
4941 /* .IA_64.unwindFOO -> .IA_64.unwind_infoFOO
18bd398b 4942 .IA_64.unwind or BAR -> .IA_64.unwind_info. */
579f31ac
JJ
4943 len = sizeof (ELF_STRING_ia64_unwind) - 1;
4944 len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1;
4945 suffix = "";
18bd398b 4946 if (strneq (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind, len))
579f31ac
JJ
4947 suffix = SECTION_NAME (unwsec) + len;
4948 for (i = 0, sec = section_headers; i < elf_header.e_shnum;
4949 ++i, ++sec)
18bd398b
NC
4950 if (strneq (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info, len2)
4951 && streq (SECTION_NAME (sec) + len2, suffix))
579f31ac
JJ
4952 break;
4953 }
4954
4955 if (i == elf_header.e_shnum)
4956 {
4957 printf (_("\nCould not find unwind info section for "));
4958
4959 if (string_table == NULL)
4960 printf ("%d", unwsec->sh_name);
4961 else
3a1a2036 4962 printf (_("'%s'"), SECTION_NAME (unwsec));
579f31ac
JJ
4963 }
4964 else
4d6ed7c8
NC
4965 {
4966 aux.info_size = sec->sh_size;
4967 aux.info_addr = sec->sh_addr;
c256ffe7 4968 aux.info = get_data (NULL, file, sec->sh_offset, 1, aux.info_size,
d3ba0551 4969 _("unwind info"));
4d6ed7c8 4970
579f31ac 4971 printf (_("\nUnwind section "));
4d6ed7c8 4972
579f31ac
JJ
4973 if (string_table == NULL)
4974 printf ("%d", unwsec->sh_name);
4975 else
3a1a2036 4976 printf (_("'%s'"), SECTION_NAME (unwsec));
4d6ed7c8 4977
579f31ac 4978 printf (_(" at offset 0x%lx contains %lu entries:\n"),
e59b4dfb 4979 (unsigned long) unwsec->sh_offset,
89fac5e3 4980 (unsigned long) (unwsec->sh_size / (3 * eh_addr_size)));
4d6ed7c8 4981
579f31ac 4982 (void) slurp_ia64_unwind_table (file, & aux, unwsec);
4d6ed7c8 4983
579f31ac
JJ
4984 if (aux.table_len > 0)
4985 dump_ia64_unwind (& aux);
4986
4987 if (aux.table)
4988 free ((char *) aux.table);
4989 if (aux.info)
4990 free ((char *) aux.info);
4991 aux.table = NULL;
4992 aux.info = NULL;
4993 }
4d6ed7c8 4994 }
4d6ed7c8 4995
4d6ed7c8
NC
4996 if (aux.symtab)
4997 free (aux.symtab);
4998 if (aux.strtab)
4999 free ((char *) aux.strtab);
5000
5001 return 1;
5002}
5003
57346661
AM
5004struct hppa_unw_aux_info
5005 {
5006 struct hppa_unw_table_entry
5007 {
5008 struct absaddr start;
5009 struct absaddr end;
5010 unsigned int Cannot_unwind:1; /* 0 */
5011 unsigned int Millicode:1; /* 1 */
5012 unsigned int Millicode_save_sr0:1; /* 2 */
5013 unsigned int Region_description:2; /* 3..4 */
5014 unsigned int reserved1:1; /* 5 */
5015 unsigned int Entry_SR:1; /* 6 */
5016 unsigned int Entry_FR:4; /* number saved */ /* 7..10 */
5017 unsigned int Entry_GR:5; /* number saved */ /* 11..15 */
5018 unsigned int Args_stored:1; /* 16 */
5019 unsigned int Variable_Frame:1; /* 17 */
5020 unsigned int Separate_Package_Body:1; /* 18 */
5021 unsigned int Frame_Extension_Millicode:1; /* 19 */
5022 unsigned int Stack_Overflow_Check:1; /* 20 */
5023 unsigned int Two_Instruction_SP_Increment:1; /* 21 */
5024 unsigned int Ada_Region:1; /* 22 */
5025 unsigned int cxx_info:1; /* 23 */
5026 unsigned int cxx_try_catch:1; /* 24 */
5027 unsigned int sched_entry_seq:1; /* 25 */
5028 unsigned int reserved2:1; /* 26 */
5029 unsigned int Save_SP:1; /* 27 */
5030 unsigned int Save_RP:1; /* 28 */
5031 unsigned int Save_MRP_in_frame:1; /* 29 */
5032 unsigned int extn_ptr_defined:1; /* 30 */
5033 unsigned int Cleanup_defined:1; /* 31 */
5034
5035 unsigned int MPE_XL_interrupt_marker:1; /* 0 */
5036 unsigned int HP_UX_interrupt_marker:1; /* 1 */
5037 unsigned int Large_frame:1; /* 2 */
5038 unsigned int Pseudo_SP_Set:1; /* 3 */
5039 unsigned int reserved4:1; /* 4 */
5040 unsigned int Total_frame_size:27; /* 5..31 */
5041 }
5042 *table; /* Unwind table. */
5043 unsigned long table_len; /* Length of unwind table. */
5044 bfd_vma seg_base; /* Starting address of segment. */
5045 Elf_Internal_Sym *symtab; /* The symbol table. */
5046 unsigned long nsyms; /* Number of symbols. */
5047 char *strtab; /* The string table. */
5048 unsigned long strtab_size; /* Size of string table. */
5049 };
5050
5051static void
5052dump_hppa_unwind (struct hppa_unw_aux_info *aux)
5053{
57346661
AM
5054 struct hppa_unw_table_entry *tp;
5055
57346661
AM
5056 for (tp = aux->table; tp < aux->table + aux->table_len; ++tp)
5057 {
5058 bfd_vma offset;
5059 const char *procname;
5060
5061 find_symbol_for_address (aux->symtab, aux->nsyms, aux->strtab,
5062 aux->strtab_size, tp->start, &procname,
5063 &offset);
5064
5065 fputs ("\n<", stdout);
5066
5067 if (procname)
5068 {
5069 fputs (procname, stdout);
5070
5071 if (offset)
5072 printf ("+%lx", (unsigned long) offset);
5073 }
5074
5075 fputs (">: [", stdout);
5076 print_vma (tp->start.offset, PREFIX_HEX);
5077 fputc ('-', stdout);
5078 print_vma (tp->end.offset, PREFIX_HEX);
5079 printf ("]\n\t");
5080
18bd398b
NC
5081#define PF(_m) if (tp->_m) printf (#_m " ");
5082#define PV(_m) if (tp->_m) printf (#_m "=%d ", tp->_m);
57346661
AM
5083 PF(Cannot_unwind);
5084 PF(Millicode);
5085 PF(Millicode_save_sr0);
18bd398b 5086 /* PV(Region_description); */
57346661
AM
5087 PF(Entry_SR);
5088 PV(Entry_FR);
5089 PV(Entry_GR);
5090 PF(Args_stored);
5091 PF(Variable_Frame);
5092 PF(Separate_Package_Body);
5093 PF(Frame_Extension_Millicode);
5094 PF(Stack_Overflow_Check);
5095 PF(Two_Instruction_SP_Increment);
5096 PF(Ada_Region);
5097 PF(cxx_info);
5098 PF(cxx_try_catch);
5099 PF(sched_entry_seq);
5100 PF(Save_SP);
5101 PF(Save_RP);
5102 PF(Save_MRP_in_frame);
5103 PF(extn_ptr_defined);
5104 PF(Cleanup_defined);
5105 PF(MPE_XL_interrupt_marker);
5106 PF(HP_UX_interrupt_marker);
5107 PF(Large_frame);
5108 PF(Pseudo_SP_Set);
5109 PV(Total_frame_size);
5110#undef PF
5111#undef PV
5112 }
5113
18bd398b 5114 printf ("\n");
57346661
AM
5115}
5116
5117static int
5118slurp_hppa_unwind_table (FILE *file,
5119 struct hppa_unw_aux_info *aux,
5120 Elf_Internal_Shdr *sec)
5121{
1c0751b2 5122 unsigned long size, unw_ent_size, nentries, nrelas, i;
57346661
AM
5123 Elf_Internal_Phdr *seg;
5124 struct hppa_unw_table_entry *tep;
5125 Elf_Internal_Shdr *relsec;
5126 Elf_Internal_Rela *rela, *rp;
5127 unsigned char *table, *tp;
5128 Elf_Internal_Sym *sym;
5129 const char *relname;
5130
57346661
AM
5131 /* First, find the starting address of the segment that includes
5132 this section. */
5133
5134 if (elf_header.e_phnum)
5135 {
5136 if (! get_program_headers (file))
5137 return 0;
5138
5139 for (seg = program_headers;
5140 seg < program_headers + elf_header.e_phnum;
5141 ++seg)
5142 {
5143 if (seg->p_type != PT_LOAD)
5144 continue;
5145
5146 if (sec->sh_addr >= seg->p_vaddr
5147 && (sec->sh_addr + sec->sh_size <= seg->p_vaddr + seg->p_memsz))
5148 {
5149 aux->seg_base = seg->p_vaddr;
5150 break;
5151 }
5152 }
5153 }
5154
5155 /* Second, build the unwind table from the contents of the unwind
5156 section. */
5157 size = sec->sh_size;
c256ffe7 5158 table = get_data (NULL, file, sec->sh_offset, 1, size, _("unwind table"));
57346661
AM
5159 if (!table)
5160 return 0;
5161
1c0751b2
DA
5162 unw_ent_size = 16;
5163 nentries = size / unw_ent_size;
5164 size = unw_ent_size * nentries;
57346661 5165
1c0751b2 5166 tep = aux->table = xcmalloc (nentries, sizeof (aux->table[0]));
57346661 5167
1c0751b2 5168 for (tp = table; tp < table + size; tp += unw_ent_size, ++tep)
57346661
AM
5169 {
5170 unsigned int tmp1, tmp2;
5171
5172 tep->start.section = SHN_UNDEF;
5173 tep->end.section = SHN_UNDEF;
5174
1c0751b2
DA
5175 tep->start.offset = byte_get ((unsigned char *) tp + 0, 4);
5176 tep->end.offset = byte_get ((unsigned char *) tp + 4, 4);
5177 tmp1 = byte_get ((unsigned char *) tp + 8, 4);
5178 tmp2 = byte_get ((unsigned char *) tp + 12, 4);
5179
5180 tep->start.offset += aux->seg_base;
5181 tep->end.offset += aux->seg_base;
57346661
AM
5182
5183 tep->Cannot_unwind = (tmp1 >> 31) & 0x1;
5184 tep->Millicode = (tmp1 >> 30) & 0x1;
5185 tep->Millicode_save_sr0 = (tmp1 >> 29) & 0x1;
5186 tep->Region_description = (tmp1 >> 27) & 0x3;
5187 tep->reserved1 = (tmp1 >> 26) & 0x1;
5188 tep->Entry_SR = (tmp1 >> 25) & 0x1;
5189 tep->Entry_FR = (tmp1 >> 21) & 0xf;
5190 tep->Entry_GR = (tmp1 >> 16) & 0x1f;
5191 tep->Args_stored = (tmp1 >> 15) & 0x1;
5192 tep->Variable_Frame = (tmp1 >> 14) & 0x1;
5193 tep->Separate_Package_Body = (tmp1 >> 13) & 0x1;
5194 tep->Frame_Extension_Millicode = (tmp1 >> 12) & 0x1;
5195 tep->Stack_Overflow_Check = (tmp1 >> 11) & 0x1;
5196 tep->Two_Instruction_SP_Increment = (tmp1 >> 10) & 0x1;
5197 tep->Ada_Region = (tmp1 >> 9) & 0x1;
5198 tep->cxx_info = (tmp1 >> 8) & 0x1;
5199 tep->cxx_try_catch = (tmp1 >> 7) & 0x1;
5200 tep->sched_entry_seq = (tmp1 >> 6) & 0x1;
5201 tep->reserved2 = (tmp1 >> 5) & 0x1;
5202 tep->Save_SP = (tmp1 >> 4) & 0x1;
5203 tep->Save_RP = (tmp1 >> 3) & 0x1;
5204 tep->Save_MRP_in_frame = (tmp1 >> 2) & 0x1;
5205 tep->extn_ptr_defined = (tmp1 >> 1) & 0x1;
5206 tep->Cleanup_defined = tmp1 & 0x1;
5207
5208 tep->MPE_XL_interrupt_marker = (tmp2 >> 31) & 0x1;
5209 tep->HP_UX_interrupt_marker = (tmp2 >> 30) & 0x1;
5210 tep->Large_frame = (tmp2 >> 29) & 0x1;
5211 tep->Pseudo_SP_Set = (tmp2 >> 28) & 0x1;
5212 tep->reserved4 = (tmp2 >> 27) & 0x1;
5213 tep->Total_frame_size = tmp2 & 0x7ffffff;
57346661
AM
5214 }
5215 free (table);
5216
5217 /* Third, apply any relocations to the unwind table. */
5218
5219 for (relsec = section_headers;
5220 relsec < section_headers + elf_header.e_shnum;
5221 ++relsec)
5222 {
5223 if (relsec->sh_type != SHT_RELA
c256ffe7 5224 || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
57346661
AM
5225 || SECTION_HEADER (relsec->sh_info) != sec)
5226 continue;
5227
5228 if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
5229 & rela, & nrelas))
5230 return 0;
5231
5232 for (rp = rela; rp < rela + nrelas; ++rp)
5233 {
5234 if (is_32bit_elf)
5235 {
5236 relname = elf_hppa_reloc_type (ELF32_R_TYPE (rp->r_info));
5237 sym = aux->symtab + ELF32_R_SYM (rp->r_info);
5238 }
5239 else
5240 {
5241 relname = elf_hppa_reloc_type (ELF64_R_TYPE (rp->r_info));
5242 sym = aux->symtab + ELF64_R_SYM (rp->r_info);
5243 }
5244
5245 /* R_PARISC_SEGREL32 or R_PARISC_SEGREL64. */
5246 if (strncmp (relname, "R_PARISC_SEGREL", 15) != 0)
5247 {
5248 warn (_("Skipping unexpected relocation type %s\n"), relname);
5249 continue;
5250 }
5251
5252 i = rp->r_offset / unw_ent_size;
5253
89fac5e3 5254 switch ((rp->r_offset % unw_ent_size) / eh_addr_size)
57346661
AM
5255 {
5256 case 0:
5257 aux->table[i].start.section = sym->st_shndx;
5258 aux->table[i].start.offset += sym->st_value + rp->r_addend;
5259 break;
5260 case 1:
5261 aux->table[i].end.section = sym->st_shndx;
5262 aux->table[i].end.offset += sym->st_value + rp->r_addend;
5263 break;
5264 default:
5265 break;
5266 }
5267 }
5268
5269 free (rela);
5270 }
5271
1c0751b2 5272 aux->table_len = nentries;
57346661
AM
5273
5274 return 1;
5275}
5276
5277static int
5278hppa_process_unwind (FILE *file)
5279{
57346661 5280 struct hppa_unw_aux_info aux;
18bd398b
NC
5281 Elf_Internal_Shdr *unwsec = NULL;
5282 Elf_Internal_Shdr *strsec;
5283 Elf_Internal_Shdr *sec;
18bd398b 5284 unsigned long i;
57346661
AM
5285
5286 memset (& aux, 0, sizeof (aux));
5287
c256ffe7
JJ
5288 if (string_table == NULL)
5289 return 1;
57346661
AM
5290
5291 for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
5292 {
c256ffe7
JJ
5293 if (sec->sh_type == SHT_SYMTAB
5294 && SECTION_HEADER_INDEX (sec->sh_link) < elf_header.e_shnum)
57346661
AM
5295 {
5296 aux.nsyms = sec->sh_size / sec->sh_entsize;
5297 aux.symtab = GET_ELF_SYMBOLS (file, sec);
5298
5299 strsec = SECTION_HEADER (sec->sh_link);
57346661 5300 aux.strtab = get_data (NULL, file, strsec->sh_offset,
c256ffe7
JJ
5301 1, strsec->sh_size, _("string table"));
5302 aux.strtab_size = aux.strtab != NULL ? strsec->sh_size : 0;
57346661 5303 }
18bd398b 5304 else if (streq (SECTION_NAME (sec), ".PARISC.unwind"))
57346661
AM
5305 unwsec = sec;
5306 }
5307
5308 if (!unwsec)
5309 printf (_("\nThere are no unwind sections in this file.\n"));
5310
5311 for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
5312 {
18bd398b 5313 if (streq (SECTION_NAME (sec), ".PARISC.unwind"))
57346661 5314 {
57346661
AM
5315 printf (_("\nUnwind section "));
5316 printf (_("'%s'"), SECTION_NAME (sec));
5317
5318 printf (_(" at offset 0x%lx contains %lu entries:\n"),
5319 (unsigned long) sec->sh_offset,
89fac5e3 5320 (unsigned long) (sec->sh_size / (2 * eh_addr_size + 8)));
57346661
AM
5321
5322 slurp_hppa_unwind_table (file, &aux, sec);
5323 if (aux.table_len > 0)
5324 dump_hppa_unwind (&aux);
5325
5326 if (aux.table)
5327 free ((char *) aux.table);
5328 aux.table = NULL;
5329 }
5330 }
5331
5332 if (aux.symtab)
5333 free (aux.symtab);
5334 if (aux.strtab)
5335 free ((char *) aux.strtab);
5336
5337 return 1;
5338}
5339
5340static int
5341process_unwind (FILE *file)
5342{
5343 struct unwind_handler {
5344 int machtype;
5345 int (*handler)(FILE *file);
5346 } handlers[] = {
5347 { EM_IA_64, ia64_process_unwind },
5348 { EM_PARISC, hppa_process_unwind },
5349 { 0, 0 }
5350 };
5351 int i;
5352
5353 if (!do_unwind)
5354 return 1;
5355
5356 for (i = 0; handlers[i].handler != NULL; i++)
5357 if (elf_header.e_machine == handlers[i].machtype)
18bd398b 5358 return handlers[i].handler (file);
57346661
AM
5359
5360 printf (_("\nThere are no unwind sections in this file.\n"));
5361 return 1;
5362}
5363
252b5132 5364static void
b2d38a17 5365dynamic_section_mips_val (Elf_Internal_Dyn *entry)
252b5132
RH
5366{
5367 switch (entry->d_tag)
5368 {
5369 case DT_MIPS_FLAGS:
5370 if (entry->d_un.d_val == 0)
5371 printf ("NONE\n");
5372 else
5373 {
5374 static const char * opts[] =
5375 {
5376 "QUICKSTART", "NOTPOT", "NO_LIBRARY_REPLACEMENT",
5377 "NO_MOVE", "SGI_ONLY", "GUARANTEE_INIT", "DELTA_C_PLUS_PLUS",
5378 "GUARANTEE_START_INIT", "PIXIE", "DEFAULT_DELAY_LOAD",
5379 "REQUICKSTART", "REQUICKSTARTED", "CORD", "NO_UNRES_UNDEF",
5380 "RLD_ORDER_SAFE"
5381 };
5382 unsigned int cnt;
5383 int first = 1;
b34976b6 5384 for (cnt = 0; cnt < NUM_ELEM (opts); ++cnt)
252b5132
RH
5385 if (entry->d_un.d_val & (1 << cnt))
5386 {
5387 printf ("%s%s", first ? "" : " ", opts[cnt]);
5388 first = 0;
5389 }
5390 puts ("");
5391 }
5392 break;
103f02d3 5393
252b5132 5394 case DT_MIPS_IVERSION:
d79b3d50
NC
5395 if (VALID_DYNAMIC_NAME (entry->d_un.d_val))
5396 printf ("Interface Version: %s\n", GET_DYNAMIC_NAME (entry->d_un.d_val));
252b5132 5397 else
d79b3d50 5398 printf ("<corrupt: %ld>\n", (long) entry->d_un.d_ptr);
252b5132 5399 break;
103f02d3 5400
252b5132
RH
5401 case DT_MIPS_TIME_STAMP:
5402 {
5403 char timebuf[20];
b34976b6 5404 struct tm *tmp;
50da7a9c 5405
252b5132 5406 time_t time = entry->d_un.d_val;
50da7a9c 5407 tmp = gmtime (&time);
e9e44622
JJ
5408 snprintf (timebuf, sizeof (timebuf), "%04u-%02u-%02uT%02u:%02u:%02u",
5409 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
5410 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
252b5132
RH
5411 printf ("Time Stamp: %s\n", timebuf);
5412 }
5413 break;
103f02d3 5414
252b5132
RH
5415 case DT_MIPS_RLD_VERSION:
5416 case DT_MIPS_LOCAL_GOTNO:
5417 case DT_MIPS_CONFLICTNO:
5418 case DT_MIPS_LIBLISTNO:
5419 case DT_MIPS_SYMTABNO:
5420 case DT_MIPS_UNREFEXTNO:
5421 case DT_MIPS_HIPAGENO:
5422 case DT_MIPS_DELTA_CLASS_NO:
5423 case DT_MIPS_DELTA_INSTANCE_NO:
5424 case DT_MIPS_DELTA_RELOC_NO:
5425 case DT_MIPS_DELTA_SYM_NO:
5426 case DT_MIPS_DELTA_CLASSSYM_NO:
5427 case DT_MIPS_COMPACT_SIZE:
5428 printf ("%ld\n", (long) entry->d_un.d_ptr);
5429 break;
103f02d3
UD
5430
5431 default:
5432 printf ("%#lx\n", (long) entry->d_un.d_ptr);
5433 }
5434}
5435
5436
5437static void
b2d38a17 5438dynamic_section_parisc_val (Elf_Internal_Dyn *entry)
103f02d3
UD
5439{
5440 switch (entry->d_tag)
5441 {
5442 case DT_HP_DLD_FLAGS:
5443 {
5444 static struct
5445 {
5446 long int bit;
b34976b6 5447 const char *str;
5e220199
NC
5448 }
5449 flags[] =
5450 {
5451 { DT_HP_DEBUG_PRIVATE, "HP_DEBUG_PRIVATE" },
5452 { DT_HP_DEBUG_CALLBACK, "HP_DEBUG_CALLBACK" },
5453 { DT_HP_DEBUG_CALLBACK_BOR, "HP_DEBUG_CALLBACK_BOR" },
5454 { DT_HP_NO_ENVVAR, "HP_NO_ENVVAR" },
5455 { DT_HP_BIND_NOW, "HP_BIND_NOW" },
5456 { DT_HP_BIND_NONFATAL, "HP_BIND_NONFATAL" },
5457 { DT_HP_BIND_VERBOSE, "HP_BIND_VERBOSE" },
5458 { DT_HP_BIND_RESTRICTED, "HP_BIND_RESTRICTED" },
5459 { DT_HP_BIND_SYMBOLIC, "HP_BIND_SYMBOLIC" },
5460 { DT_HP_RPATH_FIRST, "HP_RPATH_FIRST" },
eec8f817
DA
5461 { DT_HP_BIND_DEPTH_FIRST, "HP_BIND_DEPTH_FIRST" },
5462 { DT_HP_GST, "HP_GST" },
5463 { DT_HP_SHLIB_FIXED, "HP_SHLIB_FIXED" },
5464 { DT_HP_MERGE_SHLIB_SEG, "HP_MERGE_SHLIB_SEG" },
5465 { DT_HP_NODELETE, "HP_NODELETE" },
5466 { DT_HP_GROUP, "HP_GROUP" },
5467 { DT_HP_PROTECT_LINKAGE_TABLE, "HP_PROTECT_LINKAGE_TABLE" }
5e220199 5468 };
103f02d3 5469 int first = 1;
5e220199 5470 size_t cnt;
f7a99963 5471 bfd_vma val = entry->d_un.d_val;
103f02d3
UD
5472
5473 for (cnt = 0; cnt < sizeof (flags) / sizeof (flags[0]); ++cnt)
5474 if (val & flags[cnt].bit)
30800947
NC
5475 {
5476 if (! first)
5477 putchar (' ');
5478 fputs (flags[cnt].str, stdout);
5479 first = 0;
5480 val ^= flags[cnt].bit;
5481 }
76da6bbe 5482
103f02d3 5483 if (val != 0 || first)
f7a99963
NC
5484 {
5485 if (! first)
5486 putchar (' ');
5487 print_vma (val, HEX);
5488 }
103f02d3
UD
5489 }
5490 break;
76da6bbe 5491
252b5132 5492 default:
f7a99963
NC
5493 print_vma (entry->d_un.d_ptr, PREFIX_HEX);
5494 break;
252b5132 5495 }
35b1837e 5496 putchar ('\n');
252b5132
RH
5497}
5498
ecc51f48 5499static void
b2d38a17 5500dynamic_section_ia64_val (Elf_Internal_Dyn *entry)
ecc51f48
NC
5501{
5502 switch (entry->d_tag)
5503 {
0de14b54 5504 case DT_IA_64_PLT_RESERVE:
bdf4d63a 5505 /* First 3 slots reserved. */
ecc51f48
NC
5506 print_vma (entry->d_un.d_ptr, PREFIX_HEX);
5507 printf (" -- ");
5508 print_vma (entry->d_un.d_ptr + (3 * 8), PREFIX_HEX);
bdf4d63a
JJ
5509 break;
5510
5511 default:
5512 print_vma (entry->d_un.d_ptr, PREFIX_HEX);
5513 break;
ecc51f48 5514 }
bdf4d63a 5515 putchar ('\n');
ecc51f48
NC
5516}
5517
252b5132 5518static int
b2d38a17 5519get_32bit_dynamic_section (FILE *file)
252b5132 5520{
fb514b26 5521 Elf32_External_Dyn *edyn, *ext;
b34976b6 5522 Elf_Internal_Dyn *entry;
103f02d3 5523
c256ffe7 5524 edyn = get_data (NULL, file, dynamic_addr, 1, dynamic_size,
b2d38a17 5525 _("dynamic section"));
a6e9f9df
AM
5526 if (!edyn)
5527 return 0;
103f02d3 5528
ba2685cc
AM
5529/* SGI's ELF has more than one section in the DYNAMIC segment, and we
5530 might not have the luxury of section headers. Look for the DT_NULL
5531 terminator to determine the number of entries. */
5532 for (ext = edyn, dynamic_nent = 0;
5533 (char *) ext < (char *) edyn + dynamic_size;
5534 ext++)
5535 {
5536 dynamic_nent++;
5537 if (BYTE_GET (ext->d_tag) == DT_NULL)
5538 break;
5539 }
252b5132 5540
c256ffe7 5541 dynamic_section = cmalloc (dynamic_nent, sizeof (*entry));
b2d38a17 5542 if (dynamic_section == NULL)
252b5132 5543 {
9ea033b2
NC
5544 error (_("Out of memory\n"));
5545 free (edyn);
5546 return 0;
5547 }
252b5132 5548
fb514b26 5549 for (ext = edyn, entry = dynamic_section;
ba2685cc 5550 entry < dynamic_section + dynamic_nent;
fb514b26 5551 ext++, entry++)
9ea033b2 5552 {
fb514b26
AM
5553 entry->d_tag = BYTE_GET (ext->d_tag);
5554 entry->d_un.d_val = BYTE_GET (ext->d_un.d_val);
252b5132
RH
5555 }
5556
9ea033b2
NC
5557 free (edyn);
5558
5559 return 1;
5560}
5561
5562static int
b2d38a17 5563get_64bit_dynamic_section (FILE *file)
9ea033b2 5564{
fb514b26 5565 Elf64_External_Dyn *edyn, *ext;
b34976b6 5566 Elf_Internal_Dyn *entry;
103f02d3 5567
c256ffe7 5568 edyn = get_data (NULL, file, dynamic_addr, 1, dynamic_size,
b2d38a17 5569 _("dynamic section"));
a6e9f9df
AM
5570 if (!edyn)
5571 return 0;
103f02d3 5572
ba2685cc
AM
5573/* SGI's ELF has more than one section in the DYNAMIC segment, and we
5574 might not have the luxury of section headers. Look for the DT_NULL
5575 terminator to determine the number of entries. */
5576 for (ext = edyn, dynamic_nent = 0;
5577 (char *) ext < (char *) edyn + dynamic_size;
5578 ext++)
5579 {
5580 dynamic_nent++;
66543521 5581 if (BYTE_GET (ext->d_tag) == DT_NULL)
ba2685cc
AM
5582 break;
5583 }
252b5132 5584
c256ffe7 5585 dynamic_section = cmalloc (dynamic_nent, sizeof (*entry));
b2d38a17 5586 if (dynamic_section == NULL)
252b5132
RH
5587 {
5588 error (_("Out of memory\n"));
5589 free (edyn);
5590 return 0;
5591 }
5592
fb514b26 5593 for (ext = edyn, entry = dynamic_section;
ba2685cc 5594 entry < dynamic_section + dynamic_nent;
fb514b26 5595 ext++, entry++)
252b5132 5596 {
66543521
AM
5597 entry->d_tag = BYTE_GET (ext->d_tag);
5598 entry->d_un.d_val = BYTE_GET (ext->d_un.d_val);
252b5132
RH
5599 }
5600
5601 free (edyn);
5602
9ea033b2
NC
5603 return 1;
5604}
5605
e9e44622
JJ
5606static void
5607print_dynamic_flags (bfd_vma flags)
d1133906 5608{
e9e44622 5609 int first = 1;
13ae64f3 5610
d1133906
NC
5611 while (flags)
5612 {
5613 bfd_vma flag;
5614
5615 flag = flags & - flags;
5616 flags &= ~ flag;
5617
e9e44622
JJ
5618 if (first)
5619 first = 0;
5620 else
5621 putc (' ', stdout);
13ae64f3 5622
d1133906
NC
5623 switch (flag)
5624 {
e9e44622
JJ
5625 case DF_ORIGIN: fputs ("ORIGIN", stdout); break;
5626 case DF_SYMBOLIC: fputs ("SYMBOLIC", stdout); break;
5627 case DF_TEXTREL: fputs ("TEXTREL", stdout); break;
5628 case DF_BIND_NOW: fputs ("BIND_NOW", stdout); break;
5629 case DF_STATIC_TLS: fputs ("STATIC_TLS", stdout); break;
5630 default: fputs ("unknown", stdout); break;
d1133906
NC
5631 }
5632 }
e9e44622 5633 puts ("");
d1133906
NC
5634}
5635
b2d38a17
NC
5636/* Parse and display the contents of the dynamic section. */
5637
9ea033b2 5638static int
b2d38a17 5639process_dynamic_section (FILE *file)
9ea033b2 5640{
b34976b6 5641 Elf_Internal_Dyn *entry;
9ea033b2
NC
5642
5643 if (dynamic_size == 0)
5644 {
5645 if (do_dynamic)
b2d38a17 5646 printf (_("\nThere is no dynamic section in this file.\n"));
9ea033b2
NC
5647
5648 return 1;
5649 }
5650
5651 if (is_32bit_elf)
5652 {
b2d38a17 5653 if (! get_32bit_dynamic_section (file))
9ea033b2
NC
5654 return 0;
5655 }
b2d38a17 5656 else if (! get_64bit_dynamic_section (file))
9ea033b2
NC
5657 return 0;
5658
252b5132
RH
5659 /* Find the appropriate symbol table. */
5660 if (dynamic_symbols == NULL)
5661 {
86dba8ee
AM
5662 for (entry = dynamic_section;
5663 entry < dynamic_section + dynamic_nent;
5664 ++entry)
252b5132 5665 {
c8286bd1 5666 Elf_Internal_Shdr section;
252b5132
RH
5667
5668 if (entry->d_tag != DT_SYMTAB)
5669 continue;
5670
5671 dynamic_info[DT_SYMTAB] = entry->d_un.d_val;
5672
5673 /* Since we do not know how big the symbol table is,
5674 we default to reading in the entire file (!) and
5675 processing that. This is overkill, I know, but it
e3c8793a 5676 should work. */
d93f0186 5677 section.sh_offset = offset_from_vma (file, entry->d_un.d_val, 0);
252b5132 5678
fb52b2f4
NC
5679 if (archive_file_offset != 0)
5680 section.sh_size = archive_file_size - section.sh_offset;
5681 else
5682 {
5683 if (fseek (file, 0, SEEK_END))
5684 error (_("Unable to seek to end of file!"));
5685
5686 section.sh_size = ftell (file) - section.sh_offset;
5687 }
252b5132 5688
9ea033b2 5689 if (is_32bit_elf)
9ad5cbcf 5690 section.sh_entsize = sizeof (Elf32_External_Sym);
9ea033b2 5691 else
9ad5cbcf 5692 section.sh_entsize = sizeof (Elf64_External_Sym);
252b5132 5693
9ad5cbcf 5694 num_dynamic_syms = section.sh_size / section.sh_entsize;
19936277 5695 if (num_dynamic_syms < 1)
252b5132
RH
5696 {
5697 error (_("Unable to determine the number of symbols to load\n"));
5698 continue;
5699 }
5700
9ad5cbcf 5701 dynamic_symbols = GET_ELF_SYMBOLS (file, &section);
252b5132
RH
5702 }
5703 }
5704
5705 /* Similarly find a string table. */
5706 if (dynamic_strings == NULL)
5707 {
86dba8ee
AM
5708 for (entry = dynamic_section;
5709 entry < dynamic_section + dynamic_nent;
5710 ++entry)
252b5132
RH
5711 {
5712 unsigned long offset;
b34976b6 5713 long str_tab_len;
252b5132
RH
5714
5715 if (entry->d_tag != DT_STRTAB)
5716 continue;
5717
5718 dynamic_info[DT_STRTAB] = entry->d_un.d_val;
5719
5720 /* Since we do not know how big the string table is,
5721 we default to reading in the entire file (!) and
5722 processing that. This is overkill, I know, but it
e3c8793a 5723 should work. */
252b5132 5724
d93f0186 5725 offset = offset_from_vma (file, entry->d_un.d_val, 0);
fb52b2f4
NC
5726
5727 if (archive_file_offset != 0)
5728 str_tab_len = archive_file_size - offset;
5729 else
5730 {
5731 if (fseek (file, 0, SEEK_END))
5732 error (_("Unable to seek to end of file\n"));
5733 str_tab_len = ftell (file) - offset;
5734 }
252b5132
RH
5735
5736 if (str_tab_len < 1)
5737 {
5738 error
5739 (_("Unable to determine the length of the dynamic string table\n"));
5740 continue;
5741 }
5742
c256ffe7 5743 dynamic_strings = get_data (NULL, file, offset, 1, str_tab_len,
d3ba0551 5744 _("dynamic string table"));
d79b3d50 5745 dynamic_strings_length = str_tab_len;
252b5132
RH
5746 break;
5747 }
5748 }
5749
5750 /* And find the syminfo section if available. */
5751 if (dynamic_syminfo == NULL)
5752 {
3e8bba36 5753 unsigned long syminsz = 0;
252b5132 5754
86dba8ee
AM
5755 for (entry = dynamic_section;
5756 entry < dynamic_section + dynamic_nent;
5757 ++entry)
252b5132
RH
5758 {
5759 if (entry->d_tag == DT_SYMINENT)
5760 {
5761 /* Note: these braces are necessary to avoid a syntax
5762 error from the SunOS4 C compiler. */
5763 assert (sizeof (Elf_External_Syminfo) == entry->d_un.d_val);
5764 }
5765 else if (entry->d_tag == DT_SYMINSZ)
5766 syminsz = entry->d_un.d_val;
5767 else if (entry->d_tag == DT_SYMINFO)
d93f0186
NC
5768 dynamic_syminfo_offset = offset_from_vma (file, entry->d_un.d_val,
5769 syminsz);
252b5132
RH
5770 }
5771
5772 if (dynamic_syminfo_offset != 0 && syminsz != 0)
5773 {
86dba8ee 5774 Elf_External_Syminfo *extsyminfo, *extsym;
b34976b6 5775 Elf_Internal_Syminfo *syminfo;
252b5132
RH
5776
5777 /* There is a syminfo section. Read the data. */
c256ffe7
JJ
5778 extsyminfo = get_data (NULL, file, dynamic_syminfo_offset, 1,
5779 syminsz, _("symbol information"));
a6e9f9df
AM
5780 if (!extsyminfo)
5781 return 0;
252b5132 5782
d3ba0551 5783 dynamic_syminfo = malloc (syminsz);
252b5132
RH
5784 if (dynamic_syminfo == NULL)
5785 {
5786 error (_("Out of memory\n"));
5787 return 0;
5788 }
5789
5790 dynamic_syminfo_nent = syminsz / sizeof (Elf_External_Syminfo);
86dba8ee
AM
5791 for (syminfo = dynamic_syminfo, extsym = extsyminfo;
5792 syminfo < dynamic_syminfo + dynamic_syminfo_nent;
5793 ++syminfo, ++extsym)
252b5132 5794 {
86dba8ee
AM
5795 syminfo->si_boundto = BYTE_GET (extsym->si_boundto);
5796 syminfo->si_flags = BYTE_GET (extsym->si_flags);
252b5132
RH
5797 }
5798
5799 free (extsyminfo);
5800 }
5801 }
5802
5803 if (do_dynamic && dynamic_addr)
86dba8ee
AM
5804 printf (_("\nDynamic section at offset 0x%lx contains %u entries:\n"),
5805 dynamic_addr, dynamic_nent);
252b5132
RH
5806 if (do_dynamic)
5807 printf (_(" Tag Type Name/Value\n"));
5808
86dba8ee
AM
5809 for (entry = dynamic_section;
5810 entry < dynamic_section + dynamic_nent;
5811 entry++)
252b5132
RH
5812 {
5813 if (do_dynamic)
f7a99963 5814 {
b34976b6 5815 const char *dtype;
e699b9ff 5816
f7a99963
NC
5817 putchar (' ');
5818 print_vma (entry->d_tag, FULL_HEX);
e699b9ff
ILT
5819 dtype = get_dynamic_type (entry->d_tag);
5820 printf (" (%s)%*s", dtype,
5821 ((is_32bit_elf ? 27 : 19)
5822 - (int) strlen (dtype)),
f7a99963
NC
5823 " ");
5824 }
252b5132
RH
5825
5826 switch (entry->d_tag)
5827 {
d1133906
NC
5828 case DT_FLAGS:
5829 if (do_dynamic)
e9e44622 5830 print_dynamic_flags (entry->d_un.d_val);
d1133906 5831 break;
76da6bbe 5832
252b5132
RH
5833 case DT_AUXILIARY:
5834 case DT_FILTER:
019148e4
L
5835 case DT_CONFIG:
5836 case DT_DEPAUDIT:
5837 case DT_AUDIT:
252b5132
RH
5838 if (do_dynamic)
5839 {
019148e4 5840 switch (entry->d_tag)
b34976b6 5841 {
019148e4
L
5842 case DT_AUXILIARY:
5843 printf (_("Auxiliary library"));
5844 break;
5845
5846 case DT_FILTER:
5847 printf (_("Filter library"));
5848 break;
5849
b34976b6 5850 case DT_CONFIG:
019148e4
L
5851 printf (_("Configuration file"));
5852 break;
5853
5854 case DT_DEPAUDIT:
5855 printf (_("Dependency audit library"));
5856 break;
5857
5858 case DT_AUDIT:
5859 printf (_("Audit library"));
5860 break;
5861 }
252b5132 5862
d79b3d50
NC
5863 if (VALID_DYNAMIC_NAME (entry->d_un.d_val))
5864 printf (": [%s]\n", GET_DYNAMIC_NAME (entry->d_un.d_val));
252b5132 5865 else
f7a99963
NC
5866 {
5867 printf (": ");
5868 print_vma (entry->d_un.d_val, PREFIX_HEX);
5869 putchar ('\n');
5870 }
252b5132
RH
5871 }
5872 break;
5873
dcefbbbd 5874 case DT_FEATURE:
252b5132
RH
5875 if (do_dynamic)
5876 {
5877 printf (_("Flags:"));
86f55779 5878
252b5132
RH
5879 if (entry->d_un.d_val == 0)
5880 printf (_(" None\n"));
5881 else
5882 {
5883 unsigned long int val = entry->d_un.d_val;
86f55779 5884
252b5132
RH
5885 if (val & DTF_1_PARINIT)
5886 {
5887 printf (" PARINIT");
5888 val ^= DTF_1_PARINIT;
5889 }
dcefbbbd
L
5890 if (val & DTF_1_CONFEXP)
5891 {
5892 printf (" CONFEXP");
5893 val ^= DTF_1_CONFEXP;
5894 }
252b5132
RH
5895 if (val != 0)
5896 printf (" %lx", val);
5897 puts ("");
5898 }
5899 }
5900 break;
5901
5902 case DT_POSFLAG_1:
5903 if (do_dynamic)
5904 {
5905 printf (_("Flags:"));
86f55779 5906
252b5132
RH
5907 if (entry->d_un.d_val == 0)
5908 printf (_(" None\n"));
5909 else
5910 {
5911 unsigned long int val = entry->d_un.d_val;
86f55779 5912
252b5132
RH
5913 if (val & DF_P1_LAZYLOAD)
5914 {
5915 printf (" LAZYLOAD");
5916 val ^= DF_P1_LAZYLOAD;
5917 }
5918 if (val & DF_P1_GROUPPERM)
5919 {
5920 printf (" GROUPPERM");
5921 val ^= DF_P1_GROUPPERM;
5922 }
5923 if (val != 0)
5924 printf (" %lx", val);
5925 puts ("");
5926 }
5927 }
5928 break;
5929
5930 case DT_FLAGS_1:
5931 if (do_dynamic)
5932 {
5933 printf (_("Flags:"));
5934 if (entry->d_un.d_val == 0)
5935 printf (_(" None\n"));
5936 else
5937 {
5938 unsigned long int val = entry->d_un.d_val;
86f55779 5939
252b5132
RH
5940 if (val & DF_1_NOW)
5941 {
5942 printf (" NOW");
5943 val ^= DF_1_NOW;
5944 }
5945 if (val & DF_1_GLOBAL)
5946 {
5947 printf (" GLOBAL");
5948 val ^= DF_1_GLOBAL;
5949 }
5950 if (val & DF_1_GROUP)
5951 {
5952 printf (" GROUP");
5953 val ^= DF_1_GROUP;
5954 }
5955 if (val & DF_1_NODELETE)
5956 {
5957 printf (" NODELETE");
5958 val ^= DF_1_NODELETE;
5959 }
5960 if (val & DF_1_LOADFLTR)
5961 {
5962 printf (" LOADFLTR");
5963 val ^= DF_1_LOADFLTR;
5964 }
5965 if (val & DF_1_INITFIRST)
5966 {
5967 printf (" INITFIRST");
5968 val ^= DF_1_INITFIRST;
5969 }
5970 if (val & DF_1_NOOPEN)
5971 {
5972 printf (" NOOPEN");
5973 val ^= DF_1_NOOPEN;
5974 }
5975 if (val & DF_1_ORIGIN)
5976 {
5977 printf (" ORIGIN");
5978 val ^= DF_1_ORIGIN;
5979 }
5980 if (val & DF_1_DIRECT)
5981 {
5982 printf (" DIRECT");
5983 val ^= DF_1_DIRECT;
5984 }
5985 if (val & DF_1_TRANS)
5986 {
5987 printf (" TRANS");
5988 val ^= DF_1_TRANS;
5989 }
5990 if (val & DF_1_INTERPOSE)
5991 {
5992 printf (" INTERPOSE");
5993 val ^= DF_1_INTERPOSE;
5994 }
f7db6139 5995 if (val & DF_1_NODEFLIB)
dcefbbbd 5996 {
f7db6139
L
5997 printf (" NODEFLIB");
5998 val ^= DF_1_NODEFLIB;
dcefbbbd
L
5999 }
6000 if (val & DF_1_NODUMP)
6001 {
6002 printf (" NODUMP");
6003 val ^= DF_1_NODUMP;
6004 }
6005 if (val & DF_1_CONLFAT)
6006 {
6007 printf (" CONLFAT");
6008 val ^= DF_1_CONLFAT;
6009 }
252b5132
RH
6010 if (val != 0)
6011 printf (" %lx", val);
6012 puts ("");
6013 }
6014 }
6015 break;
6016
6017 case DT_PLTREL:
566b0d53 6018 dynamic_info[entry->d_tag] = entry->d_un.d_val;
252b5132
RH
6019 if (do_dynamic)
6020 puts (get_dynamic_type (entry->d_un.d_val));
6021 break;
6022
6023 case DT_NULL :
6024 case DT_NEEDED :
6025 case DT_PLTGOT :
6026 case DT_HASH :
6027 case DT_STRTAB :
6028 case DT_SYMTAB :
6029 case DT_RELA :
6030 case DT_INIT :
6031 case DT_FINI :
6032 case DT_SONAME :
6033 case DT_RPATH :
6034 case DT_SYMBOLIC:
6035 case DT_REL :
6036 case DT_DEBUG :
6037 case DT_TEXTREL :
6038 case DT_JMPREL :
019148e4 6039 case DT_RUNPATH :
252b5132
RH
6040 dynamic_info[entry->d_tag] = entry->d_un.d_val;
6041
6042 if (do_dynamic)
6043 {
b34976b6 6044 char *name;
252b5132 6045
d79b3d50
NC
6046 if (VALID_DYNAMIC_NAME (entry->d_un.d_val))
6047 name = GET_DYNAMIC_NAME (entry->d_un.d_val);
252b5132 6048 else
d79b3d50 6049 name = NULL;
252b5132
RH
6050
6051 if (name)
6052 {
6053 switch (entry->d_tag)
6054 {
6055 case DT_NEEDED:
6056 printf (_("Shared library: [%s]"), name);
6057
18bd398b 6058 if (streq (name, program_interpreter))
f7a99963 6059 printf (_(" program interpreter"));
252b5132
RH
6060 break;
6061
6062 case DT_SONAME:
f7a99963 6063 printf (_("Library soname: [%s]"), name);
252b5132
RH
6064 break;
6065
6066 case DT_RPATH:
f7a99963 6067 printf (_("Library rpath: [%s]"), name);
252b5132
RH
6068 break;
6069
019148e4
L
6070 case DT_RUNPATH:
6071 printf (_("Library runpath: [%s]"), name);
6072 break;
6073
252b5132 6074 default:
f7a99963
NC
6075 print_vma (entry->d_un.d_val, PREFIX_HEX);
6076 break;
252b5132
RH
6077 }
6078 }
6079 else
f7a99963
NC
6080 print_vma (entry->d_un.d_val, PREFIX_HEX);
6081
6082 putchar ('\n');
252b5132
RH
6083 }
6084 break;
6085
6086 case DT_PLTRELSZ:
6087 case DT_RELASZ :
6088 case DT_STRSZ :
6089 case DT_RELSZ :
6090 case DT_RELAENT :
6091 case DT_SYMENT :
6092 case DT_RELENT :
566b0d53 6093 dynamic_info[entry->d_tag] = entry->d_un.d_val;
252b5132
RH
6094 case DT_PLTPADSZ:
6095 case DT_MOVEENT :
6096 case DT_MOVESZ :
6097 case DT_INIT_ARRAYSZ:
6098 case DT_FINI_ARRAYSZ:
047b2264
JJ
6099 case DT_GNU_CONFLICTSZ:
6100 case DT_GNU_LIBLISTSZ:
252b5132 6101 if (do_dynamic)
f7a99963
NC
6102 {
6103 print_vma (entry->d_un.d_val, UNSIGNED);
6104 printf (" (bytes)\n");
6105 }
252b5132
RH
6106 break;
6107
6108 case DT_VERDEFNUM:
6109 case DT_VERNEEDNUM:
6110 case DT_RELACOUNT:
6111 case DT_RELCOUNT:
6112 if (do_dynamic)
f7a99963
NC
6113 {
6114 print_vma (entry->d_un.d_val, UNSIGNED);
6115 putchar ('\n');
6116 }
252b5132
RH
6117 break;
6118
6119 case DT_SYMINSZ:
6120 case DT_SYMINENT:
6121 case DT_SYMINFO:
6122 case DT_USED:
6123 case DT_INIT_ARRAY:
6124 case DT_FINI_ARRAY:
6125 if (do_dynamic)
6126 {
d79b3d50
NC
6127 if (entry->d_tag == DT_USED
6128 && VALID_DYNAMIC_NAME (entry->d_un.d_val))
252b5132 6129 {
d79b3d50 6130 char *name = GET_DYNAMIC_NAME (entry->d_un.d_val);
252b5132 6131
b34976b6 6132 if (*name)
252b5132
RH
6133 {
6134 printf (_("Not needed object: [%s]\n"), name);
6135 break;
6136 }
6137 }
103f02d3 6138
f7a99963
NC
6139 print_vma (entry->d_un.d_val, PREFIX_HEX);
6140 putchar ('\n');
252b5132
RH
6141 }
6142 break;
6143
6144 case DT_BIND_NOW:
6145 /* The value of this entry is ignored. */
35b1837e
AM
6146 if (do_dynamic)
6147 putchar ('\n');
252b5132 6148 break;
103f02d3 6149
047b2264
JJ
6150 case DT_GNU_PRELINKED:
6151 if (do_dynamic)
6152 {
b34976b6 6153 struct tm *tmp;
047b2264
JJ
6154 time_t time = entry->d_un.d_val;
6155
6156 tmp = gmtime (&time);
6157 printf ("%04u-%02u-%02uT%02u:%02u:%02u\n",
6158 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
6159 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
6160
6161 }
6162 break;
6163
252b5132
RH
6164 default:
6165 if ((entry->d_tag >= DT_VERSYM) && (entry->d_tag <= DT_VERNEEDNUM))
b34976b6 6166 version_info[DT_VERSIONTAGIDX (entry->d_tag)] =
252b5132
RH
6167 entry->d_un.d_val;
6168
6169 if (do_dynamic)
6170 {
6171 switch (elf_header.e_machine)
6172 {
6173 case EM_MIPS:
4fe85591 6174 case EM_MIPS_RS3_LE:
b2d38a17 6175 dynamic_section_mips_val (entry);
252b5132 6176 break;
103f02d3 6177 case EM_PARISC:
b2d38a17 6178 dynamic_section_parisc_val (entry);
103f02d3 6179 break;
ecc51f48 6180 case EM_IA_64:
b2d38a17 6181 dynamic_section_ia64_val (entry);
ecc51f48 6182 break;
252b5132 6183 default:
f7a99963
NC
6184 print_vma (entry->d_un.d_val, PREFIX_HEX);
6185 putchar ('\n');
252b5132
RH
6186 }
6187 }
6188 break;
6189 }
6190 }
6191
6192 return 1;
6193}
6194
6195static char *
d3ba0551 6196get_ver_flags (unsigned int flags)
252b5132 6197{
b34976b6 6198 static char buff[32];
252b5132
RH
6199
6200 buff[0] = 0;
6201
6202 if (flags == 0)
6203 return _("none");
6204
6205 if (flags & VER_FLG_BASE)
6206 strcat (buff, "BASE ");
6207
6208 if (flags & VER_FLG_WEAK)
6209 {
6210 if (flags & VER_FLG_BASE)
6211 strcat (buff, "| ");
6212
6213 strcat (buff, "WEAK ");
6214 }
6215
6216 if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK))
6217 strcat (buff, "| <unknown>");
6218
6219 return buff;
6220}
6221
6222/* Display the contents of the version sections. */
6223static int
d3ba0551 6224process_version_sections (FILE *file)
252b5132 6225{
b34976b6
AM
6226 Elf_Internal_Shdr *section;
6227 unsigned i;
6228 int found = 0;
252b5132
RH
6229
6230 if (! do_version)
6231 return 1;
6232
6233 for (i = 0, section = section_headers;
6234 i < elf_header.e_shnum;
b34976b6 6235 i++, section++)
252b5132
RH
6236 {
6237 switch (section->sh_type)
6238 {
6239 case SHT_GNU_verdef:
6240 {
b34976b6
AM
6241 Elf_External_Verdef *edefs;
6242 unsigned int idx;
6243 unsigned int cnt;
252b5132
RH
6244
6245 found = 1;
6246
6247 printf
6248 (_("\nVersion definition section '%s' contains %ld entries:\n"),
6249 SECTION_NAME (section), section->sh_info);
6250
6251 printf (_(" Addr: 0x"));
6252 printf_vma (section->sh_addr);
6253 printf (_(" Offset: %#08lx Link: %lx (%s)\n"),
1b228002 6254 (unsigned long) section->sh_offset, section->sh_link,
c256ffe7
JJ
6255 SECTION_HEADER_INDEX (section->sh_link)
6256 < elf_header.e_shnum
6257 ? SECTION_NAME (SECTION_HEADER (section->sh_link))
6258 : "<corrupt>");
252b5132 6259
c256ffe7
JJ
6260 edefs = get_data (NULL, file, section->sh_offset, 1,
6261 section->sh_size,
d3ba0551 6262 _("version definition section"));
a6e9f9df
AM
6263 if (!edefs)
6264 break;
252b5132 6265
b34976b6 6266 for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
252b5132 6267 {
b34976b6
AM
6268 char *vstart;
6269 Elf_External_Verdef *edef;
6270 Elf_Internal_Verdef ent;
6271 Elf_External_Verdaux *eaux;
6272 Elf_Internal_Verdaux aux;
6273 int j;
6274 int isum;
103f02d3 6275
252b5132
RH
6276 vstart = ((char *) edefs) + idx;
6277
6278 edef = (Elf_External_Verdef *) vstart;
6279
6280 ent.vd_version = BYTE_GET (edef->vd_version);
6281 ent.vd_flags = BYTE_GET (edef->vd_flags);
6282 ent.vd_ndx = BYTE_GET (edef->vd_ndx);
6283 ent.vd_cnt = BYTE_GET (edef->vd_cnt);
6284 ent.vd_hash = BYTE_GET (edef->vd_hash);
6285 ent.vd_aux = BYTE_GET (edef->vd_aux);
6286 ent.vd_next = BYTE_GET (edef->vd_next);
6287
6288 printf (_(" %#06x: Rev: %d Flags: %s"),
6289 idx, ent.vd_version, get_ver_flags (ent.vd_flags));
6290
6291 printf (_(" Index: %d Cnt: %d "),
6292 ent.vd_ndx, ent.vd_cnt);
6293
6294 vstart += ent.vd_aux;
6295
6296 eaux = (Elf_External_Verdaux *) vstart;
6297
6298 aux.vda_name = BYTE_GET (eaux->vda_name);
6299 aux.vda_next = BYTE_GET (eaux->vda_next);
6300
d79b3d50
NC
6301 if (VALID_DYNAMIC_NAME (aux.vda_name))
6302 printf (_("Name: %s\n"), GET_DYNAMIC_NAME (aux.vda_name));
252b5132
RH
6303 else
6304 printf (_("Name index: %ld\n"), aux.vda_name);
6305
6306 isum = idx + ent.vd_aux;
6307
b34976b6 6308 for (j = 1; j < ent.vd_cnt; j++)
252b5132
RH
6309 {
6310 isum += aux.vda_next;
6311 vstart += aux.vda_next;
6312
6313 eaux = (Elf_External_Verdaux *) vstart;
6314
6315 aux.vda_name = BYTE_GET (eaux->vda_name);
6316 aux.vda_next = BYTE_GET (eaux->vda_next);
6317
d79b3d50 6318 if (VALID_DYNAMIC_NAME (aux.vda_name))
252b5132 6319 printf (_(" %#06x: Parent %d: %s\n"),
d79b3d50 6320 isum, j, GET_DYNAMIC_NAME (aux.vda_name));
252b5132
RH
6321 else
6322 printf (_(" %#06x: Parent %d, name index: %ld\n"),
6323 isum, j, aux.vda_name);
6324 }
6325
6326 idx += ent.vd_next;
6327 }
6328
6329 free (edefs);
6330 }
6331 break;
103f02d3 6332
252b5132
RH
6333 case SHT_GNU_verneed:
6334 {
b34976b6
AM
6335 Elf_External_Verneed *eneed;
6336 unsigned int idx;
6337 unsigned int cnt;
252b5132
RH
6338
6339 found = 1;
6340
6341 printf (_("\nVersion needs section '%s' contains %ld entries:\n"),
6342 SECTION_NAME (section), section->sh_info);
6343
6344 printf (_(" Addr: 0x"));
6345 printf_vma (section->sh_addr);
6346 printf (_(" Offset: %#08lx Link to section: %ld (%s)\n"),
1b228002 6347 (unsigned long) section->sh_offset, section->sh_link,
c256ffe7
JJ
6348 SECTION_HEADER_INDEX (section->sh_link)
6349 < elf_header.e_shnum
6350 ? SECTION_NAME (SECTION_HEADER (section->sh_link))
6351 : "<corrupt>");
252b5132 6352
c256ffe7
JJ
6353 eneed = get_data (NULL, file, section->sh_offset, 1,
6354 section->sh_size,
d3ba0551 6355 _("version need section"));
a6e9f9df
AM
6356 if (!eneed)
6357 break;
252b5132
RH
6358
6359 for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
6360 {
b34976b6
AM
6361 Elf_External_Verneed *entry;
6362 Elf_Internal_Verneed ent;
6363 int j;
6364 int isum;
6365 char *vstart;
252b5132
RH
6366
6367 vstart = ((char *) eneed) + idx;
6368
6369 entry = (Elf_External_Verneed *) vstart;
6370
6371 ent.vn_version = BYTE_GET (entry->vn_version);
6372 ent.vn_cnt = BYTE_GET (entry->vn_cnt);
6373 ent.vn_file = BYTE_GET (entry->vn_file);
6374 ent.vn_aux = BYTE_GET (entry->vn_aux);
6375 ent.vn_next = BYTE_GET (entry->vn_next);
6376
6377 printf (_(" %#06x: Version: %d"), idx, ent.vn_version);
6378
d79b3d50
NC
6379 if (VALID_DYNAMIC_NAME (ent.vn_file))
6380 printf (_(" File: %s"), GET_DYNAMIC_NAME (ent.vn_file));
252b5132
RH
6381 else
6382 printf (_(" File: %lx"), ent.vn_file);
6383
6384 printf (_(" Cnt: %d\n"), ent.vn_cnt);
6385
6386 vstart += ent.vn_aux;
6387
6388 for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j)
6389 {
b34976b6
AM
6390 Elf_External_Vernaux *eaux;
6391 Elf_Internal_Vernaux aux;
252b5132
RH
6392
6393 eaux = (Elf_External_Vernaux *) vstart;
6394
6395 aux.vna_hash = BYTE_GET (eaux->vna_hash);
6396 aux.vna_flags = BYTE_GET (eaux->vna_flags);
6397 aux.vna_other = BYTE_GET (eaux->vna_other);
6398 aux.vna_name = BYTE_GET (eaux->vna_name);
6399 aux.vna_next = BYTE_GET (eaux->vna_next);
6400
d79b3d50 6401 if (VALID_DYNAMIC_NAME (aux.vna_name))
ecc2063b 6402 printf (_(" %#06x: Name: %s"),
d79b3d50 6403 isum, GET_DYNAMIC_NAME (aux.vna_name));
252b5132 6404 else
ecc2063b 6405 printf (_(" %#06x: Name index: %lx"),
252b5132
RH
6406 isum, aux.vna_name);
6407
6408 printf (_(" Flags: %s Version: %d\n"),
6409 get_ver_flags (aux.vna_flags), aux.vna_other);
6410
6411 isum += aux.vna_next;
6412 vstart += aux.vna_next;
6413 }
6414
6415 idx += ent.vn_next;
6416 }
103f02d3 6417
252b5132
RH
6418 free (eneed);
6419 }
6420 break;
6421
6422 case SHT_GNU_versym:
6423 {
b34976b6
AM
6424 Elf_Internal_Shdr *link_section;
6425 int total;
6426 int cnt;
6427 unsigned char *edata;
6428 unsigned short *data;
6429 char *strtab;
6430 Elf_Internal_Sym *symbols;
6431 Elf_Internal_Shdr *string_sec;
d3ba0551 6432 long off;
252b5132 6433
c256ffe7
JJ
6434 if (SECTION_HEADER_INDEX (section->sh_link) >= elf_header.e_shnum)
6435 break;
6436
9ad5cbcf 6437 link_section = SECTION_HEADER (section->sh_link);
08d8fa11 6438 total = section->sh_size / sizeof (Elf_External_Versym);
252b5132 6439
c256ffe7
JJ
6440 if (SECTION_HEADER_INDEX (link_section->sh_link)
6441 >= elf_header.e_shnum)
6442 break;
6443
252b5132
RH
6444 found = 1;
6445
9ad5cbcf 6446 symbols = GET_ELF_SYMBOLS (file, link_section);
252b5132 6447
9ad5cbcf 6448 string_sec = SECTION_HEADER (link_section->sh_link);
252b5132 6449
c256ffe7 6450 strtab = get_data (NULL, file, string_sec->sh_offset, 1,
d3ba0551 6451 string_sec->sh_size, _("version string table"));
a6e9f9df
AM
6452 if (!strtab)
6453 break;
252b5132
RH
6454
6455 printf (_("\nVersion symbols section '%s' contains %d entries:\n"),
6456 SECTION_NAME (section), total);
6457
6458 printf (_(" Addr: "));
6459 printf_vma (section->sh_addr);
6460 printf (_(" Offset: %#08lx Link: %lx (%s)\n"),
1b228002 6461 (unsigned long) section->sh_offset, section->sh_link,
252b5132
RH
6462 SECTION_NAME (link_section));
6463
d3ba0551
AM
6464 off = offset_from_vma (file,
6465 version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
6466 total * sizeof (short));
c256ffe7 6467 edata = get_data (NULL, file, off, total, sizeof (short),
d3ba0551 6468 _("version symbol data"));
a6e9f9df
AM
6469 if (!edata)
6470 {
6471 free (strtab);
6472 break;
6473 }
252b5132 6474
c256ffe7 6475 data = cmalloc (total, sizeof (short));
252b5132
RH
6476
6477 for (cnt = total; cnt --;)
b34976b6
AM
6478 data[cnt] = byte_get (edata + cnt * sizeof (short),
6479 sizeof (short));
252b5132
RH
6480
6481 free (edata);
6482
6483 for (cnt = 0; cnt < total; cnt += 4)
6484 {
6485 int j, nn;
00d93f34 6486 int check_def, check_need;
b34976b6 6487 char *name;
252b5132
RH
6488
6489 printf (" %03x:", cnt);
6490
6491 for (j = 0; (j < 4) && (cnt + j) < total; ++j)
b34976b6 6492 switch (data[cnt + j])
252b5132
RH
6493 {
6494 case 0:
6495 fputs (_(" 0 (*local*) "), stdout);
6496 break;
6497
6498 case 1:
6499 fputs (_(" 1 (*global*) "), stdout);
6500 break;
6501
6502 default:
b34976b6
AM
6503 nn = printf ("%4x%c", data[cnt + j] & 0x7fff,
6504 data[cnt + j] & 0x8000 ? 'h' : ' ');
252b5132 6505
00d93f34
JJ
6506 check_def = 1;
6507 check_need = 1;
c256ffe7
JJ
6508 if (SECTION_HEADER_INDEX (symbols[cnt + j].st_shndx)
6509 >= elf_header.e_shnum
6510 || SECTION_HEADER (symbols[cnt + j].st_shndx)->sh_type
6511 != SHT_NOBITS)
252b5132 6512 {
b34976b6 6513 if (symbols[cnt + j].st_shndx == SHN_UNDEF)
00d93f34
JJ
6514 check_def = 0;
6515 else
6516 check_need = 0;
252b5132 6517 }
00d93f34
JJ
6518
6519 if (check_need
b34976b6 6520 && version_info[DT_VERSIONTAGIDX (DT_VERNEED)])
252b5132 6521 {
b34976b6
AM
6522 Elf_Internal_Verneed ivn;
6523 unsigned long offset;
252b5132 6524
d93f0186
NC
6525 offset = offset_from_vma
6526 (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)],
6527 sizeof (Elf_External_Verneed));
252b5132 6528
b34976b6 6529 do
252b5132 6530 {
b34976b6
AM
6531 Elf_Internal_Vernaux ivna;
6532 Elf_External_Verneed evn;
6533 Elf_External_Vernaux evna;
6534 unsigned long a_off;
252b5132 6535
c256ffe7 6536 get_data (&evn, file, offset, sizeof (evn), 1,
a6e9f9df 6537 _("version need"));
252b5132
RH
6538
6539 ivn.vn_aux = BYTE_GET (evn.vn_aux);
6540 ivn.vn_next = BYTE_GET (evn.vn_next);
6541
6542 a_off = offset + ivn.vn_aux;
6543
6544 do
6545 {
a6e9f9df 6546 get_data (&evna, file, a_off, sizeof (evna),
c256ffe7 6547 1, _("version need aux (2)"));
252b5132
RH
6548
6549 ivna.vna_next = BYTE_GET (evna.vna_next);
6550 ivna.vna_other = BYTE_GET (evna.vna_other);
6551
6552 a_off += ivna.vna_next;
6553 }
b34976b6 6554 while (ivna.vna_other != data[cnt + j]
252b5132
RH
6555 && ivna.vna_next != 0);
6556
b34976b6 6557 if (ivna.vna_other == data[cnt + j])
252b5132
RH
6558 {
6559 ivna.vna_name = BYTE_GET (evna.vna_name);
6560
16062207 6561 name = strtab + ivna.vna_name;
252b5132 6562 nn += printf ("(%s%-*s",
16062207
ILT
6563 name,
6564 12 - (int) strlen (name),
252b5132 6565 ")");
00d93f34 6566 check_def = 0;
252b5132
RH
6567 break;
6568 }
6569
6570 offset += ivn.vn_next;
6571 }
6572 while (ivn.vn_next);
6573 }
00d93f34 6574
b34976b6
AM
6575 if (check_def && data[cnt + j] != 0x8001
6576 && version_info[DT_VERSIONTAGIDX (DT_VERDEF)])
252b5132 6577 {
b34976b6
AM
6578 Elf_Internal_Verdef ivd;
6579 Elf_External_Verdef evd;
6580 unsigned long offset;
252b5132 6581
d93f0186
NC
6582 offset = offset_from_vma
6583 (file, version_info[DT_VERSIONTAGIDX (DT_VERDEF)],
6584 sizeof evd);
252b5132
RH
6585
6586 do
6587 {
c256ffe7 6588 get_data (&evd, file, offset, sizeof (evd), 1,
a6e9f9df 6589 _("version def"));
252b5132
RH
6590
6591 ivd.vd_next = BYTE_GET (evd.vd_next);
6592 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
6593
6594 offset += ivd.vd_next;
6595 }
b34976b6 6596 while (ivd.vd_ndx != (data[cnt + j] & 0x7fff)
252b5132
RH
6597 && ivd.vd_next != 0);
6598
b34976b6 6599 if (ivd.vd_ndx == (data[cnt + j] & 0x7fff))
252b5132 6600 {
b34976b6
AM
6601 Elf_External_Verdaux evda;
6602 Elf_Internal_Verdaux ivda;
252b5132
RH
6603
6604 ivd.vd_aux = BYTE_GET (evd.vd_aux);
6605
a6e9f9df
AM
6606 get_data (&evda, file,
6607 offset - ivd.vd_next + ivd.vd_aux,
c256ffe7
JJ
6608 sizeof (evda), 1,
6609 _("version def aux"));
252b5132
RH
6610
6611 ivda.vda_name = BYTE_GET (evda.vda_name);
6612
16062207 6613 name = strtab + ivda.vda_name;
252b5132 6614 nn += printf ("(%s%-*s",
16062207
ILT
6615 name,
6616 12 - (int) strlen (name),
252b5132
RH
6617 ")");
6618 }
6619 }
6620
6621 if (nn < 18)
6622 printf ("%*c", 18 - nn, ' ');
6623 }
6624
6625 putchar ('\n');
6626 }
6627
6628 free (data);
6629 free (strtab);
6630 free (symbols);
6631 }
6632 break;
103f02d3 6633
252b5132
RH
6634 default:
6635 break;
6636 }
6637 }
6638
6639 if (! found)
6640 printf (_("\nNo version information found in this file.\n"));
6641
6642 return 1;
6643}
6644
d1133906 6645static const char *
d3ba0551 6646get_symbol_binding (unsigned int binding)
252b5132 6647{
b34976b6 6648 static char buff[32];
252b5132
RH
6649
6650 switch (binding)
6651 {
b34976b6
AM
6652 case STB_LOCAL: return "LOCAL";
6653 case STB_GLOBAL: return "GLOBAL";
6654 case STB_WEAK: return "WEAK";
252b5132
RH
6655 default:
6656 if (binding >= STB_LOPROC && binding <= STB_HIPROC)
e9e44622
JJ
6657 snprintf (buff, sizeof (buff), _("<processor specific>: %d"),
6658 binding);
252b5132 6659 else if (binding >= STB_LOOS && binding <= STB_HIOS)
e9e44622 6660 snprintf (buff, sizeof (buff), _("<OS specific>: %d"), binding);
252b5132 6661 else
e9e44622 6662 snprintf (buff, sizeof (buff), _("<unknown>: %d"), binding);
252b5132
RH
6663 return buff;
6664 }
6665}
6666
d1133906 6667static const char *
d3ba0551 6668get_symbol_type (unsigned int type)
252b5132 6669{
b34976b6 6670 static char buff[32];
252b5132
RH
6671
6672 switch (type)
6673 {
b34976b6
AM
6674 case STT_NOTYPE: return "NOTYPE";
6675 case STT_OBJECT: return "OBJECT";
6676 case STT_FUNC: return "FUNC";
6677 case STT_SECTION: return "SECTION";
6678 case STT_FILE: return "FILE";
6679 case STT_COMMON: return "COMMON";
6680 case STT_TLS: return "TLS";
252b5132
RH
6681 default:
6682 if (type >= STT_LOPROC && type <= STT_HIPROC)
df75f1af
NC
6683 {
6684 if (elf_header.e_machine == EM_ARM && type == STT_ARM_TFUNC)
103f02d3
UD
6685 return "THUMB_FUNC";
6686
351b4b40 6687 if (elf_header.e_machine == EM_SPARCV9 && type == STT_REGISTER)
103f02d3
UD
6688 return "REGISTER";
6689
6690 if (elf_header.e_machine == EM_PARISC && type == STT_PARISC_MILLI)
6691 return "PARISC_MILLI";
6692
e9e44622 6693 snprintf (buff, sizeof (buff), _("<processor specific>: %d"), type);
df75f1af 6694 }
252b5132 6695 else if (type >= STT_LOOS && type <= STT_HIOS)
103f02d3
UD
6696 {
6697 if (elf_header.e_machine == EM_PARISC)
6698 {
6699 if (type == STT_HP_OPAQUE)
6700 return "HP_OPAQUE";
6701 if (type == STT_HP_STUB)
6702 return "HP_STUB";
6703 }
6704
e9e44622 6705 snprintf (buff, sizeof (buff), _("<OS specific>: %d"), type);
103f02d3 6706 }
252b5132 6707 else
e9e44622 6708 snprintf (buff, sizeof (buff), _("<unknown>: %d"), type);
252b5132
RH
6709 return buff;
6710 }
6711}
6712
d1133906 6713static const char *
d3ba0551 6714get_symbol_visibility (unsigned int visibility)
d1133906
NC
6715{
6716 switch (visibility)
6717 {
b34976b6
AM
6718 case STV_DEFAULT: return "DEFAULT";
6719 case STV_INTERNAL: return "INTERNAL";
6720 case STV_HIDDEN: return "HIDDEN";
d1133906
NC
6721 case STV_PROTECTED: return "PROTECTED";
6722 default: abort ();
6723 }
6724}
6725
5e2b0d47
NC
6726static const char *
6727get_mips_symbol_other (unsigned int other)
6728{
6729 switch (other)
6730 {
6731 case STO_OPTIONAL: return "OPTIONAL";
6732 case STO_MIPS16: return "MIPS16";
6733 default: return NULL;
6734 }
6735}
6736
6737static const char *
6738get_symbol_other (unsigned int other)
6739{
6740 const char * result = NULL;
6741 static char buff [32];
6742
6743 if (other == 0)
6744 return "";
6745
6746 switch (elf_header.e_machine)
6747 {
6748 case EM_MIPS:
6749 result = get_mips_symbol_other (other);
6750 default:
6751 break;
6752 }
6753
6754 if (result)
6755 return result;
6756
6757 snprintf (buff, sizeof buff, _("<other>: %x"), other);
6758 return buff;
6759}
6760
d1133906 6761static const char *
d3ba0551 6762get_symbol_index_type (unsigned int type)
252b5132 6763{
b34976b6 6764 static char buff[32];
5cf1065c 6765
252b5132
RH
6766 switch (type)
6767 {
b34976b6
AM
6768 case SHN_UNDEF: return "UND";
6769 case SHN_ABS: return "ABS";
6770 case SHN_COMMON: return "COM";
252b5132 6771 default:
9ce701e2
L
6772 if (type == SHN_IA_64_ANSI_COMMON
6773 && elf_header.e_machine == EM_IA_64
6774 && elf_header.e_ident[EI_OSABI] == ELFOSABI_HPUX)
6775 return "ANSI_COM";
3b22753a
L
6776 else if (elf_header.e_machine == EM_X86_64
6777 && type == SHN_X86_64_LCOMMON)
6778 return "LARGE_COM";
9ce701e2 6779 else if (type >= SHN_LOPROC && type <= SHN_HIPROC)
5cf1065c 6780 sprintf (buff, "PRC[0x%04x]", type);
252b5132 6781 else if (type >= SHN_LOOS && type <= SHN_HIOS)
5cf1065c 6782 sprintf (buff, "OS [0x%04x]", type);
9ad5cbcf 6783 else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE)
5cf1065c 6784 sprintf (buff, "RSV[0x%04x]", type);
252b5132 6785 else
232e7cb8 6786 sprintf (buff, "%3d", type);
5cf1065c 6787 break;
252b5132 6788 }
5cf1065c
NC
6789
6790 return buff;
252b5132
RH
6791}
6792
66543521
AM
6793static bfd_vma *
6794get_dynamic_data (FILE *file, unsigned int number, unsigned int ent_size)
252b5132 6795{
b34976b6 6796 unsigned char *e_data;
66543521 6797 bfd_vma *i_data;
252b5132 6798
c256ffe7 6799 e_data = cmalloc (number, ent_size);
252b5132
RH
6800
6801 if (e_data == NULL)
6802 {
6803 error (_("Out of memory\n"));
6804 return NULL;
6805 }
6806
66543521 6807 if (fread (e_data, ent_size, number, file) != number)
252b5132
RH
6808 {
6809 error (_("Unable to read in dynamic data\n"));
6810 return NULL;
6811 }
6812
c256ffe7 6813 i_data = cmalloc (number, sizeof (*i_data));
252b5132
RH
6814
6815 if (i_data == NULL)
6816 {
6817 error (_("Out of memory\n"));
6818 free (e_data);
6819 return NULL;
6820 }
6821
6822 while (number--)
66543521 6823 i_data[number] = byte_get (e_data + number * ent_size, ent_size);
252b5132
RH
6824
6825 free (e_data);
6826
6827 return i_data;
6828}
6829
e3c8793a 6830/* Dump the symbol table. */
252b5132 6831static int
d3ba0551 6832process_symbol_table (FILE *file)
252b5132 6833{
b34976b6 6834 Elf_Internal_Shdr *section;
66543521
AM
6835 bfd_vma nbuckets = 0;
6836 bfd_vma nchains = 0;
6837 bfd_vma *buckets = NULL;
6838 bfd_vma *chains = NULL;
252b5132
RH
6839
6840 if (! do_syms && !do_histogram)
6841 return 1;
6842
6843 if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL)
6844 || do_histogram))
6845 {
66543521
AM
6846 unsigned char nb[8];
6847 unsigned char nc[8];
6848 int hash_ent_size = 4;
6849
6850 if ((elf_header.e_machine == EM_ALPHA
6851 || elf_header.e_machine == EM_S390
6852 || elf_header.e_machine == EM_S390_OLD)
6853 && elf_header.e_ident[EI_CLASS] == ELFCLASS64)
6854 hash_ent_size = 8;
6855
fb52b2f4
NC
6856 if (fseek (file,
6857 (archive_file_offset
6858 + offset_from_vma (file, dynamic_info[DT_HASH],
6859 sizeof nb + sizeof nc)),
d93f0186 6860 SEEK_SET))
252b5132
RH
6861 {
6862 error (_("Unable to seek to start of dynamic information"));
6863 return 0;
6864 }
6865
66543521 6866 if (fread (nb, hash_ent_size, 1, file) != 1)
252b5132
RH
6867 {
6868 error (_("Failed to read in number of buckets\n"));
6869 return 0;
6870 }
6871
66543521 6872 if (fread (nc, hash_ent_size, 1, file) != 1)
252b5132
RH
6873 {
6874 error (_("Failed to read in number of chains\n"));
6875 return 0;
6876 }
6877
66543521
AM
6878 nbuckets = byte_get (nb, hash_ent_size);
6879 nchains = byte_get (nc, hash_ent_size);
252b5132 6880
66543521
AM
6881 buckets = get_dynamic_data (file, nbuckets, hash_ent_size);
6882 chains = get_dynamic_data (file, nchains, hash_ent_size);
252b5132
RH
6883
6884 if (buckets == NULL || chains == NULL)
6885 return 0;
6886 }
6887
6888 if (do_syms
6889 && dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL)
6890 {
66543521
AM
6891 unsigned long hn;
6892 bfd_vma si;
252b5132
RH
6893
6894 printf (_("\nSymbol table for image:\n"));
f7a99963 6895 if (is_32bit_elf)
ca47b30c 6896 printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
f7a99963 6897 else
ca47b30c 6898 printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
252b5132
RH
6899
6900 for (hn = 0; hn < nbuckets; hn++)
6901 {
b34976b6 6902 if (! buckets[hn])
252b5132
RH
6903 continue;
6904
b34976b6 6905 for (si = buckets[hn]; si < nchains && si > 0; si = chains[si])
252b5132 6906 {
b34976b6 6907 Elf_Internal_Sym *psym;
66543521 6908 int n;
252b5132
RH
6909
6910 psym = dynamic_symbols + si;
6911
66543521
AM
6912 n = print_vma (si, DEC_5);
6913 if (n < 5)
6914 fputs (" " + n, stdout);
6915 printf (" %3lu: ", hn);
f7a99963 6916 print_vma (psym->st_value, LONG_HEX);
66543521 6917 putchar (' ');
d1133906 6918 print_vma (psym->st_size, DEC_5);
76da6bbe 6919
d1133906
NC
6920 printf (" %6s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
6921 printf (" %6s", get_symbol_binding (ELF_ST_BIND (psym->st_info)));
6922 printf (" %3s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
5e2b0d47
NC
6923 /* Check to see if any other bits in the st_other field are set.
6924 Note - displaying this information disrupts the layout of the
6925 table being generated, but for the moment this case is very rare. */
6926 if (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other))
6927 printf (" [%s] ", get_symbol_other (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other)));
31104126 6928 printf (" %3.3s ", get_symbol_index_type (psym->st_shndx));
d79b3d50
NC
6929 if (VALID_DYNAMIC_NAME (psym->st_name))
6930 print_symbol (25, GET_DYNAMIC_NAME (psym->st_name));
6931 else
6932 printf (" <corrupt: %14ld>", psym->st_name);
31104126 6933 putchar ('\n');
252b5132
RH
6934 }
6935 }
6936 }
6937 else if (do_syms && !do_using_dynamic)
6938 {
b34976b6 6939 unsigned int i;
252b5132
RH
6940
6941 for (i = 0, section = section_headers;
6942 i < elf_header.e_shnum;
6943 i++, section++)
6944 {
b34976b6 6945 unsigned int si;
c256ffe7
JJ
6946 char *strtab = NULL;
6947 unsigned long int strtab_size = 0;
b34976b6
AM
6948 Elf_Internal_Sym *symtab;
6949 Elf_Internal_Sym *psym;
252b5132
RH
6950
6951
6952 if ( section->sh_type != SHT_SYMTAB
6953 && section->sh_type != SHT_DYNSYM)
6954 continue;
6955
6956 printf (_("\nSymbol table '%s' contains %lu entries:\n"),
6957 SECTION_NAME (section),
6958 (unsigned long) (section->sh_size / section->sh_entsize));
f7a99963 6959 if (is_32bit_elf)
ca47b30c 6960 printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
f7a99963 6961 else
ca47b30c 6962 printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
252b5132 6963
9ad5cbcf 6964 symtab = GET_ELF_SYMBOLS (file, section);
252b5132
RH
6965 if (symtab == NULL)
6966 continue;
6967
6968 if (section->sh_link == elf_header.e_shstrndx)
c256ffe7
JJ
6969 {
6970 strtab = string_table;
6971 strtab_size = string_table_length;
6972 }
6973 else if (SECTION_HEADER_INDEX (section->sh_link) < elf_header.e_shnum)
252b5132 6974 {
b34976b6 6975 Elf_Internal_Shdr *string_sec;
252b5132 6976
9ad5cbcf 6977 string_sec = SECTION_HEADER (section->sh_link);
252b5132 6978
d3ba0551 6979 strtab = get_data (NULL, file, string_sec->sh_offset,
c256ffe7
JJ
6980 1, string_sec->sh_size, _("string table"));
6981 strtab_size = strtab != NULL ? string_sec->sh_size : 0;
252b5132
RH
6982 }
6983
6984 for (si = 0, psym = symtab;
6985 si < section->sh_size / section->sh_entsize;
b34976b6 6986 si++, psym++)
252b5132 6987 {
5e220199 6988 printf ("%6d: ", si);
f7a99963
NC
6989 print_vma (psym->st_value, LONG_HEX);
6990 putchar (' ');
6991 print_vma (psym->st_size, DEC_5);
d1133906
NC
6992 printf (" %-7s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
6993 printf (" %-6s", get_symbol_binding (ELF_ST_BIND (psym->st_info)));
6994 printf (" %-3s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
5e2b0d47
NC
6995 /* Check to see if any other bits in the st_other field are set.
6996 Note - displaying this information disrupts the layout of the
6997 table being generated, but for the moment this case is very rare. */
6998 if (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other))
6999 printf (" [%s] ", get_symbol_other (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other)));
31104126 7000 printf (" %4s ", get_symbol_index_type (psym->st_shndx));
c256ffe7
JJ
7001 print_symbol (25, psym->st_name < strtab_size
7002 ? strtab + psym->st_name : "<corrupt>");
252b5132
RH
7003
7004 if (section->sh_type == SHT_DYNSYM &&
b34976b6 7005 version_info[DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
252b5132 7006 {
b34976b6
AM
7007 unsigned char data[2];
7008 unsigned short vers_data;
7009 unsigned long offset;
7010 int is_nobits;
7011 int check_def;
252b5132 7012
d93f0186
NC
7013 offset = offset_from_vma
7014 (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
7015 sizeof data + si * sizeof (vers_data));
252b5132 7016
a6e9f9df 7017 get_data (&data, file, offset + si * sizeof (vers_data),
c256ffe7 7018 sizeof (data), 1, _("version data"));
252b5132
RH
7019
7020 vers_data = byte_get (data, 2);
7021
c256ffe7
JJ
7022 is_nobits = (SECTION_HEADER_INDEX (psym->st_shndx)
7023 < elf_header.e_shnum
7024 && SECTION_HEADER (psym->st_shndx)->sh_type
7025 == SHT_NOBITS);
252b5132
RH
7026
7027 check_def = (psym->st_shndx != SHN_UNDEF);
7028
7029 if ((vers_data & 0x8000) || vers_data > 1)
7030 {
b34976b6 7031 if (version_info[DT_VERSIONTAGIDX (DT_VERNEED)]
00d93f34 7032 && (is_nobits || ! check_def))
252b5132 7033 {
b34976b6
AM
7034 Elf_External_Verneed evn;
7035 Elf_Internal_Verneed ivn;
7036 Elf_Internal_Vernaux ivna;
252b5132
RH
7037
7038 /* We must test both. */
d93f0186
NC
7039 offset = offset_from_vma
7040 (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)],
7041 sizeof evn);
252b5132 7042
252b5132
RH
7043 do
7044 {
b34976b6 7045 unsigned long vna_off;
252b5132 7046
c256ffe7 7047 get_data (&evn, file, offset, sizeof (evn), 1,
a6e9f9df 7048 _("version need"));
dd27201e
L
7049
7050 ivn.vn_aux = BYTE_GET (evn.vn_aux);
7051 ivn.vn_next = BYTE_GET (evn.vn_next);
7052
252b5132
RH
7053 vna_off = offset + ivn.vn_aux;
7054
7055 do
7056 {
b34976b6 7057 Elf_External_Vernaux evna;
252b5132 7058
a6e9f9df 7059 get_data (&evna, file, vna_off,
c256ffe7 7060 sizeof (evna), 1,
a6e9f9df 7061 _("version need aux (3)"));
252b5132
RH
7062
7063 ivna.vna_other = BYTE_GET (evna.vna_other);
7064 ivna.vna_next = BYTE_GET (evna.vna_next);
7065 ivna.vna_name = BYTE_GET (evna.vna_name);
7066
7067 vna_off += ivna.vna_next;
7068 }
7069 while (ivna.vna_other != vers_data
7070 && ivna.vna_next != 0);
7071
7072 if (ivna.vna_other == vers_data)
7073 break;
7074
7075 offset += ivn.vn_next;
7076 }
7077 while (ivn.vn_next != 0);
7078
7079 if (ivna.vna_other == vers_data)
7080 {
7081 printf ("@%s (%d)",
c256ffe7
JJ
7082 ivna.vna_name < strtab_size
7083 ? strtab + ivna.vna_name : "<corrupt>",
7084 ivna.vna_other);
252b5132
RH
7085 check_def = 0;
7086 }
7087 else if (! is_nobits)
7088 error (_("bad dynamic symbol"));
7089 else
7090 check_def = 1;
7091 }
7092
7093 if (check_def)
7094 {
00d93f34 7095 if (vers_data != 0x8001
b34976b6 7096 && version_info[DT_VERSIONTAGIDX (DT_VERDEF)])
252b5132 7097 {
b34976b6
AM
7098 Elf_Internal_Verdef ivd;
7099 Elf_Internal_Verdaux ivda;
7100 Elf_External_Verdaux evda;
7101 unsigned long offset;
252b5132 7102
d93f0186
NC
7103 offset = offset_from_vma
7104 (file,
7105 version_info[DT_VERSIONTAGIDX (DT_VERDEF)],
7106 sizeof (Elf_External_Verdef));
252b5132
RH
7107
7108 do
7109 {
b34976b6 7110 Elf_External_Verdef evd;
252b5132 7111
a6e9f9df 7112 get_data (&evd, file, offset, sizeof (evd),
c256ffe7 7113 1, _("version def"));
252b5132 7114
b34976b6
AM
7115 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
7116 ivd.vd_aux = BYTE_GET (evd.vd_aux);
252b5132
RH
7117 ivd.vd_next = BYTE_GET (evd.vd_next);
7118
7119 offset += ivd.vd_next;
7120 }
7121 while (ivd.vd_ndx != (vers_data & 0x7fff)
7122 && ivd.vd_next != 0);
7123
7124 offset -= ivd.vd_next;
7125 offset += ivd.vd_aux;
7126
a6e9f9df 7127 get_data (&evda, file, offset, sizeof (evda),
c256ffe7 7128 1, _("version def aux"));
252b5132
RH
7129
7130 ivda.vda_name = BYTE_GET (evda.vda_name);
7131
7132 if (psym->st_name != ivda.vda_name)
7133 printf ((vers_data & 0x8000)
7134 ? "@%s" : "@@%s",
c256ffe7
JJ
7135 ivda.vda_name < strtab_size
7136 ? strtab + ivda.vda_name : "<corrupt>");
252b5132
RH
7137 }
7138 }
7139 }
7140 }
7141
7142 putchar ('\n');
7143 }
7144
7145 free (symtab);
7146 if (strtab != string_table)
7147 free (strtab);
7148 }
7149 }
7150 else if (do_syms)
7151 printf
7152 (_("\nDynamic symbol information is not available for displaying symbols.\n"));
7153
7154 if (do_histogram && buckets != NULL)
7155 {
66543521
AM
7156 unsigned long *lengths;
7157 unsigned long *counts;
7158 unsigned long hn;
7159 bfd_vma si;
7160 unsigned long maxlength = 0;
7161 unsigned long nzero_counts = 0;
7162 unsigned long nsyms = 0;
252b5132 7163
66543521
AM
7164 printf (_("\nHistogram for bucket list length (total of %lu buckets):\n"),
7165 (unsigned long) nbuckets);
252b5132
RH
7166 printf (_(" Length Number %% of total Coverage\n"));
7167
66543521 7168 lengths = calloc (nbuckets, sizeof (*lengths));
252b5132
RH
7169 if (lengths == NULL)
7170 {
7171 error (_("Out of memory"));
7172 return 0;
7173 }
7174 for (hn = 0; hn < nbuckets; ++hn)
7175 {
f7a99963 7176 for (si = buckets[hn]; si > 0 && si < nchains; si = chains[si])
252b5132 7177 {
b34976b6 7178 ++nsyms;
252b5132 7179 if (maxlength < ++lengths[hn])
b34976b6 7180 ++maxlength;
252b5132
RH
7181 }
7182 }
7183
66543521 7184 counts = calloc (maxlength + 1, sizeof (*counts));
252b5132
RH
7185 if (counts == NULL)
7186 {
7187 error (_("Out of memory"));
7188 return 0;
7189 }
7190
7191 for (hn = 0; hn < nbuckets; ++hn)
b34976b6 7192 ++counts[lengths[hn]];
252b5132 7193
103f02d3 7194 if (nbuckets > 0)
252b5132 7195 {
66543521
AM
7196 unsigned long i;
7197 printf (" 0 %-10lu (%5.1f%%)\n",
103f02d3 7198 counts[0], (counts[0] * 100.0) / nbuckets);
66543521 7199 for (i = 1; i <= maxlength; ++i)
103f02d3 7200 {
66543521
AM
7201 nzero_counts += counts[i] * i;
7202 printf ("%7lu %-10lu (%5.1f%%) %5.1f%%\n",
7203 i, counts[i], (counts[i] * 100.0) / nbuckets,
103f02d3
UD
7204 (nzero_counts * 100.0) / nsyms);
7205 }
252b5132
RH
7206 }
7207
7208 free (counts);
7209 free (lengths);
7210 }
7211
7212 if (buckets != NULL)
7213 {
7214 free (buckets);
7215 free (chains);
7216 }
7217
7218 return 1;
7219}
7220
7221static int
d3ba0551 7222process_syminfo (FILE *file ATTRIBUTE_UNUSED)
252b5132 7223{
b4c96d0d 7224 unsigned int i;
252b5132
RH
7225
7226 if (dynamic_syminfo == NULL
7227 || !do_dynamic)
7228 /* No syminfo, this is ok. */
7229 return 1;
7230
7231 /* There better should be a dynamic symbol section. */
7232 if (dynamic_symbols == NULL || dynamic_strings == NULL)
7233 return 0;
7234
7235 if (dynamic_addr)
7236 printf (_("\nDynamic info segment at offset 0x%lx contains %d entries:\n"),
7237 dynamic_syminfo_offset, dynamic_syminfo_nent);
7238
7239 printf (_(" Num: Name BoundTo Flags\n"));
7240 for (i = 0; i < dynamic_syminfo_nent; ++i)
7241 {
7242 unsigned short int flags = dynamic_syminfo[i].si_flags;
7243
31104126 7244 printf ("%4d: ", i);
d79b3d50
NC
7245 if (VALID_DYNAMIC_NAME (dynamic_symbols[i].st_name))
7246 print_symbol (30, GET_DYNAMIC_NAME (dynamic_symbols[i].st_name));
7247 else
7248 printf ("<corrupt: %19ld>", dynamic_symbols[i].st_name);
31104126 7249 putchar (' ');
252b5132
RH
7250
7251 switch (dynamic_syminfo[i].si_boundto)
7252 {
7253 case SYMINFO_BT_SELF:
7254 fputs ("SELF ", stdout);
7255 break;
7256 case SYMINFO_BT_PARENT:
7257 fputs ("PARENT ", stdout);
7258 break;
7259 default:
7260 if (dynamic_syminfo[i].si_boundto > 0
d79b3d50
NC
7261 && dynamic_syminfo[i].si_boundto < dynamic_nent
7262 && VALID_DYNAMIC_NAME (dynamic_section[dynamic_syminfo[i].si_boundto].d_un.d_val))
31104126 7263 {
d79b3d50 7264 print_symbol (10, GET_DYNAMIC_NAME (dynamic_section[dynamic_syminfo[i].si_boundto].d_un.d_val));
31104126
NC
7265 putchar (' ' );
7266 }
252b5132
RH
7267 else
7268 printf ("%-10d ", dynamic_syminfo[i].si_boundto);
7269 break;
7270 }
7271
7272 if (flags & SYMINFO_FLG_DIRECT)
7273 printf (" DIRECT");
7274 if (flags & SYMINFO_FLG_PASSTHRU)
7275 printf (" PASSTHRU");
7276 if (flags & SYMINFO_FLG_COPY)
7277 printf (" COPY");
7278 if (flags & SYMINFO_FLG_LAZYLOAD)
7279 printf (" LAZYLOAD");
7280
7281 puts ("");
7282 }
7283
7284 return 1;
7285}
7286
7287#ifdef SUPPORT_DISASSEMBLY
18bd398b 7288static int
d3ba0551 7289disassemble_section (Elf_Internal_Shdr *section, FILE *file)
252b5132
RH
7290{
7291 printf (_("\nAssembly dump of section %s\n"),
7292 SECTION_NAME (section));
7293
7294 /* XXX -- to be done --- XXX */
7295
7296 return 1;
7297}
7298#endif
7299
7300static int
d3ba0551 7301dump_section (Elf_Internal_Shdr *section, FILE *file)
252b5132 7302{
b34976b6
AM
7303 bfd_size_type bytes;
7304 bfd_vma addr;
7305 unsigned char *data;
7306 unsigned char *start;
252b5132
RH
7307
7308 bytes = section->sh_size;
7309
e69f2d21 7310 if (bytes == 0 || section->sh_type == SHT_NOBITS)
252b5132
RH
7311 {
7312 printf (_("\nSection '%s' has no data to dump.\n"),
7313 SECTION_NAME (section));
7314 return 0;
7315 }
7316 else
7317 printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section));
7318
7319 addr = section->sh_addr;
7320
c256ffe7
JJ
7321 start = get_data (NULL, file, section->sh_offset, 1, bytes,
7322 _("section data"));
a6e9f9df
AM
7323 if (!start)
7324 return 0;
252b5132
RH
7325
7326 data = start;
7327
7328 while (bytes)
7329 {
7330 int j;
7331 int k;
7332 int lbytes;
7333
7334 lbytes = (bytes > 16 ? 16 : bytes);
7335
148d3c43 7336 printf (" 0x%8.8lx ", (unsigned long) addr);
252b5132 7337
b34976b6 7338 switch (elf_header.e_ident[EI_DATA])
252b5132 7339 {
9ea033b2 7340 default:
252b5132
RH
7341 case ELFDATA2LSB:
7342 for (j = 15; j >= 0; j --)
7343 {
7344 if (j < lbytes)
b34976b6 7345 printf ("%2.2x", data[j]);
252b5132
RH
7346 else
7347 printf (" ");
7348
7349 if (!(j & 0x3))
7350 printf (" ");
7351 }
7352 break;
7353
7354 case ELFDATA2MSB:
7355 for (j = 0; j < 16; j++)
7356 {
7357 if (j < lbytes)
b34976b6 7358 printf ("%2.2x", data[j]);
252b5132
RH
7359 else
7360 printf (" ");
7361
7362 if ((j & 3) == 3)
7363 printf (" ");
7364 }
7365 break;
7366 }
7367
7368 for (j = 0; j < lbytes; j++)
7369 {
b34976b6 7370 k = data[j];
9376f0c7 7371 if (k >= ' ' && k < 0x7f)
252b5132
RH
7372 printf ("%c", k);
7373 else
7374 printf (".");
7375 }
7376
7377 putchar ('\n');
7378
7379 data += lbytes;
7380 addr += lbytes;
7381 bytes -= lbytes;
7382 }
7383
7384 free (start);
7385
7386 return 1;
7387}
7388
1007acb3 7389/* Apply addends of RELA relocations. */
d9296b18 7390
1007acb3
L
7391static int
7392debug_apply_rela_addends (void *file,
7393 Elf_Internal_Shdr *section,
7394 unsigned char *start)
d9296b18 7395{
1007acb3
L
7396 Elf_Internal_Shdr *relsec;
7397 unsigned char *end = start + section->sh_size;
7398 /* FIXME: The relocation field size is relocation type dependent. */
7399 unsigned int reloc_size = 4;
18bd398b 7400
1007acb3
L
7401 if (!is_relocatable)
7402 return 1;
d9296b18 7403
1007acb3
L
7404 if (section->sh_size < reloc_size)
7405 return 1;
d9296b18 7406
5b18a4bc
NC
7407 for (relsec = section_headers;
7408 relsec < section_headers + elf_header.e_shnum;
7409 ++relsec)
252b5132 7410 {
5b18a4bc
NC
7411 unsigned long nrelas;
7412 Elf_Internal_Rela *rela, *rp;
7413 Elf_Internal_Shdr *symsec;
7414 Elf_Internal_Sym *symtab;
7415 Elf_Internal_Sym *sym;
252b5132 7416
5b18a4bc 7417 if (relsec->sh_type != SHT_RELA
c256ffe7 7418 || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
5b18a4bc 7419 || SECTION_HEADER (relsec->sh_info) != section
c256ffe7
JJ
7420 || relsec->sh_size == 0
7421 || SECTION_HEADER_INDEX (relsec->sh_link) >= elf_header.e_shnum)
5b18a4bc 7422 continue;
428409d5 7423
5b18a4bc
NC
7424 if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
7425 &rela, &nrelas))
7426 return 0;
428409d5 7427
5b18a4bc
NC
7428 symsec = SECTION_HEADER (relsec->sh_link);
7429 symtab = GET_ELF_SYMBOLS (file, symsec);
103f02d3 7430
5b18a4bc 7431 for (rp = rela; rp < rela + nrelas; ++rp)
252b5132 7432 {
5b18a4bc 7433 unsigned char *loc;
103f02d3 7434
700dd8b7
L
7435 loc = start + rp->r_offset;
7436 if ((loc + reloc_size) > end)
7437 {
7438 warn (_("skipping invalid relocation offset 0x%lx in section %s\n"),
7439 (unsigned long) rp->r_offset,
7440 SECTION_NAME (section));
7441 continue;
7442 }
103f02d3 7443
5b18a4bc
NC
7444 if (is_32bit_elf)
7445 {
7446 sym = symtab + ELF32_R_SYM (rp->r_info);
103f02d3 7447
5b18a4bc
NC
7448 if (ELF32_R_SYM (rp->r_info) != 0
7449 && ELF32_ST_TYPE (sym->st_info) != STT_SECTION
7450 /* Relocations against object symbols can happen,
7451 eg when referencing a global array. For an
7452 example of this see the _clz.o binary in libgcc.a. */
7453 && ELF32_ST_TYPE (sym->st_info) != STT_OBJECT)
7454 {
520494b6 7455 warn (_("skipping unexpected symbol type %s in relocation in section .rela%s\n"),
5b18a4bc
NC
7456 get_symbol_type (ELF32_ST_TYPE (sym->st_info)),
7457 SECTION_NAME (section));
7458 continue;
7459 }
7460 }
7461 else
7462 {
a8b683fc
MR
7463 /* In MIPS little-endian objects, r_info isn't really a
7464 64-bit little-endian value: it has a 32-bit little-endian
7465 symbol index followed by four individual byte fields.
7466 Reorder INFO accordingly. */
7467 if (elf_header.e_machine == EM_MIPS
7468 && elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
7469 rp->r_info = (((rp->r_info & 0xffffffff) << 32)
7470 | ((rp->r_info >> 56) & 0xff)
7471 | ((rp->r_info >> 40) & 0xff00)
7472 | ((rp->r_info >> 24) & 0xff0000)
7473 | ((rp->r_info >> 8) & 0xff000000));
7474
5b18a4bc 7475 sym = symtab + ELF64_R_SYM (rp->r_info);
0e0c4098 7476
5b18a4bc
NC
7477 if (ELF64_R_SYM (rp->r_info) != 0
7478 && ELF64_ST_TYPE (sym->st_info) != STT_SECTION
7479 && ELF64_ST_TYPE (sym->st_info) != STT_OBJECT)
7480 {
7481 warn (_("skipping unexpected symbol type %s in relocation in section .rela.%s\n"),
7482 get_symbol_type (ELF64_ST_TYPE (sym->st_info)),
7483 SECTION_NAME (section));
7484 continue;
7485 }
7486 }
252b5132 7487
5b18a4bc
NC
7488 byte_put (loc, rp->r_addend, reloc_size);
7489 }
252b5132 7490
5b18a4bc
NC
7491 free (symtab);
7492 free (rela);
7493 break;
7494 }
7495 return 1;
7496}
103f02d3 7497
19e6b90e
L
7498int
7499load_debug_section (enum dwarf_section_display_enum debug, void *file)
1007acb3 7500{
19e6b90e
L
7501 struct dwarf_section *section = &debug_displays [debug].section;
7502 Elf_Internal_Shdr *sec;
7503 char buf [64];
1007acb3 7504
19e6b90e
L
7505 /* If it is already loaded, do nothing. */
7506 if (section->start != NULL)
7507 return 1;
1007acb3 7508
19e6b90e
L
7509 /* Locate the debug section. */
7510 sec = find_section (section->name);
7511 if (sec == NULL)
7512 return 0;
1007acb3 7513
19e6b90e
L
7514 snprintf (buf, sizeof (buf), _("%s section data"), section->name);
7515 section->address = sec->sh_addr;
7516 section->size = sec->sh_size;
7517 section->start = get_data (NULL, file, sec->sh_offset, 1,
7518 sec->sh_size, buf);
1007acb3 7519
19e6b90e
L
7520 if (debug_displays [debug].relocate)
7521 debug_apply_rela_addends (file, sec, section->start);
1007acb3 7522
19e6b90e 7523 return section->start != NULL;
1007acb3
L
7524}
7525
19e6b90e
L
7526void
7527free_debug_section (enum dwarf_section_display_enum debug)
1007acb3 7528{
19e6b90e 7529 struct dwarf_section *section = &debug_displays [debug].section;
1007acb3 7530
19e6b90e
L
7531 if (section->start == NULL)
7532 return;
1007acb3 7533
19e6b90e
L
7534 free ((char *) section->start);
7535 section->start = NULL;
7536 section->address = 0;
7537 section->size = 0;
1007acb3
L
7538}
7539
1007acb3 7540static int
19e6b90e 7541display_debug_section (Elf_Internal_Shdr *section, FILE *file)
1007acb3 7542{
19e6b90e
L
7543 char *name = SECTION_NAME (section);
7544 bfd_size_type length;
7545 int result = 1;
7546 enum dwarf_section_display_enum i;
1007acb3 7547
19e6b90e
L
7548 length = section->sh_size;
7549 if (length == 0)
1007acb3 7550 {
19e6b90e
L
7551 printf (_("\nSection '%s' has no debugging data.\n"), name);
7552 return 0;
1007acb3
L
7553 }
7554
19e6b90e
L
7555 if (strneq (name, ".gnu.linkonce.wi.", 17))
7556 name = ".debug_info";
1007acb3 7557
19e6b90e
L
7558 /* See if we know how to display the contents of this section. */
7559 for (i = 0; i < max; i++)
7560 if (streq (debug_displays[i].section.name, name))
7561 {
7562 struct dwarf_section *sec = &debug_displays [i].section;
1007acb3 7563
19e6b90e
L
7564 if (load_debug_section (i, file))
7565 {
7566 result &= debug_displays[i].display (sec, file);
1007acb3 7567
19e6b90e
L
7568 if (i != info && i != abbrev)
7569 free_debug_section (i);
7570 }
1007acb3 7571
19e6b90e
L
7572 break;
7573 }
1007acb3 7574
19e6b90e 7575 if (i == max)
1007acb3 7576 {
19e6b90e
L
7577 printf (_("Unrecognized debug section: %s\n"), name);
7578 result = 0;
1007acb3
L
7579 }
7580
19e6b90e 7581 return result;
5b18a4bc 7582}
103f02d3 7583
aef1f6d0
DJ
7584/* Set DUMP_SECTS for all sections where dumps were requested
7585 based on section name. */
7586
7587static void
7588initialise_dumps_byname (void)
7589{
7590 struct dump_list_entry *cur;
7591
7592 for (cur = dump_sects_byname; cur; cur = cur->next)
7593 {
7594 unsigned int i;
7595 int any;
7596
7597 for (i = 0, any = 0; i < elf_header.e_shnum; i++)
7598 if (streq (SECTION_NAME (section_headers + i), cur->name))
7599 {
7600 request_dump (i, cur->type);
7601 any = 1;
7602 }
7603
7604 if (!any)
7605 warn (_("Section '%s' was not dumped because it does not exist!\n"),
7606 cur->name);
7607 }
7608}
7609
5b18a4bc 7610static void
19e6b90e 7611process_section_contents (FILE *file)
5b18a4bc 7612{
19e6b90e
L
7613 Elf_Internal_Shdr *section;
7614 unsigned int i;
103f02d3 7615
19e6b90e
L
7616 if (! do_dump)
7617 return;
103f02d3 7618
aef1f6d0
DJ
7619 initialise_dumps_byname ();
7620
19e6b90e
L
7621 for (i = 0, section = section_headers;
7622 i < elf_header.e_shnum && i < num_dump_sects;
7623 i++, section++)
7624 {
7625#ifdef SUPPORT_DISASSEMBLY
7626 if (dump_sects[i] & DISASS_DUMP)
7627 disassemble_section (section, file);
7628#endif
7629 if (dump_sects[i] & HEX_DUMP)
7630 dump_section (section, file);
103f02d3 7631
19e6b90e
L
7632 if (dump_sects[i] & DEBUG_DUMP)
7633 display_debug_section (section, file);
5b18a4bc 7634 }
103f02d3 7635
19e6b90e
L
7636 /* Check to see if the user requested a
7637 dump of a section that does not exist. */
7638 while (i++ < num_dump_sects)
7639 if (dump_sects[i])
7640 warn (_("Section %d was not dumped because it does not exist!\n"), i);
5b18a4bc 7641}
103f02d3 7642
5b18a4bc 7643static void
19e6b90e 7644process_mips_fpe_exception (int mask)
5b18a4bc 7645{
19e6b90e
L
7646 if (mask)
7647 {
7648 int first = 1;
7649 if (mask & OEX_FPU_INEX)
7650 fputs ("INEX", stdout), first = 0;
7651 if (mask & OEX_FPU_UFLO)
7652 printf ("%sUFLO", first ? "" : "|"), first = 0;
7653 if (mask & OEX_FPU_OFLO)
7654 printf ("%sOFLO", first ? "" : "|"), first = 0;
7655 if (mask & OEX_FPU_DIV0)
7656 printf ("%sDIV0", first ? "" : "|"), first = 0;
7657 if (mask & OEX_FPU_INVAL)
7658 printf ("%sINVAL", first ? "" : "|");
7659 }
5b18a4bc 7660 else
19e6b90e 7661 fputs ("0", stdout);
5b18a4bc 7662}
103f02d3 7663
11c1ff18
PB
7664/* ARM EABI attributes section. */
7665typedef struct
7666{
7667 int tag;
7668 const char *name;
7669 /* 0 = special, 1 = string, 2 = uleb123, > 0x80 == table lookup. */
7670 int type;
7671 const char **table;
7672} arm_attr_public_tag;
7673
7674static const char *arm_attr_tag_CPU_arch[] =
7675 {"Pre-v4", "v4", "v4T", "v5T", "v5TE", "v5TEJ", "v6", "v6KZ", "v6T2",
7676 "v6K", "v7"};
7677static const char *arm_attr_tag_ARM_ISA_use[] = {"No", "Yes"};
7678static const char *arm_attr_tag_THUMB_ISA_use[] =
7679 {"No", "Thumb-1", "Thumb-2"};
7680static const char *arm_attr_tag_VFP_arch[] = {"No", "VFPv1", "VFPv2"};
7681static const char *arm_attr_tag_WMMX_arch[] = {"No", "WMMXv1"};
7682static const char *arm_attr_tag_NEON_arch[] = {"No", "NEONv1"};
7683static const char *arm_attr_tag_ABI_PCS_config[] =
7684 {"None", "Bare platform", "Linux application", "Linux DSO", "PalmOS 2004",
7685 "PalmOS (reserved)", "SymbianOS 2004", "SymbianOS (reserved)"};
7686static const char *arm_attr_tag_ABI_PCS_R9_use[] =
7687 {"V6", "SB", "TLS", "Unused"};
7688static const char *arm_attr_tag_ABI_PCS_RW_data[] =
7689 {"Absolute", "PC-relative", "SB-relative", "None"};
7690static const char *arm_attr_tag_ABI_PCS_RO_DATA[] =
7691 {"Absolute", "PC-relative", "None"};
7692static const char *arm_attr_tag_ABI_PCS_GOT_use[] =
7693 {"None", "direct", "GOT-indirect"};
7694static const char *arm_attr_tag_ABI_PCS_wchar_t[] =
7695 {"None", "??? 1", "2", "??? 3", "4"};
7696static const char *arm_attr_tag_ABI_FP_rounding[] = {"Unused", "Needed"};
7697static const char *arm_attr_tag_ABI_FP_denormal[] = {"Unused", "Needed"};
7698static const char *arm_attr_tag_ABI_FP_exceptions[] = {"Unused", "Needed"};
7699static const char *arm_attr_tag_ABI_FP_user_exceptions[] = {"Unused", "Needed"};
7700static const char *arm_attr_tag_ABI_FP_number_model[] =
7701 {"Unused", "Finite", "RTABI", "IEEE 754"};
7702static const char *arm_attr_tag_ABI_align8_needed[] = {"No", "Yes", "4-byte"};
7703static const char *arm_attr_tag_ABI_align8_preserved[] =
7704 {"No", "Yes, except leaf SP", "Yes"};
7705static const char *arm_attr_tag_ABI_enum_size[] =
7706 {"Unused", "small", "int", "forced to int"};
7707static const char *arm_attr_tag_ABI_HardFP_use[] =
7708 {"As Tag_VFP_arch", "SP only", "DP only", "SP and DP"};
7709static const char *arm_attr_tag_ABI_VFP_args[] =
7710 {"AAPCS", "VFP registers", "custom"};
7711static const char *arm_attr_tag_ABI_WMMX_args[] =
7712 {"AAPCS", "WMMX registers", "custom"};
7713static const char *arm_attr_tag_ABI_optimization_goals[] =
7714 {"None", "Prefer Speed", "Aggressive Speed", "Prefer Size",
7715 "Aggressive Size", "Prefer Debug", "Aggressive Debug"};
7716static const char *arm_attr_tag_ABI_FP_optimization_goals[] =
7717 {"None", "Prefer Speed", "Aggressive Speed", "Prefer Size",
7718 "Aggressive Size", "Prefer Accuracy", "Aggressive Accuracy"};
7719
7720#define LOOKUP(id, name) \
7721 {id, #name, 0x80 | ARRAY_SIZE(arm_attr_tag_##name), arm_attr_tag_##name}
7722static arm_attr_public_tag arm_attr_public_tags[] =
7723{
7724 {4, "CPU_raw_name", 1, NULL},
7725 {5, "CPU_name", 1, NULL},
7726 LOOKUP(6, CPU_arch),
7727 {7, "CPU_arch_profile", 0, NULL},
7728 LOOKUP(8, ARM_ISA_use),
7729 LOOKUP(9, THUMB_ISA_use),
7730 LOOKUP(10, VFP_arch),
7731 LOOKUP(11, WMMX_arch),
7732 LOOKUP(12, NEON_arch),
7733 LOOKUP(13, ABI_PCS_config),
7734 LOOKUP(14, ABI_PCS_R9_use),
7735 LOOKUP(15, ABI_PCS_RW_data),
7736 LOOKUP(16, ABI_PCS_RO_DATA),
7737 LOOKUP(17, ABI_PCS_GOT_use),
7738 LOOKUP(18, ABI_PCS_wchar_t),
7739 LOOKUP(19, ABI_FP_rounding),
7740 LOOKUP(20, ABI_FP_denormal),
7741 LOOKUP(21, ABI_FP_exceptions),
7742 LOOKUP(22, ABI_FP_user_exceptions),
7743 LOOKUP(23, ABI_FP_number_model),
7744 LOOKUP(24, ABI_align8_needed),
7745 LOOKUP(25, ABI_align8_preserved),
7746 LOOKUP(26, ABI_enum_size),
7747 LOOKUP(27, ABI_HardFP_use),
7748 LOOKUP(28, ABI_VFP_args),
7749 LOOKUP(29, ABI_WMMX_args),
7750 LOOKUP(30, ABI_optimization_goals),
7751 LOOKUP(31, ABI_FP_optimization_goals),
7752 {32, "compatibility", 0, NULL}
7753};
7754#undef LOOKUP
7755
7756/* Read an unsigned LEB128 encoded value from p. Set *PLEN to the number of
7757 bytes read. */
7758static unsigned int
7759read_uleb128 (unsigned char *p, unsigned int *plen)
7760{
7761 unsigned char c;
7762 unsigned int val;
7763 int shift;
7764 int len;
7765
7766 val = 0;
7767 shift = 0;
7768 len = 0;
7769 do
7770 {
7771 c = *(p++);
7772 len++;
7773 val |= ((unsigned int)c & 0x7f) << shift;
7774 shift += 7;
7775 }
7776 while (c & 0x80);
7777
7778 *plen = len;
7779 return val;
7780}
7781
7782static unsigned char *
7783display_arm_attribute (unsigned char *p)
7784{
7785 int tag;
7786 unsigned int len;
7787 int val;
7788 arm_attr_public_tag *attr;
7789 unsigned i;
7790 int type;
7791
7792 tag = read_uleb128 (p, &len);
7793 p += len;
7794 attr = NULL;
7795 for (i = 0; i < ARRAY_SIZE(arm_attr_public_tags); i++)
7796 {
7797 if (arm_attr_public_tags[i].tag == tag)
7798 {
7799 attr = &arm_attr_public_tags[i];
7800 break;
7801 }
7802 }
7803
7804 if (attr)
7805 {
7806 printf (" Tag_%s: ", attr->name);
7807 switch (attr->type)
7808 {
7809 case 0:
7810 switch (tag)
7811 {
7812 case 7: /* Tag_CPU_arch_profile. */
7813 val = read_uleb128 (p, &len);
7814 p += len;
7815 switch (val)
7816 {
7817 case 0: printf ("None\n"); break;
7818 case 'A': printf ("Application\n"); break;
7819 case 'R': printf ("Realtime\n"); break;
7820 case 'M': printf ("Microcontroller\n"); break;
7821 default: printf ("??? (%d)\n", val); break;
7822 }
7823 break;
7824
7825 case 32: /* Tag_compatibility. */
7826 val = read_uleb128 (p, &len);
7827 p += len;
7828 printf ("flag = %d, vendor = %s\n", val, p);
7829 p += strlen((char *)p) + 1;
7830 break;
7831
7832 default:
7833 abort();
7834 }
7835 return p;
7836
7837 case 1:
7838 case 2:
7839 type = attr->type;
7840 break;
7841
7842 default:
7843 assert (attr->type & 0x80);
7844 val = read_uleb128 (p, &len);
7845 p += len;
7846 type = attr->type & 0x7f;
7847 if (val >= type)
7848 printf ("??? (%d)\n", val);
7849 else
7850 printf ("%s\n", attr->table[val]);
7851 return p;
7852 }
7853 }
7854 else
7855 {
7856 if (tag & 1)
7857 type = 1; /* String. */
7858 else
7859 type = 2; /* uleb128. */
7860 printf (" Tag_unknown_%d: ", tag);
7861 }
7862
7863 if (type == 1)
7864 {
7865 printf ("\"%s\"\n", p);
7866 p += strlen((char *)p) + 1;
7867 }
7868 else
7869 {
7870 val = read_uleb128 (p, &len);
7871 p += len;
7872 printf ("%d (0x%x)\n", val, val);
7873 }
7874
7875 return p;
7876}
7877
7878static int
7879process_arm_specific (FILE *file)
7880{
7881 Elf_Internal_Shdr *sect;
7882 unsigned char *contents;
7883 unsigned char *p;
7884 unsigned char *end;
7885 bfd_vma section_len;
7886 bfd_vma len;
7887 unsigned i;
7888
7889 /* Find the section header so that we get the size. */
7890 for (i = 0, sect = section_headers;
7891 i < elf_header.e_shnum;
7892 i++, sect++)
7893 {
7894 if (sect->sh_type != SHT_ARM_ATTRIBUTES)
7895 continue;
7896
7897 contents = get_data (NULL, file, sect->sh_offset, 1, sect->sh_size,
7898 _("attributes"));
7899
7900 if (!contents)
7901 continue;
7902 p = contents;
7903 if (*p == 'A')
7904 {
7905 len = sect->sh_size - 1;
7906 p++;
7907 while (len > 0)
7908 {
7909 int namelen;
7910 bfd_boolean public_section;
7911
7912 section_len = byte_get (p, 4);
7913 p += 4;
7914 if (section_len > len)
7915 {
7916 printf (_("ERROR: Bad section length (%d > %d)\n"),
7917 (int)section_len, (int)len);
7918 section_len = len;
7919 }
7920 len -= section_len;
7921 printf ("Attribute Section: %s\n", p);
7922 if (strcmp ((char *)p, "aeabi") == 0)
7923 public_section = TRUE;
7924 else
7925 public_section = FALSE;
7926 namelen = strlen ((char *)p) + 1;
7927 p += namelen;
7928 section_len -= namelen + 4;
7929 while (section_len > 0)
7930 {
7931 int tag = *(p++);
7932 int val;
7933 bfd_vma size;
7934 size = byte_get (p, 4);
7935 if (size > section_len)
7936 {
7937 printf (_("ERROR: Bad subsection length (%d > %d)\n"),
7938 (int)size, (int)section_len);
7939 size = section_len;
7940 }
7941 section_len -= size;
7942 end = p + size - 1;
7943 p += 4;
7944 switch (tag)
7945 {
7946 case 1:
7947 printf ("File Attributes\n");
7948 break;
7949 case 2:
7950 printf ("Section Attributes:");
7951 goto do_numlist;
7952 case 3:
7953 printf ("Symbol Attributes:");
7954 do_numlist:
7955 for (;;)
7956 {
7957 unsigned int i;
7958 val = read_uleb128 (p, &i);
7959 p += i;
7960 if (val == 0)
7961 break;
7962 printf (" %d", val);
7963 }
7964 printf ("\n");
7965 break;
7966 default:
7967 printf ("Unknown tag: %d\n", tag);
7968 public_section = FALSE;
7969 break;
7970 }
7971 if (public_section)
7972 {
7973 while (p < end)
7974 p = display_arm_attribute(p);
7975 }
7976 else
7977 {
7978 /* ??? Do something sensible, like dump hex. */
7979 printf (" Unknown section contexts\n");
7980 p = end;
7981 }
7982 }
7983 }
7984 }
7985 else
7986 {
7987 printf (_("Unknown format '%c'\n"), *p);
7988 }
7989
7990 free(contents);
7991 }
7992 return 1;
7993}
7994
19e6b90e
L
7995static int
7996process_mips_specific (FILE *file)
5b18a4bc 7997{
19e6b90e
L
7998 Elf_Internal_Dyn *entry;
7999 size_t liblist_offset = 0;
8000 size_t liblistno = 0;
8001 size_t conflictsno = 0;
8002 size_t options_offset = 0;
8003 size_t conflicts_offset = 0;
103f02d3 8004
19e6b90e
L
8005 /* We have a lot of special sections. Thanks SGI! */
8006 if (dynamic_section == NULL)
8007 /* No information available. */
8008 return 0;
252b5132 8009
b2d38a17 8010 for (entry = dynamic_section; entry->d_tag != DT_NULL; ++entry)
252b5132
RH
8011 switch (entry->d_tag)
8012 {
8013 case DT_MIPS_LIBLIST:
d93f0186
NC
8014 liblist_offset
8015 = offset_from_vma (file, entry->d_un.d_val,
8016 liblistno * sizeof (Elf32_External_Lib));
252b5132
RH
8017 break;
8018 case DT_MIPS_LIBLISTNO:
8019 liblistno = entry->d_un.d_val;
8020 break;
8021 case DT_MIPS_OPTIONS:
d93f0186 8022 options_offset = offset_from_vma (file, entry->d_un.d_val, 0);
252b5132
RH
8023 break;
8024 case DT_MIPS_CONFLICT:
d93f0186
NC
8025 conflicts_offset
8026 = offset_from_vma (file, entry->d_un.d_val,
8027 conflictsno * sizeof (Elf32_External_Conflict));
252b5132
RH
8028 break;
8029 case DT_MIPS_CONFLICTNO:
8030 conflictsno = entry->d_un.d_val;
8031 break;
8032 default:
8033 break;
8034 }
8035
8036 if (liblist_offset != 0 && liblistno != 0 && do_dynamic)
8037 {
b34976b6 8038 Elf32_External_Lib *elib;
252b5132
RH
8039 size_t cnt;
8040
d3ba0551 8041 elib = get_data (NULL, file, liblist_offset,
c256ffe7 8042 liblistno, sizeof (Elf32_External_Lib),
d3ba0551 8043 _("liblist"));
a6e9f9df 8044 if (elib)
252b5132 8045 {
a6e9f9df
AM
8046 printf ("\nSection '.liblist' contains %lu entries:\n",
8047 (unsigned long) liblistno);
8048 fputs (" Library Time Stamp Checksum Version Flags\n",
8049 stdout);
8050
8051 for (cnt = 0; cnt < liblistno; ++cnt)
252b5132 8052 {
a6e9f9df
AM
8053 Elf32_Lib liblist;
8054 time_t time;
8055 char timebuf[20];
b34976b6 8056 struct tm *tmp;
a6e9f9df
AM
8057
8058 liblist.l_name = BYTE_GET (elib[cnt].l_name);
8059 time = BYTE_GET (elib[cnt].l_time_stamp);
8060 liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum);
8061 liblist.l_version = BYTE_GET (elib[cnt].l_version);
8062 liblist.l_flags = BYTE_GET (elib[cnt].l_flags);
8063
8064 tmp = gmtime (&time);
e9e44622
JJ
8065 snprintf (timebuf, sizeof (timebuf),
8066 "%04u-%02u-%02uT%02u:%02u:%02u",
8067 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
8068 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
a6e9f9df 8069
31104126 8070 printf ("%3lu: ", (unsigned long) cnt);
d79b3d50
NC
8071 if (VALID_DYNAMIC_NAME (liblist.l_name))
8072 print_symbol (20, GET_DYNAMIC_NAME (liblist.l_name));
8073 else
8074 printf ("<corrupt: %9ld>", liblist.l_name);
31104126
NC
8075 printf (" %s %#10lx %-7ld", timebuf, liblist.l_checksum,
8076 liblist.l_version);
a6e9f9df
AM
8077
8078 if (liblist.l_flags == 0)
8079 puts (" NONE");
8080 else
8081 {
8082 static const struct
252b5132 8083 {
b34976b6 8084 const char *name;
a6e9f9df 8085 int bit;
252b5132 8086 }
a6e9f9df
AM
8087 l_flags_vals[] =
8088 {
8089 { " EXACT_MATCH", LL_EXACT_MATCH },
8090 { " IGNORE_INT_VER", LL_IGNORE_INT_VER },
8091 { " REQUIRE_MINOR", LL_REQUIRE_MINOR },
8092 { " EXPORTS", LL_EXPORTS },
8093 { " DELAY_LOAD", LL_DELAY_LOAD },
8094 { " DELTA", LL_DELTA }
8095 };
8096 int flags = liblist.l_flags;
8097 size_t fcnt;
8098
8099 for (fcnt = 0;
8100 fcnt < sizeof (l_flags_vals) / sizeof (l_flags_vals[0]);
8101 ++fcnt)
8102 if ((flags & l_flags_vals[fcnt].bit) != 0)
8103 {
8104 fputs (l_flags_vals[fcnt].name, stdout);
8105 flags ^= l_flags_vals[fcnt].bit;
8106 }
8107 if (flags != 0)
8108 printf (" %#x", (unsigned int) flags);
252b5132 8109
a6e9f9df
AM
8110 puts ("");
8111 }
252b5132 8112 }
252b5132 8113
a6e9f9df
AM
8114 free (elib);
8115 }
252b5132
RH
8116 }
8117
8118 if (options_offset != 0)
8119 {
b34976b6
AM
8120 Elf_External_Options *eopt;
8121 Elf_Internal_Shdr *sect = section_headers;
8122 Elf_Internal_Options *iopt;
8123 Elf_Internal_Options *option;
252b5132
RH
8124 size_t offset;
8125 int cnt;
8126
8127 /* Find the section header so that we get the size. */
8128 while (sect->sh_type != SHT_MIPS_OPTIONS)
b34976b6 8129 ++sect;
252b5132 8130
c256ffe7 8131 eopt = get_data (NULL, file, options_offset, 1, sect->sh_size,
d3ba0551 8132 _("options"));
a6e9f9df 8133 if (eopt)
252b5132 8134 {
c256ffe7 8135 iopt = cmalloc ((sect->sh_size / sizeof (eopt)), sizeof (*iopt));
a6e9f9df
AM
8136 if (iopt == NULL)
8137 {
8138 error (_("Out of memory"));
8139 return 0;
8140 }
76da6bbe 8141
a6e9f9df
AM
8142 offset = cnt = 0;
8143 option = iopt;
252b5132 8144
a6e9f9df
AM
8145 while (offset < sect->sh_size)
8146 {
b34976b6 8147 Elf_External_Options *eoption;
252b5132 8148
a6e9f9df 8149 eoption = (Elf_External_Options *) ((char *) eopt + offset);
252b5132 8150
a6e9f9df
AM
8151 option->kind = BYTE_GET (eoption->kind);
8152 option->size = BYTE_GET (eoption->size);
8153 option->section = BYTE_GET (eoption->section);
8154 option->info = BYTE_GET (eoption->info);
76da6bbe 8155
a6e9f9df 8156 offset += option->size;
252b5132 8157
a6e9f9df
AM
8158 ++option;
8159 ++cnt;
8160 }
252b5132 8161
a6e9f9df
AM
8162 printf (_("\nSection '%s' contains %d entries:\n"),
8163 SECTION_NAME (sect), cnt);
76da6bbe 8164
a6e9f9df 8165 option = iopt;
252b5132 8166
a6e9f9df 8167 while (cnt-- > 0)
252b5132 8168 {
a6e9f9df
AM
8169 size_t len;
8170
8171 switch (option->kind)
252b5132 8172 {
a6e9f9df
AM
8173 case ODK_NULL:
8174 /* This shouldn't happen. */
8175 printf (" NULL %d %lx", option->section, option->info);
8176 break;
8177 case ODK_REGINFO:
8178 printf (" REGINFO ");
8179 if (elf_header.e_machine == EM_MIPS)
8180 {
8181 /* 32bit form. */
b34976b6
AM
8182 Elf32_External_RegInfo *ereg;
8183 Elf32_RegInfo reginfo;
a6e9f9df
AM
8184
8185 ereg = (Elf32_External_RegInfo *) (option + 1);
8186 reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
8187 reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
8188 reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
8189 reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
8190 reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
8191 reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
8192
8193 printf ("GPR %08lx GP 0x%lx\n",
8194 reginfo.ri_gprmask,
8195 (unsigned long) reginfo.ri_gp_value);
8196 printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n",
8197 reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
8198 reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
8199 }
8200 else
8201 {
8202 /* 64 bit form. */
b34976b6 8203 Elf64_External_RegInfo *ereg;
a6e9f9df
AM
8204 Elf64_Internal_RegInfo reginfo;
8205
8206 ereg = (Elf64_External_RegInfo *) (option + 1);
8207 reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
8208 reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
8209 reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
8210 reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
8211 reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
66543521 8212 reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
a6e9f9df
AM
8213
8214 printf ("GPR %08lx GP 0x",
8215 reginfo.ri_gprmask);
8216 printf_vma (reginfo.ri_gp_value);
8217 printf ("\n");
8218
8219 printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n",
8220 reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
8221 reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
8222 }
8223 ++option;
8224 continue;
8225 case ODK_EXCEPTIONS:
8226 fputs (" EXCEPTIONS fpe_min(", stdout);
8227 process_mips_fpe_exception (option->info & OEX_FPU_MIN);
8228 fputs (") fpe_max(", stdout);
8229 process_mips_fpe_exception ((option->info & OEX_FPU_MAX) >> 8);
8230 fputs (")", stdout);
8231
8232 if (option->info & OEX_PAGE0)
8233 fputs (" PAGE0", stdout);
8234 if (option->info & OEX_SMM)
8235 fputs (" SMM", stdout);
8236 if (option->info & OEX_FPDBUG)
8237 fputs (" FPDBUG", stdout);
8238 if (option->info & OEX_DISMISS)
8239 fputs (" DISMISS", stdout);
8240 break;
8241 case ODK_PAD:
8242 fputs (" PAD ", stdout);
8243 if (option->info & OPAD_PREFIX)
8244 fputs (" PREFIX", stdout);
8245 if (option->info & OPAD_POSTFIX)
8246 fputs (" POSTFIX", stdout);
8247 if (option->info & OPAD_SYMBOL)
8248 fputs (" SYMBOL", stdout);
8249 break;
8250 case ODK_HWPATCH:
8251 fputs (" HWPATCH ", stdout);
8252 if (option->info & OHW_R4KEOP)
8253 fputs (" R4KEOP", stdout);
8254 if (option->info & OHW_R8KPFETCH)
8255 fputs (" R8KPFETCH", stdout);
8256 if (option->info & OHW_R5KEOP)
8257 fputs (" R5KEOP", stdout);
8258 if (option->info & OHW_R5KCVTL)
8259 fputs (" R5KCVTL", stdout);
8260 break;
8261 case ODK_FILL:
8262 fputs (" FILL ", stdout);
8263 /* XXX Print content of info word? */
8264 break;
8265 case ODK_TAGS:
8266 fputs (" TAGS ", stdout);
8267 /* XXX Print content of info word? */
8268 break;
8269 case ODK_HWAND:
8270 fputs (" HWAND ", stdout);
8271 if (option->info & OHWA0_R4KEOP_CHECKED)
8272 fputs (" R4KEOP_CHECKED", stdout);
8273 if (option->info & OHWA0_R4KEOP_CLEAN)
8274 fputs (" R4KEOP_CLEAN", stdout);
8275 break;
8276 case ODK_HWOR:
8277 fputs (" HWOR ", stdout);
8278 if (option->info & OHWA0_R4KEOP_CHECKED)
8279 fputs (" R4KEOP_CHECKED", stdout);
8280 if (option->info & OHWA0_R4KEOP_CLEAN)
8281 fputs (" R4KEOP_CLEAN", stdout);
8282 break;
8283 case ODK_GP_GROUP:
8284 printf (" GP_GROUP %#06lx self-contained %#06lx",
8285 option->info & OGP_GROUP,
8286 (option->info & OGP_SELF) >> 16);
8287 break;
8288 case ODK_IDENT:
8289 printf (" IDENT %#06lx self-contained %#06lx",
8290 option->info & OGP_GROUP,
8291 (option->info & OGP_SELF) >> 16);
8292 break;
8293 default:
8294 /* This shouldn't happen. */
8295 printf (" %3d ??? %d %lx",
8296 option->kind, option->section, option->info);
8297 break;
252b5132 8298 }
a6e9f9df 8299
b34976b6 8300 len = sizeof (*eopt);
a6e9f9df
AM
8301 while (len < option->size)
8302 if (((char *) option)[len] >= ' '
8303 && ((char *) option)[len] < 0x7f)
8304 printf ("%c", ((char *) option)[len++]);
8305 else
8306 printf ("\\%03o", ((char *) option)[len++]);
8307
8308 fputs ("\n", stdout);
252b5132 8309 ++option;
252b5132
RH
8310 }
8311
a6e9f9df 8312 free (eopt);
252b5132 8313 }
252b5132
RH
8314 }
8315
8316 if (conflicts_offset != 0 && conflictsno != 0)
8317 {
b34976b6 8318 Elf32_Conflict *iconf;
252b5132
RH
8319 size_t cnt;
8320
8321 if (dynamic_symbols == NULL)
8322 {
3a1a2036 8323 error (_("conflict list found without a dynamic symbol table"));
252b5132
RH
8324 return 0;
8325 }
8326
c256ffe7 8327 iconf = cmalloc (conflictsno, sizeof (*iconf));
252b5132
RH
8328 if (iconf == NULL)
8329 {
8330 error (_("Out of memory"));
8331 return 0;
8332 }
8333
9ea033b2 8334 if (is_32bit_elf)
252b5132 8335 {
b34976b6 8336 Elf32_External_Conflict *econf32;
a6e9f9df 8337
d3ba0551 8338 econf32 = get_data (NULL, file, conflicts_offset,
c256ffe7 8339 conflictsno, sizeof (*econf32), _("conflict"));
a6e9f9df
AM
8340 if (!econf32)
8341 return 0;
252b5132
RH
8342
8343 for (cnt = 0; cnt < conflictsno; ++cnt)
8344 iconf[cnt] = BYTE_GET (econf32[cnt]);
a6e9f9df
AM
8345
8346 free (econf32);
252b5132
RH
8347 }
8348 else
8349 {
b34976b6 8350 Elf64_External_Conflict *econf64;
a6e9f9df 8351
d3ba0551 8352 econf64 = get_data (NULL, file, conflicts_offset,
c256ffe7 8353 conflictsno, sizeof (*econf64), _("conflict"));
a6e9f9df
AM
8354 if (!econf64)
8355 return 0;
252b5132
RH
8356
8357 for (cnt = 0; cnt < conflictsno; ++cnt)
8358 iconf[cnt] = BYTE_GET (econf64[cnt]);
a6e9f9df
AM
8359
8360 free (econf64);
252b5132
RH
8361 }
8362
c7e7ca54
NC
8363 printf (_("\nSection '.conflict' contains %lu entries:\n"),
8364 (unsigned long) conflictsno);
252b5132
RH
8365 puts (_(" Num: Index Value Name"));
8366
8367 for (cnt = 0; cnt < conflictsno; ++cnt)
8368 {
b34976b6 8369 Elf_Internal_Sym *psym = & dynamic_symbols[iconf[cnt]];
252b5132 8370
b34976b6 8371 printf ("%5lu: %8lu ", (unsigned long) cnt, iconf[cnt]);
f7a99963 8372 print_vma (psym->st_value, FULL_HEX);
31104126 8373 putchar (' ');
d79b3d50
NC
8374 if (VALID_DYNAMIC_NAME (psym->st_name))
8375 print_symbol (25, GET_DYNAMIC_NAME (psym->st_name));
8376 else
8377 printf ("<corrupt: %14ld>", psym->st_name);
31104126 8378 putchar ('\n');
252b5132
RH
8379 }
8380
252b5132
RH
8381 free (iconf);
8382 }
8383
8384 return 1;
8385}
8386
047b2264 8387static int
d3ba0551 8388process_gnu_liblist (FILE *file)
047b2264 8389{
b34976b6
AM
8390 Elf_Internal_Shdr *section, *string_sec;
8391 Elf32_External_Lib *elib;
8392 char *strtab;
c256ffe7 8393 size_t strtab_size;
047b2264
JJ
8394 size_t cnt;
8395 unsigned i;
8396
8397 if (! do_arch)
8398 return 0;
8399
8400 for (i = 0, section = section_headers;
8401 i < elf_header.e_shnum;
b34976b6 8402 i++, section++)
047b2264
JJ
8403 {
8404 switch (section->sh_type)
8405 {
8406 case SHT_GNU_LIBLIST:
c256ffe7
JJ
8407 if (SECTION_HEADER_INDEX (section->sh_link) >= elf_header.e_shnum)
8408 break;
8409
8410 elib = get_data (NULL, file, section->sh_offset, 1, section->sh_size,
d3ba0551 8411 _("liblist"));
047b2264
JJ
8412
8413 if (elib == NULL)
8414 break;
8415 string_sec = SECTION_HEADER (section->sh_link);
8416
c256ffe7 8417 strtab = get_data (NULL, file, string_sec->sh_offset, 1,
d3ba0551 8418 string_sec->sh_size, _("liblist string table"));
c256ffe7 8419 strtab_size = string_sec->sh_size;
047b2264
JJ
8420
8421 if (strtab == NULL
8422 || section->sh_entsize != sizeof (Elf32_External_Lib))
8423 {
8424 free (elib);
8425 break;
8426 }
8427
8428 printf (_("\nLibrary list section '%s' contains %lu entries:\n"),
8429 SECTION_NAME (section),
8430 (long) (section->sh_size / sizeof (Elf32_External_Lib)));
8431
8432 puts (" Library Time Stamp Checksum Version Flags");
8433
8434 for (cnt = 0; cnt < section->sh_size / sizeof (Elf32_External_Lib);
8435 ++cnt)
8436 {
8437 Elf32_Lib liblist;
8438 time_t time;
8439 char timebuf[20];
b34976b6 8440 struct tm *tmp;
047b2264
JJ
8441
8442 liblist.l_name = BYTE_GET (elib[cnt].l_name);
8443 time = BYTE_GET (elib[cnt].l_time_stamp);
8444 liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum);
8445 liblist.l_version = BYTE_GET (elib[cnt].l_version);
8446 liblist.l_flags = BYTE_GET (elib[cnt].l_flags);
8447
8448 tmp = gmtime (&time);
e9e44622
JJ
8449 snprintf (timebuf, sizeof (timebuf),
8450 "%04u-%02u-%02uT%02u:%02u:%02u",
8451 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
8452 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
047b2264
JJ
8453
8454 printf ("%3lu: ", (unsigned long) cnt);
8455 if (do_wide)
c256ffe7
JJ
8456 printf ("%-20s", liblist.l_name < strtab_size
8457 ? strtab + liblist.l_name : "<corrupt>");
047b2264 8458 else
c256ffe7
JJ
8459 printf ("%-20.20s", liblist.l_name < strtab_size
8460 ? strtab + liblist.l_name : "<corrupt>");
047b2264
JJ
8461 printf (" %s %#010lx %-7ld %-7ld\n", timebuf, liblist.l_checksum,
8462 liblist.l_version, liblist.l_flags);
8463 }
8464
8465 free (elib);
8466 }
8467 }
8468
8469 return 1;
8470}
8471
9437c45b 8472static const char *
d3ba0551 8473get_note_type (unsigned e_type)
779fe533
NC
8474{
8475 static char buff[64];
103f02d3 8476
1ec5cd37
NC
8477 if (elf_header.e_type == ET_CORE)
8478 switch (e_type)
8479 {
57346661 8480 case NT_AUXV:
1ec5cd37 8481 return _("NT_AUXV (auxiliary vector)");
57346661 8482 case NT_PRSTATUS:
1ec5cd37 8483 return _("NT_PRSTATUS (prstatus structure)");
57346661 8484 case NT_FPREGSET:
1ec5cd37 8485 return _("NT_FPREGSET (floating point registers)");
57346661 8486 case NT_PRPSINFO:
1ec5cd37 8487 return _("NT_PRPSINFO (prpsinfo structure)");
57346661 8488 case NT_TASKSTRUCT:
1ec5cd37 8489 return _("NT_TASKSTRUCT (task structure)");
57346661 8490 case NT_PRXFPREG:
1ec5cd37 8491 return _("NT_PRXFPREG (user_xfpregs structure)");
57346661 8492 case NT_PSTATUS:
1ec5cd37 8493 return _("NT_PSTATUS (pstatus structure)");
57346661 8494 case NT_FPREGS:
1ec5cd37 8495 return _("NT_FPREGS (floating point registers)");
57346661 8496 case NT_PSINFO:
1ec5cd37 8497 return _("NT_PSINFO (psinfo structure)");
57346661 8498 case NT_LWPSTATUS:
1ec5cd37 8499 return _("NT_LWPSTATUS (lwpstatus_t structure)");
57346661 8500 case NT_LWPSINFO:
1ec5cd37 8501 return _("NT_LWPSINFO (lwpsinfo_t structure)");
57346661 8502 case NT_WIN32PSTATUS:
1ec5cd37
NC
8503 return _("NT_WIN32PSTATUS (win32_pstatus structure)");
8504 default:
8505 break;
8506 }
8507 else
8508 switch (e_type)
8509 {
8510 case NT_VERSION:
8511 return _("NT_VERSION (version)");
8512 case NT_ARCH:
8513 return _("NT_ARCH (architecture)");
8514 default:
8515 break;
8516 }
8517
e9e44622 8518 snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
1ec5cd37 8519 return buff;
779fe533
NC
8520}
8521
9437c45b 8522static const char *
d3ba0551 8523get_netbsd_elfcore_note_type (unsigned e_type)
9437c45b
JT
8524{
8525 static char buff[64];
8526
b4db1224 8527 if (e_type == NT_NETBSDCORE_PROCINFO)
9437c45b
JT
8528 {
8529 /* NetBSD core "procinfo" structure. */
8530 return _("NetBSD procinfo structure");
8531 }
8532
8533 /* As of Jan 2002 there are no other machine-independent notes
8534 defined for NetBSD core files. If the note type is less
8535 than the start of the machine-dependent note types, we don't
8536 understand it. */
8537
b4db1224 8538 if (e_type < NT_NETBSDCORE_FIRSTMACH)
9437c45b 8539 {
e9e44622 8540 snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
9437c45b
JT
8541 return buff;
8542 }
8543
8544 switch (elf_header.e_machine)
8545 {
8546 /* On the Alpha, SPARC (32-bit and 64-bit), PT_GETREGS == mach+0
8547 and PT_GETFPREGS == mach+2. */
8548
8549 case EM_OLD_ALPHA:
8550 case EM_ALPHA:
8551 case EM_SPARC:
8552 case EM_SPARC32PLUS:
8553 case EM_SPARCV9:
8554 switch (e_type)
8555 {
b4db1224
JT
8556 case NT_NETBSDCORE_FIRSTMACH+0:
8557 return _("PT_GETREGS (reg structure)");
8558 case NT_NETBSDCORE_FIRSTMACH+2:
8559 return _("PT_GETFPREGS (fpreg structure)");
9437c45b
JT
8560 default:
8561 break;
8562 }
8563 break;
8564
8565 /* On all other arch's, PT_GETREGS == mach+1 and
8566 PT_GETFPREGS == mach+3. */
8567 default:
8568 switch (e_type)
8569 {
b4db1224
JT
8570 case NT_NETBSDCORE_FIRSTMACH+1:
8571 return _("PT_GETREGS (reg structure)");
8572 case NT_NETBSDCORE_FIRSTMACH+3:
8573 return _("PT_GETFPREGS (fpreg structure)");
9437c45b
JT
8574 default:
8575 break;
8576 }
8577 }
8578
e9e44622
JJ
8579 snprintf (buff, sizeof (buff), _("PT_FIRSTMACH+%d"),
8580 e_type - NT_NETBSDCORE_FIRSTMACH);
9437c45b
JT
8581 return buff;
8582}
8583
6d118b09
NC
8584/* Note that by the ELF standard, the name field is already null byte
8585 terminated, and namesz includes the terminating null byte.
8586 I.E. the value of namesz for the name "FSF" is 4.
8587
e3c8793a 8588 If the value of namesz is zero, there is no name present. */
779fe533 8589static int
d3ba0551 8590process_note (Elf_Internal_Note *pnote)
779fe533 8591{
9437c45b
JT
8592 const char *nt;
8593
8594 if (pnote->namesz == 0)
1ec5cd37
NC
8595 /* If there is no note name, then use the default set of
8596 note type strings. */
8597 nt = get_note_type (pnote->type);
8598
18bd398b 8599 else if (strneq (pnote->namedata, "NetBSD-CORE", 11))
1ec5cd37
NC
8600 /* NetBSD-specific core file notes. */
8601 nt = get_netbsd_elfcore_note_type (pnote->type);
8602
9437c45b 8603 else
1ec5cd37
NC
8604 /* Don't recognize this note name; just use the default set of
8605 note type strings. */
9437c45b 8606 nt = get_note_type (pnote->type);
9437c45b 8607
103f02d3 8608 printf (" %s\t\t0x%08lx\t%s\n",
6d118b09 8609 pnote->namesz ? pnote->namedata : "(NONE)",
9437c45b 8610 pnote->descsz, nt);
779fe533
NC
8611 return 1;
8612}
8613
6d118b09 8614
779fe533 8615static int
d3ba0551 8616process_corefile_note_segment (FILE *file, bfd_vma offset, bfd_vma length)
779fe533 8617{
b34976b6
AM
8618 Elf_External_Note *pnotes;
8619 Elf_External_Note *external;
8620 int res = 1;
103f02d3 8621
779fe533
NC
8622 if (length <= 0)
8623 return 0;
103f02d3 8624
c256ffe7 8625 pnotes = get_data (NULL, file, offset, 1, length, _("notes"));
a6e9f9df
AM
8626 if (!pnotes)
8627 return 0;
779fe533 8628
103f02d3 8629 external = pnotes;
103f02d3 8630
305c7206 8631 printf (_("\nNotes at offset 0x%08lx with length 0x%08lx:\n"),
f3485b74 8632 (unsigned long) offset, (unsigned long) length);
779fe533 8633 printf (_(" Owner\t\tData size\tDescription\n"));
103f02d3 8634
6d118b09 8635 while (external < (Elf_External_Note *)((char *) pnotes + length))
779fe533 8636 {
b34976b6
AM
8637 Elf_External_Note *next;
8638 Elf_Internal_Note inote;
8639 char *temp = NULL;
6d118b09
NC
8640
8641 inote.type = BYTE_GET (external->type);
8642 inote.namesz = BYTE_GET (external->namesz);
8643 inote.namedata = external->name;
8644 inote.descsz = BYTE_GET (external->descsz);
8645 inote.descdata = inote.namedata + align_power (inote.namesz, 2);
8646 inote.descpos = offset + (inote.descdata - (char *) pnotes);
76da6bbe 8647
3e55a963
NC
8648 next = (Elf_External_Note *)(inote.descdata + align_power (inote.descsz, 2));
8649
8650 if (((char *) next) > (((char *) pnotes) + length))
8651 {
0fd3a477
JW
8652 warn (_("corrupt note found at offset %lx into core notes\n"),
8653 (long)((char *)external - (char *)pnotes));
8654 warn (_(" type: %lx, namesize: %08lx, descsize: %08lx\n"),
3e55a963
NC
8655 inote.type, inote.namesz, inote.descsz);
8656 break;
8657 }
8658
8659 external = next;
6d118b09
NC
8660
8661 /* Verify that name is null terminated. It appears that at least
8662 one version of Linux (RedHat 6.0) generates corefiles that don't
8663 comply with the ELF spec by failing to include the null byte in
8664 namesz. */
8665 if (inote.namedata[inote.namesz] != '\0')
8666 {
8667 temp = malloc (inote.namesz + 1);
76da6bbe 8668
6d118b09
NC
8669 if (temp == NULL)
8670 {
8671 error (_("Out of memory\n"));
8672 res = 0;
8673 break;
8674 }
76da6bbe 8675
6d118b09
NC
8676 strncpy (temp, inote.namedata, inote.namesz);
8677 temp[inote.namesz] = 0;
76da6bbe 8678
6d118b09
NC
8679 /* warn (_("'%s' NOTE name not properly null terminated\n"), temp); */
8680 inote.namedata = temp;
8681 }
8682
8683 res &= process_note (& inote);
103f02d3 8684
6d118b09
NC
8685 if (temp != NULL)
8686 {
8687 free (temp);
8688 temp = NULL;
8689 }
779fe533
NC
8690 }
8691
8692 free (pnotes);
103f02d3 8693
779fe533
NC
8694 return res;
8695}
8696
8697static int
d3ba0551 8698process_corefile_note_segments (FILE *file)
779fe533 8699{
b34976b6
AM
8700 Elf_Internal_Phdr *segment;
8701 unsigned int i;
8702 int res = 1;
103f02d3 8703
d93f0186 8704 if (! get_program_headers (file))
779fe533 8705 return 0;
103f02d3 8706
779fe533
NC
8707 for (i = 0, segment = program_headers;
8708 i < elf_header.e_phnum;
b34976b6 8709 i++, segment++)
779fe533
NC
8710 {
8711 if (segment->p_type == PT_NOTE)
103f02d3 8712 res &= process_corefile_note_segment (file,
30800947
NC
8713 (bfd_vma) segment->p_offset,
8714 (bfd_vma) segment->p_filesz);
779fe533 8715 }
103f02d3 8716
779fe533
NC
8717 return res;
8718}
8719
8720static int
1ec5cd37
NC
8721process_note_sections (FILE *file)
8722{
8723 Elf_Internal_Shdr *section;
8724 unsigned long i;
8725 int res = 1;
8726
8727 for (i = 0, section = section_headers;
8728 i < elf_header.e_shnum;
8729 i++, section++)
8730 if (section->sh_type == SHT_NOTE)
8731 res &= process_corefile_note_segment (file,
8732 (bfd_vma) section->sh_offset,
8733 (bfd_vma) section->sh_size);
8734
8735 return res;
8736}
8737
8738static int
8739process_notes (FILE *file)
779fe533
NC
8740{
8741 /* If we have not been asked to display the notes then do nothing. */
8742 if (! do_notes)
8743 return 1;
103f02d3 8744
779fe533 8745 if (elf_header.e_type != ET_CORE)
1ec5cd37 8746 return process_note_sections (file);
103f02d3 8747
779fe533 8748 /* No program headers means no NOTE segment. */
1ec5cd37
NC
8749 if (elf_header.e_phnum > 0)
8750 return process_corefile_note_segments (file);
779fe533 8751
1ec5cd37
NC
8752 printf (_("No note segments present in the core file.\n"));
8753 return 1;
779fe533
NC
8754}
8755
252b5132 8756static int
d3ba0551 8757process_arch_specific (FILE *file)
252b5132 8758{
a952a375
NC
8759 if (! do_arch)
8760 return 1;
8761
252b5132
RH
8762 switch (elf_header.e_machine)
8763 {
11c1ff18
PB
8764 case EM_ARM:
8765 return process_arm_specific (file);
252b5132 8766 case EM_MIPS:
4fe85591 8767 case EM_MIPS_RS3_LE:
252b5132
RH
8768 return process_mips_specific (file);
8769 break;
8770 default:
8771 break;
8772 }
8773 return 1;
8774}
8775
8776static int
d3ba0551 8777get_file_header (FILE *file)
252b5132 8778{
9ea033b2
NC
8779 /* Read in the identity array. */
8780 if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1)
252b5132
RH
8781 return 0;
8782
9ea033b2 8783 /* Determine how to read the rest of the header. */
b34976b6 8784 switch (elf_header.e_ident[EI_DATA])
9ea033b2
NC
8785 {
8786 default: /* fall through */
8787 case ELFDATANONE: /* fall through */
adab8cdc
AO
8788 case ELFDATA2LSB:
8789 byte_get = byte_get_little_endian;
8790 byte_put = byte_put_little_endian;
8791 break;
8792 case ELFDATA2MSB:
8793 byte_get = byte_get_big_endian;
8794 byte_put = byte_put_big_endian;
8795 break;
9ea033b2
NC
8796 }
8797
8798 /* For now we only support 32 bit and 64 bit ELF files. */
b34976b6 8799 is_32bit_elf = (elf_header.e_ident[EI_CLASS] != ELFCLASS64);
9ea033b2
NC
8800
8801 /* Read in the rest of the header. */
8802 if (is_32bit_elf)
8803 {
8804 Elf32_External_Ehdr ehdr32;
252b5132 8805
9ea033b2
NC
8806 if (fread (ehdr32.e_type, sizeof (ehdr32) - EI_NIDENT, 1, file) != 1)
8807 return 0;
103f02d3 8808
9ea033b2
NC
8809 elf_header.e_type = BYTE_GET (ehdr32.e_type);
8810 elf_header.e_machine = BYTE_GET (ehdr32.e_machine);
8811 elf_header.e_version = BYTE_GET (ehdr32.e_version);
8812 elf_header.e_entry = BYTE_GET (ehdr32.e_entry);
8813 elf_header.e_phoff = BYTE_GET (ehdr32.e_phoff);
8814 elf_header.e_shoff = BYTE_GET (ehdr32.e_shoff);
8815 elf_header.e_flags = BYTE_GET (ehdr32.e_flags);
8816 elf_header.e_ehsize = BYTE_GET (ehdr32.e_ehsize);
8817 elf_header.e_phentsize = BYTE_GET (ehdr32.e_phentsize);
8818 elf_header.e_phnum = BYTE_GET (ehdr32.e_phnum);
8819 elf_header.e_shentsize = BYTE_GET (ehdr32.e_shentsize);
8820 elf_header.e_shnum = BYTE_GET (ehdr32.e_shnum);
8821 elf_header.e_shstrndx = BYTE_GET (ehdr32.e_shstrndx);
8822 }
252b5132 8823 else
9ea033b2
NC
8824 {
8825 Elf64_External_Ehdr ehdr64;
a952a375
NC
8826
8827 /* If we have been compiled with sizeof (bfd_vma) == 4, then
8828 we will not be able to cope with the 64bit data found in
8829 64 ELF files. Detect this now and abort before we start
50c2245b 8830 overwriting things. */
a952a375
NC
8831 if (sizeof (bfd_vma) < 8)
8832 {
e3c8793a
NC
8833 error (_("This instance of readelf has been built without support for a\n\
883464 bit data type and so it cannot read 64 bit ELF files.\n"));
a952a375
NC
8835 return 0;
8836 }
103f02d3 8837
9ea033b2
NC
8838 if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT, 1, file) != 1)
8839 return 0;
103f02d3 8840
9ea033b2
NC
8841 elf_header.e_type = BYTE_GET (ehdr64.e_type);
8842 elf_header.e_machine = BYTE_GET (ehdr64.e_machine);
8843 elf_header.e_version = BYTE_GET (ehdr64.e_version);
66543521
AM
8844 elf_header.e_entry = BYTE_GET (ehdr64.e_entry);
8845 elf_header.e_phoff = BYTE_GET (ehdr64.e_phoff);
8846 elf_header.e_shoff = BYTE_GET (ehdr64.e_shoff);
9ea033b2
NC
8847 elf_header.e_flags = BYTE_GET (ehdr64.e_flags);
8848 elf_header.e_ehsize = BYTE_GET (ehdr64.e_ehsize);
8849 elf_header.e_phentsize = BYTE_GET (ehdr64.e_phentsize);
8850 elf_header.e_phnum = BYTE_GET (ehdr64.e_phnum);
8851 elf_header.e_shentsize = BYTE_GET (ehdr64.e_shentsize);
8852 elf_header.e_shnum = BYTE_GET (ehdr64.e_shnum);
8853 elf_header.e_shstrndx = BYTE_GET (ehdr64.e_shstrndx);
8854 }
252b5132 8855
7ece0d85
JJ
8856 if (elf_header.e_shoff)
8857 {
8858 /* There may be some extensions in the first section header. Don't
8859 bomb if we can't read it. */
8860 if (is_32bit_elf)
8861 get_32bit_section_headers (file, 1);
8862 else
8863 get_64bit_section_headers (file, 1);
8864 }
560f3c1c 8865
1007acb3
L
8866 is_relocatable = elf_header.e_type == ET_REL;
8867
252b5132
RH
8868 return 1;
8869}
8870
fb52b2f4
NC
8871/* Process one ELF object file according to the command line options.
8872 This file may actually be stored in an archive. The file is
8873 positioned at the start of the ELF object. */
8874
ff78d6d6 8875static int
fb52b2f4 8876process_object (char *file_name, FILE *file)
252b5132 8877{
252b5132
RH
8878 unsigned int i;
8879
252b5132
RH
8880 if (! get_file_header (file))
8881 {
8882 error (_("%s: Failed to read file header\n"), file_name);
ff78d6d6 8883 return 1;
252b5132
RH
8884 }
8885
8886 /* Initialise per file variables. */
8887 for (i = NUM_ELEM (version_info); i--;)
8888 version_info[i] = 0;
8889
8890 for (i = NUM_ELEM (dynamic_info); i--;)
8891 dynamic_info[i] = 0;
8892
8893 /* Process the file. */
8894 if (show_name)
8895 printf (_("\nFile: %s\n"), file_name);
8896
18bd398b
NC
8897 /* Initialise the dump_sects array from the cmdline_dump_sects array.
8898 Note we do this even if cmdline_dump_sects is empty because we
8899 must make sure that the dump_sets array is zeroed out before each
8900 object file is processed. */
8901 if (num_dump_sects > num_cmdline_dump_sects)
8902 memset (dump_sects, 0, num_dump_sects);
8903
8904 if (num_cmdline_dump_sects > 0)
8905 {
8906 if (num_dump_sects == 0)
8907 /* A sneaky way of allocating the dump_sects array. */
8908 request_dump (num_cmdline_dump_sects, 0);
8909
8910 assert (num_dump_sects >= num_cmdline_dump_sects);
8911 memcpy (dump_sects, cmdline_dump_sects, num_cmdline_dump_sects);
8912 }
8913
252b5132 8914 if (! process_file_header ())
fb52b2f4 8915 return 1;
252b5132 8916
d1f5c6e3 8917 if (! process_section_headers (file))
2f62977e 8918 {
d1f5c6e3
L
8919 /* Without loaded section headers we cannot process lots of
8920 things. */
2f62977e 8921 do_unwind = do_version = do_dump = do_arch = 0;
252b5132 8922
2f62977e
NC
8923 if (! do_using_dynamic)
8924 do_syms = do_reloc = 0;
8925 }
252b5132 8926
d1f5c6e3
L
8927 if (! process_section_groups (file))
8928 {
8929 /* Without loaded section groups we cannot process unwind. */
8930 do_unwind = 0;
8931 }
8932
2f62977e 8933 if (process_program_headers (file))
b2d38a17 8934 process_dynamic_section (file);
252b5132
RH
8935
8936 process_relocs (file);
8937
4d6ed7c8
NC
8938 process_unwind (file);
8939
252b5132
RH
8940 process_symbol_table (file);
8941
8942 process_syminfo (file);
8943
8944 process_version_sections (file);
8945
8946 process_section_contents (file);
f5842774 8947
1ec5cd37 8948 process_notes (file);
103f02d3 8949
047b2264
JJ
8950 process_gnu_liblist (file);
8951
252b5132
RH
8952 process_arch_specific (file);
8953
d93f0186
NC
8954 if (program_headers)
8955 {
8956 free (program_headers);
8957 program_headers = NULL;
8958 }
8959
252b5132
RH
8960 if (section_headers)
8961 {
8962 free (section_headers);
8963 section_headers = NULL;
8964 }
8965
8966 if (string_table)
8967 {
8968 free (string_table);
8969 string_table = NULL;
d40ac9bd 8970 string_table_length = 0;
252b5132
RH
8971 }
8972
8973 if (dynamic_strings)
8974 {
8975 free (dynamic_strings);
8976 dynamic_strings = NULL;
d79b3d50 8977 dynamic_strings_length = 0;
252b5132
RH
8978 }
8979
8980 if (dynamic_symbols)
8981 {
8982 free (dynamic_symbols);
8983 dynamic_symbols = NULL;
19936277 8984 num_dynamic_syms = 0;
252b5132
RH
8985 }
8986
8987 if (dynamic_syminfo)
8988 {
8989 free (dynamic_syminfo);
8990 dynamic_syminfo = NULL;
8991 }
ff78d6d6 8992
e4b17d5c
L
8993 if (section_headers_groups)
8994 {
8995 free (section_headers_groups);
8996 section_headers_groups = NULL;
8997 }
8998
8999 if (section_groups)
9000 {
9001 struct group_list *g, *next;
9002
9003 for (i = 0; i < group_count; i++)
9004 {
9005 for (g = section_groups [i].root; g != NULL; g = next)
9006 {
9007 next = g->next;
9008 free (g);
9009 }
9010 }
9011
9012 free (section_groups);
9013 section_groups = NULL;
9014 }
9015
19e6b90e 9016 free_debug_memory ();
18bd398b 9017
ff78d6d6 9018 return 0;
252b5132
RH
9019}
9020
fb52b2f4
NC
9021/* Process an ELF archive. The file is positioned just after the
9022 ARMAG string. */
9023
9024static int
9025process_archive (char *file_name, FILE *file)
9026{
9027 struct ar_hdr arhdr;
9028 size_t got;
9029 unsigned long size;
9030 char *longnames = NULL;
9031 unsigned long longnames_size = 0;
9032 size_t file_name_size;
d989285c 9033 int ret;
fb52b2f4
NC
9034
9035 show_name = 1;
9036
9037 got = fread (&arhdr, 1, sizeof arhdr, file);
9038 if (got != sizeof arhdr)
9039 {
9040 if (got == 0)
9041 return 0;
9042
9043 error (_("%s: failed to read archive header\n"), file_name);
9044 return 1;
9045 }
9046
9047 if (memcmp (arhdr.ar_name, "/ ", 16) == 0)
9048 {
9049 /* This is the archive symbol table. Skip it.
9050 FIXME: We should have an option to dump it. */
9051 size = strtoul (arhdr.ar_size, NULL, 10);
9052 if (fseek (file, size + (size & 1), SEEK_CUR) != 0)
9053 {
9054 error (_("%s: failed to skip archive symbol table\n"), file_name);
9055 return 1;
9056 }
9057
9058 got = fread (&arhdr, 1, sizeof arhdr, file);
9059 if (got != sizeof arhdr)
9060 {
9061 if (got == 0)
9062 return 0;
9063
9064 error (_("%s: failed to read archive header\n"), file_name);
9065 return 1;
9066 }
9067 }
9068
9069 if (memcmp (arhdr.ar_name, "// ", 16) == 0)
9070 {
9071 /* This is the archive string table holding long member
9072 names. */
9073
9074 longnames_size = strtoul (arhdr.ar_size, NULL, 10);
9075
9076 longnames = malloc (longnames_size);
9077 if (longnames == NULL)
9078 {
9079 error (_("Out of memory\n"));
9080 return 1;
9081 }
9082
9083 if (fread (longnames, longnames_size, 1, file) != 1)
9084 {
d989285c 9085 free (longnames);
18bd398b 9086 error (_("%s: failed to read string table\n"), file_name);
fb52b2f4
NC
9087 return 1;
9088 }
9089
9090 if ((longnames_size & 1) != 0)
9091 getc (file);
9092
9093 got = fread (&arhdr, 1, sizeof arhdr, file);
9094 if (got != sizeof arhdr)
9095 {
d989285c
ILT
9096 free (longnames);
9097
fb52b2f4
NC
9098 if (got == 0)
9099 return 0;
9100
9101 error (_("%s: failed to read archive header\n"), file_name);
9102 return 1;
9103 }
9104 }
9105
9106 file_name_size = strlen (file_name);
d989285c 9107 ret = 0;
fb52b2f4
NC
9108
9109 while (1)
9110 {
9111 char *name;
9112 char *nameend;
9113 char *namealc;
9114
9115 if (arhdr.ar_name[0] == '/')
9116 {
9117 unsigned long off;
9118
9119 off = strtoul (arhdr.ar_name + 1, NULL, 10);
9120 if (off >= longnames_size)
9121 {
0fd3a477 9122 error (_("%s: invalid archive string table offset %lu\n"), file_name, off);
d989285c
ILT
9123 ret = 1;
9124 break;
fb52b2f4
NC
9125 }
9126
9127 name = longnames + off;
9128 nameend = memchr (name, '/', longnames_size - off);
9129 }
9130 else
9131 {
9132 name = arhdr.ar_name;
9133 nameend = memchr (name, '/', 16);
9134 }
9135
9136 if (nameend == NULL)
9137 {
0fd3a477 9138 error (_("%s: bad archive file name\n"), file_name);
d989285c
ILT
9139 ret = 1;
9140 break;
fb52b2f4
NC
9141 }
9142
9143 namealc = malloc (file_name_size + (nameend - name) + 3);
9144 if (namealc == NULL)
9145 {
9146 error (_("Out of memory\n"));
d989285c
ILT
9147 ret = 1;
9148 break;
fb52b2f4
NC
9149 }
9150
9151 memcpy (namealc, file_name, file_name_size);
9152 namealc[file_name_size] = '(';
9153 memcpy (namealc + file_name_size + 1, name, nameend - name);
9154 namealc[file_name_size + 1 + (nameend - name)] = ')';
9155 namealc[file_name_size + 2 + (nameend - name)] = '\0';
9156
9157 archive_file_offset = ftell (file);
9158 archive_file_size = strtoul (arhdr.ar_size, NULL, 10);
18bd398b 9159
d989285c 9160 ret |= process_object (namealc, file);
fb52b2f4
NC
9161
9162 free (namealc);
9163
9164 if (fseek (file,
9165 (archive_file_offset
9166 + archive_file_size
9167 + (archive_file_size & 1)),
9168 SEEK_SET) != 0)
9169 {
9170 error (_("%s: failed to seek to next archive header\n"), file_name);
d989285c
ILT
9171 ret = 1;
9172 break;
fb52b2f4
NC
9173 }
9174
9175 got = fread (&arhdr, 1, sizeof arhdr, file);
9176 if (got != sizeof arhdr)
9177 {
9178 if (got == 0)
d989285c 9179 break;
fb52b2f4
NC
9180
9181 error (_("%s: failed to read archive header\n"), file_name);
d989285c
ILT
9182 ret = 1;
9183 break;
fb52b2f4
NC
9184 }
9185 }
9186
9187 if (longnames != 0)
9188 free (longnames);
9189
d989285c 9190 return ret;
fb52b2f4
NC
9191}
9192
9193static int
9194process_file (char *file_name)
9195{
9196 FILE *file;
9197 struct stat statbuf;
9198 char armag[SARMAG];
9199 int ret;
9200
9201 if (stat (file_name, &statbuf) < 0)
9202 {
f24ddbdd
NC
9203 if (errno == ENOENT)
9204 error (_("'%s': No such file\n"), file_name);
9205 else
9206 error (_("Could not locate '%s'. System error message: %s\n"),
9207 file_name, strerror (errno));
9208 return 1;
9209 }
9210
9211 if (! S_ISREG (statbuf.st_mode))
9212 {
9213 error (_("'%s' is not an ordinary file\n"), file_name);
fb52b2f4
NC
9214 return 1;
9215 }
9216
9217 file = fopen (file_name, "rb");
9218 if (file == NULL)
9219 {
f24ddbdd 9220 error (_("Input file '%s' is not readable.\n"), file_name);
fb52b2f4
NC
9221 return 1;
9222 }
9223
9224 if (fread (armag, SARMAG, 1, file) != 1)
9225 {
9226 error (_("%s: Failed to read file header\n"), file_name);
9227 fclose (file);
9228 return 1;
9229 }
9230
9231 if (memcmp (armag, ARMAG, SARMAG) == 0)
9232 ret = process_archive (file_name, file);
9233 else
9234 {
9235 rewind (file);
9236 archive_file_size = archive_file_offset = 0;
9237 ret = process_object (file_name, file);
9238 }
9239
9240 fclose (file);
9241
9242 return ret;
9243}
9244
252b5132
RH
9245#ifdef SUPPORT_DISASSEMBLY
9246/* Needed by the i386 disassembler. For extra credit, someone could
9ea033b2 9247 fix this so that we insert symbolic addresses here, esp for GOT/PLT
e3c8793a 9248 symbols. */
252b5132
RH
9249
9250void
b34976b6 9251print_address (unsigned int addr, FILE *outfile)
252b5132
RH
9252{
9253 fprintf (outfile,"0x%8.8x", addr);
9254}
9255
e3c8793a 9256/* Needed by the i386 disassembler. */
252b5132
RH
9257void
9258db_task_printsym (unsigned int addr)
9259{
9260 print_address (addr, stderr);
9261}
9262#endif
9263
9264int
d3ba0551 9265main (int argc, char **argv)
252b5132 9266{
ff78d6d6
L
9267 int err;
9268
252b5132
RH
9269#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
9270 setlocale (LC_MESSAGES, "");
3882b010
L
9271#endif
9272#if defined (HAVE_SETLOCALE)
9273 setlocale (LC_CTYPE, "");
252b5132
RH
9274#endif
9275 bindtextdomain (PACKAGE, LOCALEDIR);
9276 textdomain (PACKAGE);
9277
869b9d07
MM
9278 expandargv (&argc, &argv);
9279
252b5132
RH
9280 parse_args (argc, argv);
9281
18bd398b 9282 if (num_dump_sects > 0)
59f14fc0 9283 {
18bd398b 9284 /* Make a copy of the dump_sects array. */
59f14fc0
AS
9285 cmdline_dump_sects = malloc (num_dump_sects);
9286 if (cmdline_dump_sects == NULL)
9287 error (_("Out of memory allocating dump request table."));
9288 else
9289 {
9290 memcpy (cmdline_dump_sects, dump_sects, num_dump_sects);
9291 num_cmdline_dump_sects = num_dump_sects;
9292 }
9293 }
9294
18bd398b
NC
9295 if (optind < (argc - 1))
9296 show_name = 1;
9297
ff78d6d6 9298 err = 0;
252b5132 9299 while (optind < argc)
18bd398b 9300 err |= process_file (argv[optind++]);
252b5132
RH
9301
9302 if (dump_sects != NULL)
9303 free (dump_sects);
59f14fc0
AS
9304 if (cmdline_dump_sects != NULL)
9305 free (cmdline_dump_sects);
252b5132 9306
ff78d6d6 9307 return err;
252b5132 9308}