Support for DW_AT_loclists_base and DW_FORM_loclistx.
Hi Tom, This is the updated series with ChangeLogs edits. Regards, Nitika
This commit is contained in:
parent
9f4e76a4b3
commit
4114425321
|
@ -1,3 +1,18 @@
|
|||
2020-04-07 Nitika Achra <Nitika.Achra@amd.com>
|
||||
|
||||
* 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 <simon.marchi@polymtl.ca>
|
||||
|
||||
* dwarf2/read.h (struct dwarf2_psymtab): Remove two-parameters
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue