X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=binutils%2Freadelf.c;h=cc168163b2166795c58e572ebfbd219562fcc20e;hb=1ff5d5c46342727ad6728732e122f963fbb2268b;hp=6175b330179f69b83ae2612f74b42f75db8441a7;hpb=2e6be59c8de57c32260771ac5307968d18793a0a;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/readelf.c b/binutils/readelf.c index 6175b33017..cc168163b2 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -232,6 +232,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; @@ -335,6 +336,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. */ @@ -385,9 +390,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" @@ -397,7 +402,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" @@ -429,10 +434,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) { @@ -1874,6 +1877,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; } @@ -4115,6 +4119,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; } @@ -7415,11 +7420,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. */ @@ -7565,8 +7565,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)); @@ -7574,7 +7588,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", @@ -9518,6 +9532,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); } @@ -11509,6 +11528,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 @@ -11574,12 +11594,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 : _("")); } } } @@ -11666,6 +11682,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; @@ -11831,7 +11848,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); @@ -11881,7 +11922,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 @@ -11895,7 +11937,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); @@ -12118,11 +12163,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)); @@ -12179,6 +12225,7 @@ process_symbol_table (Filedata * filedata) free (lengths); free (gnubuckets); free (gnuchains); + free (mipsxlat); } return TRUE; @@ -13358,7 +13405,7 @@ apply_relocations (Filedata * filedata, } rloc = start + rp->r_offset; - if ((rloc + reloc_size) > end || (rloc < start)) + if (rloc >= end || (rloc + reloc_size) > end || (rloc < start)) { warn (_("skipping invalid relocation offset 0x%lx in section %s\n"), (unsigned long) rp->r_offset, @@ -19108,7 +19155,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"); } @@ -19172,7 +19219,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) @@ -19737,6 +19784,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)