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