diff options
author | Nick Clifton <nickc@redhat.com> | 2022-06-28 12:30:19 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2022-06-28 12:30:19 +0100 |
commit | dbcbf67ca565ec29f13a2302dcdf9b01ef7832ca (patch) | |
tree | f6a722c2ab37987c7e093ed3bd20269a43ba3c60 /binutils/dwarf.c | |
parent | d0e0f9c87a3eb141f2036c3ca1569ce7ba2d9ff3 (diff) | |
download | binutils-dbcbf67ca565ec29f13a2302dcdf9b01ef7832ca.zip binutils-dbcbf67ca565ec29f13a2302dcdf9b01ef7832ca.tar.gz binutils-dbcbf67ca565ec29f13a2302dcdf9b01ef7832ca.tar.bz2 |
Fix the display of the idnex values for DW_FORM_loclistx and DW_FORM_rnglistx. Correct the display of .debug.loclists sections.
PR 29267
* dwarf.c (display_debug_rnglists): New function, broken out of..
(display_debug_ranges): ... here.
(read_and_display_attr_value): Correct calculation of index
displayed for DW_FORM_loclistx and DW_FORM_rnglistx.
* testsuite/binutils-all/x86-64/pr26808.dump: Update expected
output.
Diffstat (limited to 'binutils/dwarf.c')
-rw-r--r-- | binutils/dwarf.c | 218 |
1 files changed, 132 insertions, 86 deletions
diff --git a/binutils/dwarf.c b/binutils/dwarf.c index b99c569..84200ae 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -763,7 +763,7 @@ fetch_indexed_addr (dwarf_vma offset, uint32_t num_bytes) if (section->start == NULL) { - warn (_("<no .debug_addr section>")); + warn (_("Cannot fetch indexed address: the .debug_addr section is missing\n")); return 0; } @@ -778,7 +778,7 @@ fetch_indexed_addr (dwarf_vma offset, uint32_t num_bytes) } /* Fetch a value from a debug section that has been indexed by - something in another section (eg DW_FORM_loclistx). + something in another section (eg DW_FORM_loclistx or DW_FORM_rnglistx). Returns 0 if the value could not be found. */ static dwarf_vma @@ -811,7 +811,7 @@ fetch_indexed_value (dwarf_vma idx, /* Offsets are biased by the size of the section header or base address. */ - if (sec_enum == loclists) + if (base_address) offset += base_address; else offset += bias; @@ -2743,37 +2743,52 @@ read_and_display_attr_value (unsigned long attribute, case DW_FORM_rnglistx: if (!do_loc) { - dwarf_vma base; - dwarf_vma offset; + dwarf_vma base, index; - if (debug_info_p == NULL) - base = 0; - else if (debug_info_p->addr_base == DEBUG_INFO_UNAVAILABLE) - base = 0; + if (form == DW_FORM_loclistx) + { + if (debug_info_p == NULL) + { + index = fetch_indexed_value (uvalue, loclists, 0); + } + else + { + /* We want to compute: + index = fetch_indexed_value (uvalue, loclists, debug_info_p->loclists_base); + index += debug_info_p->loclists_base; + Fortunately we already have that sum cached in the + loc_offsets array. */ + index = debug_info_p->loc_offsets [uvalue]; + } + } + else if (form == DW_FORM_rnglistx) + { + if (debug_info_p == NULL) + base = 0; + else + base = debug_info_p->rnglists_base; + /* We do not have a cached value this time, so we perform the + computation manually. */ + index = fetch_indexed_value (uvalue, rnglists, base); + index += base; + } else - base = debug_info_p->addr_base; + { + if (debug_info_p == NULL) + base = 0; + else if (debug_info_p->addr_base == DEBUG_INFO_UNAVAILABLE) + base = 0; + else + base = debug_info_p->addr_base; - offset = base + uvalue * pointer_size; + base += uvalue * pointer_size; + index = fetch_indexed_addr (base, pointer_size); + } - if (do_wide) - /* We have already displayed the form name. */ - if (form == DW_FORM_loclistx) - printf (_("%c(index: 0x%s): %s"), delimiter, - dwarf_vmatoa ("x", uvalue), - dwarf_vmatoa ("x", debug_info_p->loc_offsets [uvalue])); - else - printf (_("%c(index: 0x%s): %s"), delimiter, - dwarf_vmatoa ("x", uvalue), - dwarf_vmatoa ("x", fetch_indexed_addr (offset, pointer_size))); - else - if (form == DW_FORM_loclistx) - printf (_("%c(addr_index: 0x%s): %s"), delimiter, - dwarf_vmatoa ("x", uvalue), - dwarf_vmatoa ("x", debug_info_p->loc_offsets [uvalue])); - else - printf (_("%c(addr_index: 0x%s): %s"), delimiter, - dwarf_vmatoa ("x", uvalue), - dwarf_vmatoa ("x", fetch_indexed_addr (offset, pointer_size))); + /* We have already displayed the form name. */ + printf (_("%c(index: 0x%s): %s"), delimiter, + dwarf_vmatoa ("x", uvalue), + dwarf_vmatoa ("x", index)); } break; @@ -2797,20 +2812,26 @@ read_and_display_attr_value (unsigned long attribute, { case DW_AT_loclists_base: if (debug_info_p->loclists_base) - warn (_("CU @ 0x%s has multiple loclists_base values"), - dwarf_vmatoa ("x", debug_info_p->cu_offset)); + warn (_("CU @ 0x%s has multiple loclists_base values (0x%s and 0x%s)"), + dwarf_vmatoa ("x", debug_info_p->cu_offset), + dwarf_vmatoa ("x", debug_info_p->loclists_base), + dwarf_vmatoa ("x", uvalue)); debug_info_p->loclists_base = uvalue; break; case DW_AT_rnglists_base: if (debug_info_p->rnglists_base) - warn (_("CU @ 0x%s has multiple rnglists_base values"), - dwarf_vmatoa ("x", debug_info_p->cu_offset)); + warn (_("CU @ 0x%s has multiple rnglists_base values (0x%s and 0x%s)"), + dwarf_vmatoa ("x", debug_info_p->cu_offset), + dwarf_vmatoa ("x", debug_info_p->rnglists_base), + dwarf_vmatoa ("x", uvalue)); debug_info_p->rnglists_base = uvalue; break; case DW_AT_str_offsets_base: if (debug_info_p->str_offsets_base) - warn (_("CU @ 0x%s has multiple str_offsets_base values"), - dwarf_vmatoa ("x", debug_info_p->cu_offset)); + warn (_("CU @ 0x%s has multiple str_offsets_base values (0x%s and 0x%s)"), + dwarf_vmatoa ("x", debug_info_p->cu_offset), + dwarf_vmatoa ("x", debug_info_p->str_offsets_base), + dwarf_vmatoa ("x", uvalue)); debug_info_p->str_offsets_base = uvalue; break; @@ -3811,6 +3832,7 @@ process_debug_info (struct dwarf_section * section, debug_information [unit].base_address = 0; debug_information [unit].addr_base = DEBUG_INFO_UNAVAILABLE; debug_information [unit].ranges_base = DEBUG_INFO_UNAVAILABLE; + debug_information [unit].rnglists_base = 0; debug_information [unit].loc_offsets = NULL; debug_information [unit].have_frame_base = NULL; debug_information [unit].max_loc_offsets = 0; @@ -7940,7 +7962,7 @@ display_debug_ranges_list (unsigned char * start, } } -static void +static unsigned char * display_debug_rnglists_list (unsigned char * start, unsigned char * finish, unsigned int pointer_size, @@ -8050,40 +8072,28 @@ display_debug_rnglists_list (unsigned char * start, putchar ('\n'); } + + return start; } static int -display_debug_ranges (struct dwarf_section *section, - void *file ATTRIBUTE_UNUSED) +display_debug_rnglists (struct dwarf_section *section) { unsigned char * start = section->start; - unsigned char * last_start = start; - dwarf_vma bytes = section->size; - unsigned char * section_begin = start; - unsigned char * finish = start + bytes; - unsigned int num_range_list, i; - struct range_entry * range_entries; - struct range_entry * range_entry_fill; - int is_rnglists = strstr (section->name, "debug_rnglists") != NULL; - /* Initialize it due to a false compiler warning. */ - unsigned char address_size = 0; - dwarf_vma last_offset = 0; - unsigned int offset_size = 0; - - if (bytes == 0) - { - printf (_("\nThe %s section is empty.\n"), section->name); - return 0; - } - - introduce (section, false); + unsigned char * finish = start + section->size; - if (is_rnglists) + while (start < finish) { + unsigned char * table_start; + dwarf_vma offset = start - section->start; + unsigned char * end; dwarf_vma initial_length; unsigned char segment_selector_size; unsigned int offset_entry_count; + unsigned int i; unsigned short version; + unsigned char address_size = 0; + unsigned char offset_size; /* Get and check the length of the block. */ SAFE_BYTE_GET_AND_INC (initial_length, start, 4, finish); @@ -8103,9 +8113,7 @@ display_debug_ranges (struct dwarf_section *section, not complain if it is inaccurate (and probably negative). It is copied from .debug_line handling code. */ if (reloc_at (section, (start - section->start) - offset_size)) - { - initial_length = finish - start; - } + initial_length = finish - start; else { warn (_("The length field (0x%lx) in the debug_rnglists header is wrong - the section is too small\n"), @@ -8114,12 +8122,15 @@ display_debug_ranges (struct dwarf_section *section, } } + end = start + initial_length; + /* Get the other fields in the header. */ SAFE_BYTE_GET_AND_INC (version, start, 2, finish); SAFE_BYTE_GET_AND_INC (address_size, start, 1, finish); SAFE_BYTE_GET_AND_INC (segment_selector_size, start, 1, finish); SAFE_BYTE_GET_AND_INC (offset_entry_count, start, 4, finish); + printf (_(" Table at Offset: 0x%s:\n"), dwarf_vmatoa ("x", offset)); printf (_(" Length: 0x%s\n"), dwarf_vmatoa ("x", initial_length)); printf (_(" DWARF version: %u\n"), version); printf (_(" Address size: %u\n"), address_size); @@ -8142,6 +8153,8 @@ display_debug_ranges (struct dwarf_section *section, return 0; } + table_start = start; + if (offset_entry_count != 0) { printf (_("\n Offsets starting at 0x%lx:\n"), (long)(start - section->start)); @@ -8166,8 +8179,60 @@ display_debug_ranges (struct dwarf_section *section, } } } + else + offset_entry_count = 1; + + for (i = 0; i < offset_entry_count; i++) + { + dwarf_vma indx = start - table_start; + + offset = start - section->start; + printf (_("\n Offset: %lx, Index: 0x%s\n"), + (long) offset, dwarf_vmatoa ("x", indx)); + printf (_(" Offset Begin End\n")); + start = display_debug_rnglists_list + (start, end, address_size, offset, 0, offset_size); + if (start >= end) + break; + } + + start = end; + + if (start < finish) + putchar ('\n'); } - + + return 1; +} + +static int +display_debug_ranges (struct dwarf_section *section, + void *file ATTRIBUTE_UNUSED) +{ + unsigned char * start = section->start; + unsigned char * last_start = start; + dwarf_vma bytes = section->size; + unsigned char * section_begin = start; + unsigned char * finish = start + bytes; + unsigned int num_range_list, i; + struct range_entry * range_entries; + struct range_entry * range_entry_fill; + int is_rnglists = strstr (section->name, "debug_rnglists") != NULL; + /* Initialize it due to a false compiler warning. */ + unsigned char address_size = 0; + dwarf_vma last_offset = 0; + + if (bytes == 0) + { + printf (_("\nThe %s section is empty.\n"), section->name); + return 0; + } + + introduce (section, false); + + if (is_rnglists) + return display_debug_rnglists (section); + if (load_debug_info (file) == 0) { warn (_("Unable to load/parse the .debug_info section, so cannot interpret the %s section.\n"), @@ -8177,15 +8242,7 @@ display_debug_ranges (struct dwarf_section *section, num_range_list = 0; for (i = 0; i < num_debug_info_entries; i++) - { - if (debug_information [i].dwarf_version < 5 && is_rnglists) - /* Skip .debug_rnglists reference. */ - continue; - if (debug_information [i].dwarf_version >= 5 && !is_rnglists) - /* Skip .debug_range reference. */ - continue; - num_range_list += debug_information [i].num_range_lists; - } + num_range_list += debug_information [i].num_range_lists; if (num_range_list == 0) { @@ -8204,13 +8261,6 @@ display_debug_ranges (struct dwarf_section *section, debug_info *debug_info_p = &debug_information[i]; unsigned int j; - if (debug_information [i].dwarf_version < 5 && is_rnglists) - /* Skip .debug_rnglists reference. */ - continue; - if (debug_information [i].dwarf_version >= 5 && !is_rnglists) - /* Skip .debug_range reference. */ - continue; - for (j = 0; j < debug_info_p->num_range_lists; j++) { range_entry_fill->ranges_offset = debug_info_p->range_lists[j]; @@ -8287,12 +8337,8 @@ display_debug_ranges (struct dwarf_section *section, start = next; last_start = next; - if (is_rnglists) - display_debug_rnglists_list - (start, finish, pointer_size, offset, base_address, offset_size); - else - display_debug_ranges_list - (start, finish, pointer_size, offset, base_address); + display_debug_ranges_list + (start, finish, pointer_size, offset, base_address); } putchar ('\n'); |