X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=binutils%2Fdwarf.c;h=06ef1f7285e55c120fd21736c97b46d004067613;hb=e46d79a76ea748165a3ecd1102dd10498d089a49;hp=519f9cc4ff77efed345ee6e71da9fb58a2172b30;hpb=2e8136f9453e21414cc328d025bec33218176b66;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 519f9cc4ff..06ef1f7285 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -29,6 +29,7 @@ #include "dwarf.h" #include "gdb/gdb-index.h" #include "filenames.h" +#include "safe-ctype.h" #include #undef MAX @@ -37,6 +38,7 @@ #define MIN(a, b) ((a) < (b) ? (a) : (b)) static const char *regname (unsigned int regno, int row); +static const char *regname_internal_by_table_only (unsigned int regno); static int have_frame_base; static int need_base_address; @@ -119,9 +121,9 @@ static unsigned int shndx_pool_used = 0; struct cu_tu_set { - uint64_t signature; - dwarf_vma section_offsets[DW_SECT_MAX]; - size_t section_sizes[DW_SECT_MAX]; + uint64_t signature; + dwarf_vma section_offsets[DW_SECT_MAX]; + size_t section_sizes[DW_SECT_MAX]; }; static int cu_count = 0; @@ -131,6 +133,12 @@ static struct cu_tu_set *tu_sets = NULL; static bfd_boolean load_cu_tu_indexes (void *); +/* An array that indicates for a given level of CU nesting whether + the latest DW_AT_type seen for that level was a signed type or + an unsigned type. */ +#define MAX_CU_NESTING (1 << 8) +static bfd_boolean level_type_signed[MAX_CU_NESTING]; + /* Values for do_debug_lines. */ #define FLAG_DEBUG_LINES_RAW 1 #define FLAG_DEBUG_LINES_DECODED 2 @@ -1831,10 +1839,356 @@ free_dwo_info (void) first_dwo_info = NULL; } +/* Ensure that START + UVALUE is less than END. + Return an adjusted UVALUE if necessary to ensure this relationship. */ + +static inline dwarf_vma +check_uvalue (const unsigned char * start, + dwarf_vma uvalue, + const unsigned char * end) +{ + dwarf_vma max_uvalue = end - start; + + /* See PR 17512: file: 008-103549-0.001:0.1. + and PR 24829 for examples of where these tests are triggered. */ + if (uvalue > max_uvalue) + { + warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue); + uvalue = max_uvalue; + } + + return uvalue; +} + +static unsigned char * +skip_attr_bytes (unsigned long form, + unsigned char * data, + unsigned const char * end, + dwarf_vma pointer_size, + dwarf_vma offset_size, + int dwarf_version, + dwarf_vma * value_return) +{ + unsigned int bytes_read; + dwarf_vma uvalue = 0; + + * value_return = 0; + + switch (form) + { + case DW_FORM_ref_addr: + if (dwarf_version == 2) + SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end); + else if (dwarf_version == 3 || dwarf_version == 4) + SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end); + else + return NULL; + break; + + case DW_FORM_addr: + SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end); + break; + + case DW_FORM_strp: + case DW_FORM_line_strp: + case DW_FORM_sec_offset: + case DW_FORM_GNU_ref_alt: + case DW_FORM_GNU_strp_alt: + SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end); + break; + + case DW_FORM_flag_present: + uvalue = 1; + break; + + case DW_FORM_ref1: + case DW_FORM_flag: + case DW_FORM_data1: + SAFE_BYTE_GET_AND_INC (uvalue, data, 1, end); + break; + + case DW_FORM_ref2: + case DW_FORM_data2: + SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end); + break; + + case DW_FORM_ref4: + case DW_FORM_data4: + SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end); + break; + + case DW_FORM_sdata: + uvalue = read_sleb128 (data, & bytes_read, end); + data += bytes_read; + break; + + case DW_FORM_ref_udata: + case DW_FORM_udata: + case DW_FORM_GNU_str_index: + case DW_FORM_GNU_addr_index: + uvalue = read_uleb128 (data, & bytes_read, end); + data += bytes_read; + break; + + case DW_FORM_ref8: + case DW_FORM_data8: + data += 8; + break; + + case DW_FORM_data16: + data += 16; + break; + + case DW_FORM_string: + data += strnlen ((char *) data, end - data) + 1; + break; + + case DW_FORM_block: + case DW_FORM_exprloc: + uvalue = read_uleb128 (data, & bytes_read, end); + data += bytes_read + uvalue; + break; + + case DW_FORM_block1: + SAFE_BYTE_GET (uvalue, data, 1, end); + data += 1 + uvalue; + break; + + case DW_FORM_block2: + SAFE_BYTE_GET (uvalue, data, 2, end); + data += 2 + uvalue; + break; + + case DW_FORM_block4: + SAFE_BYTE_GET (uvalue, data, 4, end); + data += 4 + uvalue; + break; + + case DW_FORM_ref_sig8: + data += 8; + break; + + case DW_FORM_indirect: + /* FIXME: Handle this form. */ + default: + return NULL; + } + + * value_return = uvalue; + if (data > end) + data = (unsigned char *) end; + return data; +} + +/* Return IS_SIGNED set to TRUE if the type at + DATA can be determined to be a signed type. */ + +static void +get_type_signedness (unsigned char * start, + unsigned char * data, + unsigned const char * end, + dwarf_vma pointer_size, + dwarf_vma offset_size, + int dwarf_version, + bfd_boolean * is_signed, + bfd_boolean is_nested) +{ + unsigned long abbrev_number; + unsigned int bytes_read; + abbrev_entry * entry; + abbrev_attr * attr; + + * is_signed = FALSE; + + abbrev_number = read_uleb128 (data, & bytes_read, end); + data += bytes_read; + + for (entry = first_abbrev; + entry != NULL && entry->entry != abbrev_number; + entry = entry->next) + continue; + + if (entry == NULL) + /* FIXME: Issue a warning ? */ + return; + + for (attr = entry->first_attr; + attr != NULL && attr->attribute; + attr = attr->next) + { + dwarf_vma uvalue = 0; + + data = skip_attr_bytes (attr->form, data, end, pointer_size, + offset_size, dwarf_version, & uvalue); + if (data == NULL) + return; + + switch (attr->attribute) + { +#if 0 /* FIXME: It would be nice to print the name of the type, + but this would mean updating a lot of binutils tests. */ + case DW_AT_name: + if (attr->form == DW_FORM_strp) + printf ("%s", fetch_indirect_string (uvalue)); + break; +#endif + case DW_AT_type: + /* Recurse. */ + if (is_nested) + { + /* FIXME: Warn - or is this expected ? + NB/ We need to avoid infinite recursion. */ + return; + } + if (uvalue >= (size_t) (end - start)) + return; + get_type_signedness (start, start + uvalue, end, pointer_size, + offset_size, dwarf_version, is_signed, TRUE); + break; + + case DW_AT_encoding: + /* Determine signness. */ + switch (uvalue) + { + case DW_ATE_address: + /* FIXME - some architectures have signed addresses. */ + case DW_ATE_boolean: + case DW_ATE_unsigned: + case DW_ATE_unsigned_char: + case DW_ATE_unsigned_fixed: + * is_signed = FALSE; + break; + + default: + case DW_ATE_complex_float: + case DW_ATE_float: + case DW_ATE_signed: + case DW_ATE_signed_char: + case DW_ATE_imaginary_float: + case DW_ATE_decimal_float: + case DW_ATE_signed_fixed: + * is_signed = TRUE; + break; + } + break; + } + } +} + +static void +read_and_print_leb128 (unsigned char * data, + unsigned int * bytes_read, + unsigned const char * end, + bfd_boolean is_signed) +{ + if (is_signed) + { + dwarf_signed_vma sval = read_sleb128 (data, bytes_read, end); + printf ("%ld", (long) sval); + } + else + { + dwarf_vma uval = read_uleb128 (data, bytes_read, end); + printf ("%lu", (unsigned long) uval); + } +} + +static void +display_discr_list (unsigned long form, + dwarf_vma uvalue, + unsigned char * data, + unsigned const char * end, + int level) +{ + if (uvalue == 0) + { + printf ("[default]"); + return; + } + + switch (form) + { + case DW_FORM_block: + case DW_FORM_block1: + case DW_FORM_block2: + case DW_FORM_block4: + /* Move data pointer back to the start of the byte array. */ + data -= uvalue; + break; + default: + printf ("\n"); + warn (_("corrupt discr_list - not using a block form\n")); + return; + } + + if (uvalue < 2) + { + printf ("\n"); + warn (_("corrupt discr_list - block not long enough\n")); + return; + } + + bfd_boolean is_signed = + (level > 0 && level <= MAX_CU_NESTING) + ? level_type_signed [level - 1] : FALSE; + + printf ("("); + while (uvalue) + { + unsigned char discriminant; + unsigned int bytes_read; + + SAFE_BYTE_GET (discriminant, data, 1, end); + -- uvalue; + data ++; + + assert (uvalue > 0); + switch (discriminant) + { + case DW_DSC_label: + printf ("label "); + read_and_print_leb128 (data, & bytes_read, end, is_signed); + assert (bytes_read <= uvalue && bytes_read > 0); + uvalue -= bytes_read; + data += bytes_read; + break; + + case DW_DSC_range: + printf ("range "); + read_and_print_leb128 (data, & bytes_read, end, is_signed); + assert (bytes_read <= uvalue && bytes_read > 0); + uvalue -= bytes_read; + data += bytes_read; + + printf (".."); + read_and_print_leb128 (data, & bytes_read, end, is_signed); + assert (bytes_read <= uvalue && bytes_read > 0); + uvalue -= bytes_read; + data += bytes_read; + break; + + default: + printf ("\n"); + warn (_("corrupt discr_list - unrecognised discriminant byte %#x\n"), + discriminant); + return; + } + + if (uvalue) + printf (", "); + } + + if (is_signed) + printf (")(signed)"); + else + printf (")(unsigned)"); +} + static unsigned char * read_and_display_attr_value (unsigned long attribute, unsigned long form, dwarf_signed_vma implicit_const, + unsigned char * start, unsigned char * data, unsigned char * end, dwarf_vma cu_offset, @@ -1845,12 +2199,13 @@ read_and_display_attr_value (unsigned long attribute, int do_loc, struct dwarf_section * section, struct cu_tu_set * this_set, - char delimiter) + char delimiter, + int level) { - dwarf_vma uvalue = 0; - unsigned char *block_start = NULL; - unsigned char * orig_data = data; - unsigned int bytes_read; + dwarf_vma uvalue = 0; + unsigned char * block_start = NULL; + unsigned char * orig_data = data; + unsigned int bytes_read; if (data > end || (data == end && form != DW_FORM_flag_present)) { @@ -1931,11 +2286,12 @@ read_and_display_attr_value (unsigned long attribute, implicit_const = read_sleb128 (data, & bytes_read, end); data += bytes_read; } - return read_and_display_attr_value (attribute, form, implicit_const, data, - end, cu_offset, pointer_size, + return read_and_display_attr_value (attribute, form, implicit_const, + start, data, end, + cu_offset, pointer_size, offset_size, dwarf_version, debug_info_p, do_loc, - section, this_set, delimiter); + section, this_set, delimiter, level); case DW_FORM_GNU_addr_index: uvalue = read_uleb128 (data, & bytes_read, end); data += bytes_read; @@ -2055,16 +2411,9 @@ read_and_display_attr_value (unsigned long attribute, uvalue = 0; block_start = end; } - /* FIXME: Testing "(block_start + uvalue) < block_start" miscompiles with - gcc 4.8.3 running on an x86_64 host in 32-bit mode. So we pre-compute - block_start + uvalue here. */ - data = block_start + uvalue; - /* PR 17512: file: 008-103549-0.001:0.1. */ - if (block_start + uvalue > end || data < block_start) - { - warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue); - uvalue = end - block_start; - } + + uvalue = check_uvalue (block_start, uvalue, end); + if (do_loc) data = block_start + uvalue; else @@ -2080,12 +2429,9 @@ read_and_display_attr_value (unsigned long attribute, uvalue = 0; block_start = end; } - data = block_start + uvalue; - if (block_start + uvalue > end || data < block_start) - { - warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue); - uvalue = end - block_start; - } + + uvalue = check_uvalue (block_start, uvalue, end); + if (do_loc) data = block_start + uvalue; else @@ -2101,12 +2447,9 @@ read_and_display_attr_value (unsigned long attribute, uvalue = 0; block_start = end; } - data = block_start + uvalue; - if (block_start + uvalue > end || data < block_start) - { - warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue); - uvalue = end - block_start; - } + + uvalue = check_uvalue (block_start, uvalue, end); + if (do_loc) data = block_start + uvalue; else @@ -2123,14 +2466,9 @@ read_and_display_attr_value (unsigned long attribute, uvalue = 0; block_start = end; } - data = block_start + uvalue; - if (block_start + uvalue > end - /* PR 17531: file: 5b5f0592. */ - || data < block_start) - { - warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue); - uvalue = end - block_start; - } + + uvalue = check_uvalue (block_start, uvalue, end); + if (do_loc) data = block_start + uvalue; else @@ -2386,6 +2724,18 @@ read_and_display_attr_value (unsigned long attribute, /* For some attributes we can display further information. */ switch (attribute) { + case DW_AT_type: + if (level >= 0 && level < MAX_CU_NESTING + && uvalue < (size_t) (end - start)) + { + bfd_boolean is_signed = FALSE; + + get_type_signedness (start, start + uvalue, end, pointer_size, + offset_size, dwarf_version, & is_signed, FALSE); + level_type_signed[level] = is_signed; + } + break; + case DW_AT_inline: printf ("\t"); switch (uvalue) @@ -2635,12 +2985,7 @@ read_and_display_attr_value (unsigned long attribute, case DW_AT_discr_list: printf ("\t"); - switch (uvalue) - { - case DW_DSC_label: printf (_("(label)")); break; - case DW_DSC_range: printf (_("(range)")); break; - default: printf (_("(unrecognised)")); break; - } + display_discr_list (form, uvalue, data, end, level); break; case DW_AT_frame_base: @@ -2757,6 +3102,7 @@ static unsigned char * read_and_display_attr (unsigned long attribute, unsigned long form, dwarf_signed_vma implicit_const, + unsigned char * start, unsigned char * data, unsigned char * end, dwarf_vma cu_offset, @@ -2766,14 +3112,16 @@ read_and_display_attr (unsigned long attribute, debug_info * debug_info_p, int do_loc, struct dwarf_section * section, - struct cu_tu_set * this_set) + struct cu_tu_set * this_set, + int level) { if (!do_loc) printf (" %-18s:", get_AT_name (attribute)); - data = read_and_display_attr_value (attribute, form, implicit_const, data, end, + data = read_and_display_attr_value (attribute, form, implicit_const, + start, data, end, cu_offset, pointer_size, offset_size, dwarf_version, debug_info_p, - do_loc, section, this_set, ' '); + do_loc, section, this_set, ' ', level); if (!do_loc) printf ("\n"); return data; @@ -3299,6 +3647,7 @@ process_debug_info (struct dwarf_section * section, tags = read_and_display_attr (attr->attribute, attr->form, attr->implicit_const, + section_begin, tags, end, cu_offset, @@ -3308,7 +3657,8 @@ process_debug_info (struct dwarf_section * section, debug_info_p, do_loc || ! do_printing, section, - this_set); + this_set, + level); } /* If a locview attribute appears before a location one, @@ -3625,11 +3975,11 @@ display_formatted_table (unsigned char * data, format += bytes_read; form = read_uleb128 (format, & bytes_read, end); format += bytes_read; - data = read_and_display_attr_value (0, form, 0, data, end, 0, 0, + data = read_and_display_attr_value (0, form, 0, start, data, end, 0, 0, linfo->li_offset_size, linfo->li_version, NULL, ((content_type == DW_LNCT_path) != (namepass == 1)), - section, NULL, '\t'); + section, NULL, '\t', -1); } } if (data == end) @@ -4069,6 +4419,7 @@ typedef struct static int display_debug_lines_decoded (struct dwarf_section * section, + unsigned char * start, unsigned char * data, unsigned char * end, void * fileptr) @@ -4202,12 +4553,12 @@ display_debug_lines_decoded (struct dwarf_section * section, } break; } - data = read_and_display_attr_value (0, form, 0, data, end, + data = read_and_display_attr_value (0, form, 0, start, data, end, 0, 0, linfo.li_offset_size, linfo.li_version, NULL, 1, section, - NULL, '\t'); + NULL, '\t', -1); } if (data == end) { @@ -4292,12 +4643,12 @@ display_debug_lines_decoded (struct dwarf_section * section, } break; } - data = read_and_display_attr_value (0, form, 0, data, end, + data = read_and_display_attr_value (0, form, 0, start, data, end, 0, 0, linfo.li_offset_size, linfo.li_version, NULL, 1, section, - NULL, '\t'); + NULL, '\t', -1); } if (data == end) { @@ -4824,7 +5175,7 @@ display_debug_lines (struct dwarf_section *section, void *file) retValRaw = display_debug_lines_raw (section, data, end, file); if (do_debug_lines & FLAG_DEBUG_LINES_DECODED) - retValDecoded = display_debug_lines_decoded (section, data, end, file); + retValDecoded = display_debug_lines_decoded (section, data, data, end, file); if (!retValRaw || !retValDecoded) return 0; @@ -5429,9 +5780,9 @@ display_debug_macro (struct dwarf_section *section, SAFE_BYTE_GET_AND_INC (val, desc, 1, end); curr = read_and_display_attr_value (0, val, 0, - curr, end, 0, 0, offset_size, + start, curr, end, 0, 0, offset_size, version, NULL, 0, NULL, - NULL, ' '); + NULL, ' ', -1); if (n != nargs - 1) printf (","); } @@ -6544,8 +6895,8 @@ display_debug_aranges (struct dwarf_section *section, static int comp_addr_base (const void * v0, const void * v1) { - debug_info * info0 = (debug_info *) v0; - debug_info * info1 = (debug_info *) v1; + debug_info *info0 = *(debug_info **) v0; + debug_info *info1 = *(debug_info **) v1; return info0->addr_base - info1->addr_base; } @@ -7010,9 +7361,12 @@ typedef struct Frame_Chunk } Frame_Chunk; +typedef const char *(*dwarf_regname_lookup_ftype) (unsigned int); +static dwarf_regname_lookup_ftype dwarf_regnames_lookup_func; static const char *const *dwarf_regnames; static unsigned int dwarf_regnames_count; + /* A marker for a col_type that means this column was never referenced in the frame info. */ #define DW_CFA_unreferenced (-1) @@ -7028,7 +7382,7 @@ frame_need_space (Frame_Chunk *fc, unsigned int reg) if (reg < (unsigned int) fc->ncols) return 0; - if (dwarf_regnames_count + if (dwarf_regnames_count > 0 && reg > dwarf_regnames_count) return -1; @@ -7039,7 +7393,7 @@ frame_need_space (Frame_Chunk *fc, unsigned int reg) return -1; /* PR 17512: file: 2844a11d. */ - if (fc->ncols > 1024) + if (fc->ncols > 1024 && dwarf_regnames_count == 0) { error (_("Unfeasibly large register number: %u\n"), reg); fc->ncols = 0; @@ -7114,18 +7468,20 @@ static const char *const dwarf_regnames_iamcu[] = NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL /* 93 - 100 */ }; -void +static void init_dwarf_regnames_i386 (void) { dwarf_regnames = dwarf_regnames_i386; dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_i386); + dwarf_regnames_lookup_func = regname_internal_by_table_only; } -void +static void init_dwarf_regnames_iamcu (void) { dwarf_regnames = dwarf_regnames_iamcu; dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_iamcu); + dwarf_regnames_lookup_func = regname_internal_by_table_only; } static const char *const dwarf_regnames_x86_64[] = @@ -7160,11 +7516,12 @@ static const char *const dwarf_regnames_x86_64[] = "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7" }; -void +static void init_dwarf_regnames_x86_64 (void) { dwarf_regnames = dwarf_regnames_x86_64; dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_x86_64); + dwarf_regnames_lookup_func = regname_internal_by_table_only; } static const char *const dwarf_regnames_aarch64[] = @@ -7187,11 +7544,12 @@ static const char *const dwarf_regnames_aarch64[] = "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31", }; -void +static void init_dwarf_regnames_aarch64 (void) { dwarf_regnames = dwarf_regnames_aarch64; dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_aarch64); + dwarf_regnames_lookup_func = regname_internal_by_table_only; } static const char *const dwarf_regnames_s390[] = @@ -7211,11 +7569,12 @@ static const char *const dwarf_regnames_s390[] = "v24", "v26", "v28", "v30", "v25", "v27", "v29", "v31", }; -void +static void init_dwarf_regnames_s390 (void) { dwarf_regnames = dwarf_regnames_s390; dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_s390); + dwarf_regnames_lookup_func = regname_internal_by_table_only; } static const char *const dwarf_regnames_riscv[] = @@ -7232,16 +7591,54 @@ static const char *const dwarf_regnames_riscv[] = "ft8", "ft9", "ft10", "ft11" /* 60 - 63 */ }; -void +/* A RISC-V replacement for REGNAME_INTERNAL_BY_TABLE_ONLY which handles + the large number of CSRs. */ + +static const char * +regname_internal_riscv (unsigned int regno) +{ + const char *name = NULL; + + /* Lookup in the table first, this covers GPR and FPR. */ + if (regno < ARRAY_SIZE (dwarf_regnames_riscv)) + name = dwarf_regnames_riscv [regno]; + else if (regno >= 4096 && regno <= 8191) + { + /* This might be a CSR, these live in a sparse number space from 4096 + to 8191 These numbers are defined in the RISC-V ELF ABI + document. */ + switch (regno) + { +#define DECLARE_CSR(NAME,VALUE) case VALUE + 4096: name = #NAME; break; +#include "opcode/riscv-opc.h" +#undef DECLARE_CSR + + default: + { + static char csr_name[10]; + snprintf (csr_name, sizeof (csr_name), "csr%d", (regno - 4096)); + name = csr_name; + } + break; + } + } + + return name; +} + +static void init_dwarf_regnames_riscv (void) { - dwarf_regnames = dwarf_regnames_riscv; - dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_riscv); + dwarf_regnames = NULL; + dwarf_regnames_count = 8192; + dwarf_regnames_lookup_func = regname_internal_riscv; } void -init_dwarf_regnames (unsigned int e_machine) +init_dwarf_regnames_by_elf_machine_code (unsigned int e_machine) { + dwarf_regnames_lookup_func = NULL; + switch (e_machine) { case EM_386: @@ -7275,19 +7672,82 @@ init_dwarf_regnames (unsigned int e_machine) } } -static const char * -regname (unsigned int regno, int row) +/* Initialize the DWARF register name lookup state based on the + architecture and specific machine type of a BFD. */ + +void +init_dwarf_regnames_by_bfd_arch_and_mach (enum bfd_architecture arch, + unsigned long mach) { - static char reg[64]; + dwarf_regnames_lookup_func = NULL; + + switch (arch) + { + case bfd_arch_i386: + switch (mach) + { + case bfd_mach_x86_64: + case bfd_mach_x86_64_intel_syntax: + case bfd_mach_x86_64_nacl: + case bfd_mach_x64_32: + case bfd_mach_x64_32_intel_syntax: + case bfd_mach_x64_32_nacl: + init_dwarf_regnames_x86_64 (); + break; + + default: + init_dwarf_regnames_i386 (); + break; + } + break; + + case bfd_arch_iamcu: + init_dwarf_regnames_iamcu (); + break; + + case bfd_arch_aarch64: + init_dwarf_regnames_aarch64(); + break; + + case bfd_arch_s390: + init_dwarf_regnames_s390 (); + break; + + case bfd_arch_riscv: + init_dwarf_regnames_riscv (); + break; + + default: + break; + } +} - if (dwarf_regnames +static const char * +regname_internal_by_table_only (unsigned int regno) +{ + if (dwarf_regnames != NULL && regno < dwarf_regnames_count && dwarf_regnames [regno] != NULL) + return dwarf_regnames [regno]; + + return NULL; +} + +static const char * +regname (unsigned int regno, int name_only_p) +{ + static char reg[64]; + + const char *name = NULL; + + if (dwarf_regnames_lookup_func != NULL) + name = dwarf_regnames_lookup_func (regno); + + if (name != NULL) { - if (row) - return dwarf_regnames [regno]; - snprintf (reg, sizeof (reg), "r%d (%s)", regno, - dwarf_regnames [regno]); + if (name_only_p) + return name; + snprintf (reg, sizeof (reg), "r%d (%s)", regno, name); } else snprintf (reg, sizeof (reg), "r%d", regno); @@ -7821,18 +8281,18 @@ display_debug_frames (struct dwarf_section *section, { READ_ULEB (augmentation_data_len); augmentation_data = start; - start += augmentation_data_len; /* PR 17512 file: 722-8446-0.004 and PR 22386. */ - if (start >= end - || ((bfd_signed_vma) augmentation_data_len) < 0 - || augmentation_data > start) + if (augmentation_data_len > (bfd_size_type) (end - start)) { - warn (_("Corrupt augmentation data length: 0x%s\n"), - dwarf_vmatoa ("x", augmentation_data_len)); + warn (_("Augmentation data too long: 0x%s, " + "expected at most %#lx\n"), + dwarf_vmatoa ("x", augmentation_data_len), + (unsigned long) (end - start)); start = end; augmentation_data = NULL; augmentation_data_len = 0; } + start += augmentation_data_len; } printf ("\n%08lx %s %s FDE cie=%08lx pc=", @@ -8543,6 +9003,8 @@ display_debug_names (struct dwarf_section *section, void *file) uint32_t augmentation_string_size; unsigned int i; unsigned long sec_off; + bfd_boolean augmentation_printable; + const char *augmentation_string; unit_start = hdrptr; @@ -8606,15 +9068,32 @@ display_debug_names (struct dwarf_section *section, void *file) augmentation_string_size); augmentation_string_size += (-augmentation_string_size) & 3; } + printf (_("Augmentation string:")); + + augmentation_printable = TRUE; + augmentation_string = (const char *) hdrptr; + for (i = 0; i < augmentation_string_size; i++) { unsigned char uc; SAFE_BYTE_GET_AND_INC (uc, hdrptr, 1, unit_end); printf (" %02x", uc); + + if (uc != 0 && !ISPRINT (uc)) + augmentation_printable = FALSE; + } + + if (augmentation_printable) + { + printf (" (\""); + for (i = 0; + i < augmentation_string_size && augmentation_string[i]; + ++i) + putchar (augmentation_string[i]); + printf ("\")"); } - putchar ('\n'); putchar ('\n'); printf (_("CU table:\n")); @@ -8850,12 +9329,12 @@ display_debug_names (struct dwarf_section *section, void *file) if (tagno >= 0) printf (" %s", get_IDX_name (xindex)); - entryptr = read_and_display_attr_value (0, form, 0, entryptr, - unit_end, 0, 0, - offset_size, + entryptr = read_and_display_attr_value (0, form, 0, + unit_start, entryptr, unit_end, + 0, 0, offset_size, dwarf_version, NULL, (tagno < 0), NULL, - NULL, '='); + NULL, '=', -1); } ++tagno; } @@ -9294,33 +9773,29 @@ process_cu_tu_index (struct dwarf_section *section, int do_display) SAFE_BYTE_GET (nslots, phdr + 12, 4, limit); phash = phdr + 16; - pindex = phash + nslots * 8; - ppool = pindex + nslots * 4; - - /* PR 17531: file: 45d69832. */ - if (pindex < phash || ppool < phdr || (pindex == phash && nslots != 0)) - { - warn (ngettext ("Section %s is too small for %d slot\n", - "Section %s is too small for %d slots\n", - nslots), - section->name, nslots); - return 0; - } + pindex = phash + (size_t) nslots * 8; + ppool = pindex + (size_t) nslots * 4; if (do_display) { introduce (section, FALSE); - printf (_(" Version: %d\n"), version); + printf (_(" Version: %u\n"), version); if (version >= 2) - printf (_(" Number of columns: %d\n"), ncols); - printf (_(" Number of used entries: %d\n"), nused); - printf (_(" Number of slots: %d\n\n"), nslots); + printf (_(" Number of columns: %u\n"), ncols); + printf (_(" Number of used entries: %u\n"), nused); + printf (_(" Number of slots: %u\n\n"), nslots); } - if (ppool > limit || ppool < phdr) + /* PR 17531: file: 45d69832. */ + if ((size_t) nslots * 8 / 8 != nslots + || phash < phdr || phash > limit + || pindex < phash || pindex > limit + || ppool < pindex || ppool > limit) { - warn (_("Section %s too small for %d hash table entries\n"), + warn (ngettext ("Section %s is too small for %u slot\n", + "Section %s is too small for %u slots\n", + nslots), section->name, nslots); return 0; } @@ -9382,9 +9857,9 @@ process_cu_tu_index (struct dwarf_section *section, int do_display) unsigned int dw_sect; unsigned char *ph = phash; unsigned char *pi = pindex; - unsigned char *poffsets = ppool + ncols * 4; - unsigned char *psizes = poffsets + nused * ncols * 4; - unsigned char *pend = psizes + nused * ncols * 4; + unsigned char *poffsets = ppool + (size_t) ncols * 4; + unsigned char *psizes = poffsets + (size_t) nused * ncols * 4; + unsigned char *pend = psizes + (size_t) nused * ncols * 4; bfd_boolean is_tu_index; struct cu_tu_set *this_set = NULL; unsigned int row; @@ -9393,14 +9868,14 @@ process_cu_tu_index (struct dwarf_section *section, int do_display) is_tu_index = strcmp (section->name, ".debug_tu_index") == 0; /* PR 17531: file: 0dd159bf. - Check for wraparound with an overlarge ncols value. */ - if (poffsets < ppool || (unsigned int) ((poffsets - ppool) / 4) != ncols) - { - warn (_("Overlarge number of columns: %x\n"), ncols); - return 0; - } - - if (pend > limit) + Check for integer overflow (can occur when size_t is 32-bit) + with overlarge ncols or nused values. */ + if (ncols > 0 + && ((size_t) ncols * 4 / 4 != ncols + || (size_t) nused * ncols * 4 / ((size_t) ncols * 4) != nused + || poffsets < ppool || poffsets > limit + || psizes < poffsets || psizes > limit + || pend < psizes || pend > limit)) { warn (_("Section %s too small for offset and size tables\n"), section->name);