Back to index

cell-binutils  2.17cvs20070401
readelf.c
Go to the documentation of this file.
00001 /* readelf.c -- display contents of an ELF format file
00002    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
00003    Free Software Foundation, Inc.
00004 
00005    Originally developed by Eric Youngdale <eric@andante.jic.com>
00006    Modifications by Nick Clifton <nickc@redhat.com>
00007 
00008    This file is part of GNU Binutils.
00009 
00010    This program is free software; you can redistribute it and/or modify
00011    it under the terms of the GNU General Public License as published by
00012    the Free Software Foundation; either version 2 of the License, or
00013    (at your option) any later version.
00014 
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019 
00020    You should have received a copy of the GNU General Public License
00021    along with this program; if not, write to the Free Software
00022    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
00023    02110-1301, USA.  */
00024 
00025 /* The difference between readelf and objdump:
00026 
00027   Both programs are capable of displaying the contents of ELF format files,
00028   so why does the binutils project have two file dumpers ?
00029 
00030   The reason is that objdump sees an ELF file through a BFD filter of the
00031   world; if BFD has a bug where, say, it disagrees about a machine constant
00032   in e_flags, then the odds are good that it will remain internally
00033   consistent.  The linker sees it the BFD way, objdump sees it the BFD way,
00034   GAS sees it the BFD way.  There was need for a tool to go find out what
00035   the file actually says.
00036 
00037   This is why the readelf program does not link against the BFD library - it
00038   exists as an independent program to help verify the correct working of BFD.
00039 
00040   There is also the case that readelf can provide more information about an
00041   ELF file than is provided by objdump.  In particular it can display DWARF
00042   debugging information which (at the moment) objdump cannot.  */
00043 
00044 #include <assert.h>
00045 #include <sys/types.h>
00046 #include <sys/stat.h>
00047 #include <stdio.h>
00048 #include <time.h>
00049 
00050 /* for PATH_MAX */
00051 #ifdef HAVE_LIMITS_H
00052 #include <limits.h>
00053 #endif
00054 
00055 #ifndef PATH_MAX
00056 /* for MAXPATHLEN */
00057 # ifdef HAVE_SYS_PARAM_H
00058 #  include <sys/param.h>
00059 # endif
00060 # ifndef PATH_MAX
00061 #  ifdef MAXPATHLEN
00062 #   define PATH_MAX MAXPATHLEN
00063 #  else
00064 #   define PATH_MAX 1024
00065 #  endif
00066 # endif
00067 #endif
00068 
00069 #if __GNUC__ >= 2
00070 /* Define BFD64 here, even if our default architecture is 32 bit ELF
00071    as this will allow us to read in and parse 64bit and 32bit ELF files.
00072    Only do this if we believe that the compiler can support a 64 bit
00073    data type.  For now we only rely on GCC being able to do this.  */
00074 #define BFD64
00075 #endif
00076 
00077 #include "dwarf.h"
00078 
00079 #include "elf/common.h"
00080 #include "elf/external.h"
00081 #include "elf/internal.h"
00082 
00083 
00084 /* Included here, before RELOC_MACROS_GEN_FUNC is defined, so that
00085    we can obtain the H8 reloc numbers.  We need these for the
00086    get_reloc_size() function.  We include h8.h again after defining
00087    RELOC_MACROS_GEN_FUNC so that we get the naming function as well.  */
00088 
00089 #include "elf/h8.h"
00090 #undef _ELF_H8_H
00091 
00092 /* Undo the effects of #including reloc-macros.h.  */
00093 
00094 #undef START_RELOC_NUMBERS
00095 #undef RELOC_NUMBER
00096 #undef FAKE_RELOC
00097 #undef EMPTY_RELOC
00098 #undef END_RELOC_NUMBERS
00099 #undef _RELOC_MACROS_H
00100 
00101 /* The following headers use the elf/reloc-macros.h file to
00102    automatically generate relocation recognition functions
00103    such as elf_mips_reloc_type()  */
00104 
00105 #define RELOC_MACROS_GEN_FUNC
00106 
00107 #include "elf/alpha.h"
00108 #include "elf/arc.h"
00109 #include "elf/arm.h"
00110 #include "elf/avr.h"
00111 #include "elf/bfin.h"
00112 #include "elf/cris.h"
00113 #include "elf/crx.h"
00114 #include "elf/d10v.h"
00115 #include "elf/d30v.h"
00116 #include "elf/dlx.h"
00117 #include "elf/fr30.h"
00118 #include "elf/frv.h"
00119 #include "elf/h8.h"
00120 #include "elf/hppa.h"
00121 #include "elf/i386.h"
00122 #include "elf/i370.h"
00123 #include "elf/i860.h"
00124 #include "elf/i960.h"
00125 #include "elf/ia64.h"
00126 #include "elf/ip2k.h"
00127 #include "elf/iq2000.h"
00128 #include "elf/m32c.h"
00129 #include "elf/m32r.h"
00130 #include "elf/m68k.h"
00131 #include "elf/m68hc11.h"
00132 #include "elf/mcore.h"
00133 #include "elf/mep.h"
00134 #include "elf/mips.h"
00135 #include "elf/mmix.h"
00136 #include "elf/mn10200.h"
00137 #include "elf/mn10300.h"
00138 #include "elf/mt.h"
00139 #include "elf/msp430.h"
00140 #include "elf/or32.h"
00141 #include "elf/pj.h"
00142 #include "elf/ppc.h"
00143 #include "elf/ppc64.h"
00144 #include "elf/s390.h"
00145 #include "elf/score.h"
00146 #include "elf/sh.h"
00147 #include "elf/sparc.h"
00148 #include "elf/spu.h"
00149 #include "elf/v850.h"
00150 #include "elf/vax.h"
00151 #include "elf/x86-64.h"
00152 #include "elf/xstormy16.h"
00153 #include "elf/xtensa.h"
00154 
00155 #include "aout/ar.h"
00156 
00157 #include "bucomm.h"
00158 #include "getopt.h"
00159 #include "libiberty.h"
00160 
00161 char *program_name = "readelf";
00162 static long archive_file_offset;
00163 static unsigned long archive_file_size;
00164 static unsigned long dynamic_addr;
00165 static bfd_size_type dynamic_size;
00166 static unsigned int dynamic_nent;
00167 static char *dynamic_strings;
00168 static unsigned long dynamic_strings_length;
00169 static char *string_table;
00170 static unsigned long string_table_length;
00171 static unsigned long num_dynamic_syms;
00172 static Elf_Internal_Sym *dynamic_symbols;
00173 static Elf_Internal_Syminfo *dynamic_syminfo;
00174 static unsigned long dynamic_syminfo_offset;
00175 static unsigned int dynamic_syminfo_nent;
00176 static char program_interpreter[PATH_MAX];
00177 static bfd_vma dynamic_info[DT_JMPREL + 1];
00178 static bfd_vma dynamic_info_DT_GNU_HASH;
00179 static bfd_vma version_info[16];
00180 static Elf_Internal_Ehdr elf_header;
00181 static Elf_Internal_Shdr *section_headers;
00182 static Elf_Internal_Phdr *program_headers;
00183 static Elf_Internal_Dyn *dynamic_section;
00184 static Elf_Internal_Shdr *symtab_shndx_hdr;
00185 static int show_name;
00186 static int do_dynamic;
00187 static int do_syms;
00188 static int do_reloc;
00189 static int do_sections;
00190 static int do_section_groups;
00191 static int do_section_details;
00192 static int do_segments;
00193 static int do_unwind;
00194 static int do_using_dynamic;
00195 static int do_header;
00196 static int do_dump;
00197 static int do_version;
00198 static int do_wide;
00199 static int do_histogram;
00200 static int do_debugging;
00201 static int do_arch;
00202 static int do_notes;
00203 static int is_32bit_elf;
00204 
00205 struct group_list
00206 {
00207   struct group_list *next;
00208   unsigned int section_index;
00209 };
00210 
00211 struct group
00212 {
00213   struct group_list *root;
00214   unsigned int group_index;
00215 };
00216 
00217 static size_t group_count;
00218 static struct group *section_groups;
00219 static struct group **section_headers_groups;
00220 
00221 /* A linked list of the section names for which dumps were requested
00222    by name.  */
00223 struct dump_list_entry
00224 {
00225   char *name;
00226   int type;
00227   struct dump_list_entry *next;
00228 };
00229 static struct dump_list_entry *dump_sects_byname;
00230 
00231 /* A dynamic array of flags indicating for which sections a hex dump
00232    has been requested (via the -x switch) and/or a disassembly dump
00233    (via the -i switch).  */
00234 char *cmdline_dump_sects = NULL;
00235 unsigned num_cmdline_dump_sects = 0;
00236 
00237 /* A dynamic array of flags indicating for which sections a dump of
00238    some kind has been requested.  It is reset on a per-object file
00239    basis and then initialised from the cmdline_dump_sects array,
00240    the results of interpreting the -w switch, and the
00241    dump_sects_byname list.  */
00242 char *dump_sects = NULL;
00243 unsigned int num_dump_sects = 0;
00244 
00245 #define HEX_DUMP     (1 << 0)
00246 #define DISASS_DUMP  (1 << 1)
00247 #define DEBUG_DUMP   (1 << 2)
00248 
00249 /* How to print a vma value.  */
00250 typedef enum print_mode
00251 {
00252   HEX,
00253   DEC,
00254   DEC_5,
00255   UNSIGNED,
00256   PREFIX_HEX,
00257   FULL_HEX,
00258   LONG_HEX
00259 }
00260 print_mode;
00261 
00262 static void (*byte_put) (unsigned char *, bfd_vma, int);
00263 
00264 #define UNKNOWN -1
00265 
00266 #define SECTION_NAME(X)     \
00267   ((X) == NULL ? "<none>" \
00268   : string_table == NULL ? "<no-name>" \
00269   : ((X)->sh_name >= string_table_length ? "<corrupt>" \
00270   : string_table + (X)->sh_name))
00271 
00272 /* Given st_shndx I, map to section_headers index.  */
00273 #define SECTION_HEADER_INDEX(I)                         \
00274   ((I) < SHN_LORESERVE                                  \
00275    ? (I)                                         \
00276    : ((I) <= SHN_HIRESERVE                       \
00277       ? 0                                        \
00278       : (I) - (SHN_HIRESERVE + 1 - SHN_LORESERVE)))
00279 
00280 /* Reverse of the above.  */
00281 #define SECTION_HEADER_NUM(N)                           \
00282   ((N) < SHN_LORESERVE                                  \
00283    ? (N)                                         \
00284    : (N) + (SHN_HIRESERVE + 1 - SHN_LORESERVE))
00285 
00286 #define SECTION_HEADER(I) (section_headers + SECTION_HEADER_INDEX (I))
00287 
00288 #define DT_VERSIONTAGIDX(tag)      (DT_VERNEEDNUM - (tag))     /* Reverse order!  */
00289 
00290 #define BYTE_GET(field)     byte_get (field, sizeof (field))
00291 
00292 #define NUM_ELEM(array)     (sizeof (array) / sizeof ((array)[0]))
00293 
00294 #define GET_ELF_SYMBOLS(file, section)                  \
00295   (is_32bit_elf ? get_32bit_elf_symbols (file, section) \
00296    : get_64bit_elf_symbols (file, section))
00297 
00298 #define VALID_DYNAMIC_NAME(offset) ((dynamic_strings != NULL) && (offset < dynamic_strings_length))
00299 /* GET_DYNAMIC_NAME asssumes that VALID_DYNAMIC_NAME has
00300    already been called and verified that the string exists.  */
00301 #define GET_DYNAMIC_NAME(offset)   (dynamic_strings + offset)
00302 
00303 /* This is just a bit of syntatic sugar.  */
00304 #define streq(a,b)   (strcmp ((a), (b)) == 0)
00305 #define strneq(a,b,n)       (strncmp ((a), (b), (n)) == 0)
00306 #define const_strneq(a,b) (strncmp ((a), (b), sizeof (b) - 1) == 0)
00307 
00308 static void *
00309 get_data (void *var, FILE *file, long offset, size_t size, size_t nmemb,
00310          const char *reason)
00311 {
00312   void *mvar;
00313 
00314   if (size == 0 || nmemb == 0)
00315     return NULL;
00316 
00317   if (fseek (file, archive_file_offset + offset, SEEK_SET))
00318     {
00319       error (_("Unable to seek to 0x%lx for %s\n"),
00320             archive_file_offset + offset, reason);
00321       return NULL;
00322     }
00323 
00324   mvar = var;
00325   if (mvar == NULL)
00326     {
00327       /* Check for overflow.  */
00328       if (nmemb < (~(size_t) 0 - 1) / size)
00329        /* + 1 so that we can '\0' terminate invalid string table sections.  */
00330        mvar = malloc (size * nmemb + 1);
00331 
00332       if (mvar == NULL)
00333        {
00334          error (_("Out of memory allocating 0x%lx bytes for %s\n"),
00335                (unsigned long)(size * nmemb), reason);
00336          return NULL;
00337        }
00338 
00339       ((char *) mvar)[size * nmemb] = '\0';
00340     }
00341 
00342   if (fread (mvar, size, nmemb, file) != nmemb)
00343     {
00344       error (_("Unable to read in 0x%lx bytes of %s\n"),
00345             (unsigned long)(size * nmemb), reason);
00346       if (mvar != var)
00347        free (mvar);
00348       return NULL;
00349     }
00350 
00351   return mvar;
00352 }
00353 
00354 static void
00355 byte_put_little_endian (unsigned char *field, bfd_vma value, int size)
00356 {
00357   switch (size)
00358     {
00359     case 8:
00360       field[7] = (((value >> 24) >> 24) >> 8) & 0xff;
00361       field[6] = ((value >> 24) >> 24) & 0xff;
00362       field[5] = ((value >> 24) >> 16) & 0xff;
00363       field[4] = ((value >> 24) >> 8) & 0xff;
00364       /* Fall through.  */
00365     case 4:
00366       field[3] = (value >> 24) & 0xff;
00367       field[2] = (value >> 16) & 0xff;
00368       /* Fall through.  */
00369     case 2:
00370       field[1] = (value >> 8) & 0xff;
00371       /* Fall through.  */
00372     case 1:
00373       field[0] = value & 0xff;
00374       break;
00375 
00376     default:
00377       error (_("Unhandled data length: %d\n"), size);
00378       abort ();
00379     }
00380 }
00381 
00382 #if defined BFD64 && !BFD_HOST_64BIT_LONG
00383 static int
00384 print_dec_vma (bfd_vma vma, int is_signed)
00385 {
00386   char buf[40];
00387   char *bufp = buf;
00388   int nc = 0;
00389 
00390   if (is_signed && (bfd_signed_vma) vma < 0)
00391     {
00392       vma = -vma;
00393       putchar ('-');
00394       nc = 1;
00395     }
00396 
00397   do
00398     {
00399       *bufp++ = '0' + vma % 10;
00400       vma /= 10;
00401     }
00402   while (vma != 0);
00403   nc += bufp - buf;
00404 
00405   while (bufp > buf)
00406     putchar (*--bufp);
00407   return nc;
00408 }
00409 
00410 static int
00411 print_hex_vma (bfd_vma vma)
00412 {
00413   char buf[32];
00414   char *bufp = buf;
00415   int nc;
00416 
00417   do
00418     {
00419       char digit = '0' + (vma & 0x0f);
00420       if (digit > '9')
00421        digit += 'a' - '0' - 10;
00422       *bufp++ = digit;
00423       vma >>= 4;
00424     }
00425   while (vma != 0);
00426   nc = bufp - buf;
00427 
00428   while (bufp > buf)
00429     putchar (*--bufp);
00430   return nc;
00431 }
00432 #endif
00433 
00434 /* Print a VMA value.  */
00435 static int
00436 print_vma (bfd_vma vma, print_mode mode)
00437 {
00438 #ifdef BFD64
00439   if (is_32bit_elf)
00440 #endif
00441     {
00442       switch (mode)
00443        {
00444        case FULL_HEX:
00445          return printf ("0x%8.8lx", (unsigned long) vma);
00446 
00447        case LONG_HEX:
00448          return printf ("%8.8lx", (unsigned long) vma);
00449 
00450        case DEC_5:
00451          if (vma <= 99999)
00452            return printf ("%5ld", (long) vma);
00453          /* Drop through.  */
00454 
00455        case PREFIX_HEX:
00456          return printf ("0x%lx", (unsigned long) vma);
00457 
00458        case HEX:
00459          return printf ("%lx", (unsigned long) vma);
00460 
00461        case DEC:
00462          return printf ("%ld", (unsigned long) vma);
00463 
00464        case UNSIGNED:
00465          return printf ("%lu", (unsigned long) vma);
00466        }
00467     }
00468 #ifdef BFD64
00469   else
00470     {
00471       int nc = 0;
00472 
00473       switch (mode)
00474        {
00475        case FULL_HEX:
00476          nc = printf ("0x");
00477          /* Drop through.  */
00478 
00479        case LONG_HEX:
00480          printf_vma (vma);
00481          return nc + 16;
00482 
00483        case PREFIX_HEX:
00484          nc = printf ("0x");
00485          /* Drop through.  */
00486 
00487        case HEX:
00488 #if BFD_HOST_64BIT_LONG
00489          return nc + printf ("%lx", vma);
00490 #else
00491          return nc + print_hex_vma (vma);
00492 #endif
00493 
00494        case DEC:
00495 #if BFD_HOST_64BIT_LONG
00496          return printf ("%ld", vma);
00497 #else
00498          return print_dec_vma (vma, 1);
00499 #endif
00500 
00501        case DEC_5:
00502 #if BFD_HOST_64BIT_LONG
00503          if (vma <= 99999)
00504            return printf ("%5ld", vma);
00505          else
00506            return printf ("%#lx", vma);
00507 #else
00508          if (vma <= 99999)
00509            return printf ("%5ld", _bfd_int64_low (vma));
00510          else
00511            return print_hex_vma (vma);
00512 #endif
00513 
00514        case UNSIGNED:
00515 #if BFD_HOST_64BIT_LONG
00516          return printf ("%lu", vma);
00517 #else
00518          return print_dec_vma (vma, 0);
00519 #endif
00520        }
00521     }
00522 #endif
00523   return 0;
00524 }
00525 
00526 /* Display a symbol on stdout.  If do_wide is not true then
00527    format the symbol to be at most WIDTH characters,
00528    truncating as necessary.  If WIDTH is negative then
00529    format the string to be exactly - WIDTH characters,
00530    truncating or padding as necessary.  */
00531 
00532 static void
00533 print_symbol (int width, const char *symbol)
00534 {
00535   if (do_wide)
00536     printf ("%s", symbol);
00537   else if (width < 0)
00538     printf ("%-*.*s", width, width, symbol);
00539   else
00540     printf ("%-.*s", width, symbol);
00541 }
00542 
00543 static void
00544 byte_put_big_endian (unsigned char *field, bfd_vma value, int size)
00545 {
00546   switch (size)
00547     {
00548     case 8:
00549       field[7] = value & 0xff;
00550       field[6] = (value >> 8) & 0xff;
00551       field[5] = (value >> 16) & 0xff;
00552       field[4] = (value >> 24) & 0xff;
00553       value >>= 16;
00554       value >>= 16;
00555       /* Fall through.  */
00556     case 4:
00557       field[3] = value & 0xff;
00558       field[2] = (value >> 8) & 0xff;
00559       value >>= 16;
00560       /* Fall through.  */
00561     case 2:
00562       field[1] = value & 0xff;
00563       value >>= 8;
00564       /* Fall through.  */
00565     case 1:
00566       field[0] = value & 0xff;
00567       break;
00568 
00569     default:
00570       error (_("Unhandled data length: %d\n"), size);
00571       abort ();
00572     }
00573 }
00574 
00575 /* Return a pointer to section NAME, or NULL if no such section exists.  */
00576 
00577 static Elf_Internal_Shdr *
00578 find_section (const char *name)
00579 {
00580   unsigned int i;
00581 
00582   for (i = 0; i < elf_header.e_shnum; i++)
00583     if (streq (SECTION_NAME (section_headers + i), name))
00584       return section_headers + i;
00585 
00586   return NULL;
00587 }
00588 
00589 /* Guess the relocation size commonly used by the specific machines.  */
00590 
00591 static int
00592 guess_is_rela (unsigned long e_machine)
00593 {
00594   switch (e_machine)
00595     {
00596       /* Targets that use REL relocations.  */
00597     case EM_386:
00598     case EM_486:
00599     case EM_960:
00600     case EM_ARM:
00601     case EM_D10V:
00602     case EM_CYGNUS_D10V:
00603     case EM_DLX:
00604     case EM_MIPS:
00605     case EM_MIPS_RS3_LE:
00606     case EM_CYGNUS_M32R:
00607     case EM_OPENRISC:
00608     case EM_OR32:
00609     case EM_SCORE:
00610       return FALSE;
00611 
00612       /* Targets that use RELA relocations.  */
00613     case EM_68K:
00614     case EM_860:
00615     case EM_ALPHA:
00616     case EM_ALTERA_NIOS2:
00617     case EM_AVR:
00618     case EM_AVR_OLD:
00619     case EM_BLACKFIN:
00620     case EM_CRIS:
00621     case EM_CRX:
00622     case EM_D30V:
00623     case EM_CYGNUS_D30V:
00624     case EM_FR30:
00625     case EM_CYGNUS_FR30:
00626     case EM_CYGNUS_FRV:
00627     case EM_H8S:
00628     case EM_H8_300:
00629     case EM_H8_300H:
00630     case EM_IA_64:
00631     case EM_IP2K:
00632     case EM_IP2K_OLD:
00633     case EM_IQ2000:
00634     case EM_M32C:
00635     case EM_M32R:
00636     case EM_MCORE:
00637     case EM_CYGNUS_MEP:
00638     case EM_MMIX:
00639     case EM_MN10200:
00640     case EM_CYGNUS_MN10200:
00641     case EM_MN10300:
00642     case EM_CYGNUS_MN10300:
00643     case EM_MSP430:
00644     case EM_MSP430_OLD:
00645     case EM_MT:
00646     case EM_NIOS32:
00647     case EM_PPC64:
00648     case EM_PPC:
00649     case EM_S390:
00650     case EM_S390_OLD:
00651     case EM_SH:
00652     case EM_SPARC:
00653     case EM_SPARC32PLUS:
00654     case EM_SPARCV9:
00655     case EM_SPU:
00656     case EM_V850:
00657     case EM_CYGNUS_V850:
00658     case EM_VAX:
00659     case EM_X86_64:
00660     case EM_XSTORMY16:
00661     case EM_XTENSA:
00662     case EM_XTENSA_OLD:
00663       return TRUE;
00664 
00665     case EM_68HC05:
00666     case EM_68HC08:
00667     case EM_68HC11:
00668     case EM_68HC16:
00669     case EM_FX66:
00670     case EM_ME16:
00671     case EM_MMA:
00672     case EM_NCPU:
00673     case EM_NDR1:
00674     case EM_PCP:
00675     case EM_ST100:
00676     case EM_ST19:
00677     case EM_ST7:
00678     case EM_ST9PLUS:
00679     case EM_STARCORE:
00680     case EM_SVX:
00681     case EM_TINYJ:
00682     default:
00683       warn (_("Don't know about relocations on this machine architecture\n"));
00684       return FALSE;
00685     }
00686 }
00687 
00688 static int
00689 slurp_rela_relocs (FILE *file,
00690                  unsigned long rel_offset,
00691                  unsigned long rel_size,
00692                  Elf_Internal_Rela **relasp,
00693                  unsigned long *nrelasp)
00694 {
00695   Elf_Internal_Rela *relas;
00696   unsigned long nrelas;
00697   unsigned int i;
00698 
00699   if (is_32bit_elf)
00700     {
00701       Elf32_External_Rela *erelas;
00702 
00703       erelas = get_data (NULL, file, rel_offset, 1, rel_size, _("relocs"));
00704       if (!erelas)
00705        return 0;
00706 
00707       nrelas = rel_size / sizeof (Elf32_External_Rela);
00708 
00709       relas = cmalloc (nrelas, sizeof (Elf_Internal_Rela));
00710 
00711       if (relas == NULL)
00712        {
00713          free (erelas);
00714          error (_("out of memory parsing relocs\n"));
00715          return 0;
00716        }
00717 
00718       for (i = 0; i < nrelas; i++)
00719        {
00720          relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
00721          relas[i].r_info   = BYTE_GET (erelas[i].r_info);
00722          relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
00723        }
00724 
00725       free (erelas);
00726     }
00727   else
00728     {
00729       Elf64_External_Rela *erelas;
00730 
00731       erelas = get_data (NULL, file, rel_offset, 1, rel_size, _("relocs"));
00732       if (!erelas)
00733        return 0;
00734 
00735       nrelas = rel_size / sizeof (Elf64_External_Rela);
00736 
00737       relas = cmalloc (nrelas, sizeof (Elf_Internal_Rela));
00738 
00739       if (relas == NULL)
00740        {
00741          free (erelas);
00742          error (_("out of memory parsing relocs\n"));
00743          return 0;
00744        }
00745 
00746       for (i = 0; i < nrelas; i++)
00747        {
00748          relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
00749          relas[i].r_info   = BYTE_GET (erelas[i].r_info);
00750          relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
00751        }
00752 
00753       free (erelas);
00754     }
00755   *relasp = relas;
00756   *nrelasp = nrelas;
00757   return 1;
00758 }
00759 
00760 static int
00761 slurp_rel_relocs (FILE *file,
00762                 unsigned long rel_offset,
00763                 unsigned long rel_size,
00764                 Elf_Internal_Rela **relsp,
00765                 unsigned long *nrelsp)
00766 {
00767   Elf_Internal_Rela *rels;
00768   unsigned long nrels;
00769   unsigned int i;
00770 
00771   if (is_32bit_elf)
00772     {
00773       Elf32_External_Rel *erels;
00774 
00775       erels = get_data (NULL, file, rel_offset, 1, rel_size, _("relocs"));
00776       if (!erels)
00777        return 0;
00778 
00779       nrels = rel_size / sizeof (Elf32_External_Rel);
00780 
00781       rels = cmalloc (nrels, sizeof (Elf_Internal_Rela));
00782 
00783       if (rels == NULL)
00784        {
00785          free (erels);
00786          error (_("out of memory parsing relocs\n"));
00787          return 0;
00788        }
00789 
00790       for (i = 0; i < nrels; i++)
00791        {
00792          rels[i].r_offset = BYTE_GET (erels[i].r_offset);
00793          rels[i].r_info   = BYTE_GET (erels[i].r_info);
00794          rels[i].r_addend = 0;
00795        }
00796 
00797       free (erels);
00798     }
00799   else
00800     {
00801       Elf64_External_Rel *erels;
00802 
00803       erels = get_data (NULL, file, rel_offset, 1, rel_size, _("relocs"));
00804       if (!erels)
00805        return 0;
00806 
00807       nrels = rel_size / sizeof (Elf64_External_Rel);
00808 
00809       rels = cmalloc (nrels, sizeof (Elf_Internal_Rela));
00810 
00811       if (rels == NULL)
00812        {
00813          free (erels);
00814          error (_("out of memory parsing relocs\n"));
00815          return 0;
00816        }
00817 
00818       for (i = 0; i < nrels; i++)
00819        {
00820          rels[i].r_offset = BYTE_GET (erels[i].r_offset);
00821          rels[i].r_info   = BYTE_GET (erels[i].r_info);
00822          rels[i].r_addend = 0;
00823        }
00824 
00825       free (erels);
00826     }
00827   *relsp = rels;
00828   *nrelsp = nrels;
00829   return 1;
00830 }
00831 
00832 /* Display the contents of the relocation data found at the specified
00833    offset.  */
00834 
00835 static int
00836 dump_relocations (FILE *file,
00837                 unsigned long rel_offset,
00838                 unsigned long rel_size,
00839                 Elf_Internal_Sym *symtab,
00840                 unsigned long nsyms,
00841                 char *strtab,
00842                 unsigned long strtablen,
00843                 int is_rela)
00844 {
00845   unsigned int i;
00846   Elf_Internal_Rela *rels;
00847 
00848 
00849   if (is_rela == UNKNOWN)
00850     is_rela = guess_is_rela (elf_header.e_machine);
00851 
00852   if (is_rela)
00853     {
00854       if (!slurp_rela_relocs (file, rel_offset, rel_size, &rels, &rel_size))
00855        return 0;
00856     }
00857   else
00858     {
00859       if (!slurp_rel_relocs (file, rel_offset, rel_size, &rels, &rel_size))
00860        return 0;
00861     }
00862 
00863   if (is_32bit_elf)
00864     {
00865       if (is_rela)
00866        {
00867          if (do_wide)
00868            printf (_(" Offset     Info    Type                Sym. Value  Symbol's Name + Addend\n"));
00869          else
00870            printf (_(" Offset     Info    Type            Sym.Value  Sym. Name + Addend\n"));
00871        }
00872       else
00873        {
00874          if (do_wide)
00875            printf (_(" Offset     Info    Type                Sym. Value  Symbol's Name\n"));
00876          else
00877            printf (_(" Offset     Info    Type            Sym.Value  Sym. Name\n"));
00878        }
00879     }
00880   else
00881     {
00882       if (is_rela)
00883        {
00884          if (do_wide)
00885            printf (_("    Offset             Info             Type               Symbol's Value  Symbol's Name + Addend\n"));
00886          else
00887            printf (_("  Offset          Info           Type           Sym. Value    Sym. Name + Addend\n"));
00888        }
00889       else
00890        {
00891          if (do_wide)
00892            printf (_("    Offset             Info             Type               Symbol's Value  Symbol's Name\n"));
00893          else
00894            printf (_("  Offset          Info           Type           Sym. Value    Sym. Name\n"));
00895        }
00896     }
00897 
00898   for (i = 0; i < rel_size; i++)
00899     {
00900       const char *rtype;
00901       const char *rtype2 = NULL;
00902       const char *rtype3 = NULL;
00903       bfd_vma offset;
00904       bfd_vma info;
00905       bfd_vma symtab_index;
00906       bfd_vma type;
00907       bfd_vma type2 = 0;
00908       bfd_vma type3 = 0;
00909 
00910       offset = rels[i].r_offset;
00911       info   = rels[i].r_info;
00912 
00913       if (is_32bit_elf)
00914        {
00915          type         = ELF32_R_TYPE (info);
00916          symtab_index = ELF32_R_SYM  (info);
00917        }
00918       else
00919        {
00920          /* The #ifdef BFD64 below is to prevent a compile time warning.
00921             We know that if we do not have a 64 bit data type that we
00922             will never execute this code anyway.  */
00923 #ifdef BFD64
00924          if (elf_header.e_machine == EM_MIPS)
00925            {
00926              /* In little-endian objects, r_info isn't really a 64-bit
00927                little-endian value: it has a 32-bit little-endian
00928                symbol index followed by four individual byte fields.
00929                Reorder INFO accordingly.  */
00930              if (elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
00931               info = (((info & 0xffffffff) << 32)
00932                      | ((info >> 56) & 0xff)
00933                      | ((info >> 40) & 0xff00)
00934                      | ((info >> 24) & 0xff0000)
00935                      | ((info >> 8) & 0xff000000));
00936              type  = ELF64_MIPS_R_TYPE (info);
00937              type2 = ELF64_MIPS_R_TYPE2 (info);
00938              type3 = ELF64_MIPS_R_TYPE3 (info);
00939            }
00940          else if (elf_header.e_machine == EM_SPARCV9)
00941            type = ELF64_R_TYPE_ID (info);
00942          else
00943            type = ELF64_R_TYPE (info);
00944 
00945          symtab_index = ELF64_R_SYM  (info);
00946 #endif
00947        }
00948 
00949       if (is_32bit_elf)
00950        {
00951 #ifdef _bfd_int64_low
00952          printf ("%8.8lx  %8.8lx ", _bfd_int64_low (offset), _bfd_int64_low (info));
00953 #else
00954          printf ("%8.8lx  %8.8lx ", offset, info);
00955 #endif
00956        }
00957       else
00958        {
00959 #ifdef _bfd_int64_low
00960          printf (do_wide
00961                 ? "%8.8lx%8.8lx  %8.8lx%8.8lx "
00962                 : "%4.4lx%8.8lx  %4.4lx%8.8lx ",
00963                 _bfd_int64_high (offset),
00964                 _bfd_int64_low (offset),
00965                 _bfd_int64_high (info),
00966                 _bfd_int64_low (info));
00967 #else
00968          printf (do_wide
00969                 ? "%16.16lx  %16.16lx "
00970                 : "%12.12lx  %12.12lx ",
00971                 offset, info);
00972 #endif
00973        }
00974 
00975       switch (elf_header.e_machine)
00976        {
00977        default:
00978          rtype = NULL;
00979          break;
00980 
00981        case EM_M32R:
00982        case EM_CYGNUS_M32R:
00983          rtype = elf_m32r_reloc_type (type);
00984          break;
00985 
00986        case EM_386:
00987        case EM_486:
00988          rtype = elf_i386_reloc_type (type);
00989          break;
00990 
00991        case EM_68HC11:
00992        case EM_68HC12:
00993          rtype = elf_m68hc11_reloc_type (type);
00994          break;
00995 
00996        case EM_68K:
00997          rtype = elf_m68k_reloc_type (type);
00998          break;
00999 
01000        case EM_960:
01001          rtype = elf_i960_reloc_type (type);
01002          break;
01003 
01004        case EM_AVR:
01005        case EM_AVR_OLD:
01006          rtype = elf_avr_reloc_type (type);
01007          break;
01008 
01009        case EM_OLD_SPARCV9:
01010        case EM_SPARC32PLUS:
01011        case EM_SPARCV9:
01012        case EM_SPARC:
01013          rtype = elf_sparc_reloc_type (type);
01014          break;
01015 
01016        case EM_SPU:
01017          rtype = elf_spu_reloc_type (type);
01018          break;
01019 
01020        case EM_V850:
01021        case EM_CYGNUS_V850:
01022          rtype = v850_reloc_type (type);
01023          break;
01024 
01025        case EM_D10V:
01026        case EM_CYGNUS_D10V:
01027          rtype = elf_d10v_reloc_type (type);
01028          break;
01029 
01030        case EM_D30V:
01031        case EM_CYGNUS_D30V:
01032          rtype = elf_d30v_reloc_type (type);
01033          break;
01034 
01035        case EM_DLX:
01036          rtype = elf_dlx_reloc_type (type);
01037          break;
01038 
01039        case EM_SH:
01040          rtype = elf_sh_reloc_type (type);
01041          break;
01042 
01043        case EM_MN10300:
01044        case EM_CYGNUS_MN10300:
01045          rtype = elf_mn10300_reloc_type (type);
01046          break;
01047 
01048        case EM_MN10200:
01049        case EM_CYGNUS_MN10200:
01050          rtype = elf_mn10200_reloc_type (type);
01051          break;
01052 
01053        case EM_FR30:
01054        case EM_CYGNUS_FR30:
01055          rtype = elf_fr30_reloc_type (type);
01056          break;
01057 
01058        case EM_CYGNUS_FRV:
01059          rtype = elf_frv_reloc_type (type);
01060          break;
01061 
01062        case EM_MCORE:
01063          rtype = elf_mcore_reloc_type (type);
01064          break;
01065 
01066        case EM_MMIX:
01067          rtype = elf_mmix_reloc_type (type);
01068          break;
01069 
01070        case EM_MSP430:
01071        case EM_MSP430_OLD:
01072          rtype = elf_msp430_reloc_type (type);
01073          break;
01074 
01075        case EM_PPC:
01076          rtype = elf_ppc_reloc_type (type);
01077          break;
01078 
01079        case EM_PPC64:
01080          rtype = elf_ppc64_reloc_type (type);
01081          break;
01082 
01083        case EM_MIPS:
01084        case EM_MIPS_RS3_LE:
01085          rtype = elf_mips_reloc_type (type);
01086          if (!is_32bit_elf)
01087            {
01088              rtype2 = elf_mips_reloc_type (type2);
01089              rtype3 = elf_mips_reloc_type (type3);
01090            }
01091          break;
01092 
01093        case EM_ALPHA:
01094          rtype = elf_alpha_reloc_type (type);
01095          break;
01096 
01097        case EM_ARM:
01098          rtype = elf_arm_reloc_type (type);
01099          break;
01100 
01101        case EM_ARC:
01102          rtype = elf_arc_reloc_type (type);
01103          break;
01104 
01105        case EM_PARISC:
01106          rtype = elf_hppa_reloc_type (type);
01107          break;
01108 
01109        case EM_H8_300:
01110        case EM_H8_300H:
01111        case EM_H8S:
01112          rtype = elf_h8_reloc_type (type);
01113          break;
01114 
01115        case EM_OPENRISC:
01116        case EM_OR32:
01117          rtype = elf_or32_reloc_type (type);
01118          break;
01119 
01120        case EM_PJ:
01121        case EM_PJ_OLD:
01122          rtype = elf_pj_reloc_type (type);
01123          break;
01124        case EM_IA_64:
01125          rtype = elf_ia64_reloc_type (type);
01126          break;
01127 
01128        case EM_CRIS:
01129          rtype = elf_cris_reloc_type (type);
01130          break;
01131 
01132        case EM_860:
01133          rtype = elf_i860_reloc_type (type);
01134          break;
01135 
01136        case EM_X86_64:
01137          rtype = elf_x86_64_reloc_type (type);
01138          break;
01139 
01140        case EM_S370:
01141          rtype = i370_reloc_type (type);
01142          break;
01143 
01144        case EM_S390_OLD:
01145        case EM_S390:
01146          rtype = elf_s390_reloc_type (type);
01147          break;
01148 
01149        case EM_SCORE:
01150          rtype = elf_score_reloc_type (type);
01151          break;
01152 
01153        case EM_XSTORMY16:
01154          rtype = elf_xstormy16_reloc_type (type);
01155          break;
01156 
01157        case EM_CRX:
01158          rtype = elf_crx_reloc_type (type);
01159          break;
01160 
01161        case EM_VAX:
01162          rtype = elf_vax_reloc_type (type);
01163          break;
01164 
01165        case EM_IP2K:
01166        case EM_IP2K_OLD:
01167          rtype = elf_ip2k_reloc_type (type);
01168          break;
01169 
01170        case EM_IQ2000:
01171          rtype = elf_iq2000_reloc_type (type);
01172          break;
01173 
01174        case EM_XTENSA_OLD:
01175        case EM_XTENSA:
01176          rtype = elf_xtensa_reloc_type (type);
01177          break;
01178 
01179        case EM_M32C:
01180          rtype = elf_m32c_reloc_type (type);
01181          break;
01182 
01183        case EM_MT:
01184          rtype = elf_mt_reloc_type (type);
01185          break;
01186 
01187        case EM_BLACKFIN:
01188          rtype = elf_bfin_reloc_type (type);
01189          break;
01190 
01191        case EM_CYGNUS_MEP:
01192          rtype = elf_mep_reloc_type (type);
01193          break;
01194        }
01195 
01196       if (rtype == NULL)
01197 #ifdef _bfd_int64_low
01198        printf (_("unrecognized: %-7lx"), _bfd_int64_low (type));
01199 #else
01200        printf (_("unrecognized: %-7lx"), type);
01201 #endif
01202       else
01203        printf (do_wide ? "%-22.22s" : "%-17.17s", rtype);
01204 
01205       if (elf_header.e_machine == EM_ALPHA
01206          && rtype != NULL
01207          && streq (rtype, "R_ALPHA_LITUSE")
01208          && is_rela)
01209        {
01210          switch (rels[i].r_addend)
01211            {
01212            case LITUSE_ALPHA_ADDR:   rtype = "ADDR";   break;
01213            case LITUSE_ALPHA_BASE:   rtype = "BASE";   break;
01214            case LITUSE_ALPHA_BYTOFF: rtype = "BYTOFF"; break;
01215            case LITUSE_ALPHA_JSR:    rtype = "JSR";    break;
01216            case LITUSE_ALPHA_TLSGD:  rtype = "TLSGD";  break;
01217            case LITUSE_ALPHA_TLSLDM: rtype = "TLSLDM"; break;
01218            case LITUSE_ALPHA_JSRDIRECT: rtype = "JSRDIRECT"; break;
01219            default: rtype = NULL;
01220            }
01221          if (rtype)
01222            printf (" (%s)", rtype);
01223          else
01224            {
01225              putchar (' ');
01226              printf (_("<unknown addend: %lx>"),
01227                     (unsigned long) rels[i].r_addend);
01228            }
01229        }
01230       else if (symtab_index)
01231        {
01232          if (symtab == NULL || symtab_index >= nsyms)
01233            printf (" bad symbol index: %08lx", (unsigned long) symtab_index);
01234          else
01235            {
01236              Elf_Internal_Sym *psym;
01237 
01238              psym = symtab + symtab_index;
01239 
01240              printf (" ");
01241              print_vma (psym->st_value, LONG_HEX);
01242              printf (is_32bit_elf ? "   " : " ");
01243 
01244              if (psym->st_name == 0)
01245               {
01246                 const char *sec_name = "<null>";
01247                 char name_buf[40];
01248 
01249                 if (ELF_ST_TYPE (psym->st_info) == STT_SECTION)
01250                   {
01251                     bfd_vma sec_index = (bfd_vma) -1;
01252 
01253                     if (psym->st_shndx < SHN_LORESERVE)
01254                      sec_index = psym->st_shndx;
01255                     else if (psym->st_shndx > SHN_HIRESERVE)
01256                      sec_index = psym->st_shndx - (SHN_HIRESERVE + 1
01257                                                 - SHN_LORESERVE);
01258 
01259                     if (sec_index != (bfd_vma) -1)
01260                      sec_name = SECTION_NAME (section_headers + sec_index);
01261                     else if (psym->st_shndx == SHN_ABS)
01262                      sec_name = "ABS";
01263                     else if (psym->st_shndx == SHN_COMMON)
01264                      sec_name = "COMMON";
01265                     else if (elf_header.e_machine == EM_MIPS
01266                             && psym->st_shndx == SHN_MIPS_SCOMMON)
01267                      sec_name = "SCOMMON";
01268                     else if (elf_header.e_machine == EM_MIPS
01269                             && psym->st_shndx == SHN_MIPS_SUNDEFINED)
01270                      sec_name = "SUNDEF";
01271                     else if (elf_header.e_machine == EM_X86_64
01272                             && psym->st_shndx == SHN_X86_64_LCOMMON)
01273                      sec_name = "LARGE_COMMON";
01274                     else if (elf_header.e_machine == EM_IA_64
01275                             && elf_header.e_ident[EI_OSABI] == ELFOSABI_HPUX
01276                             && psym->st_shndx == SHN_IA_64_ANSI_COMMON)
01277                      sec_name = "ANSI_COM";
01278                     else
01279                      {
01280                        sprintf (name_buf, "<section 0x%x>",
01281                                (unsigned int) psym->st_shndx);
01282                        sec_name = name_buf;
01283                      }
01284                   }
01285                 print_symbol (22, sec_name);
01286               }
01287              else if (strtab == NULL)
01288               printf (_("<string table index: %3ld>"), psym->st_name);
01289              else if (psym->st_name >= strtablen)
01290               printf (_("<corrupt string table index: %3ld>"), psym->st_name);
01291              else
01292               print_symbol (22, strtab + psym->st_name);
01293 
01294              if (is_rela)
01295               printf (" + %lx", (unsigned long) rels[i].r_addend);
01296            }
01297        }
01298       else if (is_rela)
01299        {
01300          printf ("%*c", is_32bit_elf ?
01301                 (do_wide ? 34 : 28) : (do_wide ? 26 : 20), ' ');
01302          print_vma (rels[i].r_addend, LONG_HEX);
01303        }
01304 
01305       if (elf_header.e_machine == EM_SPARCV9
01306          && rtype != NULL
01307          && streq (rtype, "R_SPARC_OLO10"))
01308        printf (" + %lx", (unsigned long) ELF64_R_TYPE_DATA (info));
01309 
01310       putchar ('\n');
01311 
01312       if (! is_32bit_elf && elf_header.e_machine == EM_MIPS)
01313        {
01314          printf ("                    Type2: ");
01315 
01316          if (rtype2 == NULL)
01317 #ifdef _bfd_int64_low
01318            printf (_("unrecognized: %-7lx"), _bfd_int64_low (type2));
01319 #else
01320            printf (_("unrecognized: %-7lx"), type2);
01321 #endif
01322          else
01323            printf ("%-17.17s", rtype2);
01324 
01325          printf ("\n                    Type3: ");
01326 
01327          if (rtype3 == NULL)
01328 #ifdef _bfd_int64_low
01329            printf (_("unrecognized: %-7lx"), _bfd_int64_low (type3));
01330 #else
01331            printf (_("unrecognized: %-7lx"), type3);
01332 #endif
01333          else
01334            printf ("%-17.17s", rtype3);
01335 
01336          putchar ('\n');
01337        }
01338     }
01339 
01340   free (rels);
01341 
01342   return 1;
01343 }
01344 
01345 static const char *
01346 get_mips_dynamic_type (unsigned long type)
01347 {
01348   switch (type)
01349     {
01350     case DT_MIPS_RLD_VERSION: return "MIPS_RLD_VERSION";
01351     case DT_MIPS_TIME_STAMP: return "MIPS_TIME_STAMP";
01352     case DT_MIPS_ICHECKSUM: return "MIPS_ICHECKSUM";
01353     case DT_MIPS_IVERSION: return "MIPS_IVERSION";
01354     case DT_MIPS_FLAGS: return "MIPS_FLAGS";
01355     case DT_MIPS_BASE_ADDRESS: return "MIPS_BASE_ADDRESS";
01356     case DT_MIPS_MSYM: return "MIPS_MSYM";
01357     case DT_MIPS_CONFLICT: return "MIPS_CONFLICT";
01358     case DT_MIPS_LIBLIST: return "MIPS_LIBLIST";
01359     case DT_MIPS_LOCAL_GOTNO: return "MIPS_LOCAL_GOTNO";
01360     case DT_MIPS_CONFLICTNO: return "MIPS_CONFLICTNO";
01361     case DT_MIPS_LIBLISTNO: return "MIPS_LIBLISTNO";
01362     case DT_MIPS_SYMTABNO: return "MIPS_SYMTABNO";
01363     case DT_MIPS_UNREFEXTNO: return "MIPS_UNREFEXTNO";
01364     case DT_MIPS_GOTSYM: return "MIPS_GOTSYM";
01365     case DT_MIPS_HIPAGENO: return "MIPS_HIPAGENO";
01366     case DT_MIPS_RLD_MAP: return "MIPS_RLD_MAP";
01367     case DT_MIPS_DELTA_CLASS: return "MIPS_DELTA_CLASS";
01368     case DT_MIPS_DELTA_CLASS_NO: return "MIPS_DELTA_CLASS_NO";
01369     case DT_MIPS_DELTA_INSTANCE: return "MIPS_DELTA_INSTANCE";
01370     case DT_MIPS_DELTA_INSTANCE_NO: return "MIPS_DELTA_INSTANCE_NO";
01371     case DT_MIPS_DELTA_RELOC: return "MIPS_DELTA_RELOC";
01372     case DT_MIPS_DELTA_RELOC_NO: return "MIPS_DELTA_RELOC_NO";
01373     case DT_MIPS_DELTA_SYM: return "MIPS_DELTA_SYM";
01374     case DT_MIPS_DELTA_SYM_NO: return "MIPS_DELTA_SYM_NO";
01375     case DT_MIPS_DELTA_CLASSSYM: return "MIPS_DELTA_CLASSSYM";
01376     case DT_MIPS_DELTA_CLASSSYM_NO: return "MIPS_DELTA_CLASSSYM_NO";
01377     case DT_MIPS_CXX_FLAGS: return "MIPS_CXX_FLAGS";
01378     case DT_MIPS_PIXIE_INIT: return "MIPS_PIXIE_INIT";
01379     case DT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB";
01380     case DT_MIPS_LOCALPAGE_GOTIDX: return "MIPS_LOCALPAGE_GOTIDX";
01381     case DT_MIPS_LOCAL_GOTIDX: return "MIPS_LOCAL_GOTIDX";
01382     case DT_MIPS_HIDDEN_GOTIDX: return "MIPS_HIDDEN_GOTIDX";
01383     case DT_MIPS_PROTECTED_GOTIDX: return "MIPS_PROTECTED_GOTIDX";
01384     case DT_MIPS_OPTIONS: return "MIPS_OPTIONS";
01385     case DT_MIPS_INTERFACE: return "MIPS_INTERFACE";
01386     case DT_MIPS_DYNSTR_ALIGN: return "MIPS_DYNSTR_ALIGN";
01387     case DT_MIPS_INTERFACE_SIZE: return "MIPS_INTERFACE_SIZE";
01388     case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: return "MIPS_RLD_TEXT_RESOLVE_ADDR";
01389     case DT_MIPS_PERF_SUFFIX: return "MIPS_PERF_SUFFIX";
01390     case DT_MIPS_COMPACT_SIZE: return "MIPS_COMPACT_SIZE";
01391     case DT_MIPS_GP_VALUE: return "MIPS_GP_VALUE";
01392     case DT_MIPS_AUX_DYNAMIC: return "MIPS_AUX_DYNAMIC";
01393     default:
01394       return NULL;
01395     }
01396 }
01397 
01398 static const char *
01399 get_sparc64_dynamic_type (unsigned long type)
01400 {
01401   switch (type)
01402     {
01403     case DT_SPARC_REGISTER: return "SPARC_REGISTER";
01404     default:
01405       return NULL;
01406     }
01407 }
01408 
01409 static const char *
01410 get_ppc_dynamic_type (unsigned long type)
01411 {
01412   switch (type)
01413     {
01414     case DT_PPC_GOT: return "PPC_GOT";
01415     default:
01416       return NULL;
01417     }
01418 }
01419 
01420 static const char *
01421 get_ppc64_dynamic_type (unsigned long type)
01422 {
01423   switch (type)
01424     {
01425     case DT_PPC64_GLINK: return "PPC64_GLINK";
01426     case DT_PPC64_OPD:   return "PPC64_OPD";
01427     case DT_PPC64_OPDSZ: return "PPC64_OPDSZ";
01428     default:
01429       return NULL;
01430     }
01431 }
01432 
01433 static const char *
01434 get_parisc_dynamic_type (unsigned long type)
01435 {
01436   switch (type)
01437     {
01438     case DT_HP_LOAD_MAP:    return "HP_LOAD_MAP";
01439     case DT_HP_DLD_FLAGS:   return "HP_DLD_FLAGS";
01440     case DT_HP_DLD_HOOK:    return "HP_DLD_HOOK";
01441     case DT_HP_UX10_INIT:   return "HP_UX10_INIT";
01442     case DT_HP_UX10_INITSZ: return "HP_UX10_INITSZ";
01443     case DT_HP_PREINIT:            return "HP_PREINIT";
01444     case DT_HP_PREINITSZ:   return "HP_PREINITSZ";
01445     case DT_HP_NEEDED:             return "HP_NEEDED";
01446     case DT_HP_TIME_STAMP:  return "HP_TIME_STAMP";
01447     case DT_HP_CHECKSUM:    return "HP_CHECKSUM";
01448     case DT_HP_GST_SIZE:    return "HP_GST_SIZE";
01449     case DT_HP_GST_VERSION: return "HP_GST_VERSION";
01450     case DT_HP_GST_HASHVAL: return "HP_GST_HASHVAL";
01451     case DT_HP_EPLTREL:            return "HP_GST_EPLTREL";
01452     case DT_HP_EPLTRELSZ:   return "HP_GST_EPLTRELSZ";
01453     case DT_HP_FILTERED:    return "HP_FILTERED";
01454     case DT_HP_FILTER_TLS:  return "HP_FILTER_TLS";
01455     case DT_HP_COMPAT_FILTERED:    return "HP_COMPAT_FILTERED";
01456     case DT_HP_LAZYLOAD:    return "HP_LAZYLOAD";
01457     case DT_HP_BIND_NOW_COUNT:     return "HP_BIND_NOW_COUNT";
01458     case DT_PLT:            return "PLT";
01459     case DT_PLT_SIZE:              return "PLT_SIZE";
01460     case DT_DLT:            return "DLT";
01461     case DT_DLT_SIZE:              return "DLT_SIZE";
01462     default:
01463       return NULL;
01464     }
01465 }
01466 
01467 static const char *
01468 get_ia64_dynamic_type (unsigned long type)
01469 {
01470   switch (type)
01471     {
01472     case DT_IA_64_PLT_RESERVE: return "IA_64_PLT_RESERVE";
01473     default:
01474       return NULL;
01475     }
01476 }
01477 
01478 static const char *
01479 get_alpha_dynamic_type (unsigned long type)
01480 {
01481   switch (type)
01482     {
01483     case DT_ALPHA_PLTRO: return "ALPHA_PLTRO";
01484     default:
01485       return NULL;
01486     }
01487 }
01488 
01489 static const char *
01490 get_score_dynamic_type (unsigned long type)
01491 {
01492   switch (type)
01493     {
01494     case DT_SCORE_BASE_ADDRESS: return "SCORE_BASE_ADDRESS";
01495     case DT_SCORE_LOCAL_GOTNO:  return "SCORE_LOCAL_GOTNO";
01496     case DT_SCORE_SYMTABNO:     return "SCORE_SYMTABNO";
01497     case DT_SCORE_GOTSYM:       return "SCORE_GOTSYM";
01498     case DT_SCORE_UNREFEXTNO:   return "SCORE_UNREFEXTNO";
01499     case DT_SCORE_HIPAGENO:     return "SCORE_HIPAGENO";
01500     default:
01501       return NULL;
01502     }
01503 }
01504 
01505 
01506 static const char *
01507 get_dynamic_type (unsigned long type)
01508 {
01509   static char buff[64];
01510 
01511   switch (type)
01512     {
01513     case DT_NULL:    return "NULL";
01514     case DT_NEEDED:  return "NEEDED";
01515     case DT_PLTRELSZ:       return "PLTRELSZ";
01516     case DT_PLTGOT:  return "PLTGOT";
01517     case DT_HASH:    return "HASH";
01518     case DT_STRTAB:  return "STRTAB";
01519     case DT_SYMTAB:  return "SYMTAB";
01520     case DT_RELA:    return "RELA";
01521     case DT_RELASZ:  return "RELASZ";
01522     case DT_RELAENT: return "RELAENT";
01523     case DT_STRSZ:   return "STRSZ";
01524     case DT_SYMENT:  return "SYMENT";
01525     case DT_INIT:    return "INIT";
01526     case DT_FINI:    return "FINI";
01527     case DT_SONAME:  return "SONAME";
01528     case DT_RPATH:   return "RPATH";
01529     case DT_SYMBOLIC:       return "SYMBOLIC";
01530     case DT_REL:     return "REL";
01531     case DT_RELSZ:   return "RELSZ";
01532     case DT_RELENT:  return "RELENT";
01533     case DT_PLTREL:  return "PLTREL";
01534     case DT_DEBUG:   return "DEBUG";
01535     case DT_TEXTREL: return "TEXTREL";
01536     case DT_JMPREL:  return "JMPREL";
01537     case DT_BIND_NOW:   return "BIND_NOW";
01538     case DT_INIT_ARRAY: return "INIT_ARRAY";
01539     case DT_FINI_ARRAY: return "FINI_ARRAY";
01540     case DT_INIT_ARRAYSZ: return "INIT_ARRAYSZ";
01541     case DT_FINI_ARRAYSZ: return "FINI_ARRAYSZ";
01542     case DT_RUNPATH:    return "RUNPATH";
01543     case DT_FLAGS:      return "FLAGS";
01544 
01545     case DT_PREINIT_ARRAY: return "PREINIT_ARRAY";
01546     case DT_PREINIT_ARRAYSZ: return "PREINIT_ARRAYSZ";
01547 
01548     case DT_CHECKSUM:       return "CHECKSUM";
01549     case DT_PLTPADSZ:       return "PLTPADSZ";
01550     case DT_MOVEENT: return "MOVEENT";
01551     case DT_MOVESZ:  return "MOVESZ";
01552     case DT_FEATURE: return "FEATURE";
01553     case DT_POSFLAG_1:      return "POSFLAG_1";
01554     case DT_SYMINSZ: return "SYMINSZ";
01555     case DT_SYMINENT:       return "SYMINENT"; /* aka VALRNGHI */
01556 
01557     case DT_ADDRRNGLO:  return "ADDRRNGLO";
01558     case DT_CONFIG:  return "CONFIG";
01559     case DT_DEPAUDIT:       return "DEPAUDIT";
01560     case DT_AUDIT:   return "AUDIT";
01561     case DT_PLTPAD:  return "PLTPAD";
01562     case DT_MOVETAB: return "MOVETAB";
01563     case DT_SYMINFO: return "SYMINFO"; /* aka ADDRRNGHI */
01564 
01565     case DT_VERSYM:  return "VERSYM";
01566 
01567     case DT_TLSDESC_GOT: return "TLSDESC_GOT";
01568     case DT_TLSDESC_PLT: return "TLSDESC_PLT";
01569     case DT_RELACOUNT:      return "RELACOUNT";
01570     case DT_RELCOUNT:       return "RELCOUNT";
01571     case DT_FLAGS_1: return "FLAGS_1";
01572     case DT_VERDEF:  return "VERDEF";
01573     case DT_VERDEFNUM:      return "VERDEFNUM";
01574     case DT_VERNEED: return "VERNEED";
01575     case DT_VERNEEDNUM:     return "VERNEEDNUM";
01576 
01577     case DT_AUXILIARY:      return "AUXILIARY";
01578     case DT_USED:    return "USED";
01579     case DT_FILTER:  return "FILTER";
01580 
01581     case DT_GNU_PRELINKED: return "GNU_PRELINKED";
01582     case DT_GNU_CONFLICT: return "GNU_CONFLICT";
01583     case DT_GNU_CONFLICTSZ: return "GNU_CONFLICTSZ";
01584     case DT_GNU_LIBLIST: return "GNU_LIBLIST";
01585     case DT_GNU_LIBLISTSZ: return "GNU_LIBLISTSZ";
01586     case DT_GNU_HASH:       return "GNU_HASH";
01587 
01588     default:
01589       if ((type >= DT_LOPROC) && (type <= DT_HIPROC))
01590        {
01591          const char *result;
01592 
01593          switch (elf_header.e_machine)
01594            {
01595            case EM_MIPS:
01596            case EM_MIPS_RS3_LE:
01597              result = get_mips_dynamic_type (type);
01598              break;
01599            case EM_SPARCV9:
01600              result = get_sparc64_dynamic_type (type);
01601              break;
01602            case EM_PPC:
01603              result = get_ppc_dynamic_type (type);
01604              break;
01605            case EM_PPC64:
01606              result = get_ppc64_dynamic_type (type);
01607              break;
01608            case EM_IA_64:
01609              result = get_ia64_dynamic_type (type);
01610              break;
01611            case EM_ALPHA:
01612              result = get_alpha_dynamic_type (type);
01613              break;
01614            case EM_SCORE:
01615              result = get_score_dynamic_type (type);
01616              break;
01617            default:
01618              result = NULL;
01619              break;
01620            }
01621 
01622          if (result != NULL)
01623            return result;
01624 
01625          snprintf (buff, sizeof (buff), _("Processor Specific: %lx"), type);
01626        }
01627       else if (((type >= DT_LOOS) && (type <= DT_HIOS))
01628               || (elf_header.e_machine == EM_PARISC
01629                  && (type >= OLD_DT_LOOS) && (type <= OLD_DT_HIOS)))
01630        {
01631          const char *result;
01632 
01633          switch (elf_header.e_machine)
01634            {
01635            case EM_PARISC:
01636              result = get_parisc_dynamic_type (type);
01637              break;
01638            default:
01639              result = NULL;
01640              break;
01641            }
01642 
01643          if (result != NULL)
01644            return result;
01645 
01646          snprintf (buff, sizeof (buff), _("Operating System specific: %lx"),
01647                   type);
01648        }
01649       else
01650        snprintf (buff, sizeof (buff), _("<unknown>: %lx"), type);
01651 
01652       return buff;
01653     }
01654 }
01655 
01656 static char *
01657 get_file_type (unsigned e_type)
01658 {
01659   static char buff[32];
01660 
01661   switch (e_type)
01662     {
01663     case ET_NONE:    return _("NONE (None)");
01664     case ET_REL:     return _("REL (Relocatable file)");
01665     case ET_EXEC:    return _("EXEC (Executable file)");
01666     case ET_DYN:     return _("DYN (Shared object file)");
01667     case ET_CORE:    return _("CORE (Core file)");
01668 
01669     default:
01670       if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC))
01671        snprintf (buff, sizeof (buff), _("Processor Specific: (%x)"), e_type);
01672       else if ((e_type >= ET_LOOS) && (e_type <= ET_HIOS))
01673        snprintf (buff, sizeof (buff), _("OS Specific: (%x)"), e_type);
01674       else
01675        snprintf (buff, sizeof (buff), _("<unknown>: %x"), e_type);
01676       return buff;
01677     }
01678 }
01679 
01680 static char *
01681 get_machine_name (unsigned e_machine)
01682 {
01683   static char buff[64]; /* XXX */
01684 
01685   switch (e_machine)
01686     {
01687     case EM_NONE:           return _("None");
01688     case EM_M32:            return "WE32100";
01689     case EM_SPARC:          return "Sparc";
01690     case EM_SPU:            return "SPU";
01691     case EM_386:            return "Intel 80386";
01692     case EM_68K:            return "MC68000";
01693     case EM_88K:            return "MC88000";
01694     case EM_486:            return "Intel 80486";
01695     case EM_860:            return "Intel 80860";
01696     case EM_MIPS:           return "MIPS R3000";
01697     case EM_S370:           return "IBM System/370";
01698     case EM_MIPS_RS3_LE:    return "MIPS R4000 big-endian";
01699     case EM_OLD_SPARCV9:    return "Sparc v9 (old)";
01700     case EM_PARISC:         return "HPPA";
01701     case EM_PPC_OLD:        return "Power PC (old)";
01702     case EM_SPARC32PLUS:    return "Sparc v8+" ;
01703     case EM_960:            return "Intel 90860";
01704     case EM_PPC:            return "PowerPC";
01705     case EM_PPC64:          return "PowerPC64";
01706     case EM_V800:           return "NEC V800";
01707     case EM_FR20:           return "Fujitsu FR20";
01708     case EM_RH32:           return "TRW RH32";
01709     case EM_MCORE:          return "MCORE";
01710     case EM_ARM:            return "ARM";
01711     case EM_OLD_ALPHA:             return "Digital Alpha (old)";
01712     case EM_SH:                    return "Renesas / SuperH SH";
01713     case EM_SPARCV9:        return "Sparc v9";
01714     case EM_TRICORE:        return "Siemens Tricore";
01715     case EM_ARC:            return "ARC";
01716     case EM_H8_300:         return "Renesas H8/300";
01717     case EM_H8_300H:        return "Renesas H8/300H";
01718     case EM_H8S:            return "Renesas H8S";
01719     case EM_H8_500:         return "Renesas H8/500";
01720     case EM_IA_64:          return "Intel IA-64";
01721     case EM_MIPS_X:         return "Stanford MIPS-X";
01722     case EM_COLDFIRE:              return "Motorola Coldfire";
01723     case EM_68HC12:         return "Motorola M68HC12";
01724     case EM_ALPHA:          return "Alpha";
01725     case EM_CYGNUS_D10V:
01726     case EM_D10V:           return "d10v";
01727     case EM_CYGNUS_D30V:
01728     case EM_D30V:           return "d30v";
01729     case EM_CYGNUS_M32R:
01730     case EM_M32R:           return "Renesas M32R (formerly Mitsubishi M32r)";
01731     case EM_CYGNUS_V850:
01732     case EM_V850:           return "NEC v850";
01733     case EM_CYGNUS_MN10300:
01734     case EM_MN10300:        return "mn10300";
01735     case EM_CYGNUS_MN10200:
01736     case EM_MN10200:        return "mn10200";
01737     case EM_CYGNUS_FR30:
01738     case EM_FR30:           return "Fujitsu FR30";
01739     case EM_CYGNUS_FRV:            return "Fujitsu FR-V";
01740     case EM_PJ_OLD:
01741     case EM_PJ:                    return "picoJava";
01742     case EM_MMA:            return "Fujitsu Multimedia Accelerator";
01743     case EM_PCP:            return "Siemens PCP";
01744     case EM_NCPU:           return "Sony nCPU embedded RISC processor";
01745     case EM_NDR1:           return "Denso NDR1 microprocesspr";
01746     case EM_STARCORE:              return "Motorola Star*Core processor";
01747     case EM_ME16:           return "Toyota ME16 processor";
01748     case EM_ST100:          return "STMicroelectronics ST100 processor";
01749     case EM_TINYJ:          return "Advanced Logic Corp. TinyJ embedded processor";
01750     case EM_FX66:           return "Siemens FX66 microcontroller";
01751     case EM_ST9PLUS:        return "STMicroelectronics ST9+ 8/16 bit microcontroller";
01752     case EM_ST7:            return "STMicroelectronics ST7 8-bit microcontroller";
01753     case EM_68HC16:         return "Motorola MC68HC16 Microcontroller";
01754     case EM_68HC11:         return "Motorola MC68HC11 Microcontroller";
01755     case EM_68HC08:         return "Motorola MC68HC08 Microcontroller";
01756     case EM_68HC05:         return "Motorola MC68HC05 Microcontroller";
01757     case EM_SVX:            return "Silicon Graphics SVx";
01758     case EM_ST19:           return "STMicroelectronics ST19 8-bit microcontroller";
01759     case EM_VAX:            return "Digital VAX";
01760     case EM_AVR_OLD:
01761     case EM_AVR:            return "Atmel AVR 8-bit microcontroller";
01762     case EM_CRIS:           return "Axis Communications 32-bit embedded processor";
01763     case EM_JAVELIN:        return "Infineon Technologies 32-bit embedded cpu";
01764     case EM_FIREPATH:              return "Element 14 64-bit DSP processor";
01765     case EM_ZSP:            return "LSI Logic's 16-bit DSP processor";
01766     case EM_MMIX:           return "Donald Knuth's educational 64-bit processor";
01767     case EM_HUANY:          return "Harvard Universitys's machine-independent object format";
01768     case EM_PRISM:          return "Vitesse Prism";
01769     case EM_X86_64:         return "Advanced Micro Devices X86-64";
01770     case EM_S390_OLD:
01771     case EM_S390:           return "IBM S/390";
01772     case EM_SCORE:          return "SUNPLUS S+Core";
01773     case EM_XSTORMY16:             return "Sanyo Xstormy16 CPU core";
01774     case EM_OPENRISC:
01775     case EM_OR32:           return "OpenRISC";
01776     case EM_CRX:            return "National Semiconductor CRX microprocessor";
01777     case EM_DLX:            return "OpenDLX";
01778     case EM_IP2K_OLD:
01779     case EM_IP2K:           return "Ubicom IP2xxx 8-bit microcontrollers";
01780     case EM_IQ2000:         return "Vitesse IQ2000";
01781     case EM_XTENSA_OLD:
01782     case EM_XTENSA:         return "Tensilica Xtensa Processor";
01783     case EM_M32C:            return "Renesas M32c";
01784     case EM_MT:                 return "Morpho Techologies MT processor";
01785     case EM_BLACKFIN:              return "Analog Devices Blackfin";
01786     case EM_NIOS32:         return "Altera Nios";
01787     case EM_ALTERA_NIOS2:   return "Altera Nios II";
01788     case EM_XC16X:          return "Infineon Technologies xc16x";
01789     case EM_CYGNUS_MEP:         return "Toshiba MeP Media Engine";
01790     default:
01791       snprintf (buff, sizeof (buff), _("<unknown>: 0x%x"), e_machine);
01792       return buff;
01793     }
01794 }
01795 
01796 static void
01797 decode_ARM_machine_flags (unsigned e_flags, char buf[])
01798 {
01799   unsigned eabi;
01800   int unknown = 0;
01801 
01802   eabi = EF_ARM_EABI_VERSION (e_flags);
01803   e_flags &= ~ EF_ARM_EABIMASK;
01804 
01805   /* Handle "generic" ARM flags.  */
01806   if (e_flags & EF_ARM_RELEXEC)
01807     {
01808       strcat (buf, ", relocatable executable");
01809       e_flags &= ~ EF_ARM_RELEXEC;
01810     }
01811 
01812   if (e_flags & EF_ARM_HASENTRY)
01813     {
01814       strcat (buf, ", has entry point");
01815       e_flags &= ~ EF_ARM_HASENTRY;
01816     }
01817 
01818   /* Now handle EABI specific flags.  */
01819   switch (eabi)
01820     {
01821     default:
01822       strcat (buf, ", <unrecognized EABI>");
01823       if (e_flags)
01824        unknown = 1;
01825       break;
01826 
01827     case EF_ARM_EABI_VER1:
01828       strcat (buf, ", Version1 EABI");
01829       while (e_flags)
01830        {
01831          unsigned flag;
01832 
01833          /* Process flags one bit at a time.  */
01834          flag = e_flags & - e_flags;
01835          e_flags &= ~ flag;
01836 
01837          switch (flag)
01838            {
01839            case EF_ARM_SYMSARESORTED: /* Conflicts with EF_ARM_INTERWORK.  */
01840              strcat (buf, ", sorted symbol tables");
01841              break;
01842 
01843            default:
01844              unknown = 1;
01845              break;
01846            }
01847        }
01848       break;
01849 
01850     case EF_ARM_EABI_VER2:
01851       strcat (buf, ", Version2 EABI");
01852       while (e_flags)
01853        {
01854          unsigned flag;
01855 
01856          /* Process flags one bit at a time.  */
01857          flag = e_flags & - e_flags;
01858          e_flags &= ~ flag;
01859 
01860          switch (flag)
01861            {
01862            case EF_ARM_SYMSARESORTED: /* Conflicts with EF_ARM_INTERWORK.  */
01863              strcat (buf, ", sorted symbol tables");
01864              break;
01865 
01866            case EF_ARM_DYNSYMSUSESEGIDX:
01867              strcat (buf, ", dynamic symbols use segment index");
01868              break;
01869 
01870            case EF_ARM_MAPSYMSFIRST:
01871              strcat (buf, ", mapping symbols precede others");
01872              break;
01873 
01874            default:
01875              unknown = 1;
01876              break;
01877            }
01878        }
01879       break;
01880 
01881     case EF_ARM_EABI_VER3:
01882       strcat (buf, ", Version3 EABI");
01883       break;
01884 
01885     case EF_ARM_EABI_VER4:
01886       strcat (buf, ", Version4 EABI");
01887       goto eabi;
01888 
01889     case EF_ARM_EABI_VER5:
01890       strcat (buf, ", Version5 EABI");
01891     eabi:
01892       while (e_flags)
01893        {
01894          unsigned flag;
01895 
01896          /* Process flags one bit at a time.  */
01897          flag = e_flags & - e_flags;
01898          e_flags &= ~ flag;
01899 
01900          switch (flag)
01901            {
01902            case EF_ARM_BE8:
01903              strcat (buf, ", BE8");
01904              break;
01905 
01906            case EF_ARM_LE8:
01907              strcat (buf, ", LE8");
01908              break;
01909 
01910            default:
01911              unknown = 1;
01912              break;
01913            }
01914        }
01915       break;
01916 
01917     case EF_ARM_EABI_UNKNOWN:
01918       strcat (buf, ", GNU EABI");
01919       while (e_flags)
01920        {
01921          unsigned flag;
01922 
01923          /* Process flags one bit at a time.  */
01924          flag = e_flags & - e_flags;
01925          e_flags &= ~ flag;
01926 
01927          switch (flag)
01928            {
01929            case EF_ARM_INTERWORK:
01930              strcat (buf, ", interworking enabled");
01931              break;
01932 
01933            case EF_ARM_APCS_26:
01934              strcat (buf, ", uses APCS/26");
01935              break;
01936 
01937            case EF_ARM_APCS_FLOAT:
01938              strcat (buf, ", uses APCS/float");
01939              break;
01940 
01941            case EF_ARM_PIC:
01942              strcat (buf, ", position independent");
01943              break;
01944 
01945            case EF_ARM_ALIGN8:
01946              strcat (buf, ", 8 bit structure alignment");
01947              break;
01948 
01949            case EF_ARM_NEW_ABI:
01950              strcat (buf, ", uses new ABI");
01951              break;
01952 
01953            case EF_ARM_OLD_ABI:
01954              strcat (buf, ", uses old ABI");
01955              break;
01956 
01957            case EF_ARM_SOFT_FLOAT:
01958              strcat (buf, ", software FP");
01959              break;
01960 
01961            case EF_ARM_VFP_FLOAT:
01962              strcat (buf, ", VFP");
01963              break;
01964 
01965            case EF_ARM_MAVERICK_FLOAT:
01966              strcat (buf, ", Maverick FP");
01967              break;
01968 
01969            default:
01970              unknown = 1;
01971              break;
01972            }
01973        }
01974     }
01975 
01976   if (unknown)
01977     strcat (buf,", <unknown>");
01978 }
01979 
01980 static char *
01981 get_machine_flags (unsigned e_flags, unsigned e_machine)
01982 {
01983   static char buf[1024];
01984 
01985   buf[0] = '\0';
01986 
01987   if (e_flags)
01988     {
01989       switch (e_machine)
01990        {
01991        default:
01992          break;
01993 
01994        case EM_ARM:
01995          decode_ARM_machine_flags (e_flags, buf);
01996          break;
01997 
01998        case EM_CYGNUS_FRV:
01999          switch (e_flags & EF_FRV_CPU_MASK)
02000            {
02001            case EF_FRV_CPU_GENERIC:
02002              break;
02003 
02004            default:
02005              strcat (buf, ", fr???");
02006              break;
02007 
02008            case EF_FRV_CPU_FR300:
02009              strcat (buf, ", fr300");
02010              break;
02011 
02012            case EF_FRV_CPU_FR400:
02013              strcat (buf, ", fr400");
02014              break;
02015            case EF_FRV_CPU_FR405:
02016              strcat (buf, ", fr405");
02017              break;
02018 
02019            case EF_FRV_CPU_FR450:
02020              strcat (buf, ", fr450");
02021              break;
02022 
02023            case EF_FRV_CPU_FR500:
02024              strcat (buf, ", fr500");
02025              break;
02026            case EF_FRV_CPU_FR550:
02027              strcat (buf, ", fr550");
02028              break;
02029 
02030            case EF_FRV_CPU_SIMPLE:
02031              strcat (buf, ", simple");
02032              break;
02033            case EF_FRV_CPU_TOMCAT:
02034              strcat (buf, ", tomcat");
02035              break;
02036            }
02037          break;
02038 
02039        case EM_68K:
02040          if ((e_flags & EF_M68K_ARCH_MASK) == EF_M68K_M68000)
02041            strcat (buf, ", m68000");
02042          else if ((e_flags & EF_M68K_ARCH_MASK) == EF_M68K_CPU32)
02043            strcat (buf, ", cpu32");
02044          else if ((e_flags & EF_M68K_ARCH_MASK) == EF_M68K_FIDO)
02045            strcat (buf, ", fido_a");
02046          else
02047            {
02048              char const *isa = _("unknown");
02049              char const *mac = _("unknown mac");
02050              char const *additional = NULL;
02051 
02052              switch (e_flags & EF_M68K_CF_ISA_MASK)
02053               {
02054               case EF_M68K_CF_ISA_A_NODIV:
02055                 isa = "A";
02056                 additional = ", nodiv";
02057                 break;
02058               case EF_M68K_CF_ISA_A:
02059                 isa = "A";
02060                 break;
02061               case EF_M68K_CF_ISA_A_PLUS:
02062                 isa = "A+";
02063                 break;
02064               case EF_M68K_CF_ISA_B_NOUSP:
02065                 isa = "B";
02066                 additional = ", nousp";
02067                 break;
02068               case EF_M68K_CF_ISA_B:
02069                 isa = "B";
02070                 break;
02071               }
02072              strcat (buf, ", cf, isa ");
02073              strcat (buf, isa);
02074              if (additional)
02075               strcat (buf, additional);
02076              if (e_flags & EF_M68K_CF_FLOAT)
02077               strcat (buf, ", float");
02078              switch (e_flags & EF_M68K_CF_MAC_MASK)
02079               {
02080               case 0:
02081                 mac = NULL;
02082                 break;
02083               case EF_M68K_CF_MAC:
02084                 mac = "mac";
02085                 break;
02086               case EF_M68K_CF_EMAC:
02087                 mac = "emac";
02088                 break;
02089               }
02090              if (mac)
02091               {
02092                 strcat (buf, ", ");
02093                 strcat (buf, mac);
02094               }
02095            }
02096          break;
02097 
02098        case EM_PPC:
02099          if (e_flags & EF_PPC_EMB)
02100            strcat (buf, ", emb");
02101 
02102          if (e_flags & EF_PPC_RELOCATABLE)
02103            strcat (buf, ", relocatable");
02104 
02105          if (e_flags & EF_PPC_RELOCATABLE_LIB)
02106            strcat (buf, ", relocatable-lib");
02107          break;
02108 
02109        case EM_V850:
02110        case EM_CYGNUS_V850:
02111          switch (e_flags & EF_V850_ARCH)
02112            {
02113            case E_V850E1_ARCH:
02114              strcat (buf, ", v850e1");
02115              break;
02116            case E_V850E_ARCH:
02117              strcat (buf, ", v850e");
02118              break;
02119            case E_V850_ARCH:
02120              strcat (buf, ", v850");
02121              break;
02122            default:
02123              strcat (buf, ", unknown v850 architecture variant");
02124              break;
02125            }
02126          break;
02127 
02128        case EM_M32R:
02129        case EM_CYGNUS_M32R:
02130          if ((e_flags & EF_M32R_ARCH) == E_M32R_ARCH)
02131            strcat (buf, ", m32r");
02132          break;
02133 
02134        case EM_MIPS:
02135        case EM_MIPS_RS3_LE:
02136          if (e_flags & EF_MIPS_NOREORDER)
02137            strcat (buf, ", noreorder");
02138 
02139          if (e_flags & EF_MIPS_PIC)
02140            strcat (buf, ", pic");
02141 
02142          if (e_flags & EF_MIPS_CPIC)
02143            strcat (buf, ", cpic");
02144 
02145          if (e_flags & EF_MIPS_UCODE)
02146            strcat (buf, ", ugen_reserved");
02147 
02148          if (e_flags & EF_MIPS_ABI2)
02149            strcat (buf, ", abi2");
02150 
02151          if (e_flags & EF_MIPS_OPTIONS_FIRST)
02152            strcat (buf, ", odk first");
02153 
02154          if (e_flags & EF_MIPS_32BITMODE)
02155            strcat (buf, ", 32bitmode");
02156 
02157          switch ((e_flags & EF_MIPS_MACH))
02158            {
02159            case E_MIPS_MACH_3900: strcat (buf, ", 3900"); break;
02160            case E_MIPS_MACH_4010: strcat (buf, ", 4010"); break;
02161            case E_MIPS_MACH_4100: strcat (buf, ", 4100"); break;
02162            case E_MIPS_MACH_4111: strcat (buf, ", 4111"); break;
02163            case E_MIPS_MACH_4120: strcat (buf, ", 4120"); break;
02164            case E_MIPS_MACH_4650: strcat (buf, ", 4650"); break;
02165            case E_MIPS_MACH_5400: strcat (buf, ", 5400"); break;
02166            case E_MIPS_MACH_5500: strcat (buf, ", 5500"); break;
02167            case E_MIPS_MACH_SB1:  strcat (buf, ", sb1");  break;
02168            case E_MIPS_MACH_9000: strcat (buf, ", 9000"); break;
02169            case 0:
02170            /* We simply ignore the field in this case to avoid confusion:
02171               MIPS ELF does not specify EF_MIPS_MACH, it is a GNU
02172               extension.  */
02173              break;
02174            default: strcat (buf, ", unknown CPU"); break;
02175            }
02176 
02177          switch ((e_flags & EF_MIPS_ABI))
02178            {
02179            case E_MIPS_ABI_O32: strcat (buf, ", o32"); break;
02180            case E_MIPS_ABI_O64: strcat (buf, ", o64"); break;
02181            case E_MIPS_ABI_EABI32: strcat (buf, ", eabi32"); break;
02182            case E_MIPS_ABI_EABI64: strcat (buf, ", eabi64"); break;
02183            case 0:
02184            /* We simply ignore the field in this case to avoid confusion:
02185               MIPS ELF does not specify EF_MIPS_ABI, it is a GNU extension.
02186               This means it is likely to be an o32 file, but not for
02187               sure.  */
02188              break;
02189            default: strcat (buf, ", unknown ABI"); break;
02190            }
02191 
02192          if (e_flags & EF_MIPS_ARCH_ASE_MDMX)
02193            strcat (buf, ", mdmx");
02194 
02195          if (e_flags & EF_MIPS_ARCH_ASE_M16)
02196            strcat (buf, ", mips16");
02197 
02198          switch ((e_flags & EF_MIPS_ARCH))
02199            {
02200            case E_MIPS_ARCH_1: strcat (buf, ", mips1"); break;
02201            case E_MIPS_ARCH_2: strcat (buf, ", mips2"); break;
02202            case E_MIPS_ARCH_3: strcat (buf, ", mips3"); break;
02203            case E_MIPS_ARCH_4: strcat (buf, ", mips4"); break;
02204            case E_MIPS_ARCH_5: strcat (buf, ", mips5"); break;
02205            case E_MIPS_ARCH_32: strcat (buf, ", mips32"); break;
02206            case E_MIPS_ARCH_32R2: strcat (buf, ", mips32r2"); break;
02207            case E_MIPS_ARCH_64: strcat (buf, ", mips64"); break;
02208            case E_MIPS_ARCH_64R2: strcat (buf, ", mips64r2"); break;
02209            default: strcat (buf, ", unknown ISA"); break;
02210            }
02211 
02212          break;
02213 
02214        case EM_SH:
02215          switch ((e_flags & EF_SH_MACH_MASK))
02216            {
02217            case EF_SH1: strcat (buf, ", sh1"); break;
02218            case EF_SH2: strcat (buf, ", sh2"); break;
02219            case EF_SH3: strcat (buf, ", sh3"); break;
02220            case EF_SH_DSP: strcat (buf, ", sh-dsp"); break;
02221            case EF_SH3_DSP: strcat (buf, ", sh3-dsp"); break;
02222            case EF_SH4AL_DSP: strcat (buf, ", sh4al-dsp"); break;
02223            case EF_SH3E: strcat (buf, ", sh3e"); break;
02224            case EF_SH4: strcat (buf, ", sh4"); break;
02225            case EF_SH5: strcat (buf, ", sh5"); break;
02226            case EF_SH2E: strcat (buf, ", sh2e"); break;
02227            case EF_SH4A: strcat (buf, ", sh4a"); break;
02228            case EF_SH2A: strcat (buf, ", sh2a"); break;
02229            case EF_SH4_NOFPU: strcat (buf, ", sh4-nofpu"); break;
02230            case EF_SH4A_NOFPU: strcat (buf, ", sh4a-nofpu"); break;
02231            case EF_SH2A_NOFPU: strcat (buf, ", sh2a-nofpu"); break;
02232            case EF_SH3_NOMMU: strcat (buf, ", sh3-nommu"); break;
02233            case EF_SH4_NOMMU_NOFPU: strcat (buf, ", sh4-nommu-nofpu"); break;
02234            case EF_SH2A_SH4_NOFPU: strcat (buf, ", sh2a-nofpu-or-sh4-nommu-nofpu"); break;
02235            case EF_SH2A_SH3_NOFPU: strcat (buf, ", sh2a-nofpu-or-sh3-nommu"); break;
02236            case EF_SH2A_SH4: strcat (buf, ", sh2a-or-sh4"); break;
02237            case EF_SH2A_SH3E: strcat (buf, ", sh2a-or-sh3e"); break;
02238            default: strcat (buf, ", unknown ISA"); break;
02239            }
02240 
02241          break;
02242 
02243        case EM_SPARCV9:
02244          if (e_flags & EF_SPARC_32PLUS)
02245            strcat (buf, ", v8+");
02246 
02247          if (e_flags & EF_SPARC_SUN_US1)
02248            strcat (buf, ", ultrasparcI");
02249 
02250          if (e_flags & EF_SPARC_SUN_US3)
02251            strcat (buf, ", ultrasparcIII");
02252 
02253          if (e_flags & EF_SPARC_HAL_R1)
02254            strcat (buf, ", halr1");
02255 
02256          if (e_flags & EF_SPARC_LEDATA)
02257            strcat (buf, ", ledata");
02258 
02259          if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_TSO)
02260            strcat (buf, ", tso");
02261 
02262          if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_PSO)
02263            strcat (buf, ", pso");
02264 
02265          if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_RMO)
02266            strcat (buf, ", rmo");
02267          break;
02268 
02269        case EM_PARISC:
02270          switch (e_flags & EF_PARISC_ARCH)
02271            {
02272            case EFA_PARISC_1_0:
02273              strcpy (buf, ", PA-RISC 1.0");
02274              break;
02275            case EFA_PARISC_1_1:
02276              strcpy (buf, ", PA-RISC 1.1");
02277              break;
02278            case EFA_PARISC_2_0:
02279              strcpy (buf, ", PA-RISC 2.0");
02280              break;
02281            default:
02282              break;
02283            }
02284          if (e_flags & EF_PARISC_TRAPNIL)
02285            strcat (buf, ", trapnil");
02286          if (e_flags & EF_PARISC_EXT)
02287            strcat (buf, ", ext");
02288          if (e_flags & EF_PARISC_LSB)
02289            strcat (buf, ", lsb");
02290          if (e_flags & EF_PARISC_WIDE)
02291            strcat (buf, ", wide");
02292          if (e_flags & EF_PARISC_NO_KABP)
02293            strcat (buf, ", no kabp");
02294          if (e_flags & EF_PARISC_LAZYSWAP)
02295            strcat (buf, ", lazyswap");
02296          break;
02297 
02298        case EM_PJ:
02299        case EM_PJ_OLD:
02300          if ((e_flags & EF_PICOJAVA_NEWCALLS) == EF_PICOJAVA_NEWCALLS)
02301            strcat (buf, ", new calling convention");
02302 
02303          if ((e_flags & EF_PICOJAVA_GNUCALLS) == EF_PICOJAVA_GNUCALLS)
02304            strcat (buf, ", gnu calling convention");
02305          break;
02306 
02307        case EM_IA_64:
02308          if ((e_flags & EF_IA_64_ABI64))
02309            strcat (buf, ", 64-bit");
02310          else
02311            strcat (buf, ", 32-bit");
02312          if ((e_flags & EF_IA_64_REDUCEDFP))
02313            strcat (buf, ", reduced fp model");
02314          if ((e_flags & EF_IA_64_NOFUNCDESC_CONS_GP))
02315            strcat (buf, ", no function descriptors, constant gp");
02316          else if ((e_flags & EF_IA_64_CONS_GP))
02317            strcat (buf, ", constant gp");
02318          if ((e_flags & EF_IA_64_ABSOLUTE))
02319            strcat (buf, ", absolute");
02320          break;
02321 
02322        case EM_VAX:
02323          if ((e_flags & EF_VAX_NONPIC))
02324            strcat (buf, ", non-PIC");
02325          if ((e_flags & EF_VAX_DFLOAT))
02326            strcat (buf, ", D-Float");
02327          if ((e_flags & EF_VAX_GFLOAT))
02328            strcat (buf, ", G-Float");
02329          break;
02330        }
02331     }
02332 
02333   return buf;
02334 }
02335 
02336 static const char *
02337 get_osabi_name (unsigned int osabi)
02338 {
02339   static char buff[32];
02340 
02341   switch (osabi)
02342     {
02343     case ELFOSABI_NONE:            return "UNIX - System V";
02344     case ELFOSABI_HPUX:            return "UNIX - HP-UX";
02345     case ELFOSABI_NETBSD:   return "UNIX - NetBSD";
02346     case ELFOSABI_LINUX:    return "UNIX - Linux";
02347     case ELFOSABI_HURD:            return "GNU/Hurd";
02348     case ELFOSABI_SOLARIS:  return "UNIX - Solaris";
02349     case ELFOSABI_AIX:             return "UNIX - AIX";
02350     case ELFOSABI_IRIX:            return "UNIX - IRIX";
02351     case ELFOSABI_FREEBSD:  return "UNIX - FreeBSD";
02352     case ELFOSABI_TRU64:    return "UNIX - TRU64";
02353     case ELFOSABI_MODESTO:  return "Novell - Modesto";
02354     case ELFOSABI_OPENBSD:  return "UNIX - OpenBSD";
02355     case ELFOSABI_OPENVMS:  return "VMS - OpenVMS";
02356     case ELFOSABI_NSK:             return "HP - Non-Stop Kernel";
02357     case ELFOSABI_AROS:            return "Amiga Research OS";
02358     case ELFOSABI_STANDALONE:      return _("Standalone App");
02359     case ELFOSABI_ARM:             return "ARM";
02360     default:
02361       snprintf (buff, sizeof (buff), _("<unknown: %x>"), osabi);
02362       return buff;
02363     }
02364 }
02365 
02366 static const char *
02367 get_arm_segment_type (unsigned long type)
02368 {
02369   switch (type)
02370     {
02371     case PT_ARM_EXIDX:
02372       return "EXIDX";
02373     default:
02374       break;
02375     }
02376 
02377   return NULL;
02378 }
02379 
02380 static const char *
02381 get_mips_segment_type (unsigned long type)
02382 {
02383   switch (type)
02384     {
02385     case PT_MIPS_REGINFO:
02386       return "REGINFO";
02387     case PT_MIPS_RTPROC:
02388       return "RTPROC";
02389     case PT_MIPS_OPTIONS:
02390       return "OPTIONS";
02391     default:
02392       break;
02393     }
02394 
02395   return NULL;
02396 }
02397 
02398 static const char *
02399 get_parisc_segment_type (unsigned long type)
02400 {
02401   switch (type)
02402     {
02403     case PT_HP_TLS:         return "HP_TLS";
02404     case PT_HP_CORE_NONE:   return "HP_CORE_NONE";
02405     case PT_HP_CORE_VERSION:       return "HP_CORE_VERSION";
02406     case PT_HP_CORE_KERNEL: return "HP_CORE_KERNEL";
02407     case PT_HP_CORE_COMM:   return "HP_CORE_COMM";
02408     case PT_HP_CORE_PROC:   return "HP_CORE_PROC";
02409     case PT_HP_CORE_LOADABLE:      return "HP_CORE_LOADABLE";
02410     case PT_HP_CORE_STACK:  return "HP_CORE_STACK";
02411     case PT_HP_CORE_SHM:    return "HP_CORE_SHM";
02412     case PT_HP_CORE_MMF:    return "HP_CORE_MMF";
02413     case PT_HP_PARALLEL:    return "HP_PARALLEL";
02414     case PT_HP_FASTBIND:    return "HP_FASTBIND";
02415     case PT_HP_OPT_ANNOT:   return "HP_OPT_ANNOT";
02416     case PT_HP_HSL_ANNOT:   return "HP_HSL_ANNOT";
02417     case PT_HP_STACK:              return "HP_STACK";
02418     case PT_HP_CORE_UTSNAME:       return "HP_CORE_UTSNAME";
02419     case PT_PARISC_ARCHEXT: return "PARISC_ARCHEXT";
02420     case PT_PARISC_UNWIND:  return "PARISC_UNWIND";
02421     case PT_PARISC_WEAKORDER:      return "PARISC_WEAKORDER";
02422     default:
02423       break;
02424     }
02425 
02426   return NULL;
02427 }
02428 
02429 static const char *
02430 get_ia64_segment_type (unsigned long type)
02431 {
02432   switch (type)
02433     {
02434     case PT_IA_64_ARCHEXT:  return "IA_64_ARCHEXT";
02435     case PT_IA_64_UNWIND:   return "IA_64_UNWIND";
02436     case PT_HP_TLS:         return "HP_TLS";
02437     case PT_IA_64_HP_OPT_ANOT:     return "HP_OPT_ANNOT";
02438     case PT_IA_64_HP_HSL_ANOT:     return "HP_HSL_ANNOT";
02439     case PT_IA_64_HP_STACK: return "HP_STACK";
02440     default:
02441       break;
02442     }
02443 
02444   return NULL;
02445 }
02446 
02447 static const char *
02448 get_segment_type (unsigned long p_type)
02449 {
02450   static char buff[32];
02451 
02452   switch (p_type)
02453     {
02454     case PT_NULL:    return "NULL";
02455     case PT_LOAD:    return "LOAD";
02456     case PT_DYNAMIC: return "DYNAMIC";
02457     case PT_INTERP:  return "INTERP";
02458     case PT_NOTE:    return "NOTE";
02459     case PT_SHLIB:   return "SHLIB";
02460     case PT_PHDR:    return "PHDR";
02461     case PT_TLS:     return "TLS";
02462 
02463     case PT_GNU_EH_FRAME:
02464                      return "GNU_EH_FRAME";
02465     case PT_GNU_STACK:      return "GNU_STACK";
02466     case PT_GNU_RELRO:  return "GNU_RELRO";
02467 
02468     default:
02469       if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
02470        {
02471          const char *result;
02472 
02473          switch (elf_header.e_machine)
02474            {
02475            case EM_ARM:
02476              result = get_arm_segment_type (p_type);
02477              break;
02478            case EM_MIPS:
02479            case EM_MIPS_RS3_LE:
02480              result = get_mips_segment_type (p_type);
02481              break;
02482            case EM_PARISC:
02483              result = get_parisc_segment_type (p_type);
02484              break;
02485            case EM_IA_64:
02486              result = get_ia64_segment_type (p_type);
02487              break;
02488            default:
02489              result = NULL;
02490              break;
02491            }
02492 
02493          if (result != NULL)
02494            return result;
02495 
02496          sprintf (buff, "LOPROC+%lx", p_type - PT_LOPROC);
02497        }
02498       else if ((p_type >= PT_LOOS) && (p_type <= PT_HIOS))
02499        {
02500          const char *result;
02501 
02502          switch (elf_header.e_machine)
02503            {
02504            case EM_PARISC:
02505              result = get_parisc_segment_type (p_type);
02506              break;
02507            case EM_IA_64:
02508              result = get_ia64_segment_type (p_type);
02509              break;
02510            default:
02511              result = NULL;
02512              break;
02513            }
02514 
02515          if (result != NULL)
02516            return result;
02517 
02518          sprintf (buff, "LOOS+%lx", p_type - PT_LOOS);
02519        }
02520       else
02521        snprintf (buff, sizeof (buff), _("<unknown>: %lx"), p_type);
02522 
02523       return buff;
02524     }
02525 }
02526 
02527 static const char *
02528 get_mips_section_type_name (unsigned int sh_type)
02529 {
02530   switch (sh_type)
02531     {
02532     case SHT_MIPS_LIBLIST:   return "MIPS_LIBLIST";
02533     case SHT_MIPS_MSYM:             return "MIPS_MSYM";
02534     case SHT_MIPS_CONFLICT:  return "MIPS_CONFLICT";
02535     case SHT_MIPS_GPTAB:     return "MIPS_GPTAB";
02536     case SHT_MIPS_UCODE:     return "MIPS_UCODE";
02537     case SHT_MIPS_DEBUG:     return "MIPS_DEBUG";
02538     case SHT_MIPS_REGINFO:   return "MIPS_REGINFO";
02539     case SHT_MIPS_PACKAGE:   return "MIPS_PACKAGE";
02540     case SHT_MIPS_PACKSYM:   return "MIPS_PACKSYM";
02541     case SHT_MIPS_RELD:             return "MIPS_RELD";
02542     case SHT_MIPS_IFACE:     return "MIPS_IFACE";
02543     case SHT_MIPS_CONTENT:   return "MIPS_CONTENT";
02544     case SHT_MIPS_OPTIONS:   return "MIPS_OPTIONS";
02545     case SHT_MIPS_SHDR:             return "MIPS_SHDR";
02546     case SHT_MIPS_FDESC:     return "MIPS_FDESC";
02547     case SHT_MIPS_EXTSYM:    return "MIPS_EXTSYM";
02548     case SHT_MIPS_DENSE:     return "MIPS_DENSE";
02549     case SHT_MIPS_PDESC:     return "MIPS_PDESC";
02550     case SHT_MIPS_LOCSYM:    return "MIPS_LOCSYM";
02551     case SHT_MIPS_AUXSYM:    return "MIPS_AUXSYM";
02552     case SHT_MIPS_OPTSYM:    return "MIPS_OPTSYM";
02553     case SHT_MIPS_LOCSTR:    return "MIPS_LOCSTR";
02554     case SHT_MIPS_LINE:             return "MIPS_LINE";
02555     case SHT_MIPS_RFDESC:    return "MIPS_RFDESC";
02556     case SHT_MIPS_DELTASYM:  return "MIPS_DELTASYM";
02557     case SHT_MIPS_DELTAINST:        return "MIPS_DELTAINST";
02558     case SHT_MIPS_DELTACLASS:       return "MIPS_DELTACLASS";
02559     case SHT_MIPS_DWARF:     return "MIPS_DWARF";
02560     case SHT_MIPS_DELTADECL:        return "MIPS_DELTADECL";
02561     case SHT_MIPS_SYMBOL_LIB:       return "MIPS_SYMBOL_LIB";
02562     case SHT_MIPS_EVENTS:    return "MIPS_EVENTS";
02563     case SHT_MIPS_TRANSLATE:        return "MIPS_TRANSLATE";
02564     case SHT_MIPS_PIXIE:     return "MIPS_PIXIE";
02565     case SHT_MIPS_XLATE:     return "MIPS_XLATE";
02566     case SHT_MIPS_XLATE_DEBUG:      return "MIPS_XLATE_DEBUG";
02567     case SHT_MIPS_WHIRL:     return "MIPS_WHIRL";
02568     case SHT_MIPS_EH_REGION:        return "MIPS_EH_REGION";
02569     case SHT_MIPS_XLATE_OLD:        return "MIPS_XLATE_OLD";
02570     case SHT_MIPS_PDR_EXCEPTION: return "MIPS_PDR_EXCEPTION";
02571     default:
02572       break;
02573     }
02574   return NULL;
02575 }
02576 
02577 static const char *
02578 get_parisc_section_type_name (unsigned int sh_type)
02579 {
02580   switch (sh_type)
02581     {
02582     case SHT_PARISC_EXT:    return "PARISC_EXT";
02583     case SHT_PARISC_UNWIND: return "PARISC_UNWIND";
02584     case SHT_PARISC_DOC:    return "PARISC_DOC";
02585     case SHT_PARISC_ANNOT:  return "PARISC_ANNOT";
02586     case SHT_PARISC_SYMEXTN:       return "PARISC_SYMEXTN";
02587     case SHT_PARISC_STUBS:  return "PARISC_STUBS";
02588     case SHT_PARISC_DLKM:   return "PARISC_DLKM";
02589     default:
02590       break;
02591     }
02592   return NULL;
02593 }
02594 
02595 static const char *
02596 get_ia64_section_type_name (unsigned int sh_type)
02597 {
02598   /* If the top 8 bits are 0x78 the next 8 are the os/abi ID.  */
02599   if ((sh_type & 0xFF000000) == SHT_IA_64_LOPSREG)
02600     return get_osabi_name ((sh_type & 0x00FF0000) >> 16);
02601 
02602   switch (sh_type)
02603     {
02604     case SHT_IA_64_EXT:              return "IA_64_EXT";
02605     case SHT_IA_64_UNWIND:    return "IA_64_UNWIND";
02606     case SHT_IA_64_PRIORITY_INIT: return "IA_64_PRIORITY_INIT";
02607     default:
02608       break;
02609     }
02610   return NULL;
02611 }
02612 
02613 static const char *
02614 get_x86_64_section_type_name (unsigned int sh_type)
02615 {
02616   switch (sh_type)
02617     {
02618     case SHT_X86_64_UNWIND: return "X86_64_UNWIND";
02619     default:
02620       break;
02621     }
02622   return NULL;
02623 }
02624 
02625 static const char *
02626 get_arm_section_type_name (unsigned int sh_type)
02627 {
02628   switch (sh_type)
02629     {
02630     case SHT_ARM_EXIDX:
02631       return "ARM_EXIDX";
02632     case SHT_ARM_PREEMPTMAP:
02633       return "ARM_PREEMPTMAP";
02634     case SHT_ARM_ATTRIBUTES:
02635       return "ARM_ATTRIBUTES";
02636     default:
02637       break;
02638     }
02639   return NULL;
02640 }
02641 
02642 static const char *
02643 get_section_type_name (unsigned int sh_type)
02644 {
02645   static char buff[32];
02646 
02647   switch (sh_type)
02648     {
02649     case SHT_NULL:          return "NULL";
02650     case SHT_PROGBITS:             return "PROGBITS";
02651     case SHT_SYMTAB:        return "SYMTAB";
02652     case SHT_STRTAB:        return "STRTAB";
02653     case SHT_RELA:          return "RELA";
02654     case SHT_HASH:          return "HASH";
02655     case SHT_DYNAMIC:              return "DYNAMIC";
02656     case SHT_NOTE:          return "NOTE";
02657     case SHT_NOBITS:        return "NOBITS";
02658     case SHT_REL:           return "REL";
02659     case SHT_SHLIB:         return "SHLIB";
02660     case SHT_DYNSYM:        return "DYNSYM";
02661     case SHT_INIT_ARRAY:    return "INIT_ARRAY";
02662     case SHT_FINI_ARRAY:    return "FINI_ARRAY";
02663     case SHT_PREINIT_ARRAY: return "PREINIT_ARRAY";
02664     case SHT_GNU_HASH:             return "GNU_HASH";
02665     case SHT_GROUP:         return "GROUP";
02666     case SHT_SYMTAB_SHNDX:  return "SYMTAB SECTION INDICIES";
02667     case SHT_GNU_verdef:    return "VERDEF";
02668     case SHT_GNU_verneed:   return "VERNEED";
02669     case SHT_GNU_versym:    return "VERSYM";
02670     case 0x6ffffff0:        return "VERSYM";
02671     case 0x6ffffffc:        return "VERDEF";
02672     case 0x7ffffffd:        return "AUXILIARY";
02673     case 0x7fffffff:        return "FILTER";
02674     case SHT_GNU_LIBLIST:   return "GNU_LIBLIST";
02675 
02676     default:
02677       if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC))
02678        {
02679          const char *result;
02680 
02681          switch (elf_header.e_machine)
02682            {
02683            case EM_MIPS:
02684            case EM_MIPS_RS3_LE:
02685              result = get_mips_section_type_name (sh_type);
02686              break;
02687            case EM_PARISC:
02688              result = get_parisc_section_type_name (sh_type);
02689              break;
02690            case EM_IA_64:
02691              result = get_ia64_section_type_name (sh_type);
02692              break;
02693            case EM_X86_64:
02694              result = get_x86_64_section_type_name (sh_type);
02695              break;
02696            case EM_ARM:
02697              result = get_arm_section_type_name (sh_type);
02698              break;
02699            default:
02700              result = NULL;
02701              break;
02702            }
02703 
02704          if (result != NULL)
02705            return result;
02706 
02707          sprintf (buff, "LOPROC+%x", sh_type - SHT_LOPROC);
02708        }
02709       else if ((sh_type >= SHT_LOOS) && (sh_type <= SHT_HIOS))
02710        sprintf (buff, "LOOS+%x", sh_type - SHT_LOOS);
02711       else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER))
02712        sprintf (buff, "LOUSER+%x", sh_type - SHT_LOUSER);
02713       else
02714        snprintf (buff, sizeof (buff), _("<unknown>: %x"), sh_type);
02715 
02716       return buff;
02717     }
02718 }
02719 
02720 #define OPTION_DEBUG_DUMP   512
02721 
02722 static struct option options[] =
02723 {
02724   {"all",            no_argument, 0, 'a'},
02725   {"file-header",      no_argument, 0, 'h'},
02726   {"program-headers",  no_argument, 0, 'l'},
02727   {"headers",        no_argument, 0, 'e'},
02728   {"histogram",             no_argument, 0, 'I'},
02729   {"segments",              no_argument, 0, 'l'},
02730   {"sections",              no_argument, 0, 'S'},
02731   {"section-headers",  no_argument, 0, 'S'},
02732   {"section-groups",   no_argument, 0, 'g'},
02733   {"section-details",  no_argument, 0, 't'},
02734   {"full-section-name",no_argument, 0, 'N'},
02735   {"symbols",        no_argument, 0, 's'},
02736   {"syms",           no_argument, 0, 's'},
02737   {"relocs",         no_argument, 0, 'r'},
02738   {"notes",          no_argument, 0, 'n'},
02739   {"dynamic",        no_argument, 0, 'd'},
02740   {"arch-specific",    no_argument, 0, 'A'},
02741   {"version-info",     no_argument, 0, 'V'},
02742   {"use-dynamic",      no_argument, 0, 'D'},
02743   {"hex-dump",              required_argument, 0, 'x'},
02744   {"debug-dump",       optional_argument, 0, OPTION_DEBUG_DUMP},
02745   {"unwind",         no_argument, 0, 'u'},
02746 #ifdef SUPPORT_DISASSEMBLY
02747   {"instruction-dump", required_argument, 0, 'i'},
02748 #endif
02749 
02750   {"version",        no_argument, 0, 'v'},
02751   {"wide",           no_argument, 0, 'W'},
02752   {"help",           no_argument, 0, 'H'},
02753   {0,                no_argument, 0, 0}
02754 };
02755 
02756 static void
02757 usage (FILE *stream)
02758 {
02759   fprintf (stream, _("Usage: readelf <option(s)> elf-file(s)\n"));
02760   fprintf (stream, _(" Display information about the contents of ELF format files\n"));
02761   fprintf (stream, _(" Options are:\n\
02762   -a --all               Equivalent to: -h -l -S -s -r -d -V -A -I\n\
02763   -h --file-header       Display the ELF file header\n\
02764   -l --program-headers   Display the program headers\n\
02765      --segments          An alias for --program-headers\n\
02766   -S --section-headers   Display the sections' header\n\
02767      --sections          An alias for --section-headers\n\
02768   -g --section-groups    Display the section groups\n\
02769   -t --section-details   Display the section details\n\
02770   -e --headers           Equivalent to: -h -l -S\n\
02771   -s --syms              Display the symbol table\n\
02772       --symbols          An alias for --syms\n\
02773   -n --notes             Display the core notes (if present)\n\
02774   -r --relocs            Display the relocations (if present)\n\
02775   -u --unwind            Display the unwind info (if present)\n\
02776   -d --dynamic           Display the dynamic section (if present)\n\
02777   -V --version-info      Display the version sections (if present)\n\
02778   -A --arch-specific     Display architecture specific information (if any).\n\
02779   -D --use-dynamic       Use the dynamic section info when displaying symbols\n\
02780   -x --hex-dump=<number> Dump the contents of section <number>\n\
02781   -w[liaprmfFsoR] or\n\
02782   --debug-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]\n\
02783                          Display the contents of DWARF2 debug sections\n"));
02784 #ifdef SUPPORT_DISASSEMBLY
02785   fprintf (stream, _("\
02786   -i --instruction-dump=<number>\n\
02787                          Disassemble the contents of section <number>\n"));
02788 #endif
02789   fprintf (stream, _("\
02790   -I --histogram         Display histogram of bucket list lengths\n\
02791   -W --wide              Allow output width to exceed 80 characters\n\
02792   @<file>                Read options from <file>\n\
02793   -H --help              Display this information\n\
02794   -v --version           Display the version number of readelf\n"));
02795   
02796   if (REPORT_BUGS_TO[0] && stream == stdout)
02797     fprintf (stdout, _("Report bugs to %s\n"), REPORT_BUGS_TO);
02798 
02799   exit (stream == stdout ? 0 : 1);
02800 }
02801 
02802 /* Record the fact that the user wants the contents of section number
02803    SECTION to be displayed using the method(s) encoded as flags bits
02804    in TYPE.  Note, TYPE can be zero if we are creating the array for
02805    the first time.  */
02806 
02807 static void
02808 request_dump (unsigned int section, int type)
02809 {
02810   if (section >= num_dump_sects)
02811     {
02812       char *new_dump_sects;
02813 
02814       new_dump_sects = calloc (section + 1, 1);
02815 
02816       if (new_dump_sects == NULL)
02817        error (_("Out of memory allocating dump request table.\n"));
02818       else
02819        {
02820          /* Copy current flag settings.  */
02821          memcpy (new_dump_sects, dump_sects, num_dump_sects);
02822 
02823          free (dump_sects);
02824 
02825          dump_sects = new_dump_sects;
02826          num_dump_sects = section + 1;
02827        }
02828     }
02829 
02830   if (dump_sects)
02831     dump_sects[section] |= type;
02832 
02833   return;
02834 }
02835 
02836 /* Request a dump by section name.  */
02837 
02838 static void
02839 request_dump_byname (const char *section, int type)
02840 {
02841   struct dump_list_entry *new_request;
02842 
02843   new_request = malloc (sizeof (struct dump_list_entry));
02844   if (!new_request)
02845     error (_("Out of memory allocating dump request table.\n"));
02846 
02847   new_request->name = strdup (section);
02848   if (!new_request->name)
02849     error (_("Out of memory allocating dump request table.\n"));
02850 
02851   new_request->type = type;
02852 
02853   new_request->next = dump_sects_byname;
02854   dump_sects_byname = new_request;
02855 }
02856 
02857 static void
02858 parse_args (int argc, char **argv)
02859 {
02860   int c;
02861 
02862   if (argc < 2)
02863     usage (stderr);
02864 
02865   while ((c = getopt_long
02866          (argc, argv, "ersuahnldSDAINtgw::x:i:vVWH", options, NULL)) != EOF)
02867     {
02868       char *cp;
02869       int section;
02870 
02871       switch (c)
02872        {
02873        case 0:
02874          /* Long options.  */
02875          break;
02876        case 'H':
02877          usage (stdout);
02878          break;
02879 
02880        case 'a':
02881          do_syms++;
02882          do_reloc++;
02883          do_unwind++;
02884          do_dynamic++;
02885          do_header++;
02886          do_sections++;
02887          do_section_groups++;
02888          do_segments++;
02889          do_version++;
02890          do_histogram++;
02891          do_arch++;
02892          do_notes++;
02893          break;
02894        case 'g':
02895          do_section_groups++;
02896          break;
02897        case 't':
02898        case 'N':
02899          do_sections++;
02900          do_section_details++;
02901          break;
02902        case 'e':
02903          do_header++;
02904          do_sections++;
02905          do_segments++;
02906          break;
02907        case 'A':
02908          do_arch++;
02909          break;
02910        case 'D':
02911          do_using_dynamic++;
02912          break;
02913        case 'r':
02914          do_reloc++;
02915          break;
02916        case 'u':
02917          do_unwind++;
02918          break;
02919        case 'h':
02920          do_header++;
02921          break;
02922        case 'l':
02923          do_segments++;
02924          break;
02925        case 's':
02926          do_syms++;
02927          break;
02928        case 'S':
02929          do_sections++;
02930          break;
02931        case 'd':
02932          do_dynamic++;
02933          break;
02934        case 'I':
02935          do_histogram++;
02936          break;
02937        case 'n':
02938          do_notes++;
02939          break;
02940        case 'x':
02941          do_dump++;
02942          section = strtoul (optarg, & cp, 0);
02943          if (! *cp && section >= 0)
02944            request_dump (section, HEX_DUMP);
02945          else
02946            request_dump_byname (optarg, HEX_DUMP);
02947          break;
02948        case 'w':
02949          do_dump++;
02950          if (optarg == 0)
02951            do_debugging = 1;
02952          else
02953            {
02954              unsigned int index = 0;
02955 
02956              do_debugging = 0;
02957 
02958              while (optarg[index])
02959               switch (optarg[index++])
02960                 {
02961                 case 'i':
02962                 case 'I':
02963                   do_debug_info = 1;
02964                   break;
02965 
02966                 case 'a':
02967                 case 'A':
02968                   do_debug_abbrevs = 1;
02969                   break;
02970 
02971                 case 'l':
02972                 case 'L':
02973                   do_debug_lines = 1;
02974                   break;
02975 
02976                 case 'p':
02977                 case 'P':
02978                   do_debug_pubnames = 1;
02979                   break;
02980 
02981                 case 'r':
02982                   do_debug_aranges = 1;
02983                   break;
02984 
02985                 case 'R':
02986                   do_debug_ranges = 1;
02987                   break;
02988 
02989                 case 'F':
02990                   do_debug_frames_interp = 1;
02991                 case 'f':
02992                   do_debug_frames = 1;
02993                   break;
02994 
02995                 case 'm':
02996                 case 'M':
02997                   do_debug_macinfo = 1;
02998                   break;
02999 
03000                 case 's':
03001                 case 'S':
03002                   do_debug_str = 1;
03003                   break;
03004 
03005                 case 'o':
03006                 case 'O':
03007                   do_debug_loc = 1;
03008                   break;
03009 
03010                 default:
03011                   warn (_("Unrecognized debug option '%s'\n"), optarg);
03012                   break;
03013                 }
03014            }
03015          break;
03016        case OPTION_DEBUG_DUMP:
03017          do_dump++;
03018          if (optarg == 0)
03019            do_debugging = 1;
03020          else
03021            {
03022              typedef struct
03023              {
03024               const char * option;
03025               int *        variable;
03026              }
03027              debug_dump_long_opts;
03028 
03029              debug_dump_long_opts opts_table [] =
03030               {
03031                 /* Please keep this table alpha- sorted.  */
03032                 { "Ranges", & do_debug_ranges },
03033                 { "abbrev", & do_debug_abbrevs },
03034                 { "aranges", & do_debug_aranges },
03035                 { "frames", & do_debug_frames },
03036                 { "frames-interp", & do_debug_frames_interp },
03037                 { "info", & do_debug_info },
03038                 { "line", & do_debug_lines },
03039                 { "loc",  & do_debug_loc },
03040                 { "macro", & do_debug_macinfo },
03041                 { "pubnames", & do_debug_pubnames },
03042                 /* This entry is for compatability
03043                    with earlier versions of readelf.  */
03044                 { "ranges", & do_debug_aranges },
03045                 { "str", & do_debug_str },
03046                 { NULL, NULL }
03047               };
03048 
03049              const char *p;
03050 
03051              do_debugging = 0;
03052 
03053              p = optarg;
03054              while (*p)
03055               {
03056                 debug_dump_long_opts * entry;
03057 
03058                 for (entry = opts_table; entry->option; entry++)
03059                   {
03060                     size_t len = strlen (entry->option);
03061 
03062                     if (strneq (p, entry->option, len)
03063                        && (p[len] == ',' || p[len] == '\0'))
03064                      {
03065                        * entry->variable = 1;
03066 
03067                        /* The --debug-dump=frames-interp option also
03068                           enables the --debug-dump=frames option.  */
03069                        if (do_debug_frames_interp)
03070                          do_debug_frames = 1;
03071 
03072                        p += len;
03073                        break;
03074                      }
03075                   }
03076 
03077                 if (entry->option == NULL)
03078                   {
03079                     warn (_("Unrecognized debug option '%s'\n"), p);
03080                     p = strchr (p, ',');
03081                     if (p == NULL)
03082                      break;
03083                   }
03084 
03085                 if (*p == ',')
03086                   p++;
03087               }
03088            }
03089          break;
03090 #ifdef SUPPORT_DISASSEMBLY
03091        case 'i':
03092          do_dump++;
03093          section = strtoul (optarg, & cp, 0);
03094          if (! *cp && section >= 0)
03095            {
03096              request_dump (section, DISASS_DUMP);
03097              break;
03098            }
03099          goto oops;
03100 #endif
03101        case 'v':
03102          print_version (program_name);
03103          break;
03104        case 'V':
03105          do_version++;
03106          break;
03107        case 'W':
03108          do_wide++;
03109          break;
03110        default:
03111 #ifdef SUPPORT_DISASSEMBLY
03112        oops:
03113 #endif
03114          /* xgettext:c-format */
03115          error (_("Invalid option '-%c'\n"), c);
03116          /* Drop through.  */
03117        case '?':
03118          usage (stderr);
03119        }
03120     }
03121 
03122   if (!do_dynamic && !do_syms && !do_reloc && !do_unwind && !do_sections
03123       && !do_segments && !do_header && !do_dump && !do_version
03124       && !do_histogram && !do_debugging && !do_arch && !do_notes
03125       && !do_section_groups)
03126     usage (stderr);
03127   else if (argc < 3)
03128     {
03129       warn (_("Nothing to do.\n"));
03130       usage (stderr);
03131     }
03132 }
03133 
03134 static const char *
03135 get_elf_class (unsigned int elf_class)
03136 {
03137   static char buff[32];
03138 
03139   switch (elf_class)
03140     {
03141     case ELFCLASSNONE: return _("none");
03142     case ELFCLASS32:   return "ELF32";
03143     case ELFCLASS64:   return "ELF64";
03144     default:
03145       snprintf (buff, sizeof (buff), _("<unknown: %x>"), elf_class);
03146       return buff;
03147     }
03148 }
03149 
03150 static const char *
03151 get_data_encoding (unsigned int encoding)
03152 {
03153   static char buff[32];
03154 
03155   switch (encoding)
03156     {
03157     case ELFDATANONE: return _("none");
03158     case ELFDATA2LSB: return _("2's complement, little endian");
03159     case ELFDATA2MSB: return _("2's complement, big endian");
03160     default:
03161       snprintf (buff, sizeof (buff), _("<unknown: %x>"), encoding);
03162       return buff;
03163     }
03164 }
03165 
03166 /* Decode the data held in 'elf_header'.  */
03167 
03168 static int
03169 process_file_header (void)
03170 {
03171   if (   elf_header.e_ident[EI_MAG0] != ELFMAG0
03172       || elf_header.e_ident[EI_MAG1] != ELFMAG1
03173       || elf_header.e_ident[EI_MAG2] != ELFMAG2
03174       || elf_header.e_ident[EI_MAG3] != ELFMAG3)
03175     {
03176       error
03177        (_("Not an ELF file - it has the wrong magic bytes at the start\n"));
03178       return 0;
03179     }
03180 
03181   if (do_header)
03182     {
03183       int i;
03184 
03185       printf (_("ELF Header:\n"));
03186       printf (_("  Magic:   "));
03187       for (i = 0; i < EI_NIDENT; i++)
03188        printf ("%2.2x ", elf_header.e_ident[i]);
03189       printf ("\n");
03190       printf (_("  Class:                             %s\n"),
03191              get_elf_class (elf_header.e_ident[EI_CLASS]));
03192       printf (_("  Data:                              %s\n"),
03193              get_data_encoding (elf_header.e_ident[EI_DATA]));
03194       printf (_("  Version:                           %d %s\n"),
03195              elf_header.e_ident[EI_VERSION],
03196              (elf_header.e_ident[EI_VERSION] == EV_CURRENT
03197               ? "(current)"
03198               : (elf_header.e_ident[EI_VERSION] != EV_NONE
03199                 ? "<unknown: %lx>"
03200                 : "")));
03201       printf (_("  OS/ABI:                            %s\n"),
03202              get_osabi_name (elf_header.e_ident[EI_OSABI]));
03203       printf (_("  ABI Version:                       %d\n"),
03204              elf_header.e_ident[EI_ABIVERSION]);
03205       printf (_("  Type:                              %s\n"),
03206              get_file_type (elf_header.e_type));
03207       printf (_("  Machine:                           %s\n"),
03208              get_machine_name (elf_header.e_machine));
03209       printf (_("  Version:                           0x%lx\n"),
03210              (unsigned long) elf_header.e_version);
03211 
03212       printf (_("  Entry point address:               "));
03213       print_vma ((bfd_vma) elf_header.e_entry, PREFIX_HEX);
03214       printf (_("\n  Start of program headers:          "));
03215       print_vma ((bfd_vma) elf_header.e_phoff, DEC);
03216       printf (_(" (bytes into file)\n  Start of section headers:          "));
03217       print_vma ((bfd_vma) elf_header.e_shoff, DEC);
03218       printf (_(" (bytes into file)\n"));
03219 
03220       printf (_("  Flags:                             0x%lx%s\n"),
03221              (unsigned long) elf_header.e_flags,
03222              get_machine_flags (elf_header.e_flags, elf_header.e_machine));
03223       printf (_("  Size of this header:               %ld (bytes)\n"),
03224              (long) elf_header.e_ehsize);
03225       printf (_("  Size of program headers:           %ld (bytes)\n"),
03226              (long) elf_header.e_phentsize);
03227       printf (_("  Number of program headers:         %ld\n"),
03228              (long) elf_header.e_phnum);
03229       printf (_("  Size of section headers:           %ld (bytes)\n"),
03230              (long) elf_header.e_shentsize);
03231       printf (_("  Number of section headers:         %ld"),
03232              (long) elf_header.e_shnum);
03233       if (section_headers != NULL && elf_header.e_shnum == 0)
03234        printf (" (%ld)", (long) section_headers[0].sh_size);
03235       putc ('\n', stdout);
03236       printf (_("  Section header string table index: %ld"),
03237              (long) elf_header.e_shstrndx);
03238       if (section_headers != NULL && elf_header.e_shstrndx == SHN_XINDEX)
03239        printf (" (%ld)", (long) section_headers[0].sh_link);
03240       else if (elf_header.e_shstrndx != SHN_UNDEF
03241               && (elf_header.e_shstrndx >= elf_header.e_shnum
03242                  || (elf_header.e_shstrndx >= SHN_LORESERVE
03243                      && elf_header.e_shstrndx <= SHN_HIRESERVE)))
03244        printf (" <corrupt: out of range>");
03245       putc ('\n', stdout);
03246     }
03247 
03248   if (section_headers != NULL)
03249     {
03250       if (elf_header.e_shnum == 0)
03251        elf_header.e_shnum = section_headers[0].sh_size;
03252       if (elf_header.e_shstrndx == SHN_XINDEX)
03253        elf_header.e_shstrndx = section_headers[0].sh_link;
03254       else if (elf_header.e_shstrndx != SHN_UNDEF
03255               && (elf_header.e_shstrndx >= elf_header.e_shnum
03256                  || (elf_header.e_shstrndx >= SHN_LORESERVE
03257                      && elf_header.e_shstrndx <= SHN_HIRESERVE)))
03258        elf_header.e_shstrndx = SHN_UNDEF;
03259       free (section_headers);
03260       section_headers = NULL;
03261     }
03262 
03263   return 1;
03264 }
03265 
03266 
03267 static int
03268 get_32bit_program_headers (FILE *file, Elf_Internal_Phdr *program_headers)
03269 {
03270   Elf32_External_Phdr *phdrs;
03271   Elf32_External_Phdr *external;
03272   Elf_Internal_Phdr *internal;
03273   unsigned int i;
03274 
03275   phdrs = get_data (NULL, file, elf_header.e_phoff,
03276                   elf_header.e_phentsize, elf_header.e_phnum,
03277                   _("program headers"));
03278   if (!phdrs)
03279     return 0;
03280 
03281   for (i = 0, internal = program_headers, external = phdrs;
03282        i < elf_header.e_phnum;
03283        i++, internal++, external++)
03284     {
03285       internal->p_type   = BYTE_GET (external->p_type);
03286       internal->p_offset = BYTE_GET (external->p_offset);
03287       internal->p_vaddr  = BYTE_GET (external->p_vaddr);
03288       internal->p_paddr  = BYTE_GET (external->p_paddr);
03289       internal->p_filesz = BYTE_GET (external->p_filesz);
03290       internal->p_memsz  = BYTE_GET (external->p_memsz);
03291       internal->p_flags  = BYTE_GET (external->p_flags);
03292       internal->p_align  = BYTE_GET (external->p_align);
03293     }
03294 
03295   free (phdrs);
03296 
03297   return 1;
03298 }
03299 
03300 static int
03301 get_64bit_program_headers (FILE *file, Elf_Internal_Phdr *program_headers)
03302 {
03303   Elf64_External_Phdr *phdrs;
03304   Elf64_External_Phdr *external;
03305   Elf_Internal_Phdr *internal;
03306   unsigned int i;
03307 
03308   phdrs = get_data (NULL, file, elf_header.e_phoff,
03309                   elf_header.e_phentsize, elf_header.e_phnum,
03310                   _("program headers"));
03311   if (!phdrs)
03312     return 0;
03313 
03314   for (i = 0, internal = program_headers, external = phdrs;
03315        i < elf_header.e_phnum;
03316        i++, internal++, external++)
03317     {
03318       internal->p_type   = BYTE_GET (external->p_type);
03319       internal->p_flags  = BYTE_GET (external->p_flags);
03320       internal->p_offset = BYTE_GET (external->p_offset);
03321       internal->p_vaddr  = BYTE_GET (external->p_vaddr);
03322       internal->p_paddr  = BYTE_GET (external->p_paddr);
03323       internal->p_filesz = BYTE_GET (external->p_filesz);
03324       internal->p_memsz  = BYTE_GET (external->p_memsz);
03325       internal->p_align  = BYTE_GET (external->p_align);
03326     }
03327 
03328   free (phdrs);
03329 
03330   return 1;
03331 }
03332 
03333 /* Returns 1 if the program headers were read into `program_headers'.  */
03334 
03335 static int
03336 get_program_headers (FILE *file)
03337 {
03338   Elf_Internal_Phdr *phdrs;
03339 
03340   /* Check cache of prior read.  */
03341   if (program_headers != NULL)
03342     return 1;
03343 
03344   phdrs = cmalloc (elf_header.e_phnum, sizeof (Elf_Internal_Phdr));
03345 
03346   if (phdrs == NULL)
03347     {
03348       error (_("Out of memory\n"));
03349       return 0;
03350     }
03351 
03352   if (is_32bit_elf
03353       ? get_32bit_program_headers (file, phdrs)
03354       : get_64bit_program_headers (file, phdrs))
03355     {
03356       program_headers = phdrs;
03357       return 1;
03358     }
03359 
03360   free (phdrs);
03361   return 0;
03362 }
03363 
03364 /* Returns 1 if the program headers were loaded.  */
03365 
03366 static int
03367 process_program_headers (FILE *file)
03368 {
03369   Elf_Internal_Phdr *segment;
03370   unsigned int i;
03371 
03372   if (elf_header.e_phnum == 0)
03373     {
03374       if (do_segments)
03375        printf (_("\nThere are no program headers in this file.\n"));
03376       return 0;
03377     }
03378 
03379   if (do_segments && !do_header)
03380     {
03381       printf (_("\nElf file type is %s\n"), get_file_type (elf_header.e_type));
03382       printf (_("Entry point "));
03383       print_vma ((bfd_vma) elf_header.e_entry, PREFIX_HEX);
03384       printf (_("\nThere are %d program headers, starting at offset "),
03385              elf_header.e_phnum);
03386       print_vma ((bfd_vma) elf_header.e_phoff, DEC);
03387       printf ("\n");
03388     }
03389 
03390   if (! get_program_headers (file))
03391       return 0;
03392 
03393   if (do_segments)
03394     {
03395       if (elf_header.e_phnum > 1)
03396        printf (_("\nProgram Headers:\n"));
03397       else
03398        printf (_("\nProgram Headers:\n"));
03399 
03400       if (is_32bit_elf)
03401        printf
03402          (_("  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align\n"));
03403       else if (do_wide)
03404        printf
03405          (_("  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align\n"));
03406       else
03407        {
03408          printf
03409            (_("  Type           Offset             VirtAddr           PhysAddr\n"));
03410          printf
03411            (_("                 FileSiz            MemSiz              Flags  Align\n"));
03412        }
03413     }
03414 
03415   dynamic_addr = 0;
03416   dynamic_size = 0;
03417 
03418   for (i = 0, segment = program_headers;
03419        i < elf_header.e_phnum;
03420        i++, segment++)
03421     {
03422       if (do_segments)
03423        {
03424          printf ("  %-14.14s ", get_segment_type (segment->p_type));
03425 
03426          if (is_32bit_elf)
03427            {
03428              printf ("0x%6.6lx ", (unsigned long) segment->p_offset);
03429              printf ("0x%8.8lx ", (unsigned long) segment->p_vaddr);
03430              printf ("0x%8.8lx ", (unsigned long) segment->p_paddr);
03431              printf ("0x%5.5lx ", (unsigned long) segment->p_filesz);
03432              printf ("0x%5.5lx ", (unsigned long) segment->p_memsz);
03433              printf ("%c%c%c ",
03434                     (segment->p_flags & PF_R ? 'R' : ' '),
03435                     (segment->p_flags & PF_W ? 'W' : ' '),
03436                     (segment->p_flags & PF_X ? 'E' : ' '));
03437              printf ("%#lx", (unsigned long) segment->p_align);
03438            }
03439          else if (do_wide)
03440            {
03441              if ((unsigned long) segment->p_offset == segment->p_offset)
03442               printf ("0x%6.6lx ", (unsigned long) segment->p_offset);
03443              else
03444               {
03445                 print_vma (segment->p_offset, FULL_HEX);
03446                 putchar (' ');
03447               }
03448 
03449              print_vma (segment->p_vaddr, FULL_HEX);
03450              putchar (' ');
03451              print_vma (segment->p_paddr, FULL_HEX);
03452              putchar (' ');
03453 
03454              if ((unsigned long) segment->p_filesz == segment->p_filesz)
03455               printf ("0x%6.6lx ", (unsigned long) segment->p_filesz);
03456              else
03457               {
03458                 print_vma (segment->p_filesz, FULL_HEX);
03459                 putchar (' ');
03460               }
03461 
03462              if ((unsigned long) segment->p_memsz == segment->p_memsz)
03463               printf ("0x%6.6lx", (unsigned long) segment->p_memsz);
03464              else
03465               {
03466                 print_vma (segment->p_offset, FULL_HEX);
03467               }
03468 
03469              printf (" %c%c%c ",
03470                     (segment->p_flags & PF_R ? 'R' : ' '),
03471                     (segment->p_flags & PF_W ? 'W' : ' '),
03472                     (segment->p_flags & PF_X ? 'E' : ' '));
03473 
03474              if ((unsigned long) segment->p_align == segment->p_align)
03475               printf ("%#lx", (unsigned long) segment->p_align);
03476              else
03477               {
03478                 print_vma (segment->p_align, PREFIX_HEX);
03479               }
03480            }
03481          else
03482            {
03483              print_vma (segment->p_offset, FULL_HEX);
03484              putchar (' ');
03485              print_vma (segment->p_vaddr, FULL_HEX);
03486              putchar (' ');
03487              print_vma (segment->p_paddr, FULL_HEX);
03488              printf ("\n                 ");
03489              print_vma (segment->p_filesz, FULL_HEX);
03490              putchar (' ');
03491              print_vma (segment->p_memsz, FULL_HEX);
03492              printf ("  %c%c%c    ",
03493                     (segment->p_flags & PF_R ? 'R' : ' '),
03494                     (segment->p_flags & PF_W ? 'W' : ' '),
03495                     (segment->p_flags & PF_X ? 'E' : ' '));
03496              print_vma (segment->p_align, HEX);
03497            }
03498        }
03499 
03500       switch (segment->p_type)
03501        {
03502        case PT_DYNAMIC:
03503          if (dynamic_addr)
03504            error (_("more than one dynamic segment\n"));
03505 
03506          /* Try to locate the .dynamic section. If there is
03507             a section header table, we can easily locate it.  */
03508          if (section_headers != NULL)
03509            {
03510              Elf_Internal_Shdr *sec;
03511 
03512              sec = find_section (".dynamic");
03513              if (sec == NULL || sec->sh_size == 0)
03514               {
03515                 error (_("no .dynamic section in the dynamic segment\n"));
03516                 break;
03517               }
03518 
03519              dynamic_addr = sec->sh_offset;
03520              dynamic_size = sec->sh_size;
03521 
03522              if (dynamic_addr < segment->p_offset
03523                 || dynamic_addr > segment->p_offset + segment->p_filesz)
03524               warn (_("the .dynamic section is not contained within the dynamic segment\n"));
03525              else if (dynamic_addr > segment->p_offset)
03526               warn (_("the .dynamic section is not the first section in the dynamic segment.\n"));
03527            }
03528          else
03529            {
03530              /* Otherwise, we can only assume that the .dynamic
03531                section is the first section in the DYNAMIC segment.  */
03532              dynamic_addr = segment->p_offset;
03533              dynamic_size = segment->p_filesz;
03534            }
03535          break;
03536 
03537        case PT_INTERP:
03538          if (fseek (file, archive_file_offset + (long) segment->p_offset,
03539                    SEEK_SET))
03540            error (_("Unable to find program interpreter name\n"));
03541          else
03542            {
03543              char fmt [32];
03544              int ret = snprintf (fmt, sizeof (fmt), "%%%ds", PATH_MAX);
03545 
03546              if (ret >= (int) sizeof (fmt) || ret < 0)
03547               error (_("Internal error: failed to create format string to display program interpreter\n"));
03548 
03549              program_interpreter[0] = 0;
03550              if (fscanf (file, fmt, program_interpreter) <= 0)
03551               error (_("Unable to read program interpreter name\n"));
03552 
03553              if (do_segments)
03554               printf (_("\n      [Requesting program interpreter: %s]"),
03555                   program_interpreter);
03556            }
03557          break;
03558        }
03559 
03560       if (do_segments)
03561        putc ('\n', stdout);
03562     }
03563 
03564   if (do_segments && section_headers != NULL && string_table != NULL)
03565     {
03566       printf (_("\n Section to Segment mapping:\n"));
03567       printf (_("  Segment Sections...\n"));
03568 
03569       for (i = 0; i < elf_header.e_phnum; i++)
03570        {
03571          unsigned int j;
03572          Elf_Internal_Shdr *section;
03573 
03574          segment = program_headers + i;
03575          section = section_headers;
03576 
03577          printf ("   %2.2d     ", i);
03578 
03579          for (j = 1; j < elf_header.e_shnum; j++, section++)
03580            {
03581              if (ELF_IS_SECTION_IN_SEGMENT_MEMORY(section, segment))
03582               printf ("%s ", SECTION_NAME (section));
03583            }
03584 
03585          putc ('\n',stdout);
03586        }
03587     }
03588 
03589   return 1;
03590 }
03591 
03592 
03593 /* Find the file offset corresponding to VMA by using the program headers.  */
03594 
03595 static long
03596 offset_from_vma (FILE *file, bfd_vma vma, bfd_size_type size)
03597 {
03598   Elf_Internal_Phdr *seg;
03599 
03600   if (! get_program_headers (file))
03601     {
03602       warn (_("Cannot interpret virtual addresses without program headers.\n"));
03603       return (long) vma;
03604     }
03605 
03606   for (seg = program_headers;
03607        seg < program_headers + elf_header.e_phnum;
03608        ++seg)
03609     {
03610       if (seg->p_type != PT_LOAD)
03611        continue;
03612 
03613       if (vma >= (seg->p_vaddr & -seg->p_align)
03614          && vma + size <= seg->p_vaddr + seg->p_filesz)
03615        return vma - seg->p_vaddr + seg->p_offset;
03616     }
03617 
03618   warn (_("Virtual address 0x%lx not located in any PT_LOAD segment.\n"),
03619        (long) vma);
03620   return (long) vma;
03621 }
03622 
03623 
03624 static int
03625 get_32bit_section_headers (FILE *file, unsigned int num)
03626 {
03627   Elf32_External_Shdr *shdrs;
03628   Elf_Internal_Shdr *internal;
03629   unsigned int i;
03630 
03631   shdrs = get_data (NULL, file, elf_header.e_shoff,
03632                   elf_header.e_shentsize, num, _("section headers"));
03633   if (!shdrs)
03634     return 0;
03635 
03636   section_headers = cmalloc (num, sizeof (Elf_Internal_Shdr));
03637 
03638   if (section_headers == NULL)
03639     {
03640       error (_("Out of memory\n"));
03641       return 0;
03642     }
03643 
03644   for (i = 0, internal = section_headers;
03645        i < num;
03646        i++, internal++)
03647     {
03648       internal->sh_name      = BYTE_GET (shdrs[i].sh_name);
03649       internal->sh_type      = BYTE_GET (shdrs[i].sh_type);
03650       internal->sh_flags     = BYTE_GET (shdrs[i].sh_flags);
03651       internal->sh_addr      = BYTE_GET (shdrs[i].sh_addr);
03652       internal->sh_offset    = BYTE_GET (shdrs[i].sh_offset);
03653       internal->sh_size      = BYTE_GET (shdrs[i].sh_size);
03654       internal->sh_link      = BYTE_GET (shdrs[i].sh_link);
03655       internal->sh_info      = BYTE_GET (shdrs[i].sh_info);
03656       internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
03657       internal->sh_entsize   = BYTE_GET (shdrs[i].sh_entsize);
03658     }
03659 
03660   free (shdrs);
03661 
03662   return 1;
03663 }
03664 
03665 static int
03666 get_64bit_section_headers (FILE *file, unsigned int num)
03667 {
03668   Elf64_External_Shdr *shdrs;
03669   Elf_Internal_Shdr *internal;
03670   unsigned int i;
03671 
03672   shdrs = get_data (NULL, file, elf_header.e_shoff,
03673                   elf_header.e_shentsize, num, _("section headers"));
03674   if (!shdrs)
03675     return 0;
03676 
03677   section_headers = cmalloc (num, sizeof (Elf_Internal_Shdr));
03678 
03679   if (section_headers == NULL)
03680     {
03681       error (_("Out of memory\n"));
03682       return 0;
03683     }
03684 
03685   for (i = 0, internal = section_headers;
03686        i < num;
03687        i++, internal++)
03688     {
03689       internal->sh_name      = BYTE_GET (shdrs[i].sh_name);
03690       internal->sh_type      = BYTE_GET (shdrs[i].sh_type);
03691       internal->sh_flags     = BYTE_GET (shdrs[i].sh_flags);
03692       internal->sh_addr      = BYTE_GET (shdrs[i].sh_addr);
03693       internal->sh_size      = BYTE_GET (shdrs[i].sh_size);
03694       internal->sh_entsize   = BYTE_GET (shdrs[i].sh_entsize);
03695       internal->sh_link      = BYTE_GET (shdrs[i].sh_link);
03696       internal->sh_info      = BYTE_GET (shdrs[i].sh_info);
03697       internal->sh_offset    = BYTE_GET (shdrs[i].sh_offset);
03698       internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
03699     }
03700 
03701   free (shdrs);
03702 
03703   return 1;
03704 }
03705 
03706 static Elf_Internal_Sym *
03707 get_32bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
03708 {
03709   unsigned long number;
03710   Elf32_External_Sym *esyms;
03711   Elf_External_Sym_Shndx *shndx;
03712   Elf_Internal_Sym *isyms;
03713   Elf_Internal_Sym *psym;
03714   unsigned int j;
03715 
03716   esyms = get_data (NULL, file, section->sh_offset, 1, section->sh_size,
03717                   _("symbols"));
03718   if (!esyms)
03719     return NULL;
03720 
03721   shndx = NULL;
03722   if (symtab_shndx_hdr != NULL
03723       && (symtab_shndx_hdr->sh_link
03724          == (unsigned long) SECTION_HEADER_NUM (section - section_headers)))
03725     {
03726       shndx = get_data (NULL, file, symtab_shndx_hdr->sh_offset,
03727                      1, symtab_shndx_hdr->sh_size, _("symtab shndx"));
03728       if (!shndx)
03729        {
03730          free (esyms);
03731          return NULL;
03732        }
03733     }
03734 
03735   number = section->sh_size / section->sh_entsize;
03736   isyms = cmalloc (number, sizeof (Elf_Internal_Sym));
03737 
03738   if (isyms == NULL)
03739     {
03740       error (_("Out of memory\n"));
03741       if (shndx)
03742        free (shndx);
03743       free (esyms);
03744       return NULL;
03745     }
03746 
03747   for (j = 0, psym = isyms;
03748        j < number;
03749        j++, psym++)
03750     {
03751       psym->st_name  = BYTE_GET (esyms[j].st_name);
03752       psym->st_value = BYTE_GET (esyms[j].st_value);
03753       psym->st_size  = BYTE_GET (esyms[j].st_size);
03754       psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
03755       if (psym->st_shndx == SHN_XINDEX && shndx != NULL)
03756        psym->st_shndx
03757          = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j]));
03758       psym->st_info  = BYTE_GET (esyms[j].st_info);
03759       psym->st_other = BYTE_GET (esyms[j].st_other);
03760     }
03761 
03762   if (shndx)
03763     free (shndx);
03764   free (esyms);
03765 
03766   return isyms;
03767 }
03768 
03769 static Elf_Internal_Sym *
03770 get_64bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
03771 {
03772   unsigned long number;
03773   Elf64_External_Sym *esyms;
03774   Elf_External_Sym_Shndx *shndx;
03775   Elf_Internal_Sym *isyms;
03776   Elf_Internal_Sym *psym;
03777   unsigned int j;
03778 
03779   esyms = get_data (NULL, file, section->sh_offset, 1, section->sh_size,
03780                   _("symbols"));
03781   if (!esyms)
03782     return NULL;
03783 
03784   shndx = NULL;
03785   if (symtab_shndx_hdr != NULL
03786       && (symtab_shndx_hdr->sh_link
03787          == (unsigned long) SECTION_HEADER_NUM (section - section_headers)))
03788     {
03789       shndx = get_data (NULL, file, symtab_shndx_hdr->sh_offset,
03790                      1, symtab_shndx_hdr->sh_size, _("symtab shndx"));
03791       if (!shndx)
03792        {
03793          free (esyms);
03794          return NULL;
03795        }
03796     }
03797 
03798   number = section->sh_size / section->sh_entsize;
03799   isyms = cmalloc (number, sizeof (Elf_Internal_Sym));
03800 
03801   if (isyms == NULL)
03802     {
03803       error (_("Out of memory\n"));
03804       if (shndx)
03805        free (shndx);
03806       free (esyms);
03807       return NULL;
03808     }
03809 
03810   for (j = 0, psym = isyms;
03811        j < number;
03812        j++, psym++)
03813     {
03814       psym->st_name  = BYTE_GET (esyms[j].st_name);
03815       psym->st_info  = BYTE_GET (esyms[j].st_info);
03816       psym->st_other = BYTE_GET (esyms[j].st_other);
03817       psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
03818       if (psym->st_shndx == SHN_XINDEX && shndx != NULL)
03819        psym->st_shndx
03820          = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j]));
03821       psym->st_value = BYTE_GET (esyms[j].st_value);
03822       psym->st_size  = BYTE_GET (esyms[j].st_size);
03823     }
03824 
03825   if (shndx)
03826     free (shndx);
03827   free (esyms);
03828 
03829   return isyms;
03830 }
03831 
03832 static const char *
03833 get_elf_section_flags (bfd_vma sh_flags)
03834 {
03835   static char buff[1024];
03836   char *p = buff;
03837   int field_size = is_32bit_elf ? 8 : 16;
03838   int index, size = sizeof (buff) - (field_size + 4 + 1);
03839   bfd_vma os_flags = 0;
03840   bfd_vma proc_flags = 0;
03841   bfd_vma unknown_flags = 0;
03842   const struct
03843     {
03844       const char *str;
03845       int len;
03846     }
03847   flags [] =
03848     {
03849        { "WRITE", 5 },
03850        { "ALLOC", 5 },
03851        { "EXEC", 4 },
03852        { "MERGE", 5 },
03853        { "STRINGS", 7 },
03854        { "INFO LINK", 9 },
03855        { "LINK ORDER", 10 },
03856        { "OS NONCONF", 10 },
03857        { "GROUP", 5 },
03858        { "TLS", 3 }
03859     };
03860 
03861   if (do_section_details)
03862     {
03863       sprintf (buff, "[%*.*lx]: ",
03864               field_size, field_size, (unsigned long) sh_flags);
03865       p += field_size + 4;
03866     }
03867 
03868   while (sh_flags)
03869     {
03870       bfd_vma flag;
03871 
03872       flag = sh_flags & - sh_flags;
03873       sh_flags &= ~ flag;
03874 
03875       if (do_section_details)
03876        {
03877          switch (flag)
03878            {
03879            case SHF_WRITE:         index = 0; break;
03880            case SHF_ALLOC:         index = 1; break;
03881            case SHF_EXECINSTR:            index = 2; break;
03882            case SHF_MERGE:         index = 3; break;
03883            case SHF_STRINGS:              index = 4; break;
03884            case SHF_INFO_LINK:            index = 5; break;
03885            case SHF_LINK_ORDER:    index = 6; break;
03886            case SHF_OS_NONCONFORMING:     index = 7; break;
03887            case SHF_GROUP:         index = 8; break;
03888            case SHF_TLS:           index = 9; break;
03889 
03890            default:
03891              index = -1;
03892              break;
03893            }
03894 
03895          if (index != -1)
03896            {
03897              if (p != buff + field_size + 4)
03898               {
03899                 if (size < (10 + 2))
03900                   abort ();
03901                 size -= 2;
03902                 *p++ = ',';
03903                 *p++ = ' ';
03904               }
03905 
03906              size -= flags [index].len;
03907              p = stpcpy (p, flags [index].str);
03908            }
03909          else if (flag & SHF_MASKOS)
03910            os_flags |= flag;
03911          else if (flag & SHF_MASKPROC)
03912            proc_flags |= flag;
03913          else
03914            unknown_flags |= flag;
03915        }
03916       else
03917        {
03918          switch (flag)
03919            {
03920            case SHF_WRITE:         *p = 'W'; break;
03921            case SHF_ALLOC:         *p = 'A'; break;
03922            case SHF_EXECINSTR:            *p = 'X'; break;
03923            case SHF_MERGE:         *p = 'M'; break;
03924            case SHF_STRINGS:              *p = 'S'; break;
03925            case SHF_INFO_LINK:            *p = 'I'; break;
03926            case SHF_LINK_ORDER:    *p = 'L'; break;
03927            case SHF_OS_NONCONFORMING:     *p = 'O'; break;
03928            case SHF_GROUP:         *p = 'G'; break;
03929            case SHF_TLS:           *p = 'T'; break;
03930 
03931            default:
03932              if (elf_header.e_machine == EM_X86_64
03933                 && flag == SHF_X86_64_LARGE)
03934               *p = 'l';
03935              else if (flag & SHF_MASKOS)
03936               {
03937                 *p = 'o';
03938                 sh_flags &= ~ SHF_MASKOS;
03939               }
03940              else if (flag & SHF_MASKPROC)
03941               {
03942                 *p = 'p';
03943                 sh_flags &= ~ SHF_MASKPROC;
03944               }
03945              else
03946               *p = 'x';
03947              break;
03948            }
03949          p++;
03950        }
03951     }
03952 
03953   if (do_section_details)
03954     {
03955       if (os_flags)
03956        {
03957          size -= 5 + field_size;
03958          if (p != buff + field_size + 4)
03959            {
03960              if (size < (2 + 1))
03961               abort ();
03962              size -= 2;
03963              *p++ = ',';
03964              *p++ = ' ';
03965            }
03966          sprintf (p, "OS (%*.*lx)", field_size, field_size,
03967                  (unsigned long) os_flags);
03968          p += 5 + field_size;
03969        }
03970       if (proc_flags)
03971        {
03972          size -= 7 + field_size;
03973          if (p != buff + field_size + 4)
03974            {
03975              if (size < (2 + 1))
03976               abort ();
03977              size -= 2;
03978              *p++ = ',';
03979              *p++ = ' ';
03980            }
03981          sprintf (p, "PROC (%*.*lx)", field_size, field_size,
03982                  (unsigned long) proc_flags);
03983          p += 7 + field_size;
03984        }
03985       if (unknown_flags)
03986        {
03987          size -= 10 + field_size;
03988          if (p != buff + field_size + 4)
03989            {
03990              if (size < (2 + 1))
03991               abort ();
03992              size -= 2;
03993              *p++ = ',';
03994              *p++ = ' ';
03995            }
03996          sprintf (p, "UNKNOWN (%*.*lx)", field_size, field_size,
03997                  (unsigned long) unknown_flags);
03998          p += 10 + field_size;
03999        }
04000     }
04001 
04002   *p = '\0';
04003   return buff;
04004 }
04005 
04006 static int
04007 process_section_headers (FILE *file)
04008 {
04009   Elf_Internal_Shdr *section;
04010   unsigned int i;
04011 
04012   section_headers = NULL;
04013 
04014   if (elf_header.e_shnum == 0)
04015     {
04016       if (do_sections)
04017        printf (_("\nThere are no sections in this file.\n"));
04018 
04019       return 1;
04020     }
04021 
04022   if (do_sections && !do_header)
04023     printf (_("There are %d section headers, starting at offset 0x%lx:\n"),
04024            elf_header.e_shnum, (unsigned long) elf_header.e_shoff);
04025 
04026   if (is_32bit_elf)
04027     {
04028       if (! get_32bit_section_headers (file, elf_header.e_shnum))
04029        return 0;
04030     }
04031   else if (! get_64bit_section_headers (file, elf_header.e_shnum))
04032     return 0;
04033 
04034   /* Read in the string table, so that we have names to display.  */
04035   if (elf_header.e_shstrndx != SHN_UNDEF
04036        && SECTION_HEADER_INDEX (elf_header.e_shstrndx) < elf_header.e_shnum)
04037     {
04038       section = SECTION_HEADER (elf_header.e_shstrndx);
04039 
04040       if (section->sh_size != 0)
04041        {
04042          string_table = get_data (NULL, file, section->sh_offset,
04043                                1, section->sh_size, _("string table"));
04044 
04045          string_table_length = string_table != NULL ? section->sh_size : 0;
04046        }
04047     }
04048 
04049   /* Scan the sections for the dynamic symbol table
04050      and dynamic string table and debug sections.  */
04051   dynamic_symbols = NULL;
04052   dynamic_strings = NULL;
04053   dynamic_syminfo = NULL;
04054   symtab_shndx_hdr = NULL;
04055 
04056   eh_addr_size = is_32bit_elf ? 4 : 8;
04057   switch (elf_header.e_machine)
04058     {
04059     case EM_MIPS:
04060     case EM_MIPS_RS3_LE:
04061       /* The 64-bit MIPS EABI uses a combination of 32-bit ELF and 64-bit
04062         FDE addresses.  However, the ABI also has a semi-official ILP32
04063         variant for which the normal FDE address size rules apply.
04064 
04065         GCC 4.0 marks EABI64 objects with a dummy .gcc_compiled_longXX
04066         section, where XX is the size of longs in bits.  Unfortunately,
04067         earlier compilers provided no way of distinguishing ILP32 objects
04068         from LP64 objects, so if there's any doubt, we should assume that
04069         the official LP64 form is being used.  */
04070       if ((elf_header.e_flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI64
04071          && find_section (".gcc_compiled_long32") == NULL)
04072        eh_addr_size = 8;
04073       break;
04074 
04075     case EM_H8_300:
04076     case EM_H8_300H:
04077       switch (elf_header.e_flags & EF_H8_MACH)
04078        {
04079        case E_H8_MACH_H8300:
04080        case E_H8_MACH_H8300HN:
04081        case E_H8_MACH_H8300SN:
04082        case E_H8_MACH_H8300SXN:
04083          eh_addr_size = 2;
04084          break;
04085        case E_H8_MACH_H8300H:
04086        case E_H8_MACH_H8300S:
04087        case E_H8_MACH_H8300SX:
04088          eh_addr_size = 4;
04089          break;
04090        }
04091     }
04092 
04093 #define CHECK_ENTSIZE_VALUES(section, i, size32, size64) \
04094   do                                                               \
04095     {                                                              \
04096       size_t expected_entsize                                             \
04097        = is_32bit_elf ? size32 : size64;                           \
04098       if (section->sh_entsize != expected_entsize)                        \
04099        error (_("Section %d has invalid sh_entsize %lx (expected %lx)\n"), \
04100               i, (unsigned long int) section->sh_entsize,                 \
04101               (unsigned long int) expected_entsize);                      \
04102       section->sh_entsize = expected_entsize;                             \
04103     }                                                              \
04104   while (0)
04105 #define CHECK_ENTSIZE(section, i, type) \
04106   CHECK_ENTSIZE_VALUES (section, i, sizeof (Elf32_External_##type),       \
04107                      sizeof (Elf64_External_##type))
04108 
04109   for (i = 0, section = section_headers;
04110        i < elf_header.e_shnum;
04111        i++, section++)
04112     {
04113       char *name = SECTION_NAME (section);
04114 
04115       if (section->sh_type == SHT_DYNSYM)
04116        {
04117          if (dynamic_symbols != NULL)
04118            {
04119              error (_("File contains multiple dynamic symbol tables\n"));
04120              continue;
04121            }
04122 
04123          CHECK_ENTSIZE (section, i, Sym);
04124          num_dynamic_syms = section->sh_size / section->sh_entsize;
04125          dynamic_symbols = GET_ELF_SYMBOLS (file, section);
04126        }
04127       else if (section->sh_type == SHT_STRTAB
04128               && streq (name, ".dynstr"))
04129        {
04130          if (dynamic_strings != NULL)
04131            {
04132              error (_("File contains multiple dynamic string tables\n"));
04133              continue;
04134            }
04135 
04136          dynamic_strings = get_data (NULL, file, section->sh_offset,
04137                                   1, section->sh_size, _("dynamic strings"));
04138          dynamic_strings_length = section->sh_size;
04139        }
04140       else if (section->sh_type == SHT_SYMTAB_SHNDX)
04141        {
04142          if (symtab_shndx_hdr != NULL)
04143            {
04144              error (_("File contains multiple symtab shndx tables\n"));
04145              continue;
04146            }
04147          symtab_shndx_hdr = section;
04148        }
04149       else if (section->sh_type == SHT_SYMTAB)
04150        CHECK_ENTSIZE (section, i, Sym);
04151       else if (section->sh_type == SHT_GROUP)
04152        CHECK_ENTSIZE_VALUES (section, i, GRP_ENTRY_SIZE, GRP_ENTRY_SIZE);
04153       else if (section->sh_type == SHT_REL)
04154        CHECK_ENTSIZE (section, i, Rel);
04155       else if (section->sh_type == SHT_RELA)
04156        CHECK_ENTSIZE (section, i, Rela);
04157       else if ((do_debugging || do_debug_info || do_debug_abbrevs
04158               || do_debug_lines || do_debug_pubnames || do_debug_aranges
04159               || do_debug_frames || do_debug_macinfo || do_debug_str
04160               || do_debug_loc || do_debug_ranges)
04161               && const_strneq (name, ".debug_"))
04162        {
04163          name += 7;
04164 
04165          if (do_debugging
04166              || (do_debug_info     && streq (name, "info"))
04167              || (do_debug_abbrevs  && streq (name, "abbrev"))
04168              || (do_debug_lines    && streq (name, "line"))
04169              || (do_debug_pubnames && streq (name, "pubnames"))
04170              || (do_debug_aranges  && streq (name, "aranges"))
04171              || (do_debug_ranges   && streq (name, "ranges"))
04172              || (do_debug_frames   && streq (name, "frame"))
04173              || (do_debug_macinfo  && streq (name, "macinfo"))
04174              || (do_debug_str      && streq (name, "str"))
04175              || (do_debug_loc      && streq (name, "loc"))
04176              )
04177            request_dump (i, DEBUG_DUMP);
04178        }
04179       /* linkonce section to be combined with .debug_info at link time.  */
04180       else if ((do_debugging || do_debug_info)
04181               && const_strneq (name, ".gnu.linkonce.wi."))
04182        request_dump (i, DEBUG_DUMP);
04183       else if (do_debug_frames && streq (name, ".eh_frame"))
04184        request_dump (i, DEBUG_DUMP);
04185     }
04186 
04187   if (! do_sections)
04188     return 1;
04189 
04190   if (elf_header.e_shnum > 1)
04191     printf (_("\nSection Headers:\n"));
04192   else
04193     printf (_("\nSection Header:\n"));
04194 
04195   if (is_32bit_elf)
04196     {
04197       if (do_section_details)
04198        {
04199          printf (_("  [Nr] Name\n"));
04200          printf (_("       Type            Addr     Off    Size   ES   Lk Inf Al\n"));
04201        }
04202       else
04203        printf
04204          (_("  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al\n"));
04205     }
04206   else if (do_wide)
04207     {
04208       if (do_section_details)
04209        {
04210          printf (_("  [Nr] Name\n"));
04211          printf (_("       Type            Address          Off    Size   ES   Lk Inf Al\n"));
04212        }
04213       else
04214        printf
04215          (_("  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al\n"));
04216     }
04217   else
04218     {
04219       if (do_section_details)
04220        {
04221          printf (_("  [Nr] Name\n"));
04222          printf (_("       Type              Address          Offset            Link\n"));
04223          printf (_("       Size              EntSize          Info              Align\n"));
04224        }
04225       else
04226        {
04227          printf (_("  [Nr] Name              Type             Address           Offset\n"));
04228          printf (_("       Size              EntSize          Flags  Link  Info  Align\n"));
04229        }
04230     }
04231 
04232   if (do_section_details)
04233     printf (_("       Flags\n"));
04234 
04235   for (i = 0, section = section_headers;
04236        i < elf_header.e_shnum;
04237        i++, section++)
04238     {
04239       if (do_section_details)
04240        {
04241          printf ("  [%2u] %s\n",
04242                 SECTION_HEADER_NUM (i),
04243                 SECTION_NAME (section));
04244          if (is_32bit_elf || do_wide)
04245            printf ("       %-15.15s ",
04246                   get_section_type_name (section->sh_type));
04247        }
04248       else
04249        printf ("  [%2u] %-17.17s %-15.15s ",
04250               SECTION_HEADER_NUM (i),
04251               SECTION_NAME (section),
04252               get_section_type_name (section->sh_type));
04253 
04254       if (is_32bit_elf)
04255        {
04256          print_vma (section->sh_addr, LONG_HEX);
04257 
04258          printf ( " %6.6lx %6.6lx %2.2lx",
04259                  (unsigned long) section->sh_offset,
04260                  (unsigned long) section->sh_size,
04261                  (unsigned long) section->sh_entsize);
04262 
04263          if (do_section_details)
04264            fputs ("  ", stdout);
04265          else
04266            printf (" %3s ", get_elf_section_flags (section->sh_flags));
04267 
04268          printf ("%2ld %3lu %2ld\n",
04269                 (unsigned long) section->sh_link,
04270                 (unsigned long) section->sh_info,
04271                 (unsigned long) section->sh_addralign);
04272        }
04273       else if (do_wide)
04274        {
04275          print_vma (section->sh_addr, LONG_HEX);
04276 
04277          if ((long) section->sh_offset == section->sh_offset)
04278            printf (" %6.6lx", (unsigned long) section->sh_offset);
04279          else
04280            {
04281              putchar (' ');
04282              print_vma (section->sh_offset, LONG_HEX);
04283            }
04284 
04285          if ((unsigned long) section->sh_size == section->sh_size)
04286            printf (" %6.6lx", (unsigned long) section->sh_size);
04287          else
04288            {
04289              putchar (' ');
04290              print_vma (section->sh_size, LONG_HEX);
04291            }
04292 
04293          if ((unsigned long) section->sh_entsize == section->sh_entsize)
04294            printf (" %2.2lx", (unsigned long) section->sh_entsize);
04295          else
04296            {
04297              putchar (' ');
04298              print_vma (section->sh_entsize, LONG_HEX);
04299            }
04300 
04301          if (do_section_details)
04302            fputs ("  ", stdout);
04303          else
04304            printf (" %3s ", get_elf_section_flags (section->sh_flags));
04305 
04306          printf ("%2ld %3lu ",
04307                 (unsigned long) section->sh_link,
04308                 (unsigned long) section->sh_info);
04309 
04310          if ((unsigned long) section->sh_addralign == section->sh_addralign)
04311            printf ("%2ld\n", (unsigned long) section->sh_addralign);
04312          else
04313            {
04314              print_vma (section->sh_addralign, DEC);
04315              putchar ('\n');
04316            }
04317        }
04318       else if (do_section_details)
04319        {
04320          printf ("       %-15.15s  ",
04321                 get_section_type_name (section->sh_type));
04322          print_vma (section->sh_addr, LONG_HEX);
04323          if ((long) section->sh_offset == section->sh_offset)
04324            printf ("  %16.16lx", (unsigned long) section->sh_offset);
04325          else
04326            {
04327              printf ("  ");
04328              print_vma (section->sh_offset, LONG_HEX);
04329            }
04330          printf ("  %ld\n       ", (unsigned long) section->sh_link);
04331          print_vma (section->sh_size, LONG_HEX);
04332          putchar (' ');
04333          print_vma (section->sh_entsize, LONG_HEX);
04334 
04335          printf ("  %-16lu  %ld\n",
04336                 (unsigned long) section->sh_info,
04337                 (unsigned long) section->sh_addralign);
04338        }
04339       else
04340        {
04341          putchar (' ');
04342          print_vma (section->sh_addr, LONG_HEX);
04343          if ((long) section->sh_offset == section->sh_offset)
04344            printf ("  %8.8lx", (unsigned long) section->sh_offset);
04345          else
04346            {
04347              printf ("  ");
04348              print_vma (section->sh_offset, LONG_HEX);
04349            }
04350          printf ("\n       ");
04351          print_vma (section->sh_size, LONG_HEX);
04352          printf ("  ");
04353          print_vma (section->sh_entsize, LONG_HEX);
04354 
04355          printf (" %3s ", get_elf_section_flags (section->sh_flags));
04356 
04357          printf ("     %2ld   %3lu     %ld\n",
04358                 (unsigned long) section->sh_link,
04359                 (unsigned long) section->sh_info,
04360                 (unsigned long) section->sh_addralign);
04361        }
04362 
04363       if (do_section_details)
04364        printf ("       %s\n", get_elf_section_flags (section->sh_flags));
04365     }
04366 
04367   if (!do_section_details)
04368     printf (_("Key to Flags:\n\
04369   W (write), A (alloc), X (execute), M (merge), S (strings)\n\
04370   I (info), L (link order), G (group), x (unknown)\n\
04371   O (extra OS processing required) o (OS specific), p (processor specific)\n"));
04372 
04373   return 1;
04374 }
04375 
04376 static const char *
04377 get_group_flags (unsigned int flags)
04378 {
04379   static char buff[32];
04380   switch (flags)
04381     {
04382     case GRP_COMDAT:
04383       return "COMDAT";
04384 
04385    default:
04386       snprintf (buff, sizeof (buff), _("[<unknown>: 0x%x]"), flags);
04387       break;
04388     }
04389   return buff;
04390 }
04391 
04392 static int
04393 process_section_groups (FILE *file)
04394 {
04395   Elf_Internal_Shdr *section;
04396   unsigned int i;
04397   struct group *group;
04398   Elf_Internal_Shdr *symtab_sec, *strtab_sec;
04399   Elf_Internal_Sym *symtab;
04400   char *strtab;
04401   size_t strtab_size;
04402 
04403   /* Don't process section groups unless needed.  */
04404   if (!do_unwind && !do_section_groups)
04405     return 1;
04406 
04407   if (elf_header.e_shnum == 0)
04408     {
04409       if (do_section_groups)
04410        printf (_("\nThere are no sections in this file.\n"));
04411 
04412       return 1;
04413     }
04414 
04415   if (section_headers == NULL)
04416     {
04417       error (_("Section headers are not available!\n"));
04418       abort ();
04419     }
04420 
04421   section_headers_groups = calloc (elf_header.e_shnum,
04422                                sizeof (struct group *));
04423 
04424   if (section_headers_groups == NULL)
04425     {
04426       error (_("Out of memory\n"));
04427       return 0;
04428     }
04429 
04430   /* Scan the sections for the group section.  */
04431   group_count = 0;
04432   for (i = 0, section = section_headers;
04433        i < elf_header.e_shnum;
04434        i++, section++)
04435     if (section->sh_type == SHT_GROUP)
04436       group_count++;
04437 
04438   if (group_count == 0)
04439     {
04440       if (do_section_groups)
04441        printf (_("\nThere are no section groups in this file.\n"));
04442 
04443       return 1;
04444     }
04445 
04446   section_groups = calloc (group_count, sizeof (struct group));
04447 
04448   if (section_groups == NULL)
04449     {
04450       error (_("Out of memory\n"));
04451       return 0;
04452     }
04453 
04454   symtab_sec = NULL;
04455   strtab_sec = NULL;
04456   symtab = NULL;
04457   strtab = NULL;
04458   strtab_size = 0;
04459   for (i = 0, section = section_headers, group = section_groups;
04460        i < elf_header.e_shnum;
04461        i++, section++)
04462     {
04463       if (section->sh_type == SHT_GROUP)
04464        {
04465          char *name = SECTION_NAME (section);
04466          char *group_name;
04467          unsigned char *start, *indices;
04468          unsigned int entry, j, size;
04469          Elf_Internal_Shdr *sec;
04470          Elf_Internal_Sym *sym;
04471 
04472          /* Get the symbol table.  */
04473          if (SECTION_HEADER_INDEX (section->sh_link) >= elf_header.e_shnum
04474              || ((sec = SECTION_HEADER (section->sh_link))->sh_type
04475                 != SHT_SYMTAB))
04476            {
04477              error (_("Bad sh_link in group section `%s'\n"), name);
04478              continue;
04479            }
04480 
04481          if (symtab_sec != sec)
04482            {
04483              symtab_sec = sec;
04484              if (symtab)
04485               free (symtab);
04486              symtab = GET_ELF_SYMBOLS (file, symtab_sec);
04487            }
04488 
04489          sym = symtab + section->sh_info;
04490 
04491          if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
04492            {
04493              bfd_vma sec_index = SECTION_HEADER_INDEX (sym->st_shndx);
04494              if (sec_index == 0)
04495               {
04496                 error (_("Bad sh_info in group section `%s'\n"), name);
04497                 continue;
04498               }
04499 
04500              group_name = SECTION_NAME (section_headers + sec_index);
04501              strtab_sec = NULL;
04502              if (strtab)
04503               free (strtab);
04504              strtab = NULL;
04505              strtab_size = 0;
04506            }
04507          else
04508            {
04509              /* Get the string table.  */
04510              if (SECTION_HEADER_INDEX (symtab_sec->sh_link)
04511                 >= elf_header.e_shnum)
04512               {
04513                 strtab_sec = NULL;
04514                 if (strtab)
04515                   free (strtab);
04516                 strtab = NULL;
04517                 strtab_size = 0;
04518               }
04519              else if (strtab_sec
04520                      != (sec = SECTION_HEADER (symtab_sec->sh_link)))
04521               {
04522                 strtab_sec = sec;
04523                 if (strtab)
04524                   free (strtab);
04525                 strtab = get_data (NULL, file, strtab_sec->sh_offset,
04526                                  1, strtab_sec->sh_size,
04527                                  _("string table"));
04528                 strtab_size = strtab != NULL ? strtab_sec->sh_size : 0;
04529               }
04530              group_name = sym->st_name < strtab_size
04531                         ? strtab + sym->st_name : "<corrupt>";
04532            }
04533 
04534          start = get_data (NULL, file, section->sh_offset,
04535                          1, section->sh_size, _("section data"));
04536 
04537          indices = start;
04538          size = (section->sh_size / section->sh_entsize) - 1;
04539          entry = byte_get (indices, 4);
04540          indices += 4;
04541 
04542          if (do_section_groups)
04543            {
04544              printf ("\n%s group section [%5u] `%s' [%s] contains %u sections:\n",
04545                     get_group_flags (entry), i, name, group_name, size);
04546 
04547              printf (_("   [Index]    Name\n"));
04548            }
04549 
04550          group->group_index = i;
04551 
04552          for (j = 0; j < size; j++)
04553            {
04554              struct group_list *g;
04555 
04556              entry = byte_get (indices, 4);
04557              indices += 4;
04558 
04559              if (SECTION_HEADER_INDEX (entry) >= elf_header.e_shnum)
04560               {
04561                 error (_("section [%5u] in group section [%5u] > maximum section [%5u]\n"),
04562                       entry, i, elf_header.e_shnum - 1);
04563                 continue;
04564               }
04565              else if (entry >= SHN_LORESERVE && entry <= SHN_HIRESERVE)
04566               {
04567                 error (_("invalid section [%5u] in group section [%5u]\n"),
04568                       entry, i);
04569                 continue;
04570               }
04571 
04572              if (section_headers_groups [SECTION_HEADER_INDEX (entry)]
04573                 != NULL)
04574               {
04575                 if (entry)
04576                   {
04577                     error (_("section [%5u] in group section [%5u] already in group section [%5u]\n"),
04578                           entry, i,
04579                           section_headers_groups [SECTION_HEADER_INDEX (entry)]->group_index);
04580                     continue;
04581                   }
04582                 else
04583                   {
04584                     /* Intel C/C++ compiler may put section 0 in a
04585                       section group. We just warn it the first time
04586                       and ignore it afterwards.  */
04587                     static int warned = 0;
04588                     if (!warned)
04589                      {
04590                        error (_("section 0 in group section [%5u]\n"),
04591                              section_headers_groups [SECTION_HEADER_INDEX (entry)]->group_index);
04592                        warned++;
04593                      }
04594                   }
04595               }
04596 
04597              section_headers_groups [SECTION_HEADER_INDEX (entry)]
04598               = group;
04599 
04600              if (do_section_groups)
04601               {
04602                 sec = SECTION_HEADER (entry);
04603                 printf ("   [%5u]   %s\n", entry, SECTION_NAME (sec));
04604               }
04605 
04606              g = xmalloc (sizeof (struct group_list));
04607              g->section_index = entry;
04608              g->next = group->root;
04609              group->root = g;
04610            }
04611 
04612          if (start)
04613            free (start);
04614 
04615          group++;
04616        }
04617     }
04618 
04619   if (symtab)
04620     free (symtab);
04621   if (strtab)
04622     free (strtab);
04623   return 1;
04624 }
04625 
04626 static struct
04627 {
04628   const char *name;
04629   int reloc;
04630   int size;
04631   int rela;
04632 } dynamic_relocations [] =
04633 {
04634     { "REL", DT_REL, DT_RELSZ, FALSE },
04635     { "RELA", DT_RELA, DT_RELASZ, TRUE },
04636     { "PLT", DT_JMPREL, DT_PLTRELSZ, UNKNOWN }
04637 };
04638 
04639 /* Process the reloc section.  */
04640 
04641 static int
04642 process_relocs (FILE *file)
04643 {
04644   unsigned long rel_size;
04645   unsigned long rel_offset;
04646 
04647 
04648   if (!do_reloc)
04649     return 1;
04650 
04651   if (do_using_dynamic)
04652     {
04653       int is_rela;
04654       const char *name;
04655       int has_dynamic_reloc;
04656       unsigned int i;
04657 
04658       has_dynamic_reloc = 0;
04659 
04660       for (i = 0; i < ARRAY_SIZE (dynamic_relocations); i++)
04661        {
04662          is_rela = dynamic_relocations [i].rela;
04663          name = dynamic_relocations [i].name;
04664          rel_size = dynamic_info [dynamic_relocations [i].size];
04665          rel_offset = dynamic_info [dynamic_relocations [i].reloc];
04666 
04667          has_dynamic_reloc |= rel_size;
04668 
04669          if (is_rela == UNKNOWN)
04670            {
04671              if (dynamic_relocations [i].reloc == DT_JMPREL)
04672               switch (dynamic_info[DT_PLTREL])
04673                 {
04674                 case DT_REL:
04675                   is_rela = FALSE;
04676                   break;
04677                 case DT_RELA:
04678                   is_rela = TRUE;
04679                   break;
04680                 }
04681            }
04682 
04683          if (rel_size)
04684            {
04685              printf
04686               (_("\n'%s' relocation section at offset 0x%lx contains %ld bytes:\n"),
04687                name, rel_offset, rel_size);
04688 
04689              dump_relocations (file,
04690                             offset_from_vma (file, rel_offset, rel_size),
04691                             rel_size,
04692                             dynamic_symbols, num_dynamic_syms,
04693                             dynamic_strings, dynamic_strings_length, is_rela);
04694            }
04695        }
04696 
04697       if (! has_dynamic_reloc)
04698        printf (_("\nThere are no dynamic relocations in this file.\n"));
04699     }
04700   else
04701     {
04702       Elf_Internal_Shdr *section;
04703       unsigned long i;
04704       int found = 0;
04705 
04706       for (i = 0, section = section_headers;
04707           i < elf_header.e_shnum;
04708           i++, section++)
04709        {
04710          if (   section->sh_type != SHT_RELA
04711              && section->sh_type != SHT_REL)
04712            continue;
04713 
04714          rel_offset = section->sh_offset;
04715          rel_size   = section->sh_size;
04716 
04717          if (rel_size)
04718            {
04719              Elf_Internal_Shdr *strsec;
04720              int is_rela;
04721 
04722              printf (_("\nRelocation section "));
04723 
04724              if (string_table == NULL)
04725               printf ("%d", section->sh_name);
04726              else
04727               printf (_("'%s'"), SECTION_NAME (section));
04728 
04729              printf (_(" at offset 0x%lx contains %lu entries:\n"),
04730                rel_offset, (unsigned long) (rel_size / section->sh_entsize));
04731 
04732              is_rela = section->sh_type == SHT_RELA;
04733 
04734              if (section->sh_link
04735                 && SECTION_HEADER_INDEX (section->sh_link)
04736                    < elf_header.e_shnum)
04737               {
04738                 Elf_Internal_Shdr *symsec;
04739                 Elf_Internal_Sym *symtab;
04740                 unsigned long nsyms;
04741                 unsigned long strtablen = 0;
04742                 char *strtab = NULL;
04743 
04744                 symsec = SECTION_HEADER (section->sh_link);
04745                 if (symsec->sh_type != SHT_SYMTAB
04746                     && symsec->sh_type != SHT_DYNSYM)
04747                     continue;
04748 
04749                 nsyms = symsec->sh_size / symsec->sh_entsize;
04750                 symtab = GET_ELF_SYMBOLS (file, symsec);
04751 
04752                 if (symtab == NULL)
04753                   continue;
04754 
04755                 if (SECTION_HEADER_INDEX (symsec->sh_link)
04756                     < elf_header.e_shnum)
04757                   {
04758                     strsec = SECTION_HEADER (symsec->sh_link);
04759 
04760                     strtab = get_data (NULL, file, strsec->sh_offset,
04761                                     1, strsec->sh_size,
04762                                     _("string table"));
04763                     strtablen = strtab == NULL ? 0 : strsec->sh_size;
04764                   }
04765 
04766                 dump_relocations (file, rel_offset, rel_size,
04767                                 symtab, nsyms, strtab, strtablen, is_rela);
04768                 if (strtab)
04769                   free (strtab);
04770                 free (symtab);
04771               }
04772              else
04773               dump_relocations (file, rel_offset, rel_size,
04774                               NULL, 0, NULL, 0, is_rela);
04775 
04776              found = 1;
04777            }
04778        }
04779 
04780       if (! found)
04781        printf (_("\nThere are no relocations in this file.\n"));
04782     }
04783 
04784   return 1;
04785 }
04786 
04787 /* Process the unwind section.  */
04788 
04789 #include "unwind-ia64.h"
04790 
04791 /* An absolute address consists of a section and an offset.  If the
04792    section is NULL, the offset itself is the address, otherwise, the
04793    address equals to LOAD_ADDRESS(section) + offset.  */
04794 
04795 struct absaddr
04796   {
04797     unsigned short section;
04798     bfd_vma offset;
04799   };
04800 
04801 #define ABSADDR(a) \
04802   ((a).section \
04803    ? section_headers [(a).section].sh_addr + (a).offset \
04804    : (a).offset)
04805 
04806 struct ia64_unw_aux_info
04807   {
04808     struct ia64_unw_table_entry
04809       {
04810        struct absaddr start;
04811        struct absaddr end;
04812        struct absaddr info;
04813       }
04814     *table;                 /* Unwind table.  */
04815     unsigned long table_len;       /* Length of unwind table.  */
04816     unsigned char *info;    /* Unwind info.  */
04817     unsigned long info_size;       /* Size of unwind info.  */
04818     bfd_vma info_addr;             /* starting address of unwind info.  */
04819     bfd_vma seg_base;              /* Starting address of segment.  */
04820     Elf_Internal_Sym *symtab;      /* The symbol table.  */
04821     unsigned long nsyms;    /* Number of symbols.  */
04822     char *strtab;           /* The string table.  */
04823     unsigned long strtab_size;     /* Size of string table.  */
04824   };
04825 
04826 static void
04827 find_symbol_for_address (Elf_Internal_Sym *symtab,
04828                       unsigned long nsyms,
04829                       const char *strtab,
04830                       unsigned long strtab_size,
04831                       struct absaddr addr,
04832                       const char **symname,
04833                       bfd_vma *offset)
04834 {
04835   bfd_vma dist = 0x100000;
04836   Elf_Internal_Sym *sym, *best = NULL;
04837   unsigned long i;
04838 
04839   for (i = 0, sym = symtab; i < nsyms; ++i, ++sym)
04840     {
04841       if (ELF_ST_TYPE (sym->st_info) == STT_FUNC
04842          && sym->st_name != 0
04843          && (addr.section == SHN_UNDEF || addr.section == sym->st_shndx)
04844          && addr.offset >= sym->st_value
04845          && addr.offset - sym->st_value < dist)
04846        {
04847          best = sym;
04848          dist = addr.offset - sym->st_value;
04849          if (!dist)
04850            break;
04851        }
04852     }
04853   if (best)
04854     {
04855       *symname = (best->st_name >= strtab_size
04856                 ? "<corrupt>" : strtab + best->st_name);
04857       *offset = dist;
04858       return;
04859     }
04860   *symname = NULL;
04861   *offset = addr.offset;
04862 }
04863 
04864 static void
04865 dump_ia64_unwind (struct ia64_unw_aux_info *aux)
04866 {
04867   struct ia64_unw_table_entry *tp;
04868   int in_body;
04869 
04870   for (tp = aux->table; tp < aux->table + aux->table_len; ++tp)
04871     {
04872       bfd_vma stamp;
04873       bfd_vma offset;
04874       const unsigned char *dp;
04875       const unsigned char *head;
04876       const char *procname;
04877 
04878       find_symbol_for_address (aux->symtab, aux->nsyms, aux->strtab,
04879                             aux->strtab_size, tp->start, &procname, &offset);
04880 
04881       fputs ("\n<", stdout);
04882 
04883       if (procname)
04884        {
04885          fputs (procname, stdout);
04886 
04887          if (offset)
04888            printf ("+%lx", (unsigned long) offset);
04889        }
04890 
04891       fputs (">: [", stdout);
04892       print_vma (tp->start.offset, PREFIX_HEX);
04893       fputc ('-', stdout);
04894       print_vma (tp->end.offset, PREFIX_HEX);
04895       printf ("], info at +0x%lx\n",
04896              (unsigned long) (tp->info.offset - aux->seg_base));
04897 
04898       head = aux->info + (ABSADDR (tp->info) - aux->info_addr);
04899       stamp = byte_get ((unsigned char *) head, sizeof (stamp));
04900 
04901       printf ("  v%u, flags=0x%lx (%s%s), len=%lu bytes\n",
04902              (unsigned) UNW_VER (stamp),
04903              (unsigned long) ((stamp & UNW_FLAG_MASK) >> 32),
04904              UNW_FLAG_EHANDLER (stamp) ? " ehandler" : "",
04905              UNW_FLAG_UHANDLER (stamp) ? " uhandler" : "",
04906              (unsigned long) (eh_addr_size * UNW_LENGTH (stamp)));
04907 
04908       if (UNW_VER (stamp) != 1)
04909        {
04910          printf ("\tUnknown version.\n");
04911          continue;
04912        }
04913 
04914       in_body = 0;
04915       for (dp = head + 8; dp < head + 8 + eh_addr_size * UNW_LENGTH (stamp);)
04916        dp = unw_decode (dp, in_body, & in_body);
04917     }
04918 }
04919 
04920 static int
04921 slurp_ia64_unwind_table (FILE *file,
04922                       struct ia64_unw_aux_info *aux,
04923                       Elf_Internal_Shdr *sec)
04924 {
04925   unsigned long size, nrelas, i;
04926   Elf_Internal_Phdr *seg;
04927   struct ia64_unw_table_entry *tep;
04928   Elf_Internal_Shdr *relsec;
04929   Elf_Internal_Rela *rela, *rp;
04930   unsigned char *table, *tp;
04931   Elf_Internal_Sym *sym;
04932   const char *relname;
04933 
04934   /* First, find the starting address of the segment that includes
04935      this section: */
04936 
04937   if (elf_header.e_phnum)
04938     {
04939       if (! get_program_headers (file))
04940          return 0;
04941 
04942       for (seg = program_headers;
04943           seg < program_headers + elf_header.e_phnum;
04944           ++seg)
04945        {
04946          if (seg->p_type != PT_LOAD)
04947            continue;
04948 
04949          if (sec->sh_addr >= seg->p_vaddr
04950              && (sec->sh_addr + sec->sh_size <= seg->p_vaddr + seg->p_memsz))
04951            {
04952              aux->seg_base = seg->p_vaddr;
04953              break;
04954            }
04955        }
04956     }
04957 
04958   /* Second, build the unwind table from the contents of the unwind section:  */
04959   size = sec->sh_size;
04960   table = get_data (NULL, file, sec->sh_offset, 1, size, _("unwind table"));
04961   if (!table)
04962     return 0;
04963 
04964   aux->table = xcmalloc (size / (3 * eh_addr_size), sizeof (aux->table[0]));
04965   tep = aux->table;
04966   for (tp = table; tp < table + size; tp += 3 * eh_addr_size, ++tep)
04967     {
04968       tep->start.section = SHN_UNDEF;
04969       tep->end.section   = SHN_UNDEF;
04970       tep->info.section  = SHN_UNDEF;
04971       if (is_32bit_elf)
04972        {
04973          tep->start.offset = byte_get ((unsigned char *) tp + 0, 4);
04974          tep->end.offset   = byte_get ((unsigned char *) tp + 4, 4);
04975          tep->info.offset  = byte_get ((unsigned char *) tp + 8, 4);
04976        }
04977       else
04978        {
04979          tep->start.offset = BYTE_GET ((unsigned char *) tp +  0);
04980          tep->end.offset   = BYTE_GET ((unsigned char *) tp +  8);
04981          tep->info.offset  = BYTE_GET ((unsigned char *) tp + 16);
04982        }
04983       tep->start.offset += aux->seg_base;
04984       tep->end.offset   += aux->seg_base;
04985       tep->info.offset  += aux->seg_base;
04986     }
04987   free (table);
04988 
04989   /* Third, apply any relocations to the unwind table: */
04990 
04991   for (relsec = section_headers;
04992        relsec < section_headers + elf_header.e_shnum;
04993        ++relsec)
04994     {
04995       if (relsec->sh_type != SHT_RELA
04996          || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
04997          || SECTION_HEADER (relsec->sh_info) != sec)
04998        continue;
04999 
05000       if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
05001                            & rela, & nrelas))
05002        return 0;
05003 
05004       for (rp = rela; rp < rela + nrelas; ++rp)
05005        {
05006          if (is_32bit_elf)
05007            {
05008              relname = elf_ia64_reloc_type (ELF32_R_TYPE (rp->r_info));
05009              sym = aux->symtab + ELF32_R_SYM (rp->r_info);
05010            }
05011          else
05012            {
05013              relname = elf_ia64_reloc_type (ELF64_R_TYPE (rp->r_info));
05014              sym = aux->symtab + ELF64_R_SYM (rp->r_info);
05015            }
05016 
05017          if (! const_strneq (relname, "R_IA64_SEGREL"))
05018            {
05019              warn (_("Skipping unexpected relocation type %s\n"), relname);
05020              continue;
05021            }
05022 
05023          i = rp->r_offset / (3 * eh_addr_size);
05024 
05025          switch (rp->r_offset/eh_addr_size % 3)
05026            {
05027            case 0:
05028              aux->table[i].start.section = sym->st_shndx;
05029              aux->table[i].start.offset += rp->r_addend + sym->st_value;
05030              break;
05031            case 1:
05032              aux->table[i].end.section   = sym->st_shndx;
05033              aux->table[i].end.offset   += rp->r_addend + sym->st_value;
05034              break;
05035            case 2:
05036              aux->table[i].info.section  = sym->st_shndx;
05037              aux->table[i].info.offset  += rp->r_addend + sym->st_value;
05038              break;
05039            default:
05040              break;
05041            }
05042        }
05043 
05044       free (rela);
05045     }
05046 
05047   aux->table_len = size / (3 * eh_addr_size);
05048   return 1;
05049 }
05050 
05051 static int
05052 ia64_process_unwind (FILE *file)
05053 {
05054   Elf_Internal_Shdr *sec, *unwsec = NULL, *strsec;
05055   unsigned long i, unwcount = 0, unwstart = 0;
05056   struct ia64_unw_aux_info aux;
05057 
05058   memset (& aux, 0, sizeof (aux));
05059 
05060   for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
05061     {
05062       if (sec->sh_type == SHT_SYMTAB
05063          && SECTION_HEADER_INDEX (sec->sh_link) < elf_header.e_shnum)
05064        {
05065          aux.nsyms = sec->sh_size / sec->sh_entsize;
05066          aux.symtab = GET_ELF_SYMBOLS (file, sec);
05067 
05068          strsec = SECTION_HEADER (sec->sh_link);
05069          aux.strtab = get_data (NULL, file, strsec->sh_offset,
05070                              1, strsec->sh_size, _("string table"));
05071          aux.strtab_size = aux.strtab != NULL ? strsec->sh_size : 0;
05072        }
05073       else if (sec->sh_type == SHT_IA_64_UNWIND)
05074        unwcount++;
05075     }
05076 
05077   if (!unwcount)
05078     printf (_("\nThere are no unwind sections in this file.\n"));
05079 
05080   while (unwcount-- > 0)
05081     {
05082       char *suffix;
05083       size_t len, len2;
05084 
05085       for (i = unwstart, sec = section_headers + unwstart;
05086           i < elf_header.e_shnum; ++i, ++sec)
05087        if (sec->sh_type == SHT_IA_64_UNWIND)
05088          {
05089            unwsec = sec;
05090            break;
05091          }
05092 
05093       unwstart = i + 1;
05094       len = sizeof (ELF_STRING_ia64_unwind_once) - 1;
05095 
05096       if ((unwsec->sh_flags & SHF_GROUP) != 0)
05097        {
05098          /* We need to find which section group it is in.  */
05099          struct group_list *g = section_headers_groups [i]->root;
05100 
05101          for (; g != NULL; g = g->next)
05102            {
05103              sec = SECTION_HEADER (g->section_index);
05104 
05105              if (streq (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info))
05106               break;
05107            }
05108 
05109          if (g == NULL)
05110            i = elf_header.e_shnum;
05111        }
05112       else if (strneq (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind_once, len))
05113        {
05114          /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.ia64unwi.FOO.  */
05115          len2 = sizeof (ELF_STRING_ia64_unwind_info_once) - 1;
05116          suffix = SECTION_NAME (unwsec) + len;
05117          for (i = 0, sec = section_headers; i < elf_header.e_shnum;
05118               ++i, ++sec)
05119            if (strneq (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info_once, len2)
05120               && streq (SECTION_NAME (sec) + len2, suffix))
05121              break;
05122        }
05123       else
05124        {
05125          /* .IA_64.unwindFOO -> .IA_64.unwind_infoFOO
05126             .IA_64.unwind or BAR -> .IA_64.unwind_info.  */
05127          len = sizeof (ELF_STRING_ia64_unwind) - 1;
05128          len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1;
05129          suffix = "";
05130          if (strneq (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind, len))
05131            suffix = SECTION_NAME (unwsec) + len;
05132          for (i = 0, sec = section_headers; i < elf_header.e_shnum;
05133               ++i, ++sec)
05134            if (strneq (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info, len2)
05135               && streq (SECTION_NAME (sec) + len2, suffix))
05136              break;
05137        }
05138 
05139       if (i == elf_header.e_shnum)
05140        {
05141          printf (_("\nCould not find unwind info section for "));
05142 
05143          if (string_table == NULL)
05144            printf ("%d", unwsec->sh_name);
05145          else
05146            printf (_("'%s'"), SECTION_NAME (unwsec));
05147        }
05148       else
05149        {
05150          aux.info_size = sec->sh_size;
05151          aux.info_addr = sec->sh_addr;
05152          aux.info = get_data (NULL, file, sec->sh_offset, 1, aux.info_size,
05153                             _("unwind info"));
05154 
05155          printf (_("\nUnwind section "));
05156 
05157          if (string_table == NULL)
05158            printf ("%d", unwsec->sh_name);
05159          else
05160            printf (_("'%s'"), SECTION_NAME (unwsec));
05161 
05162          printf (_(" at offset 0x%lx contains %lu entries:\n"),
05163                 (unsigned long) unwsec->sh_offset,
05164                 (unsigned long) (unwsec->sh_size / (3 * eh_addr_size)));
05165 
05166          (void) slurp_ia64_unwind_table (file, & aux, unwsec);
05167 
05168          if (aux.table_len > 0)
05169            dump_ia64_unwind (& aux);
05170 
05171          if (aux.table)
05172            free ((char *) aux.table);
05173          if (aux.info)
05174            free ((char *) aux.info);
05175          aux.table = NULL;
05176          aux.info = NULL;
05177        }
05178     }
05179 
05180   if (aux.symtab)
05181     free (aux.symtab);
05182   if (aux.strtab)
05183     free ((char *) aux.strtab);
05184 
05185   return 1;
05186 }
05187 
05188 struct hppa_unw_aux_info
05189   {
05190     struct hppa_unw_table_entry
05191       {
05192        struct absaddr start;
05193        struct absaddr end;
05194        unsigned int Cannot_unwind:1;                    /* 0 */
05195        unsigned int Millicode:1;                 /* 1 */
05196        unsigned int Millicode_save_sr0:1;        /* 2 */
05197        unsigned int Region_description:2;        /* 3..4 */
05198        unsigned int reserved1:1;                 /* 5 */
05199        unsigned int Entry_SR:1;                  /* 6 */
05200        unsigned int Entry_FR:4;     /* number saved */  /* 7..10 */
05201        unsigned int Entry_GR:5;     /* number saved */  /* 11..15 */
05202        unsigned int Args_stored:1;               /* 16 */
05203        unsigned int Variable_Frame:1;                   /* 17 */
05204        unsigned int Separate_Package_Body:1;            /* 18 */
05205        unsigned int Frame_Extension_Millicode:1; /* 19 */
05206        unsigned int Stack_Overflow_Check:1;             /* 20 */
05207        unsigned int Two_Instruction_SP_Increment:1;     /* 21 */
05208        unsigned int Ada_Region:1;                /* 22 */
05209        unsigned int cxx_info:1;                  /* 23 */
05210        unsigned int cxx_try_catch:1;                    /* 24 */
05211        unsigned int sched_entry_seq:1;                  /* 25 */
05212        unsigned int reserved2:1;                 /* 26 */
05213        unsigned int Save_SP:1;                          /* 27 */
05214        unsigned int Save_RP:1;                          /* 28 */
05215        unsigned int Save_MRP_in_frame:1;         /* 29 */
05216        unsigned int extn_ptr_defined:1;          /* 30 */
05217        unsigned int Cleanup_defined:1;                  /* 31 */
05218 
05219        unsigned int MPE_XL_interrupt_marker:1;          /* 0 */
05220        unsigned int HP_UX_interrupt_marker:1;           /* 1 */
05221        unsigned int Large_frame:1;               /* 2 */
05222        unsigned int Pseudo_SP_Set:1;                    /* 3 */
05223        unsigned int reserved4:1;                 /* 4 */
05224        unsigned int Total_frame_size:27;         /* 5..31 */
05225       }
05226     *table;                 /* Unwind table.  */
05227     unsigned long table_len;       /* Length of unwind table.  */
05228     bfd_vma seg_base;              /* Starting address of segment.  */
05229     Elf_Internal_Sym *symtab;      /* The symbol table.  */
05230     unsigned long nsyms;    /* Number of symbols.  */
05231     char *strtab;           /* The string table.  */
05232     unsigned long strtab_size;     /* Size of string table.  */
05233   };
05234 
05235 static void
05236 dump_hppa_unwind (struct hppa_unw_aux_info *aux)
05237 {
05238   struct hppa_unw_table_entry *tp;
05239 
05240   for (tp = aux->table; tp < aux->table + aux->table_len; ++tp)
05241     {
05242       bfd_vma offset;
05243       const char *procname;
05244 
05245       find_symbol_for_address (aux->symtab, aux->nsyms, aux->strtab,
05246                             aux->strtab_size, tp->start, &procname,
05247                             &offset);
05248 
05249       fputs ("\n<", stdout);
05250 
05251       if (procname)
05252        {
05253          fputs (procname, stdout);
05254 
05255          if (offset)
05256            printf ("+%lx", (unsigned long) offset);
05257        }
05258 
05259       fputs (">: [", stdout);
05260       print_vma (tp->start.offset, PREFIX_HEX);
05261       fputc ('-', stdout);
05262       print_vma (tp->end.offset, PREFIX_HEX);
05263       printf ("]\n\t");
05264 
05265 #define PF(_m) if (tp->_m) printf (#_m " ");
05266 #define PV(_m) if (tp->_m) printf (#_m "=%d ", tp->_m);
05267       PF(Cannot_unwind);
05268       PF(Millicode);
05269       PF(Millicode_save_sr0);
05270       /* PV(Region_description);  */
05271       PF(Entry_SR);
05272       PV(Entry_FR);
05273       PV(Entry_GR);
05274       PF(Args_stored);
05275       PF(Variable_Frame);
05276       PF(Separate_Package_Body);
05277       PF(Frame_Extension_Millicode);
05278       PF(Stack_Overflow_Check);
05279       PF(Two_Instruction_SP_Increment);
05280       PF(Ada_Region);
05281       PF(cxx_info);
05282       PF(cxx_try_catch);
05283       PF(sched_entry_seq);
05284       PF(Save_SP);
05285       PF(Save_RP);
05286       PF(Save_MRP_in_frame);
05287       PF(extn_ptr_defined);
05288       PF(Cleanup_defined);
05289       PF(MPE_XL_interrupt_marker);
05290       PF(HP_UX_interrupt_marker);
05291       PF(Large_frame);
05292       PF(Pseudo_SP_Set);
05293       PV(Total_frame_size);
05294 #undef PF
05295 #undef PV
05296     }
05297 
05298   printf ("\n");
05299 }
05300 
05301 static int
05302 slurp_hppa_unwind_table (FILE *file,
05303                       struct hppa_unw_aux_info *aux,
05304                       Elf_Internal_Shdr *sec)
05305 {
05306   unsigned long size, unw_ent_size, nentries, nrelas, i;
05307   Elf_Internal_Phdr *seg;
05308   struct hppa_unw_table_entry *tep;
05309   Elf_Internal_Shdr *relsec;
05310   Elf_Internal_Rela *rela, *rp;
05311   unsigned char *table, *tp;
05312   Elf_Internal_Sym *sym;
05313   const char *relname;
05314 
05315   /* First, find the starting address of the segment that includes
05316      this section.  */
05317 
05318   if (elf_header.e_phnum)
05319     {
05320       if (! get_program_headers (file))
05321        return 0;
05322 
05323       for (seg = program_headers;
05324           seg < program_headers + elf_header.e_phnum;
05325           ++seg)
05326        {
05327          if (seg->p_type != PT_LOAD)
05328            continue;
05329 
05330          if (sec->sh_addr >= seg->p_vaddr
05331              && (sec->sh_addr + sec->sh_size <= seg->p_vaddr + seg->p_memsz))
05332            {
05333              aux->seg_base = seg->p_vaddr;
05334              break;
05335            }
05336        }
05337     }
05338 
05339   /* Second, build the unwind table from the contents of the unwind
05340      section.  */
05341   size = sec->sh_size;
05342   table = get_data (NULL, file, sec->sh_offset, 1, size, _("unwind table"));
05343   if (!table)
05344     return 0;
05345 
05346   unw_ent_size = 16;
05347   nentries = size / unw_ent_size;
05348   size = unw_ent_size * nentries;
05349 
05350   tep = aux->table = xcmalloc (nentries, sizeof (aux->table[0]));
05351 
05352   for (tp = table; tp < table + size; tp += unw_ent_size, ++tep)
05353     {
05354       unsigned int tmp1, tmp2;
05355 
05356       tep->start.section = SHN_UNDEF;
05357       tep->end.section   = SHN_UNDEF;
05358 
05359       tep->start.offset = byte_get ((unsigned char *) tp + 0, 4);
05360       tep->end.offset = byte_get ((unsigned char *) tp + 4, 4);
05361       tmp1 = byte_get ((unsigned char *) tp + 8, 4);
05362       tmp2 = byte_get ((unsigned char *) tp + 12, 4);
05363 
05364       tep->start.offset += aux->seg_base;
05365       tep->end.offset   += aux->seg_base;
05366 
05367       tep->Cannot_unwind = (tmp1 >> 31) & 0x1;
05368       tep->Millicode = (tmp1 >> 30) & 0x1;
05369       tep->Millicode_save_sr0 = (tmp1 >> 29) & 0x1;
05370       tep->Region_description = (tmp1 >> 27) & 0x3;
05371       tep->reserved1 = (tmp1 >> 26) & 0x1;
05372       tep->Entry_SR = (tmp1 >> 25) & 0x1;
05373       tep->Entry_FR = (tmp1 >> 21) & 0xf;
05374       tep->Entry_GR = (tmp1 >> 16) & 0x1f;
05375       tep->Args_stored = (tmp1 >> 15) & 0x1;
05376       tep->Variable_Frame = (tmp1 >> 14) & 0x1;
05377       tep->Separate_Package_Body = (tmp1 >> 13) & 0x1;
05378       tep->Frame_Extension_Millicode = (tmp1 >> 12) & 0x1;
05379       tep->Stack_Overflow_Check = (tmp1 >> 11) & 0x1;
05380       tep->Two_Instruction_SP_Increment = (tmp1 >> 10) & 0x1;
05381       tep->Ada_Region = (tmp1 >> 9) & 0x1;
05382       tep->cxx_info = (tmp1 >> 8) & 0x1;
05383       tep->cxx_try_catch = (tmp1 >> 7) & 0x1;
05384       tep->sched_entry_seq = (tmp1 >> 6) & 0x1;
05385       tep->reserved2 = (tmp1 >> 5) & 0x1;
05386       tep->Save_SP = (tmp1 >> 4) & 0x1;
05387       tep->Save_RP = (tmp1 >> 3) & 0x1;
05388       tep->Save_MRP_in_frame = (tmp1 >> 2) & 0x1;
05389       tep->extn_ptr_defined = (tmp1 >> 1) & 0x1;
05390       tep->Cleanup_defined = tmp1 & 0x1;
05391 
05392       tep->MPE_XL_interrupt_marker = (tmp2 >> 31) & 0x1;
05393       tep->HP_UX_interrupt_marker = (tmp2 >> 30) & 0x1;
05394       tep->Large_frame = (tmp2 >> 29) & 0x1;
05395       tep->Pseudo_SP_Set = (tmp2 >> 28) & 0x1;
05396       tep->reserved4 = (tmp2 >> 27) & 0x1;
05397       tep->Total_frame_size = tmp2 & 0x7ffffff;
05398     }
05399   free (table);
05400 
05401   /* Third, apply any relocations to the unwind table.  */
05402 
05403   for (relsec = section_headers;
05404        relsec < section_headers + elf_header.e_shnum;
05405        ++relsec)
05406     {
05407       if (relsec->sh_type != SHT_RELA
05408          || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
05409          || SECTION_HEADER (relsec->sh_info) != sec)
05410        continue;
05411 
05412       if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
05413                            & rela, & nrelas))
05414        return 0;
05415 
05416       for (rp = rela; rp < rela + nrelas; ++rp)
05417        {
05418          if (is_32bit_elf)
05419            {
05420              relname = elf_hppa_reloc_type (ELF32_R_TYPE (rp->r_info));
05421              sym = aux->symtab + ELF32_R_SYM (rp->r_info);
05422            }
05423          else
05424            {
05425              relname = elf_hppa_reloc_type (ELF64_R_TYPE (rp->r_info));
05426              sym = aux->symtab + ELF64_R_SYM (rp->r_info);
05427            }
05428 
05429          /* R_PARISC_SEGREL32 or R_PARISC_SEGREL64.  */
05430          if (! const_strneq (relname, "R_PARISC_SEGREL"))
05431            {
05432              warn (_("Skipping unexpected relocation type %s\n"), relname);
05433              continue;
05434            }
05435 
05436          i = rp->r_offset / unw_ent_size;
05437 
05438          switch ((rp->r_offset % unw_ent_size) / eh_addr_size)
05439            {
05440            case 0:
05441              aux->table[i].start.section = sym->st_shndx;
05442              aux->table[i].start.offset += sym->st_value + rp->r_addend;
05443              break;
05444            case 1:
05445              aux->table[i].end.section   = sym->st_shndx;
05446              aux->table[i].end.offset   += sym->st_value + rp->r_addend;
05447              break;
05448            default:
05449              break;
05450            }
05451        }
05452 
05453       free (rela);
05454     }
05455 
05456   aux->table_len = nentries;
05457 
05458   return 1;
05459 }
05460 
05461 static int
05462 hppa_process_unwind (FILE *file)
05463 {
05464   struct hppa_unw_aux_info aux;
05465   Elf_Internal_Shdr *unwsec = NULL;
05466   Elf_Internal_Shdr *strsec;
05467   Elf_Internal_Shdr *sec;
05468   unsigned long i;
05469 
05470   memset (& aux, 0, sizeof (aux));
05471 
05472   if (string_table == NULL)
05473     return 1;
05474 
05475   for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
05476     {
05477       if (sec->sh_type == SHT_SYMTAB
05478          && SECTION_HEADER_INDEX (sec->sh_link) < elf_header.e_shnum)
05479        {
05480          aux.nsyms = sec->sh_size / sec->sh_entsize;
05481          aux.symtab = GET_ELF_SYMBOLS (file, sec);
05482 
05483          strsec = SECTION_HEADER (sec->sh_link);
05484          aux.strtab = get_data (NULL, file, strsec->sh_offset,
05485                              1, strsec->sh_size, _("string table"));
05486          aux.strtab_size = aux.strtab != NULL ? strsec->sh_size : 0;
05487        }
05488       else if (streq (SECTION_NAME (sec), ".PARISC.unwind"))
05489        unwsec = sec;
05490     }
05491 
05492   if (!unwsec)
05493     printf (_("\nThere are no unwind sections in this file.\n"));
05494 
05495   for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
05496     {
05497       if (streq (SECTION_NAME (sec), ".PARISC.unwind"))
05498        {
05499          printf (_("\nUnwind section "));
05500          printf (_("'%s'"), SECTION_NAME (sec));
05501 
05502          printf (_(" at offset 0x%lx contains %lu entries:\n"),
05503                 (unsigned long) sec->sh_offset,
05504                 (unsigned long) (sec->sh_size / (2 * eh_addr_size + 8)));
05505 
05506           slurp_hppa_unwind_table (file, &aux, sec);
05507          if (aux.table_len > 0)
05508            dump_hppa_unwind (&aux);
05509 
05510          if (aux.table)
05511            free ((char *) aux.table);
05512          aux.table = NULL;
05513        }
05514     }
05515 
05516   if (aux.symtab)
05517     free (aux.symtab);
05518   if (aux.strtab)
05519     free ((char *) aux.strtab);
05520 
05521   return 1;
05522 }
05523 
05524 static int
05525 process_unwind (FILE *file)
05526 {
05527   struct unwind_handler {
05528     int machtype;
05529     int (*handler)(FILE *file);
05530   } handlers[] = {
05531     { EM_IA_64, ia64_process_unwind },
05532     { EM_PARISC, hppa_process_unwind },
05533     { 0, 0 }
05534   };
05535   int i;
05536 
05537   if (!do_unwind)
05538     return 1;
05539 
05540   for (i = 0; handlers[i].handler != NULL; i++)
05541     if (elf_header.e_machine == handlers[i].machtype)
05542       return handlers[i].handler (file);
05543 
05544   printf (_("\nThere are no unwind sections in this file.\n"));
05545   return 1;
05546 }
05547 
05548 static void
05549 dynamic_section_mips_val (Elf_Internal_Dyn *entry)
05550 {
05551   switch (entry->d_tag)
05552     {
05553     case DT_MIPS_FLAGS:
05554       if (entry->d_un.d_val == 0)
05555        printf ("NONE\n");
05556       else
05557        {
05558          static const char * opts[] =
05559          {
05560            "QUICKSTART", "NOTPOT", "NO_LIBRARY_REPLACEMENT",
05561            "NO_MOVE", "SGI_ONLY", "GUARANTEE_INIT", "DELTA_C_PLUS_PLUS",
05562            "GUARANTEE_START_INIT", "PIXIE", "DEFAULT_DELAY_LOAD",
05563            "REQUICKSTART", "REQUICKSTARTED", "CORD", "NO_UNRES_UNDEF",
05564            "RLD_ORDER_SAFE"
05565          };
05566          unsigned int cnt;
05567          int first = 1;
05568          for (cnt = 0; cnt < NUM_ELEM (opts); ++cnt)
05569            if (entry->d_un.d_val & (1 << cnt))
05570              {
05571               printf ("%s%s", first ? "" : " ", opts[cnt]);
05572               first = 0;
05573              }
05574          puts ("");
05575        }
05576       break;
05577 
05578     case DT_MIPS_IVERSION:
05579       if (VALID_DYNAMIC_NAME (entry->d_un.d_val))
05580        printf ("Interface Version: %s\n", GET_DYNAMIC_NAME (entry->d_un.d_val));
05581       else
05582        printf ("<corrupt: %ld>\n", (long) entry->d_un.d_ptr);
05583       break;
05584 
05585     case DT_MIPS_TIME_STAMP:
05586       {
05587        char timebuf[20];
05588        struct tm *tmp;
05589 
05590        time_t time = entry->d_un.d_val;
05591        tmp = gmtime (&time);
05592        snprintf (timebuf, sizeof (timebuf), "%04u-%02u-%02uT%02u:%02u:%02u",
05593                 tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
05594                 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
05595        printf ("Time Stamp: %s\n", timebuf);
05596       }
05597       break;
05598 
05599     case DT_MIPS_RLD_VERSION:
05600     case DT_MIPS_LOCAL_GOTNO:
05601     case DT_MIPS_CONFLICTNO:
05602     case DT_MIPS_LIBLISTNO:
05603     case DT_MIPS_SYMTABNO:
05604     case DT_MIPS_UNREFEXTNO:
05605     case DT_MIPS_HIPAGENO:
05606     case DT_MIPS_DELTA_CLASS_NO:
05607     case DT_MIPS_DELTA_INSTANCE_NO:
05608     case DT_MIPS_DELTA_RELOC_NO:
05609     case DT_MIPS_DELTA_SYM_NO:
05610     case DT_MIPS_DELTA_CLASSSYM_NO:
05611     case DT_MIPS_COMPACT_SIZE:
05612       printf ("%ld\n", (long) entry->d_un.d_ptr);
05613       break;
05614 
05615     default:
05616       printf ("%#lx\n", (long) entry->d_un.d_ptr);
05617     }
05618 }
05619 
05620 
05621 static void
05622 dynamic_section_parisc_val (Elf_Internal_Dyn *entry)
05623 {
05624   switch (entry->d_tag)
05625     {
05626     case DT_HP_DLD_FLAGS:
05627       {
05628        static struct
05629        {
05630          long int bit;
05631          const char *str;
05632        }
05633        flags[] =
05634        {
05635          { DT_HP_DEBUG_PRIVATE, "HP_DEBUG_PRIVATE" },
05636          { DT_HP_DEBUG_CALLBACK, "HP_DEBUG_CALLBACK" },
05637          { DT_HP_DEBUG_CALLBACK_BOR, "HP_DEBUG_CALLBACK_BOR" },
05638          { DT_HP_NO_ENVVAR, "HP_NO_ENVVAR" },
05639          { DT_HP_BIND_NOW, "HP_BIND_NOW" },
05640          { DT_HP_BIND_NONFATAL, "HP_BIND_NONFATAL" },
05641          { DT_HP_BIND_VERBOSE, "HP_BIND_VERBOSE" },
05642          { DT_HP_BIND_RESTRICTED, "HP_BIND_RESTRICTED" },
05643          { DT_HP_BIND_SYMBOLIC, "HP_BIND_SYMBOLIC" },
05644          { DT_HP_RPATH_FIRST, "HP_RPATH_FIRST" },
05645          { DT_HP_BIND_DEPTH_FIRST, "HP_BIND_DEPTH_FIRST" },
05646          { DT_HP_GST, "HP_GST" },
05647          { DT_HP_SHLIB_FIXED, "HP_SHLIB_FIXED" },
05648          { DT_HP_MERGE_SHLIB_SEG, "HP_MERGE_SHLIB_SEG" },
05649          { DT_HP_NODELETE, "HP_NODELETE" },
05650          { DT_HP_GROUP, "HP_GROUP" },
05651          { DT_HP_PROTECT_LINKAGE_TABLE, "HP_PROTECT_LINKAGE_TABLE" }
05652        };
05653        int first = 1;
05654        size_t cnt;
05655        bfd_vma val = entry->d_un.d_val;
05656 
05657        for (cnt = 0; cnt < sizeof (flags) / sizeof (flags[0]); ++cnt)
05658          if (val & flags[cnt].bit)
05659            {
05660              if (! first)
05661               putchar (' ');
05662              fputs (flags[cnt].str, stdout);
05663              first = 0;
05664              val ^= flags[cnt].bit;
05665            }
05666 
05667        if (val != 0 || first)
05668          {
05669            if (! first)
05670              putchar (' ');
05671            print_vma (val, HEX);
05672          }
05673       }
05674       break;
05675 
05676     default:
05677       print_vma (entry->d_un.d_ptr, PREFIX_HEX);
05678       break;
05679     }
05680   putchar ('\n');
05681 }
05682 
05683 static void
05684 dynamic_section_ia64_val (Elf_Internal_Dyn *entry)
05685 {
05686   switch (entry->d_tag)
05687     {
05688     case DT_IA_64_PLT_RESERVE:
05689       /* First 3 slots reserved.  */
05690       print_vma (entry->d_un.d_ptr, PREFIX_HEX);
05691       printf (" -- ");
05692       print_vma (entry->d_un.d_ptr + (3 * 8), PREFIX_HEX);
05693       break;
05694 
05695     default:
05696       print_vma (entry->d_un.d_ptr, PREFIX_HEX);
05697       break;
05698     }
05699   putchar ('\n');
05700 }
05701 
05702 static int
05703 get_32bit_dynamic_section (FILE *file)
05704 {
05705   Elf32_External_Dyn *edyn, *ext;
05706   Elf_Internal_Dyn *entry;
05707 
05708   edyn = get_data (NULL, file, dynamic_addr, 1, dynamic_size,
05709                  _("dynamic section"));
05710   if (!edyn)
05711     return 0;
05712 
05713 /* SGI's ELF has more than one section in the DYNAMIC segment, and we
05714    might not have the luxury of section headers.  Look for the DT_NULL
05715    terminator to determine the number of entries.  */
05716   for (ext = edyn, dynamic_nent = 0;
05717        (char *) ext < (char *) edyn + dynamic_size;
05718        ext++)
05719     {
05720       dynamic_nent++;
05721       if (BYTE_GET (ext->d_tag) == DT_NULL)
05722        break;
05723     }
05724 
05725   dynamic_section = cmalloc (dynamic_nent, sizeof (*entry));
05726   if (dynamic_section == NULL)
05727     {
05728       error (_("Out of memory\n"));
05729       free (edyn);
05730       return 0;
05731     }
05732 
05733   for (ext = edyn, entry = dynamic_section;
05734        entry < dynamic_section + dynamic_nent;
05735        ext++, entry++)
05736     {
05737       entry->d_tag      = BYTE_GET (ext->d_tag);
05738       entry->d_un.d_val = BYTE_GET (ext->d_un.d_val);
05739     }
05740 
05741   free (edyn);
05742 
05743   return 1;
05744 }
05745 
05746 static int
05747 get_64bit_dynamic_section (FILE *file)
05748 {
05749   Elf64_External_Dyn *edyn, *ext;
05750   Elf_Internal_Dyn *entry;
05751 
05752   edyn = get_data (NULL, file, dynamic_addr, 1, dynamic_size,
05753                  _("dynamic section"));
05754   if (!edyn)
05755     return 0;
05756 
05757 /* SGI's ELF has more than one section in the DYNAMIC segment, and we
05758    might not have the luxury of section headers.  Look for the DT_NULL
05759    terminator to determine the number of entries.  */
05760   for (ext = edyn, dynamic_nent = 0;
05761        (char *) ext < (char *) edyn + dynamic_size;
05762        ext++)
05763     {
05764       dynamic_nent++;
05765       if (BYTE_GET (ext->d_tag) == DT_NULL)
05766        break;
05767     }
05768 
05769   dynamic_section = cmalloc (dynamic_nent, sizeof (*entry));
05770   if (dynamic_section == NULL)
05771     {
05772       error (_("Out of memory\n"));
05773       free (edyn);
05774       return 0;
05775     }
05776 
05777   for (ext = edyn, entry = dynamic_section;
05778        entry < dynamic_section + dynamic_nent;
05779        ext++, entry++)
05780     {
05781       entry->d_tag      = BYTE_GET (ext->d_tag);
05782       entry->d_un.d_val = BYTE_GET (ext->d_un.d_val);
05783     }
05784 
05785   free (edyn);
05786 
05787   return 1;
05788 }
05789 
05790 static void
05791 print_dynamic_flags (bfd_vma flags)
05792 {
05793   int first = 1;
05794 
05795   while (flags)
05796     {
05797       bfd_vma flag;
05798 
05799       flag = flags & - flags;
05800       flags &= ~ flag;
05801 
05802       if (first)
05803        first = 0;
05804       else
05805        putc (' ', stdout);
05806 
05807       switch (flag)
05808        {
05809        case DF_ORIGIN:             fputs ("ORIGIN", stdout); break;
05810        case DF_SYMBOLIC:    fputs ("SYMBOLIC", stdout); break;
05811        case DF_TEXTREL:     fputs ("TEXTREL", stdout); break;
05812        case DF_BIND_NOW:    fputs ("BIND_NOW", stdout); break;
05813        case DF_STATIC_TLS:  fputs ("STATIC_TLS", stdout); break;
05814        default:             fputs ("unknown", stdout); break;
05815        }
05816     }
05817   puts ("");
05818 }
05819 
05820 /* Parse and display the contents of the dynamic section.  */
05821 
05822 static int
05823 process_dynamic_section (FILE *file)
05824 {
05825   Elf_Internal_Dyn *entry;
05826 
05827   if (dynamic_size == 0)
05828     {
05829       if (do_dynamic)
05830        printf (_("\nThere is no dynamic section in this file.\n"));
05831 
05832       return 1;
05833     }
05834 
05835   if (is_32bit_elf)
05836     {
05837       if (! get_32bit_dynamic_section (file))
05838        return 0;
05839     }
05840   else if (! get_64bit_dynamic_section (file))
05841     return 0;
05842 
05843   /* Find the appropriate symbol table.  */
05844   if (dynamic_symbols == NULL)
05845     {
05846       for (entry = dynamic_section;
05847           entry < dynamic_section + dynamic_nent;
05848           ++entry)
05849        {
05850          Elf_Internal_Shdr section;
05851 
05852          if (entry->d_tag != DT_SYMTAB)
05853            continue;
05854 
05855          dynamic_info[DT_SYMTAB] = entry->d_un.d_val;
05856 
05857          /* Since we do not know how big the symbol table is,
05858             we default to reading in the entire file (!) and
05859             processing that.  This is overkill, I know, but it
05860             should work.  */
05861          section.sh_offset = offset_from_vma (file, entry->d_un.d_val, 0);
05862 
05863          if (archive_file_offset != 0)
05864            section.sh_size = archive_file_size - section.sh_offset;
05865          else
05866            {
05867              if (fseek (file, 0, SEEK_END))
05868               error (_("Unable to seek to end of file!\n"));
05869 
05870              section.sh_size = ftell (file) - section.sh_offset;
05871            }
05872 
05873          if (is_32bit_elf)
05874            section.sh_entsize = sizeof (Elf32_External_Sym);
05875          else
05876            section.sh_entsize = sizeof (Elf64_External_Sym);
05877 
05878          num_dynamic_syms = section.sh_size / section.sh_entsize;
05879          if (num_dynamic_syms < 1)
05880            {
05881              error (_("Unable to determine the number of symbols to load\n"));
05882              continue;
05883            }
05884 
05885          dynamic_symbols = GET_ELF_SYMBOLS (file, &section);
05886        }
05887     }
05888 
05889   /* Similarly find a string table.  */
05890   if (dynamic_strings == NULL)
05891     {
05892       for (entry = dynamic_section;
05893           entry < dynamic_section + dynamic_nent;
05894           ++entry)
05895        {
05896          unsigned long offset;
05897          long str_tab_len;
05898 
05899          if (entry->d_tag != DT_STRTAB)
05900            continue;
05901 
05902          dynamic_info[DT_STRTAB] = entry->d_un.d_val;
05903 
05904          /* Since we do not know how big the string table is,
05905             we default to reading in the entire file (!) and
05906             processing that.  This is overkill, I know, but it
05907             should work.  */
05908 
05909          offset = offset_from_vma (file, entry->d_un.d_val, 0);
05910 
05911          if (archive_file_offset != 0)
05912            str_tab_len = archive_file_size - offset;
05913          else
05914            {
05915              if (fseek (file, 0, SEEK_END))
05916               error (_("Unable to seek to end of file\n"));
05917              str_tab_len = ftell (file) - offset;
05918            }
05919 
05920          if (str_tab_len < 1)
05921            {
05922              error
05923               (_("Unable to determine the length of the dynamic string table\n"));
05924              continue;
05925            }
05926 
05927          dynamic_strings = get_data (NULL, file, offset, 1, str_tab_len,
05928                                   _("dynamic string table"));
05929          dynamic_strings_length = str_tab_len;
05930          break;
05931        }
05932     }
05933 
05934   /* And find the syminfo section if available.  */
05935   if (dynamic_syminfo == NULL)
05936     {
05937       unsigned long syminsz = 0;
05938 
05939       for (entry = dynamic_section;
05940           entry < dynamic_section + dynamic_nent;
05941           ++entry)
05942        {
05943          if (entry->d_tag == DT_SYMINENT)
05944            {
05945              /* Note: these braces are necessary to avoid a syntax
05946                error from the SunOS4 C compiler.  */
05947              assert (sizeof (Elf_External_Syminfo) == entry->d_un.d_val);
05948            }
05949          else if (entry->d_tag == DT_SYMINSZ)
05950            syminsz = entry->d_un.d_val;
05951          else if (entry->d_tag == DT_SYMINFO)
05952            dynamic_syminfo_offset = offset_from_vma (file, entry->d_un.d_val,
05953                                                 syminsz);
05954        }
05955 
05956       if (dynamic_syminfo_offset != 0 && syminsz != 0)
05957        {
05958          Elf_External_Syminfo *extsyminfo, *extsym;
05959          Elf_Internal_Syminfo *syminfo;
05960 
05961          /* There is a syminfo section.  Read the data.  */
05962          extsyminfo = get_data (NULL, file, dynamic_syminfo_offset, 1,
05963                              syminsz, _("symbol information"));
05964          if (!extsyminfo)
05965            return 0;
05966 
05967          dynamic_syminfo = malloc (syminsz);
05968          if (dynamic_syminfo == NULL)
05969            {
05970              error (_("Out of memory\n"));
05971              return 0;
05972            }
05973 
05974          dynamic_syminfo_nent = syminsz / sizeof (Elf_External_Syminfo);
05975          for (syminfo = dynamic_syminfo, extsym = extsyminfo;
05976               syminfo < dynamic_syminfo + dynamic_syminfo_nent;
05977               ++syminfo, ++extsym)
05978            {
05979              syminfo->si_boundto = BYTE_GET (extsym->si_boundto);
05980              syminfo->si_flags = BYTE_GET (extsym->si_flags);
05981            }
05982 
05983          free (extsyminfo);
05984        }
05985     }
05986 
05987   if (do_dynamic && dynamic_addr)
05988     printf (_("\nDynamic section at offset 0x%lx contains %u entries:\n"),
05989            dynamic_addr, dynamic_nent);
05990   if (do_dynamic)
05991     printf (_("  Tag        Type                         Name/Value\n"));
05992 
05993   for (entry = dynamic_section;
05994        entry < dynamic_section + dynamic_nent;
05995        entry++)
05996     {
05997       if (do_dynamic)
05998        {
05999          const char *dtype;
06000 
06001          putchar (' ');
06002          print_vma (entry->d_tag, FULL_HEX);
06003          dtype = get_dynamic_type (entry->d_tag);
06004          printf (" (%s)%*s", dtype,
06005                 ((is_32bit_elf ? 27 : 19)
06006                  - (int) strlen (dtype)),
06007                 " ");
06008        }
06009 
06010       switch (entry->d_tag)
06011        {
06012        case DT_FLAGS:
06013          if (do_dynamic)
06014            print_dynamic_flags (entry->d_un.d_val);
06015          break;
06016 
06017        case DT_AUXILIARY:
06018        case DT_FILTER:
06019        case DT_CONFIG:
06020        case DT_DEPAUDIT:
06021        case DT_AUDIT:
06022          if (do_dynamic)
06023            {
06024              switch (entry->d_tag)
06025               {
06026               case DT_AUXILIARY:
06027                 printf (_("Auxiliary library"));
06028                 break;
06029 
06030               case DT_FILTER:
06031                 printf (_("Filter library"));
06032                 break;
06033 
06034               case DT_CONFIG:
06035                 printf (_("Configuration file"));
06036                 break;
06037 
06038               case DT_DEPAUDIT:
06039                 printf (_("Dependency audit library"));
06040                 break;
06041 
06042               case DT_AUDIT:
06043                 printf (_("Audit library"));
06044                 break;
06045               }
06046 
06047              if (VALID_DYNAMIC_NAME (entry->d_un.d_val))
06048               printf (": [%s]\n", GET_DYNAMIC_NAME (entry->d_un.d_val));
06049              else
06050               {
06051                 printf (": ");
06052                 print_vma (entry->d_un.d_val, PREFIX_HEX);
06053                 putchar ('\n');
06054               }
06055            }
06056          break;
06057 
06058        case DT_FEATURE:
06059          if (do_dynamic)
06060            {
06061              printf (_("Flags:"));
06062 
06063              if (entry->d_un.d_val == 0)
06064               printf (_(" None\n"));
06065              else
06066               {
06067                 unsigned long int val = entry->d_un.d_val;
06068 
06069                 if (val & DTF_1_PARINIT)
06070                   {
06071                     printf (" PARINIT");
06072                     val ^= DTF_1_PARINIT;
06073                   }
06074                 if (val & DTF_1_CONFEXP)
06075                   {
06076                     printf (" CONFEXP");
06077                     val ^= DTF_1_CONFEXP;
06078                   }
06079                 if (val != 0)
06080                   printf (" %lx", val);
06081                 puts ("");
06082               }
06083            }
06084          break;
06085 
06086        case DT_POSFLAG_1:
06087          if (do_dynamic)
06088            {
06089              printf (_("Flags:"));
06090 
06091              if (entry->d_un.d_val == 0)
06092               printf (_(" None\n"));
06093              else
06094               {
06095                 unsigned long int val = entry->d_un.d_val;
06096 
06097                 if (val & DF_P1_LAZYLOAD)
06098                   {
06099                     printf (" LAZYLOAD");
06100                     val ^= DF_P1_LAZYLOAD;
06101                   }
06102                 if (val & DF_P1_GROUPPERM)
06103                   {
06104                     printf (" GROUPPERM");
06105                     val ^= DF_P1_GROUPPERM;
06106                   }
06107                 if (val != 0)
06108                   printf (" %lx", val);
06109                 puts ("");
06110               }
06111            }
06112          break;
06113 
06114        case DT_FLAGS_1:
06115          if (do_dynamic)
06116            {
06117              printf (_("Flags:"));
06118              if (entry->d_un.d_val == 0)
06119               printf (_(" None\n"));
06120              else
06121               {
06122                 unsigned long int val = entry->d_un.d_val;
06123 
06124                 if (val & DF_1_NOW)
06125                   {
06126                     printf (" NOW");
06127                     val ^= DF_1_NOW;
06128                   }
06129                 if (val & DF_1_GLOBAL)
06130                   {
06131                     printf (" GLOBAL");
06132                     val ^= DF_1_GLOBAL;
06133                   }
06134                 if (val & DF_1_GROUP)
06135                   {
06136                     printf (" GROUP");
06137                     val ^= DF_1_GROUP;
06138                   }
06139                 if (val & DF_1_NODELETE)
06140                   {
06141                     printf (" NODELETE");
06142                     val ^= DF_1_NODELETE;
06143                   }
06144                 if (val & DF_1_LOADFLTR)
06145                   {
06146                     printf (" LOADFLTR");
06147                     val ^= DF_1_LOADFLTR;
06148                   }
06149                 if (val & DF_1_INITFIRST)
06150                   {
06151                     printf (" INITFIRST");
06152                     val ^= DF_1_INITFIRST;
06153                   }
06154                 if (val & DF_1_NOOPEN)
06155                   {
06156                     printf (" NOOPEN");
06157                     val ^= DF_1_NOOPEN;
06158                   }
06159                 if (val & DF_1_ORIGIN)
06160                   {
06161                     printf (" ORIGIN");
06162                     val ^= DF_1_ORIGIN;
06163                   }
06164                 if (val & DF_1_DIRECT)
06165                   {
06166                     printf (" DIRECT");
06167                     val ^= DF_1_DIRECT;
06168                   }
06169                 if (val & DF_1_TRANS)
06170                   {
06171                     printf (" TRANS");
06172                     val ^= DF_1_TRANS;
06173                   }
06174                 if (val & DF_1_INTERPOSE)
06175                   {
06176                     printf (" INTERPOSE");
06177                     val ^= DF_1_INTERPOSE;
06178                   }
06179                 if (val & DF_1_NODEFLIB)
06180                   {
06181                     printf (" NODEFLIB");
06182                     val ^= DF_1_NODEFLIB;
06183                   }
06184                 if (val & DF_1_NODUMP)
06185                   {
06186                     printf (" NODUMP");
06187                     val ^= DF_1_NODUMP;
06188                   }
06189                 if (val & DF_1_CONLFAT)
06190                   {
06191                     printf (" CONLFAT");
06192                     val ^= DF_1_CONLFAT;
06193                   }
06194                 if (val != 0)
06195                   printf (" %lx", val);
06196                 puts ("");
06197               }
06198            }
06199          break;
06200 
06201        case DT_PLTREL:
06202          dynamic_info[entry->d_tag] = entry->d_un.d_val;
06203          if (do_dynamic)
06204            puts (get_dynamic_type (entry->d_un.d_val));
06205          break;
06206 
06207        case DT_NULL  :
06208        case DT_NEEDED       :
06209        case DT_PLTGOT       :
06210        case DT_HASH  :
06211        case DT_STRTAB       :
06212        case DT_SYMTAB       :
06213        case DT_RELA  :
06214        case DT_INIT  :
06215        case DT_FINI  :
06216        case DT_SONAME       :
06217        case DT_RPATH :
06218        case DT_SYMBOLIC:
06219        case DT_REL   :
06220        case DT_DEBUG :
06221        case DT_TEXTREL      :
06222        case DT_JMPREL       :
06223        case DT_RUNPATH      :
06224          dynamic_info[entry->d_tag] = entry->d_un.d_val;
06225 
06226          if (do_dynamic)
06227            {
06228              char *name;
06229 
06230              if (VALID_DYNAMIC_NAME (entry->d_un.d_val))
06231               name = GET_DYNAMIC_NAME (entry->d_un.d_val);
06232              else
06233               name = NULL;
06234 
06235              if (name)
06236               {
06237                 switch (entry->d_tag)
06238                   {
06239                   case DT_NEEDED:
06240                     printf (_("Shared library: [%s]"), name);
06241 
06242                     if (streq (name, program_interpreter))
06243                      printf (_(" program interpreter"));
06244                     break;
06245 
06246                   case DT_SONAME:
06247                     printf (_("Library soname: [%s]"), name);
06248                     break;
06249 
06250                   case DT_RPATH:
06251                     printf (_("Library rpath: [%s]"), name);
06252                     break;
06253 
06254                   case DT_RUNPATH:
06255                     printf (_("Library runpath: [%s]"), name);
06256                     break;
06257 
06258                   default:
06259                     print_vma (entry->d_un.d_val, PREFIX_HEX);
06260                     break;
06261                   }
06262               }
06263              else
06264               print_vma (entry->d_un.d_val, PREFIX_HEX);
06265 
06266              putchar ('\n');
06267            }
06268          break;
06269 
06270        case DT_PLTRELSZ:
06271        case DT_RELASZ       :
06272        case DT_STRSZ :
06273        case DT_RELSZ :
06274        case DT_RELAENT      :
06275        case DT_SYMENT       :
06276        case DT_RELENT       :
06277          dynamic_info[entry->d_tag] = entry->d_un.d_val;
06278        case DT_PLTPADSZ:
06279        case DT_MOVEENT      :
06280        case DT_MOVESZ       :
06281        case DT_INIT_ARRAYSZ:
06282        case DT_FINI_ARRAYSZ:
06283        case DT_GNU_CONFLICTSZ:
06284        case DT_GNU_LIBLISTSZ:
06285          if (do_dynamic)
06286            {
06287              print_vma (entry->d_un.d_val, UNSIGNED);
06288              printf (" (bytes)\n");
06289            }
06290          break;
06291 
06292        case DT_VERDEFNUM:
06293        case DT_VERNEEDNUM:
06294        case DT_RELACOUNT:
06295        case DT_RELCOUNT:
06296          if (do_dynamic)
06297            {
06298              print_vma (entry->d_un.d_val, UNSIGNED);
06299              putchar ('\n');
06300            }
06301          break;
06302 
06303        case DT_SYMINSZ:
06304        case DT_SYMINENT:
06305        case DT_SYMINFO:
06306        case DT_USED:
06307        case DT_INIT_ARRAY:
06308        case DT_FINI_ARRAY:
06309          if (do_dynamic)
06310            {
06311              if (entry->d_tag == DT_USED
06312                 && VALID_DYNAMIC_NAME (entry->d_un.d_val))
06313               {
06314                 char *name = GET_DYNAMIC_NAME (entry->d_un.d_val);
06315 
06316                 if (*name)
06317                   {
06318                     printf (_("Not needed object: [%s]\n"), name);
06319                     break;
06320                   }
06321               }
06322 
06323              print_vma (entry->d_un.d_val, PREFIX_HEX);
06324              putchar ('\n');
06325            }
06326          break;
06327 
06328        case DT_BIND_NOW:
06329          /* The value of this entry is ignored.  */
06330          if (do_dynamic)
06331            putchar ('\n');
06332          break;
06333 
06334        case DT_GNU_PRELINKED:
06335          if (do_dynamic)
06336            {
06337              struct tm *tmp;
06338              time_t time = entry->d_un.d_val;
06339 
06340              tmp = gmtime (&time);
06341              printf ("%04u-%02u-%02uT%02u:%02u:%02u\n",
06342                     tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
06343                     tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
06344 
06345            }
06346          break;
06347 
06348        case DT_GNU_HASH:
06349          dynamic_info_DT_GNU_HASH = entry->d_un.d_val;
06350          if (do_dynamic)
06351            {
06352              print_vma (entry->d_un.d_val, PREFIX_HEX);
06353              putchar ('\n');
06354            }
06355          break;
06356 
06357        default:
06358          if ((entry->d_tag >= DT_VERSYM) && (entry->d_tag <= DT_VERNEEDNUM))
06359            version_info[DT_VERSIONTAGIDX (entry->d_tag)] =
06360              entry->d_un.d_val;
06361 
06362          if (do_dynamic)
06363            {
06364              switch (elf_header.e_machine)
06365               {
06366               case EM_MIPS:
06367               case EM_MIPS_RS3_LE:
06368                 dynamic_section_mips_val (entry);
06369                 break;
06370               case EM_PARISC:
06371                 dynamic_section_parisc_val (entry);
06372                 break;
06373               case EM_IA_64:
06374                 dynamic_section_ia64_val (entry);
06375                 break;
06376               default:
06377                 print_vma (entry->d_un.d_val, PREFIX_HEX);
06378                 putchar ('\n');
06379               }
06380            }
06381          break;
06382        }
06383     }
06384 
06385   return 1;
06386 }
06387 
06388 static char *
06389 get_ver_flags (unsigned int flags)
06390 {
06391   static char buff[32];
06392 
06393   buff[0] = 0;
06394 
06395   if (flags == 0)
06396     return _("none");
06397 
06398   if (flags & VER_FLG_BASE)
06399     strcat (buff, "BASE ");
06400 
06401   if (flags & VER_FLG_WEAK)
06402     {
06403       if (flags & VER_FLG_BASE)
06404        strcat (buff, "| ");
06405 
06406       strcat (buff, "WEAK ");
06407     }
06408 
06409   if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK))
06410     strcat (buff, "| <unknown>");
06411 
06412   return buff;
06413 }
06414 
06415 /* Display the contents of the version sections.  */
06416 static int
06417 process_version_sections (FILE *file)
06418 {
06419   Elf_Internal_Shdr *section;
06420   unsigned i;
06421   int found = 0;
06422 
06423   if (! do_version)
06424     return 1;
06425 
06426   for (i = 0, section = section_headers;
06427        i < elf_header.e_shnum;
06428        i++, section++)
06429     {
06430       switch (section->sh_type)
06431        {
06432        case SHT_GNU_verdef:
06433          {
06434            Elf_External_Verdef *edefs;
06435            unsigned int idx;
06436            unsigned int cnt;
06437 
06438            found = 1;
06439 
06440            printf
06441              (_("\nVersion definition section '%s' contains %ld entries:\n"),
06442               SECTION_NAME (section), section->sh_info);
06443 
06444            printf (_("  Addr: 0x"));
06445            printf_vma (section->sh_addr);
06446            printf (_("  Offset: %#08lx  Link: %lx (%s)\n"),
06447                   (unsigned long) section->sh_offset, section->sh_link,
06448                   SECTION_HEADER_INDEX (section->sh_link)
06449                   < elf_header.e_shnum
06450                   ? SECTION_NAME (SECTION_HEADER (section->sh_link))
06451                   : "<corrupt>");
06452 
06453            edefs = get_data (NULL, file, section->sh_offset, 1,
06454                            section->sh_size,
06455                            _("version definition section"));
06456            if (!edefs)
06457              break;
06458 
06459            for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
06460              {
06461               char *vstart;
06462               Elf_External_Verdef *edef;
06463               Elf_Internal_Verdef ent;
06464               Elf_External_Verdaux *eaux;
06465               Elf_Internal_Verdaux aux;
06466               int j;
06467               int isum;
06468 
06469               vstart = ((char *) edefs) + idx;
06470 
06471               edef = (Elf_External_Verdef *) vstart;
06472 
06473               ent.vd_version = BYTE_GET (edef->vd_version);
06474               ent.vd_flags   = BYTE_GET (edef->vd_flags);
06475               ent.vd_ndx     = BYTE_GET (edef->vd_ndx);
06476               ent.vd_cnt     = BYTE_GET (edef->vd_cnt);
06477               ent.vd_hash    = BYTE_GET (edef->vd_hash);
06478               ent.vd_aux     = BYTE_GET (edef->vd_aux);
06479               ent.vd_next    = BYTE_GET (edef->vd_next);
06480 
06481               printf (_("  %#06x: Rev: %d  Flags: %s"),
06482                      idx, ent.vd_version, get_ver_flags (ent.vd_flags));
06483 
06484               printf (_("  Index: %d  Cnt: %d  "),
06485                      ent.vd_ndx, ent.vd_cnt);
06486 
06487               vstart += ent.vd_aux;
06488 
06489               eaux = (Elf_External_Verdaux *) vstart;
06490 
06491               aux.vda_name = BYTE_GET (eaux->vda_name);
06492               aux.vda_next = BYTE_GET (eaux->vda_next);
06493 
06494               if (VALID_DYNAMIC_NAME (aux.vda_name))
06495                 printf (_("Name: %s\n"), GET_DYNAMIC_NAME (aux.vda_name));
06496               else
06497                 printf (_("Name index: %ld\n"), aux.vda_name);
06498 
06499               isum = idx + ent.vd_aux;
06500 
06501               for (j = 1; j < ent.vd_cnt; j++)
06502                 {
06503                   isum   += aux.vda_next;
06504                   vstart += aux.vda_next;
06505 
06506                   eaux = (Elf_External_Verdaux *) vstart;
06507 
06508                   aux.vda_name = BYTE_GET (eaux->vda_name);
06509                   aux.vda_next = BYTE_GET (eaux->vda_next);
06510 
06511                   if (VALID_DYNAMIC_NAME (aux.vda_name))
06512                     printf (_("  %#06x: Parent %d: %s\n"),
06513                            isum, j, GET_DYNAMIC_NAME (aux.vda_name));
06514                   else
06515                     printf (_("  %#06x: Parent %d, name index: %ld\n"),
06516                            isum, j, aux.vda_name);
06517                 }
06518 
06519               idx += ent.vd_next;
06520              }
06521 
06522            free (edefs);
06523          }
06524          break;
06525 
06526        case SHT_GNU_verneed:
06527          {
06528            Elf_External_Verneed *eneed;
06529            unsigned int idx;
06530            unsigned int cnt;
06531 
06532            found = 1;
06533 
06534            printf (_("\nVersion needs section '%s' contains %ld entries:\n"),
06535                   SECTION_NAME (section), section->sh_info);
06536 
06537            printf (_(" Addr: 0x"));
06538            printf_vma (section->sh_addr);
06539            printf (_("  Offset: %#08lx  Link to section: %ld (%s)\n"),
06540                   (unsigned long) section->sh_offset, section->sh_link,
06541                   SECTION_HEADER_INDEX (section->sh_link)
06542                   < elf_header.e_shnum
06543                   ? SECTION_NAME (SECTION_HEADER (section->sh_link))
06544                   : "<corrupt>");
06545 
06546            eneed = get_data (NULL, file, section->sh_offset, 1,
06547                            section->sh_size,
06548                            _("version need section"));
06549            if (!eneed)
06550              break;
06551 
06552            for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
06553              {
06554               Elf_External_Verneed *entry;
06555               Elf_Internal_Verneed ent;
06556               int j;
06557               int isum;
06558               char *vstart;
06559 
06560               vstart = ((char *) eneed) + idx;
06561 
06562               entry = (Elf_External_Verneed *) vstart;
06563 
06564               ent.vn_version = BYTE_GET (entry->vn_version);
06565               ent.vn_cnt     = BYTE_GET (entry->vn_cnt);
06566               ent.vn_file    = BYTE_GET (entry->vn_file);
06567               ent.vn_aux     = BYTE_GET (entry->vn_aux);
06568               ent.vn_next    = BYTE_GET (entry->vn_next);
06569 
06570               printf (_("  %#06x: Version: %d"), idx, ent.vn_version);
06571 
06572               if (VALID_DYNAMIC_NAME (ent.vn_file))
06573                 printf (_("  File: %s"), GET_DYNAMIC_NAME (ent.vn_file));
06574               else
06575                 printf (_("  File: %lx"), ent.vn_file);
06576 
06577               printf (_("  Cnt: %d\n"), ent.vn_cnt);
06578 
06579               vstart += ent.vn_aux;
06580 
06581               for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j)
06582                 {
06583                   Elf_External_Vernaux *eaux;
06584                   Elf_Internal_Vernaux aux;
06585 
06586                   eaux = (Elf_External_Vernaux *) vstart;
06587 
06588                   aux.vna_hash  = BYTE_GET (eaux->vna_hash);
06589                   aux.vna_flags = BYTE_GET (eaux->vna_flags);
06590                   aux.vna_other = BYTE_GET (eaux->vna_other);
06591                   aux.vna_name  = BYTE_GET (eaux->vna_name);
06592                   aux.vna_next  = BYTE_GET (eaux->vna_next);
06593 
06594                   if (VALID_DYNAMIC_NAME (aux.vna_name))
06595                     printf (_("  %#06x:   Name: %s"),
06596                            isum, GET_DYNAMIC_NAME (aux.vna_name));
06597                   else
06598                     printf (_("  %#06x:   Name index: %lx"),
06599                            isum, aux.vna_name);
06600 
06601                   printf (_("  Flags: %s  Version: %d\n"),
06602                          get_ver_flags (aux.vna_flags), aux.vna_other);
06603 
06604                   isum   += aux.vna_next;
06605                   vstart += aux.vna_next;
06606                 }
06607 
06608               idx += ent.vn_next;
06609              }
06610 
06611            free (eneed);
06612          }
06613          break;
06614 
06615        case SHT_GNU_versym:
06616          {
06617            Elf_Internal_Shdr *link_section;
06618            int total;
06619            int cnt;
06620            unsigned char *edata;
06621            unsigned short *data;
06622            char *strtab;
06623            Elf_Internal_Sym *symbols;
06624            Elf_Internal_Shdr *string_sec;
06625            long off;
06626 
06627            if (SECTION_HEADER_INDEX (section->sh_link) >= elf_header.e_shnum)
06628              break;
06629 
06630            link_section = SECTION_HEADER (section->sh_link);
06631            total = section->sh_size / sizeof (Elf_External_Versym);
06632 
06633            if (SECTION_HEADER_INDEX (link_section->sh_link)
06634               >= elf_header.e_shnum)
06635              break;
06636 
06637            found = 1;
06638 
06639            symbols = GET_ELF_SYMBOLS (file, link_section);
06640 
06641            string_sec = SECTION_HEADER (link_section->sh_link);
06642 
06643            strtab = get_data (NULL, file, string_sec->sh_offset, 1,
06644                             string_sec->sh_size, _("version string table"));
06645            if (!strtab)
06646              break;
06647 
06648            printf (_("\nVersion symbols section '%s' contains %d entries:\n"),
06649                   SECTION_NAME (section), total);
06650 
06651            printf (_(" Addr: "));
06652            printf_vma (section->sh_addr);
06653            printf (_("  Offset: %#08lx  Link: %lx (%s)\n"),
06654                   (unsigned long) section->sh_offset, section->sh_link,
06655                   SECTION_NAME (link_section));
06656 
06657            off = offset_from_vma (file,
06658                                version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
06659                                total * sizeof (short));
06660            edata = get_data (NULL, file, off, total, sizeof (short),
06661                            _("version symbol data"));
06662            if (!edata)
06663              {
06664               free (strtab);
06665               break;
06666              }
06667 
06668            data = cmalloc (total, sizeof (short));
06669 
06670            for (cnt = total; cnt --;)
06671              data[cnt] = byte_get (edata + cnt * sizeof (short),
06672                                 sizeof (short));
06673 
06674            free (edata);
06675 
06676            for (cnt = 0; cnt < total; cnt += 4)
06677              {
06678               int j, nn;
06679               int check_def, check_need;
06680               char *name;
06681 
06682               printf ("  %03x:", cnt);
06683 
06684               for (j = 0; (j < 4) && (cnt + j) < total; ++j)
06685                 switch (data[cnt + j])
06686                   {
06687                   case 0:
06688                     fputs (_("   0 (*local*)    "), stdout);
06689                     break;
06690 
06691                   case 1:
06692                     fputs (_("   1 (*global*)   "), stdout);
06693                     break;
06694 
06695                   default:
06696                     nn = printf ("%4x%c", data[cnt + j] & 0x7fff,
06697                                data[cnt + j] & 0x8000 ? 'h' : ' ');
06698 
06699                     check_def = 1;
06700                     check_need = 1;
06701                     if (SECTION_HEADER_INDEX (symbols[cnt + j].st_shndx)
06702                        >= elf_header.e_shnum
06703                        || SECTION_HEADER (symbols[cnt + j].st_shndx)->sh_type
06704                           != SHT_NOBITS)
06705                      {
06706                        if (symbols[cnt + j].st_shndx == SHN_UNDEF)
06707                          check_def = 0;
06708                        else
06709                          check_need = 0;
06710                      }
06711 
06712                     if (check_need
06713                        && version_info[DT_VERSIONTAGIDX (DT_VERNEED)])
06714                      {
06715                        Elf_Internal_Verneed ivn;
06716                        unsigned long offset;
06717 
06718                        offset = offset_from_vma
06719                          (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)],
06720                           sizeof (Elf_External_Verneed));
06721 
06722                        do
06723                          {
06724                            Elf_Internal_Vernaux ivna;
06725                            Elf_External_Verneed evn;
06726                            Elf_External_Vernaux evna;
06727                            unsigned long a_off;
06728 
06729                            get_data (&evn, file, offset, sizeof (evn), 1,
06730                                    _("version need"));
06731 
06732                            ivn.vn_aux  = BYTE_GET (evn.vn_aux);
06733                            ivn.vn_next = BYTE_GET (evn.vn_next);
06734 
06735                            a_off = offset + ivn.vn_aux;
06736 
06737                            do
06738                             {
06739                               get_data (&evna, file, a_off, sizeof (evna),
06740                                        1, _("version need aux (2)"));
06741 
06742                               ivna.vna_next  = BYTE_GET (evna.vna_next);
06743                               ivna.vna_other = BYTE_GET (evna.vna_other);
06744 
06745                               a_off += ivna.vna_next;
06746                             }
06747                            while (ivna.vna_other != data[cnt + j]
06748                                  && ivna.vna_next != 0);
06749 
06750                            if (ivna.vna_other == data[cnt + j])
06751                             {
06752                               ivna.vna_name = BYTE_GET (evna.vna_name);
06753 
06754                               name = strtab + ivna.vna_name;
06755                               nn += printf ("(%s%-*s",
06756                                           name,
06757                                           12 - (int) strlen (name),
06758                                           ")");
06759                               check_def = 0;
06760                               break;
06761                             }
06762 
06763                            offset += ivn.vn_next;
06764                          }
06765                        while (ivn.vn_next);
06766                      }
06767 
06768                     if (check_def && data[cnt + j] != 0x8001
06769                        && version_info[DT_VERSIONTAGIDX (DT_VERDEF)])
06770                      {
06771                        Elf_Internal_Verdef ivd;
06772                        Elf_External_Verdef evd;
06773                        unsigned long offset;
06774 
06775                        offset = offset_from_vma
06776                          (file, version_info[DT_VERSIONTAGIDX (DT_VERDEF)],
06777                           sizeof evd);
06778 
06779                        do
06780                          {
06781                            get_data (&evd, file, offset, sizeof (evd), 1,
06782                                    _("version def"));
06783 
06784                            ivd.vd_next = BYTE_GET (evd.vd_next);
06785                            ivd.vd_ndx  = BYTE_GET (evd.vd_ndx);
06786 
06787                            offset += ivd.vd_next;
06788                          }
06789                        while (ivd.vd_ndx != (data[cnt + j] & 0x7fff)
06790                              && ivd.vd_next != 0);
06791 
06792                        if (ivd.vd_ndx == (data[cnt + j] & 0x7fff))
06793                          {
06794                            Elf_External_Verdaux evda;
06795                            Elf_Internal_Verdaux ivda;
06796 
06797                            ivd.vd_aux = BYTE_GET (evd.vd_aux);
06798 
06799                            get_data (&evda, file,
06800                                    offset - ivd.vd_next + ivd.vd_aux,
06801                                    sizeof (evda), 1,
06802                                    _("version def aux"));
06803 
06804                            ivda.vda_name = BYTE_GET (evda.vda_name);
06805 
06806                            name = strtab + ivda.vda_name;
06807                            nn += printf ("(%s%-*s",
06808                                        name,
06809                                        12 - (int) strlen (name),
06810                                        ")");
06811                          }
06812                      }
06813 
06814                     if (nn < 18)
06815                      printf ("%*c", 18 - nn, ' ');
06816                   }
06817 
06818               putchar ('\n');
06819              }
06820 
06821            free (data);
06822            free (strtab);
06823            free (symbols);
06824          }
06825          break;
06826 
06827        default:
06828          break;
06829        }
06830     }
06831 
06832   if (! found)
06833     printf (_("\nNo version information found in this file.\n"));
06834 
06835   return 1;
06836 }
06837 
06838 static const char *
06839 get_symbol_binding (unsigned int binding)
06840 {
06841   static char buff[32];
06842 
06843   switch (binding)
06844     {
06845     case STB_LOCAL:  return "LOCAL";
06846     case STB_GLOBAL: return "GLOBAL";
06847     case STB_WEAK:   return "WEAK";
06848     default:
06849       if (binding >= STB_LOPROC && binding <= STB_HIPROC)
06850        snprintf (buff, sizeof (buff), _("<processor specific>: %d"),
06851                 binding);
06852       else if (binding >= STB_LOOS && binding <= STB_HIOS)
06853        snprintf (buff, sizeof (buff), _("<OS specific>: %d"), binding);
06854       else
06855        snprintf (buff, sizeof (buff), _("<unknown>: %d"), binding);
06856       return buff;
06857     }
06858 }
06859 
06860 static const char *
06861 get_symbol_type (unsigned int type)
06862 {
06863   static char buff[32];
06864 
06865   switch (type)
06866     {
06867     case STT_NOTYPE: return "NOTYPE";
06868     case STT_OBJECT: return "OBJECT";
06869     case STT_FUNC:   return "FUNC";
06870     case STT_SECTION:       return "SECTION";
06871     case STT_FILE:   return "FILE";
06872     case STT_COMMON: return "COMMON";
06873     case STT_TLS:    return "TLS";
06874     case STT_RELC:      return "RELC";
06875     case STT_SRELC:     return "SRELC";
06876     default:
06877       if (type >= STT_LOPROC && type <= STT_HIPROC)
06878        {
06879          if (elf_header.e_machine == EM_ARM && type == STT_ARM_TFUNC)
06880            return "THUMB_FUNC";
06881 
06882          if (elf_header.e_machine == EM_SPARCV9 && type == STT_REGISTER)
06883            return "REGISTER";
06884 
06885          if (elf_header.e_machine == EM_PARISC && type == STT_PARISC_MILLI)
06886            return "PARISC_MILLI";
06887 
06888          snprintf (buff, sizeof (buff), _("<processor specific>: %d"), type);
06889        }
06890       else if (type >= STT_LOOS && type <= STT_HIOS)
06891        {
06892          if (elf_header.e_machine == EM_PARISC)
06893            {
06894              if (type == STT_HP_OPAQUE)
06895               return "HP_OPAQUE";
06896              if (type == STT_HP_STUB)
06897               return "HP_STUB";
06898            }
06899 
06900          snprintf (buff, sizeof (buff), _("<OS specific>: %d"), type);
06901        }
06902       else
06903        snprintf (buff, sizeof (buff), _("<unknown>: %d"), type);
06904       return buff;
06905     }
06906 }
06907 
06908 static const char *
06909 get_symbol_visibility (unsigned int visibility)
06910 {
06911   switch (visibility)
06912     {
06913     case STV_DEFAULT:       return "DEFAULT";
06914     case STV_INTERNAL:      return "INTERNAL";
06915     case STV_HIDDEN: return "HIDDEN";
06916     case STV_PROTECTED: return "PROTECTED";
06917     default: abort ();
06918     }
06919 }
06920 
06921 static const char *
06922 get_mips_symbol_other (unsigned int other)
06923 {
06924   switch (other)
06925     {
06926     case STO_OPTIONAL:  return "OPTIONAL";
06927     case STO_MIPS16:    return "MIPS16";
06928     default:         return NULL;
06929     }
06930 }
06931 
06932 static const char *
06933 get_symbol_other (unsigned int other)
06934 {
06935   const char * result = NULL;
06936   static char buff [32];
06937 
06938   if (other == 0)
06939     return "";
06940 
06941   switch (elf_header.e_machine)
06942     {
06943     case EM_MIPS:
06944       result = get_mips_symbol_other (other);
06945     default:
06946       break;
06947     }
06948 
06949   if (result)
06950     return result;
06951 
06952   snprintf (buff, sizeof buff, _("<other>: %x"), other);
06953   return buff;
06954 }
06955 
06956 static const char *
06957 get_symbol_index_type (unsigned int type)
06958 {
06959   static char buff[32];
06960 
06961   switch (type)
06962     {
06963     case SHN_UNDEF:  return "UND";
06964     case SHN_ABS:    return "ABS";
06965     case SHN_COMMON: return "COM";
06966     default:
06967       if (type == SHN_IA_64_ANSI_COMMON
06968          && elf_header.e_machine == EM_IA_64
06969          && elf_header.e_ident[EI_OSABI] == ELFOSABI_HPUX)
06970        return "ANSI_COM";
06971       else if (elf_header.e_machine == EM_X86_64
06972               && type == SHN_X86_64_LCOMMON)
06973        return "LARGE_COM";
06974       else if (type == SHN_MIPS_SCOMMON
06975               && elf_header.e_machine == EM_MIPS)
06976        return "SCOM";
06977       else if (type == SHN_MIPS_SUNDEFINED
06978               && elf_header.e_machine == EM_MIPS)
06979        return "SUND";
06980       else if (type >= SHN_LOPROC && type <= SHN_HIPROC)
06981        sprintf (buff, "PRC[0x%04x]", type);
06982       else if (type >= SHN_LOOS && type <= SHN_HIOS)
06983        sprintf (buff, "OS [0x%04x]", type);
06984       else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE)
06985        sprintf (buff, "RSV[0x%04x]", type);
06986       else
06987        sprintf (buff, "%3d", type);
06988       break;
06989     }
06990 
06991   return buff;
06992 }
06993 
06994 static bfd_vma *
06995 get_dynamic_data (FILE *file, unsigned int number, unsigned int ent_size)
06996 {
06997   unsigned char *e_data;
06998   bfd_vma *i_data;
06999 
07000   e_data = cmalloc (number, ent_size);
07001 
07002   if (e_data == NULL)
07003     {
07004       error (_("Out of memory\n"));
07005       return NULL;
07006     }
07007 
07008   if (fread (e_data, ent_size, number, file) != number)
07009     {
07010       error (_("Unable to read in dynamic data\n"));
07011       return NULL;
07012     }
07013 
07014   i_data = cmalloc (number, sizeof (*i_data));
07015 
07016   if (i_data == NULL)
07017     {
07018       error (_("Out of memory\n"));
07019       free (e_data);
07020       return NULL;
07021     }
07022 
07023   while (number--)
07024     i_data[number] = byte_get (e_data + number * ent_size, ent_size);
07025 
07026   free (e_data);
07027 
07028   return i_data;
07029 }
07030 
07031 /* Dump the symbol table.  */
07032 static int
07033 process_symbol_table (FILE *file)
07034 {
07035   Elf_Internal_Shdr *section;
07036   bfd_vma nbuckets = 0;
07037   bfd_vma nchains = 0;
07038   bfd_vma *buckets = NULL;
07039   bfd_vma *chains = NULL;
07040   bfd_vma ngnubuckets = 0;
07041   bfd_vma *gnubuckets = NULL;
07042   bfd_vma *gnuchains = NULL;
07043 
07044   if (! do_syms && !do_histogram)
07045     return 1;
07046 
07047   if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL)
07048                             || do_histogram))
07049     {
07050       unsigned char nb[8];
07051       unsigned char nc[8];
07052       int hash_ent_size = 4;
07053 
07054       if ((elf_header.e_machine == EM_ALPHA
07055           || elf_header.e_machine == EM_S390
07056           || elf_header.e_machine == EM_S390_OLD)
07057          && elf_header.e_ident[EI_CLASS] == ELFCLASS64)
07058        hash_ent_size = 8;
07059 
07060       if (fseek (file,
07061                (archive_file_offset
07062                 + offset_from_vma (file, dynamic_info[DT_HASH],
07063                                  sizeof nb + sizeof nc)),
07064                SEEK_SET))
07065        {
07066          error (_("Unable to seek to start of dynamic information\n"));
07067          return 0;
07068        }
07069 
07070       if (fread (nb, hash_ent_size, 1, file) != 1)
07071        {
07072          error (_("Failed to read in number of buckets\n"));
07073          return 0;
07074        }
07075 
07076       if (fread (nc, hash_ent_size, 1, file) != 1)
07077        {
07078          error (_("Failed to read in number of chains\n"));
07079          return 0;
07080        }
07081 
07082       nbuckets = byte_get (nb, hash_ent_size);
07083       nchains  = byte_get (nc, hash_ent_size);
07084 
07085       buckets = get_dynamic_data (file, nbuckets, hash_ent_size);
07086       chains  = get_dynamic_data (file, nchains, hash_ent_size);
07087 
07088       if (buckets == NULL || chains == NULL)
07089        return 0;
07090     }
07091 
07092   if (do_syms
07093       && dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL)
07094     {
07095       unsigned long hn;
07096       bfd_vma si;
07097 
07098       printf (_("\nSymbol table for image:\n"));
07099       if (is_32bit_elf)
07100        printf (_("  Num Buc:    Value  Size   Type   Bind Vis      Ndx Name\n"));
07101       else
07102        printf (_("  Num Buc:    Value          Size   Type   Bind Vis      Ndx Name\n"));
07103 
07104       for (hn = 0; hn < nbuckets; hn++)
07105        {
07106          if (! buckets[hn])
07107            continue;
07108 
07109          for (si = buckets[hn]; si < nchains && si > 0; si = chains[si])
07110            {
07111              Elf_Internal_Sym *psym;
07112              int n;
07113 
07114              psym = dynamic_symbols + si;
07115 
07116              n = print_vma (si, DEC_5);
07117              if (n < 5)
07118               fputs ("     " + n, stdout);
07119              printf (" %3lu: ", hn);
07120              print_vma (psym->st_value, LONG_HEX);
07121              putchar (' ');
07122              print_vma (psym->st_size, DEC_5);
07123 
07124              printf ("  %6s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
07125              printf (" %6s",  get_symbol_binding (ELF_ST_BIND (psym->st_info)));
07126              printf (" %3s",  get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
07127              /* Check to see if any other bits in the st_other field are set.
07128                 Note - displaying this information disrupts the layout of the
07129                 table being generated, but for the moment this case is very rare.  */
07130              if (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other))
07131               printf (" [%s] ", get_symbol_other (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other)));
07132              printf (" %3.3s ", get_symbol_index_type (psym->st_shndx));
07133              if (VALID_DYNAMIC_NAME (psym->st_name))
07134               print_symbol (25, GET_DYNAMIC_NAME (psym->st_name));
07135              else
07136               printf (" <corrupt: %14ld>", psym->st_name);
07137              putchar ('\n');
07138            }
07139        }
07140     }
07141   else if (do_syms && !do_using_dynamic)
07142     {
07143       unsigned int i;
07144 
07145       for (i = 0, section = section_headers;
07146           i < elf_header.e_shnum;
07147           i++, section++)
07148        {
07149          unsigned int si;
07150          char *strtab = NULL;
07151          unsigned long int strtab_size = 0;
07152          Elf_Internal_Sym *symtab;
07153          Elf_Internal_Sym *psym;
07154 
07155 
07156          if (   section->sh_type != SHT_SYMTAB
07157              && section->sh_type != SHT_DYNSYM)
07158            continue;
07159 
07160          printf (_("\nSymbol table '%s' contains %lu entries:\n"),
07161                 SECTION_NAME (section),
07162                 (unsigned long) (section->sh_size / section->sh_entsize));
07163          if (is_32bit_elf)
07164            printf (_("   Num:    Value  Size Type    Bind   Vis      Ndx Name\n"));
07165          else
07166            printf (_("   Num:    Value          Size Type    Bind   Vis      Ndx Name\n"));
07167 
07168          symtab = GET_ELF_SYMBOLS (file, section);
07169          if (symtab == NULL)
07170            continue;
07171 
07172          if (section->sh_link == elf_header.e_shstrndx)
07173            {
07174              strtab = string_table;
07175              strtab_size = string_table_length;
07176            }
07177          else if (SECTION_HEADER_INDEX (section->sh_link) < elf_header.e_shnum)
07178            {
07179              Elf_Internal_Shdr *string_sec;
07180 
07181              string_sec = SECTION_HEADER (section->sh_link);
07182 
07183              strtab = get_data (NULL, file, string_sec->sh_offset,
07184                              1, string_sec->sh_size, _("string table"));
07185              strtab_size = strtab != NULL ? string_sec->sh_size : 0;
07186            }
07187 
07188          for (si = 0, psym = symtab;
07189               si < section->sh_size / section->sh_entsize;
07190               si++, psym++)
07191            {
07192              printf ("%6d: ", si);
07193              print_vma (psym->st_value, LONG_HEX);
07194              putchar (' ');
07195              print_vma (psym->st_size, DEC_5);
07196              printf (" %-7s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
07197              printf (" %-6s", get_symbol_binding (ELF_ST_BIND (psym->st_info)));
07198              printf (" %-3s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
07199              /* Check to see if any other bits in the st_other field are set.
07200                 Note - displaying this information disrupts the layout of the
07201                 table being generated, but for the moment this case is very rare.  */
07202              if (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other))
07203               printf (" [%s] ", get_symbol_other (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other)));
07204              printf (" %4s ", get_symbol_index_type (psym->st_shndx));
07205              print_symbol (25, psym->st_name < strtab_size
07206                          ? strtab + psym->st_name : "<corrupt>");
07207 
07208              if (section->sh_type == SHT_DYNSYM &&
07209                 version_info[DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
07210               {
07211                 unsigned char data[2];
07212                 unsigned short vers_data;
07213                 unsigned long offset;
07214                 int is_nobits;
07215                 int check_def;
07216 
07217                 offset = offset_from_vma
07218                   (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
07219                    sizeof data + si * sizeof (vers_data));
07220 
07221                 get_data (&data, file, offset + si * sizeof (vers_data),
07222                          sizeof (data), 1, _("version data"));
07223 
07224                 vers_data = byte_get (data, 2);
07225 
07226                 is_nobits = (SECTION_HEADER_INDEX (psym->st_shndx)
07227                             < elf_header.e_shnum
07228                             && SECTION_HEADER (psym->st_shndx)->sh_type
07229                               == SHT_NOBITS);
07230 
07231                 check_def = (psym->st_shndx != SHN_UNDEF);
07232 
07233                 if ((vers_data & 0x8000) || vers_data > 1)
07234                   {
07235                     if (version_info[DT_VERSIONTAGIDX (DT_VERNEED)]
07236                        && (is_nobits || ! check_def))
07237                      {
07238                        Elf_External_Verneed evn;
07239                        Elf_Internal_Verneed ivn;
07240                        Elf_Internal_Vernaux ivna;
07241 
07242                        /* We must test both.  */
07243                        offset = offset_from_vma
07244                          (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)],
07245                           sizeof evn);
07246 
07247                        do
07248                          {
07249                            unsigned long vna_off;
07250 
07251                            get_data (&evn, file, offset, sizeof (evn), 1,
07252                                    _("version need"));
07253 
07254                            ivn.vn_aux  = BYTE_GET (evn.vn_aux);
07255                            ivn.vn_next = BYTE_GET (evn.vn_next);
07256 
07257                            vna_off = offset + ivn.vn_aux;
07258 
07259                            do
07260                             {
07261                               Elf_External_Vernaux evna;
07262 
07263                               get_data (&evna, file, vna_off,
07264                                        sizeof (evna), 1,
07265                                        _("version need aux (3)"));
07266 
07267                               ivna.vna_other = BYTE_GET (evna.vna_other);
07268                               ivna.vna_next  = BYTE_GET (evna.vna_next);
07269                               ivna.vna_name  = BYTE_GET (evna.vna_name);
07270 
07271                               vna_off += ivna.vna_next;
07272                             }
07273                            while (ivna.vna_other != vers_data
07274                                  && ivna.vna_next != 0);
07275 
07276                            if (ivna.vna_other == vers_data)
07277                             break;
07278 
07279                            offset += ivn.vn_next;
07280                          }
07281                        while (ivn.vn_next != 0);
07282 
07283                        if (ivna.vna_other == vers_data)
07284                          {
07285                            printf ("@%s (%d)",
07286                                   ivna.vna_name < strtab_size
07287                                   ? strtab + ivna.vna_name : "<corrupt>",
07288                                   ivna.vna_other);
07289                            check_def = 0;
07290                          }
07291                        else if (! is_nobits)
07292                          error (_("bad dynamic symbol\n"));
07293                        else
07294                          check_def = 1;
07295                      }
07296 
07297                     if (check_def)
07298                      {
07299                        if (vers_data != 0x8001
07300                            && version_info[DT_VERSIONTAGIDX (DT_VERDEF)])
07301                          {
07302                            Elf_Internal_Verdef ivd;
07303                            Elf_Internal_Verdaux ivda;
07304                            Elf_External_Verdaux evda;
07305                            unsigned long offset;
07306 
07307                            offset = offset_from_vma
07308                             (file,
07309                              version_info[DT_VERSIONTAGIDX (DT_VERDEF)],
07310                              sizeof (Elf_External_Verdef));
07311 
07312                            do
07313                             {
07314                               Elf_External_Verdef evd;
07315 
07316                               get_data (&evd, file, offset, sizeof (evd),
07317                                        1, _("version def"));
07318 
07319                               ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
07320                               ivd.vd_aux = BYTE_GET (evd.vd_aux);
07321                               ivd.vd_next = BYTE_GET (evd.vd_next);
07322 
07323                               offset += ivd.vd_next;
07324                             }
07325                            while (ivd.vd_ndx != (vers_data & 0x7fff)
07326                                  && ivd.vd_next != 0);
07327 
07328                            offset -= ivd.vd_next;
07329                            offset += ivd.vd_aux;
07330 
07331                            get_data (&evda, file, offset, sizeof (evda),
07332                                    1, _("version def aux"));
07333 
07334                            ivda.vda_name = BYTE_GET (evda.vda_name);
07335 
07336                            if (psym->st_name != ivda.vda_name)
07337                             printf ((vers_data & 0x8000)
07338                                    ? "@%s" : "@@%s",
07339                                    ivda.vda_name < strtab_size
07340                                    ? strtab + ivda.vda_name : "<corrupt>");
07341                          }
07342                      }
07343                   }
07344               }
07345 
07346              putchar ('\n');
07347            }
07348 
07349          free (symtab);
07350          if (strtab != string_table)
07351            free (strtab);
07352        }
07353     }
07354   else if (do_syms)
07355     printf
07356       (_("\nDynamic symbol information is not available for displaying symbols.\n"));
07357 
07358   if (do_histogram && buckets != NULL)
07359     {
07360       unsigned long *lengths;
07361       unsigned long *counts;
07362       unsigned long hn;
07363       bfd_vma si;
07364       unsigned long maxlength = 0;
07365       unsigned long nzero_counts = 0;
07366       unsigned long nsyms = 0;
07367 
07368       printf (_("\nHistogram for bucket list length (total of %lu buckets):\n"),
07369              (unsigned long) nbuckets);
07370       printf (_(" Length  Number     %% of total  Coverage\n"));
07371 
07372       lengths = calloc (nbuckets, sizeof (*lengths));
07373       if (lengths == NULL)
07374        {
07375          error (_("Out of memory\n"));
07376          return 0;
07377        }
07378       for (hn = 0; hn < nbuckets; ++hn)
07379        {
07380          for (si = buckets[hn]; si > 0 && si < nchains; si = chains[si])
07381            {
07382              ++nsyms;
07383              if (maxlength < ++lengths[hn])
07384               ++maxlength;
07385            }
07386        }
07387 
07388       counts = calloc (maxlength + 1, sizeof (*counts));
07389       if (counts == NULL)
07390        {
07391          error (_("Out of memory\n"));
07392          return 0;
07393        }
07394 
07395       for (hn = 0; hn < nbuckets; ++hn)
07396        ++counts[lengths[hn]];
07397 
07398       if (nbuckets > 0)
07399        {
07400          unsigned long i;
07401          printf ("      0  %-10lu (%5.1f%%)\n",
07402                 counts[0], (counts[0] * 100.0) / nbuckets);
07403          for (i = 1; i <= maxlength; ++i)
07404            {
07405              nzero_counts += counts[i] * i;
07406              printf ("%7lu  %-10lu (%5.1f%%)    %5.1f%%\n",
07407                     i, counts[i], (counts[i] * 100.0) / nbuckets,
07408                     (nzero_counts * 100.0) / nsyms);
07409            }
07410        }
07411 
07412       free (counts);
07413       free (lengths);
07414     }
07415 
07416   if (buckets != NULL)
07417     {
07418       free (buckets);
07419       free (chains);
07420     }
07421 
07422   if (do_histogram && dynamic_info_DT_GNU_HASH)
07423     {
07424       unsigned char nb[16];
07425       bfd_vma i, maxchain = 0xffffffff, symidx, bitmaskwords;
07426       unsigned long *lengths;
07427       unsigned long *counts;
07428       unsigned long hn;
07429       unsigned long maxlength = 0;
07430       unsigned long nzero_counts = 0;
07431       unsigned long nsyms = 0;
07432       bfd_vma buckets_vma;
07433 
07434       if (fseek (file,
07435                (archive_file_offset
07436                 + offset_from_vma (file, dynamic_info_DT_GNU_HASH,
07437                                  sizeof nb)),
07438                SEEK_SET))
07439        {
07440          error (_("Unable to seek to start of dynamic information\n"));
07441          return 0;
07442        }
07443 
07444       if (fread (nb, 16, 1, file) != 1)
07445        {
07446          error (_("Failed to read in number of buckets\n"));
07447          return 0;
07448        }
07449 
07450       ngnubuckets = byte_get (nb, 4);
07451       symidx = byte_get (nb + 4, 4);
07452       bitmaskwords = byte_get (nb + 8, 4);
07453       buckets_vma = dynamic_info_DT_GNU_HASH + 16;
07454       if (is_32bit_elf)
07455        buckets_vma += bitmaskwords * 4;
07456       else
07457        buckets_vma += bitmaskwords * 8;
07458 
07459       if (fseek (file,
07460                (archive_file_offset
07461                 + offset_from_vma (file, buckets_vma, 4)),
07462                SEEK_SET))
07463        {
07464          error (_("Unable to seek to start of dynamic information\n"));
07465          return 0;
07466        }
07467 
07468       gnubuckets = get_dynamic_data (file, ngnubuckets, 4);
07469 
07470       if (gnubuckets == NULL)
07471        return 0;
07472 
07473       for (i = 0; i < ngnubuckets; i++)
07474        if (gnubuckets[i] != 0)
07475          {
07476            if (gnubuckets[i] < symidx)
07477              return 0;
07478 
07479            if (maxchain == 0xffffffff || gnubuckets[i] > maxchain)
07480              maxchain = gnubuckets[i];
07481          }
07482 
07483       if (maxchain == 0xffffffff)
07484        return 0;
07485 
07486       maxchain -= symidx;
07487 
07488       if (fseek (file,
07489                (archive_file_offset
07490                 + offset_from_vma (file, buckets_vma
07491                                       + 4 * (ngnubuckets + maxchain), 4)),
07492                SEEK_SET))
07493        {
07494          error (_("Unable to seek to start of dynamic information\n"));
07495          return 0;
07496        }
07497 
07498       do
07499        {
07500          if (fread (nb, 4, 1, file) != 1)
07501            {
07502              error (_("Failed to determine last chain length\n"));
07503              return 0;
07504            }
07505 
07506          if (maxchain + 1 == 0)
07507            return 0;
07508 
07509          ++maxchain;
07510        }
07511       while ((byte_get (nb, 4) & 1) == 0);
07512 
07513       if (fseek (file,
07514                (archive_file_offset
07515                 + offset_from_vma (file, buckets_vma + 4 * ngnubuckets, 4)),
07516                SEEK_SET))
07517        {
07518          error (_("Unable to seek to start of dynamic information\n"));
07519          return 0;
07520        }
07521 
07522       gnuchains = get_dynamic_data (file, maxchain, 4);
07523 
07524       if (gnuchains == NULL)
07525        return 0;
07526 
07527       lengths = calloc (ngnubuckets, sizeof (*lengths));
07528       if (lengths == NULL)
07529        {
07530          error (_("Out of memory\n"));
07531          return 0;
07532        }
07533 
07534       printf (_("\nHistogram for `.gnu.hash' bucket list length (total of %lu buckets):\n"),
07535              (unsigned long) ngnubuckets);
07536       printf (_(" Length  Number     %% of total  Coverage\n"));
07537 
07538       for (hn = 0; hn < ngnubuckets; ++hn)
07539        if (gnubuckets[hn] != 0)
07540          {
07541            bfd_vma off, length = 1;
07542 
07543            for (off = gnubuckets[hn] - symidx;
07544                (gnuchains[off] & 1) == 0; ++off)
07545              ++length;
07546            lengths[hn] = length;
07547            if (length > maxlength)
07548              maxlength = length;
07549            nsyms += length;
07550          }
07551 
07552       counts = calloc (maxlength + 1, sizeof (*counts));
07553       if (counts == NULL)
07554        {
07555          error (_("Out of memory\n"));
07556          return 0;
07557        }
07558 
07559       for (hn = 0; hn < ngnubuckets; ++hn)
07560        ++counts[lengths[hn]];
07561 
07562       if (ngnubuckets > 0)
07563        {
07564          unsigned long j;
07565          printf ("      0  %-10lu (%5.1f%%)\n",
07566                 counts[0], (counts[0] * 100.0) / ngnubuckets);
07567          for (j = 1; j <= maxlength; ++j)
07568            {
07569              nzero_counts += counts[j] * j;
07570              printf ("%7lu  %-10lu (%5.1f%%)    %5.1f%%\n",
07571                     j, counts[j], (counts[j] * 100.0) / ngnubuckets,
07572                     (nzero_counts * 100.0) / nsyms);
07573            }
07574        }
07575 
07576       free (counts);
07577       free (lengths);
07578       free (gnubuckets);
07579       free (gnuchains);
07580     }
07581 
07582   return 1;
07583 }
07584 
07585 static int
07586 process_syminfo (FILE *file ATTRIBUTE_UNUSED)
07587 {
07588   unsigned int i;
07589 
07590   if (dynamic_syminfo == NULL
07591       || !do_dynamic)
07592     /* No syminfo, this is ok.  */
07593     return 1;
07594 
07595   /* There better should be a dynamic symbol section.  */
07596   if (dynamic_symbols == NULL || dynamic_strings == NULL)
07597     return 0;
07598 
07599   if (dynamic_addr)
07600     printf (_("\nDynamic info segment at offset 0x%lx contains %d entries:\n"),
07601            dynamic_syminfo_offset, dynamic_syminfo_nent);
07602 
07603   printf (_(" Num: Name                           BoundTo     Flags\n"));
07604   for (i = 0; i < dynamic_syminfo_nent; ++i)
07605     {
07606       unsigned short int flags = dynamic_syminfo[i].si_flags;
07607 
07608       printf ("%4d: ", i);
07609       if (VALID_DYNAMIC_NAME (dynamic_symbols[i].st_name))
07610        print_symbol (30, GET_DYNAMIC_NAME (dynamic_symbols[i].st_name));
07611       else
07612        printf ("<corrupt: %19ld>", dynamic_symbols[i].st_name);
07613       putchar (' ');
07614 
07615       switch (dynamic_syminfo[i].si_boundto)
07616        {
07617        case SYMINFO_BT_SELF:
07618          fputs ("SELF       ", stdout);
07619          break;
07620        case SYMINFO_BT_PARENT:
07621          fputs ("PARENT     ", stdout);
07622          break;
07623        default:
07624          if (dynamic_syminfo[i].si_boundto > 0
07625              && dynamic_syminfo[i].si_boundto < dynamic_nent
07626              && VALID_DYNAMIC_NAME (dynamic_section[dynamic_syminfo[i].si_boundto].d_un.d_val))
07627            {
07628              print_symbol (10, GET_DYNAMIC_NAME (dynamic_section[dynamic_syminfo[i].si_boundto].d_un.d_val));
07629              putchar (' ' );
07630            }
07631          else
07632            printf ("%-10d ", dynamic_syminfo[i].si_boundto);
07633          break;
07634        }
07635 
07636       if (flags &