X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=binutils%2Freadelf.c;h=7ff29bc8ba162d14147098dc8b231b7bf053a5ea;hb=25499ac7ee92bca177c9436383ee167d6a220066;hp=ab53473b4336930ddd84fad414d6f4c1077abb9f;hpb=7296a62a2a237f6b1ad8db8c38b090e9f592c8cf;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/readelf.c b/binutils/readelf.c index ab53473b43..7ff29bc8ba 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -2508,6 +2508,9 @@ decode_ARC_machine_flags (unsigned e_flags, unsigned e_machine, char buf[]) case E_ARC_OSABI_V3: strcat (buf, ", v3 no-legacy-syscalls ABI"); break; + case E_ARC_OSABI_V4: + strcat (buf, ", v4 ABI"); + break; default: strcat (buf, ", unrecognised ARC OSABI flag"); break; @@ -3897,6 +3900,18 @@ get_segment_type (unsigned long p_type) } } +static const char * +get_arc_section_type_name (unsigned int sh_type) +{ + switch (sh_type) + { + case SHT_ARC_ATTRIBUTES: return "ARC_ATTRIBUTES"; + default: + break; + } + return NULL; +} + static const char * get_mips_section_type_name (unsigned int sh_type) { @@ -4106,6 +4121,11 @@ get_section_type_name (unsigned int sh_type) { switch (elf_header.e_machine) { + case EM_ARC: + case EM_ARC_COMPACT: + case EM_ARC_COMPACT2: + result = get_arc_section_type_name (sh_type); + break; case EM_MIPS: case EM_MIPS_RS3_LE: result = get_mips_section_type_name (sh_type); @@ -6215,6 +6235,13 @@ process_section_headers (FILE * file) break; } + /* Check the sh_size field. */ + if (section->sh_size > current_file_size + && section->sh_type != SHT_NOBITS + && section->sh_type != SHT_NULL + && section->sh_type < SHT_LOOS) + warn (_("Size of section %u is larger than the entire file!\n"), i); + printf (" [%2u] ", i); if (do_section_details) printf ("%s\n ", printable_section_name (section)); @@ -10171,8 +10198,9 @@ process_version_sections (FILE * file) printf (_(" Index: %d Cnt: %d "), ent.vd_ndx, ent.vd_cnt); - /* Check for overflow. */ - if (ent.vd_aux + sizeof (* eaux) > (size_t) (endbuf - vstart)) + /* Check for overflow and underflow. */ + if (ent.vd_aux + sizeof (* eaux) > (size_t) (endbuf - vstart) + || (vstart + ent.vd_aux < vstart)) break; vstart += ent.vd_aux; @@ -13483,6 +13511,180 @@ display_tag_value (signed int tag, return p; } +/* ARC ABI attributes section. */ + +static unsigned char * +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; + + switch (tag) + { + case Tag_ARC_PCS_config: + val = read_uleb128 (p, &len, end); + p += len; + printf (" Tag_ARC_PCS_config: "); + switch (val) + { + case 0: + printf (_("Absent/Non standard\n")); + break; + case 1: + printf (_("Bare metal/mwdt\n")); + break; + case 2: + printf (_("Bare metal/newlib\n")); + break; + case 3: + printf (_("Linux/uclibc\n")); + break; + case 4: + printf (_("Linux/glibc\n")); + break; + default: + printf (_("Unknown\n")); + break; + } + break; + + case Tag_ARC_CPU_base: + val = read_uleb128 (p, &len, end); + p += len; + printf (" Tag_ARC_CPU_base: "); + switch (val) + { + default: + case TAG_CPU_NONE: + printf (_("Absent\n")); + break; + case TAG_CPU_ARC6xx: + printf ("ARC6xx\n"); + break; + case TAG_CPU_ARC7xx: + printf ("ARC7xx\n"); + break; + case TAG_CPU_ARCEM: + printf ("ARCEM\n"); + break; + case TAG_CPU_ARCHS: + printf ("ARCHS\n"); + break; + } + break; + + case Tag_ARC_CPU_variation: + val = read_uleb128 (p, &len, end); + p += len; + printf (" Tag_ARC_CPU_variation: "); + switch (val) + { + default: + if (val > 0 && val < 16) + { + printf ("Core%d\n", val); + break; + } + case 0: + printf (_("Absent\n")); + break; + } + break; + + case Tag_ARC_CPU_name: + printf (" Tag_ARC_CPU_name: "); + p = display_tag_value (-1, p, end); + break; + + case Tag_ARC_ABI_rf16: + val = read_uleb128 (p, &len, end); + p += len; + printf (" Tag_ARC_ABI_rf16: %s\n", val ? _("yes") : _("no")); + break; + + case Tag_ARC_ABI_osver: + val = read_uleb128 (p, &len, end); + p += len; + 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; + printf (tag == Tag_ARC_ABI_sda ? " Tag_ARC_ABI_sda: " + : " Tag_ARC_ABI_pic: "); + switch (val) + { + case 0: + printf (_("Absent\n")); + break; + case 1: + printf ("MWDT\n"); + break; + case 2: + printf ("GNU\n"); + break; + default: + printf (_("Unknown\n")); + break; + } + break; + + case Tag_ARC_ABI_tls: + val = read_uleb128 (p, &len, end); + p += len; + printf (" Tag_ARC_ABI_tls: %s\n", val ? "r25": "none"); + break; + + case Tag_ARC_ABI_enumsize: + val = read_uleb128 (p, &len, end); + p += len; + printf (" Tag_ARC_ABI_enumsize: %s\n", val ? _("default") : + _("smallest")); + break; + + case Tag_ARC_ABI_exceptions: + val = read_uleb128 (p, &len, end); + p += len; + 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; + printf (" Tag_ARC_ABI_double_size: %d\n", val); + break; + + case Tag_ARC_ISA_config: + printf (" Tag_ARC_ISA_config: "); + p = display_tag_value (-1, p, end); + break; + + case Tag_ARC_ISA_apex: + printf (" Tag_ARC_ISA_apex: "); + p = display_tag_value (-1, p, end); + break; + + case Tag_ARC_ISA_mpy_option: + val = read_uleb128 (p, &len, end); + p += len; + printf (" Tag_ARC_ISA_mpy_option: %d\n", val); + break; + + default: + return display_tag_value (tag & 1, p, end); + } + + return p; +} + /* ARM EABI attributes section. */ typedef struct { @@ -14841,6 +15043,8 @@ print_mips_ases (unsigned int mask) fputs ("\n\tMICROMIPS ASE", stdout); if (mask & AFL_ASE_XPA) fputs ("\n\tXPA ASE", stdout); + if (mask & AFL_ASE_MIPS16E2) + fputs ("\n\tMIPS16e2 ASE", stdout); if (mask == 0) fprintf (stdout, "\n\t%s", _("None")); else if ((mask & ~AFL_ASE_MASK) != 0) @@ -15007,8 +15211,93 @@ process_mips_specific (FILE * file) /* We have a lot of special sections. Thanks SGI! */ if (dynamic_section == NULL) - /* No information available. */ - return res; + { + /* No dynamic information available. See if there is static GOT. */ + sect = find_section (".got"); + if (sect != NULL) + { + unsigned char *data_end; + unsigned char *data; + bfd_vma ent, end; + int addr_size; + + pltgot = sect->sh_addr; + + ent = pltgot; + addr_size = (is_32bit_elf ? 4 : 8); + end = pltgot + sect->sh_size; + + data = (unsigned char *) get_data (NULL, file, sect->sh_offset, + end - pltgot, 1, + _("Global Offset Table data")); + /* PR 12855: Null data is handled gracefully throughout. */ + data_end = data + (end - pltgot); + + printf (_("\nStatic GOT:\n")); + printf (_(" Canonical gp value: ")); + print_vma (ent + 0x7ff0, LONG_HEX); + printf ("\n\n"); + + /* In a dynamic binary GOT[0] is reserved for the dynamic + loader to store the lazy resolver pointer, however in + a static binary it may well have been omitted and GOT + reduced to a table of addresses. + PR 21344: Check for the entry being fully available + before fetching it. */ + if (data + && data + ent - pltgot + addr_size <= data_end + && byte_get (data + ent - pltgot, addr_size) == 0) + { + printf (_(" Reserved entries:\n")); + printf (_(" %*s %10s %*s\n"), + addr_size * 2, _("Address"), _("Access"), + addr_size * 2, _("Value")); + ent = print_mips_got_entry (data, pltgot, ent, data_end); + printf ("\n"); + if (ent == (bfd_vma) -1) + goto sgot_print_fail; + + /* Check for the MSB of GOT[1] being set, identifying a + GNU object. This entry will be used by some runtime + loaders, to store the module pointer. Otherwise this + is an ordinary local entry. + PR 21344: Check for the entry being fully available + before fetching it. */ + if (data + && data + ent - pltgot + addr_size <= data_end + && (byte_get (data + ent - pltgot, addr_size) + >> (addr_size * 8 - 1)) != 0) + { + ent = print_mips_got_entry (data, pltgot, ent, data_end); + printf ("\n"); + if (ent == (bfd_vma) -1) + goto sgot_print_fail; + } + printf ("\n"); + } + + if (ent < end) + { + printf (_(" Local entries:\n")); + printf (" %*s %10s %*s\n", + addr_size * 2, _("Address"), _("Access"), + addr_size * 2, _("Value")); + while (ent < end) + { + ent = print_mips_got_entry (data, pltgot, ent, data_end); + printf ("\n"); + if (ent == (bfd_vma) -1) + goto sgot_print_fail; + } + printf ("\n"); + } + + sgot_print_fail: + if (data) + free (data); + } + return res; + } for (entry = dynamic_section; /* PR 17531 file: 012-50589-0.004. */ @@ -15483,8 +15772,7 @@ process_mips_specific (FILE * file) data = (unsigned char *) get_data (NULL, file, offset, global_end - pltgot, 1, _("Global Offset Table data")); - if (data == NULL) - return FALSE; + /* PR 12855: Null data is handled gracefully throughout. */ data_end = data + (global_end - pltgot); printf (_("\nPrimary GOT:\n")); @@ -15501,24 +15789,20 @@ process_mips_specific (FILE * file) if (ent == (bfd_vma) -1) goto got_print_fail; - if (data) - { - /* PR 21344 */ - if (data + ent - pltgot > data_end - addr_size) - { - error (_("Invalid got entry - %#lx - overflows GOT table\n"), - (long) ent); - goto got_print_fail; - } - - if (byte_get (data + ent - pltgot, addr_size) - >> (addr_size * 8 - 1) != 0) - { - ent = print_mips_got_entry (data, pltgot, ent, data_end); - printf (_(" Module pointer (GNU extension)\n")); - if (ent == (bfd_vma) -1) - goto got_print_fail; - } + /* Check for the MSB of GOT[1] being set, denoting a GNU object. + This entry will be used by some runtime loaders, to store the + module pointer. Otherwise this is an ordinary local entry. + PR 21344: Check for the entry being fully available before + fetching it. */ + if (data + && data + ent - pltgot + addr_size <= data_end + && (byte_get (data + ent - pltgot, addr_size) + >> (addr_size * 8 - 1)) != 0) + { + ent = print_mips_got_entry (data, pltgot, ent, data_end); + printf (_(" Module pointer (GNU extension)\n")); + if (ent == (bfd_vma) -1) + goto got_print_fail; } printf ("\n"); @@ -16902,7 +17186,6 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote) expected_types = bool_expected; ++ name; break; - default: if (ISPRINT (* name)) { @@ -16916,9 +17199,11 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote) } else { - error (_("unexpected character in name field\n")); - print_symbol (- left, _("")); - return 0; + static char tmpbuf [128]; + error (_("unrecognised byte in name field: %d\n"), * name); + sprintf (tmpbuf, _(""), * name); + text = tmpbuf; + name ++; } expected_types = "*$!+"; break; @@ -16948,10 +17233,28 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote) { case GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC: { - unsigned int bytes = pnote->namesz - (name - pnote->namedata); - unsigned long val = 0; - unsigned int shift = 0; - char * decoded = NULL; + unsigned int bytes; + unsigned long long val = 0; + unsigned int shift = 0; + char * decoded = NULL; + + bytes = pnote->namesz - (name - pnote->namedata); + if (bytes > 0) + /* The -1 is because the name field is always 0 terminated, and we + want to be able to ensure that the shift in the while loop below + will not overflow. */ + -- bytes; + + if (bytes > sizeof (val)) + { + fprintf (stderr, "namesz %lx name %p namedata %p\n", + pnote->namesz, name, pnote->namedata); + error (_("corrupt numeric name field: too many bytes in the value: %x\n"), + bytes); + bytes = sizeof (val); + } + /* We do not bother to warn if bytes == 0 as this can + happen with some early versions of the gcc plugin. */ while (bytes --) { @@ -16991,13 +17294,21 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote) } if (decoded != NULL) - print_symbol (-left, decoded); + { + print_symbol (-left, decoded); + left = 0; + } + else if (val == 0) + { + printf ("0x0"); + left -= 3; + } else { if (do_wide) - left -= printf ("0x%lx", val); + left -= printf ("0x%llx", val); else - left -= printf ("0x%-.*lx", left, val); + left -= printf ("0x%-.*llx", left, val); } } break; @@ -17458,6 +17769,12 @@ process_arch_specific (FILE * file) switch (elf_header.e_machine) { + case EM_ARC: + case EM_ARC_COMPACT: + case EM_ARC_COMPACT2: + return process_attributes (file, "ARC", SHT_ARC_ATTRIBUTES, + display_arc_attribute, + display_generic_attribute); case EM_ARM: return process_attributes (file, "aeabi", SHT_ARM_ATTRIBUTES, display_arm_attribute,