X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=binutils%2Freadelf.c;h=bd76242d15a1775c005987c3508f613ea69a2eef;hb=0520666f7582ab3511dc0be50fbc5232971f7933;hp=424624e0e4d705bb494edb0123c6f3994be21fd0;hpb=61dd8e19a8b43037125d4a767f27e98e9181521b;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/readelf.c b/binutils/readelf.c index 424624e0e4..bd76242d15 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -1,5 +1,6 @@ /* readelf.c -- display contents of an ELF format file Copyright (C) 1998-2019 Free Software Foundation, Inc. + Copyright (C) 2019 Advanced Micro Devices, Inc. All rights reserved. Originally developed by Eric Youngdale Modifications by Nick Clifton @@ -60,6 +61,7 @@ #include "bucomm.h" #include "elfcomm.h" #include "dwarf.h" +#include "ctf-api.h" #include "elf/common.h" #include "elf/external.h" @@ -91,6 +93,7 @@ #include "elf/aarch64.h" #include "elf/alpha.h" +#include "elf/amdgcn.h" #include "elf/arc.h" #include "elf/arm.h" #include "elf/avr.h" @@ -183,6 +186,7 @@ typedef struct elf_section_list #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. */ +#define CTF_DUMP (1 << 5) /* The --ctf command line switch. */ typedef unsigned char dump_type; @@ -230,6 +234,7 @@ 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 dynamic_info_DT_MIPS_XHASH; static bfd_vma version_info[16]; static Elf_Internal_Dyn * dynamic_section; static elf_section_list * symtab_shndx_list; @@ -249,12 +254,17 @@ static bfd_boolean do_dump = FALSE; static bfd_boolean do_version = FALSE; static bfd_boolean do_histogram = FALSE; static bfd_boolean do_debugging = FALSE; +static bfd_boolean do_ctf = FALSE; static bfd_boolean do_arch = FALSE; static bfd_boolean do_notes = FALSE; static bfd_boolean do_archive_index = FALSE; static bfd_boolean is_32bit_elf = FALSE; static bfd_boolean decompress_dumps = FALSE; +static char *dump_ctf_parent_name; +static char *dump_ctf_symtab_name; +static char *dump_ctf_strtab_name; + struct group_list { struct group_list * next; @@ -328,6 +338,10 @@ static const char * get_symbol_version_string (ADDR) &= ~1; \ } \ while (0) + +/* Get the correct GNU hash section name. */ +#define GNU_HASH_SECTION_NAME \ + dynamic_info_DT_MIPS_XHASH ? ".MIPS.xhash" : ".gnu.hash" /* Print a BFD_VMA to an internal buffer, for use in error messages. BFD_FMA_FMT can't be used in translated strings. */ @@ -378,9 +392,9 @@ get_data (void * var, /* 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 ((size_t) size != size + || (size_t) nmemb != nmemb + || (size_t) amt != amt) { if (reason) error (_("Size truncation prevents reading %s" @@ -390,7 +404,7 @@ get_data (void * var, } /* Check for size overflow. */ - if (amt < nmemb) + if (amt / size != nmemb || (size_t) amt + 1 == 0) { if (reason) error (_("Size overflow prevents reading %s" @@ -422,10 +436,8 @@ get_data (void * var, 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); + /* + 1 so that we can '\0' terminate invalid string table sections. */ + mvar = malloc ((size_t) amt + 1); if (mvar == NULL) { @@ -739,17 +751,6 @@ find_section_in_set (Filedata * filedata, const char * name, unsigned int * set) return find_section (filedata, name); } -/* Read an unsigned LEB128 encoded value from DATA. - Set *LENGTH_RETURN 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. */ @@ -1587,6 +1588,10 @@ dump_relocations (Filedata * filedata, else rtype = elf_nfp_reloc_type (type); break; + + case EM_AMDGPU: + rtype = elf_amdgcn_reloc_type (type); + break; } if (rtype == NULL) @@ -1867,6 +1872,7 @@ get_mips_dynamic_type (unsigned long type) case DT_MIPS_AUX_DYNAMIC: return "MIPS_AUX_DYNAMIC"; case DT_MIPS_PLTGOT: return "MIPS_PLTGOT"; case DT_MIPS_RWPLT: return "MIPS_RWPLT"; + case DT_MIPS_XHASH: return "MIPS_XHASH"; default: return NULL; } @@ -2405,7 +2411,7 @@ get_machine_name (unsigned e_machine) case EM_TPC: return "Tenor Network TPC processor"; case EM_SNP1K: return "Trebia SNP 1000 processor"; /* 100 */ - case EM_ST200: return "STMicroelectronics ST200 microcontroller"; + case EM_ST200: return "STMicroelectronics ST200 microcontroller"; case EM_IP2K_OLD: case EM_IP2K: return "Ubicom IP2xxx 8-bit microcontrollers"; case EM_MAX: return "MAX Processor"; @@ -2521,7 +2527,7 @@ get_machine_name (unsigned e_machine) case EM_MT: return "Morpho Techologies MT processor"; case EM_ALPHA: return "Alpha"; case EM_WEBASSEMBLY: return "Web Assembly"; - case EM_DLX: return "OpenDLX"; + case EM_DLX: return "OpenDLX"; case EM_XSTORMY16: return "Sanyo XStormy16 CPU core"; case EM_IQ2000: return "Vitesse IQ2000"; case EM_M32C_OLD: @@ -3248,6 +3254,27 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine) } break; + case EM_AMDGPU: + switch (e_flags & EF_AMDGPU_MACH) + { + case EF_AMDGPU_MACH_AMDGCN_GFX801 : strcat (buf, ", gfx801"); break; + case EF_AMDGPU_MACH_AMDGCN_GFX802 : strcat (buf, ", gfx802"); break; + case EF_AMDGPU_MACH_AMDGCN_GFX803 : strcat (buf, ", gfx803"); break; + case EF_AMDGPU_MACH_AMDGCN_GFX810 : strcat (buf, ", gfx810"); break; + case EF_AMDGPU_MACH_AMDGCN_GFX900 : strcat (buf, ", gfx900"); break; + case EF_AMDGPU_MACH_AMDGCN_GFX902 : strcat (buf, ", gfx902"); break; + case EF_AMDGPU_MACH_AMDGCN_GFX904 : strcat (buf, ", gfx904"); break; + case EF_AMDGPU_MACH_AMDGCN_GFX906 : strcat (buf, ", gfx906"); break; + case EF_AMDGPU_MACH_AMDGCN_GFX908 : strcat (buf, ", gfx908"); break; + case EF_AMDGPU_MACH_AMDGCN_GFX909 : strcat (buf, ", gfx909"); break; + default: strcat (buf, _(", ")); break; + } + + if (e_flags & ~ EF_AMDGPU_MACH) + sprintf (buf + strlen (buf), _(", unknown flags bits: %#x"), + e_flags & ~ EF_AMDGPU_MACH); + break; + case EM_CYGNUS_MEP: switch (e_flags & EF_MEP_CPU_MASK) { @@ -3785,6 +3812,15 @@ get_osabi_name (Filedata * filedata, unsigned int osabi) if (osabi >= 64) switch (filedata->file_header.e_machine) { + case EM_AMDGPU: + switch (osabi) + { + case ELFOSABI_AMDGPU_HSA: return "AMD HSA Runtime"; + default: + break; + } + break; + case EM_ARM: switch (osabi) { @@ -3872,22 +3908,6 @@ get_parisc_segment_type (unsigned long type) { switch (type) { - case PT_HP_TLS: return "HP_TLS"; - case PT_HP_CORE_NONE: return "HP_CORE_NONE"; - case PT_HP_CORE_VERSION: return "HP_CORE_VERSION"; - case PT_HP_CORE_KERNEL: return "HP_CORE_KERNEL"; - case PT_HP_CORE_COMM: return "HP_CORE_COMM"; - case PT_HP_CORE_PROC: return "HP_CORE_PROC"; - case PT_HP_CORE_LOADABLE: return "HP_CORE_LOADABLE"; - case PT_HP_CORE_STACK: return "HP_CORE_STACK"; - case PT_HP_CORE_SHM: return "HP_CORE_SHM"; - case PT_HP_CORE_MMF: return "HP_CORE_MMF"; - case PT_HP_PARALLEL: return "HP_PARALLEL"; - case PT_HP_FASTBIND: return "HP_FASTBIND"; - case PT_HP_OPT_ANNOT: return "HP_OPT_ANNOT"; - case PT_HP_HSL_ANNOT: return "HP_HSL_ANNOT"; - case PT_HP_STACK: return "HP_STACK"; - case PT_HP_CORE_UTSNAME: return "HP_CORE_UTSNAME"; case PT_PARISC_ARCHEXT: return "PARISC_ARCHEXT"; case PT_PARISC_UNWIND: return "PARISC_UNWIND"; case PT_PARISC_WEAKORDER: return "PARISC_WEAKORDER"; @@ -3902,10 +3922,6 @@ get_ia64_segment_type (unsigned long type) { case PT_IA_64_ARCHEXT: return "IA_64_ARCHEXT"; case PT_IA_64_UNWIND: return "IA_64_UNWIND"; - case PT_HP_TLS: return "HP_TLS"; - case PT_IA_64_HP_OPT_ANOT: return "HP_OPT_ANNOT"; - case PT_IA_64_HP_HSL_ANOT: return "HP_HSL_ANNOT"; - case PT_IA_64_HP_STACK: return "HP_STACK"; default: return NULL; } } @@ -3920,6 +3936,44 @@ get_tic6x_segment_type (unsigned long type) } } +static const char * +get_hpux_segment_type (unsigned long type, unsigned e_machine) +{ + if (e_machine == EM_PARISC) + switch (type) + { + case PT_HP_TLS: return "HP_TLS"; + case PT_HP_CORE_NONE: return "HP_CORE_NONE"; + case PT_HP_CORE_VERSION: return "HP_CORE_VERSION"; + case PT_HP_CORE_KERNEL: return "HP_CORE_KERNEL"; + case PT_HP_CORE_COMM: return "HP_CORE_COMM"; + case PT_HP_CORE_PROC: return "HP_CORE_PROC"; + case PT_HP_CORE_LOADABLE: return "HP_CORE_LOADABLE"; + case PT_HP_CORE_STACK: return "HP_CORE_STACK"; + case PT_HP_CORE_SHM: return "HP_CORE_SHM"; + case PT_HP_CORE_MMF: return "HP_CORE_MMF"; + case PT_HP_PARALLEL: return "HP_PARALLEL"; + case PT_HP_FASTBIND: return "HP_FASTBIND"; + case PT_HP_OPT_ANNOT: return "HP_OPT_ANNOT"; + case PT_HP_HSL_ANNOT: return "HP_HSL_ANNOT"; + case PT_HP_STACK: return "HP_STACK"; + case PT_HP_CORE_UTSNAME: return "HP_CORE_UTSNAME"; + default: return NULL; + } + + if (e_machine == EM_IA_64) + switch (type) + { + case PT_HP_TLS: return "HP_TLS"; + case PT_IA_64_HP_OPT_ANOT: return "HP_OPT_ANNOT"; + case PT_IA_64_HP_HSL_ANOT: return "HP_HSL_ANNOT"; + case PT_IA_64_HP_STACK: return "HP_STACK"; + default: return NULL; + } + + return NULL; +} + static const char * get_solaris_segment_type (unsigned long type) { @@ -3958,12 +4012,7 @@ get_segment_type (Filedata * filedata, unsigned long p_type) case PT_GNU_PROPERTY: return "GNU_PROPERTY"; default: - if (p_type >= PT_GNU_MBIND_LO && p_type <= PT_GNU_MBIND_HI) - { - sprintf (buff, "GNU_MBIND+%#lx", - p_type - PT_GNU_MBIND_LO); - } - else if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC)) + if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC)) { const char * result; @@ -4004,24 +4053,28 @@ get_segment_type (Filedata * filedata, unsigned long p_type) } else if ((p_type >= PT_LOOS) && (p_type <= PT_HIOS)) { - const char * result; + const char * result = NULL; - switch (filedata->file_header.e_machine) + switch (filedata->file_header.e_ident[EI_OSABI]) { - case EM_PARISC: - result = get_parisc_segment_type (p_type); + case ELFOSABI_GNU: + case ELFOSABI_FREEBSD: + if (p_type >= PT_GNU_MBIND_LO && p_type <= PT_GNU_MBIND_HI) + { + sprintf (buff, "GNU_MBIND+%#lx", p_type - PT_GNU_MBIND_LO); + result = buff; + } break; - case EM_IA_64: - result = get_ia64_segment_type (p_type); + case ELFOSABI_HPUX: + result = get_hpux_segment_type (p_type, + filedata->file_header.e_machine); + break; + case ELFOSABI_SOLARIS: + result = get_solaris_segment_type (p_type); break; default: - if (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS) - result = get_solaris_segment_type (p_type); - else - result = NULL; break; } - if (result != NULL) return result; @@ -4091,6 +4144,7 @@ get_mips_section_type_name (unsigned int sh_type) case SHT_MIPS_XLATE_OLD: return "MIPS_XLATE_OLD"; case SHT_MIPS_PDR_EXCEPTION: return "MIPS_PDR_EXCEPTION"; case SHT_MIPS_ABIFLAGS: return "MIPS_ABIFLAGS"; + case SHT_MIPS_XHASH: return "MIPS_XHASH"; default: break; } @@ -4394,6 +4448,10 @@ get_section_type_name (Filedata * filedata, unsigned int sh_type) #define OPTION_DWARF_DEPTH 514 #define OPTION_DWARF_START 515 #define OPTION_DWARF_CHECK 516 +#define OPTION_CTF_DUMP 517 +#define OPTION_CTF_PARENT 518 +#define OPTION_CTF_SYMBOLS 519 +#define OPTION_CTF_STRINGS 520 static struct option options[] = { @@ -4432,6 +4490,12 @@ static struct option options[] = {"dwarf-start", required_argument, 0, OPTION_DWARF_START}, {"dwarf-check", no_argument, 0, OPTION_DWARF_CHECK}, + {"ctf", required_argument, 0, OPTION_CTF_DUMP}, + + {"ctf-symbols", required_argument, 0, OPTION_CTF_SYMBOLS}, + {"ctf-strings", required_argument, 0, OPTION_CTF_STRINGS}, + {"ctf-parent", required_argument, 0, OPTION_CTF_PARENT}, + {"version", no_argument, 0, 'v'}, {"wide", no_argument, 0, 'W'}, {"help", no_argument, 0, 'H'}, @@ -4481,6 +4545,15 @@ usage (FILE * stream) --dwarf-depth=N Do not display DIEs at depth N or greater\n\ --dwarf-start=N Display DIEs starting with N, at the same depth\n\ or deeper\n")); + fprintf (stream, _("\ + --ctf= Display CTF info from section \n\ + --ctf-parent=\n\ + Use section as the CTF parent\n\n\ + --ctf-symbols=\n\ + Use section as the CTF external symtab\n\n\ + --ctf-strings=\n\ + Use section as the CTF external strtab\n\n")); + #ifdef SUPPORT_DISASSEMBLY fprintf (stream, _("\ -i --instruction-dump=\n\ @@ -4708,6 +4781,19 @@ parse_args (Filedata * filedata, int argc, char ** argv) case OPTION_DWARF_CHECK: dwarf_check = TRUE; break; + case OPTION_CTF_DUMP: + do_ctf = TRUE; + request_dump (filedata, CTF_DUMP); + break; + case OPTION_CTF_SYMBOLS: + dump_ctf_symtab_name = strdup (optarg); + break; + case OPTION_CTF_STRINGS: + dump_ctf_strtab_name = strdup (optarg); + break; + case OPTION_CTF_PARENT: + dump_ctf_parent_name = strdup (optarg); + break; case OPTION_DYN_SYMS: do_dyn_syms = TRUE; break; @@ -4791,7 +4877,7 @@ process_file_header (Filedata * filedata) return FALSE; } - init_dwarf_regnames (header->e_machine); + init_dwarf_regnames_by_elf_machine_code (header->e_machine); if (do_header) { @@ -5040,6 +5126,9 @@ process_program_headers (Filedata * filedata) unsigned int i; Elf_Internal_Phdr * previous_load = NULL; + dynamic_addr = 0; + dynamic_size = 0; + if (filedata->file_header.e_phnum == 0) { /* PR binutils/12467. */ @@ -5090,9 +5179,6 @@ process_program_headers (Filedata * filedata) } } - dynamic_addr = 0; - dynamic_size = 0; - for (i = 0, segment = filedata->program_headers; i < filedata->file_header.e_phnum; i++, segment++) @@ -5201,11 +5287,17 @@ process_program_headers (Filedata * filedata) unsigned int j; for (j = 1; j < filedata->file_header.e_phnum; j++) - if (filedata->program_headers[j].p_vaddr <= segment->p_vaddr - && (filedata->program_headers[j].p_vaddr - + filedata->program_headers[j].p_memsz) - >= (segment->p_vaddr + segment->p_filesz)) - break; + { + Elf_Internal_Phdr *load = filedata->program_headers + j; + if (load->p_type == PT_LOAD + && load->p_offset <= segment->p_offset + && (load->p_offset + load->p_filesz + >= segment->p_offset + segment->p_filesz) + && load->p_vaddr <= segment->p_vaddr + && (load->p_vaddr + load->p_filesz + >= segment->p_vaddr + segment->p_filesz)) + break; + } if (j == filedata->file_header.e_phnum) error (_("the PHDR segment is not covered by a LOAD segment\n")); } @@ -7359,11 +7451,6 @@ struct absaddr bfd_vma offset; }; -#define ABSADDR(a) \ - ((a).section \ - ? filedata->section_headers [(a).section].sh_addr + (a).offset \ - : (a).offset) - /* Find the nearest symbol at or below ADDR. Returns the symbol name, if found, and the offset from the symbol to ADDR. */ @@ -7509,8 +7596,22 @@ dump_ia64_unwind (Filedata * filedata, struct ia64_unw_aux_info * aux) if (aux->info == NULL) continue; + offset = tp->info.offset; + if (tp->info.section) + { + if (tp->info.section >= filedata->file_header.e_shnum) + { + warn (_("Invalid section %u in table entry %ld\n"), + tp->info.section, (long) (tp - aux->table)); + res = FALSE; + continue; + } + offset += filedata->section_headers[tp->info.section].sh_addr; + } + offset -= aux->info_addr; /* PR 17531: file: 0997b4d1. */ - if ((ABSADDR (tp->info) - aux->info_addr) >= aux->info_size) + if (offset >= aux->info_size + || aux->info_size - offset < 8) { warn (_("Invalid offset %lx in table entry %ld\n"), (long) tp->info.offset, (long) (tp - aux->table)); @@ -7518,7 +7619,7 @@ dump_ia64_unwind (Filedata * filedata, struct ia64_unw_aux_info * aux) continue; } - head = aux->info + (ABSADDR (tp->info) - aux->info_addr); + head = aux->info + offset; stamp = byte_get ((unsigned char *) head, sizeof (stamp)); printf (" v%u, flags=0x%lx (%s%s), len=%lu bytes\n", @@ -8706,7 +8807,7 @@ decode_arm_unwind_bytecode (Filedata * filedata, } else { - offset = read_uleb128 (buf, &len, buf + i + 1); + offset = read_leb128 (buf, buf + i + 1, FALSE, &len, NULL); assert (len == i + 1); offset = offset * 4 + 0x204; printf ("vsp = vsp + %ld", offset); @@ -8925,7 +9026,7 @@ decode_tic6x_unwind_bytecode (Filedata * filedata, return FALSE; } - offset = read_uleb128 (buf, &len, buf + i + 1); + offset = read_leb128 (buf, buf + i + 1, FALSE, &len, NULL); assert (len == i + 1); offset = offset * 8 + 0x408; printf (_("sp = sp + %ld"), offset); @@ -8990,6 +9091,11 @@ decode_arm_unwind (Filedata * filedata, remaining = 4; } + else + { + addr.section = SHN_UNDEF; + addr.offset = 0; + } if ((word & 0x80000000) == 0) { @@ -9457,6 +9563,11 @@ dynamic_section_mips_val (Elf_Internal_Dyn * entry) print_vma (entry->d_un.d_val, DEC); break; + case DT_MIPS_XHASH: + dynamic_info_DT_MIPS_XHASH = entry->d_un.d_val; + dynamic_info_DT_GNU_HASH = entry->d_un.d_val; + /* Falls through. */ + default: print_vma (entry->d_un.d_ptr, PREFIX_HEX); } @@ -10495,7 +10606,7 @@ process_version_sections (Filedata * filedata) printable_section_name (filedata, section), section->sh_info); - printf (_(" Addr: 0x")); + printf (_(" Addr: 0x")); printf_vma (section->sh_addr); printf (_(" Offset: %#08lx Link: %u (%s)\n"), (unsigned long) section->sh_offset, section->sh_link, @@ -10787,7 +10898,7 @@ process_version_sections (Filedata * filedata) total), printable_section_name (filedata, section), (unsigned long) total); - printf (_(" Addr: ")); + printf (_(" Addr: 0x")); printf_vma (section->sh_addr); printf (_(" Offset: %#08lx Link: %u (%s)\n"), (unsigned long) section->sh_offset, section->sh_link, @@ -11008,9 +11119,7 @@ get_symbol_binding (Filedata * filedata, unsigned int binding) else if (binding >= STB_LOOS && binding <= STB_HIOS) { if (binding == STB_GNU_UNIQUE - && (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_GNU - /* GNU is still using the default value 0. */ - || filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_NONE)) + && filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_GNU) return "UNIQUE"; snprintf (buff, sizeof (buff), _(": %d"), binding); } @@ -11062,9 +11171,7 @@ get_symbol_type (Filedata * filedata, unsigned int type) if (type == STT_GNU_IFUNC && (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_GNU - || filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_FREEBSD - /* GNU is still using the default value 0. */ - || filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_NONE)) + || filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_FREEBSD)) return "IFUNC"; snprintf (buff, sizeof (buff), _(": %d"), type); @@ -11090,6 +11197,19 @@ get_symbol_visibility (unsigned int visibility) } } +static const char * +get_alpha_symbol_other (unsigned int other) +{ + switch (other) + { + case STO_ALPHA_NOPV: return "NOPV"; + case STO_ALPHA_STD_GPLOAD: return "STD GPLOAD"; + default: + error (_("Unrecognized alpah specific other value: %u"), other); + return _(""); + } +} + static const char * get_solaris_symbol_visibility (unsigned int visibility) { @@ -11229,6 +11349,9 @@ get_symbol_other (Filedata * filedata, unsigned int other) switch (filedata->file_header.e_machine) { + case EM_ALPHA: + result = get_alpha_symbol_other (other); + break; case EM_AARCH64: result = get_aarch64_symbol_other (other); break; @@ -11436,6 +11559,7 @@ get_symbol_version_string (Filedata * filedata, if ((vers_data & VERSYM_HIDDEN) == 0 && vers_data == 0) return NULL; + *sym_info = (vers_data & VERSYM_HIDDEN) != 0 ? symbol_hidden : symbol_public; max_vd_ndx = 0; /* Usually we'd only see verdef for defined symbols, and verneed for @@ -11489,7 +11613,7 @@ get_symbol_version_string (Filedata * filedata, if (ivd.vd_ndx == (vers_data & VERSYM_VERSION)) { - if (ivd.vd_ndx == 1 && ivd.vd_flags == VER_FLG_BASE) + if (ivd.vd_ndx == 1 && ivd.vd_flags == VER_FLG_BASE) return NULL; off -= ivd.vd_next; @@ -11501,12 +11625,8 @@ get_symbol_version_string (Filedata * filedata, ivda.vda_name = BYTE_GET (evda.vda_name); if (psym->st_name != ivda.vda_name) - { - *sym_info = ((vers_data & VERSYM_HIDDEN) != 0 - ? symbol_hidden : symbol_public); - return (ivda.vda_name < strtab_size - ? strtab + ivda.vda_name : _("")); - } + return (ivda.vda_name < strtab_size + ? strtab + ivda.vda_name : _("")); } } } @@ -11593,6 +11713,7 @@ process_symbol_table (Filedata * filedata) bfd_vma ngnubuckets = 0; bfd_vma * gnubuckets = NULL; bfd_vma * gnuchains = NULL; + bfd_vma * mipsxlat = NULL; bfd_vma gnusymidx = 0; bfd_size_type ngnuchains = 0; @@ -11758,7 +11879,31 @@ process_symbol_table (Filedata * filedata) gnuchains = get_dynamic_data (filedata, maxchain, 4); ngnuchains = maxchain; + if (gnuchains == NULL) + goto no_gnu_hash; + + if (dynamic_info_DT_MIPS_XHASH) + { + if (fseek (filedata->handle, + (archive_file_offset + + offset_from_vma (filedata, (buckets_vma + + 4 * (ngnubuckets + + maxchain)), 4)), + SEEK_SET)) + { + error (_("Unable to seek to start of dynamic information\n")); + goto no_gnu_hash; + } + + mipsxlat = get_dynamic_data (filedata, maxchain, 4); + } + no_gnu_hash: + if (dynamic_info_DT_MIPS_XHASH && mipsxlat == NULL) + { + free (gnuchains); + gnuchains = NULL; + } if (gnuchains == NULL) { free (gnubuckets); @@ -11808,7 +11953,8 @@ process_symbol_table (Filedata * filedata) if (dynamic_info_DT_GNU_HASH) { - printf (_("\nSymbol table of `.gnu.hash' for image:\n")); + printf (_("\nSymbol table of `%s' for image:\n"), + GNU_HASH_SECTION_NAME); if (is_32bit_elf) printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n")); else @@ -11822,7 +11968,10 @@ process_symbol_table (Filedata * filedata) do { - print_dynamic_symbol (filedata, si, hn); + if (dynamic_info_DT_MIPS_XHASH) + print_dynamic_symbol (filedata, mipsxlat[off], hn); + else + print_dynamic_symbol (filedata, si, hn); si++; } while (off < ngnuchains && (gnuchains[off++] & 1) == 0); @@ -12045,11 +12194,12 @@ process_symbol_table (Filedata * filedata) unsigned long nzero_counts = 0; unsigned long nsyms = 0; - printf (ngettext ("\nHistogram for `.gnu.hash' bucket list length " + printf (ngettext ("\nHistogram for `%s' bucket list length " "(total of %lu bucket):\n", - "\nHistogram for `.gnu.hash' bucket list length " + "\nHistogram for `%s' bucket list length " "(total of %lu buckets):\n", (unsigned long) ngnubuckets), + GNU_HASH_SECTION_NAME, (unsigned long) ngnubuckets); lengths = (unsigned long *) calloc (ngnubuckets, sizeof (*lengths)); @@ -12106,6 +12256,7 @@ process_symbol_table (Filedata * filedata) free (lengths); free (gnubuckets); free (gnuchains); + free (mipsxlat); } return TRUE; @@ -12183,8 +12334,12 @@ process_syminfo (Filedata * filedata ATTRIBUTE_UNUSED) return TRUE; } -#define IN_RANGE(START,END,ADDR,OFF) \ - (((ADDR) >= (START)) && ((ADDR) + (OFF) < (END))) +/* A macro which evaluates to TRUE if the region ADDR .. ADDR + NELEM + is contained by the region START .. END. The types of ADDR, START + and END should all be the same. Note both ADDR + NELEM and END + point to just beyond the end of the regions that are being tested. */ +#define IN_RANGE(START,END,ADDR,NELEM) \ + (((ADDR) >= (START)) && ((ADDR) < (END)) && ((ADDR) + (NELEM) <= (END))) /* Check to see if the given reloc needs to be handled in a target specific manner. If so then process the reloc and return TRUE otherwise return @@ -12538,7 +12693,7 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) case EM_OR1K: return reloc_type == 1; /* R_OR1K_32. */ case EM_PARISC: - return (reloc_type == 1 /* R_PARISC_DIR32. */ + return (reloc_type == 1 /* R_PARISC_DIR32. */ || reloc_type == 2 /* R_PARISC_DIR21L. */ || reloc_type == 41); /* R_PARISC_SECREL32. */ case EM_PJ: @@ -12678,6 +12833,8 @@ is_32bit_pcrel_reloc (Filedata * filedata, unsigned int reloc_type) case EM_L1OM: case EM_K1OM: return reloc_type == 2; /* R_X86_64_PC32. */ + case EM_VAX: + return reloc_type == 4; /* R_VAX_PCREL32. */ case EM_XTENSA_OLD: case EM_XTENSA: return reloc_type == 14; /* R_XTENSA_32_PCREL. */ @@ -13283,7 +13440,7 @@ apply_relocations (Filedata * filedata, } rloc = start + rp->r_offset; - if ((rloc + reloc_size) > end || (rloc < start)) + if (!IN_RANGE (start, end, rloc, reloc_size)) { warn (_("skipping invalid relocation offset 0x%lx in section %s\n"), (unsigned long) rp->r_offset, @@ -13769,6 +13926,167 @@ dump_section_as_bytes (Elf_Internal_Shdr * section, return TRUE; } +static ctf_sect_t * +shdr_to_ctf_sect (ctf_sect_t *buf, Elf_Internal_Shdr *shdr, Filedata *filedata) +{ + buf->cts_name = SECTION_NAME (shdr); + buf->cts_size = shdr->sh_size; + buf->cts_entsize = shdr->sh_entsize; + + return buf; +} + +/* Formatting callback function passed to ctf_dump. Returns either the pointer + it is passed, or a pointer to newly-allocated storage, in which case + dump_ctf() will free it when it no longer needs it. */ + +static char *dump_ctf_indent_lines (ctf_sect_names_t sect ATTRIBUTE_UNUSED, + char *s, void *arg) +{ + const char *blanks = arg; + char *new_s; + + if (asprintf (&new_s, "%s%s", blanks, s) < 0) + return s; + return new_s; +} + +static bfd_boolean +dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata) +{ + Elf_Internal_Shdr * parent_sec = NULL; + Elf_Internal_Shdr * symtab_sec = NULL; + Elf_Internal_Shdr * strtab_sec = NULL; + void * data = NULL; + void * symdata = NULL; + void * strdata = NULL; + void * parentdata = NULL; + ctf_sect_t ctfsect, symsect, strsect, parentsect; + ctf_sect_t * symsectp = NULL; + ctf_sect_t * strsectp = NULL; + ctf_file_t * ctf = NULL; + ctf_file_t * parent = NULL; + + const char *things[] = {"Header", "Labels", "Data objects", + "Function objects", "Variables", "Types", "Strings", + ""}; + const char **thing; + int err; + bfd_boolean ret = FALSE; + size_t i; + + shdr_to_ctf_sect (&ctfsect, section, filedata); + data = get_section_contents (section, filedata); + ctfsect.cts_data = data; + + if (!dump_ctf_symtab_name) + dump_ctf_symtab_name = strdup (".symtab"); + + if (!dump_ctf_strtab_name) + dump_ctf_strtab_name = strdup (".strtab"); + + if (dump_ctf_symtab_name && dump_ctf_symtab_name[0] != 0) + { + if ((symtab_sec = find_section (filedata, dump_ctf_symtab_name)) == NULL) + { + error (_("No symbol section named %s\n"), dump_ctf_symtab_name); + goto fail; + } + if ((symdata = (void *) get_data (NULL, filedata, + symtab_sec->sh_offset, 1, + symtab_sec->sh_size, + _("symbols"))) == NULL) + goto fail; + symsectp = shdr_to_ctf_sect (&symsect, symtab_sec, filedata); + symsect.cts_data = symdata; + } + if (dump_ctf_strtab_name && dump_ctf_symtab_name[0] != 0) + { + if ((strtab_sec = find_section (filedata, dump_ctf_strtab_name)) == NULL) + { + error (_("No string table section named %s\n"), + dump_ctf_strtab_name); + goto fail; + } + if ((strdata = (void *) get_data (NULL, filedata, + strtab_sec->sh_offset, 1, + strtab_sec->sh_size, + _("strings"))) == NULL) + goto fail; + strsectp = shdr_to_ctf_sect (&strsect, strtab_sec, filedata); + strsect.cts_data = strdata; + } + if (dump_ctf_parent_name) + { + if ((parent_sec = find_section (filedata, dump_ctf_parent_name)) == NULL) + { + error (_("No CTF parent section named %s\n"), dump_ctf_parent_name); + goto fail; + } + if ((parentdata = (void *) get_data (NULL, filedata, + parent_sec->sh_offset, 1, + parent_sec->sh_size, + _("CTF parent"))) == NULL) + goto fail; + shdr_to_ctf_sect (&parentsect, parent_sec, filedata); + parentsect.cts_data = parentdata; + } + + /* Load the CTF file and dump it. */ + + if ((ctf = ctf_bufopen (&ctfsect, symsectp, strsectp, &err)) == NULL) + { + error (_("CTF open failure: %s\n"), ctf_errmsg (err)); + goto fail; + } + + if (parentdata) + { + if ((parent = ctf_bufopen (&parentsect, symsectp, strsectp, &err)) == NULL) + { + error (_("CTF open failure: %s\n"), ctf_errmsg (err)); + goto fail; + } + + ctf_import (ctf, parent); + } + + ret = TRUE; + + printf (_("\nDump of CTF section '%s':\n"), + printable_section_name (filedata, section)); + + for (i = 0, thing = things; *thing[0]; thing++, i++) + { + ctf_dump_state_t *s = NULL; + char *item; + + printf ("\n %s:\n", *thing); + while ((item = ctf_dump (ctf, &s, i, dump_ctf_indent_lines, + (void *) " ")) != NULL) + { + printf ("%s\n", item); + free (item); + } + + if (ctf_errno (ctf)) + { + error (_("Iteration failed: %s, %s\n"), *thing, + ctf_errmsg (ctf_errno (ctf))); + ret = FALSE; + } + } + + fail: + ctf_file_close (ctf); + ctf_file_close (parent); + free (parentdata); + free (data); + free (symdata); + free (strdata); + return ret; +} + static bfd_boolean load_specific_debug_section (enum dwarf_section_display_enum debug, const Elf_Internal_Shdr * sec, @@ -13777,7 +14095,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, struct dwarf_section * section = &debug_displays [debug].section; char buf [64]; Filedata * filedata = (Filedata *) data; - + if (section->start != NULL) { /* If it is already loaded, do nothing. */ @@ -14106,6 +14424,12 @@ process_section_contents (Filedata * filedata) if (! display_debug_section (i, section, filedata)) res = FALSE; } + + if (dump & CTF_DUMP) + { + if (! dump_section_as_ctf (section, filedata)) + res = FALSE; + } } /* Check to see if the user requested a @@ -14193,10 +14517,7 @@ display_tag_value (signed int tag, } else { - unsigned int len; - - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf ("%ld (0x%lx)\n", val, val); } @@ -14211,17 +14532,14 @@ display_arc_attribute (unsigned char * p, const unsigned char * const end) { unsigned int tag; - unsigned int len; unsigned int val; - tag = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (tag, p, end); switch (tag) { case Tag_ARC_PCS_config: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ARC_PCS_config: "); switch (val) { @@ -14247,8 +14565,7 @@ display_arc_attribute (unsigned char * p, break; case Tag_ARC_CPU_base: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ARC_CPU_base: "); switch (val) { @@ -14272,8 +14589,7 @@ display_arc_attribute (unsigned char * p, break; case Tag_ARC_CPU_variation: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ARC_CPU_variation: "); switch (val) { @@ -14296,21 +14612,18 @@ display_arc_attribute (unsigned char * p, break; case Tag_ARC_ABI_rf16: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ARC_ABI_rf16: %s\n", val ? _("yes") : _("no")); break; case Tag_ARC_ABI_osver: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ARC_ABI_osver: v%d\n", val); break; case Tag_ARC_ABI_pic: case Tag_ARC_ABI_sda: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (tag == Tag_ARC_ABI_sda ? " Tag_ARC_ABI_sda: " : " Tag_ARC_ABI_pic: "); switch (val) @@ -14331,28 +14644,24 @@ display_arc_attribute (unsigned char * p, break; case Tag_ARC_ABI_tls: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ARC_ABI_tls: %s\n", val ? "r25": "none"); break; case Tag_ARC_ABI_enumsize: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ARC_ABI_enumsize: %s\n", val ? _("default") : _("smallest")); break; case Tag_ARC_ABI_exceptions: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ARC_ABI_exceptions: %s\n", val ? _("OPTFP") : _("default")); break; case Tag_ARC_ABI_double_size: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ARC_ABI_double_size: %d\n", val); break; @@ -14367,14 +14676,12 @@ display_arc_attribute (unsigned char * p, break; case Tag_ARC_ISA_mpy_option: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ARC_ISA_mpy_option: %d\n", val); break; case Tag_ARC_ATR_version: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ARC_ATR_version: %d\n", val); break; @@ -14519,14 +14826,12 @@ display_arm_attribute (unsigned char * p, const unsigned char * const end) { unsigned int tag; - unsigned int len; unsigned int val; arm_attr_public_tag * attr; unsigned i; unsigned int type; - tag = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (tag, p, end); attr = NULL; for (i = 0; i < ARRAY_SIZE (arm_attr_public_tags); i++) { @@ -14546,8 +14851,7 @@ display_arm_attribute (unsigned char * p, switch (tag) { case 7: /* Tag_CPU_arch_profile. */ - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); switch (val) { case 0: printf (_("None\n")); break; @@ -14560,8 +14864,7 @@ display_arm_attribute (unsigned char * p, break; case 24: /* Tag_align_needed. */ - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); switch (val) { case 0: printf (_("None\n")); break; @@ -14579,8 +14882,7 @@ display_arm_attribute (unsigned char * p, break; case 25: /* Tag_align_preserved. */ - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); switch (val) { case 0: printf (_("None\n")); break; @@ -14599,8 +14901,7 @@ display_arm_attribute (unsigned char * p, case 32: /* Tag_compatibility. */ { - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (_("flag = %d, vendor = "), val); if (p < end - 1) { @@ -14626,12 +14927,10 @@ display_arm_attribute (unsigned char * p, break; case 65: /* Tag_also_compatible_with. */ - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); if (val == 6 /* Tag_CPU_arch. */) { - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); if ((unsigned int) val >= ARRAY_SIZE (arm_attr_tag_CPU_arch)) printf ("??? (%d)\n", val); else @@ -14656,8 +14955,7 @@ display_arm_attribute (unsigned char * p, default: assert (attr->type & 0x80); - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); type = attr->type & 0x7f; if (val >= type) printf ("??? (%d)\n", val); @@ -14675,19 +14973,16 @@ display_gnu_attribute (unsigned char * p, unsigned char * (* display_proc_gnu_attribute) (unsigned char *, unsigned int, const unsigned char * const), const unsigned char * const end) { - int tag; - unsigned int len; + unsigned int tag; unsigned int val; - tag = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (tag, p, end); /* Tag_compatibility is the only generic GNU attribute defined at present. */ if (tag == 32) { - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (_("flag = %d, vendor = "), val); if (p == end) @@ -14725,19 +15020,17 @@ display_power_gnu_attribute (unsigned char * p, unsigned int tag, const unsigned char * const end) { - unsigned int len; unsigned int val; if (tag == Tag_GNU_Power_ABI_FP) { - val = read_uleb128 (p, &len, end); - p += len; printf (" Tag_GNU_Power_ABI_FP: "); - if (len == 0) + if (p == end) { printf (_("\n")); return p; } + READ_ULEB (val, p, end); if (val > 15) printf ("(%#x), ", val); @@ -14778,14 +15071,13 @@ display_power_gnu_attribute (unsigned char * p, if (tag == Tag_GNU_Power_ABI_Vector) { - val = read_uleb128 (p, &len, end); - p += len; printf (" Tag_GNU_Power_ABI_Vector: "); - if (len == 0) + if (p == end) { printf (_("\n")); return p; } + READ_ULEB (val, p, end); if (val > 3) printf ("(%#x), ", val); @@ -14810,14 +15102,13 @@ display_power_gnu_attribute (unsigned char * p, if (tag == Tag_GNU_Power_ABI_Struct_Return) { - val = read_uleb128 (p, &len, end); - p += len; printf (" Tag_GNU_Power_ABI_Struct_Return: "); - if (len == 0) + if (p == end) { printf (_("\n")); return p; } + READ_ULEB (val, p, end); if (val > 2) printf ("(%#x), ", val); @@ -14848,14 +15139,12 @@ display_s390_gnu_attribute (unsigned char * p, unsigned int tag, const unsigned char * const end) { - unsigned int len; - int val; + unsigned int val; if (tag == Tag_GNU_S390_ABI_Vector) { - val = read_uleb128 (p, &len, end); - p += len; printf (" Tag_GNU_S390_ABI_Vector: "); + READ_ULEB (val, p, end); switch (val) { @@ -14963,21 +15252,18 @@ display_sparc_gnu_attribute (unsigned char * p, unsigned int tag, const unsigned char * const end) { - unsigned int len; - int val; + unsigned int val; if (tag == Tag_GNU_Sparc_HWCAPS) { - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_GNU_Sparc_HWCAPS: "); display_sparc_hwcaps (val); return p; } if (tag == Tag_GNU_Sparc_HWCAPS2) { - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_GNU_Sparc_HWCAPS2: "); display_sparc_hwcaps2 (val); return p; @@ -15031,26 +15317,20 @@ display_mips_gnu_attribute (unsigned char * p, { if (tag == Tag_GNU_MIPS_ABI_FP) { - unsigned int len; unsigned int val; - val = read_uleb128 (p, &len, end); - p += len; printf (" Tag_GNU_MIPS_ABI_FP: "); - + READ_ULEB (val, p, end); print_mips_fp_abi_value (val); - return p; } if (tag == Tag_GNU_MIPS_ABI_MSA) { - unsigned int len; unsigned int val; - val = read_uleb128 (p, &len, end); - p += len; printf (" Tag_GNU_MIPS_ABI_MSA: "); + READ_ULEB (val, p, end); switch (val) { @@ -15075,18 +15355,15 @@ display_tic6x_attribute (unsigned char * p, const unsigned char * const end) { unsigned int tag; - unsigned int len; - int val; + unsigned int val; - tag = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (tag, p, end); switch (tag) { case Tag_ISA: - val = read_uleb128 (p, &len, end); - p += len; printf (" Tag_ISA: "); + READ_ULEB (val, p, end); switch (val) { @@ -15118,9 +15395,8 @@ display_tic6x_attribute (unsigned char * p, return p; case Tag_ABI_wchar_t: - val = read_uleb128 (p, &len, end); - p += len; printf (" Tag_ABI_wchar_t: "); + READ_ULEB (val, p, end); switch (val) { case 0: @@ -15139,9 +15415,8 @@ display_tic6x_attribute (unsigned char * p, return p; case Tag_ABI_stack_align_needed: - val = read_uleb128 (p, &len, end); - p += len; printf (" Tag_ABI_stack_align_needed: "); + READ_ULEB (val, p, end); switch (val) { case 0: @@ -15157,8 +15432,7 @@ display_tic6x_attribute (unsigned char * p, return p; case Tag_ABI_stack_align_preserved: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ABI_stack_align_preserved: "); switch (val) { @@ -15175,8 +15449,7 @@ display_tic6x_attribute (unsigned char * p, return p; case Tag_ABI_DSBT: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ABI_DSBT: "); switch (val) { @@ -15193,8 +15466,7 @@ display_tic6x_attribute (unsigned char * p, return p; case Tag_ABI_PID: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ABI_PID: "); switch (val) { @@ -15214,8 +15486,7 @@ display_tic6x_attribute (unsigned char * p, return p; case Tag_ABI_PIC: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ABI_PIC: "); switch (val) { @@ -15232,8 +15503,7 @@ display_tic6x_attribute (unsigned char * p, return p; case Tag_ABI_array_object_alignment: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ABI_array_object_alignment: "); switch (val) { @@ -15253,8 +15523,7 @@ display_tic6x_attribute (unsigned char * p, return p; case Tag_ABI_array_object_align_expected: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ABI_array_object_align_expected: "); switch (val) { @@ -15275,8 +15544,7 @@ display_tic6x_attribute (unsigned char * p, case Tag_ABI_compatibility: { - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf (" Tag_ABI_compatibility: "); printf (_("flag = %d, vendor = "), val); if (p < end - 1) @@ -15367,19 +15635,16 @@ static unsigned char * display_msp430x_attribute (unsigned char * p, const unsigned char * const end) { - unsigned int len; unsigned int val; unsigned int tag; - tag = read_uleb128 (p, & len, end); - p += len; + READ_ULEB (tag, p, end); switch (tag) { case OFBA_MSPABI_Tag_ISA: - val = read_uleb128 (p, &len, end); - p += len; printf (" Tag_ISA: "); + READ_ULEB (val, p, end); switch (val) { case 0: printf (_("None\n")); break; @@ -15390,9 +15655,8 @@ display_msp430x_attribute (unsigned char * p, break; case OFBA_MSPABI_Tag_Code_Model: - val = read_uleb128 (p, &len, end); - p += len; printf (" Tag_Code_Model: "); + READ_ULEB (val, p, end); switch (val) { case 0: printf (_("None\n")); break; @@ -15403,9 +15667,8 @@ display_msp430x_attribute (unsigned char * p, break; case OFBA_MSPABI_Tag_Data_Model: - val = read_uleb128 (p, &len, end); - p += len; printf (" Tag_Data_Model: "); + READ_ULEB (val, p, end); switch (val) { case 0: printf (_("None\n")); break; @@ -15438,8 +15701,7 @@ display_msp430x_attribute (unsigned char * p, } else { - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); printf ("%d (0x%x)\n", val, val); } break; @@ -15449,9 +15711,37 @@ display_msp430x_attribute (unsigned char * p, return p; } +static unsigned char * +display_msp430_gnu_attribute (unsigned char * p, + unsigned int tag, + const unsigned char * const end) +{ + if (tag == Tag_GNU_MSP430_Data_Region) + { + unsigned int val; + + printf (" Tag_GNU_MSP430_Data_Region: "); + READ_ULEB (val, p, end); + + switch (val) + { + case Val_GNU_MSP430_Data_Region_Any: + printf (_("Any Region\n")); + break; + case Val_GNU_MSP430_Data_Region_Lower: + printf (_("Lower Region Only\n")); + break; + default: + printf ("??? (%u)\n", val); + } + return p; + } + return display_tag_value (tag & 1, p, end); +} + struct riscv_attr_tag_t { const char *name; - int tag; + unsigned int tag; }; static struct riscv_attr_tag_t riscv_attr_tag[] = @@ -15470,14 +15760,12 @@ static unsigned char * display_riscv_attribute (unsigned char *p, const unsigned char * const end) { - unsigned int len; - int val; - int tag; + unsigned int val; + unsigned int tag; struct riscv_attr_tag_t *attr = NULL; unsigned i; - tag = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (tag, p, end); /* Find the name of attribute. */ for (i = 0; i < ARRAY_SIZE (riscv_attr_tag); i++) @@ -15499,13 +15787,11 @@ display_riscv_attribute (unsigned char *p, case Tag_RISCV_priv_spec: case Tag_RISCV_priv_spec_minor: case Tag_RISCV_priv_spec_revision: - val = read_uleb128 (p, &len, end); - p += len; - printf (_("%d\n"), val); + READ_ULEB (val, p, end); + printf (_("%u\n"), val); break; case Tag_RISCV_unaligned_access: - val = read_uleb128 (p, &len, end); - p += len; + READ_ULEB (val, p, end); switch (val) { case 0: @@ -15517,9 +15803,8 @@ display_riscv_attribute (unsigned char *p, } break; case Tag_RISCV_stack_align: - val = read_uleb128 (p, &len, end); - p += len; - printf (_("%d-bytes\n"), val); + READ_ULEB (val, p, end); + printf (_("%u-bytes\n"), val); break; case Tag_RISCV_arch: p = display_tag_value (-1, p, end); @@ -15638,7 +15923,7 @@ process_attributes (Filedata * filedata, while (attr_len > 0 && p < contents + sect->sh_size) { int tag; - int val; + unsigned int val; bfd_vma size; unsigned char * end; @@ -15689,10 +15974,7 @@ process_attributes (Filedata * filedata, do_numlist: for (;;) { - unsigned int j; - - val = read_uleb128 (p, &j, end); - p += j; + READ_ULEB (val, p, end); if (val == 0) break; printf (" %d", val); @@ -16238,8 +16520,6 @@ process_mips_specific (Filedata * filedata) if (options_offset != 0) { Elf_External_Options * eopt; - Elf_Internal_Options * iopt; - Elf_Internal_Options * option; size_t offset; int cnt; sect = filedata->section_headers; @@ -16263,6 +16543,10 @@ process_mips_specific (Filedata * filedata) sect->sh_size, _("options")); if (eopt) { + Elf_Internal_Options * iopt; + Elf_Internal_Options * option; + Elf_Internal_Options * iopt_end; + iopt = (Elf_Internal_Options *) cmalloc ((sect->sh_size / sizeof (eopt)), sizeof (* iopt)); if (iopt == NULL) @@ -16273,7 +16557,8 @@ process_mips_specific (Filedata * filedata) offset = cnt = 0; option = iopt; - + iopt_end = iopt + (sect->sh_size / sizeof (eopt)); + while (offset <= sect->sh_size - sizeof (* eopt)) { Elf_External_Options * eoption; @@ -16316,15 +16601,25 @@ process_mips_specific (Filedata * filedata) /* This shouldn't happen. */ printf (" NULL %d %lx", option->section, option->info); break; + case ODK_REGINFO: printf (" REGINFO "); if (filedata->file_header.e_machine == EM_MIPS) { - /* 32bit form. */ Elf32_External_RegInfo * ereg; Elf32_RegInfo reginfo; + /* 32bit form. */ + if (option + 2 > iopt_end) + { + printf (_("\n")); + error (_("Truncated MIPS REGINFO option\n")); + cnt = 0; + break; + } + ereg = (Elf32_External_RegInfo *) (option + 1); + reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask); reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]); reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]); @@ -16345,6 +16640,14 @@ process_mips_specific (Filedata * filedata) Elf64_External_RegInfo * ereg; Elf64_Internal_RegInfo reginfo; + if (option + 2 > iopt_end) + { + printf (_("\n")); + error (_("Truncated MIPS REGINFO option\n")); + cnt = 0; + break; + } + ereg = (Elf64_External_RegInfo *) (option + 1); reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask); reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]); @@ -16364,6 +16667,7 @@ process_mips_specific (Filedata * filedata) } ++option; continue; + case ODK_EXCEPTIONS: fputs (" EXCEPTIONS fpe_min(", stdout); process_mips_fpe_exception (option->info & OEX_FPU_MIN); @@ -16380,6 +16684,7 @@ process_mips_specific (Filedata * filedata) if (option->info & OEX_DISMISS) fputs (" DISMISS", stdout); break; + case ODK_PAD: fputs (" PAD ", stdout); if (option->info & OPAD_PREFIX) @@ -16389,6 +16694,7 @@ process_mips_specific (Filedata * filedata) if (option->info & OPAD_SYMBOL) fputs (" SYMBOL", stdout); break; + case ODK_HWPATCH: fputs (" HWPATCH ", stdout); if (option->info & OHW_R4KEOP) @@ -16400,14 +16706,17 @@ process_mips_specific (Filedata * filedata) if (option->info & OHW_R5KCVTL) fputs (" R5KCVTL", stdout); break; + case ODK_FILL: fputs (" FILL ", stdout); /* XXX Print content of info word? */ break; + case ODK_TAGS: fputs (" TAGS ", stdout); /* XXX Print content of info word? */ break; + case ODK_HWAND: fputs (" HWAND ", stdout); if (option->info & OHWA0_R4KEOP_CHECKED) @@ -16415,6 +16724,7 @@ process_mips_specific (Filedata * filedata) if (option->info & OHWA0_R4KEOP_CLEAN) fputs (" R4KEOP_CLEAN", stdout); break; + case ODK_HWOR: fputs (" HWOR ", stdout); if (option->info & OHWA0_R4KEOP_CHECKED) @@ -16422,16 +16732,19 @@ process_mips_specific (Filedata * filedata) if (option->info & OHWA0_R4KEOP_CLEAN) fputs (" R4KEOP_CLEAN", stdout); break; + case ODK_GP_GROUP: printf (" GP_GROUP %#06lx self-contained %#06lx", option->info & OGP_GROUP, (option->info & OGP_SELF) >> 16); break; + case ODK_IDENT: printf (" IDENT %#06lx self-contained %#06lx", option->info & OGP_GROUP, (option->info & OGP_SELF) >> 16); break; + default: /* This shouldn't happen. */ printf (" %3d ??? %d %lx", @@ -17323,6 +17636,82 @@ decode_x86_isa (unsigned int bitmask) } } +static const char * +get_amd_elf_note_type (unsigned e_type) +{ + static char buff[64]; + + switch (e_type) + { + case NT_AMDGPU_HSA_CODE_OBJECT_VERSION: + return _("NT_AMDGPU_HSA_CODE_OBJECT_VERSION (code object version)"); + case NT_AMDGPU_HSA_HSAIL: + return _("NT_AMDGPU_HSA_HSAIL (hsail)"); + case NT_AMDGPU_HSA_ISA: + return _("NT_AMDGPU_HSA_ISA (ISA name)"); + case NT_AMDGPU_HSA_PRODUCER: + return _("NT_AMDGPU_HSA_PRODUCER (producer name)"); + case NT_AMDGPU_HSA_PRODUCER_OPTIONS: + return _("NT_AMDGPU_HSA_PRODUCER_OPTIONS (producer options"); + case NT_AMDGPU_HSA_EXTENSION: + return _("NT_AMDGPU_HSA_EXTENSION (extension)"); + case NT_AMDGPU_HSA_METADATA: + return _("NT_AMDGPU_HSA_METADATA (code object metadata)"); + case NT_AMDGPU_ISA: + return _("NT_AMDGPU_ISA"); + case NT_AMDGPU_PAL_METADATA: + return _("NT_AMDGPU_PAL_METADATA (code object metadata)"); + case NT_AMDGPU_METADATA: + return _("NT_AMDGPU_METADATA (code object metadata)"); + default: + break; + } + + snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type); + return buff; +} + +static int +print_amd_note (Elf_Internal_Note *pnote) +{ + switch (pnote->type) + { + case NT_AMDGPU_HSA_CODE_OBJECT_VERSION: + { + unsigned int major, minor; + + major = byte_get ((unsigned char*) pnote->descdata, 4); + minor = byte_get ((unsigned char*) pnote->descdata + 4, 4); + + printf (_(" Version: %d.%d\n"), major, minor); + } + break; + + case NT_AMDGPU_HSA_ISA: + { + unsigned long i, vendorsz; + unsigned int major, minor, stepping; + + vendorsz = byte_get ((unsigned char*) pnote->descdata, 2); + major = byte_get ((unsigned char*) pnote->descdata + 4, 4); + minor = byte_get ((unsigned char*) pnote->descdata + 8, 4); + stepping = byte_get ((unsigned char*) pnote->descdata + 12, 4); + + printf (_(" Vendor: ")); + for (i = 16; i < pnote->descsz && pnote->descdata[i] != '\0'; ++i) + printf ("%c", pnote->descdata[i]); + printf (_(", Architecture: ")); + for (i = 16 + vendorsz; i < pnote->descsz && pnote->descdata[i] != '\0'; ++i) + printf ("%c", pnote->descdata[i]); + + printf (_(", Version: %d.%d.%d"), major, minor, stepping); + printf ("\n"); + } + break; + } + return 1; +} + static void decode_x86_feature_1 (unsigned int bitmask) { @@ -17733,7 +18122,7 @@ print_gnu_note (Filedata * filedata, Elf_Internal_Note *pnote) case NT_GNU_PROPERTY_TYPE_0: print_gnu_property_note (filedata, pnote); break; - + default: /* Handle unrecognised types. An error message should have already been created by get_gnu_elf_note_type(), so all that we need to do is to @@ -17853,10 +18242,23 @@ process_netbsd_elf_note (Elf_Internal_Note * pnote) return TRUE; case NT_NETBSD_MARCH: - printf (" NetBSD\t0x%08lx\tMARCH <%s>\n", pnote->descsz, + printf (" NetBSD\t\t0x%08lx\tMARCH <%s>\n", pnote->descsz, pnote->descdata); return TRUE; +#ifdef NT_NETBSD_PAX + case NT_NETBSD_PAX: + version = byte_get ((unsigned char *) pnote->descdata, sizeof (version)); + printf (" NetBSD\t\t0x%08lx\tPaX <%s%s%s%s%s%s>\n", pnote->descsz, + ((version & NT_NETBSD_PAX_MPROTECT) ? "+mprotect" : ""), + ((version & NT_NETBSD_PAX_NOMPROTECT) ? "-mprotect" : ""), + ((version & NT_NETBSD_PAX_GUARD) ? "+guard" : ""), + ((version & NT_NETBSD_PAX_NOGUARD) ? "-guard" : ""), + ((version & NT_NETBSD_PAX_ASLR) ? "+ASLR" : ""), + ((version & NT_NETBSD_PAX_NOASLR) ? "-ASLR" : "")); + return TRUE; +#endif + default: printf (" NetBSD\t0x%08lx\tUnknown note type: (0x%08lx)\n", pnote->descsz, pnote->type); @@ -17900,18 +18302,29 @@ get_netbsd_elfcore_note_type (Filedata * filedata, unsigned e_type) { static char buff[64]; - if (e_type == NT_NETBSDCORE_PROCINFO) - return _("NetBSD procinfo structure"); + switch (e_type) + { + case NT_NETBSDCORE_PROCINFO: + /* NetBSD core "procinfo" structure. */ + return _("NetBSD procinfo structure"); - /* As of Jan 2002 there are no other machine-independent notes - defined for NetBSD core files. If the note type is less - than the start of the machine-dependent note types, we don't - understand it. */ +#ifdef NT_NETBSDCORE_AUXV + case NT_NETBSDCORE_AUXV: + return _("NetBSD ELF auxiliary vector data"); +#endif - if (e_type < NT_NETBSDCORE_FIRSTMACH) - { - snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type); - return buff; + default: + /* As of Jan 2002 there are no other machine-independent notes + defined for NetBSD core files. If the note type is less + than the start of the machine-dependent note types, we don't + understand it. */ + + if (e_type < NT_NETBSDCORE_FIRSTMACH) + { + snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type); + return buff; + } + break; } switch (filedata->file_header.e_machine) @@ -17935,6 +18348,23 @@ get_netbsd_elfcore_note_type (Filedata * filedata, unsigned e_type) } break; + /* On SuperH, PT_GETREGS == mach+3 and PT_GETFPREGS == mach+5. + There's also old PT___GETREGS40 == mach + 1 for old reg + structure which lacks GBR. */ + case EM_SH: + switch (e_type) + { + case NT_NETBSDCORE_FIRSTMACH + 1: + return _("PT___GETREGS40 (old reg structure)"); + case NT_NETBSDCORE_FIRSTMACH + 3: + return _("PT_GETREGS (reg structure)"); + case NT_NETBSDCORE_FIRSTMACH + 5: + return _("PT_GETFPREGS (fpreg structure)"); + default: + break; + } + break; + /* On all other arch's, PT_GETREGS == mach+1 and PT_GETFPREGS == mach+3. */ default: @@ -18017,7 +18447,7 @@ print_stapsdt_note (Elf_Internal_Note *pnote) } else goto stapdt_note_too_small; - + if (data >= data_end) goto stapdt_note_too_small; maxlen = data_end - data; @@ -18344,7 +18774,7 @@ same_section (Filedata * filedata, unsigned long addr1, unsigned long addr2) a1 = find_section_by_address (filedata, addr1); a2 = find_section_by_address (filedata, addr2); - + return a1 == a2 && a1 != NULL; } @@ -18408,7 +18838,7 @@ print_gnu_build_attribute_description (Elf_Internal_Note * pnote, start = byte_get ((unsigned char *) pnote->descdata, 8); end = byte_get ((unsigned char *) pnote->descdata + 8, 8); break; - + default: error (_(" \n"), pnote->descsz); printf (_(" ")); @@ -18703,7 +19133,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote) if (do_wide && left > 0) printf ("%-*s", left, " "); - + return TRUE; } @@ -18729,6 +19159,11 @@ process_note (Elf_Internal_Note * pnote, /* GNU-specific object file notes. */ nt = get_gnu_elf_note_type (pnote->type); + else if (const_strneq (pnote->namedata, "AMD") + || const_strneq (pnote->namedata, "AMDGPU")) + /* AMD-specific object file notes. */ + nt = get_amd_elf_note_type (pnote->type); + else if (const_strneq (pnote->namedata, "FreeBSD")) /* FreeBSD-specific core file notes. */ nt = get_freebsd_elfcore_note_type (filedata, pnote->type); @@ -18741,6 +19176,10 @@ process_note (Elf_Internal_Note * pnote, /* NetBSD-specific core file notes. */ return process_netbsd_elf_note (pnote); + else if (const_strneq (pnote->namedata, "PaX")) + /* NetBSD-specific core file notes. */ + return process_netbsd_elf_note (pnote); + else if (strneq (pnote->namedata, "SPU/", 4)) { /* SPU-specific core file notes. */ @@ -18780,6 +19219,9 @@ process_note (Elf_Internal_Note * pnote, return print_ia64_vms_note (pnote); else if (const_strneq (pnote->namedata, "GNU")) return print_gnu_note (filedata, pnote); + else if (const_strneq (pnote->namedata, "AMD") + || const_strneq (pnote->namedata, "AMDGPU")) + return print_amd_note (pnote); else if (const_strneq (pnote->namedata, "stapsdt")) return print_stapsdt_note (pnote); else if (const_strneq (pnote->namedata, "CORE")) @@ -18797,7 +19239,7 @@ process_note (Elf_Internal_Note * pnote, printf (_(" description data: ")); for (i = 0; i < pnote->descsz; i++) - printf ("%02x ", pnote->descdata[i]); + printf ("%02x ", pnote->descdata[i] & 0xff); if (!do_wide) printf ("\n"); } @@ -18861,7 +19303,7 @@ process_notes_at (Filedata * filedata, return FALSE; } - printf (_(" %-20s %10s\tDescription\n"), _("Owner"), _("Data size")); + printf (_(" %-20s %-10s\tDescription\n"), _("Owner"), _("Data size")); end = (char *) pnotes + length; while ((char *) external < end) @@ -19197,7 +19639,7 @@ process_arch_specific (Filedata * filedata) case EM_MSP430: return process_attributes (filedata, "mspabi", SHT_MSP430_ATTRIBUTES, display_msp430x_attribute, - display_generic_attribute); + display_msp430_gnu_attribute); case EM_RISCV: return process_attributes (filedata, "riscv", SHT_RISCV_ATTRIBUTES, @@ -19426,6 +19868,7 @@ process_object (Filedata * filedata) for (i = ARRAY_SIZE (dynamic_info); i--;) dynamic_info[i] = 0; dynamic_info_DT_GNU_HASH = 0; + dynamic_info_DT_MIPS_XHASH = 0; /* Process the file. */ if (show_name) @@ -19724,7 +20167,7 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive) /* PR 24049 - we cannot use filedata->file_name as this will have already been freed. */ error (_("%s: failed to read archive header\n"), arch.file_name); - + ret = FALSE; break; } @@ -19818,7 +20261,7 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive) thin_filedata.handle = nested_arch.file; thin_filedata.file_name = qualified_name; - + if (! process_object (& thin_filedata)) ret = FALSE; } @@ -19985,5 +20428,9 @@ main (int argc, char ** argv) if (cmdline.dump_sects != NULL) free (cmdline.dump_sects); + free (dump_ctf_symtab_name); + free (dump_ctf_strtab_name); + free (dump_ctf_parent_name); + return err ? EXIT_FAILURE : EXIT_SUCCESS; }