Handle multiple addresses in call_site_target

A large customer program has a function that is partitioned into hot
and cold parts.  A variable in a callee of this function is described
using DW_OP_GNU_entry_value, but gdb gets confused when trying to find
the caller.  I tracked this down to dwarf2_get_pc_bounds interpreting
the function's changes so that the returned low PC is the "wrong"
function.

Intead, when processing DW_TAG_call_site, the low PC of each range in
DW_AT_ranges should be preserved in the call_site_target.  This fixes
the variable lookup in the test case I have.

I didn't write a standalone test for this as it seemed excessively
complicated.
This commit is contained in:
Tom Tromey
2021-11-19 10:12:44 -07:00
parent a0e0ca7044
commit 48ac197b0c
3 changed files with 62 additions and 0 deletions

View File

@@ -1834,6 +1834,8 @@ struct call_site_target
PHYSNAME,
/* A DWARF block. */
DWARF_BLOCK,
/* An array of addresses. */
ADDRESSES,
};
void set_loc_physaddr (CORE_ADDR physaddr)
@@ -1854,6 +1856,13 @@ struct call_site_target
m_loc.dwarf_block = dwarf_block;
}
void set_loc_array (unsigned length, const CORE_ADDR *data)
{
m_loc_kind = ADDRESSES;
m_loc.addresses.length = length;
m_loc.addresses.values = data;
}
/* Callback type for iterate_over_addresses. */
using iterate_ftype = gdb::function_view<void (CORE_ADDR)>;
@@ -1877,6 +1886,12 @@ private:
const char *physname;
/* DWARF block. */
struct dwarf2_locexpr_baton *dwarf_block;
/* Array of addresses. */
struct
{
unsigned length;
const CORE_ADDR *values;
} addresses;
} m_loc;
/* * Discriminant for union field_location. */