From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2126) id 641CC388702E; Tue, 7 Apr 2020 15:56:17 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 641CC388702E Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Tom Tromey To: gdb-cvs@sourceware.org Subject: [binutils-gdb] Support for DW_AT_loclists_base and DW_FORM_loclistx. X-Act-Checkin: binutils-gdb X-Git-Author: nitachra X-Git-Refname: refs/heads/master X-Git-Oldrev: 9f4e76a4b3f61d8182a4a7afe0e479ea7e3093a3 X-Git-Newrev: 4114425321d5c380bc8fb5344db8bc8664c170c6 Message-Id: <20200407155617.641CC388702E@sourceware.org> Date: Tue, 7 Apr 2020 15:56:17 +0000 (GMT) X-BeenThere: gdb-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 07 Apr 2020 15:56:17 -0000 https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=4114425321d5c380bc8fb5344db8bc8664c170c6 commit 4114425321d5c380bc8fb5344db8bc8664c170c6 Author: nitachra Date: Tue Apr 7 18:35:58 2020 +0530 Support for DW_AT_loclists_base and DW_FORM_loclistx. Hi Tom, This is the updated series with ChangeLogs edits. Regards, Nitika Diff: --- gdb/ChangeLog | 15 ++++++ gdb/dwarf2/attribute.c | 3 +- gdb/dwarf2/read.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 1 deletion(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index af53206af46..a9e955304f6 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,18 @@ +2020-04-07 Nitika Achra + + * dwarf2/read.c (cu_debug_loc_section): Added the declaration for the function. + (read_loclist_index): New function definition. + (lookup_loclist_base): New function definition. + (read_loclist_header): New function definition. + (dwarf2_cu): Add loclist_base and loclist_header field. + (dwarf2_locate_dwo_sections): Handle .debug_loclists.dwo section. + (read_full_die_1): Read the value of DW_AT_loclists_base. + (read_attribute_reprocess): Handle DW_FORM_loclistx. + (read_attribute_value): Handle DW_FORM_loclistx. + (skip_one_die): Handle DW_FORM_loclistx. + (loclist_header): New structure declaration. + * dwarf2/attribute.c (form_is_section_offset): Handle DW_FORM_loclistx. + 2020-04-07 Simon Marchi * dwarf2/read.h (struct dwarf2_psymtab): Remove two-parameters diff --git a/gdb/dwarf2/attribute.c b/gdb/dwarf2/attribute.c index 0e5a8c8f536..9ceacf0409e 100644 --- a/gdb/dwarf2/attribute.c +++ b/gdb/dwarf2/attribute.c @@ -78,7 +78,8 @@ attribute::form_is_section_offset () const { return (form == DW_FORM_data4 || form == DW_FORM_data8 - || form == DW_FORM_sec_offset); + || form == DW_FORM_sec_offset + || form == DW_FORM_loclistx); } /* See attribute.h. */ diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 1e593b39065..f1ddadef8d5 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -114,6 +114,12 @@ static int dwarf2_loclist_index; static int dwarf2_locexpr_block_index; static int dwarf2_loclist_block_index; +/* Size of .debug_loclists section header for 32-bit DWARF format. */ +#define LOCLIST_HEADER_SIZE32 12 + +/* Size of .debug_loclists section header for 64-bit DWARF format. */ +#define LOCLIST_HEADER_SIZE64 20 + /* An index into a (C++) symbol name component in a symbol name as recorded in the mapped_index's symbol table. For each C++ symbol in the symbol table, we record one entry for the start of each @@ -346,6 +352,30 @@ dwop_section_names = /* local data types */ +/* The location list section (.debug_loclists) begins with a header, + which contains the following information. */ +struct loclist_header +{ + /* A 4-byte or 12-byte length containing the length of the + set of entries for this compilation unit, not including the + length field itself. */ + unsigned int length; + + /* A 2-byte version identifier. */ + short version; + + /* A 1-byte unsigned integer containing the size in bytes of an address on + the target system. */ + unsigned char addr_size; + + /* A 1-byte unsigned integer containing the size in bytes of a segment selector + on the target system. */ + unsigned char segment_collector_size; + + /* A 4-byte count of the number of offsets that follow the header. */ + unsigned int offset_entry_count; +}; + /* Type used for delaying computation of method physnames. See comments for compute_delayed_physnames. */ struct delayed_method_info @@ -493,6 +523,9 @@ public: whether the DW_AT_ranges attribute came from the skeleton or DWO. */ ULONGEST ranges_base = 0; + /* The DW_AT_loclists_base attribute if present. */ + ULONGEST loclist_base = 0; + /* When reading debug info generated by older versions of rustc, we have to rewrite some union types to be struct types with a variant part. This rewriting must be done after the CU is fully @@ -1303,6 +1336,9 @@ static void read_variable (struct die_info *die, struct dwarf2_cu *cu); static int dwarf2_ranges_read (unsigned, CORE_ADDR *, CORE_ADDR *, struct dwarf2_cu *, dwarf2_psymtab *); +/* Return the .debug_loclists section to use for cu. */ +static struct dwarf2_section_info *cu_debug_loc_section (struct dwarf2_cu *cu); + /* How dwarf2_get_pc_bounds constructed its *LOWPC and *HIGHPC return values. Keep the items ordered with increasing constraints compliance. */ enum pc_bounds_kind @@ -8591,6 +8627,7 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr, case DW_FORM_GNU_addr_index: case DW_FORM_GNU_str_index: case DW_FORM_rnglistx: + case DW_FORM_loclistx: info_ptr = safe_skip_leb128 (info_ptr, buffer_end); break; case DW_FORM_indirect: @@ -12056,6 +12093,11 @@ dwarf2_locate_dwo_sections (bfd *abfd, asection *sectp, void *dwo_sections_ptr) dwo_sections->loc.s.section = sectp; dwo_sections->loc.size = bfd_section_size (sectp); } + else if (section_is_p (sectp->name, &names->loclists_dwo)) + { + dwo_sections->loclists.s.section = sectp; + dwo_sections->loclists.size = bfd_section_size (sectp); + } else if (section_is_p (sectp->name, &names->macinfo_dwo)) { dwo_sections->macinfo.s.section = sectp; @@ -17537,6 +17579,10 @@ read_full_die_1 (const struct die_reader_specs *reader, if (attr != nullptr) cu->str_offsets_base = DW_UNSND (attr); + attr = die->attr (DW_AT_loclists_base); + if (attr != nullptr) + cu->loclist_base = DW_UNSND (attr); + auto maybe_addr_base = die->addr_base (); if (maybe_addr_base.has_value ()) cu->addr_base = *maybe_addr_base; @@ -18375,6 +18421,84 @@ partial_die_info::fixup (struct dwarf2_cu *cu) fixup_called = 1; } +/* Read the .debug_loclists header contents from the given SECTION in the + HEADER. */ +static void +read_loclist_header (struct loclist_header *header, + struct dwarf2_section_info *section) +{ + unsigned int bytes_read; + bfd *abfd = section->get_bfd_owner (); + const gdb_byte *info_ptr = section->buffer; + header->length = read_initial_length (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + header->version = read_2_bytes (abfd, info_ptr); + info_ptr += 2; + header->addr_size = read_1_byte (abfd, info_ptr); + info_ptr += 1; + header->segment_collector_size = read_1_byte (abfd, info_ptr); + info_ptr += 1; + header->offset_entry_count = read_4_bytes (abfd, info_ptr); +} + +/* Return the DW_AT_loclists_base value for the CU. */ +static ULONGEST +lookup_loclist_base (struct dwarf2_cu *cu) +{ + /* For the .dwo unit, the loclist_base points to the first offset following + the header. The header consists of the following entities- + 1. Unit Length (4 bytes for 32 bit DWARF format, and 12 bytes for the 64 + bit format) + 2. version (2 bytes) + 3. address size (1 byte) + 4. segment selector size (1 byte) + 5. offset entry count (4 bytes) + These sizes are derived as per the DWARFv5 standard. */ + if (cu->dwo_unit != nullptr) + { + if (cu->header.initial_length_size == 4) + return LOCLIST_HEADER_SIZE32; + return LOCLIST_HEADER_SIZE64; + } + return cu->loclist_base; +} + +/* Given a DW_FORM_loclistx value LOCLIST_INDEX, fetch the offset from the + array of offsets in the .debug_loclists section. */ +static CORE_ADDR +read_loclist_index (struct dwarf2_cu *cu, ULONGEST loclist_index) +{ + struct dwarf2_per_objfile *dwarf2_per_objfile + = cu->per_cu->dwarf2_per_objfile; + struct objfile *objfile = dwarf2_per_objfile->objfile; + bfd *abfd = objfile->obfd; + ULONGEST loclist_base = lookup_loclist_base (cu); + struct dwarf2_section_info *section = cu_debug_loc_section (cu); + + section->read (objfile); + if (section->buffer == NULL) + complaint (_("DW_FORM_loclistx used without .debug_loclists " + "section [in module %s]"), objfile_name (objfile)); + struct loclist_header header; + read_loclist_header (&header, section); + if (loclist_index >= header.offset_entry_count) + complaint (_("DW_FORM_loclistx pointing outside of " + ".debug_loclists offset array [in module %s]"), + objfile_name (objfile)); + if (loclist_base + loclist_index * cu->header.offset_size + >= section->size) + complaint (_("DW_FORM_loclistx pointing outside of " + ".debug_loclists section [in module %s]"), + objfile_name (objfile)); + const gdb_byte *info_ptr + = section->buffer + loclist_base + loclist_index * cu->header.offset_size; + + if (cu->header.offset_size == 4) + return bfd_get_32 (abfd, info_ptr) + loclist_base; + else + return bfd_get_64 (abfd, info_ptr) + loclist_base; +} + /* Process the attributes that had to be skipped in the first round. These attributes are the ones that need str_offsets_base or addr_base attributes. They could not have been processed in the first round, because at the time @@ -18390,6 +18514,9 @@ read_attribute_reprocess (const struct die_reader_specs *reader, case DW_FORM_GNU_addr_index: DW_ADDR (attr) = read_addr_index (cu, DW_UNSND (attr)); break; + case DW_FORM_loclistx: + DW_UNSND (attr) = read_loclist_index (cu, DW_UNSND (attr)); + break; case DW_FORM_strx: case DW_FORM_strx1: case DW_FORM_strx2: @@ -18494,6 +18621,13 @@ read_attribute_value (const struct die_reader_specs *reader, DW_UNSND (attr) = cu->header.read_offset (abfd, info_ptr, &bytes_read); info_ptr += bytes_read; break; + case DW_FORM_loclistx: + { + *need_reprocess = true; + DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + } + break; case DW_FORM_string: DW_STRING (attr) = read_direct_string (abfd, info_ptr, &bytes_read); DW_STRING_IS_CANONICAL (attr) = 0;