| /* readelf.c -- display contents of an ELF format file |
| Copyright (C) 1998-2016 Free Software Foundation, Inc. |
| |
| Originally developed by Eric Youngdale <eric@andante.jic.com> |
| Modifications by Nick Clifton <nickc@redhat.com> |
| |
| This file is part of GNU Binutils. |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA |
| 02110-1301, USA. */ |
| |
| /* The difference between readelf and objdump: |
| |
| Both programs are capable of displaying the contents of ELF format files, |
| so why does the binutils project have two file dumpers ? |
| |
| The reason is that objdump sees an ELF file through a BFD filter of the |
| world; if BFD has a bug where, say, it disagrees about a machine constant |
| in e_flags, then the odds are good that it will remain internally |
| consistent. The linker sees it the BFD way, objdump sees it the BFD way, |
| GAS sees it the BFD way. There was need for a tool to go find out what |
| the file actually says. |
| |
| This is why the readelf program does not link against the BFD library - it |
| exists as an independent program to help verify the correct working of BFD. |
| |
| There is also the case that readelf can provide more information about an |
| ELF file than is provided by objdump. In particular it can display DWARF |
| debugging information which (at the moment) objdump cannot. */ |
| |
| #include "sysdep.h" |
| #include <assert.h> |
| #include <time.h> |
| #include <zlib.h> |
| #ifdef HAVE_WCHAR_H |
| #include <wchar.h> |
| #endif |
| |
| #if __GNUC__ >= 2 |
| /* Define BFD64 here, even if our default architecture is 32 bit ELF |
| as this will allow us to read in and parse 64bit and 32bit ELF files. |
| Only do this if we believe that the compiler can support a 64 bit |
| data type. For now we only rely on GCC being able to do this. */ |
| #define BFD64 |
| #endif |
| |
| #include "bfd.h" |
| #include "bucomm.h" |
| #include "elfcomm.h" |
| #include "dwarf.h" |
| |
| #include "elf/common.h" |
| #include "elf/external.h" |
| #include "elf/internal.h" |
| |
| |
| /* Included here, before RELOC_MACROS_GEN_FUNC is defined, so that |
| we can obtain the H8 reloc numbers. We need these for the |
| get_reloc_size() function. We include h8.h again after defining |
| RELOC_MACROS_GEN_FUNC so that we get the naming function as well. */ |
| |
| #include "elf/h8.h" |
| #undef _ELF_H8_H |
| |
| /* Undo the effects of #including reloc-macros.h. */ |
| |
| #undef START_RELOC_NUMBERS |
| #undef RELOC_NUMBER |
| #undef FAKE_RELOC |
| #undef EMPTY_RELOC |
| #undef END_RELOC_NUMBERS |
| #undef _RELOC_MACROS_H |
| |
| /* The following headers use the elf/reloc-macros.h file to |
| automatically generate relocation recognition functions |
| such as elf_mips_reloc_type() */ |
| |
| #define RELOC_MACROS_GEN_FUNC |
| |
| #include "elf/aarch64.h" |
| #include "elf/alpha.h" |
| #include "elf/arc.h" |
| #include "elf/arm.h" |
| #include "elf/avr.h" |
| #include "elf/bfin.h" |
| #include "elf/cr16.h" |
| #include "elf/cris.h" |
| #include "elf/crx.h" |
| #include "elf/d10v.h" |
| #include "elf/d30v.h" |
| #include "elf/dlx.h" |
| #include "elf/epiphany.h" |
| #include "elf/fr30.h" |
| #include "elf/frv.h" |
| #include "elf/ft32.h" |
| #include "elf/h8.h" |
| #include "elf/hppa.h" |
| #include "elf/i386.h" |
| #include "elf/i370.h" |
| #include "elf/i860.h" |
| #include "elf/i960.h" |
| #include "elf/ia64.h" |
| #include "elf/ip2k.h" |
| #include "elf/lm32.h" |
| #include "elf/iq2000.h" |
| #include "elf/m32c.h" |
| #include "elf/m32r.h" |
| #include "elf/m68k.h" |
| #include "elf/m68hc11.h" |
| #include "elf/mcore.h" |
| #include "elf/mep.h" |
| #include "elf/metag.h" |
| #include "elf/microblaze.h" |
| #include "elf/mips.h" |
| #include "elf/riscv.h" |
| #include "elf/mmix.h" |
| #include "elf/mn10200.h" |
| #include "elf/mn10300.h" |
| #include "elf/moxie.h" |
| #include "elf/mt.h" |
| #include "elf/msp430.h" |
| #include "elf/nds32.h" |
| #include "elf/nios2.h" |
| #include "elf/or1k.h" |
| #include "elf/pj.h" |
| #include "elf/ppc.h" |
| #include "elf/ppc64.h" |
| #include "elf/rl78.h" |
| #include "elf/rx.h" |
| #include "elf/s390.h" |
| #include "elf/score.h" |
| #include "elf/sh.h" |
| #include "elf/sparc.h" |
| #include "elf/spu.h" |
| #include "elf/tic6x.h" |
| #include "elf/tilegx.h" |
| #include "elf/tilepro.h" |
| #include "elf/v850.h" |
| #include "elf/vax.h" |
| #include "elf/visium.h" |
| #include "elf/x86-64.h" |
| #include "elf/xc16x.h" |
| #include "elf/xgate.h" |
| #include "elf/xstormy16.h" |
| #include "elf/xtensa.h" |
| |
| #include "getopt.h" |
| #include "libiberty.h" |
| #include "safe-ctype.h" |
| #include "filenames.h" |
| |
| #ifndef offsetof |
| #define offsetof(TYPE, MEMBER) ((size_t) &(((TYPE *) 0)->MEMBER)) |
| #endif |
| |
| typedef struct elf_section_list |
| { |
| Elf_Internal_Shdr * hdr; |
| struct elf_section_list * next; |
| } elf_section_list; |
| |
| char * program_name = "readelf"; |
| static unsigned long archive_file_offset; |
| static unsigned long archive_file_size; |
| static bfd_size_type current_file_size; |
| static unsigned long dynamic_addr; |
| static bfd_size_type dynamic_size; |
| static size_t dynamic_nent; |
| static char * dynamic_strings; |
| static unsigned long dynamic_strings_length; |
| static char * string_table; |
| static unsigned long string_table_length; |
| static unsigned long num_dynamic_syms; |
| static Elf_Internal_Sym * dynamic_symbols; |
| static Elf_Internal_Syminfo * dynamic_syminfo; |
| static unsigned long dynamic_syminfo_offset; |
| static unsigned int dynamic_syminfo_nent; |
| static char program_interpreter[PATH_MAX]; |
| static bfd_vma dynamic_info[DT_ENCODING]; |
| static bfd_vma dynamic_info_DT_GNU_HASH; |
| static bfd_vma version_info[16]; |
| static Elf_Internal_Ehdr elf_header; |
| static Elf_Internal_Shdr * section_headers; |
| static Elf_Internal_Phdr * program_headers; |
| static Elf_Internal_Dyn * dynamic_section; |
| static elf_section_list * symtab_shndx_list; |
| static int show_name; |
| static int do_dynamic; |
| static int do_syms; |
| static int do_dyn_syms; |
| static int do_reloc; |
| static int do_sections; |
| static int do_section_groups; |
| static int do_section_details; |
| static int do_segments; |
| static int do_unwind; |
| static int do_using_dynamic; |
| static int do_header; |
| static int do_dump; |
| static int do_version; |
| static int do_histogram; |
| static int do_debugging; |
| static int do_arch; |
| static int do_notes; |
| static int do_archive_index; |
| static int is_32bit_elf; |
| static int decompress_dumps; |
| |
| struct group_list |
| { |
| struct group_list * next; |
| unsigned int section_index; |
| }; |
| |
| struct group |
| { |
| struct group_list * root; |
| unsigned int group_index; |
| }; |
| |
| static size_t group_count; |
| static struct group * section_groups; |
| static struct group ** section_headers_groups; |
| |
| |
| /* Flag bits indicating particular types of dump. */ |
| #define HEX_DUMP (1 << 0) /* The -x command line switch. */ |
| #define DISASS_DUMP (1 << 1) /* The -i command line switch. */ |
| #define DEBUG_DUMP (1 << 2) /* The -w command line switch. */ |
| #define STRING_DUMP (1 << 3) /* The -p command line switch. */ |
| #define RELOC_DUMP (1 << 4) /* The -R command line switch. */ |
| |
| typedef unsigned char dump_type; |
| |
| /* A linked list of the section names for which dumps were requested. */ |
| struct dump_list_entry |
| { |
| char * name; |
| dump_type type; |
| struct dump_list_entry * next; |
| }; |
| static struct dump_list_entry * dump_sects_byname; |
| |
| /* A dynamic array of flags indicating for which sections a dump |
| has been requested via command line switches. */ |
| static dump_type * cmdline_dump_sects = NULL; |
| static unsigned int num_cmdline_dump_sects = 0; |
| |
| /* A dynamic array of flags indicating for which sections a dump of |
| some kind has been requested. It is reset on a per-object file |
| basis and then initialised from the cmdline_dump_sects array, |
| the results of interpreting the -w switch, and the |
| dump_sects_byname list. */ |
| static dump_type * dump_sects = NULL; |
| static unsigned int num_dump_sects = 0; |
| |
| |
| /* How to print a vma value. */ |
| typedef enum print_mode |
| { |
| HEX, |
| DEC, |
| DEC_5, |
| UNSIGNED, |
| PREFIX_HEX, |
| FULL_HEX, |
| LONG_HEX |
| } |
| print_mode; |
| |
| /* Versioned symbol info. */ |
| enum versioned_symbol_info |
| { |
| symbol_undefined, |
| symbol_hidden, |
| symbol_public |
| }; |
| |
| static const char *get_symbol_version_string |
| (FILE *file, int is_dynsym, const char *strtab, |
| unsigned long int strtab_size, unsigned int si, |
| Elf_Internal_Sym *psym, enum versioned_symbol_info *sym_info, |
| unsigned short *vna_other); |
| |
| #define UNKNOWN -1 |
| |
| #define SECTION_NAME(X) \ |
| ((X) == NULL ? _("<none>") \ |
| : string_table == NULL ? _("<no-name>") \ |
| : ((X)->sh_name >= string_table_length ? _("<corrupt>") \ |
| : string_table + (X)->sh_name)) |
| |
| #define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ |
| |
| #define GET_ELF_SYMBOLS(file, section, sym_count) \ |
| (is_32bit_elf ? get_32bit_elf_symbols (file, section, sym_count) \ |
| : get_64bit_elf_symbols (file, section, sym_count)) |
| |
| #define VALID_DYNAMIC_NAME(offset) ((dynamic_strings != NULL) && (offset < dynamic_strings_length)) |
| /* GET_DYNAMIC_NAME asssumes that VALID_DYNAMIC_NAME has |
| already been called and verified that the string exists. */ |
| #define GET_DYNAMIC_NAME(offset) (dynamic_strings + offset) |
| |
| #define REMOVE_ARCH_BITS(ADDR) \ |
| do \ |
| { \ |
| if (elf_header.e_machine == EM_ARM) \ |
| (ADDR) &= ~1; \ |
| } \ |
| while (0) |
| |
| /* Retrieve NMEMB structures, each SIZE bytes long from FILE starting at OFFSET + |
| the offset of the current archive member, if we are examining an archive. |
| Put the retrieved data into VAR, if it is not NULL. Otherwise allocate a buffer |
| using malloc and fill that. In either case return the pointer to the start of |
| the retrieved data or NULL if something went wrong. If something does go wrong |
| and REASON is not NULL then emit an error message using REASON as part of the |
| context. */ |
| |
| static void * |
| get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size, |
| bfd_size_type nmemb, const char * reason) |
| { |
| void * mvar; |
| bfd_size_type amt = size * nmemb; |
| |
| if (size == 0 || nmemb == 0) |
| return NULL; |
| |
| /* If the size_t type is smaller than the bfd_size_type, eg because |
| you are building a 32-bit tool on a 64-bit host, then make sure |
| that when the sizes are cast to (size_t) no information is lost. */ |
| if (sizeof (size_t) < sizeof (bfd_size_type) |
| && ( (bfd_size_type) ((size_t) size) != size |
| || (bfd_size_type) ((size_t) nmemb) != nmemb)) |
| { |
| if (reason) |
| error (_("Size truncation prevents reading 0x%" BFD_VMA_FMT "x" |
| " elements of size 0x%" BFD_VMA_FMT "x for %s\n"), |
| nmemb, size, reason); |
| return NULL; |
| } |
| |
| /* Check for size overflow. */ |
| if (amt < nmemb) |
| { |
| if (reason) |
| error (_("Size overflow prevents reading 0x%" BFD_VMA_FMT "x" |
| " elements of size 0x%" BFD_VMA_FMT "x for %s\n"), |
| nmemb, size, reason); |
| return NULL; |
| } |
| |
| /* Be kind to memory chekers (eg valgrind, address sanitizer) by not |
| attempting to allocate memory when the read is bound to fail. */ |
| if (amt > current_file_size |
| || offset + archive_file_offset + amt > current_file_size) |
| { |
| if (reason) |
| error (_("Reading 0x%" BFD_VMA_FMT "x" |
| " bytes extends past end of file for %s\n"), |
| amt, reason); |
| return NULL; |
| } |
| |
| if (fseek (file, archive_file_offset + offset, SEEK_SET)) |
| { |
| if (reason) |
| error (_("Unable to seek to 0x%lx for %s\n"), |
| archive_file_offset + offset, reason); |
| return NULL; |
| } |
| |
| mvar = var; |
| if (mvar == NULL) |
| { |
| /* Check for overflow. */ |
| if (nmemb < (~(bfd_size_type) 0 - 1) / size) |
| /* + 1 so that we can '\0' terminate invalid string table sections. */ |
| mvar = malloc ((size_t) amt + 1); |
| |
| if (mvar == NULL) |
| { |
| if (reason) |
| error (_("Out of memory allocating 0x%" BFD_VMA_FMT "x" |
| " bytes for %s\n"), |
| amt, reason); |
| return NULL; |
| } |
| |
| ((char *) mvar)[amt] = '\0'; |
| } |
| |
| if (fread (mvar, (size_t) size, (size_t) nmemb, file) != nmemb) |
| { |
| if (reason) |
| error (_("Unable to read in 0x%" BFD_VMA_FMT "x bytes of %s\n"), |
| amt, reason); |
| if (mvar != var) |
| free (mvar); |
| return NULL; |
| } |
| |
| return mvar; |
| } |
| |
| /* Print a VMA value. */ |
| |
| static int |
| print_vma (bfd_vma vma, print_mode mode) |
| { |
| int nc = 0; |
| |
| switch (mode) |
| { |
| case FULL_HEX: |
| nc = printf ("0x"); |
| /* Fall through. */ |
| |
| case LONG_HEX: |
| #ifdef BFD64 |
| if (is_32bit_elf) |
| return nc + printf ("%8.8" BFD_VMA_FMT "x", vma); |
| #endif |
| printf_vma (vma); |
| return nc + 16; |
| |
| case DEC_5: |
| if (vma <= 99999) |
| return printf ("%5" BFD_VMA_FMT "d", vma); |
| /* Fall through. */ |
| |
| case PREFIX_HEX: |
| nc = printf ("0x"); |
| /* Fall through. */ |
| |
| case HEX: |
| return nc + printf ("%" BFD_VMA_FMT "x", vma); |
| |
| case DEC: |
| return printf ("%" BFD_VMA_FMT "d", vma); |
| |
| case UNSIGNED: |
| return printf ("%" BFD_VMA_FMT "u", vma); |
| } |
| return 0; |
| } |
| |
| /* Display a symbol on stdout. Handles the display of control characters and |
| multibye characters (assuming the host environment supports them). |
| |
| Display at most abs(WIDTH) characters, truncating as necessary, unless do_wide is true. |
| |
| If WIDTH is negative then ensure that the output is at least (- WIDTH) characters, |
| padding as necessary. |
| |
| Returns the number of emitted characters. */ |
| |
| static unsigned int |
| print_symbol (int width, const char *symbol) |
| { |
| bfd_boolean extra_padding = FALSE; |
| int num_printed = 0; |
| #ifdef HAVE_MBSTATE_T |
| mbstate_t state; |
| #endif |
| int width_remaining; |
| |
| if (width < 0) |
| { |
| /* Keep the width positive. This also helps. */ |
| width = - width; |
| extra_padding = TRUE; |
| } |
| assert (width != 0); |
| |
| if (do_wide) |
| /* Set the remaining width to a very large value. |
| This simplifies the code below. */ |
| width_remaining = INT_MAX; |
| else |
| width_remaining = width; |
| |
| #ifdef HAVE_MBSTATE_T |
| /* Initialise the multibyte conversion state. */ |
| memset (& state, 0, sizeof (state)); |
| #endif |
| |
| while (width_remaining) |
| { |
| size_t n; |
| const char c = *symbol++; |
| |
| if (c == 0) |
| break; |
| |
| /* Do not print control characters directly as they can affect terminal |
| settings. Such characters usually appear in the names generated |
| by the assembler for local labels. */ |
| if (ISCNTRL (c)) |
| { |
| if (width_remaining < 2) |
| break; |
| |
| printf ("^%c", c + 0x40); |
| width_remaining -= 2; |
| num_printed += 2; |
| } |
| else if (ISPRINT (c)) |
| { |
| putchar (c); |
| width_remaining --; |
| num_printed ++; |
| } |
| else |
| { |
| #ifdef HAVE_MBSTATE_T |
| wchar_t w; |
| #endif |
| /* Let printf do the hard work of displaying multibyte characters. */ |
| printf ("%.1s", symbol - 1); |
| width_remaining --; |
| num_printed ++; |
| |
| #ifdef HAVE_MBSTATE_T |
| /* Try to find out how many bytes made up the character that was |
| just printed. Advance the symbol pointer past the bytes that |
| were displayed. */ |
| n = mbrtowc (& w, symbol - 1, MB_CUR_MAX, & state); |
| #else |
| n = 1; |
| #endif |
| if (n != (size_t) -1 && n != (size_t) -2 && n > 0) |
| symbol += (n - 1); |
| } |
| } |
| |
| if (extra_padding && num_printed < width) |
| { |
| /* Fill in the remaining spaces. */ |
| printf ("%-*s", width - num_printed, " "); |
| num_printed = width; |
| } |
| |
| return num_printed; |
| } |
| |
| /* Returns a pointer to a static buffer containing a printable version of |
| the given section's name. Like print_symbol, except that it does not try |
| to print multibyte characters, it just interprets them as hex values. */ |
| |
| static const char * |
| printable_section_name (const Elf_Internal_Shdr * sec) |
| { |
| #define MAX_PRINT_SEC_NAME_LEN 128 |
| static char sec_name_buf [MAX_PRINT_SEC_NAME_LEN + 1]; |
| const char * name = SECTION_NAME (sec); |
| char * buf = sec_name_buf; |
| char c; |
| unsigned int remaining = MAX_PRINT_SEC_NAME_LEN; |
| |
| while ((c = * name ++) != 0) |
| { |
| if (ISCNTRL (c)) |
| { |
| if (remaining < 2) |
| break; |
| |
| * buf ++ = '^'; |
| * buf ++ = c + 0x40; |
| remaining -= 2; |
| } |
| else if (ISPRINT (c)) |
| { |
| * buf ++ = c; |
| remaining -= 1; |
| } |
| else |
| { |
| static char hex[17] = "0123456789ABCDEF"; |
| |
| if (remaining < 4) |
| break; |
| * buf ++ = '<'; |
| * buf ++ = hex[(c & 0xf0) >> 4]; |
| * buf ++ = hex[c & 0x0f]; |
| * buf ++ = '>'; |
| remaining -= 4; |
| } |
| |
| if (remaining == 0) |
| break; |
| } |
| |
| * buf = 0; |
| return sec_name_buf; |
| } |
| |
| static const char * |
| printable_section_name_from_index (unsigned long ndx) |
| { |
| if (ndx >= elf_header.e_shnum) |
| return _("<corrupt>"); |
| |
| return printable_section_name (section_headers + ndx); |
| } |
| |
| /* Return a pointer to section NAME, or NULL if no such section exists. */ |
| |
| static Elf_Internal_Shdr * |
| find_section (const char * name) |
| { |
| unsigned int i; |
| |
| for (i = 0; i < elf_header.e_shnum; i++) |
| if (streq (SECTION_NAME (section_headers + i), name)) |
| return section_headers + i; |
| |
| return NULL; |
| } |
| |
| /* Return a pointer to a section containing ADDR, or NULL if no such |
| section exists. */ |
| |
| static Elf_Internal_Shdr * |
| find_section_by_address (bfd_vma addr) |
| { |
| unsigned int i; |
| |
| for (i = 0; i < elf_header.e_shnum; i++) |
| { |
| Elf_Internal_Shdr *sec = section_headers + i; |
| if (addr >= sec->sh_addr && addr < sec->sh_addr + sec->sh_size) |
| return sec; |
| } |
| |
| return NULL; |
| } |
| |
| static Elf_Internal_Shdr * |
| find_section_by_type (unsigned int type) |
| { |
| unsigned int i; |
| |
| for (i = 0; i < elf_header.e_shnum; i++) |
| { |
| Elf_Internal_Shdr *sec = section_headers + i; |
| if (sec->sh_type == type) |
| return sec; |
| } |
| |
| return NULL; |
| } |
| |
| /* Return a pointer to section NAME, or NULL if no such section exists, |
| restricted to the list of sections given in SET. */ |
| |
| static Elf_Internal_Shdr * |
| find_section_in_set (const char * name, unsigned int * set) |
| { |
| unsigned int i; |
| |
| if (set != NULL) |
| { |
| while ((i = *set++) > 0) |
| if (streq (SECTION_NAME (section_headers + i), name)) |
| return section_headers + i; |
| } |
| |
| return find_section (name); |
| } |
| |
| /* Read an unsigned LEB128 encoded value from p. Set *PLEN to the number of |
| bytes read. */ |
| |
| static inline unsigned long |
| read_uleb128 (unsigned char *data, |
| unsigned int *length_return, |
| const unsigned char * const end) |
| { |
| return read_leb128 (data, length_return, FALSE, end); |
| } |
| |
| /* Return true if the current file is for IA-64 machine and OpenVMS ABI. |
| This OS has so many departures from the ELF standard that we test it at |
| many places. */ |
| |
| static inline int |
| is_ia64_vms (void) |
| { |
| return elf_header.e_machine == EM_IA_64 |
| && elf_header.e_ident[EI_OSABI] == ELFOSABI_OPENVMS; |
| } |
| |
| /* Guess the relocation size commonly used by the specific machines. */ |
| |
| static int |
| guess_is_rela (unsigned int e_machine) |
| { |
| switch (e_machine) |
| { |
| /* Targets that use REL relocations. */ |
| case EM_386: |
| case EM_IAMCU: |
| case EM_960: |
| case EM_ARM: |
| case EM_D10V: |
| case EM_CYGNUS_D10V: |
| case EM_DLX: |
| case EM_MIPS: |
| case EM_MIPS_RS3_LE: |
| case EM_CYGNUS_M32R: |
| case EM_SCORE: |
| case EM_XGATE: |
| return FALSE; |
| |
| /* Targets that use RELA relocations. */ |
| case EM_68K: |
| case EM_860: |
| case EM_AARCH64: |
| case EM_ADAPTEVA_EPIPHANY: |
| case EM_ALPHA: |
| case EM_ALTERA_NIOS2: |
| case EM_ARC: |
| case EM_ARC_COMPACT: |
| case EM_ARC_COMPACT2: |
| case EM_AVR: |
| case EM_AVR_OLD: |
| case EM_BLACKFIN: |
| case EM_CR16: |
| case EM_CRIS: |
| case EM_CRX: |
| case EM_D30V: |
| case EM_CYGNUS_D30V: |
| case EM_FR30: |
| case EM_FT32: |
| case EM_CYGNUS_FR30: |
| case EM_CYGNUS_FRV: |
| case EM_H8S: |
| case EM_H8_300: |
| case EM_H8_300H: |
| case EM_IA_64: |
| case EM_IP2K: |
| case EM_IP2K_OLD: |
| case EM_IQ2000: |
| case EM_LATTICEMICO32: |
| case EM_M32C_OLD: |
| case EM_M32C: |
| case EM_M32R: |
| case EM_MCORE: |
| case EM_CYGNUS_MEP: |
| case EM_METAG: |
| case EM_MMIX: |
| case EM_MN10200: |
| case EM_CYGNUS_MN10200: |
| case EM_MN10300: |
| case EM_CYGNUS_MN10300: |
| case EM_MOXIE: |
| case EM_MSP430: |
| case EM_MSP430_OLD: |
| case EM_MT: |
| case EM_NDS32: |
| case EM_NIOS32: |
| case EM_OR1K: |
| case EM_PPC64: |
| case EM_PPC: |
| case EM_RISCV: |
| case EM_RL78: |
| case EM_RX: |
| case EM_S390: |
| case EM_S390_OLD: |
| case EM_SH: |
| case EM_SPARC: |
| case EM_SPARC32PLUS: |
| case EM_SPARCV9: |
| case EM_SPU: |
| case EM_TI_C6000: |
| case EM_TILEGX: |
| case EM_TILEPRO: |
| case EM_V800: |
| case EM_V850: |
| case EM_CYGNUS_V850: |
| case EM_VAX: |
| case EM_VISIUM: |
| case EM_X86_64: |
| case EM_L1OM: |
| case EM_K1OM: |
| case EM_XSTORMY16: |
| case EM_XTENSA: |
| case EM_XTENSA_OLD: |
| case EM_MICROBLAZE: |
| case EM_MICROBLAZE_OLD: |
| return TRUE; |
| |
| case EM_68HC05: |
| case EM_68HC08: |
| case EM_68HC11: |
| case EM_68HC16: |
| case EM_FX66: |
| case EM_ME16: |
| case EM_MMA: |
| case EM_NCPU: |
| case EM_NDR1: |
| case EM_PCP: |
| case EM_ST100: |
| case EM_ST19: |
| case EM_ST7: |
| case EM_ST9PLUS: |
| case EM_STARCORE: |
| case EM_SVX: |
| case EM_TINYJ: |
| default: |
| warn (_("Don't know about relocations on this machine architecture\n")); |
| return FALSE; |
| } |
| } |
| |
| static int |
| slurp_rela_relocs (FILE * file, |
| unsigned long rel_offset, |
| unsigned long rel_size, |
| Elf_Internal_Rela ** relasp, |
| unsigned long * nrelasp) |
| { |
| Elf_Internal_Rela * relas; |
| size_t nrelas; |
| unsigned int i; |
| |
| if (is_32bit_elf) |
| { |
| Elf32_External_Rela * erelas; |
| |
| erelas = (Elf32_External_Rela *) get_data (NULL, file, rel_offset, 1, |
| rel_size, _("32-bit relocation data")); |
| if (!erelas) |
| return 0; |
| |
| nrelas = rel_size / sizeof (Elf32_External_Rela); |
| |
| relas = (Elf_Internal_Rela *) cmalloc (nrelas, |
| sizeof (Elf_Internal_Rela)); |
| |
| if (relas == NULL) |
| { |
| free (erelas); |
| error (_("out of memory parsing relocs\n")); |
| return 0; |
| } |
| |
| for (i = 0; i < nrelas; i++) |
| { |
| relas[i].r_offset = BYTE_GET (erelas[i].r_offset); |
| relas[i].r_info = BYTE_GET (erelas[i].r_info); |
| relas[i].r_addend = BYTE_GET_SIGNED (erelas[i].r_addend); |
| } |
| |
| free (erelas); |
| } |
| else |
| { |
| Elf64_External_Rela * erelas; |
| |
| erelas = (Elf64_External_Rela *) get_data (NULL, file, rel_offset, 1, |
| rel_size, _("64-bit relocation data")); |
| if (!erelas) |
| return 0; |
| |
| nrelas = rel_size / sizeof (Elf64_External_Rela); |
| |
| relas = (Elf_Internal_Rela *) cmalloc (nrelas, |
| sizeof (Elf_Internal_Rela)); |
| |
| if (relas == NULL) |
| { |
| free (erelas); |
| error (_("out of memory parsing relocs\n")); |
| return 0; |
| } |
| |
| for (i = 0; i < nrelas; i++) |
| { |
| relas[i].r_offset = BYTE_GET (erelas[i].r_offset); |
| relas[i].r_info = BYTE_GET (erelas[i].r_info); |
| relas[i].r_addend = BYTE_GET_SIGNED (erelas[i].r_addend); |
| |
| /* The #ifdef BFD64 below is to prevent a compile time |
| warning. We know that if we do not have a 64 bit data |
| type that we will never execute this code anyway. */ |
| #ifdef BFD64 |
| if (elf_header.e_machine == EM_MIPS |
| && elf_header.e_ident[EI_DATA] != ELFDATA2MSB) |
| { |
| /* In little-endian objects, r_info isn't really a |
| 64-bit little-endian value: it has a 32-bit |
| little-endian symbol index followed by four |
| individual byte fields. Reorder INFO |
| accordingly. */ |
| bfd_vma inf = relas[i].r_info; |
| inf = (((inf & 0xffffffff) << 32) |
| | ((inf >> 56) & 0xff) |
| | ((inf >> 40) & 0xff00) |
| | ((inf >> 24) & 0xff0000) |
| | ((inf >> 8) & 0xff000000)); |
| relas[i].r_info = inf; |
| } |
| #endif /* BFD64 */ |
| } |
| |
| free (erelas); |
| } |
| *relasp = relas; |
| *nrelasp = nrelas; |
| return 1; |
| } |
| |
| static int |
| slurp_rel_relocs (FILE * file, |
| unsigned long rel_offset, |
| unsigned long rel_size, |
| Elf_Internal_Rela ** relsp, |
| unsigned long * nrelsp) |
| { |
| Elf_Internal_Rela * rels; |
| size_t nrels; |
| unsigned int i; |
| |
| if (is_32bit_elf) |
| { |
| Elf32_External_Rel * erels; |
| |
| erels = (Elf32_External_Rel *) get_data (NULL, file, rel_offset, 1, |
| rel_size, _("32-bit relocation data")); |
| if (!erels) |
| return 0; |
| |
| nrels = rel_size / sizeof (Elf32_External_Rel); |
| |
| rels = (Elf_Internal_Rela *) cmalloc (nrels, sizeof (Elf_Internal_Rela)); |
| |
| if (rels == NULL) |
| { |
| free (erels); |
| error (_("out of memory parsing relocs\n")); |
| return 0; |
| } |
| |
| for (i = 0; i < nrels; i++) |
| { |
| rels[i].r_offset = BYTE_GET (erels[i].r_offset); |
| rels[i].r_info = BYTE_GET (erels[i].r_info); |
| rels[i].r_addend = 0; |
| } |
| |
| free (erels); |
| } |
| else |
| { |
| Elf64_External_Rel * erels; |
| |
| erels = (Elf64_External_Rel *) get_data (NULL, file, rel_offset, 1, |
| rel_size, _("64-bit relocation data")); |
| if (!erels) |
| return 0; |
| |
| nrels = rel_size / sizeof (Elf64_External_Rel); |
| |
| rels = (Elf_Internal_Rela *) cmalloc (nrels, sizeof (Elf_Internal_Rela)); |
| |
| if (rels == NULL) |
| { |
| free (erels); |
| error (_("out of memory parsing relocs\n")); |
| return 0; |
| } |
| |
| for (i = 0; i < nrels; i++) |
| { |
| rels[i].r_offset = BYTE_GET (erels[i].r_offset); |
| rels[i].r_info = BYTE_GET (erels[i].r_info); |
| rels[i].r_addend = 0; |
| |
| /* The #ifdef BFD64 below is to prevent a compile time |
| warning. We know that if we do not have a 64 bit data |
| type that we will never execute this code anyway. */ |
| #ifdef BFD64 |
| if (elf_header.e_machine == EM_MIPS |
| && elf_header.e_ident[EI_DATA] != ELFDATA2MSB) |
| { |
| /* In little-endian objects, r_info isn't really a |
| 64-bit little-endian value: it has a 32-bit |
| little-endian symbol index followed by four |
| individual byte fields. Reorder INFO |
| accordingly. */ |
| bfd_vma inf = rels[i].r_info; |
| inf = (((inf & 0xffffffff) << 32) |
| | ((inf >> 56) & 0xff) |
| | ((inf >> 40) & 0xff00) |
| | ((inf >> 24) & 0xff0000) |
| | ((inf >> 8) & 0xff000000)); |
| rels[i].r_info = inf; |
| } |
| #endif /* BFD64 */ |
| } |
| |
| free (erels); |
| } |
| *relsp = rels; |
| *nrelsp = nrels; |
| return 1; |
| } |
| |
| /* Returns the reloc type extracted from the reloc info field. */ |
| |
| static unsigned int |
| get_reloc_type (bfd_vma reloc_info) |
| { |
| if (is_32bit_elf) |
| return ELF32_R_TYPE (reloc_info); |
| |
| switch (elf_header.e_machine) |
| { |
| case EM_MIPS: |
| /* Note: We assume that reloc_info has already been adjusted for us. */ |
| return ELF64_MIPS_R_TYPE (reloc_info); |
| |
| case EM_SPARCV9: |
| return ELF64_R_TYPE_ID (reloc_info); |
| |
| default: |
| return ELF64_R_TYPE (reloc_info); |
| } |
| } |
| |
| /* Return the symbol index extracted from the reloc info field. */ |
| |
| static bfd_vma |
| get_reloc_symindex (bfd_vma reloc_info) |
| { |
| return is_32bit_elf ? ELF32_R_SYM (reloc_info) : ELF64_R_SYM (reloc_info); |
| } |
| |
| static inline bfd_boolean |
| uses_msp430x_relocs (void) |
| { |
| return |
| elf_header.e_machine == EM_MSP430 /* Paranoia. */ |
| /* GCC uses osabi == ELFOSBI_STANDALONE. */ |
| && (((elf_header.e_flags & EF_MSP430_MACH) == E_MSP430_MACH_MSP430X) |
| /* TI compiler uses ELFOSABI_NONE. */ |
| || (elf_header.e_ident[EI_OSABI] == ELFOSABI_NONE)); |
| } |
| |
| /* Display the contents of the relocation data found at the specified |
| offset. */ |
| |
| static void |
| dump_relocations (FILE * file, |
| unsigned long rel_offset, |
| unsigned long rel_size, |
| Elf_Internal_Sym * symtab, |
| unsigned long nsyms, |
| char * strtab, |
| unsigned long strtablen, |
| int is_rela, |
| int is_dynsym) |
| { |
| unsigned int i; |
| Elf_Internal_Rela * rels; |
| |
| if (is_rela == UNKNOWN) |
| is_rela = guess_is_rela (elf_header.e_machine); |
| |
| if (is_rela) |
| { |
| if (!slurp_rela_relocs (file, rel_offset, rel_size, &rels, &rel_size)) |
| return; |
| } |
| else |
| { |
| if (!slurp_rel_relocs (file, rel_offset, rel_size, &rels, &rel_size)) |
| return; |
| } |
| |
| if (is_32bit_elf) |
| { |
| if (is_rela) |
| { |
| if (do_wide) |
| printf (_(" Offset Info Type Sym. Value Symbol's Name + Addend\n")); |
| else |
| printf (_(" Offset Info Type Sym.Value Sym. Name + Addend\n")); |
| } |
| else |
| { |
| if (do_wide) |
| printf (_(" Offset Info Type Sym. Value Symbol's Name\n")); |
| else |
| printf (_(" Offset Info Type Sym.Value Sym. Name\n")); |
| } |
| } |
| else |
| { |
| if (is_rela) |
| { |
| if (do_wide) |
| printf (_(" Offset Info Type Symbol's Value Symbol's Name + Addend\n")); |
| else |
| printf (_(" Offset Info Type Sym. Value Sym. Name + Addend\n")); |
| } |
| else |
| { |
| if (do_wide) |
| printf (_(" Offset Info Type Symbol's Value Symbol's Name\n")); |
| else |
| printf (_(" Offset Info Type Sym. Value Sym. Name\n")); |
| } |
| } |
| |
| for (i = 0; i < rel_size; i++) |
| { |
| const char * rtype; |
| bfd_vma offset; |
| bfd_vma inf; |
| bfd_vma symtab_index; |
| bfd_vma type; |
| |
| offset = rels[i].r_offset; |
| inf = rels[i].r_info; |
| |
| type = get_reloc_type (inf); |
| symtab_index = get_reloc_symindex (inf); |
| |
| if (is_32bit_elf) |
| { |
| printf ("%8.8lx %8.8lx ", |
| (unsigned long) offset & 0xffffffff, |
| (unsigned long) inf & 0xffffffff); |
| } |
| else |
| { |
| #if BFD_HOST_64BIT_LONG |
| printf (do_wide |
| ? "%16.16lx %16.16lx " |
| : "%12.12lx %12.12lx ", |
| offset, inf); |
| #elif BFD_HOST_64BIT_LONG_LONG |
| #ifndef __MSVCRT__ |
| printf (do_wide |
| ? "%16.16llx %16.16llx " |
| : "%12.12llx %12.12llx ", |
| offset, inf); |
| #else |
| printf (do_wide |
| ? "%16.16I64x %16.16I64x " |
| : "%12.12I64x %12.12I64x ", |
| offset, inf); |
| #endif |
| #else |
| printf (do_wide |
| ? "%8.8lx%8.8lx %8.8lx%8.8lx " |
| : "%4.4lx%8.8lx %4.4lx%8.8lx ", |
| _bfd_int64_high (offset), |
| _bfd_int64_low (offset), |
| _bfd_int64_high (inf), |
| _bfd_int64_low (inf)); |
| #endif |
| } |
| |
| switch (elf_header.e_machine) |
| { |
| default: |
| rtype = NULL; |
| break; |
| |
| case EM_AARCH64: |
| rtype = elf_aarch64_reloc_type (type); |
| break; |
| |
| case EM_M32R: |
| case EM_CYGNUS_M32R: |
| rtype = elf_m32r_reloc_type (type); |
| break; |
| |
| case EM_386: |
| case EM_IAMCU: |
| rtype = elf_i386_reloc_type (type); |
| break; |
| |
| case EM_68HC11: |
| case EM_68HC12: |
| rtype = elf_m68hc11_reloc_type (type); |
| break; |
| |
| case EM_68K: |
| rtype = elf_m68k_reloc_type (type); |
| break; |
| |
| case EM_960: |
| rtype = elf_i960_reloc_type (type); |
| break; |
| |
| case EM_AVR: |
| case EM_AVR_OLD: |
| rtype = elf_avr_reloc_type (type); |
| break; |
| |
| case EM_OLD_SPARCV9: |
| case EM_SPARC32PLUS: |
| case EM_SPARCV9: |
| case EM_SPARC: |
| rtype = elf_sparc_reloc_type (type); |
| break; |
| |
| case EM_SPU: |
| rtype = elf_spu_reloc_type (type); |
| break; |
| |
| case EM_V800: |
| rtype = v800_reloc_type (type); |
| break; |
| case EM_V850: |
| case EM_CYGNUS_V850: |
| rtype = v850_reloc_type (type); |
| break; |
| |
| case EM_D10V: |
| case EM_CYGNUS_D10V: |
| rtype = elf_d10v_reloc_type (type); |
| break; |
| |
| case EM_D30V: |
| case EM_CYGNUS_D30V: |
| rtype = elf_d30v_reloc_type (type); |
| break; |
| |
| case EM_DLX: |
| rtype = elf_dlx_reloc_type (type); |
| break; |
| |
| case EM_SH: |
| rtype = elf_sh_reloc_type (type); |
| break; |
| |
| case EM_MN10300: |
| case EM_CYGNUS_MN10300: |
| rtype = elf_mn10300_reloc_type (type); |
| break; |
| |
| case EM_MN10200: |
| case EM_CYGNUS_MN10200: |
| rtype = elf_mn10200_reloc_type (type); |
| break; |
| |
| case EM_FR30: |
| case EM_CYGNUS_FR30: |
| rtype = elf_fr30_reloc_type (type); |
| break; |
| |
| case EM_CYGNUS_FRV: |
| rtype = elf_frv_reloc_type (type); |
| break; |
| |
| case EM_FT32: |
| rtype = elf_ft32_reloc_type (type); |
| break; |
| |
| case EM_MCORE: |
| rtype = elf_mcore_reloc_type (type); |
| break; |
| |
| case EM_MMIX: |
| rtype = elf_mmix_reloc_type (type); |
| break; |
| |
| case EM_MOXIE: |
| rtype = elf_moxie_reloc_type (type); |
| break; |
| |
| case EM_MSP430: |
| if (uses_msp430x_relocs ()) |
| { |
| rtype = elf_msp430x_reloc_type (type); |
| break; |
| } |
| /* Fall through. */ |
| case EM_MSP430_OLD: |
| rtype = elf_msp430_reloc_type (type); |
| break; |
| |
| case EM_NDS32: |
| rtype = elf_nds32_reloc_type (type); |
| break; |
| |
| case EM_PPC: |
| rtype = elf_ppc_reloc_type (type); |
| break; |
| |
| case EM_PPC64: |
| rtype = elf_ppc64_reloc_type (type); |
| break; |
| |
| case EM_MIPS: |
| case EM_MIPS_RS3_LE: |
| rtype = elf_mips_reloc_type (type); |
| break; |
| |
| case EM_RISCV: |
| rtype = elf_riscv_reloc_type (type); |
| break; |
| |
| case EM_ALPHA: |
| rtype = elf_alpha_reloc_type (type); |
| break; |
| |
| case EM_ARM: |
| rtype = elf_arm_reloc_type (type); |
| break; |
| |
| case EM_ARC: |
| case EM_ARC_COMPACT: |
| case EM_ARC_COMPACT2: |
| rtype = elf_arc_reloc_type (type); |
| break; |
| |
| case EM_PARISC: |
| rtype = elf_hppa_reloc_type (type); |
| break; |
| |
| case EM_H8_300: |
| case EM_H8_300H: |
| case EM_H8S: |
| rtype = elf_h8_reloc_type (type); |
| break; |
| |
| case EM_OR1K: |
| rtype = elf_or1k_reloc_type (type); |
| break; |
| |
| case EM_PJ: |
| case EM_PJ_OLD: |
| rtype = elf_pj_reloc_type (type); |
| break; |
| case EM_IA_64: |
| rtype = elf_ia64_reloc_type (type); |
| break; |
| |
| case EM_CRIS: |
| rtype = elf_cris_reloc_type (type); |
| break; |
| |
| case EM_860: |
| rtype = elf_i860_reloc_type (type); |
| break; |
| |
| case EM_X86_64: |
| case EM_L1OM: |
| case EM_K1OM: |
| rtype = elf_x86_64_reloc_type (type); |
| break; |
| |
| case EM_S370: |
| rtype = i370_reloc_type (type); |
| break; |
| |
| case EM_S390_OLD: |
| case EM_S390: |
| rtype = elf_s390_reloc_type (type); |
| break; |
| |
| case EM_SCORE: |
| rtype = elf_score_reloc_type (type); |
| break; |
| |
| case EM_XSTORMY16: |
| rtype = elf_xstormy16_reloc_type (type); |
| break; |
| |
| case EM_CRX: |
| rtype = elf_crx_reloc_type (type); |
| break; |
| |
| case EM_VAX: |
| rtype = elf_vax_reloc_type (type); |
| break; |
| |
| case EM_VISIUM: |
| rtype = elf_visium_reloc_type (type); |
| break; |
| |
| case EM_ADAPTEVA_EPIPHANY: |
| rtype = elf_epiphany_reloc_type (type); |
| break; |
| |
| case EM_IP2K: |
| case EM_IP2K_OLD: |
| rtype = elf_ip2k_reloc_type (type); |
| break; |
| |
| case EM_IQ2000: |
| rtype = elf_iq2000_reloc_type (type); |
| break; |
| |
| case EM_XTENSA_OLD: |
| case EM_XTENSA: |
| rtype = elf_xtensa_reloc_type (type); |
| break; |
| |
| case EM_LATTICEMICO32: |
| rtype = elf_lm32_reloc_type (type); |
| break; |
| |
| case EM_M32C_OLD: |
| case EM_M32C: |
| rtype = elf_m32c_reloc_type (type); |
| break; |
| |
| case EM_MT: |
| rtype = elf_mt_reloc_type (type); |
| break; |
| |
| case EM_BLACKFIN: |
| rtype = elf_bfin_reloc_type (type); |
| break; |
| |
| case EM_CYGNUS_MEP: |
| rtype = elf_mep_reloc_type (type); |
| break; |
| |
| case EM_CR16: |
| rtype = elf_cr16_reloc_type (type); |
| break; |
| |
| case EM_MICROBLAZE: |
| case EM_MICROBLAZE_OLD: |
| rtype = elf_microblaze_reloc_type (type); |
| break; |
| |
| case EM_RL78: |
| rtype = elf_rl78_reloc_type (type); |
| break; |
| |
| case EM_RX: |
| rtype = elf_rx_reloc_type (type); |
| break; |
| |
| case EM_METAG: |
| rtype = elf_metag_reloc_type (type); |
| break; |
| |
| case EM_XC16X: |
| case EM_C166: |
| rtype = elf_xc16x_reloc_type (type); |
| break; |
| |
| case EM_TI_C6000: |
| rtype = elf_tic6x_reloc_type (type); |
| break; |
| |
| case EM_TILEGX: |
| rtype = elf_tilegx_reloc_type (type); |
| break; |
| |
| case EM_TILEPRO: |
| rtype = elf_tilepro_reloc_type (type); |
| break; |
| |
| case EM_XGATE: |
| rtype = elf_xgate_reloc_type (type); |
| break; |
| |
| case EM_ALTERA_NIOS2: |
| rtype = elf_nios2_reloc_type (type); |
| break; |
| } |
| |
| if (rtype == NULL) |
| printf (_("unrecognized: %-7lx"), (unsigned long) type & 0xffffffff); |
| else |
| printf (do_wide ? "%-22.22s" : "%-17.17s", rtype); |
| |
| if (elf_header.e_machine == EM_ALPHA |
| && rtype != NULL |
| && streq (rtype, "R_ALPHA_LITUSE") |
| && is_rela) |
| { |
| switch (rels[i].r_addend) |
| { |
| case LITUSE_ALPHA_ADDR: rtype = "ADDR"; break; |
| case LITUSE_ALPHA_BASE: rtype = "BASE"; break; |
| case LITUSE_ALPHA_BYTOFF: rtype = "BYTOFF"; break; |
| case LITUSE_ALPHA_JSR: rtype = "JSR"; break; |
| case LITUSE_ALPHA_TLSGD: rtype = "TLSGD"; break; |
| case LITUSE_ALPHA_TLSLDM: rtype = "TLSLDM"; break; |
| case LITUSE_ALPHA_JSRDIRECT: rtype = "JSRDIRECT"; break; |
| default: rtype = NULL; |
| } |
| if (rtype) |
| printf (" (%s)", rtype); |
| else |
| { |
| putchar (' '); |
| printf (_("<unknown addend: %lx>"), |
| (unsigned long) rels[i].r_addend); |
| } |
| } |
| else if (symtab_index) |
| { |
| if (symtab == NULL || symtab_index >= nsyms) |
| printf (_(" bad symbol index: %08lx"), (unsigned long) symtab_index); |
| else |
| { |
| Elf_Internal_Sym * psym; |
| const char * version_string; |
| enum versioned_symbol_info sym_info; |
| unsigned short vna_other; |
| |
| psym = symtab + symtab_index; |
| |
| version_string |
| = get_symbol_version_string (file, is_dynsym, |
| strtab, strtablen, |
| symtab_index, |
| psym, |
| &sym_info, |
| &vna_other); |
| |
| printf (" "); |
| |
| if (ELF_ST_TYPE (psym->st_info) == STT_GNU_IFUNC) |
| { |
| const char * name; |
| unsigned int len; |
| unsigned int width = is_32bit_elf ? 8 : 14; |
| |
| /* Relocations against GNU_IFUNC symbols do not use the value |
| of the symbol as the address to relocate against. Instead |
| they invoke the function named by the symbol and use its |
| result as the address for relocation. |
| |
| To indicate this to the user, do not display the value of |
| the symbol in the "Symbols's Value" field. Instead show |
| its name followed by () as a hint that the symbol is |
| invoked. */ |
| |
| if (strtab == NULL |
| || psym->st_name == 0 |
| || psym->st_name >= strtablen) |
| name = "??"; |
| else |
| name = strtab + psym->st_name; |
| |
| len = print_symbol (width, name); |
| if (version_string) |
| printf (sym_info == symbol_public ? "@@%s" : "@%s", |
| version_string); |
| printf ("()%-*s", len <= width ? (width + 1) - len : 1, " "); |
| } |
| else |
| { |
| print_vma (psym->st_value, LONG_HEX); |
| |
| printf (is_32bit_elf ? " " : " "); |
| } |
| |
| if (psym->st_name == 0) |
| { |
| const char * sec_name = "<null>"; |
| char name_buf[40]; |
| |
| if (ELF_ST_TYPE (psym->st_info) == STT_SECTION) |
| { |
| if (psym->st_shndx < elf_header.e_shnum) |
| sec_name = SECTION_NAME (section_headers + psym->st_shndx); |
| else if (psym->st_shndx == SHN_ABS) |
| sec_name = "ABS"; |
| else if (psym->st_shndx == SHN_COMMON) |
| sec_name = "COMMON"; |
| else if ((elf_header.e_machine == EM_MIPS |
| && psym->st_shndx == SHN_MIPS_SCOMMON) |
| || (elf_header.e_machine == EM_TI_C6000 |
| && psym->st_shndx == SHN_TIC6X_SCOMMON)) |
| sec_name = "SCOMMON"; |
| else if (elf_header.e_machine == EM_MIPS |
| && psym->st_shndx == SHN_MIPS_SUNDEFINED) |
| sec_name = "SUNDEF"; |
| else if ((elf_header.e_machine == EM_X86_64 |
| || elf_header.e_machine == EM_L1OM |
| || elf_header.e_machine == EM_K1OM) |
| && psym->st_shndx == SHN_X86_64_LCOMMON) |
| sec_name = "LARGE_COMMON"; |
| else if (elf_header.e_machine == EM_IA_64 |
| && elf_header.e_ident[EI_OSABI] == ELFOSABI_HPUX |
| && psym->st_shndx == SHN_IA_64_ANSI_COMMON) |
| sec_name = "ANSI_COM"; |
| else if (is_ia64_vms () |
| && psym->st_shndx == SHN_IA_64_VMS_SYMVEC) |
| sec_name = "VMS_SYMVEC"; |
| else |
| { |
| sprintf (name_buf, "<section 0x%x>", |
| (unsigned int) psym->st_shndx); |
| sec_name = name_buf; |
| } |
| } |
| print_symbol (22, sec_name); |
| } |
| else if (strtab == NULL) |
| printf (_("<string table index: %3ld>"), psym->st_name); |
| else if (psym->st_name >= strtablen) |
| printf (_("<corrupt string table index: %3ld>"), psym->st_name); |
| else |
| { |
| print_symbol (22, strtab + psym->st_name); |
| if (version_string) |
| printf (sym_info == symbol_public ? "@@%s" : "@%s", |
| version_string); |
| } |
| |
| if (is_rela) |
| { |
| bfd_vma off = rels[i].r_addend; |
| |
| if ((bfd_signed_vma) off < 0) |
| printf (" - %" BFD_VMA_FMT "x", - off); |
| else |
| printf (" + %" BFD_VMA_FMT "x", off); |
| } |
| } |
| } |
| else if (is_rela) |
| { |
| bfd_vma off = rels[i].r_addend; |
| |
| printf ("%*c", is_32bit_elf ? 12 : 20, ' '); |
| if ((bfd_signed_vma) off < 0) |
| printf ("-%" BFD_VMA_FMT "x", - off); |
| else |
| printf ("%" BFD_VMA_FMT "x", off); |
| } |
| |
| if (elf_header.e_machine == EM_SPARCV9 |
| && rtype != NULL |
| && streq (rtype, "R_SPARC_OLO10")) |
| printf (" + %lx", (unsigned long) ELF64_R_TYPE_DATA (inf)); |
| |
| putchar ('\n'); |
| |
| #ifdef BFD64 |
| if (! is_32bit_elf && elf_header.e_machine == EM_MIPS) |
| { |
| bfd_vma type2 = ELF64_MIPS_R_TYPE2 (inf); |
| bfd_vma type3 = ELF64_MIPS_R_TYPE3 (inf); |
| const char * rtype2 = elf_mips_reloc_type (type2); |
| const char * rtype3 = elf_mips_reloc_type (type3); |
| |
| printf (" Type2: "); |
| |
| if (rtype2 == NULL) |
| printf (_("unrecognized: %-7lx"), |
| (unsigned long) type2 & 0xffffffff); |
| else |
| printf ("%-17.17s", rtype2); |
| |
| printf ("\n Type3: "); |
| |
| if (rtype3 == NULL) |
| printf (_("unrecognized: %-7lx"), |
| (unsigned long) type3 & 0xffffffff); |
| else |
| printf ("%-17.17s", rtype3); |
| |
| putchar ('\n'); |
| } |
| #endif /* BFD64 */ |
| } |
| |
| free (rels); |
| } |
| |
| static const char * |
| get_mips_dynamic_type (unsigned long type) |
| { |
| switch (type) |
| { |
| case DT_MIPS_RLD_VERSION: return "MIPS_RLD_VERSION"; |
| case DT_MIPS_TIME_STAMP: return "MIPS_TIME_STAMP"; |
| case DT_MIPS_ICHECKSUM: return "MIPS_ICHECKSUM"; |
| case DT_MIPS_IVERSION: return "MIPS_IVERSION"; |
| case DT_MIPS_FLAGS: return "MIPS_FLAGS"; |
| case DT_MIPS_BASE_ADDRESS: return "MIPS_BASE_ADDRESS"; |
| case DT_MIPS_MSYM: return "MIPS_MSYM"; |
| case DT_MIPS_CONFLICT: return "MIPS_CONFLICT"; |
| case DT_MIPS_LIBLIST: return "MIPS_LIBLIST"; |
| case DT_MIPS_LOCAL_GOTNO: return "MIPS_LOCAL_GOTNO"; |
| case DT_MIPS_CONFLICTNO: return "MIPS_CONFLICTNO"; |
| case DT_MIPS_LIBLISTNO: return "MIPS_LIBLISTNO"; |
| case DT_MIPS_SYMTABNO: return "MIPS_SYMTABNO"; |
| case DT_MIPS_UNREFEXTNO: return "MIPS_UNREFEXTNO"; |
| case DT_MIPS_GOTSYM: return "MIPS_GOTSYM"; |
| case DT_MIPS_HIPAGENO: return "MIPS_HIPAGENO"; |
| case DT_MIPS_RLD_MAP: return "MIPS_RLD_MAP"; |
| case DT_MIPS_RLD_MAP_REL: return "MIPS_RLD_MAP_REL"; |
| case DT_MIPS_DELTA_CLASS: return "MIPS_DELTA_CLASS"; |
| case DT_MIPS_DELTA_CLASS_NO: return "MIPS_DELTA_CLASS_NO"; |
| case DT_MIPS_DELTA_INSTANCE: return "MIPS_DELTA_INSTANCE"; |
| case DT_MIPS_DELTA_INSTANCE_NO: return "MIPS_DELTA_INSTANCE_NO"; |
| case DT_MIPS_DELTA_RELOC: return "MIPS_DELTA_RELOC"; |
| case DT_MIPS_DELTA_RELOC_NO: return "MIPS_DELTA_RELOC_NO"; |
| case DT_MIPS_DELTA_SYM: return "MIPS_DELTA_SYM"; |
| case DT_MIPS_DELTA_SYM_NO: return "MIPS_DELTA_SYM_NO"; |
| case DT_MIPS_DELTA_CLASSSYM: return "MIPS_DELTA_CLASSSYM"; |
| case DT_MIPS_DELTA_CLASSSYM_NO: return "MIPS_DELTA_CLASSSYM_NO"; |
| case DT_MIPS_CXX_FLAGS: return "MIPS_CXX_FLAGS"; |
| case DT_MIPS_PIXIE_INIT: return "MIPS_PIXIE_INIT"; |
| case DT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB"; |
| case DT_MIPS_LOCALPAGE_GOTIDX: return "MIPS_LOCALPAGE_GOTIDX"; |
| case DT_MIPS_LOCAL_GOTIDX: return "MIPS_LOCAL_GOTIDX"; |
| case DT_MIPS_HIDDEN_GOTIDX: return "MIPS_HIDDEN_GOTIDX"; |
| case DT_MIPS_PROTECTED_GOTIDX: return "MIPS_PROTECTED_GOTIDX"; |
| case DT_MIPS_OPTIONS: return "MIPS_OPTIONS"; |
| case DT_MIPS_INTERFACE: return "MIPS_INTERFACE"; |
| case DT_MIPS_DYNSTR_ALIGN: return "MIPS_DYNSTR_ALIGN"; |
| case DT_MIPS_INTERFACE_SIZE: return "MIPS_INTERFACE_SIZE"; |
| case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: return "MIPS_RLD_TEXT_RESOLVE_ADDR"; |
| case DT_MIPS_PERF_SUFFIX: return "MIPS_PERF_SUFFIX"; |
| case DT_MIPS_COMPACT_SIZE: return "MIPS_COMPACT_SIZE"; |
| case DT_MIPS_GP_VALUE: return "MIPS_GP_VALUE"; |
| case DT_MIPS_AUX_DYNAMIC: return "MIPS_AUX_DYNAMIC"; |
| case DT_MIPS_PLTGOT: return "MIPS_PLTGOT"; |
| case DT_MIPS_RWPLT: return "MIPS_RWPLT"; |
| default: |
| return NULL; |
| } |
| } |
| |
| static const char * |
| get_sparc64_dynamic_type (unsigned long type) |
| { |
| switch (type) |
| { |
| case DT_SPARC_REGISTER: return "SPARC_REGISTER"; |
| default: |
| return NULL; |
| } |
| } |
| |
| static const char * |
| get_ppc_dynamic_type (unsigned long type) |
| { |
| switch (type) |
| { |
| case DT_PPC_GOT: return "PPC_GOT"; |
| case DT_PPC_OPT: return "PPC_OPT"; |
| default: |
| return NULL; |
| } |
| } |
| |
| static const char * |
| get_ppc64_dynamic_type (unsigned long type) |
| { |
| switch (type) |
| { |
| case DT_PPC64_GLINK: return "PPC64_GLINK"; |
| case DT_PPC64_OPD: return "PPC64_OPD"; |
| case DT_PPC64_OPDSZ: return "PPC64_OPDSZ"; |
| case DT_PPC64_OPT: return "PPC64_OPT"; |
| default: |
| return NULL; |
| } |
| } |
| |
| static const char * |
| get_parisc_dynamic_type (unsigned long type) |
| { |
| switch (type) |
| { |
| case DT_HP_LOAD_MAP: return "HP_LOAD_MAP"; |
| case DT_HP_DLD_FLAGS: return "HP_DLD_FLAGS"; |
| case DT_HP_DLD_HOOK: return "HP_DLD_HOOK"; |
| case DT_HP_UX10_INIT: return "HP_UX10_INIT"; |
| case DT_HP_UX10_INITSZ: return "HP_UX10_INITSZ"; |
| case DT_HP_PREINIT: return "HP_PREINIT"; |
| case DT_HP_PREINITSZ: return "HP_PREINITSZ"; |
| case DT_HP_NEEDED: return "HP_NEEDED"; |
| case DT_HP_TIME_STAMP: return "HP_TIME_STAMP"; |
| case DT_HP_CHECKSUM: return "HP_CHECKSUM"; |
| case DT_HP_GST_SIZE: return "HP_GST_SIZE"; |
| case DT_HP_GST_VERSION: return "HP_GST_VERSION"; |
| case DT_HP_GST_HASHVAL: return "HP_GST_HASHVAL"; |
| case DT_HP_EPLTREL: return "HP_GST_EPLTREL"; |
| case DT_HP_EPLTRELSZ: return "HP_GST_EPLTRELSZ"; |
| case DT_HP_FILTERED: return "HP_FILTERED"; |
| case DT_HP_FILTER_TLS: return "HP_FILTER_TLS"; |
| case DT_HP_COMPAT_FILTERED: return "HP_COMPAT_FILTERED"; |
| case DT_HP_LAZYLOAD: return "HP_LAZYLOAD"; |
| case DT_HP_BIND_NOW_COUNT: return "HP_BIND_NOW_COUNT"; |
| case DT_PLT: return "PLT"; |
| case DT_PLT_SIZE: return "PLT_SIZE"; |
| case DT_DLT: return "DLT"; |
| case DT_DLT_SIZE: return "DLT_SIZE"; |
| default: |
| return NULL; |
| } |
| } |
| |
| static const char * |
| get_ia64_dynamic_type (unsigned long type) |
| { |
| switch (type) |
| { |
| case DT_IA_64_PLT_RESERVE: return "IA_64_PLT_RESERVE"; |
| case DT_IA_64_VMS_SUBTYPE: return "VMS_SUBTYPE"; |
| case DT_IA_64_VMS_IMGIOCNT: return "VMS_IMGIOCNT"; |
| case DT_IA_64_VMS_LNKFLAGS: return "VMS_LNKFLAGS"; |
| case DT_IA_64_VMS_VIR_MEM_BLK_SIZ: return "VMS_VIR_MEM_BLK_SIZ"; |
| case DT_IA_64_VMS_IDENT: return "VMS_IDENT"; |
| case DT_IA_64_VMS_NEEDED_IDENT: return "VMS_NEEDED_IDENT"; |
| case DT_IA_64_VMS_IMG_RELA_CNT: return "VMS_IMG_RELA_CNT"; |
| case DT_IA_64_VMS_SEG_RELA_CNT: return "VMS_SEG_RELA_CNT"; |
| case DT_IA_64_VMS_FIXUP_RELA_CNT: return "VMS_FIXUP_RELA_CNT"; |
| case DT_IA_64_VMS_FIXUP_NEEDED: return "VMS_FIXUP_NEEDED"; |
| case DT_IA_64_VMS_SYMVEC_CNT: return "VMS_SYMVEC_CNT"; |
| case DT_IA_64_VMS_XLATED: return "VMS_XLATED"; |
| case DT_IA_64_VMS_STACKSIZE: return "VMS_STACKSIZE"; |
| case DT_IA_64_VMS_UNWINDSZ: return "VMS_UNWINDSZ"; |
| case DT_IA_64_VMS_UNWIND_CODSEG: return "VMS_UNWIND_CODSEG"; |
| case DT_IA_64_VMS_UNWIND_INFOSEG: return "VMS_UNWIND_INFOSEG"; |
| case DT_IA_64_VMS_LINKTIME: return "VMS_LINKTIME"; |
| case DT_IA_64_VMS_SEG_NO: return "VMS_SEG_NO"; |
| case DT_IA_64_VMS_SYMVEC_OFFSET: return "VMS_SYMVEC_OFFSET"; |
| case DT_IA_64_VMS_SYMVEC_SEG: return "VMS_SYMVEC_SEG"; |
| case DT_IA_64_VMS_UNWIND_OFFSET: return "VMS_UNWIND_OFFSET"; |
| case DT_IA_64_VMS_UNWIND_SEG: return "VMS_UNWIND_SEG"; |
| case DT_IA_64_VMS_STRTAB_OFFSET: return "VMS_STRTAB_OFFSET"; |
| case DT_IA_64_VMS_SYSVER_OFFSET: return "VMS_SYSVER_OFFSET"; |
| case DT_IA_64_VMS_IMG_RELA_OFF: return "VMS_IMG_RELA_OFF"; |
| case DT_IA_64_VMS_SEG_RELA_OFF: return "VMS_SEG_RELA_OFF"; |
| case DT_IA_64_VMS_FIXUP_RELA_OFF: return "VMS_FIXUP_RELA_OFF"; |
| case DT_IA_64_VMS_PLTGOT_OFFSET: return "VMS_PLTGOT_OFFSET"; |
| case DT_IA_64_VMS_PLTGOT_SEG: return "VMS_PLTGOT_SEG"; |
| case DT_IA_64_VMS_FPMODE: return "VMS_FPMODE"; |
| default: |
| return NULL; |
| } |
| } |
| |
| static const char * |
| get_solaris_section_type (unsigned long type) |
| { |
| switch (type) |
| { |
| case 0x6fffffee: return "SUNW_ancillary"; |
| case 0x6fffffef: return "SUNW_capchain"; |
| case 0x6ffffff0: return "SUNW_capinfo"; |
| case 0x6ffffff1: return "SUNW_symsort"; |
| case 0x6ffffff2: return "SUNW_tlssort"; |
| case 0x6ffffff3: return "SUNW_LDYNSYM"; |
| case 0x6ffffff4: return "SUNW_dof"; |
| case 0x6ffffff5: return "SUNW_cap"; |
| case 0x6ffffff6: return "SUNW_SIGNATURE"; |
| case 0x6ffffff7: return "SUNW_ANNOTATE"; |
| case 0x6ffffff8: return "SUNW_DEBUGSTR"; |
| case 0x6ffffff9: return "SUNW_DEBUG"; |
| case 0x6ffffffa: return "SUNW_move"; |
| case 0x6ffffffb: return "SUNW_COMDAT"; |
| case 0x6ffffffc: return "SUNW_syminfo"; |
| case 0x6ffffffd: return "SUNW_verdef"; |
| case 0x6ffffffe: return "SUNW_verneed"; |
| case 0x6fffffff: return "SUNW_versym"; |
| case 0x70000000: return "SPARC_GOTDATA"; |
| default: return NULL; |
| } |
| } |
| |
| static const char * |
| get_alpha_dynamic_type (unsigned long type) |
| { |
| switch (type) |
| { |
| case DT_ALPHA_PLTRO: return "ALPHA_PLTRO"; |
| default: |
| return NULL; |
| } |
| } |
| |
| static const char * |
| get_score_dynamic_type (unsigned long type) |
| { |
| switch (type) |
| { |
| case DT_SCORE_BASE_ADDRESS: return "SCORE_BASE_ADDRESS"; |
| case DT_SCORE_LOCAL_GOTNO: return "SCORE_LOCAL_GOTNO"; |
| case DT_SCORE_SYMTABNO: return "SCORE_SYMTABNO"; |
| case DT_SCORE_GOTSYM: return "SCORE_GOTSYM"; |
| case DT_SCORE_UNREFEXTNO: return "SCORE_UNREFEXTNO"; |
| case DT_SCORE_HIPAGENO: return "SCORE_HIPAGENO"; |
| default: |
| return NULL; |
| } |
| } |
| |
| static const char * |
| get_tic6x_dynamic_type (unsigned long type) |
| { |
| switch (type) |
| { |
| case DT_C6000_GSYM_OFFSET: return "C6000_GSYM_OFFSET"; |
| case DT_C6000_GSTR_OFFSET: return "C6000_GSTR_OFFSET"; |
| case DT_C6000_DSBT_BASE: return "C6000_DSBT_BASE"; |
| case DT_C6000_DSBT_SIZE: return "C6000_DSBT_SIZE"; |
| case DT_C6000_PREEMPTMAP: return "C6000_PREEMPTMAP"; |
| case DT_C6000_DSBT_INDEX: return "C6000_DSBT_INDEX"; |
| default: |
| return NULL; |
| } |
| } |
| |
| static const char * |
| get_nios2_dynamic_type (unsigned long type) |
| { |
| switch (type) |
| { |
| case DT_NIOS2_GP: return "NIOS2_GP"; |
| default: |
| return NULL; |
| } |
| } |
| |
| static const char * |
| get_solaris_dynamic_type (unsigned long type) |
| { |
| switch (type) |
| { |
| case 0x6000000d: return "SUNW_AUXILIARY"; |
| case 0x6000000e: return "SUNW_RTLDINF"; |
| case 0x6000000f: return "SUNW_FILTER"; |
| case 0x60000010: return "SUNW_CAP"; |
| case 0x60000011: return "SUNW_SYMTAB"; |
| case 0x60000012: return "SUNW_SYMSZ"; |
| case 0x60000013: return "SUNW_SORTENT"; |
| case 0x60000014: return "SUNW_SYMSORT"; |
| case 0x60000015: return "SUNW_SYMSORTSZ"; |
| case 0x60000016: return "SUNW_TLSSORT"; |
| case 0x60000017: return "SUNW_TLSSORTSZ"; |
| case 0x60000018: return "SUNW_CAPINFO"; |
| case 0x60000019: return "SUNW_STRPAD"; |
| case 0x6000001a: return "SUNW_CAPCHAIN"; |
| case 0x6000001b: return "SUNW_LDMACH"; |
| case 0x6000001d: return "SUNW_CAPCHAINENT"; |
| case 0x6000001f: return "SUNW_CAPCHAINSZ"; |
| case 0x60000021: return "SUNW_PARENT"; |
| case 0x60000023: return "SUNW_ASLR"; |
| case 0x60000025: return "SUNW_RELAX"; |
| case 0x60000029: return "SUNW_NXHEAP"; |
| case 0x6000002b: return "SUNW_NXSTACK"; |
| |
| case 0x70000001: return "SPARC_REGISTER"; |
| case 0x7ffffffd: return "AUXILIARY"; |
| case 0x7ffffffe: return "USED"; |
| case 0x7fffffff: return "FILTER"; |
| |
| default: return NULL; |
| } |
| } |
| |
| static const char * |
| get_dynamic_type (unsigned long type) |
| { |
| static char buff[64]; |
| |
| switch (type) |
| { |
| case DT_NULL: return "NULL"; |
| case DT_NEEDED: return "NEEDED"; |
| case DT_PLTRELSZ: return "PLTRELSZ"; |
| case DT_PLTGOT: return "PLTGOT"; |
| case DT_HASH: return "HASH"; |
| case DT_STRTAB: return "STRTAB"; |
| case DT_SYMTAB: return "SYMTAB"; |
| case DT_RELA: return "RELA"; |
| case DT_RELASZ: return "RELASZ"; |
| case DT_RELAENT: return "RELAENT"; |
| case DT_STRSZ: return "STRSZ"; |
| case DT_SYMENT: return "SYMENT"; |
| case DT_INIT: return "INIT"; |
| case DT_FINI: return "FINI"; |
| case DT_SONAME: return "SONAME"; |
| case DT_RPATH: return "RPATH"; |
| case DT_SYMBOLIC: return "SYMBOLIC"; |
| case DT_REL: return "REL"; |
| case DT_RELSZ: return "RELSZ"; |
| case DT_RELENT: return "RELENT"; |
| case DT_PLTREL: return "PLTREL"; |
| case DT_DEBUG: return "DEBUG"; |
| case DT_TEXTREL: return "TEXTREL"; |
| case DT_JMPREL: return "JMPREL"; |
| case DT_BIND_NOW: return "BIND_NOW"; |
| case DT_INIT_ARRAY: return "INIT_ARRAY"; |
| case DT_FINI_ARRAY: return "FINI_ARRAY"; |
| case DT_INIT_ARRAYSZ: return "INIT_ARRAYSZ"; |
| case DT_FINI_ARRAYSZ: return "FINI_ARRAYSZ"; |
| case DT_RUNPATH: return "RUNPATH"; |
| case DT_FLAGS: return "FLAGS"; |
| |
| case DT_PREINIT_ARRAY: return "PREINIT_ARRAY"; |
| case DT_PREINIT_ARRAYSZ: return "PREINIT_ARRAYSZ"; |
| case DT_SYMTAB_SHNDX: return "SYMTAB_SHNDX"; |
| |
| case DT_CHECKSUM: return "CHECKSUM"; |
| case DT_PLTPADSZ: return "PLTPADSZ"; |
| case DT_MOVEENT: return "MOVEENT"; |
| case DT_MOVESZ: return "MOVESZ"; |
| case DT_FEATURE: return "FEATURE"; |
| case DT_POSFLAG_1: return "POSFLAG_1"; |
| case DT_SYMINSZ: return "SYMINSZ"; |
| case DT_SYMINENT: return "SYMINENT"; /* aka VALRNGHI */ |
| |
| case DT_ADDRRNGLO: return "ADDRRNGLO"; |
| case DT_CONFIG: return "CONFIG"; |
| case DT_DEPAUDIT: return "DEPAUDIT"; |
| case DT_AUDIT: return "AUDIT"; |
| case DT_PLTPAD: return "PLTPAD"; |
| case DT_MOVETAB: return "MOVETAB"; |
| case DT_SYMINFO: return "SYMINFO"; /* aka ADDRRNGHI */ |
| |
| case DT_VERSYM: return "VERSYM"; |
| |
| case DT_TLSDESC_GOT: return "TLSDESC_GOT"; |
| case DT_TLSDESC_PLT: return "TLSDESC_PLT"; |
| case DT_RELACOUNT: return "RELACOUNT"; |
| case DT_RELCOUNT: return "RELCOUNT"; |
| case DT_FLAGS_1: return "FLAGS_1"; |
| case DT_VERDEF: return "VERDEF"; |
| case DT_VERDEFNUM: return "VERDEFNUM"; |
| case DT_VERNEED: return "VERNEED"; |
| case DT_VERNEEDNUM: return "VERNEEDNUM"; |
| |
| case DT_AUXILIARY: return "AUXILIARY"; |
| case DT_USED: return "USED"; |
| case DT_FILTER: return "FILTER"; |
| |
| case DT_GNU_PRELINKED: return "GNU_PRELINKED"; |
| case DT_GNU_CONFLICT: return "GNU_CONFLICT"; |
| case DT_GNU_CONFLICTSZ: return "GNU_CONFLICTSZ"; |
| case DT_GNU_LIBLIST: return "GNU_LIBLIST"; |
| case DT_GNU_LIBLISTSZ: return "GNU_LIBLISTSZ"; |
| case DT_GNU_HASH: return "GNU_HASH"; |
| |
| default: |
| if ((type >= DT_LOPROC) && (type <= DT_HIPROC)) |
| { |
| const char * result; |
| |
| switch (elf_header.e_machine) |
| { |
| case EM_MIPS: |
| case EM_MIPS_RS3_LE: |
| result = get_mips_dynamic_type (type); |
| break; |
| case EM_SPARCV9: |
| result = get_sparc64_dynamic_type (type); |
| break; |
| case EM_PPC: |
| result = get_ppc_dynamic_type (type); |
| break; |
| case EM_PPC64: |
| result = get_ppc64_dynamic_type (type); |
| break; |
| case EM_IA_64: |
| result = get_ia64_dynamic_type (type); |
| break; |
| case EM_ALPHA: |
| result = get_alpha_dynamic_type (type); |
| break; |
| case EM_SCORE: |
| result = get_score_dynamic_type (type); |
| break; |
| case EM_TI_C6000: |
| result = get_tic6x_dynamic_type (type); |
| break; |
| case EM_ALTERA_NIOS2: |
| result = get_nios2_dynamic_type (type); |
| break; |
| default: |
| if (elf_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS) |
| result = get_solaris_dynamic_type (type); |
| else |
| result = NULL; |
| break; |
| } |
| |
| if (result != NULL) |
| return result; |
| |
| snprintf (buff, sizeof (buff), _("Processor Specific: %lx"), type); |
| } |
| else if (((type >= DT_LOOS) && (type <= DT_HIOS)) |
| || (elf_header.e_machine == EM_PARISC |
| && (type >= OLD_DT_LOOS) && (type <= OLD_DT_HIOS))) |
| { |
| const char * result; |
| |
| switch (elf_header.e_machine) |
| { |
| case EM_PARISC: |
| result = get_parisc_dynamic_type (type); |
| break; |
| case EM_IA_64: |
| result = get_ia64_dynamic_type (type); |
| break; |
| default: |
| if (elf_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS) |
| result = get_solaris_dynamic_type (type); |
| else |
| result = NULL; |
| break; |
| } |
| |
| if (result != NULL) |
| return result; |
| |
| snprintf (buff, sizeof (buff), _("Operating System specific: %lx"), |
| type); |
| } |
| else |
| snprintf (buff, sizeof (buff), _("<unknown>: %lx"), type); |
| |
| return buff; |
| } |
| } |
| |
| static char * |
| get_file_type (unsigned e_type) |
| { |
| static char buff[32]; |
| |
| switch (e_type) |
| { |
| case ET_NONE: return _("NONE (None)"); |
| case ET_REL: return _("REL (Relocatable file)"); |
| case ET_EXEC: return _("EXEC (Executable file)"); |
| case ET_DYN: return _("DYN (Shared object file)"); |
| case ET_CORE: return _("CORE (Core file)"); |
| |
| default: |
| if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC)) |
| snprintf (buff, sizeof (buff), _("Processor Specific: (%x)"), e_type); |
| else if ((e_type >= ET_LOOS) && (e_type <= ET_HIOS)) |
| snprintf (buff, sizeof (buff), _("OS Specific: (%x)"), e_type); |
| else |
| snprintf (buff, sizeof (buff), _("<unknown>: %x"), e_type); |
| return buff; |
| } |
| } |
| |
| static char * |
| get_machine_name (unsigned e_machine) |
| { |
| static char buff[64]; /* XXX */ |
| |
| switch (e_machine) |
| { |
| case EM_NONE: return _("None"); |
| case EM_AARCH64: return "AArch64"; |
| case EM_M32: return "WE32100"; |
| case EM_SPARC: return "Sparc"; |
| case EM_SPU: return "SPU"; |
| case EM_386: return "Intel 80386"; |
| case EM_68K: return "MC68000"; |
| case EM_88K: return "MC88000"; |
| case EM_IAMCU: return "Intel MCU"; |
| case EM_860: return "Intel 80860"; |
| case EM_MIPS: return "MIPS R3000"; |
| case EM_S370: return "IBM System/370"; |
| case EM_MIPS_RS3_LE: return "MIPS R4000 big-endian"; |
| case EM_OLD_SPARCV9: return "Sparc v9 (old)"; |
| case EM_PARISC: return "HPPA"; |
| case EM_PPC_OLD: return "Power PC (old)"; |
| case EM_SPARC32PLUS: return "Sparc v8+" ; |
| case EM_960: return "Intel 90860"; |
| case EM_PPC: return "PowerPC"; |
| case EM_PPC64: return "PowerPC64"; |
| case EM_FR20: return "Fujitsu FR20"; |
| case EM_FT32: return "FTDI FT32"; |
| case EM_RH32: return "TRW RH32"; |
| case EM_MCORE: return "MCORE"; |
| case EM_ARM: return "ARM"; |
| case EM_OLD_ALPHA: return "Digital Alpha (old)"; |
| case EM_SH: return "Renesas / SuperH SH"; |
| case EM_SPARCV9: return "Sparc v9"; |
| case EM_TRICORE: return "Siemens Tricore"; |
| case EM_ARC: return "ARC"; |
| case EM_ARC_COMPACT: return "ARCompact"; |
| case EM_ARC_COMPACT2: return "ARCv2"; |
| case EM_H8_300: return "Renesas H8/300"; |
| case EM_H8_300H: return "Renesas H8/300H"; |
| case EM_H8S: return "Renesas H8S"; |
| case EM_H8_500: return "Renesas H8/500"; |
| case EM_IA_64: return "Intel IA-64"; |
| case EM_MIPS_X: return "Stanford MIPS-X"; |
| case EM_COLDFIRE: return "Motorola Coldfire"; |
| case EM_ALPHA: return "Alpha"; |
| case EM_CYGNUS_D10V: |
| case EM_D10V: return "d10v"; |
| case EM_CYGNUS_D30V: |
| case EM_D30V: return "d30v"; |
| case EM_CYGNUS_M32R: |
| case EM_M32R: return "Renesas M32R (formerly Mitsubishi M32r)"; |
| case EM_CYGNUS_V850: |
| case EM_V800: return "Renesas V850 (using RH850 ABI)"; |
| case EM_V850: return "Renesas V850"; |
| case EM_CYGNUS_MN10300: |
| case EM_MN10300: return "mn10300"; |
| case EM_CYGNUS_MN10200: |
| case EM_MN10200: return "mn10200"; |
| case EM_MOXIE: return "Moxie"; |
| case EM_CYGNUS_FR30: |
| case EM_FR30: return "Fujitsu FR30"; |
| case EM_CYGNUS_FRV: return "Fujitsu FR-V"; |
| case EM_PJ_OLD: |
| case EM_PJ: return "picoJava"; |
| case EM_MMA: return "Fujitsu Multimedia Accelerator"; |
| case EM_PCP: return "Siemens PCP"; |
| case EM_NCPU: return "Sony nCPU embedded RISC processor"; |
| case EM_NDR1: return "Denso NDR1 microprocesspr"; |
| case EM_STARCORE: return "Motorola Star*Core processor"; |
| case EM_ME16: return "Toyota ME16 processor"; |
| case EM_ST100: return "STMicroelectronics ST100 processor"; |
| case EM_TINYJ: return "Advanced Logic Corp. TinyJ embedded processor"; |
| case EM_PDSP: return "Sony DSP processor"; |
| case EM_PDP10: return "Digital Equipment Corp. PDP-10"; |
| case EM_PDP11: return "Digital Equipment Corp. PDP-11"; |
| case EM_FX66: return "Siemens FX66 microcontroller"; |
| case EM_ST9PLUS: return "STMicroelectronics ST9+ 8/16 bit microcontroller"; |
| case EM_ST7: return "STMicroelectronics ST7 8-bit microcontroller"; |
| case EM_68HC16: return "Motorola MC68HC16 Microcontroller"; |
| case EM_68HC12: return "Motorola MC68HC12 Microcontroller"; |
| case EM_68HC11: return "Motorola MC68HC11 Microcontroller"; |
| case EM_68HC08: return "Motorola MC68HC08 Microcontroller"; |
| case EM_68HC05: return "Motorola MC68HC05 Microcontroller"; |
| case EM_SVX: return "Silicon Graphics SVx"; |
| case EM_ST19: return "STMicroelectronics ST19 8-bit microcontroller"; |
| case EM_VAX: return "Digital VAX"; |
| case EM_VISIUM: return "CDS VISIUMcore processor"; |
| case EM_AVR_OLD: |
| case EM_AVR: return "Atmel AVR 8-bit microcontroller"; |
| case EM_CRIS: return "Axis Communications 32-bit embedded processor"; |
| case EM_JAVELIN: return "Infineon Technologies 32-bit embedded cpu"; |
| case EM_FIREPATH: return "Element 14 64-bit DSP processor"; |
| case EM_ZSP: return "LSI Logic's 16-bit DSP processor"; |
| case EM_MMIX: return "Donald Knuth's educational 64-bit processor"; |
| case EM_HUANY: return "Harvard Universitys's machine-independent object format"; |
| case EM_PRISM: return "Vitesse Prism"; |
| case EM_X86_64: return "Advanced Micro Devices X86-64"; |
| case EM_L1OM: return "Intel L1OM"; |
| case EM_K1OM: return "Intel K1OM"; |
| case EM_S390_OLD: |
| case EM_S390: return "IBM S/390"; |
| case EM_SCORE: return "SUNPLUS S+Core"; |
| case EM_XSTORMY16: return "Sanyo XStormy16 CPU core"; |
| case EM_OR1K: return "OpenRISC 1000"; |
| case EM_CRX: return "National Semiconductor CRX microprocessor"; |
| case EM_ADAPTEVA_EPIPHANY: return "Adapteva EPIPHANY"; |
| case EM_DLX: return "OpenDLX"; |
| case EM_IP2K_OLD: |
| case EM_IP2K: return "Ubicom IP2xxx 8-bit microcontrollers"; |
| case EM_IQ2000: return "Vitesse IQ2000"; |
| case EM_XTENSA_OLD: |
| case EM_XTENSA: return "Tensilica Xtensa Processor"; |
| case EM_VIDEOCORE: return "Alphamosaic VideoCore processor"; |
| case EM_TMM_GPP: return "Thompson Multimedia General Purpose Processor"; |
| case EM_NS32K: return "National Semiconductor 32000 series"; |
| case EM_TPC: return "Tenor Network TPC processor"; |
| case EM_ST200: return "STMicroelectronics ST200 microcontroller"; |
| case EM_MAX: return "MAX Processor"; |
| case EM_CR: return "National Semiconductor CompactRISC"; |
| case EM_F2MC16: return "Fujitsu F2MC16"; |
| case EM_MSP430: return "Texas Instruments msp430 microcontroller"; |
| case EM_LATTICEMICO32: return "Lattice Mico32"; |
| case EM_M32C_OLD: |
| case EM_M32C: return "Renesas M32c"; |
| case EM_MT: return "Morpho Techologies MT processor"; |
| case EM_BLACKFIN: return "Analog Devices Blackfin"; |
| case EM_SE_C33: return "S1C33 Family of Seiko Epson processors"; |
| case EM_SEP: return "Sharp embedded microprocessor"; |
| case EM_ARCA: return "Arca RISC microprocessor"; |
| case EM_UNICORE: return "Unicore"; |
| case EM_EXCESS: return "eXcess 16/32/64-bit configurable embedded CPU"; |
| case EM_DXP: return "Icera Semiconductor Inc. Deep Execution Processor"; |
| case EM_NIOS32: return "Altera Nios"; |
| case EM_ALTERA_NIOS2: return "Altera Nios II"; |
| case EM_C166: |
| case EM_XC16X: return "Infineon Technologies xc16x"; |
| case EM_M16C: return "Renesas M16C series microprocessors"; |
| case EM_DSPIC30F: return "Microchip Technology dsPIC30F Digital Signal Controller"; |
| case EM_CE: return "Freescale Communication Engine RISC core"; |
| case EM_TSK3000: return "Altium TSK3000 core"; |
| case EM_RS08: return "Freescale RS08 embedded processor"; |
| case EM_ECOG2: return "Cyan Technology eCOG2 microprocessor"; |
| case EM_DSP24: return "New Japan Radio (NJR) 24-bit DSP Processor"; |
| case EM_VIDEOCORE3: return "Broadcom VideoCore III processor"; |
| case EM_SE_C17: return "Seiko Epson C17 family"; |
| case EM_TI_C6000: return "Texas Instruments TMS320C6000 DSP family"; |
| case EM_TI_C2000: return "Texas Instruments TMS320C2000 DSP family"; |
| case EM_TI_C5500: return "Texas Instruments TMS320C55x DSP family"; |
| case EM_MMDSP_PLUS: return "STMicroelectronics 64bit VLIW Data Signal Processor"; |
| case EM_CYPRESS_M8C: return "Cypress M8C microprocessor"; |
| case EM_R32C: return "Renesas R32C series microprocessors"; |
| case EM_TRIMEDIA: return "NXP Semiconductors TriMedia architecture family"; |
| case EM_QDSP6: return "QUALCOMM DSP6 Processor"; |
| case EM_8051: return "Intel 8051 and variants"; |
| case EM_STXP7X: return "STMicroelectronics STxP7x family"; |
| case EM_NDS32: return "Andes Technology compact code size embedded RISC processor family"; |
| case EM_ECOG1X: return "Cyan Technology eCOG1X family"; |
| case EM_MAXQ30: return "Dallas Semiconductor MAXQ30 Core microcontrollers"; |
| case EM_XIMO16: return "New Japan Radio (NJR) 16-bit DSP Processor"; |
| case EM_MANIK: return "M2000 Reconfigurable RISC Microprocessor"; |
| case EM_CRAYNV2: return "Cray Inc. NV2 vector architecture"; |
| case EM_CYGNUS_MEP: return "Toshiba MeP Media Engine"; |
| case EM_CR16: |
| case EM_MICROBLAZE: |
| case EM_MICROBLAZE_OLD: return "Xilinx MicroBlaze"; |
| case EM_RISCV: return "RISC-V"; |
| case EM_RL78: return "Renesas RL78"; |
| case EM_RX: return "Renesas RX"; |
| case EM_METAG: return "Imagination Technologies Meta processor architecture"; |
| case EM_MCST_ELBRUS: return "MCST Elbrus general purpose hardware architecture"; |
| case EM_ECOG16: return "Cyan Technology eCOG16 family"; |
| case EM_ETPU: return "Freescale Extended Time Processing Unit"; |
| case EM_SLE9X: return "Infineon Technologies SLE9X core"; |
| case EM_AVR32: return "Atmel Corporation 32-bit microprocessor family"; |
| case EM_STM8: return "STMicroeletronics STM8 8-bit microcontroller"; |
| case EM_TILE64: return "Tilera TILE64 multicore architecture family"; |
| case EM_TILEPRO: return "Tilera TILEPro multicore architecture family"; |
| case EM_TILEGX: return "Tilera TILE-Gx multicore architecture family"; |
| case EM_CUDA: return "NVIDIA CUDA architecture"; |
| case EM_XGATE: return "Motorola XGATE embedded processor"; |
| case EM_CLOUDSHIELD: return "CloudShield architecture family"; |
| case EM_COREA_1ST: return "KIPO-KAIST Core-A 1st generation processor family"; |
| case EM_COREA_2ND: return "KIPO-KAIST Core-A 2nd generation processor family"; |
| case EM_OPEN8: return "Open8 8-bit RISC soft processor core"; |
| case EM_VIDEOCORE5: return "Broadcom VideoCore V processor"; |
| case EM_56800EX: return "Freescale 56800EX Digital Signal Controller (DSC)"; |
| case EM_BA1: return "Beyond BA1 CPU architecture"; |
| case EM_BA2: return "Beyond BA2 CPU architecture"; |
| case EM_XCORE: return "XMOS xCORE processor family"; |
| case EM_MCHP_PIC: return "Microchip 8-bit PIC(r) family"; |
| case EM_KM32: return "KM211 KM32 32-bit processor"; |
| case EM_KMX32: return "KM211 KMX32 32-bit processor"; |
| case EM_KMX16: return "KM211 KMX16 16-bit processor"; |
| case EM_KMX8: return "KM211 KMX8 8-bit processor"; |
| case EM_KVARC: return "KM211 KVARC processor"; |
| case EM_CDP: return "Paneve CDP architecture family"; |
| case EM_COGE: return "Cognitive Smart Memory Processor"; |
| case EM_COOL: return "Bluechip Systems CoolEngine"; |
| case EM_NORC: return "Nanoradio Optimized RISC"; |
| case EM_CSR_KALIMBA: return "CSR Kalimba architecture family"; |
| case EM_Z80: return "Zilog Z80"; |
| case EM_AMDGPU: return "AMD GPU architecture"; |
| default: |
| snprintf (buff, sizeof (buff), _("<unknown>: 0x%x"), e_machine); |
| return buff; |
| } |
| } |
| |
| static void |
| decode_ARC_machine_flags (unsigned e_flags, unsigned e_machine, char buf[]) |
| { |
| /* ARC has two machine types EM_ARC_COMPACT and EM_ARC_COMPACT2. Some |
| other compilers don't a specific architecture type in the e_flags, and |
| instead use EM_ARC_COMPACT for old ARC600, ARC601, and ARC700 |
| architectures, and switch to EM_ARC_COMPACT2 for newer ARCEM and ARCHS |
| architectures. |
| |
| Th GNU tools follows this use of EM_ARC_COMPACT and EM_ARC_COMPACT2, |
| but also sets a specific architecture type in the e_flags field. |
| |
| However, when decoding the flags we don't worry if we see an |
| unexpected pairing, for example EM_ARC_COMPACT machine type, with |
| ARCEM architecture type. */ |
| |
| switch (e_flags & EF_ARC_MACH_MSK) |
| { |
| /* We only expect these to occur for EM_ARC_COMPACT2. */ |
| case EF_ARC_CPU_ARCV2EM: |
| strcat (buf, ", ARC EM"); |
| break; |
| case EF_ARC_CPU_ARCV2HS: |
| strcat (buf, ", ARC HS"); |
| break; |
| |
| /* We only expect these to occur for EM_ARC_COMPACT. */ |
| case E_ARC_MACH_ARC600: |
| strcat (buf, ", ARC600"); |
| break; |
| case E_ARC_MACH_ARC601: |
| strcat (buf, ", ARC601"); |
| break; |
| case E_ARC_MACH_ARC700: |
| strcat (buf, ", ARC700"); |
| break; |
| |
| /* The only times we should end up here are (a) A corrupt ELF, (b) A |
| new ELF with new architecture being read by an old version of |
| readelf, or (c) An ELF built with non-GNU compiler that does not |
| set the architecture in the e_flags. */ |
| default: |
| if (e_machine == EM_ARC_COMPACT) |
| strcat (buf, ", Unknown ARCompact"); |
| else |
| strcat (buf, ", Unknown ARC"); |
| break; |
| } |
| |
| switch (e_flags & EF_ARC_OSABI_MSK) |
| { |
| case E_ARC_OSABI_ORIG: |
| strcat (buf, ", (ABI:legacy)"); |
| break; |
| case E_ARC_OSABI_V2: |
| strcat (buf, ", (ABI:v2)"); |
| break; |
| /* Only upstream 3.9+ kernels will support ARCv2 ISA. */ |
| case E_ARC_OSABI_V3: |
| strcat (buf, ", v3 no-legacy-syscalls ABI"); |
| break; |
| default: |
| strcat (buf, ", unrecognised ARC OSABI flag"); |
| break; |
| } |
| } |
| |
| static void |
| decode_ARM_machine_flags (unsigned e_flags, char buf[]) |
| { |
| unsigned eabi; |
| int unknown = 0; |
| |
| eabi = EF_ARM_EABI_VERSION (e_flags); |
| e_flags &= ~ EF_ARM_EABIMASK; |
| |
| /* Handle "generic" ARM flags. */ |
| if (e_flags & EF_ARM_RELEXEC) |
| { |
| strcat (buf, ", relocatable executable"); |
| e_flags &= ~ EF_ARM_RELEXEC; |
| } |
| |
| /* Now handle EABI specific flags. */ |
| switch (eabi) |
| { |
| default: |
| strcat (buf, ", <unrecognized EABI>"); |
| if (e_flags) |
| unknown = 1; |
| break; |
| |
| case EF_ARM_EABI_VER1: |
| strcat (buf, ", Version1 EABI"); |
| while (e_flags) |
| { |
| unsigned flag; |
| |
| /* Process flags one bit at a time. */ |
| flag = e_flags & - e_flags; |
| e_flags &= ~ flag; |
| |
| switch (flag) |
| { |
| case EF_ARM_SYMSARESORTED: /* Conflicts with EF_ARM_INTERWORK. */ |
| strcat (buf, ", sorted symbol tables"); |
| break; |
| |
| default: |
| unknown = 1; |
| break; |
| } |
| } |
| break; |
| |
| case EF_ARM_EABI_VER2: |
| strcat (buf, ", Version2 EABI"); |
| while (e_flags) |
| { |
| unsigned flag; |
| |
| /* Process flags one bit at a time. */ |
| flag = e_flags & - e_flags; |
| e_flags &= ~ flag; |
| |
| switch (flag) |
| { |
| case EF_ARM_SYMSARESORTED: /* Conflicts with EF_ARM_INTERWORK. */ |
| strcat (buf, ", sorted symbol tables"); |
| break; |
| |
| case EF_ARM_DYNSYMSUSESEGIDX: |
| strcat (buf, ", dynamic symbols use segment index"); |
| break; |
| |
| case EF_ARM_MAPSYMSFIRST: |
| strcat (buf, ", mapping symbols precede others"); |
| break; |
| |
| default: |
| unknown = 1; |
| break; |
| } |
| } |
| break; |
| |
| case EF_ARM_EABI_VER3: |
| strcat (buf, ", Version3 EABI"); |
| break; |
| |
| case EF_ARM_EABI_VER4: |
| strcat (buf, ", Version4 EABI"); |
| while (e_flags) |
| { |
| unsigned flag; |
| |
| /* Process flags one bit at a time. */ |
| flag = e_flags & - e_flags; |
| e_flags &= ~ flag; |
| |
| switch (flag) |
| { |
| case EF_ARM_BE8: |
| strcat (buf, ", BE8"); |
| break; |
| |
| case EF_ARM_LE8: |
| strcat (buf, ", LE8"); |
| break; |
| |
| default: |
| unknown = 1; |
| break; |
| } |
| break; |
| } |
| break; |
| |
| case EF_ARM_EABI_VER5: |
| strcat (buf, ", Version5 EABI"); |
| while (e_flags) |
| { |
| unsigned flag; |
| |
| /* Process flags one bit at a time. */ |
| flag = e_flags & - e_flags; |
| e_flags &= ~ flag; |
| |
| switch (flag) |
| { |
| case EF_ARM_BE8: |
| strcat (buf, ", BE8"); |
| break; |
| |
| case EF_ARM_LE8: |
| strcat (buf, ", LE8"); |
| break; |
| |
| case EF_ARM_ABI_FLOAT_SOFT: /* Conflicts with EF_ARM_SOFT_FLOAT. */ |
| strcat (buf, ", soft-float ABI"); |
| break; |
| |
| case EF_ARM_ABI_FLOAT_HARD: /* Conflicts with EF_ARM_VFP_FLOAT. */ |
| strcat (buf, ", hard-float ABI"); |
| break; |
| |
| default: |
| unknown = 1; |
| break; |
| } |
| } |
| break; |
| |
| case EF_ARM_EABI_UNKNOWN: |
| strcat (buf, ", GNU EABI"); |
| while (e_flags) |
| { |
| unsigned flag; |
| |
| /* Process flags one bit at a time. */ |
| flag = e_flags & - e_flags; |
| e_flags &= ~ flag; |
| |
| switch (flag) |
| { |
| case EF_ARM_INTERWORK: |
| strcat (buf, ", interworking enabled"); |
| break; |
| |
| case EF_ARM_APCS_26: |
| strcat (buf, ", uses APCS/26"); |
| break; |
| |
| case EF_ARM_APCS_FLOAT: |
| strcat (buf, ", uses APCS/float"); |
| break; |
| |
| case EF_ARM_PIC: |
| strcat (buf, ", position independent"); |
| break; |
| |
| case EF_ARM_ALIGN8: |
| strcat (buf, ", 8 bit structure alignment"); |
| break; |
| |
| case EF_ARM_NEW_ABI: |
| strcat (buf, ", uses new ABI"); |
| break; |
| |
| case EF_ARM_OLD_ABI: |
| strcat (buf, ", uses old ABI"); |
| break; |
| |
| case EF_ARM_SOFT_FLOAT: |
| strcat (buf, ", software FP"); |
| break; |
| |
| case EF_ARM_VFP_FLOAT: |
| strcat (buf, ", VFP"); |
| break; |
| |
| case EF_ARM_MAVERICK_FLOAT: |
| strcat (buf, ", Maverick FP"); |
| break; |
| |
| default: |
| unknown = 1; |
| break; |
| } |
| } |
| } |
| |
| if (unknown) |
| strcat (buf,_(", <unknown>")); |
| } |
| |
| static void |
| decode_AVR_machine_flags (unsigned e_flags, char buf[], size_t size) |
| { |
| --size; /* Leave space for null terminator. */ |
| |
| switch (e_flags & EF_AVR_MACH) |
| { |
| case E_AVR_MACH_AVR1: |
| strncat (buf, ", avr:1", size); |
| break; |
| case E_AVR_MACH_AVR2: |
| strncat (buf, ", avr:2", size); |
| break; |
| case E_AVR_MACH_AVR25: |
| strncat (buf, ", avr:25", size); |
| break; |
| case E_AVR_MACH_AVR3: |
| strncat (buf, ", avr:3", size); |
| break; |
| case E_AVR_MACH_AVR31: |
| strncat (buf, ", avr:31", size); |
| break; |
| case E_AVR_MACH_AVR35: |
| strncat (buf, ", avr:35", size); |
| break; |
| case E_AVR_MACH_AVR4: |
| strncat (buf, ", avr:4", size); |
| break; |
| case E_AVR_MACH_AVR5: |
| strncat (buf, ", avr:5", size); |
| break; |
| case E_AVR_MACH_AVR51: |
| strncat (buf, ", avr:51", size); |
| break; |
| case E_AVR_MACH_AVR6: |
| strncat (buf, ", avr:6", size); |
| break; |
| case E_AVR_MACH_AVRTINY: |
| strncat (buf, ", avr:100", size); |
| break; |
| case E_AVR_MACH_XMEGA1: |
| strncat (buf, ", avr:101", size); |
| break; |
| case E_AVR_MACH_XMEGA2: |
| strncat (buf, ", avr:102", size); |
| break; |
| case E_AVR_MACH_XMEGA3: |
| strncat (buf, ", avr:103", size); |
| break; |
| case E_AVR_MACH_XMEGA4: |
| strncat (buf, ", avr:104", size); |
| break; |
| case E_AVR_MACH_XMEGA5: |
| strncat (buf, ", avr:105", size); |
| break; |
| case E_AVR_MACH_XMEGA6: |
| strncat (buf, ", avr:106", size); |
| break; |
| case E_AVR_MACH_XMEGA7: |
| strncat (buf, ", avr:107", size); |
| break; |
| default: |
| strncat (buf, ", avr:<unknown>", size); |
| break; |
| } |
| |
| size -= strlen (buf); |
| if (e_flags & EF_AVR_LINKRELAX_PREPARED) |
| strncat (buf, ", link-relax", size); |
| } |
| |
| static void |
| decode_NDS32_machine_flags (unsigned e_flags, char buf[], size_t size) |
| { |
| unsigned abi; |
| unsigned arch; |
| unsigned config; |
| unsigned version; |
| int has_fpu = 0; |
| int r = 0; |
| |
| static const char *ABI_STRINGS[] = |
| { |
| "ABI v0", /* use r5 as return register; only used in N1213HC */ |
| "ABI v1", /* use r0 as return register */ |
| "ABI v2", /* use r0 as return register and don't reserve 24 bytes for arguments */ |
| "ABI v2fp", /* for FPU */ |
| "AABI", |
| "ABI2 FP+" |
| }; |
| static const char *VER_STRINGS[] = |
| { |
| "Andes ELF V1.3 or older", |
| "Andes ELF V1.3.1", |
| "Andes ELF V1.4" |
| }; |
| static const char *ARCH_STRINGS[] = |
| { |
| "", |
| "Andes Star v1.0", |
| "Andes Star v2.0", |
| "Andes Star v3.0", |
| "Andes Star v3.0m" |
| }; |
| |
| abi = EF_NDS_ABI & e_flags; |
| arch = EF_NDS_ARCH & e_flags; |
| config = EF_NDS_INST & e_flags; |
| version = EF_NDS32_ELF_VERSION & e_flags; |
| |
| memset (buf, 0, size); |
| |
| switch (abi) |
| { |
| case E_NDS_ABI_V0: |
| case E_NDS_ABI_V1: |
| case E_NDS_ABI_V2: |
| case E_NDS_ABI_V2FP: |
| case E_NDS_ABI_AABI: |
| case E_NDS_ABI_V2FP_PLUS: |
| /* In case there are holes in the array. */ |
| r += snprintf (buf + r, size - r, ", %s", ABI_STRINGS[abi >> EF_NDS_ABI_SHIFT]); |
| break; |
| |
| default: |
| r += snprintf (buf + r, size - r, ", <unrecognized ABI>"); |
| break; |
| } |
| |
| switch (version) |
| { |
| case E_NDS32_ELF_VER_1_2: |
| case E_NDS32_ELF_VER_1_3: |
| case E_NDS32_ELF_VER_1_4: |
| r += snprintf (buf + r, size - r, ", %s", VER_STRINGS[version >> EF_NDS32_ELF_VERSION_SHIFT]); |
| break; |
| |
| default: |
| r += snprintf (buf + r, size - r, ", <unrecognized ELF version number>"); |
| break; |
| } |
| |
| if (E_NDS_ABI_V0 == abi) |
| { |
| /* OLD ABI; only used in N1213HC, has performance extension 1. */ |
| r += snprintf (buf + r, size - r, ", Andes Star v1.0, N1213HC, MAC, PERF1"); |
| if (arch == E_NDS_ARCH_STAR_V1_0) |
| r += snprintf (buf + r, size -r, ", 16b"); /* has 16-bit instructions */ |
| return; |
| } |
| |
| switch (arch) |
| { |
| case E_NDS_ARCH_STAR_V1_0: |
| case E_NDS_ARCH_STAR_V2_0: |
| case E_NDS_ARCH_STAR_V3_0: |
| case E_NDS_ARCH_STAR_V3_M: |
| r += snprintf (buf + r, size - r, ", %s", ARCH_STRINGS[arch >> EF_NDS_ARCH_SHIFT]); |
| break; |
| |
| default: |
| r += snprintf (buf + r, size - r, ", <unrecognized architecture>"); |
| /* ARCH version determines how the e_flags are interpreted. |
| If it is unknown, we cannot proceed. */ |
| return; |
| } |
| |
| /* Newer ABI; Now handle architecture specific flags. */ |
| if (arch == E_NDS_ARCH_STAR_V1_0) |
| { |
| if (config & E_NDS32_HAS_MFUSR_PC_INST) |
| r += snprintf (buf + r, size -r, ", MFUSR_PC"); |
| |
| if (!(config & E_NDS32_HAS_NO_MAC_INST)) |
| r += snprintf (buf + r, size -r, ", MAC"); |
| |
| if (config & E_NDS32_HAS_DIV_INST) |
| r += snprintf (buf + r, size -r, ", DIV"); |
| |
| if (config & E_NDS32_HAS_16BIT_INST) |
| r += snprintf (buf + r, size -r, ", 16b"); |
| } |
| else |
| { |
| if (config & E_NDS32_HAS_MFUSR_PC_INST) |
| { |
| if (version <= E_NDS32_ELF_VER_1_3) |
| r += snprintf (buf + r, size -r, ", [B8]"); |
| else |
| r += snprintf (buf + r, size -r, ", EX9"); |
| } |
| |
| if (config & E_NDS32_HAS_MAC_DX_INST) |
| r += snprintf (buf + r, size -r, ", MAC_DX"); |
| |
| if (config & E_NDS32_HAS_DIV_DX_INST) |
| r += snprintf (buf + r, size -r, ", DIV_DX"); |
| |
| if (config & E_NDS32_HAS_16BIT_INST) |
| { |
| if (version <= E_NDS32_ELF_VER_1_3) |
| r += snprintf (buf + r, size -r, ", 16b"); |
| else |
| r += snprintf (buf + r, size -r, ", IFC"); |
| } |
| } |
| |
| if (config & E_NDS32_HAS_EXT_INST) |
| r += snprintf (buf + r, size -r, ", PERF1"); |
| |
| if (config & E_NDS32_HAS_EXT2_INST) |
| r += snprintf (buf + r, size -r, ", PERF2"); |
| |
| if (config & E_NDS32_HAS_FPU_INST) |
| { |
| has_fpu = 1; |
| r += snprintf (buf + r, size -r, ", FPU_SP"); |
| } |
| |
| if (config & E_NDS32_HAS_FPU_DP_INST) |
| { |
| has_fpu = 1; |
| r += snprintf (buf + r, size -r, ", FPU_DP"); |
| } |
| |
| if (config & E_NDS32_HAS_FPU_MAC_INST) |
| { |
| has_fpu = 1; |
| r += snprintf (buf + r, size -r, ", FPU_MAC"); |
| } |
| |
| if (has_fpu) |
| { |
| switch ((config & E_NDS32_FPU_REG_CONF) >> E_NDS32_FPU_REG_CONF_SHIFT) |
| { |
| case E_NDS32_FPU_REG_8SP_4DP: |
| r += snprintf (buf + r, size -r, ", FPU_REG:8/4"); |
| break; |
| case E_NDS32_FPU_REG_16SP_8DP: |
| r += snprintf (buf + r, size -r, ", FPU_REG:16/8"); |
| break; |
| case E_NDS32_FPU_REG_32SP_16DP: |
| r += snprintf (buf + r, size -r, ", FPU_REG:32/16"); |
| break; |
| case E_NDS32_FPU_REG_32SP_32DP: |
| r += snprintf (buf + r, size -r, ", FPU_REG:32/32"); |
| break; |
| } |
| } |
| |
| if (config & E_NDS32_HAS_AUDIO_INST) |
| r += snprintf (buf + r, size -r, ", AUDIO"); |
| |
| if (config & E_NDS32_HAS_STRING_INST) |
| r += snprintf (buf + r, size -r, ", STR"); |
| |
| if (config & E_NDS32_HAS_REDUCED_REGS) |
| r += snprintf (buf + r, size -r, ", 16REG"); |
| |
| if (config & E_NDS32_HAS_VIDEO_INST) |
| { |
| if (version <= E_NDS32_ELF_VER_1_3) |
| r += snprintf (buf + r, size -r, ", VIDEO"); |
| else |
| r += snprintf (buf + r, size -r, ", SATURATION"); |
| } |
| |
| if (config & E_NDS32_HAS_ENCRIPT_INST) |
| r += snprintf (buf + r, size -r, ", ENCRP"); |
| |
| if (config & E_NDS32_HAS_L2C_INST) |
| r += snprintf (buf + r, size -r, ", L2C"); |
| } |
| |
| static char * |
| get_machine_flags (unsigned e_flags, unsigned e_machine) |
| { |
| static char buf[1024]; |
| |
| buf[0] = '\0'; |
| |
| if (e_flags) |
| { |
| switch (e_machine) |
| { |
| default: |
| break; |
| |
| case EM_ARC_COMPACT2: |
| case EM_ARC_COMPACT: |
| decode_ARC_machine_flags (e_flags, e_machine, buf); |
| break; |
| |
| case EM_ARM: |
| decode_ARM_machine_flags (e_flags, buf); |
| break; |
| |
| case EM_AVR: |
| decode_AVR_machine_flags (e_flags, buf, sizeof buf); |
| break; |
| |
| case EM_BLACKFIN: |
| if (e_flags & EF_BFIN_PIC) |
| strcat (buf, ", PIC"); |
| |
| if (e_flags & EF_BFIN_FDPIC) |
| strcat (buf, ", FDPIC"); |
| |
| if (e_flags & EF_BFIN_CODE_IN_L1) |
| strcat (buf, ", code in L1"); |
| |
| if (e_flags & EF_BFIN_DATA_IN_L1) |
| strcat (buf, ", data in L1"); |
| |
| break; |
| |
| case EM_CYGNUS_FRV: |
| switch (e_flags & EF_FRV_CPU_MASK) |
| { |
| case EF_FRV_CPU_GENERIC: |
| break; |
| |
| default: |
| strcat (buf, ", fr???"); |
| break; |
| |
| case EF_FRV_CPU_FR300: |
| strcat (buf, ", fr300"); |
| break; |
| |
| case EF_FRV_CPU_FR400: |
| strcat (buf, ", fr400"); |
| break; |
| case EF_FRV_CPU_FR405: |
| strcat (buf, ", fr405"); |
| break; |
| |
| case EF_FRV_CPU_FR450: |
| strcat (buf, ", fr450"); |
| break; |
| |
| case EF_FRV_CPU_FR500: |
| strcat (buf, ", fr500"); |
| break; |
| case EF_FRV_CPU_FR550: |
| strcat (buf, ", fr550"); |
| break; |
| |
| case EF_FRV_CPU_SIMPLE: |
| strcat (buf, ", simple"); |
| break; |
| case EF_FRV_CPU_TOMCAT: |
| strcat (buf, ", tomcat"); |
| break; |
| } |
| break; |
| |
| case EM_68K: |
| if ((e_flags & EF_M68K_ARCH_MASK) == EF_M68K_M68000) |
| strcat (buf, ", m68000"); |
| else if ((e_flags & EF_M68K_ARCH_MASK) == EF_M68K_CPU32) |
| strcat (buf, ", cpu32"); |
| else if ((e_flags & EF_M68K_ARCH_MASK) == EF_M68K_FIDO) |
| strcat (buf, ", fido_a"); |
| else |
| { |
| char const * isa = _("unknown"); |
| char const * mac = _("unknown mac"); |
| char const * additional = NULL; |
| |
| switch (e_flags & EF_M68K_CF_ISA_MASK) |
| { |
| case EF_M68K_CF_ISA_A_NODIV: |
| isa = "A"; |
| additional = ", nodiv"; |
| break; |
| case EF_M68K_CF_ISA_A: |
| isa = "A"; |
| break; |
| case EF_M68K_CF_ISA_A_PLUS: |
| isa = "A+"; |
| break; |
| case EF_M68K_CF_ISA_B_NOUSP: |
| isa = "B"; |
| additional = ", nousp"; |
| break; |
| case EF_M68K_CF_ISA_B: |
| isa = "B"; |
| break; |
| case EF_M68K_CF_ISA_C: |
| isa = "C"; |
| break; |
| case EF_M68K_CF_ISA_C_NODIV: |
| isa = "C"; |
| additional = ", nodiv"; |
| break; |
| } |
| strcat (buf, ", cf, isa "); |
| strcat (buf, isa); |
| if (additional) |
| strcat (buf, additional); |
| if (e_flags & EF_M68K_CF_FLOAT) |
| strcat (buf, ", float"); |
| switch (e_flags & EF_M68K_CF_MAC_MASK) |
| { |
| case 0: |
| mac = NULL; |
| break; |
| case EF_M68K_CF_MAC: |
| mac = "mac"; |
| break; |
| case EF_M68K_CF_EMAC: |
| mac = "emac"; |
| break; |
| case EF_M68K_CF_EMAC_B: |
| mac = "emac_b"; |
| break; |
| } |
| if (mac) |
| { |
| strcat (buf, ", "); |
| strcat (buf, mac); |
| } |
| |