readelf.c revision 78828
160484Sobrien/* readelf.c -- display contents of an ELF format file
278828Sobrien   Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
360484Sobrien
460484Sobrien   Originally developed by Eric Youngdale <eric@andante.jic.com>
560484Sobrien   Modifications by Nick Clifton <nickc@cygnus.com>
660484Sobrien
760484Sobrien   This file is part of GNU Binutils.
860484Sobrien
960484Sobrien   This program is free software; you can redistribute it and/or modify
1060484Sobrien   it under the terms of the GNU General Public License as published by
1160484Sobrien   the Free Software Foundation; either version 2 of the License, or
1260484Sobrien   (at your option) any later version.
1360484Sobrien
1460484Sobrien   This program is distributed in the hope that it will be useful,
1560484Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1660484Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1760484Sobrien   GNU General Public License for more details.
1860484Sobrien
1960484Sobrien   You should have received a copy of the GNU General Public License
2060484Sobrien   along with this program; if not, write to the Free Software
2160484Sobrien   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
2260484Sobrien   02111-1307, USA.  */
2360484Sobrien
2460484Sobrien
2560484Sobrien#include <assert.h>
2660484Sobrien#include <sys/types.h>
2760484Sobrien#include <sys/stat.h>
2860484Sobrien#include <stdio.h>
2960484Sobrien#include <time.h>
3060484Sobrien
3160484Sobrien#if __GNUC__ >= 2
3260484Sobrien/* Define BFD64 here, even if our default architecture is 32 bit ELF
3360484Sobrien   as this will allow us to read in and parse 64bit and 32bit ELF files.
3460484Sobrien   Only do this if we belive that the compiler can support a 64 bit
3560484Sobrien   data type.  For now we only rely on GCC being able to do this.  */
3660484Sobrien#define BFD64
3760484Sobrien#endif
3860484Sobrien
3960484Sobrien#include "bfd.h"
4060484Sobrien
4160484Sobrien#include "elf/common.h"
4260484Sobrien#include "elf/external.h"
4360484Sobrien#include "elf/internal.h"
4460484Sobrien#include "elf/dwarf2.h"
4560484Sobrien
4660484Sobrien/* The following headers use the elf/reloc-macros.h file to
4760484Sobrien   automatically generate relocation recognition functions
4860484Sobrien   such as elf_mips_reloc_type()  */
4960484Sobrien
5060484Sobrien#define RELOC_MACROS_GEN_FUNC
5160484Sobrien
5260484Sobrien#include "elf/i386.h"
5360484Sobrien#include "elf/v850.h"
5460484Sobrien#include "elf/ppc.h"
5560484Sobrien#include "elf/mips.h"
5660484Sobrien#include "elf/alpha.h"
5760484Sobrien#include "elf/arm.h"
5860484Sobrien#include "elf/m68k.h"
5960484Sobrien#include "elf/sparc.h"
6060484Sobrien#include "elf/m32r.h"
6160484Sobrien#include "elf/d10v.h"
6260484Sobrien#include "elf/d30v.h"
6360484Sobrien#include "elf/sh.h"
6460484Sobrien#include "elf/mn10200.h"
6560484Sobrien#include "elf/mn10300.h"
6660484Sobrien#include "elf/hppa.h"
6760484Sobrien#include "elf/arc.h"
6860484Sobrien#include "elf/fr30.h"
6960484Sobrien#include "elf/mcore.h"
7060484Sobrien#include "elf/i960.h"
7160484Sobrien#include "elf/pj.h"
7260484Sobrien#include "elf/avr.h"
7377298Sobrien#include "elf/ia64.h"
7477298Sobrien#include "elf/cris.h"
7577298Sobrien#include "elf/i860.h"
7677298Sobrien#include "elf/x86-64.h"
7760484Sobrien
7860484Sobrien#include "bucomm.h"
7960484Sobrien#include "getopt.h"
8060484Sobrien
8178828Sobrienchar *	program_name = "readelf";
8278828Sobrienunsigned int	dynamic_addr;
8378828Sobrienbfd_size_type		dynamic_size;
8478828Sobrienunsigned int	rela_addr;
8578828Sobrienunsigned int	rela_size;
8678828Sobrienchar *	dynamic_strings;
8760484Sobrienchar *			string_table;
8877298Sobrienunsigned long		string_table_length;
8960484Sobrienunsigned long           num_dynamic_syms;
9078828SobrienElf_Internal_Sym *	dynamic_symbols;
9160484SobrienElf_Internal_Syminfo *	dynamic_syminfo;
9278828Sobrienunsigned long	dynamic_syminfo_offset;
9360484Sobrienunsigned int		dynamic_syminfo_nent;
9478828Sobrienchar	program_interpreter [64];
9578828Sobrienint	dynamic_info[DT_JMPREL + 1];
9678828Sobrienint	version_info[16];
9778828Sobrienint	loadaddr = 0;
9860484SobrienElf_Internal_Ehdr       elf_header;
9960484SobrienElf_Internal_Shdr *     section_headers;
10060484SobrienElf_Internal_Dyn *      dynamic_segment;
10178828Sobrienint			show_name;
10278828Sobrienint			do_dynamic;
10378828Sobrienint			do_syms;
10478828Sobrienint			do_reloc;
10578828Sobrienint			do_sections;
10678828Sobrienint			do_segments;
10778828Sobrienint			do_unwind;
10878828Sobrienint			do_using_dynamic;
10978828Sobrienint			do_header;
11078828Sobrienint			do_dump;
11178828Sobrienint			do_version;
11260484Sobrienint			do_histogram;
11360484Sobrienint			do_debugging;
11460484Sobrienint                     do_debug_info;
11560484Sobrienint                     do_debug_abbrevs;
11660484Sobrienint                     do_debug_lines;
11760484Sobrienint                     do_debug_pubnames;
11860484Sobrienint                     do_debug_aranges;
11977298Sobrienint                     do_debug_frames;
12078828Sobrienint                     do_debug_frames_interp;
12160484Sobrienint                     do_arch;
12260484Sobrienint                     do_notes;
12360484Sobrienint			is_32bit_elf;
12460484Sobrien
12560484Sobrien/* A dynamic array of flags indicating which sections require dumping.  */
12660484Sobrienchar *			dump_sects = NULL;
12760484Sobrienunsigned int		num_dump_sects = 0;
12860484Sobrien
12960484Sobrien#define HEX_DUMP	(1 << 0)
13060484Sobrien#define DISASS_DUMP	(1 << 1)
13160484Sobrien#define DEBUG_DUMP	(1 << 2)
13260484Sobrien
13360484Sobrien/* How to rpint a vma value.  */
13460484Sobrientypedef enum print_mode
13560484Sobrien{
13660484Sobrien  HEX,
13760484Sobrien  DEC,
13860484Sobrien  DEC_5,
13960484Sobrien  UNSIGNED,
14060484Sobrien  PREFIX_HEX,
14160484Sobrien  FULL_HEX,
14260484Sobrien  LONG_HEX
14360484Sobrien}
14460484Sobrienprint_mode;
14560484Sobrien
14660484Sobrien/* Forward declarations for dumb compilers.  */
14760484Sobrienstatic void		  print_vma		      PARAMS ((bfd_vma, print_mode));
14860484Sobrienstatic bfd_vma (*         byte_get)                   PARAMS ((unsigned char *, int));
14960484Sobrienstatic bfd_vma            byte_get_little_endian      PARAMS ((unsigned char *, int));
15060484Sobrienstatic bfd_vma            byte_get_big_endian         PARAMS ((unsigned char *, int));
15160484Sobrienstatic const char *       get_mips_dynamic_type       PARAMS ((unsigned long));
15260484Sobrienstatic const char *       get_sparc64_dynamic_type    PARAMS ((unsigned long));
15360484Sobrienstatic const char *       get_parisc_dynamic_type     PARAMS ((unsigned long));
15460484Sobrienstatic const char *       get_dynamic_type            PARAMS ((unsigned long));
15578828Sobrienstatic int		  slurp_rela_relocs	      PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rela **, unsigned long *));
15678828Sobrienstatic int		  slurp_rel_relocs	      PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rel **, unsigned long *));
15760484Sobrienstatic int                dump_relocations            PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, unsigned long, char *, int));
15860484Sobrienstatic char *             get_file_type               PARAMS ((unsigned));
15960484Sobrienstatic char *             get_machine_name            PARAMS ((unsigned));
16077298Sobrienstatic void		  decode_ARM_machine_flags    PARAMS ((unsigned, char []));
16160484Sobrienstatic char *             get_machine_flags           PARAMS ((unsigned, unsigned));
16260484Sobrienstatic const char *       get_mips_segment_type       PARAMS ((unsigned long));
16360484Sobrienstatic const char *       get_parisc_segment_type     PARAMS ((unsigned long));
16478828Sobrienstatic const char *       get_ia64_segment_type       PARAMS ((unsigned long));
16560484Sobrienstatic const char *       get_segment_type            PARAMS ((unsigned long));
16660484Sobrienstatic const char *       get_mips_section_type_name  PARAMS ((unsigned int));
16760484Sobrienstatic const char *       get_parisc_section_type_name PARAMS ((unsigned int));
16878828Sobrienstatic const char *       get_ia64_section_type_name  PARAMS ((unsigned int));
16960484Sobrienstatic const char *       get_section_type_name       PARAMS ((unsigned int));
17060484Sobrienstatic const char *       get_symbol_binding          PARAMS ((unsigned int));
17160484Sobrienstatic const char *       get_symbol_type             PARAMS ((unsigned int));
17260484Sobrienstatic const char *       get_symbol_visibility       PARAMS ((unsigned int));
17360484Sobrienstatic const char *       get_symbol_index_type       PARAMS ((unsigned int));
17478828Sobrienstatic const char *       get_dynamic_flags	      PARAMS ((bfd_vma));
17560484Sobrienstatic void               usage                       PARAMS ((void));
17660484Sobrienstatic void               parse_args                  PARAMS ((int, char **));
17760484Sobrienstatic int                process_file_header         PARAMS ((void));
17860484Sobrienstatic int                process_program_headers     PARAMS ((FILE *));
17960484Sobrienstatic int                process_section_headers     PARAMS ((FILE *));
18078828Sobrienstatic int		  process_unwind	      PARAMS ((FILE *));
18160484Sobrienstatic void               dynamic_segment_mips_val    PARAMS ((Elf_Internal_Dyn *));
18260484Sobrienstatic void               dynamic_segment_parisc_val  PARAMS ((Elf_Internal_Dyn *));
18360484Sobrienstatic int                process_dynamic_segment     PARAMS ((FILE *));
18460484Sobrienstatic int                process_symbol_table        PARAMS ((FILE *));
18560484Sobrienstatic int                process_section_contents    PARAMS ((FILE *));
18660484Sobrienstatic void               process_file                PARAMS ((char *));
18760484Sobrienstatic int                process_relocs              PARAMS ((FILE *));
18860484Sobrienstatic int                process_version_sections    PARAMS ((FILE *));
18960484Sobrienstatic char *             get_ver_flags               PARAMS ((unsigned int));
19060484Sobrienstatic int                get_32bit_section_headers   PARAMS ((FILE *));
19160484Sobrienstatic int                get_64bit_section_headers   PARAMS ((FILE *));
19260484Sobrienstatic int		  get_32bit_program_headers   PARAMS ((FILE *, Elf_Internal_Phdr *));
19360484Sobrienstatic int		  get_64bit_program_headers   PARAMS ((FILE *, Elf_Internal_Phdr *));
19460484Sobrienstatic int                get_file_header             PARAMS ((FILE *));
19560484Sobrienstatic Elf_Internal_Sym * get_32bit_elf_symbols       PARAMS ((FILE *, unsigned long, unsigned long));
19660484Sobrienstatic Elf_Internal_Sym * get_64bit_elf_symbols       PARAMS ((FILE *, unsigned long, unsigned long));
19778828Sobrienstatic const char *	  get_elf_section_flags	      PARAMS ((bfd_vma));
19860484Sobrienstatic int *              get_dynamic_data            PARAMS ((FILE *, unsigned int));
19960484Sobrienstatic int                get_32bit_dynamic_segment   PARAMS ((FILE *));
20060484Sobrienstatic int                get_64bit_dynamic_segment   PARAMS ((FILE *));
20160484Sobrien#ifdef SUPPORT_DISASSEMBLY
20278828Sobrienstatic int	          disassemble_section         PARAMS ((Elf32_Internal_Shdr *, FILE *));
20360484Sobrien#endif
20478828Sobrienstatic int	          dump_section                PARAMS ((Elf32_Internal_Shdr *, FILE *));
20578828Sobrienstatic int	          display_debug_section       PARAMS ((Elf32_Internal_Shdr *, FILE *));
20660484Sobrienstatic int                display_debug_info          PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
20760484Sobrienstatic int                display_debug_not_supported PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
20860484Sobrienstatic int                display_debug_lines         PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
20960484Sobrienstatic int                display_debug_abbrev        PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
21060484Sobrienstatic int                display_debug_aranges       PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
21177298Sobrienstatic int                display_debug_frames        PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
21260484Sobrienstatic unsigned char *    process_abbrev_section      PARAMS ((unsigned char *, unsigned char *));
21360484Sobrienstatic unsigned long      read_leb128                 PARAMS ((unsigned char *, int *, int));
21460484Sobrienstatic int                process_extended_line_op    PARAMS ((unsigned char *, int, int));
21560484Sobrienstatic void               reset_state_machine         PARAMS ((int));
21660484Sobrienstatic char *             get_TAG_name                PARAMS ((unsigned long));
21760484Sobrienstatic char *             get_AT_name                 PARAMS ((unsigned long));
21860484Sobrienstatic char *             get_FORM_name               PARAMS ((unsigned long));
21960484Sobrienstatic void               free_abbrevs                PARAMS ((void));
22060484Sobrienstatic void               add_abbrev                  PARAMS ((unsigned long, unsigned long, int));
22160484Sobrienstatic void               add_abbrev_attr             PARAMS ((unsigned long, unsigned long));
22277298Sobrienstatic unsigned char *    read_and_display_attr       PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long, unsigned long));
22360484Sobrienstatic unsigned char *    display_block               PARAMS ((unsigned char *, unsigned long));
22477298Sobrienstatic void               decode_location_expression  PARAMS ((unsigned char *, unsigned int, unsigned long));
22560484Sobrienstatic void		  request_dump                PARAMS ((unsigned int, char));
22660484Sobrienstatic const char *       get_elf_class               PARAMS ((unsigned char));
22760484Sobrienstatic const char *       get_data_encoding           PARAMS ((unsigned char));
22860484Sobrienstatic const char *       get_osabi_name              PARAMS ((unsigned char));
22960484Sobrienstatic int		  guess_is_rela               PARAMS ((unsigned long));
23078828Sobrienstatic char *		  get_note_type		         PARAMS ((unsigned int));
23160484Sobrienstatic int		  process_note		         PARAMS ((Elf32_Internal_Note *));
23260484Sobrienstatic int		  process_corefile_note_segment  PARAMS ((FILE *, bfd_vma, bfd_vma));
23360484Sobrienstatic int		  process_corefile_note_segments PARAMS ((FILE *));
23478828Sobrienstatic int		  process_corefile_contents	 PARAMS ((FILE *));
23560484Sobrien
23660484Sobrientypedef int Elf32_Word;
23760484Sobrien
23860484Sobrien#ifndef TRUE
23960484Sobrien#define TRUE     1
24060484Sobrien#define FALSE    0
24160484Sobrien#endif
24260484Sobrien#define UNKNOWN -1
24360484Sobrien
24478828Sobrien#define SECTION_NAME(X)	((X) == NULL ? "<none>" : \
24577298Sobrien				 ((X)->sh_name >= string_table_length \
24677298Sobrien				  ? "<corrupt>" : string_table + (X)->sh_name))
24760484Sobrien
24860484Sobrien#define DT_VERSIONTAGIDX(tag)	(DT_VERNEEDNUM - (tag))	/* Reverse order! */
24960484Sobrien
25078828Sobrien#define BYTE_GET(field)	byte_get (field, sizeof (field))
25160484Sobrien
25260484Sobrien/* If we can support a 64 bit data type then BFD64 should be defined
25360484Sobrien   and sizeof (bfd_vma) == 8.  In this case when translating from an
25460484Sobrien   external 8 byte field to an internal field, we can assume that the
25578828Sobrien   internal field is also 8 bytes wide and so we can extract all the data.
25660484Sobrien   If, however, BFD64 is not defined, then we must assume that the
25760484Sobrien   internal data structure only has 4 byte wide fields that are the
25860484Sobrien   equivalent of the 8 byte wide external counterparts, and so we must
25960484Sobrien   truncate the data.  */
26060484Sobrien#ifdef  BFD64
26178828Sobrien#define BYTE_GET8(field)	byte_get (field, -8)
26260484Sobrien#else
26378828Sobrien#define BYTE_GET8(field)	byte_get (field, 8)
26460484Sobrien#endif
26560484Sobrien
26678828Sobrien#define NUM_ELEM(array)	(sizeof (array) / sizeof ((array)[0]))
26760484Sobrien
26860484Sobrien#define GET_DATA_ALLOC(offset, size, var, type, reason)			\
26960484Sobrien  if (fseek (file, offset, SEEK_SET))					\
27060484Sobrien    {									\
27160484Sobrien      error (_("Unable to seek to start of %s at %x\n"), reason, offset); \
27260484Sobrien      return 0;								\
27360484Sobrien    }									\
27460484Sobrien									\
27560484Sobrien  var = (type) malloc (size);						\
27660484Sobrien									\
27760484Sobrien  if (var == NULL)							\
27860484Sobrien    {									\
27960484Sobrien      error (_("Out of memory allocating %d bytes for %s\n"), size, reason); \
28060484Sobrien      return 0;								\
28178828Sobrien    }									\
28278828Sobrien									\
28378828Sobrien  if (fread (var, size, 1, file) != 1)					\
28478828Sobrien    {									\
28578828Sobrien      error (_("Unable to read in %d bytes of %s\n"), size, reason);	\
28678828Sobrien      free (var);							\
28760484Sobrien      var = NULL;							\
28878828Sobrien      return 0;							\
28960484Sobrien    }
29060484Sobrien
29160484Sobrien
29278828Sobrien#define GET_DATA(offset, var, reason)					\
29360484Sobrien  if (fseek (file, offset, SEEK_SET))					\
29478828Sobrien    {									\
29560484Sobrien      error (_("Unable to seek to %x for %s\n"), offset, reason);	\
29660484Sobrien      return 0;								\
29760484Sobrien    }									\
29860484Sobrien  else if (fread (& var, sizeof (var), 1, file) != 1)			\
29960484Sobrien    {									\
30060484Sobrien      error (_("Unable to read data at %x for %s\n"), offset, reason);	\
30160484Sobrien      return 0;								\
30260484Sobrien    }
30360484Sobrien
30460484Sobrien#define GET_ELF_SYMBOLS(file, offset, size)			\
30560484Sobrien  (is_32bit_elf ? get_32bit_elf_symbols (file, offset, size)	\
30660484Sobrien   : get_64bit_elf_symbols (file, offset, size))
30760484Sobrien
30860484Sobrien
30960484Sobrien#ifdef ANSI_PROTOTYPES
31060484Sobrienstatic void
31160484Sobrienerror (const char * message, ...)
31260484Sobrien{
31360484Sobrien  va_list args;
31460484Sobrien
31560484Sobrien  fprintf (stderr, _("%s: Error: "), program_name);
31660484Sobrien  va_start (args, message);
31760484Sobrien  vfprintf (stderr, message, args);
31860484Sobrien  va_end (args);
31960484Sobrien  return;
32060484Sobrien}
32160484Sobrien
32260484Sobrienstatic void
32360484Sobrienwarn (const char * message, ...)
32460484Sobrien{
32560484Sobrien  va_list args;
32660484Sobrien
32760484Sobrien  fprintf (stderr, _("%s: Warning: "), program_name);
32860484Sobrien  va_start (args, message);
32960484Sobrien  vfprintf (stderr, message, args);
33060484Sobrien  va_end (args);
33160484Sobrien  return;
33260484Sobrien}
33360484Sobrien#else
33460484Sobrienstatic void
33560484Sobrienerror (va_alist)
33660484Sobrien     va_dcl
33760484Sobrien{
33860484Sobrien  char * message;
33960484Sobrien  va_list args;
34060484Sobrien
34160484Sobrien  fprintf (stderr, _("%s: Error: "), program_name);
34260484Sobrien  va_start (args);
34360484Sobrien  message = va_arg (args, char *);
34460484Sobrien  vfprintf (stderr, message, args);
34560484Sobrien  va_end (args);
34660484Sobrien  return;
34760484Sobrien}
34860484Sobrien
34960484Sobrienstatic void
35060484Sobrienwarn (va_alist)
35160484Sobrien     va_dcl
35260484Sobrien{
35360484Sobrien  char * message;
35460484Sobrien  va_list args;
35560484Sobrien
35660484Sobrien  fprintf (stderr, _("%s: Warning: "), program_name);
35760484Sobrien  va_start (args);
35860484Sobrien  message = va_arg (args, char *);
35960484Sobrien  vfprintf (stderr, message, args);
36060484Sobrien  va_end (args);
36160484Sobrien  return;
36260484Sobrien}
36360484Sobrien#endif
36460484Sobrien
36560484Sobrienstatic bfd_vma
36660484Sobrienbyte_get_little_endian (field, size)
36760484Sobrien     unsigned char * field;
36860484Sobrien     int             size;
36960484Sobrien{
37060484Sobrien  switch (size)
37160484Sobrien    {
37260484Sobrien    case 1:
37360484Sobrien      return * field;
37460484Sobrien
37560484Sobrien    case 2:
37660484Sobrien      return  ((unsigned int) (field [0]))
37760484Sobrien	|    (((unsigned int) (field [1])) << 8);
37860484Sobrien
37978828Sobrien#ifndef BFD64
38060484Sobrien    case 8:
38160484Sobrien      /* We want to extract data from an 8 byte wide field and
38260484Sobrien	 place it into a 4 byte wide field.  Since this is a little
38360484Sobrien	 endian source we can juts use the 4 byte extraction code.  */
38460484Sobrien      /* Fall through.  */
38578828Sobrien#endif
38660484Sobrien    case 4:
38760484Sobrien      return  ((unsigned long) (field [0]))
38860484Sobrien	|    (((unsigned long) (field [1])) << 8)
38960484Sobrien	|    (((unsigned long) (field [2])) << 16)
39060484Sobrien	|    (((unsigned long) (field [3])) << 24);
39160484Sobrien
39260484Sobrien#ifdef BFD64
39378828Sobrien    case 8:
39460484Sobrien    case -8:
39560484Sobrien      /* This is a special case, generated by the BYTE_GET8 macro.
39660484Sobrien	 It means that we are loading an 8 byte value from a field
39760484Sobrien	 in an external structure into an 8 byte value in a field
39860484Sobrien	 in an internal strcuture.  */
39960484Sobrien      return  ((bfd_vma) (field [0]))
40060484Sobrien	|    (((bfd_vma) (field [1])) << 8)
40160484Sobrien	|    (((bfd_vma) (field [2])) << 16)
40260484Sobrien	|    (((bfd_vma) (field [3])) << 24)
40360484Sobrien	|    (((bfd_vma) (field [4])) << 32)
40460484Sobrien	|    (((bfd_vma) (field [5])) << 40)
40560484Sobrien	|    (((bfd_vma) (field [6])) << 48)
40660484Sobrien	|    (((bfd_vma) (field [7])) << 56);
40760484Sobrien#endif
40860484Sobrien    default:
40960484Sobrien      error (_("Unhandled data length: %d\n"), size);
41060484Sobrien      abort ();
41160484Sobrien    }
41260484Sobrien}
41360484Sobrien
41460484Sobrien/* Print a VMA value.  */
41560484Sobrienstatic void
41660484Sobrienprint_vma (vma, mode)
41760484Sobrien     bfd_vma vma;
41860484Sobrien     print_mode mode;
41960484Sobrien{
42060484Sobrien#ifdef BFD64
42160484Sobrien  if (is_32bit_elf)
42260484Sobrien#endif
42360484Sobrien    {
42460484Sobrien      switch (mode)
42560484Sobrien	{
42660484Sobrien	case FULL_HEX: printf ("0x"); /* drop through */
42760484Sobrien	case LONG_HEX: printf ("%8.8lx", (unsigned long) vma); break;
42860484Sobrien	case PREFIX_HEX: printf ("0x"); /* drop through */
42960484Sobrien	case HEX: printf ("%lx", (unsigned long) vma); break;
43060484Sobrien	case DEC: printf ("%ld", (unsigned long) vma); break;
43160484Sobrien	case DEC_5: printf ("%5ld", (long) vma); break;
43260484Sobrien	case UNSIGNED: printf ("%lu", (unsigned long) vma); break;
43360484Sobrien	}
43460484Sobrien    }
43560484Sobrien#ifdef BFD64
43660484Sobrien  else
43760484Sobrien    {
43860484Sobrien      switch (mode)
43960484Sobrien	{
44060484Sobrien	case FULL_HEX:
44160484Sobrien	  printf ("0x");
44260484Sobrien	  /* drop through */
44377298Sobrien
44460484Sobrien	case LONG_HEX:
44560484Sobrien	  printf_vma (vma);
44660484Sobrien	  break;
44777298Sobrien
44860484Sobrien	case PREFIX_HEX:
44960484Sobrien	  printf ("0x");
45060484Sobrien	  /* drop through */
45177298Sobrien
45260484Sobrien	case HEX:
45360484Sobrien#if BFD_HOST_64BIT_LONG
45460484Sobrien	  printf ("%lx", vma);
45560484Sobrien#else
45660484Sobrien	  if (_bfd_int64_high (vma))
45760484Sobrien	    printf ("%lx%lx", _bfd_int64_high (vma), _bfd_int64_low (vma));
45860484Sobrien	  else
45960484Sobrien	    printf ("%lx", _bfd_int64_low (vma));
46060484Sobrien#endif
46160484Sobrien	  break;
46260484Sobrien
46360484Sobrien	case DEC:
46460484Sobrien#if BFD_HOST_64BIT_LONG
46560484Sobrien	  printf ("%ld", vma);
46660484Sobrien#else
46760484Sobrien	  if (_bfd_int64_high (vma))
46860484Sobrien	    /* ugg */
46960484Sobrien	    printf ("++%ld", _bfd_int64_low (vma));
47060484Sobrien	  else
47160484Sobrien	    printf ("%ld", _bfd_int64_low (vma));
47277298Sobrien#endif
47360484Sobrien	  break;
47460484Sobrien
47560484Sobrien	case DEC_5:
47660484Sobrien#if BFD_HOST_64BIT_LONG
47760484Sobrien	  printf ("%5ld", vma);
47860484Sobrien#else
47960484Sobrien	  if (_bfd_int64_high (vma))
48060484Sobrien	    /* ugg */
48160484Sobrien	    printf ("++%ld", _bfd_int64_low (vma));
48260484Sobrien	  else
48360484Sobrien	    printf ("%5ld", _bfd_int64_low (vma));
48477298Sobrien#endif
48560484Sobrien	  break;
48677298Sobrien
48760484Sobrien	case UNSIGNED:
48860484Sobrien#if BFD_HOST_64BIT_LONG
48960484Sobrien	  printf ("%lu", vma);
49077298Sobrien#else
49160484Sobrien	  if (_bfd_int64_high (vma))
49260484Sobrien	    /* ugg */
49360484Sobrien	    printf ("++%lu", _bfd_int64_low (vma));
49460484Sobrien	  else
49560484Sobrien	    printf ("%lu", _bfd_int64_low (vma));
49660484Sobrien#endif
49760484Sobrien	  break;
49860484Sobrien	}
49960484Sobrien    }
50060484Sobrien#endif
50160484Sobrien}
50260484Sobrien
50360484Sobrienstatic bfd_vma
50460484Sobrienbyte_get_big_endian (field, size)
50560484Sobrien     unsigned char * field;
50660484Sobrien     int             size;
50760484Sobrien{
50860484Sobrien  switch (size)
50960484Sobrien    {
51060484Sobrien    case 1:
51160484Sobrien      return * field;
51260484Sobrien
51360484Sobrien    case 2:
51460484Sobrien      return ((unsigned int) (field [1])) | (((int) (field [0])) << 8);
51560484Sobrien
51660484Sobrien    case 4:
51760484Sobrien      return ((unsigned long) (field [3]))
51860484Sobrien	|   (((unsigned long) (field [2])) << 8)
51960484Sobrien	|   (((unsigned long) (field [1])) << 16)
52060484Sobrien	|   (((unsigned long) (field [0])) << 24);
52160484Sobrien
52278828Sobrien#ifndef BFD64
52360484Sobrien    case 8:
52460484Sobrien      /* Although we are extracing data from an 8 byte wide field, we
52560484Sobrien	 are returning only 4 bytes of data.  */
52660484Sobrien      return ((unsigned long) (field [7]))
52760484Sobrien	|   (((unsigned long) (field [6])) << 8)
52860484Sobrien	|   (((unsigned long) (field [5])) << 16)
52960484Sobrien	|   (((unsigned long) (field [4])) << 24);
53078828Sobrien#else
53178828Sobrien    case 8:
53260484Sobrien    case -8:
53360484Sobrien      /* This is a special case, generated by the BYTE_GET8 macro.
53460484Sobrien	 It means that we are loading an 8 byte value from a field
53560484Sobrien	 in an external structure into an 8 byte value in a field
53660484Sobrien	 in an internal strcuture.  */
53760484Sobrien      return ((bfd_vma) (field [7]))
53860484Sobrien	|   (((bfd_vma) (field [6])) << 8)
53960484Sobrien	|   (((bfd_vma) (field [5])) << 16)
54060484Sobrien	|   (((bfd_vma) (field [4])) << 24)
54160484Sobrien	|   (((bfd_vma) (field [3])) << 32)
54260484Sobrien	|   (((bfd_vma) (field [2])) << 40)
54360484Sobrien	|   (((bfd_vma) (field [1])) << 48)
54460484Sobrien	|   (((bfd_vma) (field [0])) << 56);
54560484Sobrien#endif
54660484Sobrien
54760484Sobrien    default:
54860484Sobrien      error (_("Unhandled data length: %d\n"), size);
54960484Sobrien      abort ();
55060484Sobrien    }
55160484Sobrien}
55260484Sobrien
55377298Sobrien/* Guess the relocation size commonly used by the specific machines.  */
55460484Sobrien
55560484Sobrienstatic int
55660484Sobrienguess_is_rela (e_machine)
55760484Sobrien     unsigned long e_machine;
55860484Sobrien{
55960484Sobrien  switch (e_machine)
56060484Sobrien    {
56160484Sobrien      /* Targets that use REL relocations.  */
56260484Sobrien    case EM_ARM:
56360484Sobrien    case EM_386:
56460484Sobrien    case EM_486:
56560484Sobrien    case EM_960:
56660484Sobrien    case EM_CYGNUS_M32R:
56760484Sobrien    case EM_CYGNUS_D10V:
56860484Sobrien    case EM_MIPS:
56978828Sobrien    case EM_MIPS_RS3_LE:
57060484Sobrien      return FALSE;
57160484Sobrien
57260484Sobrien      /* Targets that use RELA relocations.  */
57360484Sobrien    case EM_68K:
57460484Sobrien    case EM_SPARC32PLUS:
57560484Sobrien    case EM_SPARCV9:
57660484Sobrien    case EM_SPARC:
57760484Sobrien    case EM_PPC:
57860484Sobrien    case EM_CYGNUS_V850:
57960484Sobrien    case EM_CYGNUS_D30V:
58060484Sobrien    case EM_CYGNUS_MN10200:
58160484Sobrien    case EM_CYGNUS_MN10300:
58260484Sobrien    case EM_CYGNUS_FR30:
58360484Sobrien    case EM_SH:
58460484Sobrien    case EM_ALPHA:
58560484Sobrien    case EM_MCORE:
58677298Sobrien    case EM_IA_64:
58777298Sobrien    case EM_AVR:
58877298Sobrien    case EM_CRIS:
58977298Sobrien    case EM_860:
59077298Sobrien    case EM_X86_64:
59160484Sobrien      return TRUE;
59260484Sobrien
59360484Sobrien    case EM_MMA:
59460484Sobrien    case EM_PCP:
59560484Sobrien    case EM_NCPU:
59660484Sobrien    case EM_NDR1:
59760484Sobrien    case EM_STARCORE:
59860484Sobrien    case EM_ME16:
59960484Sobrien    case EM_ST100:
60060484Sobrien    case EM_TINYJ:
60160484Sobrien    case EM_FX66:
60260484Sobrien    case EM_ST9PLUS:
60360484Sobrien    case EM_ST7:
60460484Sobrien    case EM_68HC16:
60560484Sobrien    case EM_68HC11:
60660484Sobrien    case EM_68HC08:
60760484Sobrien    case EM_68HC05:
60860484Sobrien    case EM_SVX:
60960484Sobrien    case EM_ST19:
61060484Sobrien    case EM_VAX:
61160484Sobrien    default:
61260484Sobrien      warn (_("Don't know about relocations on this machine architecture\n"));
61360484Sobrien      return FALSE;
61460484Sobrien    }
61560484Sobrien}
61660484Sobrien
61760484Sobrienstatic int
61878828Sobrienslurp_rela_relocs (file, rel_offset, rel_size, relasp, nrelasp)
61978828Sobrien     FILE *file;
62078828Sobrien     unsigned long rel_offset;
62178828Sobrien     unsigned long rel_size;
62278828Sobrien     Elf_Internal_Rela **relasp;
62378828Sobrien     unsigned long *nrelasp;
62460484Sobrien{
62578828Sobrien  Elf_Internal_Rela *relas;
62678828Sobrien  unsigned long nrelas;
62778828Sobrien  unsigned int i;
62860484Sobrien
62978828Sobrien  if (is_32bit_elf)
63078828Sobrien    {
63178828Sobrien      Elf32_External_Rela * erelas;
63260484Sobrien
63378828Sobrien      GET_DATA_ALLOC (rel_offset, rel_size, erelas,
63478828Sobrien		      Elf32_External_Rela *, "relocs");
63560484Sobrien
63678828Sobrien      nrelas = rel_size / sizeof (Elf32_External_Rela);
63778828Sobrien
63878828Sobrien      relas = (Elf_Internal_Rela *)
63978828Sobrien	malloc (nrelas * sizeof (Elf_Internal_Rela));
64078828Sobrien
64178828Sobrien      if (relas == NULL)
64260484Sobrien	{
64378828Sobrien	  error(_("out of memory parsing relocs"));
64478828Sobrien	  return 0;
64578828Sobrien	}
64660484Sobrien
64778828Sobrien      for (i = 0; i < nrelas; i++)
64878828Sobrien	{
64978828Sobrien	  relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
65078828Sobrien	  relas[i].r_info   = BYTE_GET (erelas[i].r_info);
65178828Sobrien	  relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
65278828Sobrien	}
65360484Sobrien
65478828Sobrien      free (erelas);
65578828Sobrien    }
65678828Sobrien  else
65778828Sobrien    {
65878828Sobrien      Elf64_External_Rela * erelas;
65960484Sobrien
66078828Sobrien      GET_DATA_ALLOC (rel_offset, rel_size, erelas,
66178828Sobrien		      Elf64_External_Rela *, "relocs");
66260484Sobrien
66378828Sobrien      nrelas = rel_size / sizeof (Elf64_External_Rela);
66460484Sobrien
66578828Sobrien      relas = (Elf_Internal_Rela *)
66678828Sobrien	malloc (nrelas * sizeof (Elf_Internal_Rela));
66760484Sobrien
66878828Sobrien      if (relas == NULL)
66978828Sobrien	{
67078828Sobrien	  error(_("out of memory parsing relocs"));
67178828Sobrien	  return 0;
67278828Sobrien	}
67360484Sobrien
67478828Sobrien      for (i = 0; i < nrelas; i++)
67578828Sobrien	{
67678828Sobrien	  relas[i].r_offset = BYTE_GET8 (erelas[i].r_offset);
67778828Sobrien	  relas[i].r_info   = BYTE_GET8 (erelas[i].r_info);
67878828Sobrien	  relas[i].r_addend = BYTE_GET8 (erelas[i].r_addend);
67960484Sobrien	}
68060484Sobrien
68178828Sobrien      free (erelas);
68278828Sobrien    }
68378828Sobrien  *relasp = relas;
68478828Sobrien  *nrelasp = nrelas;
68578828Sobrien  return 1;
68678828Sobrien}
68760484Sobrien
68878828Sobrienstatic int
68978828Sobrienslurp_rel_relocs (file, rel_offset, rel_size, relsp, nrelsp)
69078828Sobrien     FILE *file;
69178828Sobrien     unsigned long rel_offset;
69278828Sobrien     unsigned long rel_size;
69378828Sobrien     Elf_Internal_Rel **relsp;
69478828Sobrien     unsigned long *nrelsp;
69578828Sobrien{
69678828Sobrien  Elf_Internal_Rel *rels;
69778828Sobrien  unsigned long nrels;
69878828Sobrien  unsigned int i;
69960484Sobrien
70078828Sobrien  if (is_32bit_elf)
70178828Sobrien    {
70278828Sobrien      Elf32_External_Rel * erels;
70360484Sobrien
70478828Sobrien      GET_DATA_ALLOC (rel_offset, rel_size, erels,
70578828Sobrien		      Elf32_External_Rel *, "relocs");
70660484Sobrien
70778828Sobrien      nrels = rel_size / sizeof (Elf32_External_Rel);
70860484Sobrien
70978828Sobrien      rels = (Elf_Internal_Rel *) malloc (nrels * sizeof (Elf_Internal_Rel));
71060484Sobrien
71178828Sobrien      if (rels == NULL)
71278828Sobrien	{
71378828Sobrien	  error(_("out of memory parsing relocs"));
71478828Sobrien	  return 0;
71560484Sobrien	}
71678828Sobrien
71778828Sobrien      for (i = 0; i < nrels; i++)
71878828Sobrien	{
71978828Sobrien	  rels[i].r_offset = BYTE_GET (erels[i].r_offset);
72078828Sobrien	  rels[i].r_info   = BYTE_GET (erels[i].r_info);
72178828Sobrien	}
72278828Sobrien
72378828Sobrien      free (erels);
72460484Sobrien    }
72560484Sobrien  else
72660484Sobrien    {
72778828Sobrien      Elf64_External_Rel * erels;
72860484Sobrien
72978828Sobrien      GET_DATA_ALLOC (rel_offset, rel_size, erels,
73078828Sobrien		      Elf64_External_Rel *, "relocs");
73160484Sobrien
73278828Sobrien      nrels = rel_size / sizeof (Elf64_External_Rel);
73360484Sobrien
73478828Sobrien      rels = (Elf_Internal_Rel *) malloc (nrels * sizeof (Elf_Internal_Rel));
73560484Sobrien
73678828Sobrien      if (rels == NULL)
73778828Sobrien	{
73878828Sobrien	  error(_("out of memory parsing relocs"));
73978828Sobrien	  return 0;
74078828Sobrien	}
74160484Sobrien
74278828Sobrien      for (i = 0; i < nrels; i++)
74378828Sobrien	{
74478828Sobrien	  rels[i].r_offset = BYTE_GET8 (erels[i].r_offset);
74578828Sobrien	  rels[i].r_info   = BYTE_GET8 (erels[i].r_info);
74660484Sobrien	}
74760484Sobrien
74878828Sobrien      free (erels);
74978828Sobrien    }
75078828Sobrien  *relsp = rels;
75178828Sobrien  *nrelsp = nrels;
75278828Sobrien  return 1;
75378828Sobrien}
75460484Sobrien
75578828Sobrien/* Display the contents of the relocation data found at the specified offset.  */
75678828Sobrienstatic int
75778828Sobriendump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
75878828Sobrien     FILE *             file;
75978828Sobrien     unsigned long      rel_offset;
76078828Sobrien     unsigned long      rel_size;
76178828Sobrien     Elf_Internal_Sym * symtab;
76278828Sobrien     unsigned long      nsyms;
76378828Sobrien     char *             strtab;
76478828Sobrien     int                is_rela;
76578828Sobrien{
76678828Sobrien  unsigned int        i;
76778828Sobrien  Elf_Internal_Rel *  rels;
76878828Sobrien  Elf_Internal_Rela * relas;
76960484Sobrien
77060484Sobrien
77178828Sobrien  if (is_rela == UNKNOWN)
77278828Sobrien    is_rela = guess_is_rela (elf_header.e_machine);
77360484Sobrien
77478828Sobrien  if (is_rela)
77578828Sobrien    {
77678828Sobrien      if (!slurp_rela_relocs (file, rel_offset, rel_size, &relas, &rel_size))
77778828Sobrien	return 0;
77860484Sobrien    }
77978828Sobrien  else
78078828Sobrien    {
78178828Sobrien      if (!slurp_rel_relocs (file, rel_offset, rel_size, &rels, &rel_size))
78278828Sobrien	return 0;
78378828Sobrien    }
78460484Sobrien
78560484Sobrien  if (is_rela)
78660484Sobrien    printf
78760484Sobrien      (_("  Offset    Info  Type            Symbol's Value  Symbol's Name          Addend\n"));
78860484Sobrien  else
78960484Sobrien    printf
79060484Sobrien      (_("  Offset    Info  Type            Symbol's Value  Symbol's Name\n"));
79160484Sobrien
79260484Sobrien  for (i = 0; i < rel_size; i++)
79360484Sobrien    {
79460484Sobrien      const char * rtype;
79560484Sobrien      bfd_vma      offset;
79660484Sobrien      bfd_vma      info;
79760484Sobrien      bfd_vma      symtab_index;
79860484Sobrien      bfd_vma      type;
79960484Sobrien
80060484Sobrien      if (is_rela)
80160484Sobrien	{
80260484Sobrien	  offset = relas [i].r_offset;
80360484Sobrien	  info   = relas [i].r_info;
80460484Sobrien	}
80560484Sobrien      else
80660484Sobrien	{
80760484Sobrien	  offset = rels [i].r_offset;
80860484Sobrien	  info   = rels [i].r_info;
80960484Sobrien	}
81060484Sobrien
81160484Sobrien      if (is_32bit_elf)
81260484Sobrien	{
81360484Sobrien	  type         = ELF32_R_TYPE (info);
81460484Sobrien	  symtab_index = ELF32_R_SYM  (info);
81560484Sobrien	}
81660484Sobrien      else
81760484Sobrien	{
81860484Sobrien	  if (elf_header.e_machine == EM_SPARCV9)
81960484Sobrien	    type       = ELF64_R_TYPE_ID (info);
82060484Sobrien	  else
82160484Sobrien	    type       = ELF64_R_TYPE (info);
82260484Sobrien	  /* The #ifdef BFD64 below is to prevent a compile time warning.
82360484Sobrien	     We know that if we do not have a 64 bit data type that we
82460484Sobrien	     will never execute this code anyway.  */
82560484Sobrien#ifdef BFD64
82660484Sobrien	  symtab_index = ELF64_R_SYM  (info);
82760484Sobrien#endif
82860484Sobrien	}
82960484Sobrien
83060484Sobrien#ifdef _bfd_int64_low
83160484Sobrien      printf ("  %8.8lx  %5.5lx ", _bfd_int64_low (offset), _bfd_int64_low (info));
83260484Sobrien#else
83360484Sobrien      printf ("  %8.8lx  %5.5lx ", offset, info);
83460484Sobrien#endif
83560484Sobrien
83660484Sobrien      switch (elf_header.e_machine)
83760484Sobrien	{
83860484Sobrien	default:
83960484Sobrien	  rtype = NULL;
84060484Sobrien	  break;
84160484Sobrien
84260484Sobrien	case EM_CYGNUS_M32R:
84360484Sobrien	  rtype = elf_m32r_reloc_type (type);
84460484Sobrien	  break;
84560484Sobrien
84660484Sobrien	case EM_386:
84760484Sobrien	case EM_486:
84860484Sobrien	  rtype = elf_i386_reloc_type (type);
84960484Sobrien	  break;
85060484Sobrien
85160484Sobrien	case EM_68K:
85260484Sobrien	  rtype = elf_m68k_reloc_type (type);
85360484Sobrien	  break;
85460484Sobrien
85560484Sobrien	case EM_960:
85660484Sobrien	  rtype = elf_i960_reloc_type (type);
85760484Sobrien	  break;
85860484Sobrien
85960484Sobrien	case EM_AVR:
86060484Sobrien	  rtype = elf_avr_reloc_type (type);
86160484Sobrien	  break;
86260484Sobrien
86360484Sobrien	case EM_OLD_SPARCV9:
86460484Sobrien	case EM_SPARC32PLUS:
86560484Sobrien	case EM_SPARCV9:
86660484Sobrien	case EM_SPARC:
86760484Sobrien	  rtype = elf_sparc_reloc_type (type);
86860484Sobrien	  break;
86960484Sobrien
87060484Sobrien	case EM_CYGNUS_V850:
87160484Sobrien	  rtype = v850_reloc_type (type);
87260484Sobrien	  break;
87360484Sobrien
87460484Sobrien	case EM_CYGNUS_D10V:
87560484Sobrien	  rtype = elf_d10v_reloc_type (type);
87660484Sobrien	  break;
87760484Sobrien
87860484Sobrien	case EM_CYGNUS_D30V:
87960484Sobrien	  rtype = elf_d30v_reloc_type (type);
88060484Sobrien	  break;
88160484Sobrien
88260484Sobrien	case EM_SH:
88360484Sobrien	  rtype = elf_sh_reloc_type (type);
88460484Sobrien	  break;
88560484Sobrien
88660484Sobrien	case EM_CYGNUS_MN10300:
88760484Sobrien	  rtype = elf_mn10300_reloc_type (type);
88860484Sobrien	  break;
88960484Sobrien
89060484Sobrien	case EM_CYGNUS_MN10200:
89160484Sobrien	  rtype = elf_mn10200_reloc_type (type);
89260484Sobrien	  break;
89360484Sobrien
89460484Sobrien	case EM_CYGNUS_FR30:
89560484Sobrien	  rtype = elf_fr30_reloc_type (type);
89660484Sobrien	  break;
89760484Sobrien
89860484Sobrien	case EM_MCORE:
89960484Sobrien	  rtype = elf_mcore_reloc_type (type);
90060484Sobrien	  break;
90160484Sobrien
90260484Sobrien	case EM_PPC:
90360484Sobrien	  rtype = elf_ppc_reloc_type (type);
90460484Sobrien	  break;
90560484Sobrien
90660484Sobrien	case EM_MIPS:
90778828Sobrien	case EM_MIPS_RS3_LE:
90860484Sobrien	  rtype = elf_mips_reloc_type (type);
90960484Sobrien	  break;
91060484Sobrien
91160484Sobrien	case EM_ALPHA:
91260484Sobrien	  rtype = elf_alpha_reloc_type (type);
91360484Sobrien	  break;
91460484Sobrien
91560484Sobrien	case EM_ARM:
91660484Sobrien	  rtype = elf_arm_reloc_type (type);
91760484Sobrien	  break;
91860484Sobrien
91960484Sobrien	case EM_CYGNUS_ARC:
92077298Sobrien	case EM_ARC:
92160484Sobrien	  rtype = elf_arc_reloc_type (type);
92260484Sobrien	  break;
92360484Sobrien
92460484Sobrien	case EM_PARISC:
92560484Sobrien	  rtype = elf_hppa_reloc_type (type);
92660484Sobrien	  break;
92760484Sobrien
92860484Sobrien	case EM_PJ:
92960484Sobrien	  rtype = elf_pj_reloc_type (type);
93060484Sobrien	  break;
93177298Sobrien	case EM_IA_64:
93277298Sobrien	  rtype = elf_ia64_reloc_type (type);
93377298Sobrien	  break;
93477298Sobrien
93577298Sobrien	case EM_CRIS:
93677298Sobrien	  rtype = elf_cris_reloc_type (type);
93777298Sobrien	  break;
93877298Sobrien
93977298Sobrien	case EM_860:
94077298Sobrien	  rtype = elf_i860_reloc_type (type);
94177298Sobrien	  break;
94277298Sobrien
94377298Sobrien	case EM_X86_64:
94477298Sobrien	  rtype = elf_x86_64_reloc_type (type);
94577298Sobrien	  break;
94660484Sobrien	}
94760484Sobrien
94860484Sobrien      if (rtype == NULL)
94960484Sobrien#ifdef _bfd_int64_low
95060484Sobrien	printf (_("unrecognised: %-7lx"), _bfd_int64_low (type));
95160484Sobrien#else
95260484Sobrien	printf (_("unrecognised: %-7lx"), type);
95360484Sobrien#endif
95460484Sobrien      else
95560484Sobrien	printf ("%-21.21s", rtype);
95660484Sobrien
95760484Sobrien      if (symtab_index)
95860484Sobrien	{
95960484Sobrien	  if (symtab != NULL)
96060484Sobrien	    {
96160484Sobrien	      if (symtab_index >= nsyms)
96260484Sobrien		printf (" bad symbol index: %08lx", (unsigned long) symtab_index);
96360484Sobrien	      else
96460484Sobrien		{
96560484Sobrien		  Elf_Internal_Sym * psym;
96660484Sobrien
96760484Sobrien		  psym = symtab + symtab_index;
96860484Sobrien
96960484Sobrien		  printf (" ");
97060484Sobrien		  print_vma (psym->st_value, LONG_HEX);
97160484Sobrien		  printf ("  ");
97260484Sobrien
97360484Sobrien		  if (psym->st_name == 0)
97460484Sobrien		    printf ("%-25.25s",
97560484Sobrien			    SECTION_NAME (section_headers + psym->st_shndx));
97660484Sobrien		  else if (strtab == NULL)
97760484Sobrien		    printf (_("<string table index %3ld>"), psym->st_name);
97860484Sobrien		  else
97960484Sobrien		    printf ("%-25.25s", strtab + psym->st_name);
98060484Sobrien
98160484Sobrien		  if (is_rela)
98260484Sobrien		    printf (" + %lx", (unsigned long) relas [i].r_addend);
98360484Sobrien		}
98460484Sobrien	    }
98560484Sobrien	}
98660484Sobrien      else if (is_rela)
98760484Sobrien	{
98860484Sobrien	  printf ("%*c", is_32bit_elf ? 34 : 26, ' ');
98960484Sobrien	  print_vma (relas[i].r_addend, LONG_HEX);
99060484Sobrien	}
99160484Sobrien
99260484Sobrien      if (elf_header.e_machine == EM_SPARCV9
99360484Sobrien	  && !strcmp (rtype, "R_SPARC_OLO10"))
99460484Sobrien	printf (" + %lx", (unsigned long) ELF64_R_TYPE_DATA (info));
99560484Sobrien
99660484Sobrien      putchar ('\n');
99760484Sobrien    }
99860484Sobrien
99978828Sobrien  if (is_rela)
100078828Sobrien    free (relas);
100178828Sobrien  else
100278828Sobrien    free (rels);
100360484Sobrien
100460484Sobrien  return 1;
100560484Sobrien}
100660484Sobrien
100760484Sobrienstatic const char *
100860484Sobrienget_mips_dynamic_type (type)
100960484Sobrien     unsigned long type;
101060484Sobrien{
101160484Sobrien  switch (type)
101260484Sobrien    {
101360484Sobrien    case DT_MIPS_RLD_VERSION: return "MIPS_RLD_VERSION";
101460484Sobrien    case DT_MIPS_TIME_STAMP: return "MIPS_TIME_STAMP";
101560484Sobrien    case DT_MIPS_ICHECKSUM: return "MIPS_ICHECKSUM";
101660484Sobrien    case DT_MIPS_IVERSION: return "MIPS_IVERSION";
101760484Sobrien    case DT_MIPS_FLAGS: return "MIPS_FLAGS";
101860484Sobrien    case DT_MIPS_BASE_ADDRESS: return "MIPS_BASE_ADDRESS";
101960484Sobrien    case DT_MIPS_MSYM: return "MIPS_MSYM";
102060484Sobrien    case DT_MIPS_CONFLICT: return "MIPS_CONFLICT";
102160484Sobrien    case DT_MIPS_LIBLIST: return "MIPS_LIBLIST";
102260484Sobrien    case DT_MIPS_LOCAL_GOTNO: return "MIPS_LOCAL_GOTNO";
102360484Sobrien    case DT_MIPS_CONFLICTNO: return "MIPS_CONFLICTNO";
102460484Sobrien    case DT_MIPS_LIBLISTNO: return "MIPS_LIBLISTNO";
102560484Sobrien    case DT_MIPS_SYMTABNO: return "MIPS_SYMTABNO";
102660484Sobrien    case DT_MIPS_UNREFEXTNO: return "MIPS_UNREFEXTNO";
102760484Sobrien    case DT_MIPS_GOTSYM: return "MIPS_GOTSYM";
102860484Sobrien    case DT_MIPS_HIPAGENO: return "MIPS_HIPAGENO";
102960484Sobrien    case DT_MIPS_RLD_MAP: return "MIPS_RLD_MAP";
103060484Sobrien    case DT_MIPS_DELTA_CLASS: return "MIPS_DELTA_CLASS";
103160484Sobrien    case DT_MIPS_DELTA_CLASS_NO: return "MIPS_DELTA_CLASS_NO";
103260484Sobrien    case DT_MIPS_DELTA_INSTANCE: return "MIPS_DELTA_INSTANCE";
103360484Sobrien    case DT_MIPS_DELTA_INSTANCE_NO: return "MIPS_DELTA_INSTANCE_NO";
103460484Sobrien    case DT_MIPS_DELTA_RELOC: return "MIPS_DELTA_RELOC";
103560484Sobrien    case DT_MIPS_DELTA_RELOC_NO: return "MIPS_DELTA_RELOC_NO";
103660484Sobrien    case DT_MIPS_DELTA_SYM: return "MIPS_DELTA_SYM";
103760484Sobrien    case DT_MIPS_DELTA_SYM_NO: return "MIPS_DELTA_SYM_NO";
103860484Sobrien    case DT_MIPS_DELTA_CLASSSYM: return "MIPS_DELTA_CLASSSYM";
103960484Sobrien    case DT_MIPS_DELTA_CLASSSYM_NO: return "MIPS_DELTA_CLASSSYM_NO";
104060484Sobrien    case DT_MIPS_CXX_FLAGS: return "MIPS_CXX_FLAGS";
104160484Sobrien    case DT_MIPS_PIXIE_INIT: return "MIPS_PIXIE_INIT";
104260484Sobrien    case DT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB";
104360484Sobrien    case DT_MIPS_LOCALPAGE_GOTIDX: return "MIPS_LOCALPAGE_GOTIDX";
104460484Sobrien    case DT_MIPS_LOCAL_GOTIDX: return "MIPS_LOCAL_GOTIDX";
104560484Sobrien    case DT_MIPS_HIDDEN_GOTIDX: return "MIPS_HIDDEN_GOTIDX";
104660484Sobrien    case DT_MIPS_PROTECTED_GOTIDX: return "MIPS_PROTECTED_GOTIDX";
104760484Sobrien    case DT_MIPS_OPTIONS: return "MIPS_OPTIONS";
104860484Sobrien    case DT_MIPS_INTERFACE: return "MIPS_INTERFACE";
104960484Sobrien    case DT_MIPS_DYNSTR_ALIGN: return "MIPS_DYNSTR_ALIGN";
105060484Sobrien    case DT_MIPS_INTERFACE_SIZE: return "MIPS_INTERFACE_SIZE";
105160484Sobrien    case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: return "MIPS_RLD_TEXT_RESOLVE_ADDR";
105260484Sobrien    case DT_MIPS_PERF_SUFFIX: return "MIPS_PERF_SUFFIX";
105360484Sobrien    case DT_MIPS_COMPACT_SIZE: return "MIPS_COMPACT_SIZE";
105460484Sobrien    case DT_MIPS_GP_VALUE: return "MIPS_GP_VALUE";
105560484Sobrien    case DT_MIPS_AUX_DYNAMIC: return "MIPS_AUX_DYNAMIC";
105660484Sobrien    default:
105760484Sobrien      return NULL;
105860484Sobrien    }
105960484Sobrien}
106060484Sobrien
106160484Sobrienstatic const char *
106260484Sobrienget_sparc64_dynamic_type (type)
106360484Sobrien     unsigned long type;
106460484Sobrien{
106560484Sobrien  switch (type)
106660484Sobrien    {
106760484Sobrien    case DT_SPARC_REGISTER: return "SPARC_REGISTER";
106860484Sobrien    default:
106960484Sobrien      return NULL;
107060484Sobrien    }
107160484Sobrien}
107260484Sobrien
107360484Sobrienstatic const char *
107460484Sobrienget_parisc_dynamic_type (type)
107560484Sobrien     unsigned long type;
107660484Sobrien{
107760484Sobrien  switch (type)
107860484Sobrien    {
107960484Sobrien    case DT_HP_LOAD_MAP:	return "HP_LOAD_MAP";
108060484Sobrien    case DT_HP_DLD_FLAGS:	return "HP_DLD_FLAGS";
108160484Sobrien    case DT_HP_DLD_HOOK:	return "HP_DLD_HOOK";
108260484Sobrien    case DT_HP_UX10_INIT:	return "HP_UX10_INIT";
108360484Sobrien    case DT_HP_UX10_INITSZ:	return "HP_UX10_INITSZ";
108460484Sobrien    case DT_HP_PREINIT:		return "HP_PREINIT";
108560484Sobrien    case DT_HP_PREINITSZ:	return "HP_PREINITSZ";
108660484Sobrien    case DT_HP_NEEDED:		return "HP_NEEDED";
108760484Sobrien    case DT_HP_TIME_STAMP:	return "HP_TIME_STAMP";
108860484Sobrien    case DT_HP_CHECKSUM:	return "HP_CHECKSUM";
108960484Sobrien    case DT_HP_GST_SIZE:	return "HP_GST_SIZE";
109060484Sobrien    case DT_HP_GST_VERSION:	return "HP_GST_VERSION";
109160484Sobrien    case DT_HP_GST_HASHVAL:	return "HP_GST_HASHVAL";
109260484Sobrien    default:
109360484Sobrien      return NULL;
109460484Sobrien    }
109560484Sobrien}
109660484Sobrien
109760484Sobrienstatic const char *
109860484Sobrienget_dynamic_type (type)
109960484Sobrien     unsigned long type;
110060484Sobrien{
110160484Sobrien  static char buff [32];
110260484Sobrien
110360484Sobrien  switch (type)
110460484Sobrien    {
110560484Sobrien    case DT_NULL:	return "NULL";
110660484Sobrien    case DT_NEEDED:	return "NEEDED";
110760484Sobrien    case DT_PLTRELSZ:	return "PLTRELSZ";
110860484Sobrien    case DT_PLTGOT:	return "PLTGOT";
110960484Sobrien    case DT_HASH:	return "HASH";
111060484Sobrien    case DT_STRTAB:	return "STRTAB";
111160484Sobrien    case DT_SYMTAB:	return "SYMTAB";
111260484Sobrien    case DT_RELA:	return "RELA";
111360484Sobrien    case DT_RELASZ:	return "RELASZ";
111460484Sobrien    case DT_RELAENT:	return "RELAENT";
111560484Sobrien    case DT_STRSZ:	return "STRSZ";
111660484Sobrien    case DT_SYMENT:	return "SYMENT";
111760484Sobrien    case DT_INIT:	return "INIT";
111860484Sobrien    case DT_FINI:	return "FINI";
111960484Sobrien    case DT_SONAME:	return "SONAME";
112060484Sobrien    case DT_RPATH:	return "RPATH";
112160484Sobrien    case DT_SYMBOLIC:	return "SYMBOLIC";
112260484Sobrien    case DT_REL:	return "REL";
112360484Sobrien    case DT_RELSZ:	return "RELSZ";
112460484Sobrien    case DT_RELENT:	return "RELENT";
112560484Sobrien    case DT_PLTREL:	return "PLTREL";
112660484Sobrien    case DT_DEBUG:	return "DEBUG";
112760484Sobrien    case DT_TEXTREL:	return "TEXTREL";
112860484Sobrien    case DT_JMPREL:	return "JMPREL";
112960484Sobrien    case DT_BIND_NOW:   return "BIND_NOW";
113060484Sobrien    case DT_INIT_ARRAY: return "INIT_ARRAY";
113160484Sobrien    case DT_FINI_ARRAY: return "FINI_ARRAY";
113260484Sobrien    case DT_INIT_ARRAYSZ: return "INIT_ARRAYSZ";
113360484Sobrien    case DT_FINI_ARRAYSZ: return "FINI_ARRAYSZ";
113460484Sobrien    case DT_RUNPATH:    return "RUNPATH";
113560484Sobrien    case DT_FLAGS:      return "FLAGS";
113660484Sobrien
113760484Sobrien    case DT_PREINIT_ARRAY: return "PREINIT_ARRAY";
113860484Sobrien    case DT_PREINIT_ARRAYSZ: return "PREINIT_ARRAYSZ";
113960484Sobrien
114068765Sobrien    case DT_CHECKSUM:	return "CHECKSUM";
114160484Sobrien    case DT_PLTPADSZ:	return "PLTPADSZ";
114260484Sobrien    case DT_MOVEENT:	return "MOVEENT";
114360484Sobrien    case DT_MOVESZ:	return "MOVESZ";
114468765Sobrien    case DT_FEATURE:	return "FEATURE";
114560484Sobrien    case DT_POSFLAG_1:	return "POSFLAG_1";
114660484Sobrien    case DT_SYMINSZ:	return "SYMINSZ";
114760484Sobrien    case DT_SYMINENT:	return "SYMINENT"; /* aka VALRNGHI */
114860484Sobrien
114960484Sobrien    case DT_ADDRRNGLO:  return "ADDRRNGLO";
115068765Sobrien    case DT_CONFIG:	return "CONFIG";
115168765Sobrien    case DT_DEPAUDIT:	return "DEPAUDIT";
115268765Sobrien    case DT_AUDIT:	return "AUDIT";
115368765Sobrien    case DT_PLTPAD:	return "PLTPAD";
115468765Sobrien    case DT_MOVETAB:	return "MOVETAB";
115560484Sobrien    case DT_SYMINFO:	return "SYMINFO"; /* aka ADDRRNGHI */
115660484Sobrien
115760484Sobrien    case DT_VERSYM:	return "VERSYM";
115860484Sobrien
115960484Sobrien    case DT_RELACOUNT:	return "RELACOUNT";
116060484Sobrien    case DT_RELCOUNT:	return "RELCOUNT";
116160484Sobrien    case DT_FLAGS_1:	return "FLAGS_1";
116260484Sobrien    case DT_VERDEF:	return "VERDEF";
116360484Sobrien    case DT_VERDEFNUM:	return "VERDEFNUM";
116460484Sobrien    case DT_VERNEED:	return "VERNEED";
116560484Sobrien    case DT_VERNEEDNUM:	return "VERNEEDNUM";
116660484Sobrien
116768765Sobrien    case DT_AUXILIARY:	return "AUXILIARY";
116860484Sobrien    case DT_USED:	return "USED";
116960484Sobrien    case DT_FILTER:	return "FILTER";
117060484Sobrien
117160484Sobrien    default:
117260484Sobrien      if ((type >= DT_LOPROC) && (type <= DT_HIPROC))
117360484Sobrien	{
117460484Sobrien	  const char * result;
117560484Sobrien
117660484Sobrien	  switch (elf_header.e_machine)
117760484Sobrien	    {
117860484Sobrien	    case EM_MIPS:
117978828Sobrien	    case EM_MIPS_RS3_LE:
118060484Sobrien	      result = get_mips_dynamic_type (type);
118160484Sobrien	      break;
118260484Sobrien	    case EM_SPARCV9:
118360484Sobrien	      result = get_sparc64_dynamic_type (type);
118460484Sobrien	      break;
118560484Sobrien	    default:
118660484Sobrien	      result = NULL;
118760484Sobrien	      break;
118860484Sobrien	    }
118960484Sobrien
119060484Sobrien	  if (result != NULL)
119160484Sobrien	    return result;
119260484Sobrien
119360484Sobrien	  sprintf (buff, _("Processor Specific: %lx"), type);
119460484Sobrien	}
119560484Sobrien      else if ((type >= DT_LOOS) && (type <= DT_HIOS))
119660484Sobrien	{
119760484Sobrien	  const char * result;
119860484Sobrien
119960484Sobrien	  switch (elf_header.e_machine)
120060484Sobrien	    {
120160484Sobrien	    case EM_PARISC:
120260484Sobrien	      result = get_parisc_dynamic_type (type);
120360484Sobrien	      break;
120460484Sobrien	    default:
120560484Sobrien	      result = NULL;
120660484Sobrien	      break;
120760484Sobrien	    }
120860484Sobrien
120960484Sobrien	  if (result != NULL)
121060484Sobrien	    return result;
121160484Sobrien
121260484Sobrien	  sprintf (buff, _("Operating System specific: %lx"), type);
121360484Sobrien	}
121460484Sobrien      else
121560484Sobrien	sprintf (buff, _("<unknown>: %lx"), type);
121660484Sobrien
121760484Sobrien      return buff;
121860484Sobrien    }
121960484Sobrien}
122060484Sobrien
122160484Sobrienstatic char *
122260484Sobrienget_file_type (e_type)
122360484Sobrien     unsigned e_type;
122460484Sobrien{
122560484Sobrien  static char buff [32];
122660484Sobrien
122760484Sobrien  switch (e_type)
122860484Sobrien    {
122960484Sobrien    case ET_NONE:	return _("NONE (None)");
123060484Sobrien    case ET_REL:	return _("REL (Relocatable file)");
123160484Sobrien    case ET_EXEC:       return _("EXEC (Executable file)");
123260484Sobrien    case ET_DYN:        return _("DYN (Shared object file)");
123360484Sobrien    case ET_CORE:       return _("CORE (Core file)");
123460484Sobrien
123560484Sobrien    default:
123660484Sobrien      if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC))
123760484Sobrien	sprintf (buff, _("Processor Specific: (%x)"), e_type);
123860484Sobrien      else if ((e_type >= ET_LOOS) && (e_type <= ET_HIOS))
123960484Sobrien	sprintf (buff, _("OS Specific: (%x)"), e_type);
124060484Sobrien      else
124160484Sobrien	sprintf (buff, _("<unknown>: %x"), e_type);
124260484Sobrien      return buff;
124360484Sobrien    }
124460484Sobrien}
124560484Sobrien
124660484Sobrienstatic char *
124760484Sobrienget_machine_name (e_machine)
124860484Sobrien     unsigned e_machine;
124960484Sobrien{
125060484Sobrien  static char buff [64]; /* XXX */
125160484Sobrien
125260484Sobrien  switch (e_machine)
125360484Sobrien    {
125478828Sobrien    case EM_NONE:	return _("None");
125578828Sobrien    case EM_M32:	return "WE32100";
125678828Sobrien    case EM_SPARC:	return "Sparc";
125778828Sobrien    case EM_386:	return "Intel 80386";
125878828Sobrien    case EM_68K:	return "MC68000";
125978828Sobrien    case EM_88K:	return "MC88000";
126078828Sobrien    case EM_486:	return "Intel 80486";
126178828Sobrien    case EM_860:	return "Intel 80860";
126278828Sobrien    case EM_MIPS:	return "MIPS R3000";
126378828Sobrien    case EM_S370:	return "IBM System/370";
126478828Sobrien    case EM_MIPS_RS3_LE:	return "MIPS R4000 big-endian";
126560484Sobrien    case EM_OLD_SPARCV9:	return "Sparc v9 (old)";
126678828Sobrien    case EM_PARISC:	return "HPPA";
126760484Sobrien    case EM_PPC_OLD:		return "Power PC (old)";
126878828Sobrien    case EM_SPARC32PLUS:	return "Sparc v8+" ;
126978828Sobrien    case EM_960:	return "Intel 90860";
127078828Sobrien    case EM_PPC:	return "PowerPC";
127178828Sobrien    case EM_V800:	return "NEC V800";
127278828Sobrien    case EM_FR20:	return "Fujitsu FR20";
127378828Sobrien    case EM_RH32:	return "TRW RH32";
127460484Sobrien    case EM_MCORE:	        return "MCORE";
127578828Sobrien    case EM_ARM:		return "ARM";
127678828Sobrien    case EM_OLD_ALPHA:		return "Digital Alpha (old)";
127778828Sobrien    case EM_SH:			return "Hitachi SH";
127878828Sobrien    case EM_SPARCV9:	return "Sparc v9";
127978828Sobrien    case EM_TRICORE:	return "Siemens Tricore";
128077298Sobrien    case EM_ARC:		return "ARC";
128160484Sobrien    case EM_H8_300:		return "Hitachi H8/300";
128260484Sobrien    case EM_H8_300H:		return "Hitachi H8/300H";
128360484Sobrien    case EM_H8S:		return "Hitachi H8S";
128460484Sobrien    case EM_H8_500:		return "Hitachi H8/500";
128560484Sobrien    case EM_IA_64:		return "Intel IA-64";
128660484Sobrien    case EM_MIPS_X:		return "Stanford MIPS-X";
128760484Sobrien    case EM_COLDFIRE:		return "Motorola Coldfire";
128860484Sobrien    case EM_68HC12:		return "Motorola M68HC12";
128978828Sobrien    case EM_ALPHA:	return "Alpha";
129060484Sobrien    case EM_CYGNUS_D10V:        return "d10v";
129160484Sobrien    case EM_CYGNUS_D30V:        return "d30v";
129277298Sobrien    case EM_CYGNUS_ARC:		return "ARC";
129360484Sobrien    case EM_CYGNUS_M32R:	return "Mitsubishi M32r";
129460484Sobrien    case EM_CYGNUS_V850:	return "NEC v850";
129560484Sobrien    case EM_CYGNUS_MN10300:	return "mn10300";
129660484Sobrien    case EM_CYGNUS_MN10200:	return "mn10200";
129760484Sobrien    case EM_CYGNUS_FR30:	return "Fujitsu FR30";
129860484Sobrien    case EM_PJ:                 return "picoJava";
129978828Sobrien    case EM_MMA:		return "Fujitsu Multimedia Accelerator";
130078828Sobrien    case EM_PCP:		return "Siemens PCP";
130178828Sobrien    case EM_NCPU:		return "Sony nCPU embedded RISC processor";
130278828Sobrien    case EM_NDR1:		return "Denso NDR1 microprocesspr";
130378828Sobrien    case EM_STARCORE:		return "Motorola Star*Core processor";
130478828Sobrien    case EM_ME16:		return "Toyota ME16 processor";
130578828Sobrien    case EM_ST100:		return "STMicroelectronics ST100 processor";
130678828Sobrien    case EM_TINYJ:		return "Advanced Logic Corp. TinyJ embedded processor";
130778828Sobrien    case EM_FX66:		return "Siemens FX66 microcontroller";
130878828Sobrien    case EM_ST9PLUS:		return "STMicroelectronics ST9+ 8/16 bit microcontroller";
130978828Sobrien    case EM_ST7:		return "STMicroelectronics ST7 8-bit microcontroller";
131078828Sobrien    case EM_68HC16:		return "Motorola MC68HC16 Microcontroller";
131178828Sobrien    case EM_68HC11:		return "Motorola MC68HC11 Microcontroller";
131278828Sobrien    case EM_68HC08:		return "Motorola MC68HC08 Microcontroller";
131378828Sobrien    case EM_68HC05:		return "Motorola MC68HC05 Microcontroller";
131478828Sobrien    case EM_SVX:		return "Silicon Graphics SVx";
131578828Sobrien    case EM_ST19:		return "STMicroelectronics ST19 8-bit microcontroller";
131678828Sobrien    case EM_VAX:		return "Digital VAX";
131777298Sobrien    case EM_AVR:                return "Atmel AVR 8-bit microcontroller";
131877298Sobrien    case EM_CRIS:		return "Axis Communications 32-bit embedded processor";
131978828Sobrien    case EM_JAVELIN:	return "Infineon Technologies 32-bit embedded cpu";
132078828Sobrien    case EM_FIREPATH:	return "Element 14 64-bit DSP processor";
132178828Sobrien    case EM_ZSP:	return "LSI Logic's 16-bit DSP processor";
132277298Sobrien    case EM_MMIX:	        return "Donald Knuth's educational 64-bit processor";
132378828Sobrien    case EM_HUANY:	return "Harvard Universitys's machine-independent object format";
132478828Sobrien    case EM_PRISM:	return "SiTera Prism";
132577298Sobrien    case EM_X86_64:		return "Advanced Micro Devices X86-64";
132660484Sobrien    default:
132760484Sobrien      sprintf (buff, _("<unknown>: %x"), e_machine);
132860484Sobrien      return buff;
132960484Sobrien    }
133060484Sobrien}
133160484Sobrien
133277298Sobrienstatic void
133377298Sobriendecode_ARM_machine_flags (e_flags, buf)
133477298Sobrien     unsigned e_flags;
133577298Sobrien     char buf[];
133677298Sobrien{
133777298Sobrien  unsigned eabi;
133877298Sobrien  int unknown = 0;
133977298Sobrien
134077298Sobrien  eabi = EF_ARM_EABI_VERSION (e_flags);
134177298Sobrien  e_flags &= ~ EF_ARM_EABIMASK;
134277298Sobrien
134377298Sobrien  /* Handle "generic" ARM flags.  */
134477298Sobrien  if (e_flags & EF_ARM_RELEXEC)
134577298Sobrien    {
134677298Sobrien      strcat (buf, ", relocatable executable");
134777298Sobrien      e_flags &= ~ EF_ARM_RELEXEC;
134877298Sobrien    }
134977298Sobrien
135077298Sobrien  if (e_flags & EF_ARM_HASENTRY)
135177298Sobrien    {
135277298Sobrien      strcat (buf, ", has entry point");
135377298Sobrien      e_flags &= ~ EF_ARM_HASENTRY;
135477298Sobrien    }
135577298Sobrien
135677298Sobrien  /* Now handle EABI specific flags.  */
135777298Sobrien  switch (eabi)
135877298Sobrien    {
135977298Sobrien    default:
136077298Sobrien      strcat (buf, ", <unknown EABI>");
136177298Sobrien      if (e_flags)
136277298Sobrien	unknown = 1;
136377298Sobrien      break;
136477298Sobrien
136577298Sobrien    case EF_ARM_EABI_VER1:
136677298Sobrien      while (e_flags)
136777298Sobrien	{
136877298Sobrien	  unsigned flag;
136977298Sobrien
137077298Sobrien	  /* Process flags one bit at a time.  */
137177298Sobrien	  flag = e_flags & - e_flags;
137277298Sobrien	  e_flags &= ~ flag;
137377298Sobrien
137477298Sobrien	  switch (flag)
137577298Sobrien	    {
137677298Sobrien	    case EF_ARM_SYMSARESORTED: /* Conflicts with EF_INTERWORK.  */
137777298Sobrien	      strcat (buf, ", sorted symbol tables");
137877298Sobrien	      break;
137977298Sobrien
138077298Sobrien	    default:
138177298Sobrien	      unknown = 1;
138277298Sobrien	      break;
138377298Sobrien	    }
138477298Sobrien	}
138577298Sobrien      break;
138677298Sobrien
138777298Sobrien    case EF_ARM_EABI_UNKNOWN:
138877298Sobrien      while (e_flags)
138977298Sobrien	{
139077298Sobrien	  unsigned flag;
139177298Sobrien
139277298Sobrien	  /* Process flags one bit at a time.  */
139377298Sobrien	  flag = e_flags & - e_flags;
139477298Sobrien	  e_flags &= ~ flag;
139577298Sobrien
139677298Sobrien	  switch (flag)
139777298Sobrien	    {
139877298Sobrien	    case EF_INTERWORK:
139977298Sobrien	      strcat (buf, ", interworking enabled");
140077298Sobrien	      break;
140177298Sobrien
140277298Sobrien	    case EF_APCS_26:
140377298Sobrien	      strcat (buf, ", uses APCS/26");
140477298Sobrien	      break;
140577298Sobrien
140677298Sobrien	    case EF_APCS_FLOAT:
140777298Sobrien	      strcat (buf, ", uses APCS/float");
140877298Sobrien	      break;
140977298Sobrien
141077298Sobrien	    case EF_PIC:
141177298Sobrien	      strcat (buf, ", position independent");
141277298Sobrien	      break;
141377298Sobrien
141477298Sobrien	    case EF_ALIGN8:
141577298Sobrien	      strcat (buf, ", 8 bit structure alignment");
141677298Sobrien	      break;
141777298Sobrien
141877298Sobrien	    case EF_NEW_ABI:
141977298Sobrien	      strcat (buf, ", uses new ABI");
142077298Sobrien	      break;
142177298Sobrien
142277298Sobrien	    case EF_OLD_ABI:
142377298Sobrien	      strcat (buf, ", uses old ABI");
142477298Sobrien	      break;
142577298Sobrien
142677298Sobrien	    case EF_SOFT_FLOAT:
142777298Sobrien	      strcat (buf, ", software FP");
142877298Sobrien	      break;
142977298Sobrien
143077298Sobrien	    default:
143177298Sobrien	      unknown = 1;
143277298Sobrien	      break;
143377298Sobrien	    }
143477298Sobrien	}
143577298Sobrien    }
143677298Sobrien
143777298Sobrien  if (unknown)
143877298Sobrien    strcat (buf,", <unknown>");
143977298Sobrien}
144077298Sobrien
144160484Sobrienstatic char *
144260484Sobrienget_machine_flags (e_flags, e_machine)
144360484Sobrien     unsigned e_flags;
144460484Sobrien     unsigned e_machine;
144560484Sobrien{
144660484Sobrien  static char buf [1024];
144760484Sobrien
144860484Sobrien  buf[0] = '\0';
144977298Sobrien
145060484Sobrien  if (e_flags)
145160484Sobrien    {
145260484Sobrien      switch (e_machine)
145360484Sobrien	{
145460484Sobrien	default:
145560484Sobrien	  break;
145660484Sobrien
145777298Sobrien	case EM_ARM:
145877298Sobrien	  decode_ARM_machine_flags (e_flags, buf);
145977298Sobrien	  break;
146077298Sobrien
146160484Sobrien        case EM_68K:
146260484Sobrien          if (e_flags & EF_CPU32)
146360484Sobrien            strcat (buf, ", cpu32");
146460484Sobrien          break;
146560484Sobrien
146660484Sobrien	case EM_PPC:
146760484Sobrien	  if (e_flags & EF_PPC_EMB)
146860484Sobrien	    strcat (buf, ", emb");
146960484Sobrien
147060484Sobrien	  if (e_flags & EF_PPC_RELOCATABLE)
147160484Sobrien	    strcat (buf, ", relocatable");
147260484Sobrien
147360484Sobrien	  if (e_flags & EF_PPC_RELOCATABLE_LIB)
147460484Sobrien	    strcat (buf, ", relocatable-lib");
147560484Sobrien	  break;
147660484Sobrien
147760484Sobrien	case EM_CYGNUS_V850:
147860484Sobrien	  switch (e_flags & EF_V850_ARCH)
147960484Sobrien	    {
148060484Sobrien	    case E_V850E_ARCH:
148160484Sobrien	      strcat (buf, ", v850e");
148260484Sobrien	      break;
148360484Sobrien	    case E_V850EA_ARCH:
148460484Sobrien	      strcat (buf, ", v850ea");
148560484Sobrien	      break;
148660484Sobrien	    case E_V850_ARCH:
148760484Sobrien	      strcat (buf, ", v850");
148860484Sobrien	      break;
148960484Sobrien	    default:
149060484Sobrien	      strcat (buf, ", unknown v850 architecture variant");
149160484Sobrien	      break;
149260484Sobrien	    }
149360484Sobrien	  break;
149460484Sobrien
149560484Sobrien	case EM_CYGNUS_M32R:
149660484Sobrien	  if ((e_flags & EF_M32R_ARCH) == E_M32R_ARCH)
149760484Sobrien	    strcat (buf, ", m32r");
149860484Sobrien
149960484Sobrien	  break;
150060484Sobrien
150160484Sobrien	case EM_MIPS:
150278828Sobrien	case EM_MIPS_RS3_LE:
150360484Sobrien	  if (e_flags & EF_MIPS_NOREORDER)
150460484Sobrien	    strcat (buf, ", noreorder");
150560484Sobrien
150660484Sobrien	  if (e_flags & EF_MIPS_PIC)
150760484Sobrien	    strcat (buf, ", pic");
150860484Sobrien
150960484Sobrien	  if (e_flags & EF_MIPS_CPIC)
151060484Sobrien	    strcat (buf, ", cpic");
151160484Sobrien
151260484Sobrien	  if (e_flags & EF_MIPS_ABI2)
151360484Sobrien	    strcat (buf, ", abi2");
151460484Sobrien
151560484Sobrien	  if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1)
151660484Sobrien	    strcat (buf, ", mips1");
151760484Sobrien
151860484Sobrien	  if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2)
151960484Sobrien	    strcat (buf, ", mips2");
152060484Sobrien
152160484Sobrien	  if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_3)
152260484Sobrien	    strcat (buf, ", mips3");
152360484Sobrien
152460484Sobrien	  if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_4)
152560484Sobrien	    strcat (buf, ", mips4");
152677298Sobrien
152777298Sobrien	  if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_5)
152877298Sobrien	    strcat (buf, ", mips5");
152977298Sobrien
153077298Sobrien	  if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32)
153177298Sobrien	    strcat (buf, ", mips32");
153277298Sobrien
153377298Sobrien	  if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64)
153477298Sobrien	    strcat (buf, ", mips64");
153577298Sobrien
153677298Sobrien	  switch ((e_flags & EF_MIPS_MACH))
153777298Sobrien	    {
153877298Sobrien	    case E_MIPS_MACH_3900: strcat (buf, ", 3900"); break;
153977298Sobrien	    case E_MIPS_MACH_4010: strcat (buf, ", 4010"); break;
154077298Sobrien	    case E_MIPS_MACH_4100: strcat (buf, ", 4100"); break;
154177298Sobrien	    case E_MIPS_MACH_4650: strcat (buf, ", 4650"); break;
154277298Sobrien	    case E_MIPS_MACH_4111: strcat (buf, ", 4111"); break;
154377298Sobrien	    case E_MIPS_MACH_MIPS32_4K: strcat (buf, ", mips32-4k"); break;
154477298Sobrien	    case E_MIPS_MACH_SB1:  strcat (buf, ", sb1");  break;
154577298Sobrien	    default: strcat (buf, " UNKNOWN"); break;
154677298Sobrien	    }
154760484Sobrien	  break;
154860484Sobrien
154960484Sobrien	case EM_SPARCV9:
155060484Sobrien	  if (e_flags & EF_SPARC_32PLUS)
155160484Sobrien	    strcat (buf, ", v8+");
155260484Sobrien
155360484Sobrien	  if (e_flags & EF_SPARC_SUN_US1)
155460484Sobrien	    strcat (buf, ", ultrasparcI");
155560484Sobrien
155660484Sobrien	  if (e_flags & EF_SPARC_SUN_US3)
155760484Sobrien	    strcat (buf, ", ultrasparcIII");
155860484Sobrien
155960484Sobrien	  if (e_flags & EF_SPARC_HAL_R1)
156060484Sobrien	    strcat (buf, ", halr1");
156160484Sobrien
156260484Sobrien	  if (e_flags & EF_SPARC_LEDATA)
156360484Sobrien	    strcat (buf, ", ledata");
156460484Sobrien
156560484Sobrien	  if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_TSO)
156660484Sobrien	    strcat (buf, ", tso");
156760484Sobrien
156860484Sobrien	  if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_PSO)
156960484Sobrien	    strcat (buf, ", pso");
157060484Sobrien
157160484Sobrien	  if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_RMO)
157260484Sobrien	    strcat (buf, ", rmo");
157360484Sobrien	  break;
157460484Sobrien
157560484Sobrien	case EM_PARISC:
157660484Sobrien	  switch (e_flags & EF_PARISC_ARCH)
157760484Sobrien	    {
157860484Sobrien	    case EFA_PARISC_1_0:
157960484Sobrien	      strcpy (buf, ", PA-RISC 1.0");
158060484Sobrien	      break;
158160484Sobrien	    case EFA_PARISC_1_1:
158260484Sobrien	      strcpy (buf, ", PA-RISC 1.1");
158360484Sobrien	      break;
158460484Sobrien	    case EFA_PARISC_2_0:
158560484Sobrien	      strcpy (buf, ", PA-RISC 2.0");
158660484Sobrien	      break;
158760484Sobrien	    default:
158860484Sobrien	      break;
158960484Sobrien	    }
159060484Sobrien	  if (e_flags & EF_PARISC_TRAPNIL)
159160484Sobrien	    strcat (buf, ", trapnil");
159260484Sobrien	  if (e_flags & EF_PARISC_EXT)
159360484Sobrien	    strcat (buf, ", ext");
159460484Sobrien	  if (e_flags & EF_PARISC_LSB)
159560484Sobrien	    strcat (buf, ", lsb");
159660484Sobrien	  if (e_flags & EF_PARISC_WIDE)
159760484Sobrien	    strcat (buf, ", wide");
159860484Sobrien	  if (e_flags & EF_PARISC_NO_KABP)
159960484Sobrien	    strcat (buf, ", no kabp");
160060484Sobrien	  if (e_flags & EF_PARISC_LAZYSWAP)
160160484Sobrien	    strcat (buf, ", lazyswap");
160260484Sobrien	  break;
160377298Sobrien
160460484Sobrien	case EM_PJ:
160560484Sobrien	  if ((e_flags & EF_PICOJAVA_NEWCALLS) == EF_PICOJAVA_NEWCALLS)
160660484Sobrien	    strcat (buf, ", new calling convention");
160760484Sobrien
160860484Sobrien	  if ((e_flags & EF_PICOJAVA_GNUCALLS) == EF_PICOJAVA_GNUCALLS)
160960484Sobrien	    strcat (buf, ", gnu calling convention");
161060484Sobrien	  break;
161178828Sobrien
161278828Sobrien	case EM_IA_64:
161378828Sobrien	  if ((e_flags & EF_IA_64_ABI64))
161478828Sobrien	    strcat (buf, ", 64-bit");
161578828Sobrien	  else
161678828Sobrien	    strcat (buf, ", 32-bit");
161778828Sobrien	  if ((e_flags & EF_IA_64_REDUCEDFP))
161878828Sobrien	    strcat (buf, ", reduced fp model");
161978828Sobrien	  if ((e_flags & EF_IA_64_NOFUNCDESC_CONS_GP))
162078828Sobrien	    strcat (buf, ", no function descriptors, constant gp");
162178828Sobrien	  else if ((e_flags & EF_IA_64_CONS_GP))
162278828Sobrien	    strcat (buf, ", constant gp");
162378828Sobrien	  if ((e_flags & EF_IA_64_ABSOLUTE))
162478828Sobrien	    strcat (buf, ", absolute");
162578828Sobrien	  break;
162660484Sobrien	}
162760484Sobrien    }
162860484Sobrien
162960484Sobrien  return buf;
163060484Sobrien}
163160484Sobrien
163260484Sobrienstatic const char *
163360484Sobrienget_mips_segment_type (type)
163460484Sobrien     unsigned long type;
163560484Sobrien{
163660484Sobrien  switch (type)
163760484Sobrien    {
163860484Sobrien    case PT_MIPS_REGINFO:
163960484Sobrien      return "REGINFO";
164060484Sobrien    case PT_MIPS_RTPROC:
164160484Sobrien      return "RTPROC";
164260484Sobrien    case PT_MIPS_OPTIONS:
164360484Sobrien      return "OPTIONS";
164460484Sobrien    default:
164560484Sobrien      break;
164660484Sobrien    }
164760484Sobrien
164860484Sobrien  return NULL;
164960484Sobrien}
165060484Sobrien
165160484Sobrienstatic const char *
165260484Sobrienget_parisc_segment_type (type)
165360484Sobrien     unsigned long type;
165460484Sobrien{
165560484Sobrien  switch (type)
165660484Sobrien    {
165760484Sobrien    case PT_HP_TLS:		return "HP_TLS";
165860484Sobrien    case PT_HP_CORE_NONE:	return "HP_CORE_NONE";
165960484Sobrien    case PT_HP_CORE_VERSION:	return "HP_CORE_VERSION";
166060484Sobrien    case PT_HP_CORE_KERNEL:	return "HP_CORE_KERNEL";
166160484Sobrien    case PT_HP_CORE_COMM:	return "HP_CORE_COMM";
166260484Sobrien    case PT_HP_CORE_PROC:	return "HP_CORE_PROC";
166360484Sobrien    case PT_HP_CORE_LOADABLE:	return "HP_CORE_LOADABLE";
166460484Sobrien    case PT_HP_CORE_STACK:	return "HP_CORE_STACK";
166560484Sobrien    case PT_HP_CORE_SHM:	return "HP_CORE_SHM";
166660484Sobrien    case PT_HP_CORE_MMF:	return "HP_CORE_MMF";
166760484Sobrien    case PT_HP_PARALLEL:	return "HP_PARALLEL";
166860484Sobrien    case PT_HP_FASTBIND:	return "HP_FASTBIND";
166960484Sobrien    case PT_PARISC_ARCHEXT:	return "PARISC_ARCHEXT";
167060484Sobrien    case PT_PARISC_UNWIND:	return "PARISC_UNWIND";
167160484Sobrien    default:
167260484Sobrien      break;
167360484Sobrien    }
167460484Sobrien
167560484Sobrien  return NULL;
167660484Sobrien}
167760484Sobrien
167860484Sobrienstatic const char *
167978828Sobrienget_ia64_segment_type (type)
168078828Sobrien     unsigned long type;
168178828Sobrien{
168278828Sobrien  switch (type)
168378828Sobrien    {
168478828Sobrien    case PT_IA_64_ARCHEXT:	return "IA_64_ARCHEXT";
168578828Sobrien    case PT_IA_64_UNWIND:	return "IA_64_UNWIND";
168678828Sobrien    default:
168778828Sobrien      break;
168878828Sobrien    }
168978828Sobrien
169078828Sobrien  return NULL;
169178828Sobrien}
169278828Sobrien
169378828Sobrienstatic const char *
169460484Sobrienget_segment_type (p_type)
169560484Sobrien     unsigned long p_type;
169660484Sobrien{
169760484Sobrien  static char buff [32];
169860484Sobrien
169960484Sobrien  switch (p_type)
170060484Sobrien    {
170160484Sobrien    case PT_NULL:       return "NULL";
170260484Sobrien    case PT_LOAD:       return "LOAD";
170360484Sobrien    case PT_DYNAMIC:	return "DYNAMIC";
170460484Sobrien    case PT_INTERP:     return "INTERP";
170560484Sobrien    case PT_NOTE:       return "NOTE";
170660484Sobrien    case PT_SHLIB:      return "SHLIB";
170760484Sobrien    case PT_PHDR:       return "PHDR";
170860484Sobrien
170960484Sobrien    default:
171060484Sobrien      if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
171160484Sobrien	{
171260484Sobrien	  const char * result;
171360484Sobrien
171460484Sobrien	  switch (elf_header.e_machine)
171560484Sobrien	    {
171660484Sobrien	    case EM_MIPS:
171778828Sobrien	    case EM_MIPS_RS3_LE:
171860484Sobrien	      result = get_mips_segment_type (p_type);
171960484Sobrien	      break;
172060484Sobrien	    case EM_PARISC:
172160484Sobrien	      result = get_parisc_segment_type (p_type);
172260484Sobrien	      break;
172378828Sobrien	    case EM_IA_64:
172478828Sobrien	      result = get_ia64_segment_type (p_type);
172578828Sobrien	      break;
172660484Sobrien	    default:
172760484Sobrien	      result = NULL;
172860484Sobrien	      break;
172960484Sobrien	    }
173060484Sobrien
173160484Sobrien	  if (result != NULL)
173260484Sobrien	    return result;
173360484Sobrien
173460484Sobrien	  sprintf (buff, "LOPROC+%lx", p_type - PT_LOPROC);
173560484Sobrien	}
173660484Sobrien      else if ((p_type >= PT_LOOS) && (p_type <= PT_HIOS))
173760484Sobrien	{
173860484Sobrien	  const char * result;
173960484Sobrien
174060484Sobrien	  switch (elf_header.e_machine)
174160484Sobrien	    {
174260484Sobrien	    case EM_PARISC:
174360484Sobrien	      result = get_parisc_segment_type (p_type);
174460484Sobrien	      break;
174560484Sobrien	    default:
174660484Sobrien	      result = NULL;
174760484Sobrien	      break;
174860484Sobrien	    }
174960484Sobrien
175060484Sobrien	  if (result != NULL)
175160484Sobrien	    return result;
175260484Sobrien
175360484Sobrien	  sprintf (buff, "LOOS+%lx", p_type - PT_LOOS);
175460484Sobrien	}
175560484Sobrien      else
175660484Sobrien	sprintf (buff, _("<unknown>: %lx"), p_type);
175760484Sobrien
175860484Sobrien      return buff;
175960484Sobrien    }
176060484Sobrien}
176160484Sobrien
176260484Sobrienstatic const char *
176360484Sobrienget_mips_section_type_name (sh_type)
176460484Sobrien     unsigned int sh_type;
176560484Sobrien{
176660484Sobrien  switch (sh_type)
176760484Sobrien    {
176860484Sobrien    case SHT_MIPS_LIBLIST:       return "MIPS_LIBLIST";
176960484Sobrien    case SHT_MIPS_MSYM:          return "MIPS_MSYM";
177060484Sobrien    case SHT_MIPS_CONFLICT:      return "MIPS_CONFLICT";
177160484Sobrien    case SHT_MIPS_GPTAB:         return "MIPS_GPTAB";
177260484Sobrien    case SHT_MIPS_UCODE:         return "MIPS_UCODE";
177360484Sobrien    case SHT_MIPS_DEBUG:         return "MIPS_DEBUG";
177460484Sobrien    case SHT_MIPS_REGINFO:       return "MIPS_REGINFO";
177560484Sobrien    case SHT_MIPS_PACKAGE:       return "MIPS_PACKAGE";
177660484Sobrien    case SHT_MIPS_PACKSYM:       return "MIPS_PACKSYM";
177760484Sobrien    case SHT_MIPS_RELD:          return "MIPS_RELD";
177860484Sobrien    case SHT_MIPS_IFACE:         return "MIPS_IFACE";
177960484Sobrien    case SHT_MIPS_CONTENT:       return "MIPS_CONTENT";
178060484Sobrien    case SHT_MIPS_OPTIONS:       return "MIPS_OPTIONS";
178160484Sobrien    case SHT_MIPS_SHDR:          return "MIPS_SHDR";
178260484Sobrien    case SHT_MIPS_FDESC:         return "MIPS_FDESC";
178360484Sobrien    case SHT_MIPS_EXTSYM:        return "MIPS_EXTSYM";
178460484Sobrien    case SHT_MIPS_DENSE:         return "MIPS_DENSE";
178560484Sobrien    case SHT_MIPS_PDESC:         return "MIPS_PDESC";
178660484Sobrien    case SHT_MIPS_LOCSYM:        return "MIPS_LOCSYM";
178760484Sobrien    case SHT_MIPS_AUXSYM:        return "MIPS_AUXSYM";
178860484Sobrien    case SHT_MIPS_OPTSYM:        return "MIPS_OPTSYM";
178960484Sobrien    case SHT_MIPS_LOCSTR:        return "MIPS_LOCSTR";
179060484Sobrien    case SHT_MIPS_LINE:          return "MIPS_LINE";
179160484Sobrien    case SHT_MIPS_RFDESC:        return "MIPS_RFDESC";
179260484Sobrien    case SHT_MIPS_DELTASYM:      return "MIPS_DELTASYM";
179360484Sobrien    case SHT_MIPS_DELTAINST:     return "MIPS_DELTAINST";
179460484Sobrien    case SHT_MIPS_DELTACLASS:    return "MIPS_DELTACLASS";
179560484Sobrien    case SHT_MIPS_DWARF:         return "MIPS_DWARF";
179660484Sobrien    case SHT_MIPS_DELTADECL:     return "MIPS_DELTADECL";
179760484Sobrien    case SHT_MIPS_SYMBOL_LIB:    return "MIPS_SYMBOL_LIB";
179860484Sobrien    case SHT_MIPS_EVENTS:        return "MIPS_EVENTS";
179960484Sobrien    case SHT_MIPS_TRANSLATE:     return "MIPS_TRANSLATE";
180060484Sobrien    case SHT_MIPS_PIXIE:         return "MIPS_PIXIE";
180160484Sobrien    case SHT_MIPS_XLATE:         return "MIPS_XLATE";
180260484Sobrien    case SHT_MIPS_XLATE_DEBUG:   return "MIPS_XLATE_DEBUG";
180360484Sobrien    case SHT_MIPS_WHIRL:         return "MIPS_WHIRL";
180460484Sobrien    case SHT_MIPS_EH_REGION:     return "MIPS_EH_REGION";
180560484Sobrien    case SHT_MIPS_XLATE_OLD:     return "MIPS_XLATE_OLD";
180660484Sobrien    case SHT_MIPS_PDR_EXCEPTION: return "MIPS_PDR_EXCEPTION";
180760484Sobrien    default:
180860484Sobrien      break;
180960484Sobrien    }
181060484Sobrien  return NULL;
181160484Sobrien}
181260484Sobrien
181360484Sobrienstatic const char *
181460484Sobrienget_parisc_section_type_name (sh_type)
181560484Sobrien     unsigned int sh_type;
181660484Sobrien{
181760484Sobrien  switch (sh_type)
181860484Sobrien    {
181960484Sobrien    case SHT_PARISC_EXT:	return "PARISC_EXT";
182060484Sobrien    case SHT_PARISC_UNWIND:	return "PARISC_UNWIND";
182160484Sobrien    case SHT_PARISC_DOC:	return "PARISC_DOC";
182260484Sobrien    default:
182360484Sobrien      break;
182460484Sobrien    }
182560484Sobrien  return NULL;
182660484Sobrien}
182760484Sobrien
182860484Sobrienstatic const char *
182978828Sobrienget_ia64_section_type_name (sh_type)
183078828Sobrien     unsigned int sh_type;
183178828Sobrien{
183278828Sobrien  switch (sh_type)
183378828Sobrien    {
183478828Sobrien    case SHT_IA_64_EXT:		return "IA_64_EXT";
183578828Sobrien    case SHT_IA_64_UNWIND:	return "IA_64_UNWIND";
183678828Sobrien    default:
183778828Sobrien      break;
183878828Sobrien    }
183978828Sobrien  return NULL;
184078828Sobrien}
184178828Sobrien
184278828Sobrienstatic const char *
184360484Sobrienget_section_type_name (sh_type)
184460484Sobrien     unsigned int sh_type;
184560484Sobrien{
184660484Sobrien  static char buff [32];
184760484Sobrien
184860484Sobrien  switch (sh_type)
184960484Sobrien    {
185060484Sobrien    case SHT_NULL:		return "NULL";
185160484Sobrien    case SHT_PROGBITS:		return "PROGBITS";
185260484Sobrien    case SHT_SYMTAB:		return "SYMTAB";
185360484Sobrien    case SHT_STRTAB:		return "STRTAB";
185460484Sobrien    case SHT_RELA:		return "RELA";
185560484Sobrien    case SHT_HASH:		return "HASH";
185660484Sobrien    case SHT_DYNAMIC:		return "DYNAMIC";
185760484Sobrien    case SHT_NOTE:		return "NOTE";
185860484Sobrien    case SHT_NOBITS:		return "NOBITS";
185960484Sobrien    case SHT_REL:		return "REL";
186060484Sobrien    case SHT_SHLIB:		return "SHLIB";
186160484Sobrien    case SHT_DYNSYM:		return "DYNSYM";
186260484Sobrien    case SHT_INIT_ARRAY:	return "INIT_ARRAY";
186360484Sobrien    case SHT_FINI_ARRAY:	return "FINI_ARRAY";
186460484Sobrien    case SHT_PREINIT_ARRAY:	return "PREINIT_ARRAY";
186577298Sobrien    case SHT_GROUP:		return "GROUP";
186677298Sobrien    case SHT_SYMTAB_SHNDX:	return "SYMTAB SECTION INDICIES";
186760484Sobrien    case SHT_GNU_verdef:	return "VERDEF";
186860484Sobrien    case SHT_GNU_verneed:	return "VERNEED";
186960484Sobrien    case SHT_GNU_versym:	return "VERSYM";
187060484Sobrien    case 0x6ffffff0:	        return "VERSYM";
187160484Sobrien    case 0x6ffffffc:	        return "VERDEF";
187260484Sobrien    case 0x7ffffffd:		return "AUXILIARY";
187360484Sobrien    case 0x7fffffff:		return "FILTER";
187460484Sobrien
187560484Sobrien    default:
187660484Sobrien      if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC))
187760484Sobrien	{
187860484Sobrien	  const char * result;
187960484Sobrien
188060484Sobrien	  switch (elf_header.e_machine)
188160484Sobrien	    {
188260484Sobrien	    case EM_MIPS:
188378828Sobrien	    case EM_MIPS_RS3_LE:
188460484Sobrien	      result = get_mips_section_type_name (sh_type);
188560484Sobrien	      break;
188660484Sobrien	    case EM_PARISC:
188760484Sobrien	      result = get_parisc_section_type_name (sh_type);
188860484Sobrien	      break;
188978828Sobrien	    case EM_IA_64:
189078828Sobrien	      result = get_ia64_section_type_name (sh_type);
189178828Sobrien	      break;
189260484Sobrien	    default:
189360484Sobrien	      result = NULL;
189460484Sobrien	      break;
189560484Sobrien	    }
189660484Sobrien
189760484Sobrien	  if (result != NULL)
189860484Sobrien	    return result;
189960484Sobrien
190060484Sobrien	  sprintf (buff, "SHT_LOPROC+%x", sh_type - SHT_LOPROC);
190160484Sobrien	}
190260484Sobrien      else if ((sh_type >= SHT_LOOS) && (sh_type <= SHT_HIOS))
190360484Sobrien	sprintf (buff, "SHT_LOOS+%x", sh_type - SHT_LOOS);
190460484Sobrien      else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER))
190560484Sobrien	sprintf (buff, "SHT_LOUSER+%x", sh_type - SHT_LOUSER);
190660484Sobrien      else
190760484Sobrien	sprintf (buff, _("<unknown>: %x"), sh_type);
190860484Sobrien
190960484Sobrien      return buff;
191060484Sobrien    }
191160484Sobrien}
191260484Sobrien
191360484Sobrienstruct option options [] =
191460484Sobrien{
191560484Sobrien  {"all",              no_argument, 0, 'a'},
191660484Sobrien  {"file-header",      no_argument, 0, 'h'},
191760484Sobrien  {"program-headers",  no_argument, 0, 'l'},
191860484Sobrien  {"headers",          no_argument, 0, 'e'},
191960484Sobrien  {"histogram",        no_argument, 0, 'I'},
192060484Sobrien  {"segments",         no_argument, 0, 'l'},
192160484Sobrien  {"sections",         no_argument, 0, 'S'},
192260484Sobrien  {"section-headers",  no_argument, 0, 'S'},
192360484Sobrien  {"symbols",          no_argument, 0, 's'},
192460484Sobrien  {"syms",             no_argument, 0, 's'},
192560484Sobrien  {"relocs",           no_argument, 0, 'r'},
192660484Sobrien  {"notes",            no_argument, 0, 'n'},
192760484Sobrien  {"dynamic",          no_argument, 0, 'd'},
192860484Sobrien  {"arch-specific",    no_argument, 0, 'A'},
192960484Sobrien  {"version-info",     no_argument, 0, 'V'},
193060484Sobrien  {"use-dynamic",      no_argument, 0, 'D'},
193160484Sobrien  {"hex-dump",         required_argument, 0, 'x'},
193260484Sobrien  {"debug-dump",       optional_argument, 0, 'w'},
193378828Sobrien  {"unwind",	       no_argument, 0, 'u'},
193460484Sobrien#ifdef SUPPORT_DISASSEMBLY
193560484Sobrien  {"instruction-dump", required_argument, 0, 'i'},
193660484Sobrien#endif
193760484Sobrien
193860484Sobrien  {"version",          no_argument, 0, 'v'},
193960484Sobrien  {"help",             no_argument, 0, 'H'},
194060484Sobrien  {0,                  no_argument, 0, 0}
194160484Sobrien};
194260484Sobrien
194360484Sobrienstatic void
194460484Sobrienusage ()
194560484Sobrien{
194660484Sobrien  fprintf (stdout, _("Usage: readelf {options} elf-file(s)\n"));
194760484Sobrien  fprintf (stdout, _("  Options are:\n"));
194860484Sobrien  fprintf (stdout, _("  -a or --all               Equivalent to: -h -l -S -s -r -d -V -A -I\n"));
194960484Sobrien  fprintf (stdout, _("  -h or --file-header       Display the ELF file header\n"));
195060484Sobrien  fprintf (stdout, _("  -l or --program-headers or --segments\n"));
195160484Sobrien  fprintf (stdout, _("                            Display the program headers\n"));
195260484Sobrien  fprintf (stdout, _("  -S or --section-headers or --sections\n"));
195360484Sobrien  fprintf (stdout, _("                            Display the sections' header\n"));
195460484Sobrien  fprintf (stdout, _("  -e or --headers           Equivalent to: -h -l -S\n"));
195560484Sobrien  fprintf (stdout, _("  -s or --syms or --symbols Display the symbol table\n"));
195660484Sobrien  fprintf (stdout, _("  -n or --notes             Display the core notes (if present)\n"));
195760484Sobrien  fprintf (stdout, _("  -r or --relocs            Display the relocations (if present)\n"));
195878828Sobrien  fprintf (stdout, _("  -u or --unwind            Display the unwind info (if present)\n"));
195960484Sobrien  fprintf (stdout, _("  -d or --dynamic           Display the dynamic segment (if present)\n"));
196060484Sobrien  fprintf (stdout, _("  -V or --version-info      Display the version sections (if present)\n"));
196160484Sobrien  fprintf (stdout, _("  -A or --arch-specific     Display architecture specific information (if any).\n"));
196260484Sobrien  fprintf (stdout, _("  -D or --use-dynamic       Use the dynamic section info when displaying symbols\n"));
196360484Sobrien  fprintf (stdout, _("  -x <number> or --hex-dump=<number>\n"));
196460484Sobrien  fprintf (stdout, _("                            Dump the contents of section <number>\n"));
196577298Sobrien  fprintf (stdout, _("  -w[liaprf] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=frames]\n"));
196660484Sobrien  fprintf (stdout, _("                            Display the contents of DWARF2 debug sections\n"));
196760484Sobrien#ifdef SUPPORT_DISASSEMBLY
196860484Sobrien  fprintf (stdout, _("  -i <number> or --instruction-dump=<number>\n"));
196960484Sobrien  fprintf (stdout, _("                            Disassemble the contents of section <number>\n"));
197060484Sobrien#endif
197160484Sobrien  fprintf (stdout, _("  -I or --histogram         Display histogram of bucket list lengths\n"));
197260484Sobrien  fprintf (stdout, _("  -v or --version           Display the version number of readelf\n"));
197360484Sobrien  fprintf (stdout, _("  -H or --help              Display this information\n"));
197460484Sobrien  fprintf (stdout, _("Report bugs to %s\n"), REPORT_BUGS_TO);
197560484Sobrien
197660484Sobrien  exit (0);
197760484Sobrien}
197860484Sobrien
197960484Sobrienstatic void
198060484Sobrienrequest_dump (section, type)
198160484Sobrien     unsigned int section;
198260484Sobrien     char         type;
198360484Sobrien{
198460484Sobrien  if (section >= num_dump_sects)
198560484Sobrien    {
198660484Sobrien      char * new_dump_sects;
198760484Sobrien
198860484Sobrien      new_dump_sects = (char *) calloc (section + 1, 1);
198960484Sobrien
199060484Sobrien      if (new_dump_sects == NULL)
199160484Sobrien	error (_("Out of memory allocating dump request table."));
199260484Sobrien      else
199360484Sobrien	{
199460484Sobrien	  /* Copy current flag settings.  */
199560484Sobrien	  memcpy (new_dump_sects, dump_sects, num_dump_sects);
199660484Sobrien
199760484Sobrien	  free (dump_sects);
199860484Sobrien
199960484Sobrien	  dump_sects = new_dump_sects;
200060484Sobrien	  num_dump_sects = section + 1;
200160484Sobrien	}
200260484Sobrien    }
200360484Sobrien
200460484Sobrien  if (dump_sects)
200560484Sobrien    dump_sects [section] |= type;
200660484Sobrien
200760484Sobrien  return;
200860484Sobrien}
200960484Sobrien
201060484Sobrienstatic void
201160484Sobrienparse_args (argc, argv)
201260484Sobrien     int argc;
201360484Sobrien     char ** argv;
201460484Sobrien{
201560484Sobrien  int c;
201660484Sobrien
201760484Sobrien  if (argc < 2)
201860484Sobrien    usage ();
201960484Sobrien
202060484Sobrien  while ((c = getopt_long
202178828Sobrien	  (argc, argv, "ersuahnldSDAIw::x:i:vV", options, NULL)) != EOF)
202260484Sobrien    {
202360484Sobrien      char *    cp;
202460484Sobrien      int	section;
202560484Sobrien
202660484Sobrien      switch (c)
202760484Sobrien	{
202860484Sobrien	case 0:
202960484Sobrien	  /* Long options.  */
203060484Sobrien	  break;
203160484Sobrien	case 'H':
203260484Sobrien	  usage ();
203360484Sobrien	  break;
203460484Sobrien
203560484Sobrien	case 'a':
203660484Sobrien	  do_syms ++;
203760484Sobrien	  do_reloc ++;
203878828Sobrien	  do_unwind ++;
203960484Sobrien	  do_dynamic ++;
204060484Sobrien	  do_header ++;
204160484Sobrien	  do_sections ++;
204260484Sobrien	  do_segments ++;
204360484Sobrien	  do_version ++;
204460484Sobrien	  do_histogram ++;
204560484Sobrien	  do_arch ++;
204660484Sobrien	  do_notes ++;
204760484Sobrien	  break;
204860484Sobrien	case 'e':
204960484Sobrien	  do_header ++;
205060484Sobrien	  do_sections ++;
205160484Sobrien	  do_segments ++;
205260484Sobrien	  break;
205360484Sobrien	case 'A':
205460484Sobrien	  do_arch ++;
205560484Sobrien	  break;
205660484Sobrien	case 'D':
205760484Sobrien	  do_using_dynamic ++;
205860484Sobrien	  break;
205960484Sobrien	case 'r':
206060484Sobrien	  do_reloc ++;
206160484Sobrien	  break;
206278828Sobrien	case 'u':
206378828Sobrien	  do_unwind ++;
206478828Sobrien	  break;
206560484Sobrien	case 'h':
206660484Sobrien	  do_header ++;
206760484Sobrien	  break;
206860484Sobrien	case 'l':
206960484Sobrien	  do_segments ++;
207060484Sobrien	  break;
207160484Sobrien	case 's':
207260484Sobrien	  do_syms ++;
207360484Sobrien	  break;
207460484Sobrien	case 'S':
207560484Sobrien	  do_sections ++;
207660484Sobrien	  break;
207760484Sobrien	case 'd':
207860484Sobrien	  do_dynamic ++;
207960484Sobrien	  break;
208060484Sobrien	case 'I':
208160484Sobrien	  do_histogram ++;
208260484Sobrien	  break;
208360484Sobrien	case 'n':
208460484Sobrien	  do_notes ++;
208560484Sobrien	  break;
208660484Sobrien	case 'x':
208760484Sobrien	  do_dump ++;
208860484Sobrien	  section = strtoul (optarg, & cp, 0);
208960484Sobrien	  if (! * cp && section >= 0)
209060484Sobrien	    {
209160484Sobrien	      request_dump (section, HEX_DUMP);
209260484Sobrien	      break;
209360484Sobrien	    }
209460484Sobrien	  goto oops;
209560484Sobrien	case 'w':
209660484Sobrien	  do_dump ++;
209760484Sobrien	  if (optarg == 0)
209860484Sobrien	    do_debugging = 1;
209960484Sobrien	  else
210060484Sobrien	    {
210160484Sobrien	      do_debugging = 0;
210260484Sobrien	      switch (optarg[0])
210360484Sobrien		{
210460484Sobrien		case 'i':
210560484Sobrien		case 'I':
210660484Sobrien		  do_debug_info = 1;
210760484Sobrien		  break;
210860484Sobrien
210960484Sobrien		case 'a':
211060484Sobrien		case 'A':
211160484Sobrien		  do_debug_abbrevs = 1;
211260484Sobrien		  break;
211360484Sobrien
211460484Sobrien		case 'l':
211560484Sobrien		case 'L':
211660484Sobrien		  do_debug_lines = 1;
211760484Sobrien		  break;
211860484Sobrien
211960484Sobrien		case 'p':
212060484Sobrien		case 'P':
212160484Sobrien		  do_debug_pubnames = 1;
212260484Sobrien		  break;
212360484Sobrien
212460484Sobrien		case 'r':
212560484Sobrien		case 'R':
212660484Sobrien		  do_debug_aranges = 1;
212760484Sobrien		  break;
212860484Sobrien
212978828Sobrien		case 'F':
213078828Sobrien		  do_debug_frames_interp = 1;
213177298Sobrien		case 'f':
213277298Sobrien		  do_debug_frames = 1;
213377298Sobrien		  break;
213477298Sobrien
213560484Sobrien		default:
213660484Sobrien		  warn (_("Unrecognised debug option '%s'\n"), optarg);
213760484Sobrien		  break;
213860484Sobrien		}
213960484Sobrien	    }
214060484Sobrien	  break;
214160484Sobrien#ifdef SUPPORT_DISASSEMBLY
214260484Sobrien	case 'i':
214360484Sobrien	  do_dump ++;
214460484Sobrien	  section = strtoul (optarg, & cp, 0);
214560484Sobrien	  if (! * cp && section >= 0)
214660484Sobrien	    {
214760484Sobrien	      request_dump (section, DISASS_DUMP);
214860484Sobrien	      break;
214960484Sobrien	    }
215060484Sobrien	  goto oops;
215160484Sobrien#endif
215260484Sobrien	case 'v':
215360484Sobrien	  print_version (program_name);
215460484Sobrien	  break;
215560484Sobrien	case 'V':
215660484Sobrien	  do_version ++;
215760484Sobrien	  break;
215860484Sobrien	default:
215960484Sobrien	oops:
216060484Sobrien	  /* xgettext:c-format */
216160484Sobrien	  error (_("Invalid option '-%c'\n"), c);
216260484Sobrien	  /* Drop through.  */
216360484Sobrien	case '?':
216460484Sobrien	  usage ();
216560484Sobrien	}
216660484Sobrien    }
216760484Sobrien
216878828Sobrien  if (!do_dynamic && !do_syms && !do_reloc && !do_unwind && !do_sections
216960484Sobrien      && !do_segments && !do_header && !do_dump && !do_version
217060484Sobrien      && !do_histogram && !do_debugging && !do_arch && !do_notes)
217160484Sobrien    usage ();
217260484Sobrien  else if (argc < 3)
217360484Sobrien    {
217460484Sobrien      warn (_("Nothing to do.\n"));
217560484Sobrien      usage();
217660484Sobrien    }
217760484Sobrien}
217860484Sobrien
217960484Sobrienstatic const char *
218060484Sobrienget_elf_class (elf_class)
218160484Sobrien     unsigned char elf_class;
218260484Sobrien{
218360484Sobrien  static char buff [32];
218460484Sobrien
218560484Sobrien  switch (elf_class)
218660484Sobrien    {
218760484Sobrien    case ELFCLASSNONE: return _("none");
218860484Sobrien    case ELFCLASS32:   return _("ELF32");
218960484Sobrien    case ELFCLASS64:   return _("ELF64");
219060484Sobrien    default:
219160484Sobrien      sprintf (buff, _("<unknown: %x>"), elf_class);
219260484Sobrien      return buff;
219360484Sobrien    }
219460484Sobrien}
219560484Sobrien
219660484Sobrienstatic const char *
219760484Sobrienget_data_encoding (encoding)
219860484Sobrien     unsigned char encoding;
219960484Sobrien{
220060484Sobrien  static char buff [32];
220160484Sobrien
220260484Sobrien  switch (encoding)
220360484Sobrien    {
220460484Sobrien    case ELFDATANONE: return _("none");
220560484Sobrien    case ELFDATA2LSB: return _("2's complement, little endian");
220660484Sobrien    case ELFDATA2MSB: return _("2's complement, big endian");
220760484Sobrien    default:
220860484Sobrien      sprintf (buff, _("<unknown: %x>"), encoding);
220960484Sobrien      return buff;
221060484Sobrien    }
221160484Sobrien}
221260484Sobrien
221360484Sobrienstatic const char *
221460484Sobrienget_osabi_name (osabi)
221560484Sobrien     unsigned char osabi;
221660484Sobrien{
221760484Sobrien  static char buff [32];
221860484Sobrien
221960484Sobrien  switch (osabi)
222060484Sobrien    {
222161843Sobrien    case ELFOSABI_NONE:       return _("UNIX - System V");
222260484Sobrien    case ELFOSABI_HPUX:       return _("UNIX - HP-UX");
222361843Sobrien    case ELFOSABI_NETBSD:     return _("UNIX - NetBSD");
222460484Sobrien    case ELFOSABI_LINUX:      return _("UNIX - Linux");
222561843Sobrien    case ELFOSABI_HURD:       return _("GNU/Hurd");
222661843Sobrien    case ELFOSABI_SOLARIS:    return _("UNIX - Solaris");
222777298Sobrien    case ELFOSABI_AIX:        return _("UNIX - AIX");
222861843Sobrien    case ELFOSABI_IRIX:       return _("UNIX - IRIX");
222961843Sobrien    case ELFOSABI_FREEBSD:    return _("UNIX - FreeBSD");
223061843Sobrien    case ELFOSABI_TRU64:      return _("UNIX - TRU64");
223161843Sobrien    case ELFOSABI_MODESTO:    return _("Novell - Modesto");
223261843Sobrien    case ELFOSABI_OPENBSD:    return _("UNIX - OpenBSD");
223360484Sobrien    case ELFOSABI_STANDALONE: return _("Standalone App");
223460484Sobrien    case ELFOSABI_ARM:        return _("ARM");
223560484Sobrien    default:
223660484Sobrien      sprintf (buff, _("<unknown: %x>"), osabi);
223760484Sobrien      return buff;
223860484Sobrien    }
223960484Sobrien}
224060484Sobrien
224160484Sobrien/* Decode the data held in 'elf_header'.  */
224260484Sobrienstatic int
224360484Sobrienprocess_file_header ()
224460484Sobrien{
224560484Sobrien  if (   elf_header.e_ident [EI_MAG0] != ELFMAG0
224660484Sobrien      || elf_header.e_ident [EI_MAG1] != ELFMAG1
224760484Sobrien      || elf_header.e_ident [EI_MAG2] != ELFMAG2
224860484Sobrien      || elf_header.e_ident [EI_MAG3] != ELFMAG3)
224960484Sobrien    {
225060484Sobrien      error
225160484Sobrien	(_("Not an ELF file - it has the wrong magic bytes at the start\n"));
225260484Sobrien      return 0;
225360484Sobrien    }
225460484Sobrien
225560484Sobrien  if (do_header)
225660484Sobrien    {
225760484Sobrien      int i;
225860484Sobrien
225960484Sobrien      printf (_("ELF Header:\n"));
226060484Sobrien      printf (_("  Magic:   "));
226160484Sobrien      for (i = 0; i < EI_NIDENT; i ++)
226260484Sobrien	printf ("%2.2x ", elf_header.e_ident [i]);
226360484Sobrien      printf ("\n");
226460484Sobrien      printf (_("  Class:                             %s\n"),
226560484Sobrien	      get_elf_class (elf_header.e_ident [EI_CLASS]));
226660484Sobrien      printf (_("  Data:                              %s\n"),
226760484Sobrien	      get_data_encoding (elf_header.e_ident [EI_DATA]));
226860484Sobrien      printf (_("  Version:                           %d %s\n"),
226960484Sobrien	      elf_header.e_ident [EI_VERSION],
227060484Sobrien	      (elf_header.e_ident [EI_VERSION] == EV_CURRENT
227160484Sobrien	       ? "(current)"
227260484Sobrien	       : (elf_header.e_ident [EI_VERSION] != EV_NONE
227360484Sobrien		  ? "<unknown: %lx>"
227460484Sobrien		  : "")));
227560484Sobrien      printf (_("  OS/ABI:                            %s\n"),
227660484Sobrien	      get_osabi_name (elf_header.e_ident [EI_OSABI]));
227760484Sobrien      printf (_("  ABI Version:                       %d\n"),
227860484Sobrien	      elf_header.e_ident [EI_ABIVERSION]);
227960484Sobrien      printf (_("  Type:                              %s\n"),
228060484Sobrien	      get_file_type (elf_header.e_type));
228160484Sobrien      printf (_("  Machine:                           %s\n"),
228260484Sobrien	      get_machine_name (elf_header.e_machine));
228360484Sobrien      printf (_("  Version:                           0x%lx\n"),
228460484Sobrien	      (unsigned long) elf_header.e_version);
228577298Sobrien
228660484Sobrien      printf (_("  Entry point address:               "));
228760484Sobrien      print_vma ((bfd_vma) elf_header.e_entry, PREFIX_HEX);
228860484Sobrien      printf (_("\n  Start of program headers:          "));
228960484Sobrien      print_vma ((bfd_vma) elf_header.e_phoff, DEC);
229060484Sobrien      printf (_(" (bytes into file)\n  Start of section headers:          "));
229160484Sobrien      print_vma ((bfd_vma) elf_header.e_shoff, DEC);
229260484Sobrien      printf (_(" (bytes into file)\n"));
229377298Sobrien
229460484Sobrien      printf (_("  Flags:                             0x%lx%s\n"),
229560484Sobrien	      (unsigned long) elf_header.e_flags,
229660484Sobrien	      get_machine_flags (elf_header.e_flags, elf_header.e_machine));
229760484Sobrien      printf (_("  Size of this header:               %ld (bytes)\n"),
229860484Sobrien	      (long) elf_header.e_ehsize);
229960484Sobrien      printf (_("  Size of program headers:           %ld (bytes)\n"),
230060484Sobrien	      (long) elf_header.e_phentsize);
230160484Sobrien      printf (_("  Number of program headers:         %ld\n"),
230260484Sobrien	      (long) elf_header.e_phnum);
230360484Sobrien      printf (_("  Size of section headers:           %ld (bytes)\n"),
230460484Sobrien	      (long) elf_header.e_shentsize);
230560484Sobrien      printf (_("  Number of section headers:         %ld\n"),
230660484Sobrien	      (long) elf_header.e_shnum);
230760484Sobrien      printf (_("  Section header string table index: %ld\n"),
230860484Sobrien	      (long) elf_header.e_shstrndx);
230960484Sobrien    }
231060484Sobrien
231160484Sobrien  return 1;
231260484Sobrien}
231360484Sobrien
231460484Sobrien
231560484Sobrienstatic int
231660484Sobrienget_32bit_program_headers (file, program_headers)
231760484Sobrien     FILE * file;
231860484Sobrien     Elf_Internal_Phdr * program_headers;
231960484Sobrien{
232060484Sobrien  Elf32_External_Phdr * phdrs;
232160484Sobrien  Elf32_External_Phdr * external;
232260484Sobrien  Elf32_Internal_Phdr * internal;
232360484Sobrien  unsigned int          i;
232460484Sobrien
232560484Sobrien  GET_DATA_ALLOC (elf_header.e_phoff,
232660484Sobrien		  elf_header.e_phentsize * elf_header.e_phnum,
232760484Sobrien		  phdrs, Elf32_External_Phdr *, "program headers");
232860484Sobrien
232960484Sobrien  for (i = 0, internal = program_headers, external = phdrs;
233060484Sobrien       i < elf_header.e_phnum;
233160484Sobrien       i ++, internal ++, external ++)
233260484Sobrien    {
233360484Sobrien      internal->p_type   = BYTE_GET (external->p_type);
233460484Sobrien      internal->p_offset = BYTE_GET (external->p_offset);
233560484Sobrien      internal->p_vaddr  = BYTE_GET (external->p_vaddr);
233660484Sobrien      internal->p_paddr  = BYTE_GET (external->p_paddr);
233760484Sobrien      internal->p_filesz = BYTE_GET (external->p_filesz);
233860484Sobrien      internal->p_memsz  = BYTE_GET (external->p_memsz);
233960484Sobrien      internal->p_flags  = BYTE_GET (external->p_flags);
234060484Sobrien      internal->p_align  = BYTE_GET (external->p_align);
234160484Sobrien    }
234260484Sobrien
234360484Sobrien  free (phdrs);
234460484Sobrien
234560484Sobrien  return 1;
234660484Sobrien}
234760484Sobrien
234860484Sobrienstatic int
234960484Sobrienget_64bit_program_headers (file, program_headers)
235060484Sobrien     FILE * file;
235160484Sobrien     Elf_Internal_Phdr * program_headers;
235260484Sobrien{
235360484Sobrien  Elf64_External_Phdr * phdrs;
235460484Sobrien  Elf64_External_Phdr * external;
235560484Sobrien  Elf64_Internal_Phdr * internal;
235660484Sobrien  unsigned int          i;
235760484Sobrien
235860484Sobrien  GET_DATA_ALLOC (elf_header.e_phoff,
235960484Sobrien		  elf_header.e_phentsize * elf_header.e_phnum,
236060484Sobrien		  phdrs, Elf64_External_Phdr *, "program headers");
236160484Sobrien
236260484Sobrien  for (i = 0, internal = program_headers, external = phdrs;
236360484Sobrien       i < elf_header.e_phnum;
236460484Sobrien       i ++, internal ++, external ++)
236560484Sobrien    {
236660484Sobrien      internal->p_type   = BYTE_GET (external->p_type);
236760484Sobrien      internal->p_flags  = BYTE_GET (external->p_flags);
236860484Sobrien      internal->p_offset = BYTE_GET8 (external->p_offset);
236960484Sobrien      internal->p_vaddr  = BYTE_GET8 (external->p_vaddr);
237060484Sobrien      internal->p_paddr  = BYTE_GET8 (external->p_paddr);
237160484Sobrien      internal->p_filesz = BYTE_GET8 (external->p_filesz);
237260484Sobrien      internal->p_memsz  = BYTE_GET8 (external->p_memsz);
237360484Sobrien      internal->p_align  = BYTE_GET8 (external->p_align);
237460484Sobrien    }
237560484Sobrien
237660484Sobrien  free (phdrs);
237760484Sobrien
237860484Sobrien  return 1;
237960484Sobrien}
238060484Sobrien
238160484Sobrienstatic int
238260484Sobrienprocess_program_headers (file)
238360484Sobrien     FILE * file;
238460484Sobrien{
238560484Sobrien  Elf_Internal_Phdr * program_headers;
238660484Sobrien  Elf_Internal_Phdr * segment;
238760484Sobrien  unsigned int	      i;
238860484Sobrien
238960484Sobrien  if (elf_header.e_phnum == 0)
239060484Sobrien    {
239160484Sobrien      if (do_segments)
239260484Sobrien	printf (_("\nThere are no program headers in this file.\n"));
239360484Sobrien      return 1;
239460484Sobrien    }
239560484Sobrien
239660484Sobrien  if (do_segments && !do_header)
239760484Sobrien    {
239860484Sobrien      printf (_("\nElf file type is %s\n"), get_file_type (elf_header.e_type));
239960484Sobrien      printf (_("Entry point "));
240060484Sobrien      print_vma ((bfd_vma) elf_header.e_entry, PREFIX_HEX);
240160484Sobrien      printf (_("\nThere are %d program headers, starting at offset "),
240260484Sobrien	      elf_header.e_phnum);
240360484Sobrien      print_vma ((bfd_vma) elf_header.e_phoff, DEC);
240460484Sobrien      printf ("\n");
240560484Sobrien    }
240660484Sobrien
240760484Sobrien  program_headers = (Elf_Internal_Phdr *) malloc
240860484Sobrien    (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
240960484Sobrien
241060484Sobrien  if (program_headers == NULL)
241160484Sobrien    {
241260484Sobrien      error (_("Out of memory\n"));
241360484Sobrien      return 0;
241460484Sobrien    }
241560484Sobrien
241660484Sobrien  if (is_32bit_elf)
241760484Sobrien    i = get_32bit_program_headers (file, program_headers);
241860484Sobrien  else
241960484Sobrien    i = get_64bit_program_headers (file, program_headers);
242060484Sobrien
242160484Sobrien  if (i == 0)
242260484Sobrien    {
242360484Sobrien      free (program_headers);
242460484Sobrien      return 0;
242560484Sobrien    }
242660484Sobrien
242760484Sobrien  if (do_segments)
242860484Sobrien    {
242960484Sobrien      printf
243060484Sobrien	(_("\nProgram Header%s:\n"), elf_header.e_phnum > 1 ? "s" : "");
243177298Sobrien
243260484Sobrien      if (is_32bit_elf)
243360484Sobrien	printf
243460484Sobrien	  (_("  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align\n"));
243560484Sobrien      else
243660484Sobrien	{
243760484Sobrien	  printf
243860484Sobrien	    (_("  Type           Offset             VirtAddr           PhysAddr\n"));
243960484Sobrien	  printf
244060484Sobrien	    (_("                 FileSiz            MemSiz              Flags  Align\n"));
244160484Sobrien	}
244260484Sobrien    }
244360484Sobrien
244460484Sobrien  loadaddr = -1;
244560484Sobrien  dynamic_addr = 0;
244660484Sobrien  dynamic_size = 0;
244760484Sobrien
244860484Sobrien  for (i = 0, segment = program_headers;
244960484Sobrien       i < elf_header.e_phnum;
245060484Sobrien       i ++, segment ++)
245160484Sobrien    {
245260484Sobrien      if (do_segments)
245360484Sobrien	{
245460484Sobrien	  printf ("  %-14.14s ", get_segment_type (segment->p_type));
245560484Sobrien
245660484Sobrien	  if (is_32bit_elf)
245760484Sobrien	    {
245860484Sobrien	      printf ("0x%6.6lx ", (unsigned long) segment->p_offset);
245960484Sobrien	      printf ("0x%8.8lx ", (unsigned long) segment->p_vaddr);
246060484Sobrien	      printf ("0x%8.8lx ", (unsigned long) segment->p_paddr);
246160484Sobrien	      printf ("0x%5.5lx ", (unsigned long) segment->p_filesz);
246260484Sobrien	      printf ("0x%5.5lx ", (unsigned long) segment->p_memsz);
246360484Sobrien	      printf ("%c%c%c ",
246460484Sobrien		      (segment->p_flags & PF_R ? 'R' : ' '),
246560484Sobrien		      (segment->p_flags & PF_W ? 'W' : ' '),
246660484Sobrien		      (segment->p_flags & PF_X ? 'E' : ' '));
246760484Sobrien	      printf ("%#lx", (unsigned long) segment->p_align);
246860484Sobrien	    }
246960484Sobrien	  else
247060484Sobrien	    {
247160484Sobrien	      print_vma (segment->p_offset, FULL_HEX);
247260484Sobrien	      putchar (' ');
247360484Sobrien	      print_vma (segment->p_vaddr, FULL_HEX);
247460484Sobrien	      putchar (' ');
247560484Sobrien	      print_vma (segment->p_paddr, FULL_HEX);
247660484Sobrien	      printf ("\n                 ");
247760484Sobrien	      print_vma (segment->p_filesz, FULL_HEX);
247860484Sobrien	      putchar (' ');
247960484Sobrien	      print_vma (segment->p_memsz, FULL_HEX);
248060484Sobrien	      printf ("  %c%c%c    ",
248160484Sobrien		      (segment->p_flags & PF_R ? 'R' : ' '),
248260484Sobrien		      (segment->p_flags & PF_W ? 'W' : ' '),
248360484Sobrien		      (segment->p_flags & PF_X ? 'E' : ' '));
248460484Sobrien	      print_vma (segment->p_align, HEX);
248560484Sobrien	    }
248660484Sobrien	}
248760484Sobrien
248860484Sobrien      switch (segment->p_type)
248960484Sobrien	{
249060484Sobrien	case PT_LOAD:
249160484Sobrien	  if (loadaddr == -1)
249260484Sobrien	    loadaddr = (segment->p_vaddr & 0xfffff000)
249360484Sobrien	      - (segment->p_offset & 0xfffff000);
249460484Sobrien	  break;
249560484Sobrien
249660484Sobrien	case PT_DYNAMIC:
249760484Sobrien	  if (dynamic_addr)
249860484Sobrien	    error (_("more than one dynamic segment\n"));
249960484Sobrien
250060484Sobrien	  dynamic_addr = segment->p_offset;
250160484Sobrien	  dynamic_size = segment->p_filesz;
250260484Sobrien	  break;
250360484Sobrien
250460484Sobrien	case PT_INTERP:
250560484Sobrien	  if (fseek (file, (long) segment->p_offset, SEEK_SET))
250660484Sobrien	    error (_("Unable to find program interpreter name\n"));
250760484Sobrien	  else
250860484Sobrien	    {
250960484Sobrien	      program_interpreter[0] = 0;
251060484Sobrien	      fscanf (file, "%63s", program_interpreter);
251160484Sobrien
251260484Sobrien	      if (do_segments)
251360484Sobrien		printf (_("\n      [Requesting program interpreter: %s]"),
251460484Sobrien		    program_interpreter);
251560484Sobrien	    }
251660484Sobrien	  break;
251760484Sobrien	}
251860484Sobrien
251960484Sobrien      if (do_segments)
252060484Sobrien	putc ('\n', stdout);
252160484Sobrien    }
252260484Sobrien
252360484Sobrien  if (loadaddr == -1)
252460484Sobrien    {
252560484Sobrien      /* Very strange. */
252660484Sobrien      loadaddr = 0;
252760484Sobrien    }
252860484Sobrien
252960484Sobrien  if (do_segments && section_headers != NULL)
253060484Sobrien    {
253160484Sobrien      printf (_("\n Section to Segment mapping:\n"));
253260484Sobrien      printf (_("  Segment Sections...\n"));
253360484Sobrien
253460484Sobrien      assert (string_table != NULL);
253560484Sobrien
253660484Sobrien      for (i = 0; i < elf_header.e_phnum; i++)
253760484Sobrien	{
253860484Sobrien	  int                 j;
253960484Sobrien	  Elf_Internal_Shdr * section;
254060484Sobrien
254160484Sobrien	  segment = program_headers + i;
254260484Sobrien	  section = section_headers;
254360484Sobrien
254460484Sobrien	  printf ("   %2.2d     ", i);
254560484Sobrien
254660484Sobrien	  for (j = 0; j < elf_header.e_shnum; j++, section ++)
254760484Sobrien	    {
254860484Sobrien	      if (section->sh_size > 0
254960484Sobrien		  /* Compare allocated sections by VMA, unallocated
255060484Sobrien		     sections by file offset.  */
255160484Sobrien		  && (section->sh_flags & SHF_ALLOC
255260484Sobrien		      ? (section->sh_addr >= segment->p_vaddr
255360484Sobrien			 && section->sh_addr + section->sh_size
255460484Sobrien			 <= segment->p_vaddr + segment->p_memsz)
255560484Sobrien		      : ((bfd_vma) section->sh_offset >= segment->p_offset
255660484Sobrien			 && (section->sh_offset + section->sh_size
255760484Sobrien			     <= segment->p_offset + segment->p_filesz))))
255860484Sobrien		printf ("%s ", SECTION_NAME (section));
255960484Sobrien	    }
256060484Sobrien
256160484Sobrien	  putc ('\n',stdout);
256260484Sobrien	}
256360484Sobrien    }
256460484Sobrien
256560484Sobrien  free (program_headers);
256660484Sobrien
256760484Sobrien  return 1;
256860484Sobrien}
256960484Sobrien
257060484Sobrien
257160484Sobrienstatic int
257260484Sobrienget_32bit_section_headers (file)
257360484Sobrien     FILE * file;
257460484Sobrien{
257560484Sobrien  Elf32_External_Shdr * shdrs;
257660484Sobrien  Elf32_Internal_Shdr * internal;
257760484Sobrien  unsigned int          i;
257860484Sobrien
257960484Sobrien  GET_DATA_ALLOC (elf_header.e_shoff,
258060484Sobrien		  elf_header.e_shentsize * elf_header.e_shnum,
258160484Sobrien		  shdrs, Elf32_External_Shdr *, "section headers");
258260484Sobrien
258360484Sobrien  section_headers = (Elf_Internal_Shdr *) malloc
258460484Sobrien    (elf_header.e_shnum * sizeof (Elf_Internal_Shdr));
258560484Sobrien
258660484Sobrien  if (section_headers == NULL)
258760484Sobrien    {
258860484Sobrien      error (_("Out of memory\n"));
258960484Sobrien      return 0;
259060484Sobrien    }
259160484Sobrien
259260484Sobrien  for (i = 0, internal = section_headers;
259360484Sobrien       i < elf_header.e_shnum;
259460484Sobrien       i ++, internal ++)
259560484Sobrien    {
259660484Sobrien      internal->sh_name      = BYTE_GET (shdrs[i].sh_name);
259760484Sobrien      internal->sh_type      = BYTE_GET (shdrs[i].sh_type);
259860484Sobrien      internal->sh_flags     = BYTE_GET (shdrs[i].sh_flags);
259960484Sobrien      internal->sh_addr      = BYTE_GET (shdrs[i].sh_addr);
260060484Sobrien      internal->sh_offset    = BYTE_GET (shdrs[i].sh_offset);
260160484Sobrien      internal->sh_size      = BYTE_GET (shdrs[i].sh_size);
260260484Sobrien      internal->sh_link      = BYTE_GET (shdrs[i].sh_link);
260360484Sobrien      internal->sh_info      = BYTE_GET (shdrs[i].sh_info);
260460484Sobrien      internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
260560484Sobrien      internal->sh_entsize   = BYTE_GET (shdrs[i].sh_entsize);
260660484Sobrien    }
260760484Sobrien
260860484Sobrien  free (shdrs);
260960484Sobrien
261060484Sobrien  return 1;
261160484Sobrien}
261260484Sobrien
261360484Sobrienstatic int
261460484Sobrienget_64bit_section_headers (file)
261560484Sobrien     FILE * file;
261660484Sobrien{
261760484Sobrien  Elf64_External_Shdr * shdrs;
261860484Sobrien  Elf64_Internal_Shdr * internal;
261960484Sobrien  unsigned int          i;
262060484Sobrien
262160484Sobrien  GET_DATA_ALLOC (elf_header.e_shoff,
262260484Sobrien		  elf_header.e_shentsize * elf_header.e_shnum,
262360484Sobrien		  shdrs, Elf64_External_Shdr *, "section headers");
262460484Sobrien
262560484Sobrien  section_headers = (Elf_Internal_Shdr *) malloc
262660484Sobrien    (elf_header.e_shnum * sizeof (Elf_Internal_Shdr));
262760484Sobrien
262860484Sobrien  if (section_headers == NULL)
262960484Sobrien    {
263060484Sobrien      error (_("Out of memory\n"));
263160484Sobrien      return 0;
263260484Sobrien    }
263360484Sobrien
263460484Sobrien  for (i = 0, internal = section_headers;
263560484Sobrien       i < elf_header.e_shnum;
263660484Sobrien       i ++, internal ++)
263760484Sobrien    {
263860484Sobrien      internal->sh_name      = BYTE_GET (shdrs[i].sh_name);
263960484Sobrien      internal->sh_type      = BYTE_GET (shdrs[i].sh_type);
264060484Sobrien      internal->sh_flags     = BYTE_GET8 (shdrs[i].sh_flags);
264160484Sobrien      internal->sh_addr      = BYTE_GET8 (shdrs[i].sh_addr);
264260484Sobrien      internal->sh_size      = BYTE_GET8 (shdrs[i].sh_size);
264360484Sobrien      internal->sh_entsize   = BYTE_GET8 (shdrs[i].sh_entsize);
264460484Sobrien      internal->sh_link      = BYTE_GET (shdrs[i].sh_link);
264560484Sobrien      internal->sh_info      = BYTE_GET (shdrs[i].sh_info);
264660484Sobrien      internal->sh_offset    = BYTE_GET (shdrs[i].sh_offset);
264760484Sobrien      internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
264860484Sobrien    }
264960484Sobrien
265060484Sobrien  free (shdrs);
265160484Sobrien
265260484Sobrien  return 1;
265360484Sobrien}
265460484Sobrien
265560484Sobrienstatic Elf_Internal_Sym *
265660484Sobrienget_32bit_elf_symbols (file, offset, number)
265760484Sobrien     FILE * file;
265860484Sobrien     unsigned long offset;
265960484Sobrien     unsigned long number;
266060484Sobrien{
266160484Sobrien  Elf32_External_Sym * esyms;
266260484Sobrien  Elf_Internal_Sym *   isyms;
266360484Sobrien  Elf_Internal_Sym *   psym;
266460484Sobrien  unsigned int         j;
266560484Sobrien
266660484Sobrien  GET_DATA_ALLOC (offset, number * sizeof (Elf32_External_Sym),
266760484Sobrien		  esyms, Elf32_External_Sym *, "symbols");
266860484Sobrien
266960484Sobrien  isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym));
267060484Sobrien
267160484Sobrien  if (isyms == NULL)
267260484Sobrien    {
267360484Sobrien      error (_("Out of memory\n"));
267460484Sobrien      free (esyms);
267560484Sobrien
267660484Sobrien      return NULL;
267760484Sobrien    }
267860484Sobrien
267960484Sobrien  for (j = 0, psym = isyms;
268060484Sobrien       j < number;
268160484Sobrien       j ++, psym ++)
268260484Sobrien    {
268360484Sobrien      psym->st_name  = BYTE_GET (esyms[j].st_name);
268460484Sobrien      psym->st_value = BYTE_GET (esyms[j].st_value);
268560484Sobrien      psym->st_size  = BYTE_GET (esyms[j].st_size);
268660484Sobrien      psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
268760484Sobrien      psym->st_info  = BYTE_GET (esyms[j].st_info);
268860484Sobrien      psym->st_other = BYTE_GET (esyms[j].st_other);
268960484Sobrien    }
269060484Sobrien
269160484Sobrien  free (esyms);
269260484Sobrien
269360484Sobrien  return isyms;
269460484Sobrien}
269560484Sobrien
269660484Sobrienstatic Elf_Internal_Sym *
269760484Sobrienget_64bit_elf_symbols (file, offset, number)
269860484Sobrien     FILE * file;
269960484Sobrien     unsigned long offset;
270060484Sobrien     unsigned long number;
270160484Sobrien{
270260484Sobrien  Elf64_External_Sym * esyms;
270360484Sobrien  Elf_Internal_Sym *   isyms;
270460484Sobrien  Elf_Internal_Sym *   psym;
270560484Sobrien  unsigned int         j;
270660484Sobrien
270760484Sobrien  GET_DATA_ALLOC (offset, number * sizeof (Elf64_External_Sym),
270860484Sobrien		  esyms, Elf64_External_Sym *, "symbols");
270960484Sobrien
271060484Sobrien  isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym));
271160484Sobrien
271260484Sobrien  if (isyms == NULL)
271360484Sobrien    {
271460484Sobrien      error (_("Out of memory\n"));
271560484Sobrien      free (esyms);
271660484Sobrien
271760484Sobrien      return NULL;
271860484Sobrien    }
271960484Sobrien
272060484Sobrien  for (j = 0, psym = isyms;
272160484Sobrien       j < number;
272260484Sobrien       j ++, psym ++)
272360484Sobrien    {
272460484Sobrien      psym->st_name  = BYTE_GET (esyms[j].st_name);
272560484Sobrien      psym->st_info  = BYTE_GET (esyms[j].st_info);
272660484Sobrien      psym->st_other = BYTE_GET (esyms[j].st_other);
272760484Sobrien      psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
272860484Sobrien      psym->st_value = BYTE_GET8 (esyms[j].st_value);
272960484Sobrien      psym->st_size  = BYTE_GET8 (esyms[j].st_size);
273060484Sobrien    }
273160484Sobrien
273260484Sobrien  free (esyms);
273360484Sobrien
273460484Sobrien  return isyms;
273560484Sobrien}
273660484Sobrien
273760484Sobrienstatic const char *
273860484Sobrienget_elf_section_flags (sh_flags)
273960484Sobrien     bfd_vma sh_flags;
274060484Sobrien{
274160484Sobrien  static char buff [32];
274260484Sobrien
274360484Sobrien  * buff = 0;
274477298Sobrien
274560484Sobrien  while (sh_flags)
274660484Sobrien    {
274760484Sobrien      bfd_vma flag;
274860484Sobrien
274960484Sobrien      flag = sh_flags & - sh_flags;
275060484Sobrien      sh_flags &= ~ flag;
275177298Sobrien
275260484Sobrien      switch (flag)
275360484Sobrien	{
275460484Sobrien	case SHF_WRITE:            strcat (buff, "W"); break;
275560484Sobrien	case SHF_ALLOC:            strcat (buff, "A"); break;
275660484Sobrien	case SHF_EXECINSTR:        strcat (buff, "X"); break;
275760484Sobrien	case SHF_MERGE:            strcat (buff, "M"); break;
275860484Sobrien	case SHF_STRINGS:          strcat (buff, "S"); break;
275960484Sobrien	case SHF_INFO_LINK:        strcat (buff, "I"); break;
276060484Sobrien	case SHF_LINK_ORDER:       strcat (buff, "L"); break;
276160484Sobrien	case SHF_OS_NONCONFORMING: strcat (buff, "O"); break;
276277298Sobrien	case SHF_GROUP:            strcat (buff, "G"); break;
276377298Sobrien
276460484Sobrien	default:
276560484Sobrien	  if (flag & SHF_MASKOS)
276660484Sobrien	    {
276760484Sobrien	      strcat (buff, "o");
276860484Sobrien	      sh_flags &= ~ SHF_MASKOS;
276960484Sobrien	    }
277060484Sobrien	  else if (flag & SHF_MASKPROC)
277160484Sobrien	    {
277260484Sobrien	      strcat (buff, "p");
277360484Sobrien	      sh_flags &= ~ SHF_MASKPROC;
277460484Sobrien	    }
277560484Sobrien	  else
277660484Sobrien	    strcat (buff, "x");
277760484Sobrien	  break;
277860484Sobrien	}
277960484Sobrien    }
278077298Sobrien
278160484Sobrien  return buff;
278260484Sobrien}
278360484Sobrien
278460484Sobrienstatic int
278560484Sobrienprocess_section_headers (file)
278660484Sobrien     FILE * file;
278760484Sobrien{
278860484Sobrien  Elf_Internal_Shdr * section;
278960484Sobrien  int                 i;
279060484Sobrien
279160484Sobrien  section_headers = NULL;
279260484Sobrien
279360484Sobrien  if (elf_header.e_shnum == 0)
279460484Sobrien    {
279560484Sobrien      if (do_sections)
279660484Sobrien	printf (_("\nThere are no sections in this file.\n"));
279760484Sobrien
279860484Sobrien      return 1;
279960484Sobrien    }
280060484Sobrien
280160484Sobrien  if (do_sections && !do_header)
280260484Sobrien    printf (_("There are %d section headers, starting at offset 0x%lx:\n"),
280360484Sobrien	    elf_header.e_shnum, (unsigned long) elf_header.e_shoff);
280460484Sobrien
280560484Sobrien  if (is_32bit_elf)
280660484Sobrien    {
280760484Sobrien      if (! get_32bit_section_headers (file))
280860484Sobrien	return 0;
280960484Sobrien    }
281060484Sobrien  else if (! get_64bit_section_headers (file))
281160484Sobrien    return 0;
281260484Sobrien
281360484Sobrien  /* Read in the string table, so that we have names to display.  */
281460484Sobrien  section = section_headers + elf_header.e_shstrndx;
281560484Sobrien
281660484Sobrien  if (section->sh_size != 0)
281760484Sobrien    {
281860484Sobrien      GET_DATA_ALLOC (section->sh_offset, section->sh_size,
281960484Sobrien		      string_table, char *, "string table");
282077298Sobrien
282177298Sobrien      string_table_length = section->sh_size;
282260484Sobrien    }
282360484Sobrien
282460484Sobrien  /* Scan the sections for the dynamic symbol table
282560484Sobrien     and dynamic string table and debug sections. */
282660484Sobrien  dynamic_symbols = NULL;
282760484Sobrien  dynamic_strings = NULL;
282860484Sobrien  dynamic_syminfo = NULL;
282960484Sobrien
283060484Sobrien  for (i = 0, section = section_headers;
283160484Sobrien       i < elf_header.e_shnum;
283260484Sobrien       i ++, section ++)
283360484Sobrien    {
283460484Sobrien      char * name = SECTION_NAME (section);
283560484Sobrien
283660484Sobrien      if (section->sh_type == SHT_DYNSYM)
283760484Sobrien	{
283860484Sobrien	  if (dynamic_symbols != NULL)
283960484Sobrien	    {
284060484Sobrien	      error (_("File contains multiple dynamic symbol tables\n"));
284160484Sobrien	      continue;
284260484Sobrien	    }
284360484Sobrien
284460484Sobrien	  num_dynamic_syms = section->sh_size / section->sh_entsize;
284560484Sobrien	  dynamic_symbols =
284660484Sobrien	    GET_ELF_SYMBOLS (file, section->sh_offset, num_dynamic_syms);
284760484Sobrien	}
284860484Sobrien      else if (section->sh_type == SHT_STRTAB
284960484Sobrien	       && strcmp (name, ".dynstr") == 0)
285060484Sobrien	{
285160484Sobrien	  if (dynamic_strings != NULL)
285260484Sobrien	    {
285360484Sobrien	      error (_("File contains multiple dynamic string tables\n"));
285460484Sobrien	      continue;
285560484Sobrien	    }
285660484Sobrien
285760484Sobrien	  GET_DATA_ALLOC (section->sh_offset, section->sh_size,
285860484Sobrien			  dynamic_strings, char *, "dynamic strings");
285960484Sobrien	}
286060484Sobrien      else if ((do_debugging || do_debug_info || do_debug_abbrevs
286178828Sobrien		|| do_debug_lines || do_debug_pubnames || do_debug_aranges
286278828Sobrien		|| do_debug_frames)
286360484Sobrien	       && strncmp (name, ".debug_", 7) == 0)
286460484Sobrien	{
286560484Sobrien	  name += 7;
286660484Sobrien
286760484Sobrien	  if (do_debugging
286860484Sobrien	      || (do_debug_info     && (strcmp (name, "info") == 0))
286960484Sobrien	      || (do_debug_abbrevs  && (strcmp (name, "abbrev") == 0))
287060484Sobrien	      || (do_debug_lines    && (strcmp (name, "line") == 0))
287160484Sobrien	      || (do_debug_pubnames && (strcmp (name, "pubnames") == 0))
287260484Sobrien	      || (do_debug_aranges  && (strcmp (name, "aranges") == 0))
287377298Sobrien	      || (do_debug_frames   && (strcmp (name, "frame") == 0))
287460484Sobrien	      )
287560484Sobrien	    request_dump (i, DEBUG_DUMP);
287660484Sobrien	}
287777298Sobrien      /* linkonce section to be combined with .debug_info at link time.  */
287877298Sobrien      else if ((do_debugging || do_debug_info)
287977298Sobrien	       && strncmp (name, ".gnu.linkonce.wi.", 17) == 0)
288077298Sobrien	request_dump (i, DEBUG_DUMP);
288177298Sobrien      else if (do_debug_frames && strcmp (name, ".eh_frame") == 0)
288277298Sobrien	request_dump (i, DEBUG_DUMP);
288360484Sobrien    }
288460484Sobrien
288560484Sobrien  if (! do_sections)
288660484Sobrien    return 1;
288760484Sobrien
288860484Sobrien  printf (_("\nSection Header%s:\n"), elf_header.e_shnum > 1 ? "s" : "");
288977298Sobrien
289060484Sobrien  if (is_32bit_elf)
289160484Sobrien    printf
289260484Sobrien      (_("  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al\n"));
289360484Sobrien  else
289460484Sobrien    {
289560484Sobrien      printf (_("  [Nr] Name              Type             Address           Offset\n"));
289660484Sobrien      printf (_("       Size              EntSize          Flags  Link  Info  Align\n"));
289760484Sobrien    }
289860484Sobrien
289960484Sobrien  for (i = 0, section = section_headers;
290060484Sobrien       i < elf_header.e_shnum;
290160484Sobrien       i ++, section ++)
290260484Sobrien    {
290360484Sobrien      printf ("  [%2d] %-17.17s %-15.15s ",
290460484Sobrien	      i,
290560484Sobrien	      SECTION_NAME (section),
290660484Sobrien	      get_section_type_name (section->sh_type));
290760484Sobrien
290860484Sobrien      if (is_32bit_elf)
290960484Sobrien	{
291060484Sobrien	  print_vma (section->sh_addr, LONG_HEX);
291177298Sobrien
291260484Sobrien	  printf ( " %6.6lx %6.6lx %2.2lx",
291360484Sobrien		   (unsigned long) section->sh_offset,
291460484Sobrien		   (unsigned long) section->sh_size,
291560484Sobrien		   (unsigned long) section->sh_entsize);
291660484Sobrien
291760484Sobrien	  printf (" %3s ", get_elf_section_flags (section->sh_flags));
291877298Sobrien
291977298Sobrien	  printf ("%2ld %3lx %2ld\n",
292060484Sobrien		  (unsigned long) section->sh_link,
292160484Sobrien		  (unsigned long) section->sh_info,
292260484Sobrien		  (unsigned long) section->sh_addralign);
292360484Sobrien	}
292460484Sobrien      else
292560484Sobrien	{
292660484Sobrien	  putchar (' ');
292760484Sobrien	  print_vma (section->sh_addr, LONG_HEX);
292860484Sobrien	  printf ("  %8.8lx", section->sh_offset);
292960484Sobrien	  printf ("\n       ");
293060484Sobrien	  print_vma (section->sh_size, LONG_HEX);
293160484Sobrien	  printf ("  ");
293260484Sobrien	  print_vma (section->sh_entsize, LONG_HEX);
293377298Sobrien
293460484Sobrien	  printf (" %3s ", get_elf_section_flags (section->sh_flags));
293577298Sobrien
293660484Sobrien	  printf ("     %2ld   %3lx     %ld\n",
293760484Sobrien		  (unsigned long) section->sh_link,
293860484Sobrien		  (unsigned long) section->sh_info,
293960484Sobrien		  (unsigned long) section->sh_addralign);
294060484Sobrien	}
294160484Sobrien    }
294260484Sobrien
294377298Sobrien  printf (_("Key to Flags:\n"));
294477298Sobrien  printf (_("  W (write), A (alloc), X (execute), M (merge), S (strings)\n"));
294577298Sobrien  printf (_("  I (info), L (link order), G (group), x (unknown)\n"));
294677298Sobrien  printf (_("  O (extra OS processing required) o (OS specific), p (processor specific)\n"));
294760484Sobrien
294860484Sobrien  return 1;
294960484Sobrien}
295060484Sobrien
295160484Sobrien/* Process the reloc section.  */
295260484Sobrienstatic int
295360484Sobrienprocess_relocs (file)
295460484Sobrien     FILE * file;
295560484Sobrien{
295660484Sobrien  unsigned long    rel_size;
295760484Sobrien  unsigned long	   rel_offset;
295860484Sobrien
295960484Sobrien
296060484Sobrien  if (!do_reloc)
296160484Sobrien    return 1;
296260484Sobrien
296360484Sobrien  if (do_using_dynamic)
296460484Sobrien    {
296560484Sobrien      int is_rela = FALSE;
296660484Sobrien
296760484Sobrien      rel_size   = 0;
296860484Sobrien      rel_offset = 0;
296960484Sobrien
297060484Sobrien      if (dynamic_info[DT_REL])
297160484Sobrien	{
297260484Sobrien	  rel_offset = dynamic_info[DT_REL];
297360484Sobrien	  rel_size   = dynamic_info[DT_RELSZ];
297460484Sobrien	  is_rela    = FALSE;
297560484Sobrien	}
297660484Sobrien      else if (dynamic_info [DT_RELA])
297760484Sobrien	{
297860484Sobrien	  rel_offset = dynamic_info[DT_RELA];
297960484Sobrien	  rel_size   = dynamic_info[DT_RELASZ];
298060484Sobrien	  is_rela    = TRUE;
298160484Sobrien	}
298260484Sobrien      else if (dynamic_info[DT_JMPREL])
298360484Sobrien	{
298460484Sobrien	  rel_offset = dynamic_info[DT_JMPREL];
298560484Sobrien	  rel_size   = dynamic_info[DT_PLTRELSZ];
298660484Sobrien
298760484Sobrien	  switch (dynamic_info[DT_PLTREL])
298860484Sobrien	    {
298960484Sobrien	    case DT_REL:
299060484Sobrien	      is_rela = FALSE;
299160484Sobrien	      break;
299260484Sobrien	    case DT_RELA:
299360484Sobrien	      is_rela = TRUE;
299460484Sobrien	      break;
299560484Sobrien	    default:
299660484Sobrien	      is_rela = UNKNOWN;
299760484Sobrien	      break;
299860484Sobrien	    }
299960484Sobrien	}
300060484Sobrien
300160484Sobrien      if (rel_size)
300260484Sobrien	{
300360484Sobrien	  printf
300460484Sobrien	    (_("\nRelocation section at offset 0x%lx contains %ld bytes:\n"),
300560484Sobrien	     rel_offset, rel_size);
300660484Sobrien
300760484Sobrien	  dump_relocations (file, rel_offset - loadaddr, rel_size,
300860484Sobrien			    dynamic_symbols, num_dynamic_syms, dynamic_strings, is_rela);
300960484Sobrien	}
301060484Sobrien      else
301160484Sobrien	printf (_("\nThere are no dynamic relocations in this file.\n"));
301260484Sobrien    }
301360484Sobrien  else
301460484Sobrien    {
301560484Sobrien      Elf32_Internal_Shdr *     section;
301678828Sobrien      unsigned long		i;
301778828Sobrien      int		found = 0;
301860484Sobrien
301960484Sobrien      for (i = 0, section = section_headers;
302060484Sobrien	   i < elf_header.e_shnum;
302160484Sobrien	   i++, section ++)
302260484Sobrien	{
302360484Sobrien	  if (   section->sh_type != SHT_RELA
302460484Sobrien	      && section->sh_type != SHT_REL)
302560484Sobrien	    continue;
302660484Sobrien
302760484Sobrien	  rel_offset = section->sh_offset;
302860484Sobrien	  rel_size   = section->sh_size;
302960484Sobrien
303060484Sobrien	  if (rel_size)
303160484Sobrien	    {
303260484Sobrien	      Elf32_Internal_Shdr * strsec;
303360484Sobrien	      Elf32_Internal_Shdr * symsec;
303460484Sobrien	      Elf_Internal_Sym *    symtab;
303560484Sobrien	      char *                strtab;
303660484Sobrien	      int                   is_rela;
303760484Sobrien	      unsigned long         nsyms;
303860484Sobrien
303960484Sobrien	      printf (_("\nRelocation section "));
304060484Sobrien
304160484Sobrien	      if (string_table == NULL)
304260484Sobrien		printf ("%d", section->sh_name);
304360484Sobrien	      else
304460484Sobrien		printf ("'%s'", SECTION_NAME (section));
304560484Sobrien
304660484Sobrien	      printf (_(" at offset 0x%lx contains %lu entries:\n"),
304760484Sobrien		 rel_offset, (unsigned long) (rel_size / section->sh_entsize));
304860484Sobrien
304960484Sobrien	      symsec = section_headers + section->sh_link;
305060484Sobrien
305160484Sobrien	      nsyms = symsec->sh_size / symsec->sh_entsize;
305260484Sobrien	      symtab = GET_ELF_SYMBOLS (file, symsec->sh_offset, nsyms);
305360484Sobrien
305460484Sobrien	      if (symtab == NULL)
305560484Sobrien		continue;
305660484Sobrien
305760484Sobrien	      strsec = section_headers + symsec->sh_link;
305860484Sobrien
305960484Sobrien	      GET_DATA_ALLOC (strsec->sh_offset, strsec->sh_size, strtab,
306060484Sobrien			      char *, "string table");
306160484Sobrien
306260484Sobrien	      is_rela = section->sh_type == SHT_RELA;
306360484Sobrien
306460484Sobrien	      dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela);
306560484Sobrien
306660484Sobrien	      free (strtab);
306760484Sobrien	      free (symtab);
306860484Sobrien
306960484Sobrien	      found = 1;
307060484Sobrien	    }
307160484Sobrien	}
307260484Sobrien
307360484Sobrien      if (! found)
307460484Sobrien	printf (_("\nThere are no relocations in this file.\n"));
307560484Sobrien    }
307660484Sobrien
307760484Sobrien  return 1;
307860484Sobrien}
307960484Sobrien
308078828Sobrien#include "unwind-ia64.h"
308160484Sobrien
308278828Sobrien/* An absolute address consists of a section and an offset.  If the
308378828Sobrien   section is NULL, the offset itself is the address, otherwise, the
308478828Sobrien   address equals to LOAD_ADDRESS(section) + offset.  */
308578828Sobrien
308678828Sobrienstruct absaddr
308778828Sobrien  {
308878828Sobrien    unsigned short section;
308978828Sobrien    bfd_vma offset;
309078828Sobrien  };
309178828Sobrien
309278828Sobrienstruct unw_aux_info
309378828Sobrien  {
309478828Sobrien    struct unw_table_entry
309578828Sobrien      {
309678828Sobrien	struct absaddr    start;
309778828Sobrien	struct absaddr    end;
309878828Sobrien	struct absaddr    info;
309978828Sobrien      }
310078828Sobrien    *table;				/* Unwind table.  */
310178828Sobrien    unsigned long         table_len;	/* Length of unwind table.  */
310278828Sobrien    unsigned char *       info;		/* Unwind info.  */
310378828Sobrien    unsigned long         info_size;	/* Size of unwind info.  */
310478828Sobrien    bfd_vma               info_addr;	/* starting address of unwind info.  */
310578828Sobrien    bfd_vma               seg_base;	/* Starting address of segment.  */
310678828Sobrien    Elf_Internal_Sym *    symtab;	/* The symbol table.  */
310778828Sobrien    unsigned              long nsyms;	/* Number of symbols.  */
310878828Sobrien    char *                strtab;	/* The string table.  */
310978828Sobrien    unsigned long         strtab_size;	/* Size of string table.  */
311078828Sobrien  };
311178828Sobrien
311278828Sobrienstatic void find_symbol_for_address PARAMS ((struct unw_aux_info *,
311378828Sobrien					     struct absaddr, const char **,
311478828Sobrien					     bfd_vma *));
311578828Sobrienstatic void dump_ia64_unwind PARAMS ((struct unw_aux_info *));
311678828Sobrienstatic int  slurp_ia64_unwind_table PARAMS ((FILE *, struct unw_aux_info *,
311778828Sobrien					    Elf32_Internal_Shdr *));
311878828Sobrien
311960484Sobrienstatic void
312078828Sobrienfind_symbol_for_address (aux, addr, symname, offset)
312178828Sobrien     struct unw_aux_info *aux;
312278828Sobrien     struct absaddr addr;
312378828Sobrien     const char **symname;
312478828Sobrien     bfd_vma *offset;
312578828Sobrien{
312678828Sobrien  bfd_vma dist = (bfd_vma) 0x100000;
312778828Sobrien  Elf_Internal_Sym *sym, *best = NULL;
312878828Sobrien  unsigned long i;
312978828Sobrien
313078828Sobrien  for (i = 0, sym = aux->symtab; i < aux->nsyms; ++i, ++sym)
313178828Sobrien    {
313278828Sobrien      if (ELF_ST_TYPE (sym->st_info) == STT_FUNC
313378828Sobrien	  && sym->st_name != 0
313478828Sobrien	  && (addr.section == SHN_UNDEF || addr.section == sym->st_shndx)
313578828Sobrien	  && addr.offset >= sym->st_value
313678828Sobrien	  && addr.offset - sym->st_value < dist)
313778828Sobrien	{
313878828Sobrien	  best = sym;
313978828Sobrien	  dist = addr.offset - sym->st_value;
314078828Sobrien	  if (!dist)
314178828Sobrien	    break;
314278828Sobrien	}
314378828Sobrien    }
314478828Sobrien  if (best)
314578828Sobrien    {
314678828Sobrien      *symname = (best->st_name >= aux->strtab_size
314778828Sobrien		  ? "<corrupt>" : aux->strtab + best->st_name);
314878828Sobrien      *offset = dist;
314978828Sobrien      return;
315078828Sobrien    }
315178828Sobrien  *symname = NULL;
315278828Sobrien  *offset = addr.offset;
315378828Sobrien}
315478828Sobrien
315578828Sobrienstatic void
315678828Sobriendump_ia64_unwind (aux)
315778828Sobrien     struct unw_aux_info *aux;
315878828Sobrien{
315978828Sobrien  bfd_vma addr_size;
316078828Sobrien  struct unw_table_entry * tp;
316178828Sobrien  int in_body;
316278828Sobrien
316378828Sobrien  addr_size = is_32bit_elf ? 4 : 8;
316478828Sobrien
316578828Sobrien  for (tp = aux->table; tp < aux->table + aux->table_len; ++tp)
316678828Sobrien    {
316778828Sobrien      bfd_vma stamp;
316878828Sobrien      bfd_vma offset;
316978828Sobrien      const unsigned char * dp;
317078828Sobrien      const unsigned char * head;
317178828Sobrien      const char * procname;
317278828Sobrien
317378828Sobrien      find_symbol_for_address (aux, tp->start, &procname, &offset);
317478828Sobrien
317578828Sobrien      fputs ("\n<", stdout);
317678828Sobrien
317778828Sobrien      if (procname)
317878828Sobrien	{
317978828Sobrien	  fputs (procname, stdout);
318078828Sobrien
318178828Sobrien	  if (offset)
318278828Sobrien	    printf ("+%lx", (unsigned long) offset);
318378828Sobrien	}
318478828Sobrien
318578828Sobrien      fputs (">: [", stdout);
318678828Sobrien      print_vma (tp->start.offset, PREFIX_HEX);
318778828Sobrien      fputc ('-', stdout);
318878828Sobrien      print_vma (tp->end.offset, PREFIX_HEX);
318978828Sobrien      printf ("), info at +0x%lx\n",
319078828Sobrien	      (unsigned long) (tp->info.offset - aux->seg_base));
319178828Sobrien
319278828Sobrien      head = aux->info + (tp->info.offset - aux->info_addr);
319378828Sobrien      stamp = BYTE_GET8 ((unsigned char *) head);
319478828Sobrien
319578828Sobrien      printf ("  v%u, flags=0x%lx (%s%s ), len=%lu bytes\n",
319678828Sobrien	      (unsigned) UNW_VER (stamp),
319778828Sobrien	      (unsigned long) ((stamp & UNW_FLAG_MASK) >> 32),
319878828Sobrien	      UNW_FLAG_EHANDLER (stamp) ? " ehandler" : "",
319978828Sobrien	      UNW_FLAG_UHANDLER (stamp) ? " uhandler" : "",
320078828Sobrien	      (unsigned long) (addr_size * UNW_LENGTH (stamp)));
320178828Sobrien
320278828Sobrien      if (UNW_VER (stamp) != 1)
320378828Sobrien	{
320478828Sobrien	  printf ("\tUnknown version.\n");
320578828Sobrien	  continue;
320678828Sobrien	}
320778828Sobrien
320878828Sobrien      in_body = 0;
320978828Sobrien      for (dp = head + 8; dp < head + 8 + addr_size * UNW_LENGTH (stamp);)
321078828Sobrien	dp = unw_decode (dp, in_body, & in_body);
321178828Sobrien    }
321278828Sobrien}
321378828Sobrien
321478828Sobrienstatic int
321578828Sobrienslurp_ia64_unwind_table (file, aux, sec)
321678828Sobrien     FILE *file;
321778828Sobrien     struct unw_aux_info *aux;
321878828Sobrien     Elf32_Internal_Shdr *sec;
321978828Sobrien{
322078828Sobrien  unsigned long size, addr_size, nrelas, i;
322178828Sobrien  Elf_Internal_Phdr *prog_hdrs, *seg;
322278828Sobrien  struct unw_table_entry *tep;
322378828Sobrien  Elf32_Internal_Shdr *relsec;
322478828Sobrien  Elf_Internal_Rela *rela, *rp;
322578828Sobrien  unsigned char *table, *tp;
322678828Sobrien  Elf_Internal_Sym *sym;
322778828Sobrien  const char *relname;
322878828Sobrien  int result;
322978828Sobrien
323078828Sobrien  addr_size = is_32bit_elf ? 4 : 8;
323178828Sobrien
323278828Sobrien  /* First, find the starting address of the segment that includes
323378828Sobrien     this section: */
323478828Sobrien
323578828Sobrien  if (elf_header.e_phnum)
323678828Sobrien    {
323778828Sobrien      prog_hdrs = (Elf_Internal_Phdr *)
323878828Sobrien	xmalloc (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
323978828Sobrien
324078828Sobrien      if (is_32bit_elf)
324178828Sobrien	result = get_32bit_program_headers (file, prog_hdrs);
324278828Sobrien      else
324378828Sobrien	result = get_64bit_program_headers (file, prog_hdrs);
324478828Sobrien
324578828Sobrien      if (!result)
324678828Sobrien	{
324778828Sobrien	  free (prog_hdrs);
324878828Sobrien	  return 0;
324978828Sobrien	}
325078828Sobrien
325178828Sobrien      for (seg = prog_hdrs; seg < prog_hdrs + elf_header.e_phnum; ++seg)
325278828Sobrien	{
325378828Sobrien	  if (seg->p_type != PT_LOAD)
325478828Sobrien	    continue;
325578828Sobrien
325678828Sobrien	  if (sec->sh_addr >= seg->p_vaddr
325778828Sobrien	      && (sec->sh_addr + sec->sh_size <= seg->p_vaddr + seg->p_memsz))
325878828Sobrien	    {
325978828Sobrien	      aux->seg_base = seg->p_vaddr;
326078828Sobrien	      break;
326178828Sobrien	    }
326278828Sobrien	}
326378828Sobrien
326478828Sobrien      free (prog_hdrs);
326578828Sobrien    }
326678828Sobrien
326778828Sobrien  /* Second, build the unwind table from the contents of the unwind section:  */
326878828Sobrien  size = sec->sh_size;
326978828Sobrien  GET_DATA_ALLOC (sec->sh_offset, size, table, char *, "unwind table");
327078828Sobrien
327178828Sobrien  tep = aux->table = xmalloc (size / (3 * addr_size) * sizeof (aux->table[0]));
327278828Sobrien  for (tp = table; tp < table + size; tp += 3 * addr_size, ++ tep)
327378828Sobrien    {
327478828Sobrien      tep->start.section = SHN_UNDEF;
327578828Sobrien      tep->end.section   = SHN_UNDEF;
327678828Sobrien      tep->info.section  = SHN_UNDEF;
327778828Sobrien      if (is_32bit_elf)
327878828Sobrien	{
327978828Sobrien	  tep->start.offset = byte_get ((unsigned char *) tp + 0, 4);
328078828Sobrien	  tep->end.offset   = byte_get ((unsigned char *) tp + 4, 4);
328178828Sobrien	  tep->info.offset  = byte_get ((unsigned char *) tp + 8, 4);
328278828Sobrien	}
328378828Sobrien      else
328478828Sobrien	{
328578828Sobrien	  tep->start.offset = BYTE_GET8 ((unsigned char *) tp +  0);
328678828Sobrien	  tep->end.offset   = BYTE_GET8 ((unsigned char *) tp +  8);
328778828Sobrien	  tep->info.offset  = BYTE_GET8 ((unsigned char *) tp + 16);
328878828Sobrien	}
328978828Sobrien      tep->start.offset += aux->seg_base;
329078828Sobrien      tep->end.offset   += aux->seg_base;
329178828Sobrien      tep->info.offset  += aux->seg_base;
329278828Sobrien    }
329378828Sobrien  free (table);
329478828Sobrien
329578828Sobrien  /* Third, apply any relocations to the unwind table: */
329678828Sobrien
329778828Sobrien  for (relsec = section_headers;
329878828Sobrien       relsec < section_headers + elf_header.e_shnum;
329978828Sobrien       ++relsec)
330078828Sobrien    {
330178828Sobrien      if (relsec->sh_type != SHT_RELA
330278828Sobrien	  || section_headers + relsec->sh_info != sec)
330378828Sobrien	continue;
330478828Sobrien
330578828Sobrien      if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
330678828Sobrien			      & rela, & nrelas))
330778828Sobrien	return 0;
330878828Sobrien
330978828Sobrien      for (rp = rela; rp < rela + nrelas; ++rp)
331078828Sobrien	{
331178828Sobrien	  if (is_32bit_elf)
331278828Sobrien	    {
331378828Sobrien	      relname = elf_ia64_reloc_type (ELF32_R_TYPE (rp->r_info));
331478828Sobrien	      sym = aux->symtab + ELF32_R_SYM (rp->r_info);
331578828Sobrien
331678828Sobrien	      if (ELF32_ST_TYPE (sym->st_info) != STT_SECTION)
331778828Sobrien		{
331878828Sobrien		  warn (_("Skipping unexpected symbol type %u"),
331978828Sobrien			ELF32_ST_TYPE (sym->st_info));
332078828Sobrien		  continue;
332178828Sobrien		}
332278828Sobrien	    }
332378828Sobrien	  else
332478828Sobrien	    {
332578828Sobrien	      relname = elf_ia64_reloc_type (ELF64_R_TYPE (rp->r_info));
332678828Sobrien	      sym = aux->symtab + ELF64_R_SYM (rp->r_info);
332778828Sobrien
332878828Sobrien	      if (ELF64_ST_TYPE (sym->st_info) != STT_SECTION)
332978828Sobrien		{
333078828Sobrien		  warn (_("Skipping unexpected symbol type %u"),
333178828Sobrien			ELF64_ST_TYPE (sym->st_info));
333278828Sobrien		  continue;
333378828Sobrien		}
333478828Sobrien	    }
333578828Sobrien
333678828Sobrien	  if (strncmp (relname, "R_IA64_SEGREL", 13) != 0)
333778828Sobrien	    {
333878828Sobrien	      warn (_("Skipping unexpected relocation type %s"), relname);
333978828Sobrien	      continue;
334078828Sobrien	    }
334178828Sobrien
334278828Sobrien	  i = rp->r_offset / (3 * addr_size);
334378828Sobrien
334478828Sobrien	  switch (rp->r_offset/addr_size % 3)
334578828Sobrien	    {
334678828Sobrien	    case 0:
334778828Sobrien	      aux->table[i].start.section = sym->st_shndx;
334878828Sobrien	      aux->table[i].start.offset += rp->r_addend;
334978828Sobrien	      break;
335078828Sobrien	    case 1:
335178828Sobrien	      aux->table[i].end.section   = sym->st_shndx;
335278828Sobrien	      aux->table[i].end.offset   += rp->r_addend;
335378828Sobrien	      break;
335478828Sobrien	    case 2:
335578828Sobrien	      aux->table[i].info.section  = sym->st_shndx;
335678828Sobrien	      aux->table[i].info.offset  += rp->r_addend;
335778828Sobrien	      break;
335878828Sobrien	    default:
335978828Sobrien	      break;
336078828Sobrien	    }
336178828Sobrien	}
336278828Sobrien
336378828Sobrien      free (rela);
336478828Sobrien    }
336578828Sobrien
336678828Sobrien  aux->table_len = size / (3 * addr_size);
336778828Sobrien  return 1;
336878828Sobrien}
336978828Sobrien
337078828Sobrienstatic int
337178828Sobrienprocess_unwind (file)
337278828Sobrien     FILE * file;
337378828Sobrien{
337478828Sobrien  Elf32_Internal_Shdr *sec, *unwsec = NULL, *strsec;
337578828Sobrien  unsigned long i, addr_size, unwcount = 0, unwstart = 0;
337678828Sobrien  struct unw_aux_info aux;
337778828Sobrien
337878828Sobrien  if (!do_unwind)
337978828Sobrien    return 1;
338078828Sobrien
338178828Sobrien  if (elf_header.e_machine != EM_IA_64)
338278828Sobrien    {
338378828Sobrien      printf (_("\nThere are no unwind sections in this file.\n"));
338478828Sobrien      return 1;
338578828Sobrien    }
338678828Sobrien
338778828Sobrien  memset (& aux, 0, sizeof (aux));
338878828Sobrien
338978828Sobrien  addr_size = is_32bit_elf ? 4 : 8;
339078828Sobrien
339178828Sobrien  for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
339278828Sobrien    {
339378828Sobrien      if (sec->sh_type == SHT_SYMTAB)
339478828Sobrien	{
339578828Sobrien	  aux.nsyms = sec->sh_size / sec->sh_entsize;
339678828Sobrien	  aux.symtab = GET_ELF_SYMBOLS (file, sec->sh_offset, aux.nsyms);
339778828Sobrien
339878828Sobrien	  strsec = section_headers + sec->sh_link;
339978828Sobrien	  aux.strtab_size = strsec->sh_size;
340078828Sobrien	  GET_DATA_ALLOC (strsec->sh_offset, aux.strtab_size,
340178828Sobrien			  aux.strtab, char *, "string table");
340278828Sobrien	}
340378828Sobrien      else if (sec->sh_type == SHT_IA_64_UNWIND)
340478828Sobrien	unwcount++;
340578828Sobrien    }
340678828Sobrien
340778828Sobrien  if (!unwcount)
340878828Sobrien    printf (_("\nThere are no unwind sections in this file.\n"));
340978828Sobrien
341078828Sobrien  while (unwcount-- > 0)
341178828Sobrien    {
341278828Sobrien      char *suffix;
341378828Sobrien      size_t len, len2;
341478828Sobrien
341578828Sobrien      for (i = unwstart, sec = section_headers + unwstart;
341678828Sobrien	   i < elf_header.e_shnum; ++i, ++sec)
341778828Sobrien	if (sec->sh_type == SHT_IA_64_UNWIND)
341878828Sobrien	  {
341978828Sobrien	    unwsec = sec;
342078828Sobrien	    break;
342178828Sobrien	  }
342278828Sobrien
342378828Sobrien      unwstart = i + 1;
342478828Sobrien      len = sizeof (ELF_STRING_ia64_unwind_once) - 1;
342578828Sobrien
342678828Sobrien      if (strncmp (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind_once,
342778828Sobrien		   len) == 0)
342878828Sobrien	{
342978828Sobrien	  /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.ia64unwi.FOO */
343078828Sobrien	  len2 = sizeof (ELF_STRING_ia64_unwind_info_once) - 1;
343178828Sobrien	  suffix = SECTION_NAME (unwsec) + len;
343278828Sobrien	  for (i = 0, sec = section_headers; i < elf_header.e_shnum;
343378828Sobrien	       ++i, ++sec)
343478828Sobrien	    if (strncmp (SECTION_NAME (sec),
343578828Sobrien			 ELF_STRING_ia64_unwind_info_once, len2) == 0
343678828Sobrien		&& strcmp (SECTION_NAME (sec) + len2, suffix) == 0)
343778828Sobrien	      break;
343878828Sobrien	}
343978828Sobrien      else
344078828Sobrien	{
344178828Sobrien	  /* .IA_64.unwindFOO -> .IA_64.unwind_infoFOO
344278828Sobrien	     .IA_64.unwind or BAR -> .IA_64.unwind_info */
344378828Sobrien	  len = sizeof (ELF_STRING_ia64_unwind) - 1;
344478828Sobrien	  len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1;
344578828Sobrien	  suffix = "";
344678828Sobrien	  if (strncmp (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind,
344778828Sobrien		       len) == 0)
344878828Sobrien	    suffix = SECTION_NAME (unwsec) + len;
344978828Sobrien	  for (i = 0, sec = section_headers; i < elf_header.e_shnum;
345078828Sobrien	       ++i, ++sec)
345178828Sobrien	    if (strncmp (SECTION_NAME (sec),
345278828Sobrien			 ELF_STRING_ia64_unwind_info, len2) == 0
345378828Sobrien		&& strcmp (SECTION_NAME (sec) + len2, suffix) == 0)
345478828Sobrien	      break;
345578828Sobrien	}
345678828Sobrien
345778828Sobrien      if (i == elf_header.e_shnum)
345878828Sobrien	{
345978828Sobrien	  printf (_("\nCould not find unwind info section for "));
346078828Sobrien
346178828Sobrien	  if (string_table == NULL)
346278828Sobrien	    printf ("%d", unwsec->sh_name);
346378828Sobrien	  else
346478828Sobrien	    printf ("'%s'", SECTION_NAME (unwsec));
346578828Sobrien	}
346678828Sobrien      else
346778828Sobrien	{
346878828Sobrien	  aux.info_size = sec->sh_size;
346978828Sobrien	  aux.info_addr = sec->sh_addr;
347078828Sobrien	  GET_DATA_ALLOC (sec->sh_offset, aux.info_size, aux.info,
347178828Sobrien			  char *, "unwind info");
347278828Sobrien
347378828Sobrien	  printf (_("\nUnwind section "));
347478828Sobrien
347578828Sobrien	  if (string_table == NULL)
347678828Sobrien	    printf ("%d", unwsec->sh_name);
347778828Sobrien	  else
347878828Sobrien	    printf ("'%s'", SECTION_NAME (unwsec));
347978828Sobrien
348078828Sobrien	  printf (_(" at offset 0x%lx contains %lu entries:\n"),
348178828Sobrien		  unwsec->sh_offset,
348278828Sobrien		  (unsigned long) (unwsec->sh_size / (3 * addr_size)));
348378828Sobrien
348478828Sobrien	  (void) slurp_ia64_unwind_table (file, & aux, unwsec);
348578828Sobrien
348678828Sobrien	  if (aux.table_len > 0)
348778828Sobrien	    dump_ia64_unwind (& aux);
348878828Sobrien
348978828Sobrien	  if (aux.table)
349078828Sobrien	    free ((char *) aux.table);
349178828Sobrien	  if (aux.info)
349278828Sobrien	    free ((char *) aux.info);
349378828Sobrien	  aux.table = NULL;
349478828Sobrien	  aux.info = NULL;
349578828Sobrien	}
349678828Sobrien    }
349778828Sobrien
349878828Sobrien  if (aux.symtab)
349978828Sobrien    free (aux.symtab);
350078828Sobrien  if (aux.strtab)
350178828Sobrien    free ((char *) aux.strtab);
350278828Sobrien
350378828Sobrien  return 1;
350478828Sobrien}
350578828Sobrien
350678828Sobrienstatic void
350760484Sobriendynamic_segment_mips_val (entry)
350860484Sobrien     Elf_Internal_Dyn * entry;
350960484Sobrien{
351060484Sobrien  switch (entry->d_tag)
351160484Sobrien    {
351260484Sobrien    case DT_MIPS_FLAGS:
351360484Sobrien      if (entry->d_un.d_val == 0)
351460484Sobrien	printf ("NONE\n");
351560484Sobrien      else
351660484Sobrien	{
351760484Sobrien	  static const char * opts[] =
351860484Sobrien	  {
351960484Sobrien	    "QUICKSTART", "NOTPOT", "NO_LIBRARY_REPLACEMENT",
352060484Sobrien	    "NO_MOVE", "SGI_ONLY", "GUARANTEE_INIT", "DELTA_C_PLUS_PLUS",
352160484Sobrien	    "GUARANTEE_START_INIT", "PIXIE", "DEFAULT_DELAY_LOAD",
352260484Sobrien	    "REQUICKSTART", "REQUICKSTARTED", "CORD", "NO_UNRES_UNDEF",
352360484Sobrien	    "RLD_ORDER_SAFE"
352460484Sobrien	  };
352560484Sobrien	  unsigned int cnt;
352660484Sobrien	  int first = 1;
352760484Sobrien	  for (cnt = 0; cnt < NUM_ELEM (opts); ++ cnt)
352860484Sobrien	    if (entry->d_un.d_val & (1 << cnt))
352960484Sobrien	      {
353060484Sobrien		printf ("%s%s", first ? "" : " ", opts[cnt]);
353160484Sobrien		first = 0;
353260484Sobrien	      }
353360484Sobrien	  puts ("");
353460484Sobrien	}
353560484Sobrien      break;
353660484Sobrien
353760484Sobrien    case DT_MIPS_IVERSION:
353860484Sobrien      if (dynamic_strings != NULL)
353960484Sobrien	printf ("Interface Version: %s\n",
354060484Sobrien		dynamic_strings + entry->d_un.d_val);
354160484Sobrien      else
354260484Sobrien	printf ("%ld\n", (long) entry->d_un.d_ptr);
354360484Sobrien      break;
354460484Sobrien
354560484Sobrien    case DT_MIPS_TIME_STAMP:
354660484Sobrien      {
354760484Sobrien	char timebuf[20];
354860484Sobrien	struct tm * tmp;
354960484Sobrien
355060484Sobrien	time_t time = entry->d_un.d_val;
355160484Sobrien	tmp = gmtime (&time);
355260484Sobrien	sprintf (timebuf, "%04u-%02u-%02uT%02u:%02u:%02u",
355360484Sobrien		 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
355460484Sobrien		 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
355560484Sobrien	printf ("Time Stamp: %s\n", timebuf);
355660484Sobrien      }
355760484Sobrien      break;
355860484Sobrien
355960484Sobrien    case DT_MIPS_RLD_VERSION:
356060484Sobrien    case DT_MIPS_LOCAL_GOTNO:
356160484Sobrien    case DT_MIPS_CONFLICTNO:
356260484Sobrien    case DT_MIPS_LIBLISTNO:
356360484Sobrien    case DT_MIPS_SYMTABNO:
356460484Sobrien    case DT_MIPS_UNREFEXTNO:
356560484Sobrien    case DT_MIPS_HIPAGENO:
356660484Sobrien    case DT_MIPS_DELTA_CLASS_NO:
356760484Sobrien    case DT_MIPS_DELTA_INSTANCE_NO:
356860484Sobrien    case DT_MIPS_DELTA_RELOC_NO:
356960484Sobrien    case DT_MIPS_DELTA_SYM_NO:
357060484Sobrien    case DT_MIPS_DELTA_CLASSSYM_NO:
357160484Sobrien    case DT_MIPS_COMPACT_SIZE:
357260484Sobrien      printf ("%ld\n", (long) entry->d_un.d_ptr);
357360484Sobrien      break;
357460484Sobrien
357560484Sobrien    default:
357660484Sobrien      printf ("%#lx\n", (long) entry->d_un.d_ptr);
357760484Sobrien    }
357860484Sobrien}
357960484Sobrien
358060484Sobrien
358160484Sobrienstatic void
358260484Sobriendynamic_segment_parisc_val (entry)
358360484Sobrien     Elf_Internal_Dyn * entry;
358460484Sobrien{
358560484Sobrien  switch (entry->d_tag)
358660484Sobrien    {
358760484Sobrien    case DT_HP_DLD_FLAGS:
358860484Sobrien      {
358960484Sobrien	static struct
359060484Sobrien	{
359160484Sobrien	  long int bit;
359260484Sobrien	  const char * str;
359360484Sobrien	}
359460484Sobrien	flags[] =
359560484Sobrien	{
359660484Sobrien	  { DT_HP_DEBUG_PRIVATE, "HP_DEBUG_PRIVATE" },
359760484Sobrien	  { DT_HP_DEBUG_CALLBACK, "HP_DEBUG_CALLBACK" },
359860484Sobrien	  { DT_HP_DEBUG_CALLBACK_BOR, "HP_DEBUG_CALLBACK_BOR" },
359960484Sobrien	  { DT_HP_NO_ENVVAR, "HP_NO_ENVVAR" },
360060484Sobrien	  { DT_HP_BIND_NOW, "HP_BIND_NOW" },
360160484Sobrien	  { DT_HP_BIND_NONFATAL, "HP_BIND_NONFATAL" },
360260484Sobrien	  { DT_HP_BIND_VERBOSE, "HP_BIND_VERBOSE" },
360360484Sobrien	  { DT_HP_BIND_RESTRICTED, "HP_BIND_RESTRICTED" },
360460484Sobrien	  { DT_HP_BIND_SYMBOLIC, "HP_BIND_SYMBOLIC" },
360560484Sobrien	  { DT_HP_RPATH_FIRST, "HP_RPATH_FIRST" },
360660484Sobrien	  { DT_HP_BIND_DEPTH_FIRST, "HP_BIND_DEPTH_FIRST" }
360760484Sobrien	};
360860484Sobrien	int first = 1;
360960484Sobrien	size_t cnt;
361060484Sobrien	bfd_vma val = entry->d_un.d_val;
361160484Sobrien
361260484Sobrien	for (cnt = 0; cnt < sizeof (flags) / sizeof (flags[0]); ++cnt)
361360484Sobrien	  if (val & flags[cnt].bit)
361460484Sobrien	    {
361560484Sobrien	      if (! first)
361660484Sobrien		putchar (' ');
361760484Sobrien	      fputs (flags[cnt].str, stdout);
361860484Sobrien	      first = 0;
361960484Sobrien	      val ^= flags[cnt].bit;
362060484Sobrien	    }
362177298Sobrien
362260484Sobrien	if (val != 0 || first)
362360484Sobrien	  {
362460484Sobrien	    if (! first)
362560484Sobrien	      putchar (' ');
362660484Sobrien	    print_vma (val, HEX);
362760484Sobrien	  }
362860484Sobrien      }
362960484Sobrien      break;
363077298Sobrien
363160484Sobrien    default:
363260484Sobrien      print_vma (entry->d_un.d_ptr, PREFIX_HEX);
363360484Sobrien      break;
363460484Sobrien    }
363560484Sobrien}
363660484Sobrien
363760484Sobrienstatic int
363860484Sobrienget_32bit_dynamic_segment (file)
363960484Sobrien     FILE * file;
364060484Sobrien{
364160484Sobrien  Elf32_External_Dyn * edyn;
364260484Sobrien  Elf_Internal_Dyn *   entry;
364360484Sobrien  bfd_size_type        i;
364460484Sobrien
364560484Sobrien  GET_DATA_ALLOC (dynamic_addr, dynamic_size,
364660484Sobrien		  edyn, Elf32_External_Dyn *, "dynamic segment");
364760484Sobrien
364860484Sobrien  /* SGI's ELF has more than one section in the DYNAMIC segment.  Determine
364960484Sobrien     how large this .dynamic is now.  We can do this even before the byte
365060484Sobrien     swapping since the DT_NULL tag is recognizable.  */
365160484Sobrien  dynamic_size = 0;
365260484Sobrien  while (*(Elf32_Word *) edyn [dynamic_size++].d_tag != DT_NULL)
365360484Sobrien    ;
365460484Sobrien
365560484Sobrien  dynamic_segment = (Elf_Internal_Dyn *)
365660484Sobrien    malloc (dynamic_size * sizeof (Elf_Internal_Dyn));
365760484Sobrien
365860484Sobrien  if (dynamic_segment == NULL)
365960484Sobrien    {
366060484Sobrien      error (_("Out of memory\n"));
366160484Sobrien      free (edyn);
366260484Sobrien      return 0;
366360484Sobrien    }
366460484Sobrien
366560484Sobrien  for (i = 0, entry = dynamic_segment;
366660484Sobrien       i < dynamic_size;
366760484Sobrien       i ++, entry ++)
366860484Sobrien    {
366960484Sobrien      entry->d_tag      = BYTE_GET (edyn [i].d_tag);
367060484Sobrien      entry->d_un.d_val = BYTE_GET (edyn [i].d_un.d_val);
367160484Sobrien    }
367260484Sobrien
367360484Sobrien  free (edyn);
367460484Sobrien
367560484Sobrien  return 1;
367660484Sobrien}
367760484Sobrien
367860484Sobrienstatic int
367960484Sobrienget_64bit_dynamic_segment (file)
368060484Sobrien     FILE * file;
368160484Sobrien{
368260484Sobrien  Elf64_External_Dyn * edyn;
368360484Sobrien  Elf_Internal_Dyn *   entry;
368460484Sobrien  bfd_size_type        i;
368560484Sobrien
368660484Sobrien  GET_DATA_ALLOC (dynamic_addr, dynamic_size,
368760484Sobrien		  edyn, Elf64_External_Dyn *, "dynamic segment");
368860484Sobrien
368960484Sobrien  /* SGI's ELF has more than one section in the DYNAMIC segment.  Determine
369060484Sobrien     how large this .dynamic is now.  We can do this even before the byte
369160484Sobrien     swapping since the DT_NULL tag is recognizable.  */
369260484Sobrien  dynamic_size = 0;
369360484Sobrien  while (*(bfd_vma *) edyn [dynamic_size ++].d_tag != DT_NULL)
369460484Sobrien    ;
369560484Sobrien
369660484Sobrien  dynamic_segment = (Elf_Internal_Dyn *)
369760484Sobrien    malloc (dynamic_size * sizeof (Elf_Internal_Dyn));
369860484Sobrien
369960484Sobrien  if (dynamic_segment == NULL)
370060484Sobrien    {
370160484Sobrien      error (_("Out of memory\n"));
370260484Sobrien      free (edyn);
370360484Sobrien      return 0;
370460484Sobrien    }
370560484Sobrien
370660484Sobrien  for (i = 0, entry = dynamic_segment;
370760484Sobrien       i < dynamic_size;
370860484Sobrien       i ++, entry ++)
370960484Sobrien    {
371060484Sobrien      entry->d_tag      = BYTE_GET8 (edyn [i].d_tag);
371160484Sobrien      entry->d_un.d_val = BYTE_GET8 (edyn [i].d_un.d_val);
371260484Sobrien    }
371360484Sobrien
371460484Sobrien  free (edyn);
371560484Sobrien
371660484Sobrien  return 1;
371760484Sobrien}
371860484Sobrien
371960484Sobrienstatic const char *
372060484Sobrienget_dynamic_flags (flags)
372160484Sobrien     bfd_vma flags;
372260484Sobrien{
372360484Sobrien  static char buff [64];
372460484Sobrien  while (flags)
372560484Sobrien    {
372660484Sobrien      bfd_vma flag;
372760484Sobrien
372860484Sobrien      flag = flags & - flags;
372960484Sobrien      flags &= ~ flag;
373060484Sobrien
373160484Sobrien      switch (flag)
373260484Sobrien	{
373360484Sobrien	case DF_ORIGIN:   strcat (buff, "ORIGIN "); break;
373460484Sobrien	case DF_SYMBOLIC: strcat (buff, "SYMBOLIC "); break;
373560484Sobrien	case DF_TEXTREL:  strcat (buff, "TEXTREL "); break;
373660484Sobrien	case DF_BIND_NOW: strcat (buff, "BIND_NOW "); break;
373760484Sobrien	default:          strcat (buff, "unknown "); break;
373860484Sobrien	}
373960484Sobrien    }
374060484Sobrien  return buff;
374160484Sobrien}
374260484Sobrien
374360484Sobrien/* Parse and display the contents of the dynamic segment.  */
374460484Sobrienstatic int
374560484Sobrienprocess_dynamic_segment (file)
374660484Sobrien     FILE * file;
374760484Sobrien{
374860484Sobrien  Elf_Internal_Dyn * entry;
374960484Sobrien  bfd_size_type      i;
375060484Sobrien
375160484Sobrien  if (dynamic_size == 0)
375260484Sobrien    {
375360484Sobrien      if (do_dynamic)
375460484Sobrien	printf (_("\nThere is no dynamic segment in this file.\n"));
375560484Sobrien
375660484Sobrien      return 1;
375760484Sobrien    }
375860484Sobrien
375960484Sobrien  if (is_32bit_elf)
376060484Sobrien    {
376160484Sobrien      if (! get_32bit_dynamic_segment (file))
376260484Sobrien	return 0;
376360484Sobrien    }
376460484Sobrien  else if (! get_64bit_dynamic_segment (file))
376560484Sobrien    return 0;
376660484Sobrien
376760484Sobrien  /* Find the appropriate symbol table.  */
376860484Sobrien  if (dynamic_symbols == NULL)
376960484Sobrien    {
377060484Sobrien      for (i = 0, entry = dynamic_segment;
377160484Sobrien	   i < dynamic_size;
377260484Sobrien	   ++i, ++ entry)
377360484Sobrien	{
377460484Sobrien	  unsigned long        offset;
377560484Sobrien
377660484Sobrien	  if (entry->d_tag != DT_SYMTAB)
377760484Sobrien	    continue;
377860484Sobrien
377960484Sobrien	  dynamic_info[DT_SYMTAB] = entry->d_un.d_val;
378060484Sobrien
378160484Sobrien	  /* Since we do not know how big the symbol table is,
378260484Sobrien	     we default to reading in the entire file (!) and
378360484Sobrien	     processing that.  This is overkill, I know, but it
378460484Sobrien	     should work. */
378560484Sobrien	  offset = entry->d_un.d_val - loadaddr;
378660484Sobrien
378760484Sobrien	  if (fseek (file, 0, SEEK_END))
378860484Sobrien	    error (_("Unable to seek to end of file!"));
378960484Sobrien
379060484Sobrien	  if (is_32bit_elf)
379160484Sobrien	    num_dynamic_syms = (ftell (file) - offset) / sizeof (Elf32_External_Sym);
379260484Sobrien	  else
379360484Sobrien	    num_dynamic_syms = (ftell (file) - offset) / sizeof (Elf64_External_Sym);
379460484Sobrien
379560484Sobrien	  if (num_dynamic_syms < 1)
379660484Sobrien	    {
379760484Sobrien	      error (_("Unable to determine the number of symbols to load\n"));
379860484Sobrien	      continue;
379960484Sobrien	    }
380060484Sobrien
380160484Sobrien	  dynamic_symbols = GET_ELF_SYMBOLS (file, offset, num_dynamic_syms);
380260484Sobrien	}
380360484Sobrien    }
380460484Sobrien
380560484Sobrien  /* Similarly find a string table.  */
380660484Sobrien  if (dynamic_strings == NULL)
380760484Sobrien    {
380860484Sobrien      for (i = 0, entry = dynamic_segment;
380960484Sobrien	   i < dynamic_size;
381060484Sobrien	   ++i, ++ entry)
381160484Sobrien	{
381260484Sobrien	  unsigned long offset;
381360484Sobrien	  long          str_tab_len;
381460484Sobrien
381560484Sobrien	  if (entry->d_tag != DT_STRTAB)
381660484Sobrien	    continue;
381760484Sobrien
381860484Sobrien	  dynamic_info[DT_STRTAB] = entry->d_un.d_val;
381960484Sobrien
382060484Sobrien	  /* Since we do not know how big the string table is,
382160484Sobrien	     we default to reading in the entire file (!) and
382260484Sobrien	     processing that.  This is overkill, I know, but it
382360484Sobrien	     should work. */
382460484Sobrien
382560484Sobrien	  offset = entry->d_un.d_val - loadaddr;
382660484Sobrien	  if (fseek (file, 0, SEEK_END))
382760484Sobrien	    error (_("Unable to seek to end of file\n"));
382860484Sobrien	  str_tab_len = ftell (file) - offset;
382960484Sobrien
383060484Sobrien	  if (str_tab_len < 1)
383160484Sobrien	    {
383260484Sobrien	      error
383360484Sobrien		(_("Unable to determine the length of the dynamic string table\n"));
383460484Sobrien	      continue;
383560484Sobrien	    }
383660484Sobrien
383760484Sobrien	  GET_DATA_ALLOC (offset, str_tab_len, dynamic_strings, char *,
383860484Sobrien			  "dynamic string table");
383960484Sobrien
384060484Sobrien	  break;
384160484Sobrien	}
384260484Sobrien    }
384360484Sobrien
384460484Sobrien  /* And find the syminfo section if available.  */
384560484Sobrien  if (dynamic_syminfo == NULL)
384660484Sobrien    {
384760484Sobrien      unsigned int syminsz = 0;
384860484Sobrien
384960484Sobrien      for (i = 0, entry = dynamic_segment;
385060484Sobrien	   i < dynamic_size;
385160484Sobrien	   ++i, ++ entry)
385260484Sobrien	{
385360484Sobrien	  if (entry->d_tag == DT_SYMINENT)
385460484Sobrien	    {
385560484Sobrien	      /* Note: these braces are necessary to avoid a syntax
385660484Sobrien		 error from the SunOS4 C compiler.  */
385760484Sobrien	      assert (sizeof (Elf_External_Syminfo) == entry->d_un.d_val);
385860484Sobrien	    }
385960484Sobrien	  else if (entry->d_tag == DT_SYMINSZ)
386060484Sobrien	    syminsz = entry->d_un.d_val;
386160484Sobrien	  else if (entry->d_tag == DT_SYMINFO)
386260484Sobrien	    dynamic_syminfo_offset = entry->d_un.d_val - loadaddr;
386360484Sobrien	}
386460484Sobrien
386560484Sobrien      if (dynamic_syminfo_offset != 0 && syminsz != 0)
386660484Sobrien	{
386760484Sobrien	  Elf_External_Syminfo * extsyminfo;
386860484Sobrien	  Elf_Internal_Syminfo * syminfo;
386960484Sobrien
387060484Sobrien	  /* There is a syminfo section.  Read the data.  */
387160484Sobrien	  GET_DATA_ALLOC (dynamic_syminfo_offset, syminsz, extsyminfo,
387260484Sobrien			  Elf_External_Syminfo *, "symbol information");
387360484Sobrien
387460484Sobrien	  dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz);
387560484Sobrien	  if (dynamic_syminfo == NULL)
387660484Sobrien	    {
387760484Sobrien	      error (_("Out of memory\n"));
387860484Sobrien	      return 0;
387960484Sobrien	    }
388060484Sobrien
388160484Sobrien	  dynamic_syminfo_nent = syminsz / sizeof (Elf_External_Syminfo);
388260484Sobrien	  for (i = 0, syminfo = dynamic_syminfo; i < dynamic_syminfo_nent;
388360484Sobrien	       ++i, ++syminfo)
388460484Sobrien	    {
388560484Sobrien	      syminfo->si_boundto = BYTE_GET (extsyminfo[i].si_boundto);
388660484Sobrien	      syminfo->si_flags = BYTE_GET (extsyminfo[i].si_flags);
388760484Sobrien	    }
388860484Sobrien
388960484Sobrien	  free (extsyminfo);
389060484Sobrien	}
389160484Sobrien    }
389260484Sobrien
389360484Sobrien  if (do_dynamic && dynamic_addr)
389460484Sobrien    printf (_("\nDynamic segment at offset 0x%x contains %ld entries:\n"),
389560484Sobrien	    dynamic_addr, (long) dynamic_size);
389660484Sobrien  if (do_dynamic)
389760484Sobrien    printf (_("  Tag        Type                         Name/Value\n"));
389860484Sobrien
389960484Sobrien  for (i = 0, entry = dynamic_segment;
390060484Sobrien       i < dynamic_size;
390160484Sobrien       i++, entry ++)
390260484Sobrien    {
390360484Sobrien      if (do_dynamic)
390460484Sobrien	{
390577298Sobrien	  const char * dtype;
390660484Sobrien
390760484Sobrien	  putchar (' ');
390860484Sobrien	  print_vma (entry->d_tag, FULL_HEX);
390960484Sobrien	  dtype = get_dynamic_type (entry->d_tag);
391060484Sobrien	  printf (" (%s)%*s", dtype,
391160484Sobrien		  ((is_32bit_elf ? 27 : 19)
391260484Sobrien		   - (int) strlen (dtype)),
391360484Sobrien		  " ");
391460484Sobrien	}
391560484Sobrien
391660484Sobrien      switch (entry->d_tag)
391760484Sobrien	{
391860484Sobrien	case DT_FLAGS:
391960484Sobrien	  if (do_dynamic)
392060484Sobrien	    printf ("%s", get_dynamic_flags (entry->d_un.d_val));
392160484Sobrien	  break;
392277298Sobrien
392360484Sobrien	case DT_AUXILIARY:
392460484Sobrien	case DT_FILTER:
392568765Sobrien	case DT_CONFIG:
392668765Sobrien	case DT_DEPAUDIT:
392768765Sobrien	case DT_AUDIT:
392860484Sobrien	  if (do_dynamic)
392960484Sobrien	    {
393068765Sobrien	      switch (entry->d_tag)
393168765Sobrien	        {
393268765Sobrien		case DT_AUXILIARY:
393368765Sobrien		  printf (_("Auxiliary library"));
393468765Sobrien		  break;
393560484Sobrien
393668765Sobrien		case DT_FILTER:
393768765Sobrien		  printf (_("Filter library"));
393868765Sobrien		  break;
393968765Sobrien
394068765Sobrien	        case DT_CONFIG:
394168765Sobrien		  printf (_("Configuration file"));
394268765Sobrien		  break;
394368765Sobrien
394468765Sobrien		case DT_DEPAUDIT:
394568765Sobrien		  printf (_("Dependency audit library"));
394668765Sobrien		  break;
394768765Sobrien
394868765Sobrien		case DT_AUDIT:
394968765Sobrien		  printf (_("Audit library"));
395068765Sobrien		  break;
395168765Sobrien		}
395268765Sobrien
395360484Sobrien	      if (dynamic_strings)
395460484Sobrien		printf (": [%s]\n", dynamic_strings + entry->d_un.d_val);
395560484Sobrien	      else
395660484Sobrien		{
395760484Sobrien		  printf (": ");
395860484Sobrien		  print_vma (entry->d_un.d_val, PREFIX_HEX);
395960484Sobrien		  putchar ('\n');
396060484Sobrien		}
396160484Sobrien	    }
396260484Sobrien	  break;
396360484Sobrien
396468765Sobrien	case DT_FEATURE:
396560484Sobrien	  if (do_dynamic)
396660484Sobrien	    {
396760484Sobrien	      printf (_("Flags:"));
396860484Sobrien	      if (entry->d_un.d_val == 0)
396960484Sobrien		printf (_(" None\n"));
397060484Sobrien	      else
397160484Sobrien		{
397260484Sobrien		  unsigned long int val = entry->d_un.d_val;
397360484Sobrien		  if (val & DTF_1_PARINIT)
397460484Sobrien		    {
397560484Sobrien		      printf (" PARINIT");
397660484Sobrien		      val ^= DTF_1_PARINIT;
397760484Sobrien		    }
397868765Sobrien		  if (val & DTF_1_CONFEXP)
397968765Sobrien		    {
398068765Sobrien		      printf (" CONFEXP");
398168765Sobrien		      val ^= DTF_1_CONFEXP;
398268765Sobrien		    }
398360484Sobrien		  if (val != 0)
398460484Sobrien		    printf (" %lx", val);
398560484Sobrien		  puts ("");
398660484Sobrien		}
398760484Sobrien	    }
398860484Sobrien	  break;
398960484Sobrien
399060484Sobrien	case DT_POSFLAG_1:
399160484Sobrien	  if (do_dynamic)
399260484Sobrien	    {
399360484Sobrien	      printf (_("Flags:"));
399460484Sobrien	      if (entry->d_un.d_val == 0)
399560484Sobrien		printf (_(" None\n"));
399660484Sobrien	      else
399760484Sobrien		{
399860484Sobrien		  unsigned long int val = entry->d_un.d_val;
399960484Sobrien		  if (val & DF_P1_LAZYLOAD)
400060484Sobrien		    {
400160484Sobrien		      printf (" LAZYLOAD");
400260484Sobrien		      val ^= DF_P1_LAZYLOAD;
400360484Sobrien		    }
400460484Sobrien		  if (val & DF_P1_GROUPPERM)
400560484Sobrien		    {
400660484Sobrien		      printf (" GROUPPERM");
400760484Sobrien		      val ^= DF_P1_GROUPPERM;
400860484Sobrien		    }
400960484Sobrien		  if (val != 0)
401060484Sobrien		    printf (" %lx", val);
401160484Sobrien		  puts ("");
401260484Sobrien		}
401360484Sobrien	    }
401460484Sobrien	  break;
401560484Sobrien
401660484Sobrien	case DT_FLAGS_1:
401760484Sobrien	  if (do_dynamic)
401860484Sobrien	    {
401960484Sobrien	      printf (_("Flags:"));
402060484Sobrien	      if (entry->d_un.d_val == 0)
402160484Sobrien		printf (_(" None\n"));
402260484Sobrien	      else
402360484Sobrien		{
402460484Sobrien		  unsigned long int val = entry->d_un.d_val;
402560484Sobrien		  if (val & DF_1_NOW)
402660484Sobrien		    {
402760484Sobrien		      printf (" NOW");
402860484Sobrien		      val ^= DF_1_NOW;
402960484Sobrien		    }
403060484Sobrien		  if (val & DF_1_GLOBAL)
403160484Sobrien		    {
403260484Sobrien		      printf (" GLOBAL");
403360484Sobrien		      val ^= DF_1_GLOBAL;
403460484Sobrien		    }
403560484Sobrien		  if (val & DF_1_GROUP)
403660484Sobrien		    {
403760484Sobrien		      printf (" GROUP");
403860484Sobrien		      val ^= DF_1_GROUP;
403960484Sobrien		    }
404060484Sobrien		  if (val & DF_1_NODELETE)
404160484Sobrien		    {
404260484Sobrien		      printf (" NODELETE");
404360484Sobrien		      val ^= DF_1_NODELETE;
404460484Sobrien		    }
404560484Sobrien		  if (val & DF_1_LOADFLTR)
404660484Sobrien		    {
404760484Sobrien		      printf (" LOADFLTR");
404860484Sobrien		      val ^= DF_1_LOADFLTR;
404960484Sobrien		    }
405060484Sobrien		  if (val & DF_1_INITFIRST)
405160484Sobrien		    {
405260484Sobrien		      printf (" INITFIRST");
405360484Sobrien		      val ^= DF_1_INITFIRST;
405460484Sobrien		    }
405560484Sobrien		  if (val & DF_1_NOOPEN)
405660484Sobrien		    {
405760484Sobrien		      printf (" NOOPEN");
405860484Sobrien		      val ^= DF_1_NOOPEN;
405960484Sobrien		    }
406060484Sobrien		  if (val & DF_1_ORIGIN)
406160484Sobrien		    {
406260484Sobrien		      printf (" ORIGIN");
406360484Sobrien		      val ^= DF_1_ORIGIN;
406460484Sobrien		    }
406560484Sobrien		  if (val & DF_1_DIRECT)
406660484Sobrien		    {
406760484Sobrien		      printf (" DIRECT");
406860484Sobrien		      val ^= DF_1_DIRECT;
406960484Sobrien		    }
407060484Sobrien		  if (val & DF_1_TRANS)
407160484Sobrien		    {
407260484Sobrien		      printf (" TRANS");
407360484Sobrien		      val ^= DF_1_TRANS;
407460484Sobrien		    }
407560484Sobrien		  if (val & DF_1_INTERPOSE)
407660484Sobrien		    {
407760484Sobrien		      printf (" INTERPOSE");
407860484Sobrien		      val ^= DF_1_INTERPOSE;
407960484Sobrien		    }
408068765Sobrien		  if (val & DF_1_NODEFLIB)
408168765Sobrien		    {
408268765Sobrien		      printf (" NODEFLIB");
408368765Sobrien		      val ^= DF_1_NODEFLIB;
408468765Sobrien		    }
408568765Sobrien		  if (val & DF_1_NODUMP)
408668765Sobrien		    {
408768765Sobrien		      printf (" NODUMP");
408868765Sobrien		      val ^= DF_1_NODUMP;
408968765Sobrien		    }
409068765Sobrien		  if (val & DF_1_CONLFAT)
409168765Sobrien		    {
409268765Sobrien		      printf (" CONLFAT");
409368765Sobrien		      val ^= DF_1_CONLFAT;
409468765Sobrien		    }
409560484Sobrien		  if (val != 0)
409660484Sobrien		    printf (" %lx", val);
409760484Sobrien		  puts ("");
409860484Sobrien		}
409960484Sobrien	    }
410060484Sobrien	  break;
410160484Sobrien
410260484Sobrien	case DT_PLTREL:
410360484Sobrien	  if (do_dynamic)
410460484Sobrien	    puts (get_dynamic_type (entry->d_un.d_val));
410560484Sobrien	  break;
410660484Sobrien
410760484Sobrien	case DT_NULL	:
410860484Sobrien	case DT_NEEDED	:
410960484Sobrien	case DT_PLTGOT	:
411060484Sobrien	case DT_HASH	:
411160484Sobrien	case DT_STRTAB	:
411260484Sobrien	case DT_SYMTAB	:
411360484Sobrien	case DT_RELA	:
411460484Sobrien	case DT_INIT	:
411560484Sobrien	case DT_FINI	:
411660484Sobrien	case DT_SONAME	:
411760484Sobrien	case DT_RPATH	:
411860484Sobrien	case DT_SYMBOLIC:
411960484Sobrien	case DT_REL	:
412060484Sobrien	case DT_DEBUG	:
412160484Sobrien	case DT_TEXTREL	:
412260484Sobrien	case DT_JMPREL	:
412368765Sobrien	case DT_RUNPATH	:
412460484Sobrien	  dynamic_info[entry->d_tag] = entry->d_un.d_val;
412560484Sobrien
412660484Sobrien	  if (do_dynamic)
412760484Sobrien	    {
412860484Sobrien	      char * name;
412960484Sobrien
413060484Sobrien	      if (dynamic_strings == NULL)
413160484Sobrien		name = NULL;
413260484Sobrien	      else
413360484Sobrien		name = dynamic_strings + entry->d_un.d_val;
413460484Sobrien
413560484Sobrien	      if (name)
413660484Sobrien		{
413760484Sobrien		  switch (entry->d_tag)
413860484Sobrien		    {
413960484Sobrien		    case DT_NEEDED:
414060484Sobrien		      printf (_("Shared library: [%s]"), name);
414160484Sobrien
414260484Sobrien		      if (strcmp (name, program_interpreter) == 0)
414360484Sobrien			printf (_(" program interpreter"));
414460484Sobrien		      break;
414560484Sobrien
414660484Sobrien		    case DT_SONAME:
414760484Sobrien		      printf (_("Library soname: [%s]"), name);
414860484Sobrien		      break;
414960484Sobrien
415060484Sobrien		    case DT_RPATH:
415160484Sobrien		      printf (_("Library rpath: [%s]"), name);
415260484Sobrien		      break;
415360484Sobrien
415468765Sobrien		    case DT_RUNPATH:
415568765Sobrien		      printf (_("Library runpath: [%s]"), name);
415668765Sobrien		      break;
415768765Sobrien
415860484Sobrien		    default:
415960484Sobrien		      print_vma (entry->d_un.d_val, PREFIX_HEX);
416060484Sobrien		      break;
416160484Sobrien		    }
416260484Sobrien		}
416360484Sobrien	      else
416460484Sobrien		print_vma (entry->d_un.d_val, PREFIX_HEX);
416560484Sobrien
416660484Sobrien	      putchar ('\n');
416760484Sobrien	    }
416860484Sobrien	  break;
416960484Sobrien
417060484Sobrien	case DT_PLTRELSZ:
417160484Sobrien	case DT_RELASZ	:
417260484Sobrien	case DT_STRSZ	:
417360484Sobrien	case DT_RELSZ	:
417460484Sobrien	case DT_RELAENT	:
417560484Sobrien	case DT_SYMENT	:
417660484Sobrien	case DT_RELENT	:
417760484Sobrien	case DT_PLTPADSZ:
417860484Sobrien	case DT_MOVEENT	:
417960484Sobrien	case DT_MOVESZ	:
418060484Sobrien	case DT_INIT_ARRAYSZ:
418160484Sobrien	case DT_FINI_ARRAYSZ:
418260484Sobrien	  if (do_dynamic)
418360484Sobrien	    {
418460484Sobrien	      print_vma (entry->d_un.d_val, UNSIGNED);
418560484Sobrien	      printf (" (bytes)\n");
418660484Sobrien	    }
418760484Sobrien	  break;
418860484Sobrien
418960484Sobrien	case DT_VERDEFNUM:
419060484Sobrien	case DT_VERNEEDNUM:
419160484Sobrien	case DT_RELACOUNT:
419260484Sobrien	case DT_RELCOUNT:
419360484Sobrien	  if (do_dynamic)
419460484Sobrien	    {
419560484Sobrien	      print_vma (entry->d_un.d_val, UNSIGNED);
419660484Sobrien	      putchar ('\n');
419760484Sobrien	    }
419860484Sobrien	  break;
419960484Sobrien
420060484Sobrien	case DT_SYMINSZ:
420160484Sobrien	case DT_SYMINENT:
420260484Sobrien	case DT_SYMINFO:
420360484Sobrien	case DT_USED:
420460484Sobrien	case DT_INIT_ARRAY:
420560484Sobrien	case DT_FINI_ARRAY:
420660484Sobrien	  if (do_dynamic)
420760484Sobrien	    {
420860484Sobrien	      if (dynamic_strings != NULL && entry->d_tag == DT_USED)
420960484Sobrien		{
421060484Sobrien		  char * name;
421160484Sobrien
421260484Sobrien		  name = dynamic_strings + entry->d_un.d_val;
421360484Sobrien
421460484Sobrien		  if (* name)
421560484Sobrien		    {
421660484Sobrien		      printf (_("Not needed object: [%s]\n"), name);
421760484Sobrien		      break;
421860484Sobrien		    }
421960484Sobrien		}
422060484Sobrien
422160484Sobrien	      print_vma (entry->d_un.d_val, PREFIX_HEX);
422260484Sobrien	      putchar ('\n');
422360484Sobrien	    }
422460484Sobrien	  break;
422560484Sobrien
422660484Sobrien	case DT_BIND_NOW:
422760484Sobrien	  /* The value of this entry is ignored.  */
422860484Sobrien	  break;
422960484Sobrien
423060484Sobrien	default:
423160484Sobrien	  if ((entry->d_tag >= DT_VERSYM) && (entry->d_tag <= DT_VERNEEDNUM))
423260484Sobrien	    version_info [DT_VERSIONTAGIDX (entry->d_tag)] =
423360484Sobrien	      entry->d_un.d_val;
423460484Sobrien
423560484Sobrien	  if (do_dynamic)
423660484Sobrien	    {
423760484Sobrien	      switch (elf_header.e_machine)
423860484Sobrien		{
423960484Sobrien		case EM_MIPS:
424078828Sobrien		case EM_MIPS_RS3_LE:
424160484Sobrien		  dynamic_segment_mips_val (entry);
424260484Sobrien		  break;
424360484Sobrien		case EM_PARISC:
424460484Sobrien		  dynamic_segment_parisc_val (entry);
424560484Sobrien		  break;
424660484Sobrien		default:
424760484Sobrien		  print_vma (entry->d_un.d_val, PREFIX_HEX);
424860484Sobrien		  putchar ('\n');
424960484Sobrien		}
425060484Sobrien	    }
425160484Sobrien	  break;
425260484Sobrien	}
425360484Sobrien    }
425460484Sobrien
425560484Sobrien  return 1;
425660484Sobrien}
425760484Sobrien
425860484Sobrienstatic char *
425960484Sobrienget_ver_flags (flags)
426060484Sobrien     unsigned int flags;
426160484Sobrien{
426260484Sobrien  static char buff [32];
426360484Sobrien
426460484Sobrien  buff[0] = 0;
426560484Sobrien
426660484Sobrien  if (flags == 0)
426760484Sobrien    return _("none");
426860484Sobrien
426960484Sobrien  if (flags & VER_FLG_BASE)
427060484Sobrien    strcat (buff, "BASE ");
427160484Sobrien
427260484Sobrien  if (flags & VER_FLG_WEAK)
427360484Sobrien    {
427460484Sobrien      if (flags & VER_FLG_BASE)
427560484Sobrien	strcat (buff, "| ");
427660484Sobrien
427760484Sobrien      strcat (buff, "WEAK ");
427860484Sobrien    }
427960484Sobrien
428060484Sobrien  if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK))
428160484Sobrien    strcat (buff, "| <unknown>");
428260484Sobrien
428360484Sobrien  return buff;
428460484Sobrien}
428560484Sobrien
428660484Sobrien/* Display the contents of the version sections.  */
428760484Sobrienstatic int
428860484Sobrienprocess_version_sections (file)
428960484Sobrien     FILE * file;
429060484Sobrien{
429160484Sobrien  Elf32_Internal_Shdr * section;
429260484Sobrien  unsigned   i;
429360484Sobrien  int        found = 0;
429460484Sobrien
429560484Sobrien  if (! do_version)
429660484Sobrien    return 1;
429760484Sobrien
429860484Sobrien  for (i = 0, section = section_headers;
429960484Sobrien       i < elf_header.e_shnum;
430060484Sobrien       i++, section ++)
430160484Sobrien    {
430260484Sobrien      switch (section->sh_type)
430360484Sobrien	{
430460484Sobrien	case SHT_GNU_verdef:
430560484Sobrien	  {
430660484Sobrien	    Elf_External_Verdef * edefs;
430760484Sobrien	    unsigned int          idx;
430860484Sobrien	    unsigned int          cnt;
430960484Sobrien
431060484Sobrien	    found = 1;
431160484Sobrien
431260484Sobrien	    printf
431360484Sobrien	      (_("\nVersion definition section '%s' contains %ld entries:\n"),
431460484Sobrien	       SECTION_NAME (section), section->sh_info);
431560484Sobrien
431660484Sobrien	    printf (_("  Addr: 0x"));
431760484Sobrien	    printf_vma (section->sh_addr);
431860484Sobrien	    printf (_("  Offset: %#08lx  Link: %lx (%s)\n"),
431960484Sobrien		    (unsigned long) section->sh_offset, section->sh_link,
432060484Sobrien		    SECTION_NAME (section_headers + section->sh_link));
432160484Sobrien
432260484Sobrien	    GET_DATA_ALLOC (section->sh_offset, section->sh_size,
432360484Sobrien			    edefs, Elf_External_Verdef *,
432460484Sobrien			    "version definition section");
432560484Sobrien
432660484Sobrien	    for (idx = cnt = 0; cnt < section->sh_info; ++ cnt)
432760484Sobrien	      {
432860484Sobrien		char *                 vstart;
432960484Sobrien		Elf_External_Verdef *  edef;
433060484Sobrien		Elf_Internal_Verdef    ent;
433160484Sobrien		Elf_External_Verdaux * eaux;
433260484Sobrien		Elf_Internal_Verdaux   aux;
433360484Sobrien		int                    j;
433460484Sobrien		int                    isum;
433560484Sobrien
433660484Sobrien		vstart = ((char *) edefs) + idx;
433760484Sobrien
433860484Sobrien		edef = (Elf_External_Verdef *) vstart;
433960484Sobrien
434060484Sobrien		ent.vd_version = BYTE_GET (edef->vd_version);
434160484Sobrien		ent.vd_flags   = BYTE_GET (edef->vd_flags);
434260484Sobrien		ent.vd_ndx     = BYTE_GET (edef->vd_ndx);
434360484Sobrien		ent.vd_cnt     = BYTE_GET (edef->vd_cnt);
434460484Sobrien		ent.vd_hash    = BYTE_GET (edef->vd_hash);
434560484Sobrien		ent.vd_aux     = BYTE_GET (edef->vd_aux);
434660484Sobrien		ent.vd_next    = BYTE_GET (edef->vd_next);
434760484Sobrien
434860484Sobrien		printf (_("  %#06x: Rev: %d  Flags: %s"),
434960484Sobrien			idx, ent.vd_version, get_ver_flags (ent.vd_flags));
435060484Sobrien
435160484Sobrien		printf (_("  Index: %d  Cnt: %d  "),
435260484Sobrien			ent.vd_ndx, ent.vd_cnt);
435360484Sobrien
435460484Sobrien		vstart += ent.vd_aux;
435560484Sobrien
435660484Sobrien		eaux = (Elf_External_Verdaux *) vstart;
435760484Sobrien
435860484Sobrien		aux.vda_name = BYTE_GET (eaux->vda_name);
435960484Sobrien		aux.vda_next = BYTE_GET (eaux->vda_next);
436060484Sobrien
436160484Sobrien		if (dynamic_strings)
436260484Sobrien		  printf (_("Name: %s\n"), dynamic_strings + aux.vda_name);
436360484Sobrien		else
436460484Sobrien		  printf (_("Name index: %ld\n"), aux.vda_name);
436560484Sobrien
436660484Sobrien		isum = idx + ent.vd_aux;
436760484Sobrien
436860484Sobrien		for (j = 1; j < ent.vd_cnt; j ++)
436960484Sobrien		  {
437060484Sobrien		    isum   += aux.vda_next;
437160484Sobrien		    vstart += aux.vda_next;
437260484Sobrien
437360484Sobrien		    eaux = (Elf_External_Verdaux *) vstart;
437460484Sobrien
437560484Sobrien		    aux.vda_name = BYTE_GET (eaux->vda_name);
437660484Sobrien		    aux.vda_next = BYTE_GET (eaux->vda_next);
437760484Sobrien
437860484Sobrien		    if (dynamic_strings)
437960484Sobrien		      printf (_("  %#06x: Parent %d: %s\n"),
438060484Sobrien			      isum, j, dynamic_strings + aux.vda_name);
438160484Sobrien		    else
438260484Sobrien		      printf (_("  %#06x: Parent %d, name index: %ld\n"),
438360484Sobrien			      isum, j, aux.vda_name);
438460484Sobrien		  }
438560484Sobrien
438660484Sobrien		idx += ent.vd_next;
438760484Sobrien	      }
438860484Sobrien
438960484Sobrien	    free (edefs);
439060484Sobrien	  }
439160484Sobrien	  break;
439260484Sobrien
439360484Sobrien	case SHT_GNU_verneed:
439460484Sobrien	  {
439560484Sobrien	    Elf_External_Verneed *  eneed;
439660484Sobrien	    unsigned int            idx;
439760484Sobrien	    unsigned int            cnt;
439860484Sobrien
439960484Sobrien	    found = 1;
440060484Sobrien
440160484Sobrien	    printf (_("\nVersion needs section '%s' contains %ld entries:\n"),
440260484Sobrien		    SECTION_NAME (section), section->sh_info);
440360484Sobrien
440460484Sobrien	    printf (_(" Addr: 0x"));
440560484Sobrien	    printf_vma (section->sh_addr);
440660484Sobrien	    printf (_("  Offset: %#08lx  Link to section: %ld (%s)\n"),
440760484Sobrien		    (unsigned long) section->sh_offset, section->sh_link,
440860484Sobrien		    SECTION_NAME (section_headers + section->sh_link));
440960484Sobrien
441060484Sobrien	    GET_DATA_ALLOC (section->sh_offset, section->sh_size,
441160484Sobrien			    eneed, Elf_External_Verneed *,
441260484Sobrien			    "version need section");
441360484Sobrien
441460484Sobrien	    for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
441560484Sobrien	      {
441660484Sobrien		Elf_External_Verneed * entry;
441760484Sobrien		Elf_Internal_Verneed     ent;
441860484Sobrien		int                      j;
441960484Sobrien		int                      isum;
442060484Sobrien		char *                   vstart;
442160484Sobrien
442260484Sobrien		vstart = ((char *) eneed) + idx;
442360484Sobrien
442460484Sobrien		entry = (Elf_External_Verneed *) vstart;
442560484Sobrien
442660484Sobrien		ent.vn_version = BYTE_GET (entry->vn_version);
442760484Sobrien		ent.vn_cnt     = BYTE_GET (entry->vn_cnt);
442860484Sobrien		ent.vn_file    = BYTE_GET (entry->vn_file);
442960484Sobrien		ent.vn_aux     = BYTE_GET (entry->vn_aux);
443060484Sobrien		ent.vn_next    = BYTE_GET (entry->vn_next);
443160484Sobrien
443260484Sobrien		printf (_("  %#06x: Version: %d"), idx, ent.vn_version);
443360484Sobrien
443460484Sobrien		if (dynamic_strings)
443560484Sobrien		  printf (_("  File: %s"), dynamic_strings + ent.vn_file);
443660484Sobrien		else
443760484Sobrien		  printf (_("  File: %lx"), ent.vn_file);
443860484Sobrien
443960484Sobrien		printf (_("  Cnt: %d\n"), ent.vn_cnt);
444060484Sobrien
444160484Sobrien		vstart += ent.vn_aux;
444260484Sobrien
444360484Sobrien		for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j)
444460484Sobrien		  {
444560484Sobrien		    Elf_External_Vernaux * eaux;
444660484Sobrien		    Elf_Internal_Vernaux   aux;
444760484Sobrien
444860484Sobrien		    eaux = (Elf_External_Vernaux *) vstart;
444960484Sobrien
445060484Sobrien		    aux.vna_hash  = BYTE_GET (eaux->vna_hash);
445160484Sobrien		    aux.vna_flags = BYTE_GET (eaux->vna_flags);
445260484Sobrien		    aux.vna_other = BYTE_GET (eaux->vna_other);
445360484Sobrien		    aux.vna_name  = BYTE_GET (eaux->vna_name);
445460484Sobrien		    aux.vna_next  = BYTE_GET (eaux->vna_next);
445560484Sobrien
445660484Sobrien		    if (dynamic_strings)
445760484Sobrien		      printf (_("  %#06x: Name: %s"),
445860484Sobrien			      isum, dynamic_strings + aux.vna_name);
445960484Sobrien		    else
446060484Sobrien		      printf (_("  %#06x: Name index: %lx"),
446160484Sobrien			      isum, aux.vna_name);
446260484Sobrien
446360484Sobrien		    printf (_("  Flags: %s  Version: %d\n"),
446460484Sobrien			    get_ver_flags (aux.vna_flags), aux.vna_other);
446560484Sobrien
446660484Sobrien		    isum   += aux.vna_next;
446760484Sobrien		    vstart += aux.vna_next;
446860484Sobrien		  }
446960484Sobrien
447060484Sobrien		idx += ent.vn_next;
447160484Sobrien	      }
447260484Sobrien
447360484Sobrien	    free (eneed);
447460484Sobrien	  }
447560484Sobrien	  break;
447660484Sobrien
447760484Sobrien	case SHT_GNU_versym:
447860484Sobrien	  {
447960484Sobrien	    Elf32_Internal_Shdr *       link_section;
448078828Sobrien	    int		total;
448178828Sobrien	    int		cnt;
448278828Sobrien	    unsigned char *		edata;
448378828Sobrien	    unsigned short *		data;
448478828Sobrien	    char *		strtab;
448578828Sobrien	    Elf_Internal_Sym *		symbols;
448660484Sobrien	    Elf32_Internal_Shdr *       string_sec;
448760484Sobrien
448860484Sobrien	    link_section = section_headers + section->sh_link;
448960484Sobrien	    total = section->sh_size / section->sh_entsize;
449060484Sobrien
449160484Sobrien	    found = 1;
449260484Sobrien
449360484Sobrien	    symbols = GET_ELF_SYMBOLS (file, link_section->sh_offset,
449460484Sobrien				       link_section->sh_size / link_section->sh_entsize);
449560484Sobrien
449660484Sobrien	    string_sec = section_headers + link_section->sh_link;
449760484Sobrien
449860484Sobrien	    GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
449960484Sobrien			    strtab, char *, "version string table");
450060484Sobrien
450160484Sobrien	    printf (_("\nVersion symbols section '%s' contains %d entries:\n"),
450260484Sobrien		    SECTION_NAME (section), total);
450360484Sobrien
450460484Sobrien	    printf (_(" Addr: "));
450560484Sobrien	    printf_vma (section->sh_addr);
450660484Sobrien	    printf (_("  Offset: %#08lx  Link: %lx (%s)\n"),
450760484Sobrien		    (unsigned long) section->sh_offset, section->sh_link,
450860484Sobrien		    SECTION_NAME (link_section));
450960484Sobrien
451060484Sobrien	    GET_DATA_ALLOC (version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
451160484Sobrien			    - loadaddr,
451260484Sobrien			    total * sizeof (short), edata,
451360484Sobrien			    unsigned char *, "version symbol data");
451460484Sobrien
451560484Sobrien	    data = (unsigned short *) malloc (total * sizeof (short));
451660484Sobrien
451760484Sobrien	    for (cnt = total; cnt --;)
451860484Sobrien	      data [cnt] = byte_get (edata + cnt * sizeof (short),
451960484Sobrien				     sizeof (short));
452060484Sobrien
452160484Sobrien	    free (edata);
452260484Sobrien
452360484Sobrien	    for (cnt = 0; cnt < total; cnt += 4)
452460484Sobrien	      {
452560484Sobrien		int j, nn;
452677298Sobrien		int check_def, check_need;
452777298Sobrien		char * name;
452860484Sobrien
452960484Sobrien		printf ("  %03x:", cnt);
453060484Sobrien
453160484Sobrien		for (j = 0; (j < 4) && (cnt + j) < total; ++j)
453260484Sobrien		  switch (data [cnt + j])
453360484Sobrien		    {
453460484Sobrien		    case 0:
453560484Sobrien		      fputs (_("   0 (*local*)    "), stdout);
453660484Sobrien		      break;
453760484Sobrien
453860484Sobrien		    case 1:
453960484Sobrien		      fputs (_("   1 (*global*)   "), stdout);
454060484Sobrien		      break;
454160484Sobrien
454260484Sobrien		    default:
454360484Sobrien		      nn = printf ("%4x%c", data [cnt + j] & 0x7fff,
454460484Sobrien				   data [cnt + j] & 0x8000 ? 'h' : ' ');
454560484Sobrien
454677298Sobrien		      check_def = 1;
454777298Sobrien		      check_need = 1;
454877298Sobrien		      if (symbols [cnt + j].st_shndx >= SHN_LORESERVE
454977298Sobrien			  || section_headers[symbols [cnt + j].st_shndx].sh_type
455077298Sobrien			  != SHT_NOBITS)
455160484Sobrien			{
455277298Sobrien			  if (symbols [cnt + j].st_shndx == SHN_UNDEF)
455377298Sobrien			    check_def = 0;
455477298Sobrien			  else
455577298Sobrien			    check_need = 0;
455677298Sobrien			}
455760484Sobrien
455877298Sobrien		      if (check_need
455977298Sobrien			  && version_info [DT_VERSIONTAGIDX (DT_VERNEED)])
456060484Sobrien			{
456160484Sobrien			  Elf_Internal_Verneed     ivn;
456260484Sobrien			  unsigned long            offset;
456360484Sobrien
456460484Sobrien			  offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
456560484Sobrien			    - loadaddr;
456660484Sobrien
456760484Sobrien		          do
456860484Sobrien			    {
456960484Sobrien			      Elf_Internal_Vernaux   ivna;
457060484Sobrien			      Elf_External_Verneed   evn;
457160484Sobrien			      Elf_External_Vernaux   evna;
457260484Sobrien			      unsigned long          a_off;
457360484Sobrien
457460484Sobrien			      GET_DATA (offset, evn, "version need");
457560484Sobrien
457660484Sobrien			      ivn.vn_aux  = BYTE_GET (evn.vn_aux);
457760484Sobrien			      ivn.vn_next = BYTE_GET (evn.vn_next);
457860484Sobrien
457960484Sobrien			      a_off = offset + ivn.vn_aux;
458060484Sobrien
458160484Sobrien			      do
458260484Sobrien				{
458360484Sobrien				  GET_DATA (a_off, evna,
458460484Sobrien					    "version need aux (2)");
458560484Sobrien
458660484Sobrien				  ivna.vna_next  = BYTE_GET (evna.vna_next);
458760484Sobrien				  ivna.vna_other = BYTE_GET (evna.vna_other);
458860484Sobrien
458960484Sobrien				  a_off += ivna.vna_next;
459060484Sobrien				}
459160484Sobrien			      while (ivna.vna_other != data [cnt + j]
459260484Sobrien				     && ivna.vna_next != 0);
459360484Sobrien
459460484Sobrien			      if (ivna.vna_other == data [cnt + j])
459560484Sobrien				{
459660484Sobrien				  ivna.vna_name = BYTE_GET (evna.vna_name);
459760484Sobrien
459860484Sobrien				  name = strtab + ivna.vna_name;
459960484Sobrien				  nn += printf ("(%s%-*s",
460060484Sobrien						name,
460160484Sobrien						12 - (int) strlen (name),
460260484Sobrien						")");
460377298Sobrien				  check_def = 0;
460460484Sobrien				  break;
460560484Sobrien				}
460660484Sobrien
460760484Sobrien			      offset += ivn.vn_next;
460860484Sobrien			    }
460960484Sobrien			  while (ivn.vn_next);
461060484Sobrien			}
461177298Sobrien
461277298Sobrien		      if (check_def && data [cnt + j] != 0x8001
461377298Sobrien			  && version_info [DT_VERSIONTAGIDX (DT_VERDEF)])
461460484Sobrien			{
461560484Sobrien			  Elf_Internal_Verdef  ivd;
461660484Sobrien			  Elf_External_Verdef  evd;
461760484Sobrien			  unsigned long        offset;
461860484Sobrien
461960484Sobrien			  offset = version_info
462060484Sobrien			    [DT_VERSIONTAGIDX (DT_VERDEF)] - loadaddr;
462160484Sobrien
462260484Sobrien			  do
462360484Sobrien			    {
462460484Sobrien			      GET_DATA (offset, evd, "version def");
462560484Sobrien
462660484Sobrien			      ivd.vd_next = BYTE_GET (evd.vd_next);
462760484Sobrien			      ivd.vd_ndx  = BYTE_GET (evd.vd_ndx);
462860484Sobrien
462960484Sobrien			      offset += ivd.vd_next;
463060484Sobrien			    }
463160484Sobrien			  while (ivd.vd_ndx != (data [cnt + j] & 0x7fff)
463260484Sobrien				 && ivd.vd_next != 0);
463360484Sobrien
463460484Sobrien			  if (ivd.vd_ndx == (data [cnt + j] & 0x7fff))
463560484Sobrien			    {
463660484Sobrien			      Elf_External_Verdaux  evda;
463760484Sobrien			      Elf_Internal_Verdaux  ivda;
463860484Sobrien
463960484Sobrien			      ivd.vd_aux = BYTE_GET (evd.vd_aux);
464060484Sobrien
464160484Sobrien			      GET_DATA (offset - ivd.vd_next + ivd.vd_aux,
464260484Sobrien					evda, "version def aux");
464360484Sobrien
464460484Sobrien			      ivda.vda_name = BYTE_GET (evda.vda_name);
464560484Sobrien
464660484Sobrien			      name = strtab + ivda.vda_name;
464760484Sobrien			      nn += printf ("(%s%-*s",
464860484Sobrien					    name,
464960484Sobrien					    12 - (int) strlen (name),
465060484Sobrien					    ")");
465160484Sobrien			    }
465260484Sobrien			}
465360484Sobrien
465460484Sobrien		      if (nn < 18)
465560484Sobrien			printf ("%*c", 18 - nn, ' ');
465660484Sobrien		    }
465760484Sobrien
465860484Sobrien		putchar ('\n');
465960484Sobrien	      }
466060484Sobrien
466160484Sobrien	    free (data);
466260484Sobrien	    free (strtab);
466360484Sobrien	    free (symbols);
466460484Sobrien	  }
466560484Sobrien	  break;
466660484Sobrien
466760484Sobrien	default:
466860484Sobrien	  break;
466960484Sobrien	}
467060484Sobrien    }
467160484Sobrien
467260484Sobrien  if (! found)
467360484Sobrien    printf (_("\nNo version information found in this file.\n"));
467460484Sobrien
467560484Sobrien  return 1;
467660484Sobrien}
467760484Sobrien
467860484Sobrienstatic const char *
467960484Sobrienget_symbol_binding (binding)
468060484Sobrien     unsigned int binding;
468160484Sobrien{
468260484Sobrien  static char buff [32];
468360484Sobrien
468460484Sobrien  switch (binding)
468560484Sobrien    {
468660484Sobrien    case STB_LOCAL:  return "LOCAL";
468760484Sobrien    case STB_GLOBAL: return "GLOBAL";
468860484Sobrien    case STB_WEAK:   return "WEAK";
468960484Sobrien    default:
469060484Sobrien      if (binding >= STB_LOPROC && binding <= STB_HIPROC)
469160484Sobrien	sprintf (buff, _("<processor specific>: %d"), binding);
469260484Sobrien      else if (binding >= STB_LOOS && binding <= STB_HIOS)
469360484Sobrien	sprintf (buff, _("<OS specific>: %d"), binding);
469460484Sobrien      else
469560484Sobrien	sprintf (buff, _("<unknown>: %d"), binding);
469660484Sobrien      return buff;
469760484Sobrien    }
469860484Sobrien}
469960484Sobrien
470060484Sobrienstatic const char *
470160484Sobrienget_symbol_type (type)
470260484Sobrien     unsigned int type;
470360484Sobrien{
470460484Sobrien  static char buff [32];
470560484Sobrien
470660484Sobrien  switch (type)
470760484Sobrien    {
470860484Sobrien    case STT_NOTYPE:   return "NOTYPE";
470960484Sobrien    case STT_OBJECT:   return "OBJECT";
471060484Sobrien    case STT_FUNC:     return "FUNC";
471160484Sobrien    case STT_SECTION:  return "SECTION";
471260484Sobrien    case STT_FILE:     return "FILE";
471360484Sobrien    case STT_COMMON:   return "COMMON";
471460484Sobrien    default:
471560484Sobrien      if (type >= STT_LOPROC && type <= STT_HIPROC)
471660484Sobrien	{
471760484Sobrien	  if (elf_header.e_machine == EM_ARM && type == STT_ARM_TFUNC)
471860484Sobrien	    return "THUMB_FUNC";
471960484Sobrien
472060484Sobrien	  if (elf_header.e_machine == EM_SPARCV9 && type == STT_REGISTER)
472160484Sobrien	    return "REGISTER";
472260484Sobrien
472360484Sobrien	  if (elf_header.e_machine == EM_PARISC && type == STT_PARISC_MILLI)
472460484Sobrien	    return "PARISC_MILLI";
472560484Sobrien
472660484Sobrien	  sprintf (buff, _("<processor specific>: %d"), type);
472760484Sobrien	}
472860484Sobrien      else if (type >= STT_LOOS && type <= STT_HIOS)
472960484Sobrien	{
473060484Sobrien	  if (elf_header.e_machine == EM_PARISC)
473160484Sobrien	    {
473260484Sobrien	      if (type == STT_HP_OPAQUE)
473360484Sobrien		return "HP_OPAQUE";
473460484Sobrien	      if (type == STT_HP_STUB)
473560484Sobrien		return "HP_STUB";
473660484Sobrien	    }
473760484Sobrien
473860484Sobrien	  sprintf (buff, _("<OS specific>: %d"), type);
473960484Sobrien	}
474060484Sobrien      else
474160484Sobrien	sprintf (buff, _("<unknown>: %d"), type);
474260484Sobrien      return buff;
474360484Sobrien    }
474460484Sobrien}
474560484Sobrien
474660484Sobrienstatic const char *
474760484Sobrienget_symbol_visibility (visibility)
474860484Sobrien     unsigned int visibility;
474960484Sobrien{
475060484Sobrien  switch (visibility)
475160484Sobrien    {
475260484Sobrien    case STV_DEFAULT:   return "DEFAULT";
475360484Sobrien    case STV_INTERNAL:  return "INTERNAL";
475460484Sobrien    case STV_HIDDEN:    return "HIDDEN";
475560484Sobrien    case STV_PROTECTED: return "PROTECTED";
475660484Sobrien    default: abort ();
475760484Sobrien    }
475860484Sobrien}
475960484Sobrien
476060484Sobrienstatic const char *
476160484Sobrienget_symbol_index_type (type)
476260484Sobrien     unsigned int type;
476360484Sobrien{
476460484Sobrien  switch (type)
476560484Sobrien    {
476660484Sobrien    case SHN_UNDEF:  return "UND";
476760484Sobrien    case SHN_ABS:    return "ABS";
476860484Sobrien    case SHN_COMMON: return "COM";
476960484Sobrien    default:
477060484Sobrien      if (type >= SHN_LOPROC && type <= SHN_HIPROC)
477160484Sobrien	return "PRC";
477260484Sobrien      else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE)
477360484Sobrien	return "RSV";
477460484Sobrien      else if (type >= SHN_LOOS && type <= SHN_HIOS)
477560484Sobrien	return "OS ";
477660484Sobrien      else
477760484Sobrien	{
477860484Sobrien	  static char buff [32];
477960484Sobrien
478060484Sobrien	  sprintf (buff, "%3d", type);
478160484Sobrien	  return buff;
478260484Sobrien	}
478360484Sobrien    }
478460484Sobrien}
478560484Sobrien
478660484Sobrienstatic int *
478760484Sobrienget_dynamic_data (file, number)
478860484Sobrien     FILE *       file;
478960484Sobrien     unsigned int number;
479060484Sobrien{
479177298Sobrien  unsigned char * e_data;
479260484Sobrien  int *  i_data;
479360484Sobrien
479477298Sobrien  e_data = (unsigned char *) malloc (number * 4);
479560484Sobrien
479660484Sobrien  if (e_data == NULL)
479760484Sobrien    {
479860484Sobrien      error (_("Out of memory\n"));
479960484Sobrien      return NULL;
480060484Sobrien    }
480160484Sobrien
480260484Sobrien  if (fread (e_data, 4, number, file) != number)
480360484Sobrien    {
480460484Sobrien      error (_("Unable to read in dynamic data\n"));
480560484Sobrien      return NULL;
480660484Sobrien    }
480760484Sobrien
480860484Sobrien  i_data = (int *) malloc (number * sizeof (* i_data));
480960484Sobrien
481060484Sobrien  if (i_data == NULL)
481160484Sobrien    {
481260484Sobrien      error (_("Out of memory\n"));
481360484Sobrien      free (e_data);
481460484Sobrien      return NULL;
481560484Sobrien    }
481660484Sobrien
481760484Sobrien  while (number--)
481860484Sobrien    i_data [number] = byte_get (e_data + number * 4, 4);
481960484Sobrien
482060484Sobrien  free (e_data);
482160484Sobrien
482260484Sobrien  return i_data;
482360484Sobrien}
482460484Sobrien
482560484Sobrien/* Dump the symbol table */
482660484Sobrienstatic int
482760484Sobrienprocess_symbol_table (file)
482860484Sobrien     FILE * file;
482960484Sobrien{
483060484Sobrien  Elf32_Internal_Shdr *   section;
483177298Sobrien  unsigned char   nb [4];
483277298Sobrien  unsigned char   nc [4];
483360484Sobrien  int    nbuckets = 0;
483460484Sobrien  int    nchains = 0;
483560484Sobrien  int *  buckets = NULL;
483660484Sobrien  int *  chains = NULL;
483760484Sobrien
483860484Sobrien  if (! do_syms && !do_histogram)
483960484Sobrien    return 1;
484060484Sobrien
484160484Sobrien  if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL)
484260484Sobrien				|| do_histogram))
484360484Sobrien    {
484460484Sobrien      if (fseek (file, dynamic_info[DT_HASH] - loadaddr, SEEK_SET))
484560484Sobrien	{
484660484Sobrien	  error (_("Unable to seek to start of dynamic information"));
484760484Sobrien	  return 0;
484860484Sobrien	}
484960484Sobrien
485060484Sobrien      if (fread (nb, sizeof (nb), 1, file) != 1)
485160484Sobrien	{
485260484Sobrien	  error (_("Failed to read in number of buckets\n"));
485360484Sobrien	  return 0;
485460484Sobrien	}
485560484Sobrien
485660484Sobrien      if (fread (nc, sizeof (nc), 1, file) != 1)
485760484Sobrien	{
485860484Sobrien	  error (_("Failed to read in number of chains\n"));
485960484Sobrien	  return 0;
486060484Sobrien	}
486160484Sobrien
486260484Sobrien      nbuckets = byte_get (nb, 4);
486360484Sobrien      nchains  = byte_get (nc, 4);
486460484Sobrien
486560484Sobrien      buckets = get_dynamic_data (file, nbuckets);
486660484Sobrien      chains  = get_dynamic_data (file, nchains);
486760484Sobrien
486860484Sobrien      if (buckets == NULL || chains == NULL)
486960484Sobrien	return 0;
487060484Sobrien    }
487160484Sobrien
487260484Sobrien  if (do_syms
487360484Sobrien      && dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL)
487460484Sobrien    {
487560484Sobrien      int    hn;
487660484Sobrien      int    si;
487760484Sobrien
487860484Sobrien      printf (_("\nSymbol table for image:\n"));
487960484Sobrien      if (is_32bit_elf)
488060484Sobrien	printf (_("  Num Buc:    Value  Size   Type   Bind Vis      Ndx Name\n"));
488160484Sobrien      else
488260484Sobrien	printf (_("  Num Buc:    Value          Size   Type   Bind Vis      Ndx Name\n"));
488360484Sobrien
488460484Sobrien      for (hn = 0; hn < nbuckets; hn++)
488560484Sobrien	{
488660484Sobrien	  if (! buckets [hn])
488760484Sobrien	    continue;
488860484Sobrien
488960484Sobrien	  for (si = buckets [hn]; si < nchains && si > 0; si = chains [si])
489060484Sobrien	    {
489160484Sobrien	      Elf_Internal_Sym * psym;
489260484Sobrien
489360484Sobrien	      psym = dynamic_symbols + si;
489460484Sobrien
489560484Sobrien	      printf ("  %3d %3d: ", si, hn);
489660484Sobrien	      print_vma (psym->st_value, LONG_HEX);
489760484Sobrien	      putchar (' ' );
489860484Sobrien	      print_vma (psym->st_size, DEC_5);
489977298Sobrien
490060484Sobrien	      printf ("  %6s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
490160484Sobrien	      printf (" %6s",  get_symbol_binding (ELF_ST_BIND (psym->st_info)));
490260484Sobrien	      printf (" %3s",  get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
490360484Sobrien	      printf (" %3.3s", get_symbol_index_type (psym->st_shndx));
490460484Sobrien	      printf (" %s\n", dynamic_strings + psym->st_name);
490560484Sobrien	    }
490660484Sobrien	}
490760484Sobrien    }
490860484Sobrien  else if (do_syms && !do_using_dynamic)
490960484Sobrien    {
491060484Sobrien      unsigned int     i;
491160484Sobrien
491260484Sobrien      for (i = 0, section = section_headers;
491360484Sobrien	   i < elf_header.e_shnum;
491460484Sobrien	   i++, section++)
491560484Sobrien	{
491660484Sobrien	  unsigned int          si;
491760484Sobrien	  char *                strtab;
491860484Sobrien	  Elf_Internal_Sym *    symtab;
491960484Sobrien	  Elf_Internal_Sym *    psym;
492060484Sobrien
492160484Sobrien
492260484Sobrien	  if (   section->sh_type != SHT_SYMTAB
492360484Sobrien	      && section->sh_type != SHT_DYNSYM)
492460484Sobrien	    continue;
492560484Sobrien
492660484Sobrien	  printf (_("\nSymbol table '%s' contains %lu entries:\n"),
492760484Sobrien		  SECTION_NAME (section),
492860484Sobrien		  (unsigned long) (section->sh_size / section->sh_entsize));
492960484Sobrien	  if (is_32bit_elf)
493060484Sobrien	    printf (_("   Num:    Value  Size Type    Bind   Vis      Ndx Name\n"));
493160484Sobrien	  else
493260484Sobrien	    printf (_("   Num:    Value          Size Type    Bind   Vis      Ndx Name\n"));
493360484Sobrien
493460484Sobrien	  symtab = GET_ELF_SYMBOLS (file, section->sh_offset,
493560484Sobrien				    section->sh_size / section->sh_entsize);
493660484Sobrien	  if (symtab == NULL)
493760484Sobrien	    continue;
493860484Sobrien
493960484Sobrien	  if (section->sh_link == elf_header.e_shstrndx)
494060484Sobrien	    strtab = string_table;
494160484Sobrien	  else
494260484Sobrien	    {
494360484Sobrien	      Elf32_Internal_Shdr * string_sec;
494460484Sobrien
494560484Sobrien	      string_sec = section_headers + section->sh_link;
494660484Sobrien
494760484Sobrien	      GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size,
494860484Sobrien			      strtab, char *, "string table");
494960484Sobrien	    }
495060484Sobrien
495160484Sobrien	  for (si = 0, psym = symtab;
495260484Sobrien	       si < section->sh_size / section->sh_entsize;
495360484Sobrien	       si ++, psym ++)
495460484Sobrien	    {
495560484Sobrien	      printf ("%6d: ", si);
495660484Sobrien	      print_vma (psym->st_value, LONG_HEX);
495760484Sobrien	      putchar (' ');
495860484Sobrien	      print_vma (psym->st_size, DEC_5);
495960484Sobrien	      printf (" %-7s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
496060484Sobrien	      printf (" %-6s", get_symbol_binding (ELF_ST_BIND (psym->st_info)));
496160484Sobrien	      printf (" %-3s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
496260484Sobrien	      printf (" %4s", get_symbol_index_type (psym->st_shndx));
496360484Sobrien	      printf (" %s", strtab + psym->st_name);
496460484Sobrien
496560484Sobrien	      if (section->sh_type == SHT_DYNSYM &&
496660484Sobrien		  version_info [DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
496760484Sobrien		{
496860484Sobrien		  unsigned char   data[2];
496960484Sobrien		  unsigned short  vers_data;
497060484Sobrien		  unsigned long   offset;
497160484Sobrien		  int             is_nobits;
497260484Sobrien		  int             check_def;
497360484Sobrien
497460484Sobrien		  offset = version_info [DT_VERSIONTAGIDX (DT_VERSYM)]
497560484Sobrien		    - loadaddr;
497660484Sobrien
497760484Sobrien		  GET_DATA (offset + si * sizeof (vers_data), data,
497860484Sobrien			    "version data");
497960484Sobrien
498060484Sobrien		  vers_data = byte_get (data, 2);
498160484Sobrien
498260484Sobrien		  is_nobits = psym->st_shndx < SHN_LORESERVE ?
498360484Sobrien		    (section_headers [psym->st_shndx].sh_type == SHT_NOBITS)
498460484Sobrien		    : 0;
498560484Sobrien
498660484Sobrien		  check_def = (psym->st_shndx != SHN_UNDEF);
498760484Sobrien
498860484Sobrien		  if ((vers_data & 0x8000) || vers_data > 1)
498960484Sobrien		    {
499077298Sobrien		      if (version_info [DT_VERSIONTAGIDX (DT_VERNEED)]
499177298Sobrien			  && (is_nobits || ! check_def))
499260484Sobrien			{
499360484Sobrien			  Elf_External_Verneed  evn;
499460484Sobrien			  Elf_Internal_Verneed  ivn;
499560484Sobrien			  Elf_Internal_Vernaux  ivna;
499660484Sobrien
499760484Sobrien			  /* We must test both.  */
499860484Sobrien			  offset = version_info
499960484Sobrien			    [DT_VERSIONTAGIDX (DT_VERNEED)] - loadaddr;
500060484Sobrien
500160484Sobrien			  do
500260484Sobrien			    {
500360484Sobrien			      unsigned long  vna_off;
500460484Sobrien
500560484Sobrien			      GET_DATA (offset, evn, "version need");
500660484Sobrien
500760484Sobrien			      ivn.vn_aux  = BYTE_GET (evn.vn_aux);
500860484Sobrien			      ivn.vn_next = BYTE_GET (evn.vn_next);
500960484Sobrien
501060484Sobrien			      vna_off = offset + ivn.vn_aux;
501160484Sobrien
501260484Sobrien			      do
501360484Sobrien				{
501460484Sobrien				  Elf_External_Vernaux  evna;
501560484Sobrien
501660484Sobrien				  GET_DATA (vna_off, evna,
501760484Sobrien					    "version need aux (3)");
501860484Sobrien
501960484Sobrien				  ivna.vna_other = BYTE_GET (evna.vna_other);
502060484Sobrien				  ivna.vna_next  = BYTE_GET (evna.vna_next);
502160484Sobrien				  ivna.vna_name  = BYTE_GET (evna.vna_name);
502260484Sobrien
502360484Sobrien				  vna_off += ivna.vna_next;
502460484Sobrien				}
502560484Sobrien			      while (ivna.vna_other != vers_data
502660484Sobrien				     && ivna.vna_next != 0);
502760484Sobrien
502860484Sobrien			      if (ivna.vna_other == vers_data)
502960484Sobrien				break;
503060484Sobrien
503160484Sobrien			      offset += ivn.vn_next;
503260484Sobrien			    }
503360484Sobrien			  while (ivn.vn_next != 0);
503460484Sobrien
503560484Sobrien			  if (ivna.vna_other == vers_data)
503660484Sobrien			    {
503760484Sobrien			      printf ("@%s (%d)",
503860484Sobrien				      strtab + ivna.vna_name, ivna.vna_other);
503960484Sobrien			      check_def = 0;
504060484Sobrien			    }
504160484Sobrien			  else if (! is_nobits)
504260484Sobrien			    error (_("bad dynamic symbol"));
504360484Sobrien			  else
504460484Sobrien			    check_def = 1;
504560484Sobrien			}
504660484Sobrien
504760484Sobrien		      if (check_def)
504860484Sobrien			{
504977298Sobrien			  if (vers_data != 0x8001
505077298Sobrien			      && version_info [DT_VERSIONTAGIDX (DT_VERDEF)])
505160484Sobrien			    {
505260484Sobrien			      Elf_Internal_Verdef     ivd;
505360484Sobrien			      Elf_Internal_Verdaux    ivda;
505460484Sobrien			      Elf_External_Verdaux  evda;
505560484Sobrien			      unsigned long           offset;
505660484Sobrien
505760484Sobrien			      offset =
505860484Sobrien				version_info [DT_VERSIONTAGIDX (DT_VERDEF)]
505960484Sobrien				- loadaddr;
506060484Sobrien
506160484Sobrien			      do
506260484Sobrien				{
506360484Sobrien				  Elf_External_Verdef   evd;
506460484Sobrien
506560484Sobrien				  GET_DATA (offset, evd, "version def");
506660484Sobrien
506760484Sobrien				  ivd.vd_ndx  = BYTE_GET (evd.vd_ndx);
506860484Sobrien				  ivd.vd_aux  = BYTE_GET (evd.vd_aux);
506960484Sobrien				  ivd.vd_next = BYTE_GET (evd.vd_next);
507060484Sobrien
507160484Sobrien				  offset += ivd.vd_next;
507260484Sobrien				}
507360484Sobrien			      while (ivd.vd_ndx != (vers_data & 0x7fff)
507460484Sobrien				     && ivd.vd_next != 0);
507560484Sobrien
507660484Sobrien			      offset -= ivd.vd_next;
507760484Sobrien			      offset += ivd.vd_aux;
507860484Sobrien
507960484Sobrien			      GET_DATA (offset, evda, "version def aux");
508060484Sobrien
508160484Sobrien			      ivda.vda_name = BYTE_GET (evda.vda_name);
508260484Sobrien
508360484Sobrien			      if (psym->st_name != ivda.vda_name)
508460484Sobrien				printf ((vers_data & 0x8000)
508560484Sobrien					? "@%s" : "@@%s",
508660484Sobrien					strtab + ivda.vda_name);
508760484Sobrien			    }
508860484Sobrien			}
508960484Sobrien		    }
509060484Sobrien		}
509160484Sobrien
509260484Sobrien	      putchar ('\n');
509360484Sobrien	    }
509460484Sobrien
509560484Sobrien	  free (symtab);
509660484Sobrien	  if (strtab != string_table)
509760484Sobrien	    free (strtab);
509860484Sobrien	}
509960484Sobrien    }
510060484Sobrien  else if (do_syms)
510160484Sobrien    printf
510260484Sobrien      (_("\nDynamic symbol information is not available for displaying symbols.\n"));
510360484Sobrien
510460484Sobrien  if (do_histogram && buckets != NULL)
510560484Sobrien    {
510677298Sobrien      int * lengths;
510777298Sobrien      int * counts;
510877298Sobrien      int   hn;
510977298Sobrien      int   si;
511077298Sobrien      int   maxlength = 0;
511177298Sobrien      int   nzero_counts = 0;
511277298Sobrien      int   nsyms = 0;
511360484Sobrien
511460484Sobrien      printf (_("\nHistogram for bucket list length (total of %d buckets):\n"),
511560484Sobrien	      nbuckets);
511660484Sobrien      printf (_(" Length  Number     %% of total  Coverage\n"));
511760484Sobrien
511860484Sobrien      lengths = (int *) calloc (nbuckets, sizeof (int));
511960484Sobrien      if (lengths == NULL)
512060484Sobrien	{
512160484Sobrien	  error (_("Out of memory"));
512260484Sobrien	  return 0;
512360484Sobrien	}
512460484Sobrien      for (hn = 0; hn < nbuckets; ++hn)
512560484Sobrien	{
512660484Sobrien	  if (! buckets [hn])
512760484Sobrien	    continue;
512860484Sobrien
512960484Sobrien	  for (si = buckets[hn]; si > 0 && si < nchains; si = chains[si])
513060484Sobrien	    {
513160484Sobrien	      ++ nsyms;
513260484Sobrien	      if (maxlength < ++lengths[hn])
513360484Sobrien		++ maxlength;
513460484Sobrien	    }
513560484Sobrien	}
513660484Sobrien
513760484Sobrien      counts = (int *) calloc (maxlength + 1, sizeof (int));
513860484Sobrien      if (counts == NULL)
513960484Sobrien	{
514060484Sobrien	  error (_("Out of memory"));
514160484Sobrien	  return 0;
514260484Sobrien	}
514360484Sobrien
514460484Sobrien      for (hn = 0; hn < nbuckets; ++hn)
514560484Sobrien	++ counts [lengths [hn]];
514660484Sobrien
514760484Sobrien      if (nbuckets > 0)
514860484Sobrien	{
514960484Sobrien	  printf ("      0  %-10d (%5.1f%%)\n",
515060484Sobrien		  counts[0], (counts[0] * 100.0) / nbuckets);
515160484Sobrien	  for (si = 1; si <= maxlength; ++si)
515260484Sobrien	    {
515360484Sobrien	      nzero_counts += counts[si] * si;
515460484Sobrien	      printf ("%7d  %-10d (%5.1f%%)    %5.1f%%\n",
515560484Sobrien		      si, counts[si], (counts[si] * 100.0) / nbuckets,
515660484Sobrien		      (nzero_counts * 100.0) / nsyms);
515760484Sobrien	    }
515860484Sobrien	}
515960484Sobrien
516060484Sobrien      free (counts);
516160484Sobrien      free (lengths);
516260484Sobrien    }
516360484Sobrien
516460484Sobrien  if (buckets != NULL)
516560484Sobrien    {
516660484Sobrien      free (buckets);
516760484Sobrien      free (chains);
516860484Sobrien    }
516960484Sobrien
517060484Sobrien  return 1;
517160484Sobrien}
517260484Sobrien
517360484Sobrienstatic int
517460484Sobrienprocess_syminfo (file)
517560484Sobrien     FILE * file ATTRIBUTE_UNUSED;
517660484Sobrien{
517760484Sobrien  unsigned int i;
517860484Sobrien
517960484Sobrien  if (dynamic_syminfo == NULL
518060484Sobrien      || !do_dynamic)
518160484Sobrien    /* No syminfo, this is ok.  */
518260484Sobrien    return 1;
518360484Sobrien
518460484Sobrien  /* There better should be a dynamic symbol section.  */
518560484Sobrien  if (dynamic_symbols == NULL || dynamic_strings == NULL)
518660484Sobrien    return 0;
518760484Sobrien
518860484Sobrien  if (dynamic_addr)
518960484Sobrien    printf (_("\nDynamic info segment at offset 0x%lx contains %d entries:\n"),
519060484Sobrien	    dynamic_syminfo_offset, dynamic_syminfo_nent);
519160484Sobrien
519260484Sobrien  printf (_(" Num: Name                           BoundTo     Flags\n"));
519360484Sobrien  for (i = 0; i < dynamic_syminfo_nent; ++i)
519460484Sobrien    {
519560484Sobrien      unsigned short int flags = dynamic_syminfo[i].si_flags;
519660484Sobrien
519760484Sobrien      printf ("%4d: %-30s ", i,
519860484Sobrien	      dynamic_strings + dynamic_symbols[i].st_name);
519960484Sobrien
520060484Sobrien      switch (dynamic_syminfo[i].si_boundto)
520160484Sobrien	{
520260484Sobrien	case SYMINFO_BT_SELF:
520360484Sobrien	  fputs ("SELF       ", stdout);
520460484Sobrien	  break;
520560484Sobrien	case SYMINFO_BT_PARENT:
520660484Sobrien	  fputs ("PARENT     ", stdout);
520760484Sobrien	  break;
520860484Sobrien	default:
520960484Sobrien	  if (dynamic_syminfo[i].si_boundto > 0
521060484Sobrien	      && dynamic_syminfo[i].si_boundto < dynamic_size)
521160484Sobrien	    printf ("%-10s ",
521260484Sobrien		    dynamic_strings
521360484Sobrien		    + dynamic_segment[dynamic_syminfo[i].si_boundto].d_un.d_val);
521460484Sobrien	  else
521560484Sobrien	    printf ("%-10d ", dynamic_syminfo[i].si_boundto);
521660484Sobrien	  break;
521760484Sobrien	}
521860484Sobrien
521960484Sobrien      if (flags & SYMINFO_FLG_DIRECT)
522060484Sobrien	printf (" DIRECT");
522160484Sobrien      if (flags & SYMINFO_FLG_PASSTHRU)
522260484Sobrien	printf (" PASSTHRU");
522360484Sobrien      if (flags & SYMINFO_FLG_COPY)
522460484Sobrien	printf (" COPY");
522560484Sobrien      if (flags & SYMINFO_FLG_LAZYLOAD)
522660484Sobrien	printf (" LAZYLOAD");
522760484Sobrien
522860484Sobrien      puts ("");
522960484Sobrien    }
523060484Sobrien
523160484Sobrien  return 1;
523260484Sobrien}
523360484Sobrien
523460484Sobrien#ifdef SUPPORT_DISASSEMBLY
523560484Sobrienstatic void
523660484Sobriendisassemble_section (section, file)
523760484Sobrien     Elf32_Internal_Shdr * section;
523860484Sobrien     FILE * file;
523960484Sobrien{
524060484Sobrien  printf (_("\nAssembly dump of section %s\n"),
524160484Sobrien	  SECTION_NAME (section));
524260484Sobrien
524360484Sobrien  /* XXX -- to be done --- XXX */
524460484Sobrien
524560484Sobrien  return 1;
524660484Sobrien}
524760484Sobrien#endif
524860484Sobrien
524960484Sobrienstatic int
525060484Sobriendump_section (section, file)
525160484Sobrien     Elf32_Internal_Shdr * section;
525260484Sobrien     FILE * file;
525360484Sobrien{
525460484Sobrien  bfd_size_type   bytes;
525560484Sobrien  bfd_vma         addr;
525660484Sobrien  unsigned char * data;
525760484Sobrien  unsigned char * start;
525860484Sobrien
525960484Sobrien  bytes = section->sh_size;
526060484Sobrien
526160484Sobrien  if (bytes == 0)
526260484Sobrien    {
526360484Sobrien      printf (_("\nSection '%s' has no data to dump.\n"),
526460484Sobrien	      SECTION_NAME (section));
526560484Sobrien      return 0;
526660484Sobrien    }
526760484Sobrien  else
526860484Sobrien    printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section));
526960484Sobrien
527060484Sobrien  addr = section->sh_addr;
527160484Sobrien
527260484Sobrien  GET_DATA_ALLOC (section->sh_offset, bytes, start, unsigned char *,
527360484Sobrien		  "section data");
527460484Sobrien
527560484Sobrien  data = start;
527660484Sobrien
527760484Sobrien  while (bytes)
527860484Sobrien    {
527960484Sobrien      int j;
528060484Sobrien      int k;
528160484Sobrien      int lbytes;
528260484Sobrien
528360484Sobrien      lbytes = (bytes > 16 ? 16 : bytes);
528460484Sobrien
528560484Sobrien      printf ("  0x%8.8lx ", (unsigned long) addr);
528660484Sobrien
528760484Sobrien      switch (elf_header.e_ident [EI_DATA])
528860484Sobrien	{
528960484Sobrien	default:
529060484Sobrien	case ELFDATA2LSB:
529160484Sobrien	  for (j = 15; j >= 0; j --)
529260484Sobrien	    {
529360484Sobrien	      if (j < lbytes)
529460484Sobrien		printf ("%2.2x", data [j]);
529560484Sobrien	      else
529660484Sobrien		printf ("  ");
529760484Sobrien
529860484Sobrien	      if (!(j & 0x3))
529960484Sobrien		printf (" ");
530060484Sobrien	    }
530160484Sobrien	  break;
530260484Sobrien
530360484Sobrien	case ELFDATA2MSB:
530460484Sobrien	  for (j = 0; j < 16; j++)
530560484Sobrien	    {
530660484Sobrien	      if (j < lbytes)
530760484Sobrien		printf ("%2.2x", data [j]);
530860484Sobrien	      else
530960484Sobrien		printf ("  ");
531060484Sobrien
531160484Sobrien	      if ((j & 3) == 3)
531260484Sobrien		printf (" ");
531360484Sobrien	    }
531460484Sobrien	  break;
531560484Sobrien	}
531660484Sobrien
531760484Sobrien      for (j = 0; j < lbytes; j++)
531860484Sobrien	{
531960484Sobrien	  k = data [j];
532060484Sobrien	  if (k >= ' ' && k < 0x80)
532160484Sobrien	    printf ("%c", k);
532260484Sobrien	  else
532360484Sobrien	    printf (".");
532460484Sobrien	}
532560484Sobrien
532660484Sobrien      putchar ('\n');
532760484Sobrien
532860484Sobrien      data  += lbytes;
532960484Sobrien      addr  += lbytes;
533060484Sobrien      bytes -= lbytes;
533160484Sobrien    }
533260484Sobrien
533360484Sobrien  free (start);
533460484Sobrien
533560484Sobrien  return 1;
533660484Sobrien}
533760484Sobrien
533860484Sobrien
533960484Sobrienstatic unsigned long int
534060484Sobrienread_leb128 (data, length_return, sign)
534160484Sobrien     unsigned char * data;
534260484Sobrien     int *           length_return;
534360484Sobrien     int             sign;
534460484Sobrien{
534560484Sobrien  unsigned long int result = 0;
534660484Sobrien  unsigned int      num_read = 0;
534760484Sobrien  int               shift = 0;
534860484Sobrien  unsigned char     byte;
534960484Sobrien
535060484Sobrien  do
535160484Sobrien    {
535260484Sobrien      byte = * data ++;
535360484Sobrien      num_read ++;
535460484Sobrien
535560484Sobrien      result |= (byte & 0x7f) << shift;
535660484Sobrien
535760484Sobrien      shift += 7;
535860484Sobrien
535960484Sobrien    }
536060484Sobrien  while (byte & 0x80);
536160484Sobrien
536260484Sobrien  if (length_return != NULL)
536360484Sobrien    * length_return = num_read;
536460484Sobrien
536560484Sobrien  if (sign && (shift < 32) && (byte & 0x40))
536660484Sobrien    result |= -1 << shift;
536760484Sobrien
536860484Sobrien  return result;
536960484Sobrien}
537060484Sobrien
537160484Sobrientypedef struct State_Machine_Registers
537260484Sobrien{
537360484Sobrien  unsigned long	address;
537460484Sobrien  unsigned int  file;
537560484Sobrien  unsigned int  line;
537660484Sobrien  unsigned int  column;
537760484Sobrien  int           is_stmt;
537860484Sobrien  int           basic_block;
537960484Sobrien  int	        end_sequence;
538060484Sobrien/* This variable hold the number of the last entry seen
538160484Sobrien   in the File Table.  */
538260484Sobrien  unsigned int  last_file_entry;
538360484Sobrien} SMR;
538460484Sobrien
538560484Sobrienstatic SMR state_machine_regs;
538660484Sobrien
538760484Sobrienstatic void
538860484Sobrienreset_state_machine (is_stmt)
538960484Sobrien     int is_stmt;
539060484Sobrien{
539160484Sobrien  state_machine_regs.address = 0;
539260484Sobrien  state_machine_regs.file = 1;
539360484Sobrien  state_machine_regs.line = 1;
539460484Sobrien  state_machine_regs.column = 0;
539560484Sobrien  state_machine_regs.is_stmt = is_stmt;
539660484Sobrien  state_machine_regs.basic_block = 0;
539760484Sobrien  state_machine_regs.end_sequence = 0;
539860484Sobrien  state_machine_regs.last_file_entry = 0;
539960484Sobrien}
540060484Sobrien
540160484Sobrien/* Handled an extend line op.  Returns true if this is the end
540260484Sobrien   of sequence.  */
540360484Sobrienstatic int
540460484Sobrienprocess_extended_line_op (data, is_stmt, pointer_size)
540560484Sobrien     unsigned char * data;
540660484Sobrien     int is_stmt;
540760484Sobrien     int pointer_size;
540860484Sobrien{
540960484Sobrien  unsigned char   op_code;
541060484Sobrien  int             bytes_read;
541160484Sobrien  unsigned int    len;
541260484Sobrien  unsigned char * name;
541360484Sobrien  unsigned long   adr;
541460484Sobrien
541560484Sobrien  len = read_leb128 (data, & bytes_read, 0);
541660484Sobrien  data += bytes_read;
541760484Sobrien
541860484Sobrien  if (len == 0)
541960484Sobrien    {
542060484Sobrien      warn (_("badly formed extended line op encountered!"));
542160484Sobrien      return bytes_read;
542260484Sobrien    }
542360484Sobrien
542460484Sobrien  len += bytes_read;
542560484Sobrien  op_code = * data ++;
542660484Sobrien
542760484Sobrien  printf (_("  Extended opcode %d: "), op_code);
542860484Sobrien
542960484Sobrien  switch (op_code)
543060484Sobrien    {
543160484Sobrien    case DW_LNE_end_sequence:
543260484Sobrien      printf (_("End of Sequence\n\n"));
543360484Sobrien      reset_state_machine (is_stmt);
543460484Sobrien      break;
543560484Sobrien
543660484Sobrien    case DW_LNE_set_address:
543760484Sobrien      adr = byte_get (data, pointer_size);
543860484Sobrien      printf (_("set Address to 0x%lx\n"), adr);
543960484Sobrien      state_machine_regs.address = adr;
544060484Sobrien      break;
544160484Sobrien
544260484Sobrien    case DW_LNE_define_file:
544360484Sobrien      printf (_("  define new File Table entry\n"));
544460484Sobrien      printf (_("  Entry\tDir\tTime\tSize\tName\n"));
544560484Sobrien
544660484Sobrien      printf (_("   %d\t"), ++ state_machine_regs.last_file_entry);
544760484Sobrien      name = data;
544877298Sobrien      data += strlen ((char *) data) + 1;
544960484Sobrien      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
545060484Sobrien      data += bytes_read;
545160484Sobrien      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
545260484Sobrien      data += bytes_read;
545360484Sobrien      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
545460484Sobrien      printf (_("%s\n\n"), name);
545560484Sobrien      break;
545660484Sobrien
545760484Sobrien    default:
545860484Sobrien      printf (_("UNKNOWN: length %d\n"), len - bytes_read);
545960484Sobrien      break;
546060484Sobrien    }
546160484Sobrien
546260484Sobrien  return len;
546360484Sobrien}
546460484Sobrien
546560484Sobrien/* Size of pointers in the .debug_line section.  This information is not
546660484Sobrien   really present in that section.  It's obtained before dumping the debug
546760484Sobrien   sections by doing some pre-scan of the .debug_info section.  */
546860484Sobrienstatic int debug_line_pointer_size = 4;
546960484Sobrien
547060484Sobrienstatic int
547160484Sobriendisplay_debug_lines (section, start, file)
547260484Sobrien     Elf32_Internal_Shdr * section;
547360484Sobrien     unsigned char *       start;
547460484Sobrien     FILE *                file ATTRIBUTE_UNUSED;
547560484Sobrien{
547660484Sobrien  DWARF2_External_LineInfo * external;
547760484Sobrien  DWARF2_Internal_LineInfo   info;
547860484Sobrien  unsigned char *            standard_opcodes;
547960484Sobrien  unsigned char *            data = start;
548060484Sobrien  unsigned char *            end  = start + section->sh_size;
548160484Sobrien  unsigned char *            end_of_sequence;
548260484Sobrien  int                        i;
548360484Sobrien
548460484Sobrien  printf (_("\nDump of debug contents of section %s:\n\n"),
548560484Sobrien	  SECTION_NAME (section));
548660484Sobrien
548760484Sobrien  while (data < end)
548860484Sobrien    {
548960484Sobrien      external = (DWARF2_External_LineInfo *) data;
549060484Sobrien
549160484Sobrien      /* Check the length of the block.  */
549260484Sobrien      info.li_length = BYTE_GET (external->li_length);
549377298Sobrien      if (info.li_length + sizeof (external->li_length) > section->sh_size)
549460484Sobrien	{
549560484Sobrien	  warn
549660484Sobrien	    (_("The line info appears to be corrupt - the section is too small\n"));
549760484Sobrien	  return 0;
549860484Sobrien	}
549960484Sobrien
550060484Sobrien      /* Check its version number.  */
550160484Sobrien      info.li_version = BYTE_GET (external->li_version);
550260484Sobrien      if (info.li_version != 2)
550360484Sobrien	{
550460484Sobrien	  warn (_("Only DWARF version 2 line info is currently supported.\n"));
550560484Sobrien	  return 0;
550660484Sobrien	}
550760484Sobrien
550860484Sobrien      info.li_prologue_length = BYTE_GET (external->li_prologue_length);
550960484Sobrien      info.li_min_insn_length = BYTE_GET (external->li_min_insn_length);
551060484Sobrien      info.li_default_is_stmt = BYTE_GET (external->li_default_is_stmt);
551160484Sobrien      info.li_line_base       = BYTE_GET (external->li_line_base);
551260484Sobrien      info.li_line_range      = BYTE_GET (external->li_line_range);
551360484Sobrien      info.li_opcode_base     = BYTE_GET (external->li_opcode_base);
551460484Sobrien
551560484Sobrien      /* Sign extend the line base field.  */
551660484Sobrien      info.li_line_base <<= 24;
551760484Sobrien      info.li_line_base >>= 24;
551860484Sobrien
551960484Sobrien      printf (_("  Length:                      %ld\n"), info.li_length);
552060484Sobrien      printf (_("  DWARF Version:               %d\n"), info.li_version);
552178828Sobrien      printf (_("  Prologue Length:             %d\n"), info.li_prologue_length);
552260484Sobrien      printf (_("  Minimum Instruction Length:  %d\n"), info.li_min_insn_length);
552360484Sobrien      printf (_("  Initial value of 'is_stmt':  %d\n"), info.li_default_is_stmt);
552460484Sobrien      printf (_("  Line Base:                   %d\n"), info.li_line_base);
552560484Sobrien      printf (_("  Line Range:                  %d\n"), info.li_line_range);
552660484Sobrien      printf (_("  Opcode Base:                 %d\n"), info.li_opcode_base);
552760484Sobrien
552877298Sobrien      end_of_sequence = data + info.li_length + sizeof (external->li_length);
552960484Sobrien
553060484Sobrien      reset_state_machine (info.li_default_is_stmt);
553160484Sobrien
553260484Sobrien      /* Display the contents of the Opcodes table.  */
553360484Sobrien      standard_opcodes = data + sizeof (* external);
553460484Sobrien
553560484Sobrien      printf (_("\n Opcodes:\n"));
553660484Sobrien
553760484Sobrien      for (i = 1; i < info.li_opcode_base; i++)
553860484Sobrien	printf (_("  Opcode %d has %d args\n"), i, standard_opcodes[i - 1]);
553960484Sobrien
554060484Sobrien      /* Display the contents of the Directory table.  */
554160484Sobrien      data = standard_opcodes + info.li_opcode_base - 1;
554260484Sobrien
554360484Sobrien      if (* data == 0)
554460484Sobrien	printf (_("\n The Directory Table is empty.\n"));
554560484Sobrien      else
554660484Sobrien	{
554760484Sobrien	  printf (_("\n The Directory Table:\n"));
554860484Sobrien
554960484Sobrien	  while (* data != 0)
555060484Sobrien	    {
555160484Sobrien	      printf (_("  %s\n"), data);
555260484Sobrien
555377298Sobrien	      data += strlen ((char *) data) + 1;
555460484Sobrien	    }
555560484Sobrien	}
555660484Sobrien
555760484Sobrien      /* Skip the NUL at the end of the table.  */
555860484Sobrien      data ++;
555960484Sobrien
556060484Sobrien      /* Display the contents of the File Name table.  */
556160484Sobrien      if (* data == 0)
556260484Sobrien	printf (_("\n The File Name Table is empty.\n"));
556360484Sobrien      else
556460484Sobrien	{
556560484Sobrien	  printf (_("\n The File Name Table:\n"));
556660484Sobrien	  printf (_("  Entry\tDir\tTime\tSize\tName\n"));
556760484Sobrien
556860484Sobrien	  while (* data != 0)
556960484Sobrien	    {
557077298Sobrien	      unsigned char * name;
557160484Sobrien	      int bytes_read;
557260484Sobrien
557360484Sobrien	      printf (_("  %d\t"), ++ state_machine_regs.last_file_entry);
557460484Sobrien	      name = data;
557560484Sobrien
557677298Sobrien	      data += strlen ((char *) data) + 1;
557760484Sobrien
557860484Sobrien	      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
557960484Sobrien	      data += bytes_read;
558060484Sobrien	      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
558160484Sobrien	      data += bytes_read;
558260484Sobrien	      printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
558360484Sobrien	      data += bytes_read;
558460484Sobrien	      printf (_("%s\n"), name);
558560484Sobrien	    }
558660484Sobrien	}
558760484Sobrien
558860484Sobrien      /* Skip the NUL at the end of the table.  */
558960484Sobrien      data ++;
559060484Sobrien
559160484Sobrien      /* Now display the statements.  */
559260484Sobrien      printf (_("\n Line Number Statements:\n"));
559360484Sobrien
559460484Sobrien
559560484Sobrien      while (data < end_of_sequence)
559660484Sobrien	{
559760484Sobrien	  unsigned char op_code;
559860484Sobrien	  int           adv;
559960484Sobrien	  int           bytes_read;
560060484Sobrien
560160484Sobrien	  op_code = * data ++;
560260484Sobrien
560360484Sobrien	  switch (op_code)
560460484Sobrien	    {
560560484Sobrien	    case DW_LNS_extended_op:
560660484Sobrien	      data += process_extended_line_op (data, info.li_default_is_stmt,
560760484Sobrien                                                debug_line_pointer_size);
560860484Sobrien	      break;
560960484Sobrien
561060484Sobrien	    case DW_LNS_copy:
561160484Sobrien	      printf (_("  Copy\n"));
561260484Sobrien	      break;
561360484Sobrien
561460484Sobrien	    case DW_LNS_advance_pc:
561560484Sobrien	      adv = info.li_min_insn_length * read_leb128 (data, & bytes_read, 0);
561660484Sobrien	      data += bytes_read;
561760484Sobrien	      state_machine_regs.address += adv;
561860484Sobrien	      printf (_("  Advance PC by %d to %lx\n"), adv,
561960484Sobrien		      state_machine_regs.address);
562060484Sobrien	      break;
562160484Sobrien
562260484Sobrien	    case DW_LNS_advance_line:
562360484Sobrien	      adv = read_leb128 (data, & bytes_read, 1);
562460484Sobrien	      data += bytes_read;
562560484Sobrien	      state_machine_regs.line += adv;
562660484Sobrien	      printf (_("  Advance Line by %d to %d\n"), adv,
562760484Sobrien		      state_machine_regs.line);
562860484Sobrien	      break;
562960484Sobrien
563060484Sobrien	    case DW_LNS_set_file:
563160484Sobrien	      adv = read_leb128 (data, & bytes_read, 0);
563260484Sobrien	      data += bytes_read;
563360484Sobrien	      printf (_("  Set File Name to entry %d in the File Name Table\n"),
563460484Sobrien		      adv);
563560484Sobrien	      state_machine_regs.file = adv;
563660484Sobrien	      break;
563760484Sobrien
563860484Sobrien	    case DW_LNS_set_column:
563960484Sobrien	      adv = read_leb128 (data, & bytes_read, 0);
564060484Sobrien	      data += bytes_read;
564160484Sobrien	      printf (_("  Set column to %d\n"), adv);
564260484Sobrien	      state_machine_regs.column = adv;
564360484Sobrien	      break;
564460484Sobrien
564560484Sobrien	    case DW_LNS_negate_stmt:
564660484Sobrien	      adv = state_machine_regs.is_stmt;
564760484Sobrien	      adv = ! adv;
564860484Sobrien	      printf (_("  Set is_stmt to %d\n"), adv);
564960484Sobrien	      state_machine_regs.is_stmt = adv;
565060484Sobrien	      break;
565160484Sobrien
565260484Sobrien	    case DW_LNS_set_basic_block:
565360484Sobrien	      printf (_("  Set basic block\n"));
565460484Sobrien	      state_machine_regs.basic_block = 1;
565560484Sobrien	      break;
565660484Sobrien
565760484Sobrien	    case DW_LNS_const_add_pc:
565860484Sobrien	      adv = (((255 - info.li_opcode_base) / info.li_line_range)
565960484Sobrien		     * info.li_min_insn_length);
566060484Sobrien	      state_machine_regs.address += adv;
566160484Sobrien	      printf (_("  Advance PC by constant %d to 0x%lx\n"), adv,
566260484Sobrien		      state_machine_regs.address);
566360484Sobrien	      break;
566460484Sobrien
566560484Sobrien	    case DW_LNS_fixed_advance_pc:
566660484Sobrien	      adv = byte_get (data, 2);
566760484Sobrien	      data += 2;
566860484Sobrien	      state_machine_regs.address += adv;
566960484Sobrien	      printf (_("  Advance PC by fixed size amount %d to 0x%lx\n"),
567060484Sobrien		      adv, state_machine_regs.address);
567160484Sobrien	      break;
567260484Sobrien
567360484Sobrien	    default:
567460484Sobrien	      op_code -= info.li_opcode_base;
567560484Sobrien	      adv      = (op_code / info.li_line_range) * info.li_min_insn_length;
567660484Sobrien	      state_machine_regs.address += adv;
567760484Sobrien	      printf (_("  Special opcode %d: advance Address by %d to 0x%lx"),
567860484Sobrien		      op_code, adv, state_machine_regs.address);
567960484Sobrien	      adv = (op_code % info.li_line_range) + info.li_line_base;
568060484Sobrien	      state_machine_regs.line += adv;
568160484Sobrien	      printf (_(" and Line by %d to %d\n"),
568260484Sobrien		      adv, state_machine_regs.line);
568360484Sobrien	      break;
568460484Sobrien	    }
568560484Sobrien	}
568660484Sobrien      printf ("\n");
568760484Sobrien    }
568860484Sobrien
568960484Sobrien  return 1;
569060484Sobrien}
569160484Sobrien
569260484Sobrienstatic int
569360484Sobriendisplay_debug_pubnames (section, start, file)
569460484Sobrien     Elf32_Internal_Shdr * section;
569560484Sobrien     unsigned char *       start;
569660484Sobrien     FILE *                file ATTRIBUTE_UNUSED;
569760484Sobrien{
569860484Sobrien  DWARF2_External_PubNames * external;
569960484Sobrien  DWARF2_Internal_PubNames   pubnames;
570060484Sobrien  unsigned char *            end;
570160484Sobrien
570260484Sobrien  end = start + section->sh_size;
570360484Sobrien
570460484Sobrien  printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section));
570560484Sobrien
570660484Sobrien  while (start < end)
570760484Sobrien    {
570860484Sobrien      unsigned char * data;
570960484Sobrien      unsigned long   offset;
571060484Sobrien
571160484Sobrien      external = (DWARF2_External_PubNames *) start;
571260484Sobrien
571360484Sobrien      pubnames.pn_length  = BYTE_GET (external->pn_length);
571460484Sobrien      pubnames.pn_version = BYTE_GET (external->pn_version);
571560484Sobrien      pubnames.pn_offset  = BYTE_GET (external->pn_offset);
571660484Sobrien      pubnames.pn_size    = BYTE_GET (external->pn_size);
571760484Sobrien
571860484Sobrien      data   = start + sizeof (* external);
571960484Sobrien      start += pubnames.pn_length + sizeof (external->pn_length);
572060484Sobrien
572160484Sobrien      if (pubnames.pn_version != 2)
572260484Sobrien	{
572368765Sobrien	  static int warned = 0;
572468765Sobrien
572568765Sobrien	  if (! warned)
572668765Sobrien	    {
572768765Sobrien	      warn (_("Only DWARF 2 pubnames are currently supported\n"));
572868765Sobrien	      warned = 1;
572968765Sobrien	    }
573077298Sobrien
573160484Sobrien	  continue;
573260484Sobrien	}
573360484Sobrien
573460484Sobrien      printf (_("  Length:                              %ld\n"),
573560484Sobrien	      pubnames.pn_length);
573660484Sobrien      printf (_("  Version:                             %d\n"),
573760484Sobrien	      pubnames.pn_version);
573860484Sobrien      printf (_("  Offset into .debug_info section:     %ld\n"),
573960484Sobrien	      pubnames.pn_offset);
574060484Sobrien      printf (_("  Size of area in .debug_info section: %ld\n"),
574160484Sobrien	      pubnames.pn_size);
574260484Sobrien
574360484Sobrien      printf (_("\n    Offset\tName\n"));
574460484Sobrien
574560484Sobrien      do
574660484Sobrien	{
574760484Sobrien	  offset = byte_get (data, 4);
574860484Sobrien
574960484Sobrien	  if (offset != 0)
575060484Sobrien	    {
575160484Sobrien	      data += 4;
575260484Sobrien	      printf ("    %ld\t\t%s\n", offset, data);
575377298Sobrien	      data += strlen ((char *) data) + 1;
575460484Sobrien	    }
575560484Sobrien	}
575660484Sobrien      while (offset != 0);
575760484Sobrien    }
575860484Sobrien
575960484Sobrien  printf ("\n");
576060484Sobrien  return 1;
576160484Sobrien}
576260484Sobrien
576360484Sobrienstatic char *
576460484Sobrienget_TAG_name (tag)
576560484Sobrien     unsigned long tag;
576660484Sobrien{
576760484Sobrien  switch (tag)
576860484Sobrien    {
576960484Sobrien    case DW_TAG_padding: return "DW_TAG_padding";
577060484Sobrien    case DW_TAG_array_type: return "DW_TAG_array_type";
577160484Sobrien    case DW_TAG_class_type: return "DW_TAG_class_type";
577260484Sobrien    case DW_TAG_entry_point: return "DW_TAG_entry_point";
577360484Sobrien    case DW_TAG_enumeration_type: return "DW_TAG_enumeration_type";
577460484Sobrien    case DW_TAG_formal_parameter: return "DW_TAG_formal_parameter";
577560484Sobrien    case DW_TAG_imported_declaration: return "DW_TAG_imported_declaration";
577660484Sobrien    case DW_TAG_label: return "DW_TAG_label";
577760484Sobrien    case DW_TAG_lexical_block: return "DW_TAG_lexical_block";
577860484Sobrien    case DW_TAG_member: return "DW_TAG_member";
577960484Sobrien    case DW_TAG_pointer_type: return "DW_TAG_pointer_type";
578060484Sobrien    case DW_TAG_reference_type: return "DW_TAG_reference_type";
578160484Sobrien    case DW_TAG_compile_unit: return "DW_TAG_compile_unit";
578260484Sobrien    case DW_TAG_string_type: return "DW_TAG_string_type";
578360484Sobrien    case DW_TAG_structure_type: return "DW_TAG_structure_type";
578460484Sobrien    case DW_TAG_subroutine_type: return "DW_TAG_subroutine_type";
578560484Sobrien    case DW_TAG_typedef: return "DW_TAG_typedef";
578660484Sobrien    case DW_TAG_union_type: return "DW_TAG_union_type";
578760484Sobrien    case DW_TAG_unspecified_parameters: return "DW_TAG_unspecified_parameters";
578860484Sobrien    case DW_TAG_variant: return "DW_TAG_variant";
578960484Sobrien    case DW_TAG_common_block: return "DW_TAG_common_block";
579060484Sobrien    case DW_TAG_common_inclusion: return "DW_TAG_common_inclusion";
579160484Sobrien    case DW_TAG_inheritance: return "DW_TAG_inheritance";
579260484Sobrien    case DW_TAG_inlined_subroutine: return "DW_TAG_inlined_subroutine";
579360484Sobrien    case DW_TAG_module: return "DW_TAG_module";
579460484Sobrien    case DW_TAG_ptr_to_member_type: return "DW_TAG_ptr_to_member_type";
579560484Sobrien    case DW_TAG_set_type: return "DW_TAG_set_type";
579660484Sobrien    case DW_TAG_subrange_type: return "DW_TAG_subrange_type";
579760484Sobrien    case DW_TAG_with_stmt: return "DW_TAG_with_stmt";
579860484Sobrien    case DW_TAG_access_declaration: return "DW_TAG_access_declaration";
579960484Sobrien    case DW_TAG_base_type: return "DW_TAG_base_type";
580060484Sobrien    case DW_TAG_catch_block: return "DW_TAG_catch_block";
580160484Sobrien    case DW_TAG_const_type: return "DW_TAG_const_type";
580260484Sobrien    case DW_TAG_constant: return "DW_TAG_constant";
580360484Sobrien    case DW_TAG_enumerator: return "DW_TAG_enumerator";
580460484Sobrien    case DW_TAG_file_type: return "DW_TAG_file_type";
580560484Sobrien    case DW_TAG_friend: return "DW_TAG_friend";
580660484Sobrien    case DW_TAG_namelist: return "DW_TAG_namelist";
580760484Sobrien    case DW_TAG_namelist_item: return "DW_TAG_namelist_item";
580860484Sobrien    case DW_TAG_packed_type: return "DW_TAG_packed_type";
580960484Sobrien    case DW_TAG_subprogram: return "DW_TAG_subprogram";
581060484Sobrien    case DW_TAG_template_type_param: return "DW_TAG_template_type_param";
581160484Sobrien    case DW_TAG_template_value_param: return "DW_TAG_template_value_param";
581260484Sobrien    case DW_TAG_thrown_type: return "DW_TAG_thrown_type";
581360484Sobrien    case DW_TAG_try_block: return "DW_TAG_try_block";
581460484Sobrien    case DW_TAG_variant_part: return "DW_TAG_variant_part";
581560484Sobrien    case DW_TAG_variable: return "DW_TAG_variable";
581660484Sobrien    case DW_TAG_volatile_type: return "DW_TAG_volatile_type";
581760484Sobrien    case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop";
581860484Sobrien    case DW_TAG_format_label: return "DW_TAG_format_label";
581960484Sobrien    case DW_TAG_function_template: return "DW_TAG_function_template";
582060484Sobrien    case DW_TAG_class_template: return "DW_TAG_class_template";
582160484Sobrien    default:
582260484Sobrien      {
582360484Sobrien	static char buffer [100];
582460484Sobrien
582560484Sobrien	sprintf (buffer, _("Unknown TAG value: %lx"), tag);
582660484Sobrien	return buffer;
582760484Sobrien      }
582860484Sobrien    }
582960484Sobrien}
583060484Sobrien
583160484Sobrienstatic char *
583260484Sobrienget_AT_name (attribute)
583360484Sobrien     unsigned long attribute;
583460484Sobrien{
583560484Sobrien  switch (attribute)
583660484Sobrien    {
583760484Sobrien    case DW_AT_sibling: return "DW_AT_sibling";
583860484Sobrien    case DW_AT_location: return "DW_AT_location";
583960484Sobrien    case DW_AT_name: return "DW_AT_name";
584060484Sobrien    case DW_AT_ordering: return "DW_AT_ordering";
584160484Sobrien    case DW_AT_subscr_data: return "DW_AT_subscr_data";
584260484Sobrien    case DW_AT_byte_size: return "DW_AT_byte_size";
584360484Sobrien    case DW_AT_bit_offset: return "DW_AT_bit_offset";
584460484Sobrien    case DW_AT_bit_size: return "DW_AT_bit_size";
584560484Sobrien    case DW_AT_element_list: return "DW_AT_element_list";
584660484Sobrien    case DW_AT_stmt_list: return "DW_AT_stmt_list";
584760484Sobrien    case DW_AT_low_pc: return "DW_AT_low_pc";
584860484Sobrien    case DW_AT_high_pc: return "DW_AT_high_pc";
584960484Sobrien    case DW_AT_language: return "DW_AT_language";
585060484Sobrien    case DW_AT_member: return "DW_AT_member";
585160484Sobrien    case DW_AT_discr: return "DW_AT_discr";
585260484Sobrien    case DW_AT_discr_value: return "DW_AT_discr_value";
585360484Sobrien    case DW_AT_visibility: return "DW_AT_visibility";
585460484Sobrien    case DW_AT_import: return "DW_AT_import";
585560484Sobrien    case DW_AT_string_length: return "DW_AT_string_length";
585660484Sobrien    case DW_AT_common_reference: return "DW_AT_common_reference";
585760484Sobrien    case DW_AT_comp_dir: return "DW_AT_comp_dir";
585860484Sobrien    case DW_AT_const_value: return "DW_AT_const_value";
585960484Sobrien    case DW_AT_containing_type: return "DW_AT_containing_type";
586060484Sobrien    case DW_AT_default_value: return "DW_AT_default_value";
586160484Sobrien    case DW_AT_inline: return "DW_AT_inline";
586260484Sobrien    case DW_AT_is_optional: return "DW_AT_is_optional";
586360484Sobrien    case DW_AT_lower_bound: return "DW_AT_lower_bound";
586460484Sobrien    case DW_AT_producer: return "DW_AT_producer";
586560484Sobrien    case DW_AT_prototyped: return "DW_AT_prototyped";
586660484Sobrien    case DW_AT_return_addr: return "DW_AT_return_addr";
586760484Sobrien    case DW_AT_start_scope: return "DW_AT_start_scope";
586860484Sobrien    case DW_AT_stride_size: return "DW_AT_stride_size";
586960484Sobrien    case DW_AT_upper_bound: return "DW_AT_upper_bound";
587060484Sobrien    case DW_AT_abstract_origin: return "DW_AT_abstract_origin";
587160484Sobrien    case DW_AT_accessibility: return "DW_AT_accessibility";
587260484Sobrien    case DW_AT_address_class: return "DW_AT_address_class";
587360484Sobrien    case DW_AT_artificial: return "DW_AT_artificial";
587460484Sobrien    case DW_AT_base_types: return "DW_AT_base_types";
587560484Sobrien    case DW_AT_calling_convention: return "DW_AT_calling_convention";
587660484Sobrien    case DW_AT_count: return "DW_AT_count";
587760484Sobrien    case DW_AT_data_member_location: return "DW_AT_data_member_location";
587860484Sobrien    case DW_AT_decl_column: return "DW_AT_decl_column";
587960484Sobrien    case DW_AT_decl_file: return "DW_AT_decl_file";
588060484Sobrien    case DW_AT_decl_line: return "DW_AT_decl_line";
588160484Sobrien    case DW_AT_declaration: return "DW_AT_declaration";
588260484Sobrien    case DW_AT_discr_list: return "DW_AT_discr_list";
588360484Sobrien    case DW_AT_encoding: return "DW_AT_encoding";
588460484Sobrien    case DW_AT_external: return "DW_AT_external";
588560484Sobrien    case DW_AT_frame_base: return "DW_AT_frame_base";
588660484Sobrien    case DW_AT_friend: return "DW_AT_friend";
588760484Sobrien    case DW_AT_identifier_case: return "DW_AT_identifier_case";
588860484Sobrien    case DW_AT_macro_info: return "DW_AT_macro_info";
588960484Sobrien    case DW_AT_namelist_items: return "DW_AT_namelist_items";
589060484Sobrien    case DW_AT_priority: return "DW_AT_priority";
589160484Sobrien    case DW_AT_segment: return "DW_AT_segment";
589260484Sobrien    case DW_AT_specification: return "DW_AT_specification";
589360484Sobrien    case DW_AT_static_link: return "DW_AT_static_link";
589460484Sobrien    case DW_AT_type: return "DW_AT_type";
589560484Sobrien    case DW_AT_use_location: return "DW_AT_use_location";
589660484Sobrien    case DW_AT_variable_parameter: return "DW_AT_variable_parameter";
589760484Sobrien    case DW_AT_virtuality: return "DW_AT_virtuality";
589860484Sobrien    case DW_AT_vtable_elem_location: return "DW_AT_vtable_elem_location";
589960484Sobrien    case DW_AT_MIPS_fde: return "DW_AT_MIPS_fde";
590060484Sobrien    case DW_AT_MIPS_loop_begin: return "DW_AT_MIPS_loop_begin";
590160484Sobrien    case DW_AT_MIPS_tail_loop_begin: return "DW_AT_MIPS_tail_loop_begin";
590260484Sobrien    case DW_AT_MIPS_epilog_begin: return "DW_AT_MIPS_epilog_begin";
590360484Sobrien    case DW_AT_MIPS_loop_unroll_factor: return "DW_AT_MIPS_loop_unroll_factor";
590460484Sobrien    case DW_AT_MIPS_software_pipeline_depth: return "DW_AT_MIPS_software_pipeline_depth";
590560484Sobrien    case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name";
590660484Sobrien    case DW_AT_MIPS_stride: return "DW_AT_MIPS_stride";
590760484Sobrien    case DW_AT_MIPS_abstract_name: return "DW_AT_MIPS_abstract_name";
590860484Sobrien    case DW_AT_MIPS_clone_origin: return "DW_AT_MIPS_clone_origin";
590960484Sobrien    case DW_AT_MIPS_has_inlines: return "DW_AT_MIPS_has_inlines";
591060484Sobrien    case DW_AT_sf_names: return "DW_AT_sf_names";
591160484Sobrien    case DW_AT_src_info: return "DW_AT_src_info";
591260484Sobrien    case DW_AT_mac_info: return "DW_AT_mac_info";
591360484Sobrien    case DW_AT_src_coords: return "DW_AT_src_coords";
591460484Sobrien    case DW_AT_body_begin: return "DW_AT_body_begin";
591560484Sobrien    case DW_AT_body_end: return "DW_AT_body_end";
591660484Sobrien    default:
591760484Sobrien      {
591860484Sobrien	static char buffer [100];
591960484Sobrien
592060484Sobrien	sprintf (buffer, _("Unknown AT value: %lx"), attribute);
592160484Sobrien	return buffer;
592260484Sobrien      }
592360484Sobrien    }
592460484Sobrien}
592560484Sobrien
592660484Sobrienstatic char *
592760484Sobrienget_FORM_name (form)
592860484Sobrien     unsigned long form;
592960484Sobrien{
593060484Sobrien  switch (form)
593160484Sobrien    {
593260484Sobrien    case DW_FORM_addr: return "DW_FORM_addr";
593360484Sobrien    case DW_FORM_block2: return "DW_FORM_block2";
593460484Sobrien    case DW_FORM_block4: return "DW_FORM_block4";
593560484Sobrien    case DW_FORM_data2: return "DW_FORM_data2";
593660484Sobrien    case DW_FORM_data4: return "DW_FORM_data4";
593760484Sobrien    case DW_FORM_data8: return "DW_FORM_data8";
593860484Sobrien    case DW_FORM_string: return "DW_FORM_string";
593960484Sobrien    case DW_FORM_block: return "DW_FORM_block";
594060484Sobrien    case DW_FORM_block1: return "DW_FORM_block1";
594160484Sobrien    case DW_FORM_data1: return "DW_FORM_data1";
594260484Sobrien    case DW_FORM_flag: return "DW_FORM_flag";
594360484Sobrien    case DW_FORM_sdata: return "DW_FORM_sdata";
594460484Sobrien    case DW_FORM_strp: return "DW_FORM_strp";
594560484Sobrien    case DW_FORM_udata: return "DW_FORM_udata";
594660484Sobrien    case DW_FORM_ref_addr: return "DW_FORM_ref_addr";
594760484Sobrien    case DW_FORM_ref1: return "DW_FORM_ref1";
594860484Sobrien    case DW_FORM_ref2: return "DW_FORM_ref2";
594960484Sobrien    case DW_FORM_ref4: return "DW_FORM_ref4";
595060484Sobrien    case DW_FORM_ref8: return "DW_FORM_ref8";
595160484Sobrien    case DW_FORM_ref_udata: return "DW_FORM_ref_udata";
595260484Sobrien    case DW_FORM_indirect: return "DW_FORM_indirect";
595360484Sobrien    default:
595460484Sobrien      {
595560484Sobrien	static char buffer [100];
595660484Sobrien
595760484Sobrien	sprintf (buffer, _("Unknown FORM value: %lx"), form);
595860484Sobrien	return buffer;
595960484Sobrien      }
596060484Sobrien    }
596160484Sobrien}
596260484Sobrien
596360484Sobrien/* FIXME:  There are better and more effiecint ways to handle
596460484Sobrien   these structures.  For now though, I just want something that
596560484Sobrien   is simple to implement.  */
596660484Sobrientypedef struct abbrev_attr
596760484Sobrien{
596860484Sobrien  unsigned long        attribute;
596960484Sobrien  unsigned long        form;
597060484Sobrien  struct abbrev_attr * next;
597160484Sobrien}
597260484Sobrienabbrev_attr;
597360484Sobrien
597460484Sobrientypedef struct abbrev_entry
597560484Sobrien{
597660484Sobrien  unsigned long          entry;
597760484Sobrien  unsigned long          tag;
597860484Sobrien  int                    children;
597960484Sobrien  struct abbrev_attr *   first_attr;
598060484Sobrien  struct abbrev_attr *   last_attr;
598160484Sobrien  struct abbrev_entry *  next;
598260484Sobrien}
598360484Sobrienabbrev_entry;
598460484Sobrien
598560484Sobrienstatic abbrev_entry * first_abbrev = NULL;
598660484Sobrienstatic abbrev_entry * last_abbrev = NULL;
598760484Sobrien
598860484Sobrienstatic void
598960484Sobrienfree_abbrevs PARAMS ((void))
599060484Sobrien{
599160484Sobrien  abbrev_entry * abbrev;
599260484Sobrien
599360484Sobrien  for (abbrev = first_abbrev; abbrev;)
599460484Sobrien    {
599560484Sobrien      abbrev_entry * next = abbrev->next;
599660484Sobrien      abbrev_attr  * attr;
599760484Sobrien
599860484Sobrien      for (attr = abbrev->first_attr; attr;)
599960484Sobrien	{
600060484Sobrien	  abbrev_attr * next = attr->next;
600160484Sobrien
600260484Sobrien	  free (attr);
600360484Sobrien	  attr = next;
600460484Sobrien	}
600560484Sobrien
600660484Sobrien      free (abbrev);
600760484Sobrien      abbrev = next;
600860484Sobrien    }
600960484Sobrien
601060484Sobrien  last_abbrev = first_abbrev = NULL;
601160484Sobrien}
601260484Sobrien
601360484Sobrienstatic void
601460484Sobrienadd_abbrev (number, tag, children)
601560484Sobrien     unsigned long number;
601660484Sobrien     unsigned long tag;
601760484Sobrien     int           children;
601860484Sobrien{
601960484Sobrien  abbrev_entry * entry;
602060484Sobrien
602160484Sobrien  entry = (abbrev_entry *) malloc (sizeof (* entry));
602260484Sobrien
602360484Sobrien  if (entry == NULL)
602460484Sobrien    /* ugg */
602560484Sobrien    return;
602660484Sobrien
602760484Sobrien  entry->entry      = number;
602860484Sobrien  entry->tag        = tag;
602960484Sobrien  entry->children   = children;
603060484Sobrien  entry->first_attr = NULL;
603160484Sobrien  entry->last_attr  = NULL;
603260484Sobrien  entry->next       = NULL;
603360484Sobrien
603460484Sobrien  if (first_abbrev == NULL)
603560484Sobrien    first_abbrev = entry;
603660484Sobrien  else
603760484Sobrien    last_abbrev->next = entry;
603860484Sobrien
603960484Sobrien  last_abbrev = entry;
604060484Sobrien}
604160484Sobrien
604260484Sobrienstatic void
604360484Sobrienadd_abbrev_attr (attribute, form)
604460484Sobrien     unsigned long attribute;
604560484Sobrien     unsigned long form;
604660484Sobrien{
604760484Sobrien  abbrev_attr * attr;
604860484Sobrien
604960484Sobrien  attr = (abbrev_attr *) malloc (sizeof (* attr));
605060484Sobrien
605160484Sobrien  if (attr == NULL)
605260484Sobrien    /* ugg */
605360484Sobrien    return;
605460484Sobrien
605560484Sobrien  attr->attribute = attribute;
605660484Sobrien  attr->form      = form;
605760484Sobrien  attr->next      = NULL;
605860484Sobrien
605960484Sobrien  if (last_abbrev->first_attr == NULL)
606060484Sobrien    last_abbrev->first_attr = attr;
606160484Sobrien  else
606260484Sobrien    last_abbrev->last_attr->next = attr;
606360484Sobrien
606460484Sobrien  last_abbrev->last_attr = attr;
606560484Sobrien}
606660484Sobrien
606760484Sobrien/* Processes the (partial) contents of a .debug_abbrev section.
606860484Sobrien   Returns NULL if the end of the section was encountered.
606960484Sobrien   Returns the address after the last byte read if the end of
607060484Sobrien   an abbreviation set was found.  */
607160484Sobrien
607260484Sobrienstatic unsigned char *
607360484Sobrienprocess_abbrev_section (start, end)
607460484Sobrien     unsigned char * start;
607560484Sobrien     unsigned char * end;
607660484Sobrien{
607760484Sobrien  if (first_abbrev != NULL)
607860484Sobrien    return NULL;
607960484Sobrien
608060484Sobrien  while (start < end)
608160484Sobrien    {
608260484Sobrien      int           bytes_read;
608360484Sobrien      unsigned long entry;
608460484Sobrien      unsigned long tag;
608560484Sobrien      unsigned long attribute;
608660484Sobrien      int           children;
608760484Sobrien
608860484Sobrien      entry = read_leb128 (start, & bytes_read, 0);
608960484Sobrien      start += bytes_read;
609060484Sobrien
609160484Sobrien      /* A single zero is supposed to end the section according
609260484Sobrien	 to the standard.  If there's more, then signal that to
609360484Sobrien	 the caller.  */
609460484Sobrien      if (entry == 0)
609560484Sobrien	return start == end ? NULL : start;
609660484Sobrien
609760484Sobrien      tag = read_leb128 (start, & bytes_read, 0);
609860484Sobrien      start += bytes_read;
609960484Sobrien
610060484Sobrien      children = * start ++;
610160484Sobrien
610260484Sobrien      add_abbrev (entry, tag, children);
610360484Sobrien
610460484Sobrien      do
610560484Sobrien	{
610660484Sobrien	  unsigned long form;
610760484Sobrien
610860484Sobrien	  attribute = read_leb128 (start, & bytes_read, 0);
610960484Sobrien	  start += bytes_read;
611060484Sobrien
611160484Sobrien	  form = read_leb128 (start, & bytes_read, 0);
611260484Sobrien	  start += bytes_read;
611360484Sobrien
611460484Sobrien	  if (attribute != 0)
611560484Sobrien	    add_abbrev_attr (attribute, form);
611660484Sobrien	}
611760484Sobrien      while (attribute != 0);
611860484Sobrien    }
611960484Sobrien
612060484Sobrien  return NULL;
612160484Sobrien}
612260484Sobrien
612360484Sobrien
612460484Sobrienstatic int
612560484Sobriendisplay_debug_abbrev (section, start, file)
612660484Sobrien     Elf32_Internal_Shdr * section;
612760484Sobrien     unsigned char *       start;
612860484Sobrien     FILE *                file ATTRIBUTE_UNUSED;
612960484Sobrien{
613077298Sobrien  abbrev_entry *  entry;
613160484Sobrien  unsigned char * end = start + section->sh_size;
613260484Sobrien
613360484Sobrien  printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section));
613460484Sobrien
613560484Sobrien  do
613660484Sobrien    {
613760484Sobrien      start = process_abbrev_section (start, end);
613860484Sobrien
613960484Sobrien      printf (_("  Number TAG\n"));
614060484Sobrien
614160484Sobrien      for (entry = first_abbrev; entry; entry = entry->next)
614260484Sobrien	{
614360484Sobrien	  abbrev_attr * attr;
614460484Sobrien
614560484Sobrien	  printf (_("   %ld      %s    [%s]\n"),
614660484Sobrien		  entry->entry,
614760484Sobrien		  get_TAG_name (entry->tag),
614860484Sobrien		  entry->children ? _("has children") : _("no children"));
614960484Sobrien
615060484Sobrien	  for (attr = entry->first_attr; attr; attr = attr->next)
615160484Sobrien	    {
615260484Sobrien	      printf (_("    %-18s %s\n"),
615360484Sobrien		      get_AT_name (attr->attribute),
615460484Sobrien		      get_FORM_name (attr->form));
615560484Sobrien	    }
615660484Sobrien	}
615760484Sobrien    }
615860484Sobrien  while (start);
615960484Sobrien
616060484Sobrien  printf ("\n");
616160484Sobrien
616260484Sobrien  return 1;
616360484Sobrien}
616460484Sobrien
616560484Sobrien
616660484Sobrienstatic unsigned char *
616760484Sobriendisplay_block (data, length)
616860484Sobrien     unsigned char * data;
616960484Sobrien     unsigned long   length;
617060484Sobrien{
617160484Sobrien  printf (_(" %lu byte block: "), length);
617260484Sobrien
617360484Sobrien  while (length --)
617460484Sobrien    printf ("%lx ", (unsigned long) byte_get (data ++, 1));
617560484Sobrien
617660484Sobrien  return data;
617760484Sobrien}
617860484Sobrien
617960484Sobrienstatic void
618077298Sobriendecode_location_expression (data, pointer_size, length)
618160484Sobrien     unsigned char * data;
618260484Sobrien     unsigned int    pointer_size;
618377298Sobrien     unsigned long   length;
618460484Sobrien{
618577298Sobrien  unsigned        op;
618677298Sobrien  int             bytes_read;
618777298Sobrien  unsigned long   uvalue;
618877298Sobrien  unsigned char * end = data + length;
618960484Sobrien
619077298Sobrien  while (data < end)
619160484Sobrien    {
619277298Sobrien      op = * data ++;
619360484Sobrien
619477298Sobrien      switch (op)
619577298Sobrien	{
619677298Sobrien	case DW_OP_addr:
619777298Sobrien	  printf ("DW_OP_addr: %lx",
619877298Sobrien		  (unsigned long) byte_get (data, pointer_size));
619977298Sobrien	  data += pointer_size;
620077298Sobrien	  break;
620177298Sobrien	case DW_OP_deref:
620277298Sobrien	  printf ("DW_OP_deref");
620377298Sobrien	  break;
620477298Sobrien	case DW_OP_const1u:
620577298Sobrien	  printf ("DW_OP_const1u: %lu", (unsigned long) byte_get (data++, 1));
620677298Sobrien	  break;
620777298Sobrien	case DW_OP_const1s:
620877298Sobrien	  printf ("DW_OP_const1s: %ld", (long) byte_get (data++, 1));
620977298Sobrien	  break;
621077298Sobrien	case DW_OP_const2u:
621177298Sobrien	  printf ("DW_OP_const2u: %lu", (unsigned long) byte_get (data, 2));
621277298Sobrien	  data += 2;
621377298Sobrien	  break;
621477298Sobrien	case DW_OP_const2s:
621577298Sobrien	  printf ("DW_OP_const2s: %ld", (long) byte_get (data, 2));
621677298Sobrien	  data += 2;
621777298Sobrien	  break;
621877298Sobrien	case DW_OP_const4u:
621977298Sobrien	  printf ("DW_OP_const4u: %lu", (unsigned long) byte_get (data, 4));
622077298Sobrien	  data += 4;
622177298Sobrien	  break;
622277298Sobrien	case DW_OP_const4s:
622377298Sobrien	  printf ("DW_OP_const4s: %ld", (long) byte_get (data, 4));
622477298Sobrien	  data += 4;
622577298Sobrien	  break;
622677298Sobrien	case DW_OP_const8u:
622777298Sobrien	  printf ("DW_OP_const8u: %lu %lu", (unsigned long) byte_get (data, 4),
622877298Sobrien		  (unsigned long) byte_get (data + 4, 4));
622977298Sobrien	  data += 8;
623077298Sobrien	  break;
623177298Sobrien	case DW_OP_const8s:
623277298Sobrien	  printf ("DW_OP_const8s: %ld %ld", (long) byte_get (data, 4),
623377298Sobrien		  (long) byte_get (data + 4, 4));
623477298Sobrien	  data += 8;
623577298Sobrien	  break;
623677298Sobrien	case DW_OP_constu:
623777298Sobrien	  printf ("DW_OP_constu: %lu", read_leb128 (data, &bytes_read, 0));
623877298Sobrien	  data += bytes_read;
623977298Sobrien	  break;
624077298Sobrien	case DW_OP_consts:
624177298Sobrien	  printf ("DW_OP_consts: %ld", read_leb128 (data, &bytes_read, 1));
624277298Sobrien	  data += bytes_read;
624377298Sobrien	  break;
624477298Sobrien	case DW_OP_dup:
624577298Sobrien	  printf ("DW_OP_dup");
624677298Sobrien	  break;
624777298Sobrien	case DW_OP_drop:
624877298Sobrien	  printf ("DW_OP_drop");
624977298Sobrien	  break;
625077298Sobrien	case DW_OP_over:
625177298Sobrien	  printf ("DW_OP_over");
625277298Sobrien	  break;
625377298Sobrien	case DW_OP_pick:
625477298Sobrien	  printf ("DW_OP_pick: %ld", (unsigned long) byte_get (data++, 1));
625577298Sobrien	  break;
625677298Sobrien	case DW_OP_swap:
625777298Sobrien	  printf ("DW_OP_swap");
625877298Sobrien	  break;
625977298Sobrien	case DW_OP_rot:
626077298Sobrien	  printf ("DW_OP_rot");
626177298Sobrien	  break;
626277298Sobrien	case DW_OP_xderef:
626377298Sobrien	  printf ("DW_OP_xderef");
626477298Sobrien	  break;
626577298Sobrien	case DW_OP_abs:
626677298Sobrien	  printf ("DW_OP_abs");
626777298Sobrien	  break;
626877298Sobrien	case DW_OP_and:
626977298Sobrien	  printf ("DW_OP_and");
627077298Sobrien	  break;
627177298Sobrien	case DW_OP_div:
627277298Sobrien	  printf ("DW_OP_div");
627377298Sobrien	  break;
627477298Sobrien	case DW_OP_minus:
627577298Sobrien	  printf ("DW_OP_minus");
627677298Sobrien	  break;
627777298Sobrien	case DW_OP_mod:
627877298Sobrien	  printf ("DW_OP_mod");
627977298Sobrien	  break;
628077298Sobrien	case DW_OP_mul:
628177298Sobrien	  printf ("DW_OP_mul");
628277298Sobrien	  break;
628377298Sobrien	case DW_OP_neg:
628477298Sobrien	  printf ("DW_OP_neg");
628577298Sobrien	  break;
628677298Sobrien	case DW_OP_not:
628777298Sobrien	  printf ("DW_OP_not");
628877298Sobrien	  break;
628977298Sobrien	case DW_OP_or:
629077298Sobrien	  printf ("DW_OP_or");
629177298Sobrien	  break;
629277298Sobrien	case DW_OP_plus:
629377298Sobrien	  printf ("DW_OP_plus");
629477298Sobrien	  break;
629577298Sobrien	case DW_OP_plus_uconst:
629677298Sobrien	  printf ("DW_OP_plus_uconst: %lu",
629777298Sobrien		  read_leb128 (data, &bytes_read, 0));
629877298Sobrien	  data += bytes_read;
629977298Sobrien	  break;
630077298Sobrien	case DW_OP_shl:
630177298Sobrien	  printf ("DW_OP_shl");
630277298Sobrien	  break;
630377298Sobrien	case DW_OP_shr:
630477298Sobrien	  printf ("DW_OP_shr");
630577298Sobrien	  break;
630677298Sobrien	case DW_OP_shra:
630777298Sobrien	  printf ("DW_OP_shra");
630877298Sobrien	  break;
630977298Sobrien	case DW_OP_xor:
631077298Sobrien	  printf ("DW_OP_xor");
631177298Sobrien	  break;
631277298Sobrien	case DW_OP_bra:
631377298Sobrien	  printf ("DW_OP_bra: %ld", (long) byte_get (data, 2));
631477298Sobrien	  data += 2;
631577298Sobrien	  break;
631677298Sobrien	case DW_OP_eq:
631777298Sobrien	  printf ("DW_OP_eq");
631877298Sobrien	  break;
631977298Sobrien	case DW_OP_ge:
632077298Sobrien	  printf ("DW_OP_ge");
632177298Sobrien	  break;
632277298Sobrien	case DW_OP_gt:
632377298Sobrien	  printf ("DW_OP_gt");
632477298Sobrien	  break;
632577298Sobrien	case DW_OP_le:
632677298Sobrien	  printf ("DW_OP_le");
632777298Sobrien	  break;
632877298Sobrien	case DW_OP_lt:
632977298Sobrien	  printf ("DW_OP_lt");
633077298Sobrien	  break;
633177298Sobrien	case DW_OP_ne:
633277298Sobrien	  printf ("DW_OP_ne");
633377298Sobrien	  break;
633477298Sobrien	case DW_OP_skip:
633577298Sobrien	  printf ("DW_OP_skip: %ld", (long) byte_get (data, 2));
633677298Sobrien	  data += 2;
633777298Sobrien	  break;
633877298Sobrien
633977298Sobrien	case DW_OP_lit0:
634077298Sobrien	case DW_OP_lit1:
634177298Sobrien	case DW_OP_lit2:
634277298Sobrien	case DW_OP_lit3:
634377298Sobrien	case DW_OP_lit4:
634477298Sobrien	case DW_OP_lit5:
634577298Sobrien	case DW_OP_lit6:
634677298Sobrien	case DW_OP_lit7:
634777298Sobrien	case DW_OP_lit8:
634877298Sobrien	case DW_OP_lit9:
634977298Sobrien	case DW_OP_lit10:
635077298Sobrien	case DW_OP_lit11:
635177298Sobrien	case DW_OP_lit12:
635277298Sobrien	case DW_OP_lit13:
635377298Sobrien	case DW_OP_lit14:
635477298Sobrien	case DW_OP_lit15:
635577298Sobrien	case DW_OP_lit16:
635677298Sobrien	case DW_OP_lit17:
635777298Sobrien	case DW_OP_lit18:
635877298Sobrien	case DW_OP_lit19:
635977298Sobrien	case DW_OP_lit20:
636077298Sobrien	case DW_OP_lit21:
636177298Sobrien	case DW_OP_lit22:
636277298Sobrien	case DW_OP_lit23:
636377298Sobrien	case DW_OP_lit24:
636477298Sobrien	case DW_OP_lit25:
636577298Sobrien	case DW_OP_lit26:
636677298Sobrien	case DW_OP_lit27:
636777298Sobrien	case DW_OP_lit28:
636877298Sobrien	case DW_OP_lit29:
636977298Sobrien	case DW_OP_lit30:
637077298Sobrien	case DW_OP_lit31:
637177298Sobrien	  printf ("DW_OP_lit%d", op - DW_OP_lit0);
637277298Sobrien	  break;
637377298Sobrien
637477298Sobrien	case DW_OP_reg0:
637577298Sobrien	case DW_OP_reg1:
637677298Sobrien	case DW_OP_reg2:
637777298Sobrien	case DW_OP_reg3:
637877298Sobrien	case DW_OP_reg4:
637977298Sobrien	case DW_OP_reg5:
638077298Sobrien	case DW_OP_reg6:
638177298Sobrien	case DW_OP_reg7:
638277298Sobrien	case DW_OP_reg8:
638377298Sobrien	case DW_OP_reg9:
638477298Sobrien	case DW_OP_reg10:
638577298Sobrien	case DW_OP_reg11:
638677298Sobrien	case DW_OP_reg12:
638777298Sobrien	case DW_OP_reg13:
638877298Sobrien	case DW_OP_reg14:
638977298Sobrien	case DW_OP_reg15:
639077298Sobrien	case DW_OP_reg16:
639177298Sobrien	case DW_OP_reg17:
639277298Sobrien	case DW_OP_reg18:
639377298Sobrien	case DW_OP_reg19:
639477298Sobrien	case DW_OP_reg20:
639577298Sobrien	case DW_OP_reg21:
639677298Sobrien	case DW_OP_reg22:
639777298Sobrien	case DW_OP_reg23:
639877298Sobrien	case DW_OP_reg24:
639977298Sobrien	case DW_OP_reg25:
640077298Sobrien	case DW_OP_reg26:
640177298Sobrien	case DW_OP_reg27:
640277298Sobrien	case DW_OP_reg28:
640377298Sobrien	case DW_OP_reg29:
640477298Sobrien	case DW_OP_reg30:
640577298Sobrien	case DW_OP_reg31:
640677298Sobrien	  printf ("DW_OP_reg%d", op - DW_OP_reg0);
640777298Sobrien	  break;
640877298Sobrien
640977298Sobrien	case DW_OP_breg0:
641077298Sobrien	case DW_OP_breg1:
641177298Sobrien	case DW_OP_breg2:
641277298Sobrien	case DW_OP_breg3:
641377298Sobrien	case DW_OP_breg4:
641477298Sobrien	case DW_OP_breg5:
641577298Sobrien	case DW_OP_breg6:
641677298Sobrien	case DW_OP_breg7:
641777298Sobrien	case DW_OP_breg8:
641877298Sobrien	case DW_OP_breg9:
641977298Sobrien	case DW_OP_breg10:
642077298Sobrien	case DW_OP_breg11:
642177298Sobrien	case DW_OP_breg12:
642277298Sobrien	case DW_OP_breg13:
642377298Sobrien	case DW_OP_breg14:
642477298Sobrien	case DW_OP_breg15:
642577298Sobrien	case DW_OP_breg16:
642677298Sobrien	case DW_OP_breg17:
642777298Sobrien	case DW_OP_breg18:
642877298Sobrien	case DW_OP_breg19:
642977298Sobrien	case DW_OP_breg20:
643077298Sobrien	case DW_OP_breg21:
643177298Sobrien	case DW_OP_breg22:
643277298Sobrien	case DW_OP_breg23:
643377298Sobrien	case DW_OP_breg24:
643477298Sobrien	case DW_OP_breg25:
643577298Sobrien	case DW_OP_breg26:
643677298Sobrien	case DW_OP_breg27:
643777298Sobrien	case DW_OP_breg28:
643877298Sobrien	case DW_OP_breg29:
643977298Sobrien	case DW_OP_breg30:
644077298Sobrien	case DW_OP_breg31:
644177298Sobrien	  printf ("DW_OP_breg%d: %ld", op - DW_OP_breg0,
644277298Sobrien		  read_leb128 (data, &bytes_read, 1));
644377298Sobrien	  data += bytes_read;
644477298Sobrien	  break;
644577298Sobrien
644677298Sobrien	case DW_OP_regx:
644777298Sobrien	  printf ("DW_OP_regx: %lu", read_leb128 (data, &bytes_read, 0));
644877298Sobrien	  data += bytes_read;
644977298Sobrien	  break;
645077298Sobrien	case DW_OP_fbreg:
645177298Sobrien	  printf ("DW_OP_fbreg: %ld", read_leb128 (data, &bytes_read, 1));
645277298Sobrien	  data += bytes_read;
645377298Sobrien	  break;
645477298Sobrien	case DW_OP_bregx:
645577298Sobrien	  uvalue = read_leb128 (data, &bytes_read, 0);
645677298Sobrien	  data += bytes_read;
645777298Sobrien	  printf ("DW_OP_bregx: %lu %ld", uvalue,
645877298Sobrien		  read_leb128 (data, &bytes_read, 1));
645977298Sobrien	  data += bytes_read;
646077298Sobrien	  break;
646177298Sobrien	case DW_OP_piece:
646277298Sobrien	  printf ("DW_OP_piece: %lu", read_leb128 (data, &bytes_read, 0));
646377298Sobrien	  data += bytes_read;
646477298Sobrien	  break;
646577298Sobrien	case DW_OP_deref_size:
646677298Sobrien	  printf ("DW_OP_deref_size: %ld", (long) byte_get (data++, 1));
646777298Sobrien	  break;
646877298Sobrien	case DW_OP_xderef_size:
646977298Sobrien	  printf ("DW_OP_xderef_size: %ld", (long) byte_get (data++, 1));
647077298Sobrien	  break;
647177298Sobrien	case DW_OP_nop:
647277298Sobrien	  printf ("DW_OP_nop");
647377298Sobrien	  break;
647477298Sobrien
647577298Sobrien	default:
647677298Sobrien	  if (op >= DW_OP_lo_user
647777298Sobrien	      && op <= DW_OP_hi_user)
647877298Sobrien	    printf (_("(User defined location op)"));
647977298Sobrien	  else
648077298Sobrien	    printf (_("(Unknown location op)"));
648177298Sobrien	  /* No way to tell where the next op is, so just bail.  */
648277298Sobrien	  return;
648377298Sobrien	}
648460484Sobrien    }
648560484Sobrien}
648660484Sobrien
648760484Sobrien
648860484Sobrienstatic unsigned char *
648977298Sobrienread_and_display_attr (attribute, form, data, cu_offset, pointer_size)
649060484Sobrien     unsigned long   attribute;
649160484Sobrien     unsigned long   form;
649260484Sobrien     unsigned char * data;
649377298Sobrien     unsigned long   cu_offset;
649460484Sobrien     unsigned long   pointer_size;
649560484Sobrien{
649660484Sobrien  unsigned long   uvalue = 0;
649760484Sobrien  unsigned char * block_start = NULL;
649860484Sobrien  int             bytes_read;
649960484Sobrien
650060484Sobrien  printf ("     %-18s:", get_AT_name (attribute));
650160484Sobrien
650260484Sobrien  switch (form)
650360484Sobrien    {
650477298Sobrien    default:
650577298Sobrien      break;
650660484Sobrien
650760484Sobrien    case DW_FORM_ref_addr:
650860484Sobrien    case DW_FORM_addr:
650960484Sobrien      uvalue = byte_get (data, pointer_size);
651060484Sobrien      data += pointer_size;
651160484Sobrien      break;
651260484Sobrien
651360484Sobrien    case DW_FORM_ref1:
651460484Sobrien    case DW_FORM_flag:
651560484Sobrien    case DW_FORM_data1:
651660484Sobrien      uvalue = byte_get (data ++, 1);
651760484Sobrien      break;
651860484Sobrien
651960484Sobrien    case DW_FORM_ref2:
652060484Sobrien    case DW_FORM_data2:
652160484Sobrien      uvalue = byte_get (data, 2);
652260484Sobrien      data += 2;
652360484Sobrien      break;
652460484Sobrien
652560484Sobrien    case DW_FORM_ref4:
652660484Sobrien    case DW_FORM_data4:
652760484Sobrien      uvalue = byte_get (data, 4);
652860484Sobrien      data += 4;
652960484Sobrien      break;
653060484Sobrien
653177298Sobrien    case DW_FORM_sdata:
653277298Sobrien      uvalue = read_leb128 (data, & bytes_read, 1);
653377298Sobrien      data += bytes_read;
653477298Sobrien      break;
653577298Sobrien
653677298Sobrien    case DW_FORM_ref_udata:
653777298Sobrien    case DW_FORM_udata:
653877298Sobrien      uvalue = read_leb128 (data, & bytes_read, 0);
653977298Sobrien      data += bytes_read;
654077298Sobrien      break;
654177298Sobrien    }
654277298Sobrien
654377298Sobrien  switch (form)
654477298Sobrien    {
654577298Sobrien    case DW_FORM_ref_addr:
654677298Sobrien      printf (" <#%lx>", uvalue);
654777298Sobrien      break;
654877298Sobrien
654977298Sobrien    case DW_FORM_ref1:
655077298Sobrien    case DW_FORM_ref2:
655177298Sobrien    case DW_FORM_ref4:
655277298Sobrien    case DW_FORM_ref_udata:
655377298Sobrien      printf (" <%lx>", uvalue + cu_offset);
655477298Sobrien      break;
655577298Sobrien
655677298Sobrien    case DW_FORM_addr:
655777298Sobrien      printf (" %#lx", uvalue);
655877298Sobrien
655977298Sobrien    case DW_FORM_flag:
656077298Sobrien    case DW_FORM_data1:
656177298Sobrien    case DW_FORM_data2:
656277298Sobrien    case DW_FORM_data4:
656377298Sobrien    case DW_FORM_sdata:
656477298Sobrien    case DW_FORM_udata:
656577298Sobrien      printf (" %ld", uvalue);
656677298Sobrien      break;
656777298Sobrien
656860484Sobrien    case DW_FORM_ref8:
656960484Sobrien    case DW_FORM_data8:
657060484Sobrien      uvalue = byte_get (data, 4);
657160484Sobrien      printf (" %lx", uvalue);
657260484Sobrien      printf (" %lx", (unsigned long) byte_get (data + 4, 4));
657360484Sobrien      data += 8;
657460484Sobrien      break;
657560484Sobrien
657660484Sobrien    case DW_FORM_string:
657760484Sobrien      printf (" %s", data);
657877298Sobrien      data += strlen ((char *) data) + 1;
657960484Sobrien      break;
658060484Sobrien
658160484Sobrien    case DW_FORM_block:
658260484Sobrien      uvalue = read_leb128 (data, & bytes_read, 0);
658360484Sobrien      block_start = data + bytes_read;
658460484Sobrien      data = display_block (block_start, uvalue);
658560484Sobrien      break;
658660484Sobrien
658760484Sobrien    case DW_FORM_block1:
658860484Sobrien      uvalue = byte_get (data, 1);
658960484Sobrien      block_start = data + 1;
659060484Sobrien      data = display_block (block_start, uvalue);
659160484Sobrien      break;
659260484Sobrien
659360484Sobrien    case DW_FORM_block2:
659460484Sobrien      uvalue = byte_get (data, 2);
659560484Sobrien      block_start = data + 2;
659660484Sobrien      data = display_block (block_start, uvalue);
659760484Sobrien      break;
659860484Sobrien
659960484Sobrien    case DW_FORM_block4:
660060484Sobrien      uvalue = byte_get (data, 4);
660160484Sobrien      block_start = data + 4;
660260484Sobrien      data = display_block (block_start, uvalue);
660360484Sobrien      break;
660460484Sobrien
660560484Sobrien    case DW_FORM_strp:
660660484Sobrien    case DW_FORM_indirect:
660760484Sobrien      warn (_("Unable to handle FORM: %d"), form);
660860484Sobrien      break;
660960484Sobrien
661060484Sobrien    default:
661160484Sobrien      warn (_("Unrecognised form: %d"), form);
661260484Sobrien      break;
661360484Sobrien    }
661460484Sobrien
661560484Sobrien  /* For some attributes we can display futher information.  */
661660484Sobrien
661760484Sobrien  printf ("\t");
661860484Sobrien
661960484Sobrien  switch (attribute)
662060484Sobrien    {
662160484Sobrien    case DW_AT_inline:
662260484Sobrien      switch (uvalue)
662360484Sobrien	{
662460484Sobrien	case DW_INL_not_inlined:          printf (_("(not inlined)")); break;
662560484Sobrien	case DW_INL_inlined:              printf (_("(inlined)")); break;
662660484Sobrien	case DW_INL_declared_not_inlined: printf (_("(declared as inline but ignored)")); break;
662760484Sobrien	case DW_INL_declared_inlined:     printf (_("(declared as inline and inlined)")); break;
662860484Sobrien	default: printf (_("  (Unknown inline attribute value: %lx)"), uvalue); break;
662960484Sobrien	}
663060484Sobrien      break;
663160484Sobrien
663260484Sobrien    case DW_AT_language:
663360484Sobrien      switch (uvalue)
663460484Sobrien	{
663560484Sobrien	case DW_LANG_C:              printf ("(non-ANSI C)"); break;
663660484Sobrien	case DW_LANG_C89:            printf ("(ANSI C)"); break;
663760484Sobrien	case DW_LANG_C_plus_plus:    printf ("(C++)"); break;
663860484Sobrien	case DW_LANG_Fortran77:      printf ("(FORTRAN 77)"); break;
663960484Sobrien	case DW_LANG_Fortran90:      printf ("(Fortran 90)"); break;
664060484Sobrien	case DW_LANG_Modula2:        printf ("(Modula 2)"); break;
664160484Sobrien	case DW_LANG_Pascal83:       printf ("(ANSI Pascal)"); break;
664260484Sobrien	case DW_LANG_Ada83:          printf ("(Ada)"); break;
664360484Sobrien	case DW_LANG_Cobol74:        printf ("(Cobol 74)"); break;
664460484Sobrien	case DW_LANG_Cobol85:        printf ("(Cobol 85)"); break;
664560484Sobrien	case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break;
664660484Sobrien	default:                     printf ("(Unknown: %lx)", uvalue); break;
664760484Sobrien	}
664860484Sobrien      break;
664960484Sobrien
665060484Sobrien    case DW_AT_encoding:
665160484Sobrien      switch (uvalue)
665260484Sobrien	{
665360484Sobrien	case DW_ATE_void:            printf ("(void)"); break;
665460484Sobrien	case DW_ATE_address:         printf ("(machine address)"); break;
665560484Sobrien	case DW_ATE_boolean:         printf ("(boolean)"); break;
665660484Sobrien	case DW_ATE_complex_float:   printf ("(complex float)"); break;
665760484Sobrien	case DW_ATE_float:           printf ("(float)"); break;
665860484Sobrien	case DW_ATE_signed:          printf ("(signed)"); break;
665960484Sobrien	case DW_ATE_signed_char:     printf ("(signed char)"); break;
666060484Sobrien	case DW_ATE_unsigned:        printf ("(unsigned)"); break;
666160484Sobrien	case DW_ATE_unsigned_char:   printf ("(unsigned char)"); break;
666260484Sobrien	default:
666360484Sobrien	  if (uvalue >= DW_ATE_lo_user
666460484Sobrien	      && uvalue <= DW_ATE_hi_user)
666560484Sobrien	    printf ("(user defined type)");
666660484Sobrien	  else
666760484Sobrien	    printf ("(unknown type)");
666860484Sobrien	  break;
666960484Sobrien	}
667060484Sobrien      break;
667160484Sobrien
667260484Sobrien    case DW_AT_accessibility:
667360484Sobrien      switch (uvalue)
667460484Sobrien	{
667560484Sobrien	case DW_ACCESS_public:		printf ("(public)"); break;
667660484Sobrien	case DW_ACCESS_protected:	printf ("(protected)"); break;
667760484Sobrien	case DW_ACCESS_private:		printf ("(private)"); break;
667860484Sobrien	default:		        printf ("(unknown accessibility)"); break;
667960484Sobrien	}
668060484Sobrien      break;
668160484Sobrien
668260484Sobrien    case DW_AT_visibility:
668360484Sobrien      switch (uvalue)
668460484Sobrien	{
668560484Sobrien	case DW_VIS_local:	printf ("(local)"); break;
668660484Sobrien	case DW_VIS_exported:	printf ("(exported)"); break;
668760484Sobrien	case DW_VIS_qualified:	printf ("(qualified)"); break;
668860484Sobrien	default:		printf ("(unknown visibility)"); break;
668960484Sobrien	}
669060484Sobrien      break;
669160484Sobrien
669260484Sobrien    case DW_AT_virtuality:
669360484Sobrien      switch (uvalue)
669460484Sobrien	{
669560484Sobrien	case DW_VIRTUALITY_none:	printf ("(none)"); break;
669660484Sobrien	case DW_VIRTUALITY_virtual:	printf ("(virtual)"); break;
669760484Sobrien	case DW_VIRTUALITY_pure_virtual:printf ("(pure_virtual)"); break;
669860484Sobrien	default:		        printf ("(unknown virtuality)"); break;
669960484Sobrien	}
670060484Sobrien      break;
670160484Sobrien
670260484Sobrien    case DW_AT_identifier_case:
670360484Sobrien      switch (uvalue)
670460484Sobrien	{
670560484Sobrien	case DW_ID_case_sensitive:	printf ("(case_sensitive)"); break;
670660484Sobrien	case DW_ID_up_case:		printf ("(up_case)"); break;
670760484Sobrien	case DW_ID_down_case:		printf ("(down_case)"); break;
670860484Sobrien	case DW_ID_case_insensitive:	printf ("(case_insensitive)"); break;
670960484Sobrien	default:		        printf ("(unknown case)"); break;
671060484Sobrien	}
671160484Sobrien      break;
671260484Sobrien
671360484Sobrien    case DW_AT_calling_convention:
671460484Sobrien      switch (uvalue)
671560484Sobrien	{
671660484Sobrien	case DW_CC_normal:	printf ("(normal)"); break;
671760484Sobrien	case DW_CC_program:	printf ("(program)"); break;
671860484Sobrien	case DW_CC_nocall:	printf ("(nocall)"); break;
671960484Sobrien	default:
672060484Sobrien	  if (uvalue >= DW_CC_lo_user
672160484Sobrien	      && uvalue <= DW_CC_hi_user)
672260484Sobrien	    printf ("(user defined)");
672360484Sobrien	  else
672460484Sobrien	    printf ("(unknown convention)");
672560484Sobrien	}
672660484Sobrien      break;
672760484Sobrien
672877298Sobrien    case DW_AT_frame_base:
672960484Sobrien    case DW_AT_location:
673060484Sobrien    case DW_AT_data_member_location:
673160484Sobrien    case DW_AT_vtable_elem_location:
673277298Sobrien      if (block_start)
673377298Sobrien	{
673477298Sobrien	  printf ("(");
673577298Sobrien	  decode_location_expression (block_start, pointer_size, uvalue);
673677298Sobrien	  printf (")");
673777298Sobrien	}
673860484Sobrien      break;
673960484Sobrien
674060484Sobrien    default:
674160484Sobrien      break;
674260484Sobrien    }
674360484Sobrien
674460484Sobrien  printf ("\n");
674560484Sobrien  return data;
674660484Sobrien}
674760484Sobrien
674860484Sobrienstatic int
674960484Sobriendisplay_debug_info (section, start, file)
675060484Sobrien     Elf32_Internal_Shdr * section;
675160484Sobrien     unsigned char *       start;
675260484Sobrien     FILE *                file;
675360484Sobrien{
675460484Sobrien  unsigned char * end = start + section->sh_size;
675560484Sobrien  unsigned char * section_begin = start;
675660484Sobrien
675760484Sobrien  printf (_("The section %s contains:\n\n"), SECTION_NAME (section));
675860484Sobrien
675960484Sobrien  while (start < end)
676060484Sobrien    {
676160484Sobrien      DWARF2_External_CompUnit * external;
676260484Sobrien      DWARF2_Internal_CompUnit   compunit;
676360484Sobrien      unsigned char *            tags;
676460484Sobrien      int                        i;
676560484Sobrien      int			 level;
676677298Sobrien      unsigned long		 cu_offset;
676760484Sobrien
676860484Sobrien      external = (DWARF2_External_CompUnit *) start;
676960484Sobrien
677060484Sobrien      compunit.cu_length        = BYTE_GET (external->cu_length);
677160484Sobrien      compunit.cu_version       = BYTE_GET (external->cu_version);
677260484Sobrien      compunit.cu_abbrev_offset = BYTE_GET (external->cu_abbrev_offset);
677360484Sobrien      compunit.cu_pointer_size  = BYTE_GET (external->cu_pointer_size);
677460484Sobrien
677560484Sobrien      tags = start + sizeof (* external);
677677298Sobrien      cu_offset = start - section_begin;
677760484Sobrien      start += compunit.cu_length + sizeof (external->cu_length);
677860484Sobrien
677977298Sobrien      printf (_("  Compilation Unit @ %lx:\n"), cu_offset);
678077298Sobrien      printf (_("   Length:        %ld\n"), compunit.cu_length);
678177298Sobrien      printf (_("   Version:       %d\n"), compunit.cu_version);
678277298Sobrien      printf (_("   Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset);
678377298Sobrien      printf (_("   Pointer Size:  %d\n"), compunit.cu_pointer_size);
678477298Sobrien
678560484Sobrien      if (compunit.cu_version != 2)
678660484Sobrien	{
678760484Sobrien	  warn (_("Only version 2 DWARF debug information is currently supported.\n"));
678860484Sobrien	  continue;
678960484Sobrien	}
679060484Sobrien
679160484Sobrien      if (first_abbrev != NULL)
679260484Sobrien	free_abbrevs ();
679360484Sobrien
679460484Sobrien      /* Read in the abbrevs used by this compilation unit.  */
679560484Sobrien
679660484Sobrien      {
679760484Sobrien	Elf32_Internal_Shdr * sec;
679860484Sobrien	unsigned char *       begin;
679960484Sobrien
680060484Sobrien	/* Locate the .debug_abbrev section and process it.  */
680160484Sobrien	for (i = 0, sec = section_headers;
680260484Sobrien	     i < elf_header.e_shnum;
680360484Sobrien	     i ++, sec ++)
680460484Sobrien	  if (strcmp (SECTION_NAME (sec), ".debug_abbrev") == 0)
680560484Sobrien	    break;
680660484Sobrien
680760484Sobrien	if (i == -1 || sec->sh_size == 0)
680860484Sobrien	  {
680960484Sobrien	    warn (_("Unable to locate .debug_abbrev section!\n"));
681060484Sobrien	    return 0;
681160484Sobrien	  }
681260484Sobrien
681360484Sobrien	GET_DATA_ALLOC (sec->sh_offset, sec->sh_size, begin, unsigned char *,
681460484Sobrien			"debug_abbrev section data");
681560484Sobrien
681660484Sobrien	process_abbrev_section (begin + compunit.cu_abbrev_offset,
681760484Sobrien				begin + sec->sh_size);
681860484Sobrien
681960484Sobrien	free (begin);
682060484Sobrien      }
682160484Sobrien
682260484Sobrien      level = 0;
682360484Sobrien      while (tags < start)
682460484Sobrien	{
682560484Sobrien	  int            bytes_read;
682660484Sobrien	  unsigned long  abbrev_number;
682760484Sobrien	  abbrev_entry * entry;
682860484Sobrien	  abbrev_attr  * attr;
682960484Sobrien
683060484Sobrien	  abbrev_number = read_leb128 (tags, & bytes_read, 0);
683160484Sobrien	  tags += bytes_read;
683260484Sobrien
683360484Sobrien	  /* A null DIE marks the end of a list of children.  */
683460484Sobrien	  if (abbrev_number == 0)
683560484Sobrien	    {
683660484Sobrien	      --level;
683760484Sobrien	      continue;
683860484Sobrien	    }
683960484Sobrien
684060484Sobrien	  /* Scan through the abbreviation list until we reach the
684160484Sobrien	     correct entry.  */
684260484Sobrien	  for (entry = first_abbrev;
684360484Sobrien	       entry && entry->entry != abbrev_number;
684460484Sobrien	       entry = entry->next)
684560484Sobrien	    continue;
684660484Sobrien
684760484Sobrien	  if (entry == NULL)
684860484Sobrien	    {
684960484Sobrien	      warn (_("Unable to locate entry %lu in the abbreviation table\n"),
685060484Sobrien		    abbrev_number);
685160484Sobrien	      return 0;
685260484Sobrien	    }
685360484Sobrien
685460484Sobrien	  printf (_(" <%d><%x>: Abbrev Number: %lu (%s)\n"),
685560484Sobrien		  level, tags - section_begin - bytes_read,
685660484Sobrien		  abbrev_number,
685760484Sobrien		  get_TAG_name (entry->tag));
685860484Sobrien
685960484Sobrien	  for (attr = entry->first_attr; attr; attr = attr->next)
686060484Sobrien	    tags = read_and_display_attr (attr->attribute,
686160484Sobrien					  attr->form,
686277298Sobrien					  tags, cu_offset,
686360484Sobrien					  compunit.cu_pointer_size);
686460484Sobrien
686560484Sobrien	  if (entry->children)
686660484Sobrien	    ++level;
686760484Sobrien	}
686860484Sobrien    }
686960484Sobrien
687060484Sobrien  printf ("\n");
687160484Sobrien
687260484Sobrien  return 1;
687360484Sobrien}
687460484Sobrien
687560484Sobrienstatic int
687660484Sobriendisplay_debug_aranges (section, start, file)
687760484Sobrien     Elf32_Internal_Shdr * section;
687860484Sobrien     unsigned char *       start;
687960484Sobrien     FILE *                file ATTRIBUTE_UNUSED;
688060484Sobrien{
688160484Sobrien  unsigned char * end = start + section->sh_size;
688260484Sobrien
688360484Sobrien  printf (_("The section %s contains:\n\n"), SECTION_NAME (section));
688460484Sobrien
688560484Sobrien  while (start < end)
688660484Sobrien    {
688760484Sobrien      DWARF2_External_ARange * external;
688860484Sobrien      DWARF2_Internal_ARange   arange;
688960484Sobrien      unsigned char *          ranges;
689060484Sobrien      unsigned long            length;
689160484Sobrien      unsigned long            address;
689260484Sobrien      int		       excess;
689360484Sobrien
689460484Sobrien      external = (DWARF2_External_ARange *) start;
689560484Sobrien
689660484Sobrien      arange.ar_length       = BYTE_GET (external->ar_length);
689760484Sobrien      arange.ar_version      = BYTE_GET (external->ar_version);
689860484Sobrien      arange.ar_info_offset  = BYTE_GET (external->ar_info_offset);
689960484Sobrien      arange.ar_pointer_size = BYTE_GET (external->ar_pointer_size);
690060484Sobrien      arange.ar_segment_size = BYTE_GET (external->ar_segment_size);
690160484Sobrien
690268765Sobrien      if (arange.ar_version != 2)
690368765Sobrien	{
690468765Sobrien	  warn (_("Only DWARF 2 aranges are currently supported.\n"));
690568765Sobrien	  break;
690668765Sobrien	}
690768765Sobrien
690860484Sobrien      printf (_("  Length:                   %ld\n"), arange.ar_length);
690960484Sobrien      printf (_("  Version:                  %d\n"), arange.ar_version);
691060484Sobrien      printf (_("  Offset into .debug_info:  %lx\n"), arange.ar_info_offset);
691160484Sobrien      printf (_("  Pointer Size:             %d\n"), arange.ar_pointer_size);
691260484Sobrien      printf (_("  Segment Size:             %d\n"), arange.ar_segment_size);
691360484Sobrien
691460484Sobrien      printf (_("\n    Address  Length\n"));
691560484Sobrien
691660484Sobrien      ranges = start + sizeof (* external);
691760484Sobrien
691860484Sobrien      /* Must pad to an alignment boundary that is twice the pointer size.  */
691977298Sobrien      excess = sizeof (* external) % (2 * arange.ar_pointer_size);
692060484Sobrien      if (excess)
692160484Sobrien	ranges += (2 * arange.ar_pointer_size) - excess;
692260484Sobrien
692360484Sobrien      for (;;)
692460484Sobrien	{
692560484Sobrien	  address = byte_get (ranges, arange.ar_pointer_size);
692660484Sobrien
692760484Sobrien	  ranges += arange.ar_pointer_size;
692860484Sobrien
692960484Sobrien	  length  = byte_get (ranges, arange.ar_pointer_size);
693060484Sobrien
693160484Sobrien	  ranges += arange.ar_pointer_size;
693260484Sobrien
693360484Sobrien	  /* A pair of zeros marks the end of the list.  */
693460484Sobrien	  if (address == 0 && length == 0)
693560484Sobrien	    break;
693660484Sobrien
693760484Sobrien	  printf ("    %8.8lx %lu\n", address, length);
693860484Sobrien	}
693960484Sobrien
694060484Sobrien      start += arange.ar_length + sizeof (external->ar_length);
694160484Sobrien    }
694260484Sobrien
694360484Sobrien  printf ("\n");
694460484Sobrien
694560484Sobrien  return 1;
694660484Sobrien}
694760484Sobrien
694877298Sobrientypedef struct Frame_Chunk
694977298Sobrien{
695077298Sobrien  struct Frame_Chunk * next;
695177298Sobrien  unsigned char *      chunk_start;
695277298Sobrien  int                  ncols;
695377298Sobrien  /* DW_CFA_{undefined,same_value,offset,register,unreferenced}  */
695477298Sobrien  short int *          col_type;
695577298Sobrien  int *                col_offset;
695677298Sobrien  char *               augmentation;
695777298Sobrien  unsigned int         code_factor;
695878828Sobrien  int                  data_factor;
695977298Sobrien  unsigned long        pc_begin;
696077298Sobrien  unsigned long        pc_range;
696177298Sobrien  int                  cfa_reg;
696277298Sobrien  int                  cfa_offset;
696377298Sobrien  int                  ra;
696478828Sobrien  unsigned char        fde_encoding;
696577298Sobrien}
696677298SobrienFrame_Chunk;
696760484Sobrien
696877298Sobrien/* A marker for a col_type that means this column was never referenced
696977298Sobrien   in the frame info.  */
697077298Sobrien#define DW_CFA_unreferenced (-1)
697177298Sobrien
697277298Sobrienstatic void
697377298Sobrienframe_need_space (fc, reg)
697477298Sobrien     Frame_Chunk * fc;
697577298Sobrien     int reg;
697677298Sobrien{
697777298Sobrien  int prev = fc->ncols;
697877298Sobrien
697977298Sobrien  if (reg < fc->ncols)
698077298Sobrien    return;
698177298Sobrien
698277298Sobrien  fc->ncols = reg + 1;
698377298Sobrien  fc->col_type = (short int *) xrealloc (fc->col_type,
698477298Sobrien					 fc->ncols * sizeof (short int));
698577298Sobrien  fc->col_offset = (int *) xrealloc (fc->col_offset,
698677298Sobrien				     fc->ncols * sizeof (int));
698777298Sobrien
698877298Sobrien  while (prev < fc->ncols)
698977298Sobrien    {
699077298Sobrien      fc->col_type[prev] = DW_CFA_unreferenced;
699177298Sobrien      fc->col_offset[prev] = 0;
699277298Sobrien      prev++;
699377298Sobrien    }
699477298Sobrien}
699577298Sobrien
699677298Sobrienstatic void
699777298Sobrienframe_display_row (fc, need_col_headers, max_regs)
699877298Sobrien     Frame_Chunk * fc;
699977298Sobrien     int *         need_col_headers;
700077298Sobrien     int *         max_regs;
700177298Sobrien{
700277298Sobrien  int r;
700377298Sobrien  char tmp[100];
700477298Sobrien
700577298Sobrien  if (* max_regs < fc->ncols)
700677298Sobrien    * max_regs = fc->ncols;
700777298Sobrien
700877298Sobrien  if (* need_col_headers)
700977298Sobrien    {
701077298Sobrien      * need_col_headers = 0;
701177298Sobrien
701277298Sobrien      printf ("   LOC   CFA      ");
701377298Sobrien
701477298Sobrien      for (r = 0; r < * max_regs; r++)
701577298Sobrien	if (fc->col_type[r] != DW_CFA_unreferenced)
701677298Sobrien	  {
701777298Sobrien	    if (r == fc->ra)
701877298Sobrien	      printf ("ra   ");
701977298Sobrien	    else
702077298Sobrien	      printf ("r%-4d", r);
702177298Sobrien	  }
702277298Sobrien
702377298Sobrien      printf ("\n");
702477298Sobrien    }
702577298Sobrien
702678828Sobrien  printf ("%08lx ", fc->pc_begin);
702777298Sobrien  sprintf (tmp, "r%d%+d", fc->cfa_reg, fc->cfa_offset);
702877298Sobrien  printf ("%-8s ", tmp);
702977298Sobrien
703077298Sobrien  for (r = 0; r < fc->ncols; r++)
703177298Sobrien    {
703277298Sobrien      if (fc->col_type[r] != DW_CFA_unreferenced)
703377298Sobrien	{
703477298Sobrien	  switch (fc->col_type[r])
703577298Sobrien	    {
703677298Sobrien	    case DW_CFA_undefined:
703777298Sobrien	      strcpy (tmp, "u");
703877298Sobrien	      break;
703977298Sobrien	    case DW_CFA_same_value:
704077298Sobrien	      strcpy (tmp, "s");
704177298Sobrien	      break;
704277298Sobrien	    case DW_CFA_offset:
704377298Sobrien	      sprintf (tmp, "c%+d", fc->col_offset[r]);
704477298Sobrien	      break;
704577298Sobrien	    case DW_CFA_register:
704677298Sobrien	      sprintf (tmp, "r%d", fc->col_offset[r]);
704777298Sobrien	      break;
704877298Sobrien	    default:
704977298Sobrien	      strcpy (tmp, "n/a");
705077298Sobrien	      break;
705177298Sobrien	    }
705277298Sobrien	  printf ("%-5s", tmp);
705377298Sobrien	}
705477298Sobrien    }
705577298Sobrien  printf ("\n");
705677298Sobrien}
705777298Sobrien
705878828Sobrienstatic int
705978828Sobriensize_of_encoded_value (encoding)
706078828Sobrien     int encoding;
706178828Sobrien{
706278828Sobrien  switch (encoding & 0x7)
706378828Sobrien    {
706478828Sobrien    default:	/* ??? */
706578828Sobrien    case 0:	return is_32bit_elf ? 4 : 8;
706678828Sobrien    case 2:	return 2;
706778828Sobrien    case 3:	return 4;
706878828Sobrien    case 4:	return 8;
706978828Sobrien    }
707078828Sobrien}
707178828Sobrien
707277298Sobrien#define GET(N)	byte_get (start, N); start += N
707377298Sobrien#define LEB()	read_leb128 (start, & length_return, 0); start += length_return
707477298Sobrien#define SLEB()	read_leb128 (start, & length_return, 1); start += length_return
707577298Sobrien
707660484Sobrienstatic int
707777298Sobriendisplay_debug_frames (section, start, file)
707877298Sobrien     Elf32_Internal_Shdr * section;
707977298Sobrien     unsigned char *       start;
708077298Sobrien     FILE *                file ATTRIBUTE_UNUSED;
708177298Sobrien{
708277298Sobrien  unsigned char * end = start + section->sh_size;
708377298Sobrien  unsigned char * section_start = start;
708477298Sobrien  Frame_Chunk *   chunks = 0;
708577298Sobrien  Frame_Chunk *   remembered_state = 0;
708677298Sobrien  Frame_Chunk *   rs;
708777298Sobrien  int             is_eh = (strcmp (SECTION_NAME (section), ".eh_frame") == 0);
708877298Sobrien  int             length_return;
708977298Sobrien  int             max_regs = 0;
709078828Sobrien  int             addr_size = is_32bit_elf ? 4 : 8;
709177298Sobrien
709277298Sobrien  printf (_("The section %s contains:\n"), SECTION_NAME (section));
709377298Sobrien
709477298Sobrien  while (start < end)
709577298Sobrien    {
709677298Sobrien      unsigned char * saved_start;
709777298Sobrien      unsigned char * block_end;
709877298Sobrien      unsigned long   length;
709977298Sobrien      unsigned long   cie_id;
710077298Sobrien      Frame_Chunk *   fc;
710177298Sobrien      Frame_Chunk *   cie;
710277298Sobrien      int             need_col_headers = 1;
710378828Sobrien      unsigned char * augmentation_data = NULL;
710478828Sobrien      unsigned long   augmentation_data_len = 0;
710578828Sobrien      int	      encoded_ptr_size = addr_size;
710677298Sobrien
710777298Sobrien      saved_start = start;
710877298Sobrien      length = byte_get (start, 4); start += 4;
710977298Sobrien
711077298Sobrien      if (length == 0)
711177298Sobrien	return 1;
711277298Sobrien
711377298Sobrien      block_end = saved_start + length + 4;
711477298Sobrien      cie_id = byte_get (start, 4); start += 4;
711577298Sobrien
711677298Sobrien      if (is_eh ? (cie_id == 0) : (cie_id == DW_CIE_ID))
711777298Sobrien	{
711878828Sobrien	  int version;
711978828Sobrien
712077298Sobrien	  fc = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk));
712177298Sobrien	  memset (fc, 0, sizeof (Frame_Chunk));
712277298Sobrien
712377298Sobrien	  fc->next = chunks;
712477298Sobrien	  chunks = fc;
712577298Sobrien	  fc->chunk_start = saved_start;
712677298Sobrien	  fc->ncols = 0;
712777298Sobrien	  fc->col_type = (short int *) xmalloc (sizeof (short int));
712877298Sobrien	  fc->col_offset = (int *) xmalloc (sizeof (int));
712977298Sobrien	  frame_need_space (fc, max_regs-1);
713077298Sobrien
713178828Sobrien	  version = *start++;
713278828Sobrien
713377298Sobrien	  fc->augmentation = start;
713478828Sobrien	  start = strchr (start, '\0') + 1;
713577298Sobrien
713677298Sobrien	  if (fc->augmentation[0] == 'z')
713777298Sobrien	    {
713877298Sobrien	      fc->code_factor = LEB ();
713977298Sobrien	      fc->data_factor = SLEB ();
714077298Sobrien	      fc->ra = byte_get (start, 1); start += 1;
714178828Sobrien	      augmentation_data_len = LEB ();
714278828Sobrien	      augmentation_data = start;
714378828Sobrien	      start += augmentation_data_len;
714477298Sobrien	    }
714577298Sobrien	  else if (strcmp (fc->augmentation, "eh") == 0)
714677298Sobrien	    {
714778828Sobrien	      start += addr_size;
714877298Sobrien	      fc->code_factor = LEB ();
714977298Sobrien	      fc->data_factor = SLEB ();
715077298Sobrien	      fc->ra = byte_get (start, 1); start += 1;
715177298Sobrien	    }
715277298Sobrien	  else
715377298Sobrien	    {
715477298Sobrien	      fc->code_factor = LEB ();
715577298Sobrien	      fc->data_factor = SLEB ();
715677298Sobrien	      fc->ra = byte_get (start, 1); start += 1;
715777298Sobrien	    }
715877298Sobrien	  cie = fc;
715977298Sobrien
716078828Sobrien	  if (do_debug_frames_interp)
716178828Sobrien	    printf ("\n%08lx %08lx %08lx CIE \"%s\" cf=%d df=%d ra=%d\n",
716278828Sobrien		    (unsigned long)(saved_start - section_start), length, cie_id,
716378828Sobrien		    fc->augmentation, fc->code_factor, fc->data_factor,
716478828Sobrien		    fc->ra);
716578828Sobrien	  else
716678828Sobrien	    {
716778828Sobrien	      printf ("\n%08lx %08lx %08lx CIE\n",
716878828Sobrien		      (unsigned long)(saved_start - section_start), length, cie_id);
716978828Sobrien	      printf ("  Version:               %d\n", version);
717078828Sobrien	      printf ("  Augmentation:          \"%s\"\n", fc->augmentation);
717178828Sobrien	      printf ("  Code alignment factor: %u\n", fc->code_factor);
717278828Sobrien	      printf ("  Data alignment factor: %d\n", fc->data_factor);
717378828Sobrien	      printf ("  Return address column: %d\n", fc->ra);
717478828Sobrien
717578828Sobrien	      if (augmentation_data_len)
717678828Sobrien		{
717778828Sobrien		  unsigned long i;
717878828Sobrien		  printf ("  Augmentation data:    ");
717978828Sobrien		  for (i = 0; i < augmentation_data_len; ++i)
718078828Sobrien		    printf (" %02x", augmentation_data[i]);
718178828Sobrien		  putchar ('\n');
718278828Sobrien		}
718378828Sobrien	      putchar ('\n');
718478828Sobrien	    }
718578828Sobrien
718678828Sobrien	  if (augmentation_data_len)
718778828Sobrien	    {
718878828Sobrien	      unsigned char *p, *q;
718978828Sobrien	      p = fc->augmentation + 1;
719078828Sobrien	      q = augmentation_data;
719178828Sobrien
719278828Sobrien	      while (1)
719378828Sobrien		{
719478828Sobrien		  if (*p == 'L')
719578828Sobrien		    q++;
719678828Sobrien		  else if (*p == 'P')
719778828Sobrien		    q += 1 + size_of_encoded_value (*q);
719878828Sobrien		  else if (*p == 'R')
719978828Sobrien		    fc->fde_encoding = *q++;
720078828Sobrien		  else
720178828Sobrien		    break;
720278828Sobrien		  p++;
720378828Sobrien		}
720478828Sobrien
720578828Sobrien	      if (fc->fde_encoding)
720678828Sobrien		encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
720778828Sobrien	    }
720878828Sobrien
720977298Sobrien	  frame_need_space (fc, fc->ra);
721077298Sobrien	}
721177298Sobrien      else
721277298Sobrien	{
721377298Sobrien	  unsigned char *    look_for;
721477298Sobrien	  static Frame_Chunk fde_fc;
721577298Sobrien
721677298Sobrien	  fc = & fde_fc;
721777298Sobrien	  memset (fc, 0, sizeof (Frame_Chunk));
721877298Sobrien
721978828Sobrien	  look_for = is_eh ? start - 4 - cie_id : section_start + cie_id;
722077298Sobrien
722178828Sobrien	  for (cie=chunks; cie ; cie = cie->next)
722278828Sobrien	    if (cie->chunk_start == look_for)
722378828Sobrien	      break;
722477298Sobrien
722577298Sobrien	  if (!cie)
722677298Sobrien	    {
722778828Sobrien	      warn ("Invalid CIE pointer %08lx in FDE at %08lx\n",
722878828Sobrien		    cie_id, saved_start);
722977298Sobrien	      start = block_end;
723077298Sobrien	      fc->ncols = 0;
723177298Sobrien	      fc->col_type = (short int *) xmalloc (sizeof (short int));
723277298Sobrien	      fc->col_offset = (int *) xmalloc (sizeof (int));
723377298Sobrien	      frame_need_space (fc, max_regs - 1);
723477298Sobrien	      cie = fc;
723577298Sobrien	      fc->augmentation = "";
723678828Sobrien	      fc->fde_encoding = 0;
723777298Sobrien	    }
723877298Sobrien	  else
723977298Sobrien	    {
724077298Sobrien	      fc->ncols = cie->ncols;
724177298Sobrien	      fc->col_type = (short int *) xmalloc (fc->ncols * sizeof (short int));
724277298Sobrien	      fc->col_offset = (int *) xmalloc (fc->ncols * sizeof (int));
724377298Sobrien	      memcpy (fc->col_type, cie->col_type, fc->ncols * sizeof (short int));
724477298Sobrien	      memcpy (fc->col_offset, cie->col_offset, fc->ncols * sizeof (int));
724577298Sobrien	      fc->augmentation = cie->augmentation;
724677298Sobrien	      fc->code_factor = cie->code_factor;
724777298Sobrien	      fc->data_factor = cie->data_factor;
724877298Sobrien	      fc->cfa_reg = cie->cfa_reg;
724977298Sobrien	      fc->cfa_offset = cie->cfa_offset;
725077298Sobrien	      fc->ra = cie->ra;
725177298Sobrien	      frame_need_space (fc, max_regs-1);
725278828Sobrien	      fc->fde_encoding = cie->fde_encoding;
725377298Sobrien	    }
725477298Sobrien
725578828Sobrien	  if (fc->fde_encoding)
725678828Sobrien	    encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
725778828Sobrien
725878828Sobrien	  fc->pc_begin = byte_get (start, encoded_ptr_size);
725978828Sobrien	  start += encoded_ptr_size;
726078828Sobrien	  fc->pc_range = byte_get (start, encoded_ptr_size);
726178828Sobrien	  start += encoded_ptr_size;
726278828Sobrien
726377298Sobrien	  if (cie->augmentation[0] == 'z')
726477298Sobrien	    {
726578828Sobrien	      augmentation_data_len = LEB ();
726678828Sobrien	      augmentation_data = start;
726778828Sobrien	      start += augmentation_data_len;
726877298Sobrien	    }
726977298Sobrien
727078828Sobrien	  printf ("\n%08lx %08lx %08lx FDE cie=%08x pc=%08lx..%08lx\n",
727178828Sobrien		  (unsigned long)(saved_start - section_start), length, cie_id,
727278828Sobrien		  cie->chunk_start - section_start, fc->pc_begin,
727377298Sobrien		  fc->pc_begin + fc->pc_range);
727478828Sobrien	  if (! do_debug_frames_interp && augmentation_data_len)
727578828Sobrien	    {
727678828Sobrien	      unsigned long i;
727778828Sobrien	      printf ("  Augmentation data:    ");
727878828Sobrien	      for (i = 0; i < augmentation_data_len; ++i)
727978828Sobrien	        printf (" %02x", augmentation_data[i]);
728078828Sobrien	      putchar ('\n');
728178828Sobrien	      putchar ('\n');
728278828Sobrien	    }
728377298Sobrien	}
728477298Sobrien
728577298Sobrien      /* At this point, fc is the current chunk, cie (if any) is set, and we're
728677298Sobrien	 about to interpret instructions for the chunk.  */
728777298Sobrien
728878828Sobrien      if (do_debug_frames_interp)
728977298Sobrien      {
729077298Sobrien	/* Start by making a pass over the chunk, allocating storage
729177298Sobrien           and taking note of what registers are used.  */
729277298Sobrien	unsigned char * tmp = start;
729377298Sobrien
729477298Sobrien	while (start < block_end)
729577298Sobrien	  {
729677298Sobrien	    unsigned op, opa;
729777298Sobrien	    unsigned long reg;
729878828Sobrien
729977298Sobrien	    op = * start ++;
730077298Sobrien	    opa = op & 0x3f;
730177298Sobrien	    if (op & 0xc0)
730277298Sobrien	      op &= 0xc0;
730378828Sobrien
730477298Sobrien	    /* Warning: if you add any more cases to this switch, be
730577298Sobrien	       sure to add them to the corresponding switch below.  */
730677298Sobrien	    switch (op)
730777298Sobrien	      {
730877298Sobrien	      case DW_CFA_advance_loc:
730977298Sobrien		break;
731077298Sobrien	      case DW_CFA_offset:
731177298Sobrien		LEB ();
731277298Sobrien		frame_need_space (fc, opa);
731377298Sobrien		fc->col_type[opa] = DW_CFA_undefined;
731477298Sobrien		break;
731577298Sobrien	      case DW_CFA_restore:
731677298Sobrien		frame_need_space (fc, opa);
731777298Sobrien		fc->col_type[opa] = DW_CFA_undefined;
731877298Sobrien		break;
731977298Sobrien	      case DW_CFA_set_loc:
732078828Sobrien		start += encoded_ptr_size;
732177298Sobrien		break;
732277298Sobrien	      case DW_CFA_advance_loc1:
732377298Sobrien		start += 1;
732477298Sobrien		break;
732577298Sobrien	      case DW_CFA_advance_loc2:
732677298Sobrien		start += 2;
732777298Sobrien		break;
732877298Sobrien	      case DW_CFA_advance_loc4:
732977298Sobrien		start += 4;
733077298Sobrien		break;
733177298Sobrien	      case DW_CFA_offset_extended:
733277298Sobrien		reg = LEB (); LEB ();
733377298Sobrien		frame_need_space (fc, reg);
733477298Sobrien		fc->col_type[reg] = DW_CFA_undefined;
733577298Sobrien		break;
733677298Sobrien	      case DW_CFA_restore_extended:
733777298Sobrien		reg = LEB ();
733877298Sobrien		frame_need_space (fc, reg);
733977298Sobrien		fc->col_type[reg] = DW_CFA_undefined;
734077298Sobrien		break;
734177298Sobrien	      case DW_CFA_undefined:
734277298Sobrien		reg = LEB ();
734377298Sobrien		frame_need_space (fc, reg);
734477298Sobrien		fc->col_type[reg] = DW_CFA_undefined;
734577298Sobrien		break;
734677298Sobrien	      case DW_CFA_same_value:
734777298Sobrien		reg = LEB ();
734877298Sobrien		frame_need_space (fc, reg);
734977298Sobrien		fc->col_type[reg] = DW_CFA_undefined;
735077298Sobrien		break;
735177298Sobrien	      case DW_CFA_register:
735277298Sobrien		reg = LEB (); LEB ();
735377298Sobrien		frame_need_space (fc, reg);
735477298Sobrien		fc->col_type[reg] = DW_CFA_undefined;
735577298Sobrien		break;
735677298Sobrien	      case DW_CFA_def_cfa:
735777298Sobrien		LEB (); LEB ();
735877298Sobrien		break;
735977298Sobrien	      case DW_CFA_def_cfa_register:
736077298Sobrien		LEB ();
736177298Sobrien		break;
736277298Sobrien	      case DW_CFA_def_cfa_offset:
736377298Sobrien		LEB ();
736477298Sobrien		break;
736577298Sobrien#ifndef DW_CFA_GNU_args_size
736677298Sobrien#define DW_CFA_GNU_args_size 0x2e
736777298Sobrien#endif
736877298Sobrien	      case DW_CFA_GNU_args_size:
736977298Sobrien		LEB ();
737078828Sobrien		break;
737177298Sobrien#ifndef DW_CFA_GNU_negative_offset_extended
737277298Sobrien#define DW_CFA_GNU_negative_offset_extended 0x2f
737377298Sobrien#endif
737477298Sobrien	      case DW_CFA_GNU_negative_offset_extended:
737578828Sobrien		reg = LEB (); LEB ();
737677298Sobrien		frame_need_space (fc, reg);
737777298Sobrien		fc->col_type[reg] = DW_CFA_undefined;
737878828Sobrien
737977298Sobrien	      default:
738077298Sobrien		break;
738177298Sobrien	      }
738277298Sobrien	  }
738377298Sobrien	start = tmp;
738477298Sobrien      }
738577298Sobrien
738677298Sobrien      /* Now we know what registers are used, make a second pass over
738777298Sobrien         the chunk, this time actually printing out the info.  */
738877298Sobrien
738977298Sobrien      while (start < block_end)
739077298Sobrien	{
739177298Sobrien	  unsigned op, opa;
739277298Sobrien	  unsigned long ul, reg, roffs;
739377298Sobrien	  long l, ofs;
739477298Sobrien	  bfd_vma vma;
739577298Sobrien
739677298Sobrien	  op = * start ++;
739777298Sobrien	  opa = op & 0x3f;
739877298Sobrien	  if (op & 0xc0)
739977298Sobrien	    op &= 0xc0;
740077298Sobrien
740177298Sobrien	    /* Warning: if you add any more cases to this switch, be
740277298Sobrien	       sure to add them to the corresponding switch above.  */
740377298Sobrien	  switch (op)
740477298Sobrien	    {
740577298Sobrien	    case DW_CFA_advance_loc:
740678828Sobrien	      if (do_debug_frames_interp)
740778828Sobrien	        frame_display_row (fc, &need_col_headers, &max_regs);
740878828Sobrien	      else
740978828Sobrien	        printf ("  DW_CFA_advance_loc: %d to %08lx\n",
741078828Sobrien		        opa * fc->code_factor,
741178828Sobrien			fc->pc_begin + opa * fc->code_factor);
741277298Sobrien	      fc->pc_begin += opa * fc->code_factor;
741377298Sobrien	      break;
741477298Sobrien
741577298Sobrien	    case DW_CFA_offset:
741677298Sobrien	      roffs = LEB ();
741778828Sobrien	      if (! do_debug_frames_interp)
741878828Sobrien	        printf ("  DW_CFA_offset: r%d at cfa%+ld\n",
741978828Sobrien			opa, roffs * fc->data_factor);
742077298Sobrien	      fc->col_type[opa] = DW_CFA_offset;
742177298Sobrien	      fc->col_offset[opa] = roffs * fc->data_factor;
742277298Sobrien	      break;
742377298Sobrien
742477298Sobrien	    case DW_CFA_restore:
742578828Sobrien	      if (! do_debug_frames_interp)
742678828Sobrien	        printf ("  DW_CFA_restore: r%d\n", opa);
742777298Sobrien	      fc->col_type[opa] = cie->col_type[opa];
742877298Sobrien	      fc->col_offset[opa] = cie->col_offset[opa];
742977298Sobrien	      break;
743077298Sobrien
743177298Sobrien	    case DW_CFA_set_loc:
743278828Sobrien	      vma = byte_get (start, encoded_ptr_size);
743378828Sobrien	      start += encoded_ptr_size;
743478828Sobrien	      if (do_debug_frames_interp)
743578828Sobrien	        frame_display_row (fc, &need_col_headers, &max_regs);
743678828Sobrien	      else
743778828Sobrien	        printf ("  DW_CFA_set_loc: %08lx\n", (unsigned long)vma);
743877298Sobrien	      fc->pc_begin = vma;
743977298Sobrien	      break;
744077298Sobrien
744177298Sobrien	    case DW_CFA_advance_loc1:
744277298Sobrien	      ofs = byte_get (start, 1); start += 1;
744378828Sobrien	      if (do_debug_frames_interp)
744478828Sobrien	        frame_display_row (fc, &need_col_headers, &max_regs);
744578828Sobrien	      else
744678828Sobrien	        printf ("  DW_CFA_advance_loc1: %ld to %08lx\n",
744778828Sobrien		        ofs * fc->code_factor,
744878828Sobrien			fc->pc_begin + ofs * fc->code_factor);
744977298Sobrien	      fc->pc_begin += ofs * fc->code_factor;
745077298Sobrien	      break;
745177298Sobrien
745277298Sobrien	    case DW_CFA_advance_loc2:
745377298Sobrien	      ofs = byte_get (start, 2); start += 2;
745478828Sobrien	      if (do_debug_frames_interp)
745578828Sobrien	        frame_display_row (fc, &need_col_headers, &max_regs);
745678828Sobrien	      else
745778828Sobrien	        printf ("  DW_CFA_advance_loc2: %ld to %08lx\n",
745878828Sobrien		        ofs * fc->code_factor,
745978828Sobrien			fc->pc_begin + ofs * fc->code_factor);
746077298Sobrien	      fc->pc_begin += ofs * fc->code_factor;
746177298Sobrien	      break;
746277298Sobrien
746377298Sobrien	    case DW_CFA_advance_loc4:
746477298Sobrien	      ofs = byte_get (start, 4); start += 4;
746578828Sobrien	      if (do_debug_frames_interp)
746678828Sobrien	        frame_display_row (fc, &need_col_headers, &max_regs);
746778828Sobrien	      else
746878828Sobrien	        printf ("  DW_CFA_advance_loc4: %ld to %08lx\n",
746978828Sobrien		        ofs * fc->code_factor,
747078828Sobrien			fc->pc_begin + ofs * fc->code_factor);
747177298Sobrien	      fc->pc_begin += ofs * fc->code_factor;
747277298Sobrien	      break;
747377298Sobrien
747477298Sobrien	    case DW_CFA_offset_extended:
747577298Sobrien	      reg = LEB ();
747677298Sobrien	      roffs = LEB ();
747778828Sobrien	      if (! do_debug_frames_interp)
747878828Sobrien		printf ("  DW_CFA_offset_extended: r%ld at cfa%+ld\n",
747978828Sobrien			reg, roffs * fc->data_factor);
748077298Sobrien	      fc->col_type[reg] = DW_CFA_offset;
748177298Sobrien	      fc->col_offset[reg] = roffs * fc->data_factor;
748277298Sobrien	      break;
748377298Sobrien
748477298Sobrien	    case DW_CFA_restore_extended:
748577298Sobrien	      reg = LEB ();
748678828Sobrien	      if (! do_debug_frames_interp)
748778828Sobrien	        printf ("  DW_CFA_restore_extended: r%ld\n", reg);
748877298Sobrien	      fc->col_type[reg] = cie->col_type[reg];
748977298Sobrien	      fc->col_offset[reg] = cie->col_offset[reg];
749077298Sobrien	      break;
749177298Sobrien
749277298Sobrien	    case DW_CFA_undefined:
749377298Sobrien	      reg = LEB ();
749478828Sobrien	      if (! do_debug_frames_interp)
749578828Sobrien	        printf ("  DW_CFA_undefined: r%ld\n", reg);
749677298Sobrien	      fc->col_type[reg] = DW_CFA_undefined;
749777298Sobrien	      fc->col_offset[reg] = 0;
749877298Sobrien	      break;
749977298Sobrien
750077298Sobrien	    case DW_CFA_same_value:
750177298Sobrien	      reg = LEB ();
750278828Sobrien	      if (! do_debug_frames_interp)
750378828Sobrien	        printf ("  DW_CFA_same_value: r%ld\n", reg);
750477298Sobrien	      fc->col_type[reg] = DW_CFA_same_value;
750577298Sobrien	      fc->col_offset[reg] = 0;
750677298Sobrien	      break;
750777298Sobrien
750877298Sobrien	    case DW_CFA_register:
750977298Sobrien	      reg = LEB ();
751077298Sobrien	      roffs = LEB ();
751178828Sobrien	      if (! do_debug_frames_interp)
751278828Sobrien	        printf ("  DW_CFA_register: r%ld\n", reg);
751377298Sobrien	      fc->col_type[reg] = DW_CFA_register;
751477298Sobrien	      fc->col_offset[reg] = roffs;
751577298Sobrien	      break;
751677298Sobrien
751777298Sobrien	    case DW_CFA_remember_state:
751878828Sobrien	      if (! do_debug_frames_interp)
751978828Sobrien	        printf ("  DW_CFA_remember_state\n");
752077298Sobrien	      rs = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk));
752177298Sobrien	      rs->ncols = fc->ncols;
752277298Sobrien	      rs->col_type = (short int *) xmalloc (rs->ncols * sizeof (short int));
752377298Sobrien	      rs->col_offset = (int *) xmalloc (rs->ncols * sizeof (int));
752477298Sobrien	      memcpy (rs->col_type, fc->col_type, rs->ncols);
752577298Sobrien	      memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (int));
752677298Sobrien	      rs->next = remembered_state;
752777298Sobrien	      remembered_state = rs;
752877298Sobrien	      break;
752977298Sobrien
753077298Sobrien	    case DW_CFA_restore_state:
753178828Sobrien	      if (! do_debug_frames_interp)
753278828Sobrien	        printf ("  DW_CFA_restore_state\n");
753377298Sobrien	      rs = remembered_state;
753477298Sobrien	      remembered_state = rs->next;
753577298Sobrien	      frame_need_space (fc, rs->ncols-1);
753677298Sobrien	      memcpy (fc->col_type, rs->col_type, rs->ncols);
753777298Sobrien	      memcpy (fc->col_offset, rs->col_offset, rs->ncols * sizeof (int));
753877298Sobrien	      free (rs->col_type);
753977298Sobrien	      free (rs->col_offset);
754077298Sobrien	      free (rs);
754177298Sobrien	      break;
754277298Sobrien
754377298Sobrien	    case DW_CFA_def_cfa:
754477298Sobrien	      fc->cfa_reg = LEB ();
754577298Sobrien	      fc->cfa_offset = LEB ();
754678828Sobrien	      if (! do_debug_frames_interp)
754778828Sobrien	        printf ("  DW_CFA_def_cfa: r%d ofs %d\n",
754878828Sobrien			fc->cfa_reg, fc->cfa_offset);
754977298Sobrien	      break;
755077298Sobrien
755177298Sobrien	    case DW_CFA_def_cfa_register:
755277298Sobrien	      fc->cfa_reg = LEB ();
755378828Sobrien	      if (! do_debug_frames_interp)
755478828Sobrien	        printf ("  DW_CFA_def_cfa_reg: r%d\n", fc->cfa_reg);
755577298Sobrien	      break;
755677298Sobrien
755777298Sobrien	    case DW_CFA_def_cfa_offset:
755877298Sobrien	      fc->cfa_offset = LEB ();
755978828Sobrien	      if (! do_debug_frames_interp)
756078828Sobrien	        printf ("  DW_CFA_def_cfa_offset: %d\n", fc->cfa_offset);
756177298Sobrien	      break;
756277298Sobrien
756377298Sobrien	    case DW_CFA_nop:
756478828Sobrien	      if (! do_debug_frames_interp)
756578828Sobrien	        printf ("  DW_CFA_nop\n");
756677298Sobrien	      break;
756777298Sobrien
756877298Sobrien#ifndef DW_CFA_GNU_window_save
756977298Sobrien#define DW_CFA_GNU_window_save 0x2d
757077298Sobrien#endif
757177298Sobrien	    case DW_CFA_GNU_window_save:
757278828Sobrien	      if (! do_debug_frames_interp)
757378828Sobrien	        printf ("  DW_CFA_GNU_window_save\n");
757477298Sobrien	      break;
757577298Sobrien
757677298Sobrien	    case DW_CFA_GNU_args_size:
757777298Sobrien	      ul = LEB ();
757878828Sobrien	      if (! do_debug_frames_interp)
757978828Sobrien	        printf ("  DW_CFA_GNU_args_size: %ld\n", ul);
758077298Sobrien	      break;
758177298Sobrien
758277298Sobrien	    case DW_CFA_GNU_negative_offset_extended:
758377298Sobrien	      reg = LEB ();
758477298Sobrien	      l = - LEB ();
758577298Sobrien	      frame_need_space (fc, reg);
758678828Sobrien	      if (! do_debug_frames_interp)
758778828Sobrien	        printf ("  DW_CFA_GNU_negative_offset_extended: r%ld at cfa%+ld\n",
758878828Sobrien			reg, l * fc->data_factor);
758977298Sobrien	      fc->col_type[reg] = DW_CFA_offset;
759077298Sobrien	      fc->col_offset[reg] = l * fc->data_factor;
759177298Sobrien	      break;
759277298Sobrien
759377298Sobrien	    default:
759477298Sobrien	      fprintf (stderr, "unsupported or unknown DW_CFA_%d\n", op);
759577298Sobrien	      start = block_end;
759677298Sobrien	    }
759777298Sobrien	}
759877298Sobrien
759978828Sobrien      if (do_debug_frames_interp)
760078828Sobrien        frame_display_row (fc, &need_col_headers, &max_regs);
760177298Sobrien
760277298Sobrien      start = block_end;
760377298Sobrien    }
760477298Sobrien
760577298Sobrien  printf ("\n");
760677298Sobrien
760777298Sobrien  return 1;
760877298Sobrien}
760977298Sobrien
761077298Sobrien#undef GET
761177298Sobrien#undef LEB
761277298Sobrien#undef SLEB
761377298Sobrien
761477298Sobrienstatic int
761560484Sobriendisplay_debug_not_supported (section, start, file)
761660484Sobrien     Elf32_Internal_Shdr * section;
761760484Sobrien     unsigned char *       start ATTRIBUTE_UNUSED;
761860484Sobrien     FILE *                file ATTRIBUTE_UNUSED;
761960484Sobrien{
762060484Sobrien  printf (_("Displaying the debug contents of section %s is not yet supported.\n"),
762160484Sobrien	    SECTION_NAME (section));
762260484Sobrien
762360484Sobrien  return 1;
762460484Sobrien}
762560484Sobrien
762660484Sobrien/* Pre-scan the .debug_info section to record the size of address.
762760484Sobrien   When dumping the .debug_line, we use that size information, assuming
762860484Sobrien   that all compilation units have the same address size.  */
762960484Sobrienstatic int
763060484Sobrienprescan_debug_info (section, start, file)
763160484Sobrien     Elf32_Internal_Shdr * section ATTRIBUTE_UNUSED;
763260484Sobrien     unsigned char *       start;
763360484Sobrien     FILE *                file ATTRIBUTE_UNUSED;
763460484Sobrien{
763560484Sobrien  DWARF2_External_CompUnit * external;
763660484Sobrien
763760484Sobrien  external = (DWARF2_External_CompUnit *) start;
763860484Sobrien
763960484Sobrien  debug_line_pointer_size = BYTE_GET (external->cu_pointer_size);
764060484Sobrien  return 0;
764160484Sobrien}
764260484Sobrien
764360484Sobrien  /* A structure containing the name of a debug section and a pointer
764460484Sobrien     to a function that can decode it.  The third field is a prescan
764560484Sobrien     function to be run over the section before displaying any of the
764660484Sobrien     sections.  */
764760484Sobrienstruct
764860484Sobrien{
764960484Sobrien  char * name;
765060484Sobrien  int (* display) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
765160484Sobrien  int (* prescan) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
765260484Sobrien}
765360484Sobriendebug_displays[] =
765460484Sobrien{
765560484Sobrien  { ".debug_info",        display_debug_info, prescan_debug_info },
765660484Sobrien  { ".debug_abbrev",      display_debug_abbrev, NULL },
765760484Sobrien  { ".debug_line",        display_debug_lines, NULL },
765860484Sobrien  { ".debug_aranges",     display_debug_aranges, NULL },
765960484Sobrien  { ".debug_pubnames",    display_debug_pubnames, NULL },
766077298Sobrien  { ".debug_frame",       display_debug_frames, NULL },
766177298Sobrien  { ".eh_frame",          display_debug_frames, NULL },
766260484Sobrien  { ".debug_macinfo",     display_debug_not_supported, NULL },
766360484Sobrien  { ".debug_str",         display_debug_not_supported, NULL },
766460484Sobrien  { ".debug_static_func", display_debug_not_supported, NULL },
766560484Sobrien  { ".debug_static_vars", display_debug_not_supported, NULL },
766660484Sobrien  { ".debug_types",       display_debug_not_supported, NULL },
766760484Sobrien  { ".debug_weaknames",   display_debug_not_supported, NULL }
766860484Sobrien};
766960484Sobrien
767060484Sobrienstatic int
767160484Sobriendisplay_debug_section (section, file)
767260484Sobrien     Elf32_Internal_Shdr * section;
767360484Sobrien     FILE * file;
767460484Sobrien{
767560484Sobrien  char *          name = SECTION_NAME (section);
767660484Sobrien  bfd_size_type   length;
767760484Sobrien  unsigned char * start;
767860484Sobrien  int             i;
767960484Sobrien
768060484Sobrien  length = section->sh_size;
768160484Sobrien  if (length == 0)
768260484Sobrien    {
768360484Sobrien      printf (_("\nSection '%s' has no debugging data.\n"), name);
768460484Sobrien      return 0;
768560484Sobrien    }
768660484Sobrien
768760484Sobrien  GET_DATA_ALLOC (section->sh_offset, length, start, unsigned char *,
768860484Sobrien		  "debug section data");
768960484Sobrien
769060484Sobrien  /* See if we know how to display the contents of this section.  */
769177298Sobrien  if (strncmp (name, ".gnu.linkonce.wi.", 17) == 0)
769278828Sobrien    name = ".debug_info";
769377298Sobrien
769460484Sobrien  for (i = NUM_ELEM (debug_displays); i--;)
769560484Sobrien    if (strcmp (debug_displays[i].name, name) == 0)
769660484Sobrien      {
769760484Sobrien	debug_displays[i].display (section, start, file);
769860484Sobrien	break;
769960484Sobrien      }
770060484Sobrien
770160484Sobrien  if (i == -1)
770260484Sobrien    printf (_("Unrecognised debug section: %s\n"), name);
770360484Sobrien
770460484Sobrien  free (start);
770560484Sobrien
770660484Sobrien  /* If we loaded in the abbrev section at some point,
770760484Sobrien     we must release it here.  */
770860484Sobrien  if (first_abbrev != NULL)
770960484Sobrien    free_abbrevs ();
771060484Sobrien
771160484Sobrien  return 1;
771260484Sobrien}
771360484Sobrien
771460484Sobrienstatic int
771560484Sobrienprocess_section_contents (file)
771660484Sobrien     FILE * file;
771760484Sobrien{
771860484Sobrien  Elf32_Internal_Shdr * section;
771978828Sobrien  unsigned int	i;
772060484Sobrien
772160484Sobrien  if (! do_dump)
772260484Sobrien    return 1;
772360484Sobrien
772460484Sobrien  /* Pre-scan the debug sections to find some debug information not
772560484Sobrien     present in some of them.  For the .debug_line, we must find out the
772660484Sobrien     size of address (specified in .debug_info and .debug_aranges).  */
772760484Sobrien  for (i = 0, section = section_headers;
772860484Sobrien       i < elf_header.e_shnum && i < num_dump_sects;
772960484Sobrien       i ++, section ++)
773060484Sobrien    {
773160484Sobrien      char *	name = SECTION_NAME (section);
773260484Sobrien      int       j;
773360484Sobrien
773460484Sobrien      if (section->sh_size == 0)
773560484Sobrien        continue;
773660484Sobrien
773760484Sobrien      /* See if there is some pre-scan operation for this section.  */
773860484Sobrien      for (j = NUM_ELEM (debug_displays); j--;)
773960484Sobrien        if (strcmp (debug_displays[j].name, name) == 0)
774060484Sobrien	  {
774160484Sobrien	    if (debug_displays[j].prescan != NULL)
774260484Sobrien	      {
774360484Sobrien		bfd_size_type   length;
774460484Sobrien		unsigned char * start;
774560484Sobrien
774660484Sobrien		length = section->sh_size;
774760484Sobrien		GET_DATA_ALLOC (section->sh_offset, length, start, unsigned char *,
774860484Sobrien				"debug section data");
774960484Sobrien
775060484Sobrien		debug_displays[j].prescan (section, start, file);
775160484Sobrien		free (start);
775260484Sobrien	      }
775360484Sobrien
775460484Sobrien            break;
775560484Sobrien          }
775660484Sobrien    }
775760484Sobrien
775860484Sobrien  for (i = 0, section = section_headers;
775960484Sobrien       i < elf_header.e_shnum && i < num_dump_sects;
776060484Sobrien       i ++, section ++)
776160484Sobrien    {
776260484Sobrien#ifdef SUPPORT_DISASSEMBLY
776360484Sobrien      if (dump_sects[i] & DISASS_DUMP)
776460484Sobrien	disassemble_section (section, file);
776560484Sobrien#endif
776660484Sobrien      if (dump_sects[i] & HEX_DUMP)
776760484Sobrien	dump_section (section, file);
776860484Sobrien
776960484Sobrien      if (dump_sects[i] & DEBUG_DUMP)
777060484Sobrien	display_debug_section (section, file);
777160484Sobrien    }
777260484Sobrien
777360484Sobrien  if (i < num_dump_sects)
777460484Sobrien    warn (_("Some sections were not dumped because they do not exist!\n"));
777560484Sobrien
777660484Sobrien  return 1;
777760484Sobrien}
777860484Sobrien
777960484Sobrienstatic void
778060484Sobrienprocess_mips_fpe_exception (mask)
778160484Sobrien     int mask;
778260484Sobrien{
778360484Sobrien  if (mask)
778460484Sobrien    {
778560484Sobrien      int first = 1;
778660484Sobrien      if (mask & OEX_FPU_INEX)
778760484Sobrien	fputs ("INEX", stdout), first = 0;
778860484Sobrien      if (mask & OEX_FPU_UFLO)
778960484Sobrien	printf ("%sUFLO", first ? "" : "|"), first = 0;
779060484Sobrien      if (mask & OEX_FPU_OFLO)
779160484Sobrien	printf ("%sOFLO", first ? "" : "|"), first = 0;
779260484Sobrien      if (mask & OEX_FPU_DIV0)
779360484Sobrien	printf ("%sDIV0", first ? "" : "|"), first = 0;
779460484Sobrien      if (mask & OEX_FPU_INVAL)
779560484Sobrien	printf ("%sINVAL", first ? "" : "|");
779660484Sobrien    }
779760484Sobrien  else
779860484Sobrien    fputs ("0", stdout);
779960484Sobrien}
780060484Sobrien
780160484Sobrienstatic int
780260484Sobrienprocess_mips_specific (file)
780360484Sobrien     FILE * file;
780460484Sobrien{
780560484Sobrien  Elf_Internal_Dyn * entry;
780660484Sobrien  size_t liblist_offset = 0;
780760484Sobrien  size_t liblistno = 0;
780860484Sobrien  size_t conflictsno = 0;
780960484Sobrien  size_t options_offset = 0;
781060484Sobrien  size_t conflicts_offset = 0;
781160484Sobrien
781260484Sobrien  /* We have a lot of special sections.  Thanks SGI!  */
781360484Sobrien  if (dynamic_segment == NULL)
781460484Sobrien    /* No information available.  */
781560484Sobrien    return 0;
781660484Sobrien
781760484Sobrien  for (entry = dynamic_segment; entry->d_tag != DT_NULL; ++entry)
781860484Sobrien    switch (entry->d_tag)
781960484Sobrien      {
782060484Sobrien      case DT_MIPS_LIBLIST:
782160484Sobrien	liblist_offset = entry->d_un.d_val - loadaddr;
782260484Sobrien	break;
782360484Sobrien      case DT_MIPS_LIBLISTNO:
782460484Sobrien	liblistno = entry->d_un.d_val;
782560484Sobrien	break;
782660484Sobrien      case DT_MIPS_OPTIONS:
782760484Sobrien	options_offset = entry->d_un.d_val - loadaddr;
782860484Sobrien	break;
782960484Sobrien      case DT_MIPS_CONFLICT:
783060484Sobrien	conflicts_offset = entry->d_un.d_val - loadaddr;
783160484Sobrien	break;
783260484Sobrien      case DT_MIPS_CONFLICTNO:
783360484Sobrien	conflictsno = entry->d_un.d_val;
783460484Sobrien	break;
783560484Sobrien      default:
783660484Sobrien	break;
783760484Sobrien      }
783860484Sobrien
783960484Sobrien  if (liblist_offset != 0 && liblistno != 0 && do_dynamic)
784060484Sobrien    {
784160484Sobrien      Elf32_External_Lib * elib;
784260484Sobrien      size_t cnt;
784360484Sobrien
784460484Sobrien      GET_DATA_ALLOC (liblist_offset, liblistno * sizeof (Elf32_External_Lib),
784560484Sobrien		      elib, Elf32_External_Lib *, "liblist");
784660484Sobrien
784760484Sobrien      printf ("\nSection '.liblist' contains %lu entries:\n",
784860484Sobrien	      (unsigned long) liblistno);
784960484Sobrien      fputs ("     Library              Time Stamp          Checksum   Version Flags\n",
785060484Sobrien	     stdout);
785160484Sobrien
785260484Sobrien      for (cnt = 0; cnt < liblistno; ++cnt)
785360484Sobrien	{
785460484Sobrien	  Elf32_Lib liblist;
785560484Sobrien	  time_t time;
785660484Sobrien	  char timebuf[20];
785760484Sobrien	  struct tm * tmp;
785860484Sobrien
785960484Sobrien	  liblist.l_name = BYTE_GET (elib[cnt].l_name);
786060484Sobrien	  time = BYTE_GET (elib[cnt].l_time_stamp);
786160484Sobrien	  liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum);
786260484Sobrien	  liblist.l_version = BYTE_GET (elib[cnt].l_version);
786360484Sobrien	  liblist.l_flags = BYTE_GET (elib[cnt].l_flags);
786460484Sobrien
786560484Sobrien	  tmp = gmtime (&time);
786660484Sobrien	  sprintf (timebuf, "%04u-%02u-%02uT%02u:%02u:%02u",
786760484Sobrien		   tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
786860484Sobrien		   tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
786960484Sobrien
787060484Sobrien	  printf ("%3lu: %-20s %s %#10lx %-7ld", (unsigned long) cnt,
787160484Sobrien		  dynamic_strings + liblist.l_name, timebuf,
787260484Sobrien		  liblist.l_checksum, liblist.l_version);
787360484Sobrien
787460484Sobrien	  if (liblist.l_flags == 0)
787560484Sobrien	    puts (" NONE");
787660484Sobrien	  else
787760484Sobrien	    {
787860484Sobrien	      static const struct
787960484Sobrien	      {
788060484Sobrien		const char * name;
788160484Sobrien		int bit;
788260484Sobrien	      }
788360484Sobrien	      l_flags_vals[] =
788460484Sobrien	      {
788560484Sobrien		{ " EXACT_MATCH", LL_EXACT_MATCH },
788660484Sobrien		{ " IGNORE_INT_VER", LL_IGNORE_INT_VER },
788760484Sobrien		{ " REQUIRE_MINOR", LL_REQUIRE_MINOR },
788860484Sobrien		{ " EXPORTS", LL_EXPORTS },
788960484Sobrien		{ " DELAY_LOAD", LL_DELAY_LOAD },
789060484Sobrien		{ " DELTA", LL_DELTA }
789160484Sobrien	      };
789260484Sobrien	      int flags = liblist.l_flags;
789360484Sobrien	      size_t fcnt;
789460484Sobrien
789560484Sobrien	      for (fcnt = 0;
789660484Sobrien		   fcnt < sizeof (l_flags_vals) / sizeof (l_flags_vals[0]);
789760484Sobrien		   ++fcnt)
789860484Sobrien		if ((flags & l_flags_vals[fcnt].bit) != 0)
789960484Sobrien		  {
790060484Sobrien		    fputs (l_flags_vals[fcnt].name, stdout);
790160484Sobrien		    flags ^= l_flags_vals[fcnt].bit;
790260484Sobrien		  }
790360484Sobrien	      if (flags != 0)
790460484Sobrien		printf (" %#x", (unsigned int) flags);
790560484Sobrien
790660484Sobrien	      puts ("");
790760484Sobrien	    }
790860484Sobrien	}
790960484Sobrien
791060484Sobrien      free (elib);
791160484Sobrien    }
791260484Sobrien
791360484Sobrien  if (options_offset != 0)
791460484Sobrien    {
791560484Sobrien      Elf_External_Options * eopt;
791660484Sobrien      Elf_Internal_Shdr *    sect = section_headers;
791760484Sobrien      Elf_Internal_Options * iopt;
791860484Sobrien      Elf_Internal_Options * option;
791960484Sobrien      size_t offset;
792060484Sobrien      int cnt;
792160484Sobrien
792260484Sobrien      /* Find the section header so that we get the size.  */
792360484Sobrien      while (sect->sh_type != SHT_MIPS_OPTIONS)
792460484Sobrien	++ sect;
792560484Sobrien
792660484Sobrien      GET_DATA_ALLOC (options_offset, sect->sh_size, eopt,
792760484Sobrien		      Elf_External_Options *, "options");
792860484Sobrien
792960484Sobrien      iopt = (Elf_Internal_Options *) malloc ((sect->sh_size / sizeof (eopt))
793077298Sobrien					      * sizeof (* iopt));
793160484Sobrien      if (iopt == NULL)
793260484Sobrien	{
793360484Sobrien	  error (_("Out of memory"));
793460484Sobrien	  return 0;
793560484Sobrien	}
793660484Sobrien
793760484Sobrien      offset = cnt = 0;
793860484Sobrien      option = iopt;
793977298Sobrien
794060484Sobrien      while (offset < sect->sh_size)
794160484Sobrien	{
794260484Sobrien	  Elf_External_Options * eoption;
794360484Sobrien
794460484Sobrien	  eoption = (Elf_External_Options *) ((char *) eopt + offset);
794560484Sobrien
794660484Sobrien	  option->kind = BYTE_GET (eoption->kind);
794760484Sobrien	  option->size = BYTE_GET (eoption->size);
794860484Sobrien	  option->section = BYTE_GET (eoption->section);
794960484Sobrien	  option->info = BYTE_GET (eoption->info);
795060484Sobrien
795160484Sobrien	  offset += option->size;
795277298Sobrien
795360484Sobrien	  ++option;
795460484Sobrien	  ++cnt;
795560484Sobrien	}
795660484Sobrien
795760484Sobrien      printf (_("\nSection '%s' contains %d entries:\n"),
795877298Sobrien	      SECTION_NAME (sect), cnt);
795960484Sobrien
796060484Sobrien      option = iopt;
796177298Sobrien
796260484Sobrien      while (cnt-- > 0)
796360484Sobrien	{
796460484Sobrien	  size_t len;
796560484Sobrien
796660484Sobrien	  switch (option->kind)
796760484Sobrien	    {
796860484Sobrien	    case ODK_NULL:
796960484Sobrien	      /* This shouldn't happen.  */
797060484Sobrien	      printf (" NULL       %d %lx", option->section, option->info);
797160484Sobrien	      break;
797260484Sobrien	    case ODK_REGINFO:
797360484Sobrien	      printf (" REGINFO    ");
797460484Sobrien	      if (elf_header.e_machine == EM_MIPS)
797560484Sobrien		{
797660484Sobrien		  /* 32bit form.  */
797777298Sobrien		  Elf32_External_RegInfo * ereg;
797877298Sobrien		  Elf32_RegInfo            reginfo;
797960484Sobrien
798060484Sobrien		  ereg = (Elf32_External_RegInfo *) (option + 1);
798160484Sobrien		  reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask);
798260484Sobrien		  reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
798360484Sobrien		  reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
798460484Sobrien		  reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
798560484Sobrien		  reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
798660484Sobrien		  reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
798760484Sobrien
798860484Sobrien		  printf ("GPR %08lx  GP 0x%lx\n",
798960484Sobrien			  reginfo.ri_gprmask,
799060484Sobrien			  (unsigned long) reginfo.ri_gp_value);
799160484Sobrien		  printf ("            CPR0 %08lx  CPR1 %08lx  CPR2 %08lx  CPR3 %08lx\n",
799260484Sobrien			  reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
799360484Sobrien			  reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
799460484Sobrien		}
799560484Sobrien	      else
799660484Sobrien		{
799760484Sobrien		  /* 64 bit form.  */
799860484Sobrien		  Elf64_External_RegInfo * ereg;
799960484Sobrien		  Elf64_Internal_RegInfo reginfo;
800060484Sobrien
800160484Sobrien		  ereg = (Elf64_External_RegInfo *) (option + 1);
800260484Sobrien		  reginfo.ri_gprmask    = BYTE_GET (ereg->ri_gprmask);
800360484Sobrien		  reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]);
800460484Sobrien		  reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
800560484Sobrien		  reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
800660484Sobrien		  reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
800760484Sobrien		  reginfo.ri_gp_value   = BYTE_GET8 (ereg->ri_gp_value);
800860484Sobrien
800960484Sobrien		  printf ("GPR %08lx  GP 0x",
801060484Sobrien			  reginfo.ri_gprmask);
801160484Sobrien		  printf_vma (reginfo.ri_gp_value);
801260484Sobrien		  printf ("\n");
801360484Sobrien
801460484Sobrien		  printf ("            CPR0 %08lx  CPR1 %08lx  CPR2 %08lx  CPR3 %08lx\n",
801560484Sobrien			  reginfo.ri_cprmask[0], reginfo.ri_cprmask[1],
801660484Sobrien			  reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]);
801760484Sobrien		}
801860484Sobrien	      ++option;
801960484Sobrien	      continue;
802060484Sobrien	    case ODK_EXCEPTIONS:
802160484Sobrien	      fputs (" EXCEPTIONS fpe_min(", stdout);
802260484Sobrien	      process_mips_fpe_exception (option->info & OEX_FPU_MIN);
802360484Sobrien	      fputs (") fpe_max(", stdout);
802460484Sobrien	      process_mips_fpe_exception ((option->info & OEX_FPU_MAX) >> 8);
802560484Sobrien	      fputs (")", stdout);
802660484Sobrien
802760484Sobrien	      if (option->info & OEX_PAGE0)
802860484Sobrien		fputs (" PAGE0", stdout);
802960484Sobrien	      if (option->info & OEX_SMM)
803060484Sobrien		fputs (" SMM", stdout);
803160484Sobrien	      if (option->info & OEX_FPDBUG)
803260484Sobrien		fputs (" FPDBUG", stdout);
803360484Sobrien	      if (option->info & OEX_DISMISS)
803460484Sobrien		fputs (" DISMISS", stdout);
803560484Sobrien	      break;
803660484Sobrien	    case ODK_PAD:
803760484Sobrien	      fputs (" PAD       ", stdout);
803860484Sobrien	      if (option->info & OPAD_PREFIX)
803960484Sobrien		fputs (" PREFIX", stdout);
804060484Sobrien	      if (option->info & OPAD_POSTFIX)
804160484Sobrien		fputs (" POSTFIX", stdout);
804260484Sobrien	      if (option->info & OPAD_SYMBOL)
804360484Sobrien		fputs (" SYMBOL", stdout);
804460484Sobrien	      break;
804560484Sobrien	    case ODK_HWPATCH:
804660484Sobrien	      fputs (" HWPATCH   ", stdout);
804760484Sobrien	      if (option->info & OHW_R4KEOP)
804860484Sobrien		fputs (" R4KEOP", stdout);
804960484Sobrien	      if (option->info & OHW_R8KPFETCH)
805060484Sobrien		fputs (" R8KPFETCH", stdout);
805160484Sobrien	      if (option->info & OHW_R5KEOP)
805260484Sobrien		fputs (" R5KEOP", stdout);
805360484Sobrien	      if (option->info & OHW_R5KCVTL)
805460484Sobrien		fputs (" R5KCVTL", stdout);
805560484Sobrien	      break;
805660484Sobrien	    case ODK_FILL:
805760484Sobrien	      fputs (" FILL       ", stdout);
805860484Sobrien	      /* XXX Print content of info word?  */
805960484Sobrien	      break;
806060484Sobrien	    case ODK_TAGS:
806160484Sobrien	      fputs (" TAGS       ", stdout);
806260484Sobrien	      /* XXX Print content of info word?  */
806360484Sobrien	      break;
806460484Sobrien	    case ODK_HWAND:
806560484Sobrien	      fputs (" HWAND     ", stdout);
806660484Sobrien	      if (option->info & OHWA0_R4KEOP_CHECKED)
806760484Sobrien		fputs (" R4KEOP_CHECKED", stdout);
806860484Sobrien	      if (option->info & OHWA0_R4KEOP_CLEAN)
806960484Sobrien		fputs (" R4KEOP_CLEAN", stdout);
807060484Sobrien	      break;
807160484Sobrien	    case ODK_HWOR:
807260484Sobrien	      fputs (" HWOR      ", stdout);
807360484Sobrien	      if (option->info & OHWA0_R4KEOP_CHECKED)
807460484Sobrien		fputs (" R4KEOP_CHECKED", stdout);
807560484Sobrien	      if (option->info & OHWA0_R4KEOP_CLEAN)
807660484Sobrien		fputs (" R4KEOP_CLEAN", stdout);
807760484Sobrien	      break;
807860484Sobrien	    case ODK_GP_GROUP:
807960484Sobrien	      printf (" GP_GROUP  %#06lx  self-contained %#06lx",
808060484Sobrien		      option->info & OGP_GROUP,
808160484Sobrien		      (option->info & OGP_SELF) >> 16);
808260484Sobrien	      break;
808360484Sobrien	    case ODK_IDENT:
808460484Sobrien	      printf (" IDENT     %#06lx  self-contained %#06lx",
808560484Sobrien		      option->info & OGP_GROUP,
808660484Sobrien		      (option->info & OGP_SELF) >> 16);
808760484Sobrien	      break;
808860484Sobrien	    default:
808960484Sobrien	      /* This shouldn't happen.  */
809060484Sobrien	      printf (" %3d ???     %d %lx",
809160484Sobrien		      option->kind, option->section, option->info);
809260484Sobrien	      break;
809360484Sobrien	    }
809460484Sobrien
809577298Sobrien	  len = sizeof (* eopt);
809660484Sobrien	  while (len < option->size)
809760484Sobrien	    if (((char *) option)[len] >= ' '
809860484Sobrien		&& ((char *) option)[len] < 0x7f)
809960484Sobrien	      printf ("%c", ((char *) option)[len++]);
810060484Sobrien	    else
810160484Sobrien	      printf ("\\%03o", ((char *) option)[len++]);
810260484Sobrien
810360484Sobrien	  fputs ("\n", stdout);
810460484Sobrien	  ++option;
810560484Sobrien	}
810660484Sobrien
810760484Sobrien      free (eopt);
810860484Sobrien    }
810960484Sobrien
811060484Sobrien  if (conflicts_offset != 0 && conflictsno != 0)
811160484Sobrien    {
811260484Sobrien      Elf32_External_Conflict * econf32;
811360484Sobrien      Elf64_External_Conflict * econf64;
811460484Sobrien      Elf32_Conflict * iconf;
811560484Sobrien      size_t cnt;
811660484Sobrien
811760484Sobrien      if (dynamic_symbols == NULL)
811860484Sobrien	{
811960484Sobrien	  error (_("conflict list with without table"));
812060484Sobrien	  return 0;
812160484Sobrien	}
812260484Sobrien
812377298Sobrien      iconf = (Elf32_Conflict *) malloc (conflictsno * sizeof (* iconf));
812460484Sobrien      if (iconf == NULL)
812560484Sobrien	{
812660484Sobrien	  error (_("Out of memory"));
812760484Sobrien	  return 0;
812860484Sobrien	}
812960484Sobrien
813060484Sobrien      if (is_32bit_elf)
813160484Sobrien	{
813277298Sobrien	  GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (* econf32),
813360484Sobrien			  econf32, Elf32_External_Conflict *, "conflict");
813460484Sobrien
813560484Sobrien	  for (cnt = 0; cnt < conflictsno; ++cnt)
813660484Sobrien	    iconf[cnt] = BYTE_GET (econf32[cnt]);
813760484Sobrien	}
813860484Sobrien      else
813960484Sobrien	{
814077298Sobrien	  GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (* econf64),
814160484Sobrien			  econf64, Elf64_External_Conflict *, "conflict");
814260484Sobrien
814360484Sobrien	  for (cnt = 0; cnt < conflictsno; ++cnt)
814460484Sobrien	    iconf[cnt] = BYTE_GET (econf64[cnt]);
814560484Sobrien	}
814660484Sobrien
814760484Sobrien      printf (_("\nSection '.conflict' contains %d entries:\n"), conflictsno);
814860484Sobrien      puts (_("  Num:    Index       Value  Name"));
814960484Sobrien
815060484Sobrien      for (cnt = 0; cnt < conflictsno; ++cnt)
815160484Sobrien	{
815260484Sobrien	  Elf_Internal_Sym * psym = &dynamic_symbols[iconf[cnt]];
815360484Sobrien
815460484Sobrien	  printf ("%5lu: %8lu  ", (unsigned long) cnt, iconf[cnt]);
815560484Sobrien	  print_vma (psym->st_value, FULL_HEX);
815660484Sobrien	  printf ("  %s\n", dynamic_strings + psym->st_name);
815760484Sobrien	}
815860484Sobrien
815960484Sobrien      free (iconf);
816060484Sobrien    }
816160484Sobrien
816260484Sobrien  return 1;
816360484Sobrien}
816460484Sobrien
816560484Sobrienstatic char *
816660484Sobrienget_note_type (e_type)
816760484Sobrien     unsigned e_type;
816860484Sobrien{
816960484Sobrien  static char buff[64];
817060484Sobrien
817160484Sobrien  switch (e_type)
817260484Sobrien    {
817360484Sobrien    case NT_PRSTATUS:	return _("NT_PRSTATUS (prstatus structure)");
817460484Sobrien    case NT_FPREGSET:	return _("NT_FPREGSET (floating point registers)");
817560484Sobrien    case NT_PRPSINFO:   return _("NT_PRPSINFO (prpsinfo structure)");
817660484Sobrien    case NT_TASKSTRUCT: return _("NT_TASKSTRUCT (task structure)");
817760484Sobrien    case NT_PRXFPREG:   return _("NT_PRXFPREG (user_xfpregs structure)");
817860484Sobrien    case NT_PSTATUS:	return _("NT_PSTATUS (pstatus structure)");
817960484Sobrien    case NT_FPREGS:	return _("NT_FPREGS (floating point registers)");
818060484Sobrien    case NT_PSINFO:	return _("NT_PSINFO (psinfo structure)");
818160484Sobrien    case NT_LWPSTATUS:	return _("NT_LWPSTATUS (lwpstatus_t structure)");
818260484Sobrien    case NT_LWPSINFO:	return _("NT_LWPSINFO (lwpsinfo_t structure)");
818360484Sobrien    case NT_WIN32PSTATUS: return _("NT_WIN32PSTATUS (win32_pstatus strcuture)");
818460484Sobrien    default:
818560484Sobrien      sprintf (buff, _("Unknown note type: (0x%08x)"), e_type);
818660484Sobrien      return buff;
818760484Sobrien    }
818860484Sobrien}
818960484Sobrien
819060484Sobrien/* Note that by the ELF standard, the name field is already null byte
819160484Sobrien   terminated, and namesz includes the terminating null byte.
819260484Sobrien   I.E. the value of namesz for the name "FSF" is 4.
819360484Sobrien
819460484Sobrien   If the value of namesz is zero, there is no name present. */
819560484Sobrienstatic int
819660484Sobrienprocess_note (pnote)
819760484Sobrien  Elf32_Internal_Note * pnote;
819860484Sobrien{
819960484Sobrien  printf ("  %s\t\t0x%08lx\t%s\n",
820060484Sobrien	  pnote->namesz ? pnote->namedata : "(NONE)",
820178828Sobrien	  pnote->descsz, get_note_type (pnote->type));
820260484Sobrien  return 1;
820360484Sobrien}
820460484Sobrien
820560484Sobrien
820660484Sobrienstatic int
820760484Sobrienprocess_corefile_note_segment (file, offset, length)
820860484Sobrien     FILE * file;
820960484Sobrien     bfd_vma offset;
821060484Sobrien     bfd_vma length;
821160484Sobrien{
821260484Sobrien  Elf_External_Note *  pnotes;
821360484Sobrien  Elf_External_Note *  external;
821460484Sobrien  int                  res = 1;
821560484Sobrien
821660484Sobrien  if (length <= 0)
821760484Sobrien    return 0;
821860484Sobrien
821960484Sobrien  GET_DATA_ALLOC (offset, length, pnotes, Elf_External_Note *, "notes");
822060484Sobrien
822160484Sobrien  external = pnotes;
822260484Sobrien
822360484Sobrien  printf (_("\nNotes at offset 0x%08lx with length 0x%08lx:\n"),
822477298Sobrien	  (unsigned long) offset, (unsigned long) length);
822560484Sobrien  printf (_("  Owner\t\tData size\tDescription\n"));
822660484Sobrien
822760484Sobrien  while (external < (Elf_External_Note *)((char *) pnotes + length))
822860484Sobrien    {
822960484Sobrien      Elf32_Internal_Note inote;
823060484Sobrien      char * temp = NULL;
823160484Sobrien
823260484Sobrien      inote.type     = BYTE_GET (external->type);
823360484Sobrien      inote.namesz   = BYTE_GET (external->namesz);
823460484Sobrien      inote.namedata = external->name;
823560484Sobrien      inote.descsz   = BYTE_GET (external->descsz);
823660484Sobrien      inote.descdata = inote.namedata + align_power (inote.namesz, 2);
823760484Sobrien      inote.descpos  = offset + (inote.descdata - (char *) pnotes);
823877298Sobrien
823960484Sobrien      external = (Elf_External_Note *)(inote.descdata + align_power (inote.descsz, 2));
824060484Sobrien
824160484Sobrien      /* Verify that name is null terminated.  It appears that at least
824260484Sobrien	 one version of Linux (RedHat 6.0) generates corefiles that don't
824360484Sobrien	 comply with the ELF spec by failing to include the null byte in
824460484Sobrien	 namesz.  */
824560484Sobrien      if (inote.namedata[inote.namesz] != '\0')
824660484Sobrien	{
824760484Sobrien	  temp = malloc (inote.namesz + 1);
824877298Sobrien
824960484Sobrien	  if (temp == NULL)
825060484Sobrien	    {
825160484Sobrien	      error (_("Out of memory\n"));
825260484Sobrien	      res = 0;
825360484Sobrien	      break;
825460484Sobrien	    }
825577298Sobrien
825660484Sobrien	  strncpy (temp, inote.namedata, inote.namesz);
825760484Sobrien	  temp[inote.namesz] = 0;
825877298Sobrien
825960484Sobrien	  /* warn (_("'%s' NOTE name not properly null terminated\n"), temp);  */
826060484Sobrien	  inote.namedata = temp;
826160484Sobrien	}
826260484Sobrien
826360484Sobrien      res &= process_note (& inote);
826460484Sobrien
826560484Sobrien      if (temp != NULL)
826660484Sobrien	{
826760484Sobrien	  free (temp);
826860484Sobrien	  temp = NULL;
826960484Sobrien	}
827060484Sobrien    }
827160484Sobrien
827260484Sobrien  free (pnotes);
827360484Sobrien
827460484Sobrien  return res;
827560484Sobrien}
827660484Sobrien
827760484Sobrienstatic int
827860484Sobrienprocess_corefile_note_segments (file)
827960484Sobrien     FILE * file;
828060484Sobrien{
828160484Sobrien  Elf_Internal_Phdr * program_headers;
828260484Sobrien  Elf_Internal_Phdr * segment;
828360484Sobrien  unsigned int	      i;
828460484Sobrien  int                 res = 1;
828560484Sobrien
828660484Sobrien  program_headers = (Elf_Internal_Phdr *) malloc
828760484Sobrien    (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
828860484Sobrien
828960484Sobrien  if (program_headers == NULL)
829060484Sobrien    {
829160484Sobrien      error (_("Out of memory\n"));
829260484Sobrien      return 0;
829360484Sobrien    }
829460484Sobrien
829560484Sobrien  if (is_32bit_elf)
829660484Sobrien    i = get_32bit_program_headers (file, program_headers);
829760484Sobrien  else
829860484Sobrien    i = get_64bit_program_headers (file, program_headers);
829960484Sobrien
830060484Sobrien  if (i == 0)
830160484Sobrien    {
830260484Sobrien      free (program_headers);
830360484Sobrien      return 0;
830460484Sobrien    }
830560484Sobrien
830660484Sobrien  for (i = 0, segment = program_headers;
830760484Sobrien       i < elf_header.e_phnum;
830860484Sobrien       i ++, segment ++)
830960484Sobrien    {
831060484Sobrien      if (segment->p_type == PT_NOTE)
831160484Sobrien	res &= process_corefile_note_segment (file,
831260484Sobrien					      (bfd_vma) segment->p_offset,
831360484Sobrien					      (bfd_vma) segment->p_filesz);
831460484Sobrien    }
831560484Sobrien
831660484Sobrien  free (program_headers);
831760484Sobrien
831860484Sobrien  return res;
831960484Sobrien}
832060484Sobrien
832160484Sobrienstatic int
832260484Sobrienprocess_corefile_contents (file)
832360484Sobrien     FILE * file;
832460484Sobrien{
832560484Sobrien  /* If we have not been asked to display the notes then do nothing.  */
832660484Sobrien  if (! do_notes)
832760484Sobrien    return 1;
832860484Sobrien
832960484Sobrien  /* If file is not a core file then exit.  */
833060484Sobrien  if (elf_header.e_type != ET_CORE)
833160484Sobrien    return 1;
833260484Sobrien
833360484Sobrien  /* No program headers means no NOTE segment.  */
833460484Sobrien  if (elf_header.e_phnum == 0)
833560484Sobrien    {
833660484Sobrien      printf (_("No note segments present in the core file.\n"));
833760484Sobrien      return 1;
833860484Sobrien   }
833960484Sobrien
834060484Sobrien  return process_corefile_note_segments (file);
834160484Sobrien}
834260484Sobrien
834360484Sobrienstatic int
834460484Sobrienprocess_arch_specific (file)
834560484Sobrien     FILE * file;
834660484Sobrien{
834760484Sobrien  if (! do_arch)
834860484Sobrien    return 1;
834960484Sobrien
835060484Sobrien  switch (elf_header.e_machine)
835160484Sobrien    {
835260484Sobrien    case EM_MIPS:
835378828Sobrien    case EM_MIPS_RS3_LE:
835460484Sobrien      return process_mips_specific (file);
835560484Sobrien      break;
835660484Sobrien    default:
835760484Sobrien      break;
835860484Sobrien    }
835960484Sobrien  return 1;
836060484Sobrien}
836160484Sobrien
836260484Sobrienstatic int
836360484Sobrienget_file_header (file)
836460484Sobrien     FILE * file;
836560484Sobrien{
836660484Sobrien  /* Read in the identity array.  */
836760484Sobrien  if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1)
836860484Sobrien    return 0;
836960484Sobrien
837060484Sobrien  /* Determine how to read the rest of the header.  */
837160484Sobrien  switch (elf_header.e_ident [EI_DATA])
837260484Sobrien    {
837360484Sobrien    default: /* fall through */
837460484Sobrien    case ELFDATANONE: /* fall through */
837560484Sobrien    case ELFDATA2LSB: byte_get = byte_get_little_endian; break;
837660484Sobrien    case ELFDATA2MSB: byte_get = byte_get_big_endian; break;
837760484Sobrien    }
837860484Sobrien
837960484Sobrien  /* For now we only support 32 bit and 64 bit ELF files.  */
838060484Sobrien  is_32bit_elf = (elf_header.e_ident [EI_CLASS] != ELFCLASS64);
838160484Sobrien
838260484Sobrien  /* Read in the rest of the header.  */
838360484Sobrien  if (is_32bit_elf)
838460484Sobrien    {
838560484Sobrien      Elf32_External_Ehdr ehdr32;
838660484Sobrien
838760484Sobrien      if (fread (ehdr32.e_type, sizeof (ehdr32) - EI_NIDENT, 1, file) != 1)
838860484Sobrien	return 0;
838960484Sobrien
839060484Sobrien      elf_header.e_type      = BYTE_GET (ehdr32.e_type);
839160484Sobrien      elf_header.e_machine   = BYTE_GET (ehdr32.e_machine);
839260484Sobrien      elf_header.e_version   = BYTE_GET (ehdr32.e_version);
839360484Sobrien      elf_header.e_entry     = BYTE_GET (ehdr32.e_entry);
839460484Sobrien      elf_header.e_phoff     = BYTE_GET (ehdr32.e_phoff);
839560484Sobrien      elf_header.e_shoff     = BYTE_GET (ehdr32.e_shoff);
839660484Sobrien      elf_header.e_flags     = BYTE_GET (ehdr32.e_flags);
839760484Sobrien      elf_header.e_ehsize    = BYTE_GET (ehdr32.e_ehsize);
839860484Sobrien      elf_header.e_phentsize = BYTE_GET (ehdr32.e_phentsize);
839960484Sobrien      elf_header.e_phnum     = BYTE_GET (ehdr32.e_phnum);
840060484Sobrien      elf_header.e_shentsize = BYTE_GET (ehdr32.e_shentsize);
840160484Sobrien      elf_header.e_shnum     = BYTE_GET (ehdr32.e_shnum);
840260484Sobrien      elf_header.e_shstrndx  = BYTE_GET (ehdr32.e_shstrndx);
840360484Sobrien    }
840460484Sobrien  else
840560484Sobrien    {
840660484Sobrien      Elf64_External_Ehdr ehdr64;
840760484Sobrien
840860484Sobrien      /* If we have been compiled with sizeof (bfd_vma) == 4, then
840960484Sobrien	 we will not be able to cope with the 64bit data found in
841060484Sobrien	 64 ELF files.  Detect this now and abort before we start
841160484Sobrien	 overwritting things.  */
841260484Sobrien      if (sizeof (bfd_vma) < 8)
841360484Sobrien	{
841460484Sobrien	  error (_("This instance of readelf has been built without support for a\n"));
841560484Sobrien	  error (_("64 bit data type and so it cannot read 64 bit ELF files.\n"));
841660484Sobrien	  return 0;
841760484Sobrien	}
841860484Sobrien
841960484Sobrien      if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT, 1, file) != 1)
842060484Sobrien	return 0;
842160484Sobrien
842260484Sobrien      elf_header.e_type      = BYTE_GET (ehdr64.e_type);
842360484Sobrien      elf_header.e_machine   = BYTE_GET (ehdr64.e_machine);
842460484Sobrien      elf_header.e_version   = BYTE_GET (ehdr64.e_version);
842560484Sobrien      elf_header.e_entry     = BYTE_GET8 (ehdr64.e_entry);
842660484Sobrien      elf_header.e_phoff     = BYTE_GET8 (ehdr64.e_phoff);
842760484Sobrien      elf_header.e_shoff     = BYTE_GET8 (ehdr64.e_shoff);
842860484Sobrien      elf_header.e_flags     = BYTE_GET (ehdr64.e_flags);
842960484Sobrien      elf_header.e_ehsize    = BYTE_GET (ehdr64.e_ehsize);
843060484Sobrien      elf_header.e_phentsize = BYTE_GET (ehdr64.e_phentsize);
843160484Sobrien      elf_header.e_phnum     = BYTE_GET (ehdr64.e_phnum);
843260484Sobrien      elf_header.e_shentsize = BYTE_GET (ehdr64.e_shentsize);
843360484Sobrien      elf_header.e_shnum     = BYTE_GET (ehdr64.e_shnum);
843460484Sobrien      elf_header.e_shstrndx  = BYTE_GET (ehdr64.e_shstrndx);
843560484Sobrien    }
843660484Sobrien
843760484Sobrien  return 1;
843860484Sobrien}
843960484Sobrien
844060484Sobrienstatic void
844160484Sobrienprocess_file (file_name)
844260484Sobrien     char * file_name;
844360484Sobrien{
844460484Sobrien  FILE *       file;
844560484Sobrien  struct stat  statbuf;
844660484Sobrien  unsigned int i;
844760484Sobrien
844860484Sobrien  if (stat (file_name, & statbuf) < 0)
844960484Sobrien    {
845060484Sobrien      error (_("Cannot stat input file %s.\n"), file_name);
845160484Sobrien      return;
845260484Sobrien    }
845360484Sobrien
845460484Sobrien  file = fopen (file_name, "rb");
845560484Sobrien  if (file == NULL)
845660484Sobrien    {
845760484Sobrien      error (_("Input file %s not found.\n"), file_name);
845860484Sobrien      return;
845960484Sobrien    }
846060484Sobrien
846160484Sobrien  if (! get_file_header (file))
846260484Sobrien    {
846360484Sobrien      error (_("%s: Failed to read file header\n"), file_name);
846460484Sobrien      fclose (file);
846560484Sobrien      return;
846660484Sobrien    }
846760484Sobrien
846860484Sobrien  /* Initialise per file variables.  */
846960484Sobrien  for (i = NUM_ELEM (version_info); i--;)
847060484Sobrien    version_info[i] = 0;
847160484Sobrien
847260484Sobrien  for (i = NUM_ELEM (dynamic_info); i--;)
847360484Sobrien    dynamic_info[i] = 0;
847460484Sobrien
847560484Sobrien  /* Process the file.  */
847660484Sobrien  if (show_name)
847760484Sobrien    printf (_("\nFile: %s\n"), file_name);
847860484Sobrien
847960484Sobrien  if (! process_file_header ())
848060484Sobrien    {
848160484Sobrien      fclose (file);
848260484Sobrien      return;
848360484Sobrien    }
848460484Sobrien
848560484Sobrien  process_section_headers (file);
848660484Sobrien
848760484Sobrien  process_program_headers (file);
848860484Sobrien
848960484Sobrien  process_dynamic_segment (file);
849060484Sobrien
849160484Sobrien  process_relocs (file);
849260484Sobrien
849378828Sobrien  process_unwind (file);
849478828Sobrien
849560484Sobrien  process_symbol_table (file);
849660484Sobrien
849760484Sobrien  process_syminfo (file);
849860484Sobrien
849960484Sobrien  process_version_sections (file);
850060484Sobrien
850160484Sobrien  process_section_contents (file);
850260484Sobrien
850360484Sobrien  process_corefile_contents (file);
850460484Sobrien
850560484Sobrien  process_arch_specific (file);
850660484Sobrien
850760484Sobrien  fclose (file);
850860484Sobrien
850960484Sobrien  if (section_headers)
851060484Sobrien    {
851160484Sobrien      free (section_headers);
851260484Sobrien      section_headers = NULL;
851360484Sobrien    }
851460484Sobrien
851560484Sobrien  if (string_table)
851660484Sobrien    {
851760484Sobrien      free (string_table);
851860484Sobrien      string_table = NULL;
851977298Sobrien      string_table_length = 0;
852060484Sobrien    }
852160484Sobrien
852260484Sobrien  if (dynamic_strings)
852360484Sobrien    {
852460484Sobrien      free (dynamic_strings);
852560484Sobrien      dynamic_strings = NULL;
852660484Sobrien    }
852760484Sobrien
852860484Sobrien  if (dynamic_symbols)
852960484Sobrien    {
853060484Sobrien      free (dynamic_symbols);
853160484Sobrien      dynamic_symbols = NULL;
853260484Sobrien      num_dynamic_syms = 0;
853360484Sobrien    }
853460484Sobrien
853560484Sobrien  if (dynamic_syminfo)
853660484Sobrien    {
853760484Sobrien      free (dynamic_syminfo);
853860484Sobrien      dynamic_syminfo = NULL;
853960484Sobrien    }
854060484Sobrien}
854160484Sobrien
854260484Sobrien#ifdef SUPPORT_DISASSEMBLY
854360484Sobrien/* Needed by the i386 disassembler.  For extra credit, someone could
854460484Sobrien   fix this so that we insert symbolic addresses here, esp for GOT/PLT
854560484Sobrien   symbols */
854660484Sobrien
854760484Sobrienvoid
854860484Sobrienprint_address (unsigned int addr, FILE * outfile)
854960484Sobrien{
855060484Sobrien  fprintf (outfile,"0x%8.8x", addr);
855160484Sobrien}
855260484Sobrien
855360484Sobrien/* Needed by the i386 disassembler. */
855460484Sobrienvoid
855560484Sobriendb_task_printsym (unsigned int addr)
855660484Sobrien{
855760484Sobrien  print_address (addr, stderr);
855860484Sobrien}
855960484Sobrien#endif
856060484Sobrien
856160484Sobrienint
856260484Sobrienmain (argc, argv)
856360484Sobrien     int     argc;
856460484Sobrien     char ** argv;
856560484Sobrien{
856660484Sobrien#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
856760484Sobrien  setlocale (LC_MESSAGES, "");
856860484Sobrien#endif
856960484Sobrien  bindtextdomain (PACKAGE, LOCALEDIR);
857060484Sobrien  textdomain (PACKAGE);
857160484Sobrien
857260484Sobrien  parse_args (argc, argv);
857360484Sobrien
857460484Sobrien  if (optind < (argc - 1))
857560484Sobrien    show_name = 1;
857660484Sobrien
857760484Sobrien  while (optind < argc)
857860484Sobrien    process_file (argv [optind ++]);
857960484Sobrien
858060484Sobrien  if (dump_sects != NULL)
858160484Sobrien    free (dump_sects);
858260484Sobrien
858360484Sobrien  return 0;
858460484Sobrien}
8585