aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2
diff options
context:
space:
mode:
authornitachra <Nitika.Achra@amd.com>2020-04-07 18:35:58 +0530
committerTom Tromey <tromey@adacore.com>2020-04-07 09:55:35 -0600
commit4114425321d5c380bc8fb5344db8bc8664c170c6 (patch)
tree964f145106ceb15fa5c9b8d7d580a7bfd0335a96 /gdb/dwarf2
parent9f4e76a4b3f61d8182a4a7afe0e479ea7e3093a3 (diff)
downloadgdb-4114425321d5c380bc8fb5344db8bc8664c170c6.zip
gdb-4114425321d5c380bc8fb5344db8bc8664c170c6.tar.gz
gdb-4114425321d5c380bc8fb5344db8bc8664c170c6.tar.bz2
Support for DW_AT_loclists_base and DW_FORM_loclistx.
Hi Tom, This is the updated series with ChangeLogs edits. Regards, Nitika
Diffstat (limited to 'gdb/dwarf2')
-rw-r--r--gdb/dwarf2/attribute.c3
-rw-r--r--gdb/dwarf2/read.c134
2 files changed, 136 insertions, 1 deletions
diff --git a/gdb/dwarf2/attribute.c b/gdb/dwarf2/attribute.c
index 0e5a8c8..9ceacf0 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 1e593b3..f1ddade 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;