From: Caroline Tice <cmtice@google.com>
To: Simon Marchi <simark@simark.ca>
Cc: "H.J. Lu" <hjl.tools@gmail.com>,
Eric Christopher <echristo@google.com>,
Tom Tromey <tom@tromey.com>,
Caroline Tice via Gdb-patches <gdb-patches@sourceware.org>
Subject: Re: [PATCH V5] Fix issues with reading rnglists, especially from dwo files, for DWARF v5
Date: Wed, 15 Jul 2020 21:46:20 -0700 [thread overview]
Message-ID: <CABtf2+QRcLtr4PpDzTdUvQHKWE6pCFwTMWdJmb9h06qMa7YVvw@mail.gmail.com> (raw)
In-Reply-To: <fe767f7f-1007-b5a9-4a2d-39e6e63cc81a@simark.ca>
[-- Attachment #1: Type: text/plain, Size: 4763 bytes --]
The attached patch has an updated commit message that explains how to
run the test and what version of clang was used. Other than that it
is identical to the previous patch.
On Wed, Jul 15, 2020 at 7:35 PM Simon Marchi <simark@simark.ca> wrote:
>
> On 2020-07-15 6:35 p.m., Caroline Tice wrote:
> > Thank you for that suggestion!
> >
> > It turns out that I CAN create the .o file with clang, then use that
> > for the basis of my test; linking it with GCC works and gives the
> > results I expect (it fails with ToT GDB , but passes with my patch).
> >
> > In order to make this work, however, I have to make a small change to
> > gdb/testsuite/lib/gdb.exp (in build_executable_from_specs, I have to
> > check to see if the source file is already an object file before
> > trying to compile it into an object file, and if it is an object file,
> > copy it into the proper directory)l
> >
> > Should I add that (and the .o version of the test case) to this patch,
> > or should I make it a separate patch? If the latter (which is what
> > feels right to me), then if this patch can receive final approval (and
> > someone can commit it, as I do not have write privileges to the GDB
> > code base), then I will submit the subsequent patch to replace the
> > current test with the .o version and update gdb/testsuite/lib/gdb.exp
> > to make it work.
>
> I'd be fine merging the patch with the current test and keep working on
> improving the test coverage. I think that we'll need indeed need to do
> a bit of infrastructure work to improve the testing of DWARF5 in general.
>
> Can you please provide a final patch version where you mention in the commit
> message how to run the test in order to provoke a failure. Please make sure
> to include the compiler version as well (output of `clang --version`) because,
> as you said, the code compilers output changes with time. So in order to be
> able to reproduce the failure, it would be useful to know the compiler version.
>
Done.
> I'm not sure what you mean by "the .o version of the test case". Do you
> mean check-in the .o in the git repository? We currently don't check in
> binary test artifacts for GDB. However, I'm of the opinion that it could
> be useful sometimes (like here). But we'd need to have a discussion
> about this first, how we want to do that, which guidelines to follow.
>
I'll submit a separate patch, where it can be discussed.
> About this comment, in your other message:
>
> > I did try, originally, to make this an assembly code test, as I do
> > understand that compilers change, and the code they generate today is
> > not necessarily the code they generate tomorrow. Unfortunately the
> > GNU assembler cannot process the DWARF v5 that is generated by clang
> > (e.g. it can't handle file numbers that start at 0 instead of 1 (which
> > is in the DWARF v5 spec, and which clang generates); and I have not
> > been able to figure out a way to get GDB test to use the clang
> > integrated assembler.
>
> Just wondering, doesn't gcc emit at least *some* DWARF 5 by now? If so,
> can't the GNU assembler deal with it?
>
Not that it matters for this patch, but I believe you are
misunderstanding the situation. GCC *does* emit some DWARF 5, but at
least the GCC version I'm using (Debian 9.3.0-8) does not seem to be
generating DWARF v5 line table sections; the line table section it
generates (when I compile with -gdwarf-5) is a DWARF v3 .debug_line
sections.
In fact my gcc-generated binary has the following debug sections,
which are a mix of various dwarf versions:
.debug_aranges (dwarf v2)
.debug_info (dwarf v5)
.debug_abbrev (dwarf v5)
.debug_line (dwarf v3)
.debug_str
.debug_addr (dwarf v5)
.debug_gnu_pubnames (dwarf v2)
.debug_gnu_pubtypes (dwarf v2)
.debug_rnglists (dwarf v5)
In contrast, here are the sections my clang compiler, when passed
-gdwarf-5 is generating dwarf v5 versions
of nearly all the sections:
.debug_info (dwarf v5)
.debug_abbrev (dwarf v5)
.debug_line (dwarf v5)
.debug_str
.debug_addr (dwarf v5)
.debug_rnglists (dwarf v5)
.debug_str_offsets (dwarf v5)
.debug_gnu_pubnames (dwarf v2)
.debug_gnu_pubtypes (dwarf v2)
.debug_line_str (dwarf v5)
So either the GNU assembler has not been updated to handle DWARF v5
.debug_line file indices because GCC is not yet generating them; or
GCC is not yet generating them because the GNU assembler has not yet
been
updated to handle them. Take your pick.
In any case, I hope my patch is now acceptable! :-)
-- Caroline Tice
cmtice@google.com
> Simon
[-- Attachment #2: v6-0001-Update-GDB-to-fix-issues-with-handling-DWARF-v5-r.patch --]
[-- Type: application/octet-stream, Size: 27644 bytes --]
From f9b52a463039cc7765445e1033cb07514afebf16 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice@google.com>
Date: Wed, 1 Jul 2020 12:39:08 -0700
Subject: [PATCH v6] Update GDB to fix issues with handling DWARF v5 rnglists &
.dwo files.
While experimenting with GDB on DWARF 5 with split debug (dwo files),
I discovered that GDB was not reading the rnglist index
properly (it needed to be reprocessed in the same way the loclist
index does), and that there was no code for reading rnglists out of
dwo files at all. Also, the rnglist address reading function
(dwarf2_rnglists_process) was adding the base address to all rnglist
entries, when it's only supposed to add it to the DW_RLE_offset_pair
entries (http://dwarfstd.org/doc/DWARF5.pdf, p. 53), and was not
handling several entry types.
- Added 'reprocessing' for reading rnglist index (as is done for loclist
index).
- Added code for reading rnglists out of .dwo files.
- Added several missing rnglist forms to dwarf2_rnglists_process.
- Fixed bug that was alwayas adding base address for rnglists (only
one form needs that).
- Updated dwarf2_rnglists_process to read rnglist out of dwo file when
appropriate.
- Added new functions cu_debug_rnglist_section & read_rnglist_index.
- Added new testcase, dw5-rnglist-test.{cc,exp}
Special note about the new testcase:
In order for the test case to test anything meaningful, it must be
compiled with clang, not GCC. The way to do this is as follows:
$ make check RUNTESTFLAGS="CC_FOR_TARGET=/path/to/clang CXX_FOR_TARGET=/path/to/clang++ dw5-rnglist-test.exp"
This following version of clang was used for this testing:
clang version 9.0.1-11
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
---
gdb/dwarf2/read.c | 261 ++++++++++++++----
gdb/testsuite/gdb.dwarf2/dw5-rnglist-test.cc | 97 +++++++
gdb/testsuite/gdb.dwarf2/dw5-rnglist-test.exp | 40 +++
3 files changed, 350 insertions(+), 48 deletions(-)
create mode 100644 gdb/testsuite/gdb.dwarf2/dw5-rnglist-test.cc
create mode 100644 gdb/testsuite/gdb.dwarf2/dw5-rnglist-test.exp
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 558fad74f8..39ed455def 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -132,6 +132,12 @@ static int dwarf2_loclist_block_index;
/* Size of .debug_loclists section header for 64-bit DWARF format. */
#define LOCLIST_HEADER_SIZE64 20
+/* Size of .debug_rnglists section header for 32-bit DWARF format. */
+#define RNGLIST_HEADER_SIZE32 12
+
+/* Size of .debug_rnglists section header for 64-bit DWARF format. */
+#define RNGLIST_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
@@ -340,6 +346,7 @@ static const struct dwop_section_names
struct dwarf2_section_names loclists_dwo;
struct dwarf2_section_names macinfo_dwo;
struct dwarf2_section_names macro_dwo;
+ struct dwarf2_section_names rnglists_dwo;
struct dwarf2_section_names str_dwo;
struct dwarf2_section_names str_offsets_dwo;
struct dwarf2_section_names types_dwo;
@@ -355,6 +362,7 @@ dwop_section_names =
{ ".debug_loclists.dwo", ".zdebug_loclists.dwo" },
{ ".debug_macinfo.dwo", ".zdebug_macinfo.dwo" },
{ ".debug_macro.dwo", ".zdebug_macro.dwo" },
+ { ".debug_rnglists.dwo", ".zdebug_rnglists.dwo" },
{ ".debug_str.dwo", ".zdebug_str.dwo" },
{ ".debug_str_offsets.dwo", ".zdebug_str_offsets.dwo" },
{ ".debug_types.dwo", ".zdebug_types.dwo" },
@@ -364,9 +372,9 @@ dwop_section_names =
/* local data types */
-/* The location list section (.debug_loclists) begins with a header,
- which contains the following information. */
-struct loclist_header
+/* The location list and range list sections (.debug_loclists & .debug_rnglists)
+ begin with a header, which contains the following information. */
+struct loclists_rnglists_header
{
/* A 4-byte or 12-byte length containing the length of the
set of entries for this compilation unit, not including the
@@ -650,6 +658,7 @@ struct dwo_sections
struct dwarf2_section_info loclists;
struct dwarf2_section_info macinfo;
struct dwarf2_section_info macro;
+ struct dwarf2_section_info rnglists;
struct dwarf2_section_info str;
struct dwarf2_section_info str_offsets;
/* In the case of a virtual DWO file, these two are unused. */
@@ -1274,7 +1283,7 @@ static const gdb_byte *read_attribute (const struct die_reader_specs *,
const gdb_byte *, bool *need_reprocess);
static void read_attribute_reprocess (const struct die_reader_specs *reader,
- struct attribute *attr);
+ struct attribute *attr, dwarf_tag tag);
static CORE_ADDR read_addr_index (struct dwarf2_cu *cu, unsigned int addr_index);
@@ -1378,12 +1387,13 @@ static void read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu);
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);
+/* Return the .debug_rnglists section to use for cu. */
+static struct dwarf2_section_info *cu_debug_rnglists_section
+ (struct dwarf2_cu *cu, dwarf_tag tag);
+
/* How dwarf2_get_pc_bounds constructed its *LOWPC and *HIGHPC return
values. Keep the items ordered with increasing constraints compliance. */
enum pc_bounds_kind
@@ -12447,6 +12457,11 @@ dwarf2_locate_dwo_sections (bfd *abfd, asection *sectp, void *dwo_sections_ptr)
dwo_sections->macro.s.section = sectp;
dwo_sections->macro.size = bfd_section_size (sectp);
}
+ else if (section_is_p (sectp->name, &names->rnglists_dwo))
+ {
+ dwo_sections->rnglists.s.section = sectp;
+ dwo_sections->rnglists.size = bfd_section_size (sectp);
+ }
else if (section_is_p (sectp->name, &names->str_dwo))
{
dwo_sections->str.s.section = sectp;
@@ -13791,7 +13806,7 @@ read_variable (struct die_info *die, struct dwarf2_cu *cu)
template <typename Callback>
static bool
dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
- Callback &&callback)
+ dwarf_tag tag, Callback &&callback)
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
struct objfile *objfile = per_objfile->objfile;
@@ -13801,17 +13816,20 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
const gdb_byte *buffer;
CORE_ADDR baseaddr;
bool overflow = false;
+ ULONGEST addr_index;
+ struct dwarf2_section_info *rnglists_section;
base = cu->base_address;
+ rnglists_section = cu_debug_rnglists_section (cu, tag);
+ rnglists_section->read (objfile);
- per_objfile->per_bfd->rnglists.read (objfile);
- if (offset >= per_objfile->per_bfd->rnglists.size)
+ if (offset >= rnglists_section->size)
{
complaint (_("Offset %d out of bounds for DW_AT_ranges attribute"),
offset);
return false;
}
- buffer = per_objfile->per_bfd->rnglists.buffer + offset;
+ buffer = rnglists_section->buffer + offset;
baseaddr = objfile->text_section_offset ();
@@ -13819,8 +13837,8 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
{
/* Initialize it due to a false compiler warning. */
CORE_ADDR range_beginning = 0, range_end = 0;
- const gdb_byte *buf_end = (per_objfile->per_bfd->rnglists.buffer
- + per_objfile->per_bfd->rnglists.size);
+ const gdb_byte *buf_end = (rnglists_section->buffer
+ + rnglists_section->size);
unsigned int bytes_read;
if (buffer == buf_end)
@@ -13842,6 +13860,11 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
base = cu->header.read_address (obfd, buffer, &bytes_read);
buffer += bytes_read;
break;
+ case DW_RLE_base_addressx:
+ addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+ buffer += bytes_read;
+ base = read_addr_index (cu, addr_index);
+ break;
case DW_RLE_start_length:
if (buffer + cu->header.addr_size > buf_end)
{
@@ -13860,6 +13883,19 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
break;
}
break;
+ case DW_RLE_startx_length:
+ addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+ buffer += bytes_read;
+ range_beginning = read_addr_index (cu, addr_index);
+ if (buffer > buf_end)
+ {
+ overflow = true;
+ break;
+ }
+ range_end = (range_beginning
+ + read_unsigned_leb128 (obfd, buffer, &bytes_read));
+ buffer += bytes_read;
+ break;
case DW_RLE_offset_pair:
range_beginning = read_unsigned_leb128 (obfd, buffer, &bytes_read);
buffer += bytes_read;
@@ -13888,6 +13924,19 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
range_end = cu->header.read_address (obfd, buffer, &bytes_read);
buffer += bytes_read;
break;
+ case DW_RLE_startx_endx:
+ addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+ buffer += bytes_read;
+ range_beginning = read_addr_index (cu, addr_index);
+ if (buffer > buf_end)
+ {
+ overflow = true;
+ break;
+ }
+ addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+ buffer += bytes_read;
+ range_end = read_addr_index (cu, addr_index);
+ break;
default:
complaint (_("Invalid .debug_rnglists data (no base address)"));
return false;
@@ -13897,14 +13946,6 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
if (rlet == DW_RLE_base_address)
continue;
- if (!base.has_value ())
- {
- /* We have no valid base address for the ranges
- data. */
- complaint (_("Invalid .debug_rnglists data (no base address)"));
- return false;
- }
-
if (range_beginning > range_end)
{
/* Inverted range entries are invalid. */
@@ -13916,8 +13957,20 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
if (range_beginning == range_end)
continue;
- range_beginning += *base;
- range_end += *base;
+ /* Only DW_RLE_offset_pair needs the base address added. */
+ if (rlet == DW_RLE_offset_pair)
+ {
+ if (!base.has_value ())
+ {
+ /* We have no valid base address for the DW_RLE_offset_pair. */
+ complaint (_("Invalid .debug_rnglists data (no base address for "
+ "DW_RLE_offset_pair)"));
+ return false;
+ }
+
+ range_beginning += *base;
+ range_end += *base;
+ }
/* A not-uncommon case of bad debug info.
Don't pollute the addrmap with bad data. */
@@ -13950,7 +14003,7 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
template <typename Callback>
static int
-dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu,
+dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu, dwarf_tag tag,
Callback &&callback)
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
@@ -13966,7 +14019,7 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu,
CORE_ADDR baseaddr;
if (cu_header->version >= 5)
- return dwarf2_rnglists_process (offset, cu, callback);
+ return dwarf2_rnglists_process (offset, cu, tag, callback);
base = cu->base_address;
@@ -14052,7 +14105,7 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu,
static int
dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
CORE_ADDR *high_return, struct dwarf2_cu *cu,
- dwarf2_psymtab *ranges_pst)
+ dwarf2_psymtab *ranges_pst, dwarf_tag tag)
{
struct objfile *objfile = cu->per_objfile->objfile;
struct gdbarch *gdbarch = objfile->arch ();
@@ -14062,7 +14115,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
CORE_ADDR high = 0;
int retval;
- retval = dwarf2_ranges_process (offset, cu,
+ retval = dwarf2_ranges_process (offset, cu, tag,
[&] (CORE_ADDR range_beginning, CORE_ADDR range_end)
{
if (ranges_pst != NULL)
@@ -14154,8 +14207,14 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
{
/* DW_AT_rnglists_base does not apply to DIEs from the DWO skeleton.
We take advantage of the fact that DW_AT_ranges does not appear
- in DW_TAG_compile_unit of DWO files. */
- int need_ranges_base = die->tag != DW_TAG_compile_unit;
+ in DW_TAG_compile_unit of DWO files.
+
+ Attributes of the form DW_FORM_rnglistx have already had their
+ value changed by read_rnglist_index and already include
+ DW_AT_rnglists_base, so don't need to add the ranges base,
+ either. */
+ int need_ranges_base = (die->tag != DW_TAG_compile_unit
+ && attr->form != DW_FORM_rnglistx);
unsigned int ranges_offset = (DW_UNSND (attr)
+ (need_ranges_base
? cu->ranges_base
@@ -14163,7 +14222,8 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
/* Value of the DW_AT_ranges attribute is the offset in the
.debug_ranges section. */
- if (!dwarf2_ranges_read (ranges_offset, &low, &high, cu, pst))
+ if (!dwarf2_ranges_read (ranges_offset, &low, &high, cu, pst,
+ die->tag))
return PC_BOUNDS_INVALID;
/* Found discontinuous range of addresses. */
ret = PC_BOUNDS_RANGES;
@@ -14325,8 +14385,14 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
{
/* DW_AT_rnglists_base does not apply to DIEs from the DWO skeleton.
We take advantage of the fact that DW_AT_ranges does not appear
- in DW_TAG_compile_unit of DWO files. */
- int need_ranges_base = die->tag != DW_TAG_compile_unit;
+ in DW_TAG_compile_unit of DWO files.
+
+ Attributes of the form DW_FORM_rnglistx have already had their
+ value changed by read_rnglist_index and already include
+ DW_AT_rnglists_base, so don't need to add the ranges base,
+ either. */
+ int need_ranges_base = (die->tag != DW_TAG_compile_unit
+ && attr->form != DW_FORM_rnglistx);
/* The value of the DW_AT_ranges attribute is the offset of the
address range list in the .debug_ranges section. */
@@ -14334,7 +14400,7 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
+ (need_ranges_base ? cu->ranges_base : 0));
std::vector<blockrange> blockvec;
- dwarf2_ranges_process (offset, cu,
+ dwarf2_ranges_process (offset, cu, die->tag,
[&] (CORE_ADDR start, CORE_ADDR end)
{
start += baseaddr;
@@ -18154,8 +18220,13 @@ read_full_die_1 (const struct die_reader_specs *reader,
auto maybe_addr_base = die->addr_base ();
if (maybe_addr_base.has_value ())
cu->addr_base = *maybe_addr_base;
+
+ attr = die->attr (DW_AT_rnglists_base);
+ if (attr != nullptr)
+ cu->ranges_base = DW_UNSND (attr);
+
for (int index : indexes_that_need_reprocess)
- read_attribute_reprocess (reader, &die->attrs[index]);
+ read_attribute_reprocess (reader, &die->attrs[index], die->tag);
*diep = die;
return info_ptr;
}
@@ -18524,7 +18595,7 @@ partial_die_info::read (const struct die_reader_specs *reader,
already been read at this point, so there is no need to wait until
the loop terminates to do the reprocessing. */
if (need_reprocess)
- read_attribute_reprocess (reader, &attr);
+ read_attribute_reprocess (reader, &attr, tag);
/* Store the data if it is of an attribute we want to keep in a
partial symbol table. */
switch (attr.name)
@@ -18670,10 +18741,16 @@ partial_die_info::read (const struct die_reader_specs *reader,
case DW_AT_ranges:
{
- /* It would be nice to reuse dwarf2_get_pc_bounds here,
- but that requires a full DIE, so instead we just
- reimplement it. */
- int need_ranges_base = tag != DW_TAG_compile_unit;
+ /* DW_AT_rnglists_base does not apply to DIEs from the DWO
+ skeleton. We take advantage of the fact the DW_AT_ranges
+ does not appear in DW_TAG_compile_unit of DWO files.
+
+ Attributes of the form DW_FORM_rnglistx have already had
+ their value changed by read_rnglist_index and already
+ include DW_AT_rnglists_base, so don't need to add the ranges
+ base, either. */
+ int need_ranges_base = (tag != DW_TAG_compile_unit
+ && attr.form != DW_FORM_rnglistx);
unsigned int ranges_offset = (DW_UNSND (&attr)
+ (need_ranges_base
? cu->ranges_base
@@ -18682,7 +18759,7 @@ partial_die_info::read (const struct die_reader_specs *reader,
/* Value of the DW_AT_ranges attribute is the offset in the
.debug_ranges section. */
if (dwarf2_ranges_read (ranges_offset, &lowpc, &highpc, cu,
- nullptr))
+ nullptr, tag))
has_pc_info = 1;
}
break;
@@ -19006,11 +19083,11 @@ partial_die_info::fixup (struct dwarf2_cu *cu)
fixup_called = 1;
}
-/* Read the .debug_loclists header contents from the given SECTION in the
- HEADER. */
+/* Read the .debug_loclists or .debug_rnglists header (they are the same format)
+ contents from the given SECTION in the HEADER. */
static void
-read_loclist_header (struct loclist_header *header,
- struct dwarf2_section_info *section)
+read_loclists_rnglists_header (struct loclists_rnglists_header *header,
+ struct dwarf2_section_info *section)
{
unsigned int bytes_read;
bfd *abfd = section->get_bfd_owner ();
@@ -19063,8 +19140,8 @@ read_loclist_index (struct dwarf2_cu *cu, ULONGEST loclist_index)
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);
+ struct loclists_rnglists_header header;
+ read_loclists_rnglists_header (&header, section);
if (loclist_index >= header.offset_entry_count)
complaint (_("DW_FORM_loclistx pointing outside of "
".debug_loclists offset array [in module %s]"),
@@ -19083,13 +19160,68 @@ read_loclist_index (struct dwarf2_cu *cu, ULONGEST loclist_index)
return bfd_get_64 (abfd, info_ptr) + loclist_base;
}
+/* Given a DW_FORM_rnglistx value RNGLIST_INDEX, fetch the offset from the
+ array of offsets in the .debug_rnglists section. */
+static CORE_ADDR
+read_rnglist_index (struct dwarf2_cu *cu, ULONGEST rnglist_index,
+ dwarf_tag tag)
+{
+ struct dwarf2_per_objfile *dwarf2_per_objfile = cu->per_objfile;
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ bfd *abfd = objfile->obfd;
+ ULONGEST rnglist_header_size =
+ (cu->header.initial_length_size == 4 ? RNGLIST_HEADER_SIZE32
+ : RNGLIST_HEADER_SIZE64);
+ ULONGEST rnglist_base =
+ (cu->dwo_unit != nullptr) ? rnglist_header_size : cu->ranges_base;
+ ULONGEST start_offset =
+ rnglist_base + rnglist_index * cu->header.offset_size;
+
+ /* Get rnglists section. */
+ struct dwarf2_section_info *section = cu_debug_rnglists_section (cu, tag);
+
+ /* Read the rnglists section content. */
+ section->read (objfile);
+ if (section->buffer == nullptr)
+ error (_("DW_FORM_rnglistx used without .debug_rnglists section "
+ "[in module %s]"),
+ objfile_name (objfile));
+
+ /* Verify the rnglist index is valid. */
+ struct loclists_rnglists_header header;
+ read_loclists_rnglists_header (&header, section);
+ if (rnglist_index >= header.offset_entry_count)
+ error (_("DW_FORM_rnglistx index pointing outside of "
+ ".debug_rnglists offset array [in module %s]"),
+ objfile_name (objfile));
+
+ /* Validate that the offset is within the section's range. */
+ if (start_offset >= section->size)
+ error (_("DW_FORM_rnglistx pointing outside of "
+ ".debug_rnglists section [in module %s]"),
+ objfile_name (objfile));
+
+ /* Validate that reading won't go beyond the end of the section. */
+ if (start_offset + cu->header.offset_size > rnglist_base + section->size)
+ error (_("Reading DW_FORM_rnglistx index beyond end of"
+ ".debug_rnglists section [in module %s]"),
+ objfile_name (objfile));
+
+ const gdb_byte *info_ptr = section->buffer + start_offset;
+
+ if (cu->header.offset_size == 4)
+ return read_4_bytes (abfd, info_ptr) + rnglist_base;
+ else
+ return read_8_bytes (abfd, info_ptr) + rnglist_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
the values of str_offsets_base or addr_base may not have been known. */
static void
read_attribute_reprocess (const struct die_reader_specs *reader,
- struct attribute *attr)
+ struct attribute *attr, dwarf_tag tag)
{
struct dwarf2_cu *cu = reader->cu;
switch (attr->form)
@@ -19101,6 +19233,9 @@ read_attribute_reprocess (const struct die_reader_specs *reader,
case DW_FORM_loclistx:
DW_UNSND (attr) = read_loclist_index (cu, DW_UNSND (attr));
break;
+ case DW_FORM_rnglistx:
+ DW_UNSND (attr) = read_rnglist_index (cu, DW_UNSND (attr), tag);
+ break;
case DW_FORM_strx:
case DW_FORM_strx1:
case DW_FORM_strx2:
@@ -19282,8 +19417,10 @@ read_attribute_value (const struct die_reader_specs *reader,
DW_SND (attr) = read_signed_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
- case DW_FORM_udata:
case DW_FORM_rnglistx:
+ *need_reprocess = true;
+ /* FALLTHROUGH */
+ case DW_FORM_udata:
DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
@@ -23372,6 +23509,34 @@ cu_debug_loc_section (struct dwarf2_cu *cu)
: &per_objfile->per_bfd->loc);
}
+/* Return the .debug_rnglists section to use for CU. */
+static struct dwarf2_section_info *
+cu_debug_rnglists_section (struct dwarf2_cu *cu, dwarf_tag tag)
+{
+ if (cu->header.version < 5)
+ error (_(".debug_rnglists section cannot be used in DWARF %d"),
+ cu->header.version);
+ struct dwarf2_per_objfile *dwarf2_per_objfile = cu->per_objfile;
+
+ /* Make sure we read the .debug_rnglists section from the file that
+ contains the DW_AT_ranges attribute we are reading. Normally that
+ would be the .dwo file, if there is one. However for DW_TAG_compile_unit
+ or DW_TAG_skeleton unit, we always want to read from objfile/linked
+ program. */
+ if (cu->dwo_unit != nullptr
+ && tag != DW_TAG_compile_unit
+ && tag != DW_TAG_skeleton_unit)
+ {
+ struct dwo_sections *sections = &cu->dwo_unit->dwo_file->sections;
+
+ if (sections->rnglists.size > 0)
+ return §ions->rnglists;
+ else
+ error (_(".debug_rnglists section is missing from .dwo file."));
+ }
+ return &dwarf2_per_objfile->per_bfd->rnglists;
+}
+
/* A helper function that fills in a dwarf2_loclist_baton. */
static void
diff --git a/gdb/testsuite/gdb.dwarf2/dw5-rnglist-test.cc b/gdb/testsuite/gdb.dwarf2/dw5-rnglist-test.cc
new file mode 100644
index 0000000000..81693f569d
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw5-rnglist-test.cc
@@ -0,0 +1,97 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2020 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <iostream>
+#include <vector>
+
+struct node {
+ int id;
+ node *left;
+ node *right;
+ bool visited;
+};
+
+node node_array[50];
+unsigned int CUR_IDX = 0;
+
+node *
+make_node (int val)
+{
+ node *new_node = &(node_array[CUR_IDX++]);
+ new_node->left = NULL;
+ new_node->right = NULL;
+ new_node->id = val;
+ new_node->visited = false;
+
+ return new_node;
+}
+
+void
+tree_insert (node *root, int val)
+{
+ if (val < root->id)
+ {
+ if (root->left)
+ tree_insert (root->left, val);
+ else
+ root->left = make_node(val);
+ }
+ else if (val > root->id)
+ {
+ if (root->right)
+ tree_insert (root->right, val);
+ else
+ root->right = make_node(val);
+ }
+}
+
+void
+inorder (node *root)
+{
+ std::vector<node *> todo;
+ todo.push_back (root);
+ while (!todo.empty())
+ {
+ node *curr = todo.back();
+ todo.pop_back(); /* break-here */
+ if (curr->visited)
+ std::cout << curr->id << " ";
+ else
+ {
+ curr->visited = true;
+ if (curr->right)
+ todo.push_back (curr->right);
+ todo.push_back (curr);
+ if (curr->left)
+ todo.push_back (curr->left);
+ }
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ node *root = make_node (35);
+
+ tree_insert (root, 28);
+ tree_insert (root, 20);
+ tree_insert (root, 60);
+
+ inorder (root);
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.dwarf2/dw5-rnglist-test.exp b/gdb/testsuite/gdb.dwarf2/dw5-rnglist-test.exp
new file mode 100644
index 0000000000..af6c34b5dd
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw5-rnglist-test.exp
@@ -0,0 +1,40 @@
+# Copyright 2020 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Check that GDB can find the variables in a lexical block with a
+# DW_FORM_rnglistx DW_AT_ranges field. This test is intended for DWARF-5,
+# compiled with clang++.
+
+standard_testfile .cc
+
+# This test is intended for targets which support DWARF-5.
+# Since we pass an explicit -gdwarf-5 to the compiler,
+# we let that be the test of whether the target supports it.
+
+if { [prepare_for_testing "failed to prepare" "${testfile}" \
+ $srcfile {debug c++ additional_flags=-gdwarf-5 \
+ additional_flags=-O0}] } {
+ return -1
+}
+
+if ![runto_main] {
+ return -1
+}
+
+gdb_breakpoint [gdb_get_line_number "break-here"]
+gdb_continue_to_breakpoint "break-here" ".* break-here .*"
+
+gdb_test "print curr" "\\\(node \\\*\\\) $hex <node_array>"
+gdb_test "print *curr" "= {id = 35, left = $hex <node_array\\+$decimal>, right = $hex <node_array\\+$decimal>, visited = false}"
--
2.27.0.389.gc38d7665816-goog
next prev parent reply other threads:[~2020-07-16 4:46 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-06-01 17:16 [PATCH] " Caroline Tice
2020-06-01 20:33 ` Tom Tromey
2020-06-02 17:04 ` Caroline Tice
2020-06-03 14:49 ` Tom Tromey
2020-06-04 21:39 ` Caroline Tice
2020-06-09 23:32 ` Caroline Tice
2020-06-16 15:37 ` Caroline Tice
2020-06-18 20:27 ` Tom Tromey
2020-06-23 19:04 ` Caroline Tice
2020-07-01 0:09 ` Caroline Tice
2020-07-01 0:34 ` Simon Marchi
2020-07-01 0:36 ` Simon Marchi
2020-07-01 19:57 ` Caroline Tice
2020-07-02 5:41 ` Simon Marchi
2020-07-03 22:47 ` [PATCH V3] " Caroline Tice
2020-07-04 5:11 ` Simon Marchi
2020-07-09 15:48 ` [PATCH V4] " Caroline Tice
2020-07-11 17:54 ` Simon Marchi
2020-07-14 15:47 ` [PATCH V5] " Caroline Tice
2020-07-15 2:04 ` Simon Marchi
2020-07-15 3:15 ` Simon Marchi
2020-07-15 16:57 ` Caroline Tice
2020-07-15 17:04 ` H.J. Lu
2020-07-15 22:35 ` Caroline Tice
2020-07-16 2:34 ` Simon Marchi
2020-07-16 4:46 ` Caroline Tice [this message]
2020-07-16 15:41 ` Simon Marchi
2020-07-16 15:46 ` Caroline Tice
2020-07-16 16:09 ` Simon Marchi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CABtf2+QRcLtr4PpDzTdUvQHKWE6pCFwTMWdJmb9h06qMa7YVvw@mail.gmail.com \
--to=cmtice@google.com \
--cc=echristo@google.com \
--cc=gdb-patches@sourceware.org \
--cc=hjl.tools@gmail.com \
--cc=simark@simark.ca \
--cc=tom@tromey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox