From 048fde1ef43843aa67e9ac30829e0d30f019a7dd Mon Sep 17 00:00:00 2001 From: nitachra Date: Sun, 20 Sep 2020 23:22:59 +0530 Subject: [PATCH] DWARFv5: Handle DW_MACRO_define_strx and DW_MACRO_undef_strx macro entries. GDB complaints "During symbol reading: unrecognized DW_MACFINO opcode 0xb" with the testcase given below. Clang is emitting DW_MACRO_define_strx and DW_MACRO_undef_strx entries in .debug_macro section which are not supported in GDB. This patch handles them. DW_MACRO_define_strx and DW_MACRO_undef_strx are added in DWARFv5. They have two operands. The first operand encodes the line number of the #define or #undef macro directive. The second operand identifies a string; it is represented using an unsigned LEB128 encoded value, which is interpreted as a zero-based index into an array of offsets in the .debug_str_offsets section. This is as per the section 6.3.2.1 of Dwarf Debugging Information Format Version 5. Test case used: #define MAX_SIZE 10 int main(void) { int size = 0; size = size + MAX_SIZE; printf("\n The value of size is [%d]\n",size); return 0; } clang -gdwarf-5 -fdebug-macro macro.c -o macro.out Before the patch: gdb/new_gdb/binutils-gdb/build/bin/gdb -q macro.out -ex "set complaints 1" -ex "start" Reading symbols from macro.out... During symbol reading: unrecognized DW_MACFINO opcode 0xb Temporary breakpoint 1 at 0x4004df: file macro.c, line 7. Starting program: /home/nitika/workspace/macro.out Temporary breakpoint 1, main () at macro.c:7 7 int size = 0; (gdb) Tested by running the testsuite before and after the patch with -gdwarf-5 and there is no increase in the number of test cases that fails. Used clang 11.0.0. gdb/ChangeLog: * dwarf2/macro.c (dwarf_decode_macro_bytes): Handle DW_MACRO_define_strx and DW_MACRO_undef_strx. (dwarf_decode_macros): Likewise * dwarf2/read.c (dwarf_decode_macros): Pass str_offsets_base in the parameters which is the value of DW_AT_str_offsets_base. * dwarf2/macro.h (dwarf_decode_macros): Modify the definition to include str_offsets_base. --- gdb/ChangeLog | 10 +++++++ gdb/dwarf2/macro.c | 71 ++++++++++++++++++++++++++++++++++++++++++++-- gdb/dwarf2/macro.h | 3 ++ gdb/dwarf2/read.c | 21 +++++++++++++- 4 files changed, 101 insertions(+), 4 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8081081b8d..9dd2123d60 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +2020-10-02 Nitika Achra + + * dwarf2/macro.c (dwarf_decode_macro_bytes): Handle DW_MACRO_define_strx + and DW_MACRO_undef_strx. + (dwarf_decode_macros): Likewise + * dwarf2/read.c (dwarf_decode_macros): Pass str_offsets_base in the parameters + which is the value of DW_AT_str_offsets_base. + * dwarf2/macro.h (dwarf_decode_macros): Modify the definition to include + str_offsets_base. + 2020-10-01 Kamil Rytarowski * i386-tdep.h (i386nbsd_sc_reg_offset): Remove. diff --git a/gdb/dwarf2/macro.c b/gdb/dwarf2/macro.c index d047d806f8..9208614564 100644 --- a/gdb/dwarf2/macro.c +++ b/gdb/dwarf2/macro.c @@ -427,6 +427,9 @@ dwarf_decode_macro_bytes (dwarf2_per_objfile *per_objfile, const struct dwarf2_section_info *section, int section_is_gnu, int section_is_dwz, unsigned int offset_size, + struct dwarf2_section_info *str_section, + struct dwarf2_section_info *str_offsets_section, + ULONGEST str_offsets_base, htab_t include_hash) { struct objfile *objfile = per_objfile->objfile; @@ -561,6 +564,53 @@ dwarf_decode_macro_bytes (dwarf2_per_objfile *per_objfile, } break; + case DW_MACRO_define_strx: + case DW_MACRO_undef_strx: + { + unsigned int bytes_read; + + int line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + int offset_index = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + + str_offsets_section->read (objfile); + const gdb_byte *info_ptr = (str_offsets_section->buffer + + str_offsets_base + + offset_index * offset_size); + + const char *macinfo_str = (macinfo_type == DW_MACRO_define_strx ? + "DW_MACRO_define_strx" : "DW_MACRO_undef_strx"); + + if (str_offsets_base + offset_index * offset_size + >= str_offsets_section->size) + { + complaint (_("%s pointing outside of .debug_str_offsets section " + "[in module %s]"), macinfo_str, objfile_name (objfile)); + break; + } + + ULONGEST str_offset = read_offset (abfd, info_ptr, offset_size); + + const char *body = str_section->read_string (objfile, str_offset, + macinfo_str); + if (current_file == nullptr) + { + /* DWARF violation as no main source is present. */ + complaint (_("debug info with no main source gives macro %s " + "on line %d: %s"), + macinfo_type == DW_MACRO_define_strx ? _("definition") + : _("undefinition"), line, body); + break; + } + + if (macinfo_type == DW_MACRO_define_strx) + parse_macro_definition (current_file, line, body); + else + macro_undef (current_file, line, body); + } + break; + case DW_MACRO_start_file: { unsigned int bytes_read; @@ -671,7 +721,8 @@ dwarf_decode_macro_bytes (dwarf2_per_objfile *per_objfile, new_mac_ptr, include_mac_end, current_file, lh, section, section_is_gnu, is_dwz, offset_size, - include_hash); + str_section, str_offsets_section, + str_offsets_base, include_hash); htab_remove_elt (include_hash, (void *) new_mac_ptr); } @@ -712,7 +763,9 @@ dwarf_decode_macros (dwarf2_per_objfile *per_objfile, buildsym_compunit *builder, const dwarf2_section_info *section, const struct line_header *lh, unsigned int offset_size, - unsigned int offset, int section_is_gnu) + unsigned int offset, struct dwarf2_section_info *str_section, + struct dwarf2_section_info *str_offsets_section, + ULONGEST str_offsets_base, int section_is_gnu) { bfd *abfd; const gdb_byte *mac_ptr, *mac_end; @@ -814,6 +867,17 @@ dwarf_decode_macros (dwarf2_per_objfile *per_objfile, mac_ptr += offset_size; } break; + case DW_MACRO_define_strx: + case DW_MACRO_undef_strx: + { + unsigned int bytes_read; + + read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + } + break; case DW_MACRO_import: case DW_MACRO_import_sup: @@ -861,5 +925,6 @@ dwarf_decode_macros (dwarf2_per_objfile *per_objfile, *slot = (void *) mac_ptr; dwarf_decode_macro_bytes (per_objfile, builder, abfd, mac_ptr, mac_end, current_file, lh, section, section_is_gnu, 0, - offset_size, include_hash.get ()); + offset_size, str_section, str_offsets_section, + str_offsets_base, include_hash.get ()); } diff --git a/gdb/dwarf2/macro.h b/gdb/dwarf2/macro.h index d874068947..0a7ac55fc0 100644 --- a/gdb/dwarf2/macro.h +++ b/gdb/dwarf2/macro.h @@ -28,6 +28,9 @@ extern void dwarf_decode_macros (dwarf2_per_objfile *per_objfile, const struct line_header *lh, unsigned int offset_size, unsigned int offset, + dwarf2_section_info *str_section, + dwarf2_section_info *str_offsets_section, + ULONGEST str_offsets_base, int section_is_gnu); #endif /* GDB_DWARF2_MACRO_H */ diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 973a375641..eedfea112d 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -23900,8 +23900,27 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset, buildsym_compunit *builder = cu->get_builder (); + struct dwarf2_section_info *str_offsets_section; + struct dwarf2_section_info *str_section; + ULONGEST str_offsets_base; + + if (cu->dwo_unit != nullptr) + { + str_offsets_section = &cu->dwo_unit->dwo_file + ->sections.str_offsets; + str_section = &cu->dwo_unit->dwo_file->sections.str; + str_offsets_base = cu->header.addr_size; + } + else + { + str_offsets_section = &per_objfile->per_bfd->str_offsets; + str_section = &per_objfile->per_bfd->str; + str_offsets_base = *cu->str_offsets_base; + } + dwarf_decode_macros (per_objfile, builder, section, lh, - offset_size, offset, section_is_gnu); + offset_size, offset, str_section, str_offsets_section, + str_offsets_base, section_is_gnu); } /* Return the .debug_loc section to use for CU. -- 2.34.1