mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 04:24:43 +00:00
[gdb/symtab] Improve invalid range check in create_addrmap_from_gdb_index
When running test-case gdb.tui/tui-missing-src.exp with target board gold-gdb-index (and likewise fission and fission-dwp) on aarch64-linux, I run into: ... FAIL: gdb.tui/tui-missing-src.exp: checking if inside f2 () ... Looking at the gold-gdb-index case, the problem is caused by the address table of the .gdb_index section: ... Address table: 000000000040066c 0000000000400694 0 000000000040053f 0000000000400563 1 ... The address range for f2 is [0x400694, 0x4006b8), but the address table says it's [0x40053f, 0x400563). The address 0x40053f is not even in a section: ... [Nr] Name Type Address Off Size ES Flg Lk Inf Al ... [12] .plt PROGBITS 00000000004004b8 0004b8 000050 10 AX 0 0 8 [13] .text PROGBITS 0000000000400540 000540 000178 00 AX 0 0 64 ... but part of the hole [0x400508, 0x400540) in between .plt and .text. Detect this in the invalid range check in create_addrmap_from_gdb_index. Tested on aarch64-linux. Approved-By: Simon Marchi <simon.marchi@efficios.com>
This commit is contained in:
@@ -597,13 +597,46 @@ static bool
|
||||
create_addrmap_from_gdb_index (dwarf2_per_objfile *per_objfile,
|
||||
mapped_gdb_index *index)
|
||||
{
|
||||
const gdb_byte *iter, *end;
|
||||
objfile *objfile = per_objfile->objfile;
|
||||
|
||||
addrmap_mutable mutable_map;
|
||||
|
||||
iter = index->address_table.data ();
|
||||
end = iter + index->address_table.size ();
|
||||
/* Build an unrelocated address map of the sections in this objfile. */
|
||||
addrmap_mutable sect_map;
|
||||
for (obj_section &s : objfile->sections ())
|
||||
{
|
||||
if (s.addr_unrel () >= s.endaddr_unrel ())
|
||||
continue;
|
||||
|
||||
CORE_ADDR start = CORE_ADDR (s.addr_unrel ());
|
||||
CORE_ADDR end_inclusive = CORE_ADDR (s.endaddr_unrel ()) - 1;
|
||||
sect_map.set_empty (start, end_inclusive, &s);
|
||||
}
|
||||
|
||||
auto find_section
|
||||
= [&] (ULONGEST addr, struct obj_section *&cached_section)
|
||||
{
|
||||
if (cached_section != nullptr
|
||||
&& cached_section->contains (unrelocated_addr (addr)))
|
||||
return cached_section;
|
||||
|
||||
cached_section = (struct obj_section *) sect_map.find (addr);
|
||||
return cached_section;
|
||||
};
|
||||
|
||||
auto invalid_range_warning = [&] (ULONGEST lo, ULONGEST hi)
|
||||
{
|
||||
warning (_(".gdb_index address table has invalid range (%s - %s),"
|
||||
" ignoring .gdb_index"),
|
||||
hex_string (lo), hex_string (hi));
|
||||
return false;
|
||||
};
|
||||
|
||||
/* Cache the section for possible re-use on the next entry. */
|
||||
struct obj_section *prev_sect = nullptr;
|
||||
|
||||
const gdb_byte *iter = index->address_table.data ();
|
||||
const gdb_byte *end = iter + index->address_table.size ();
|
||||
while (iter < end)
|
||||
{
|
||||
ULONGEST hi, lo, cu_index;
|
||||
@@ -615,12 +648,7 @@ create_addrmap_from_gdb_index (dwarf2_per_objfile *per_objfile,
|
||||
iter += 4;
|
||||
|
||||
if (lo >= hi)
|
||||
{
|
||||
warning (_(".gdb_index address table has invalid range (%s - %s),"
|
||||
" ignoring .gdb_index"),
|
||||
hex_string (lo), hex_string (hi));
|
||||
return false;
|
||||
}
|
||||
return invalid_range_warning (lo, hi);
|
||||
|
||||
if (cu_index >= index->units.size ())
|
||||
{
|
||||
@@ -630,8 +658,16 @@ create_addrmap_from_gdb_index (dwarf2_per_objfile *per_objfile,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Variable hi is the exclusive upper bound, get the inclusive one. */
|
||||
CORE_ADDR hi_incl = hi - 1;
|
||||
|
||||
struct obj_section *lo_sect = find_section (lo, prev_sect);
|
||||
struct obj_section *hi_sect = find_section (hi_incl, prev_sect);
|
||||
if (lo_sect == nullptr || hi_sect == nullptr)
|
||||
return invalid_range_warning (lo, hi);
|
||||
|
||||
bool full_range_p
|
||||
= mutable_map.set_empty (lo, hi - 1, index->units[cu_index]);
|
||||
= mutable_map.set_empty (lo, hi_incl, index->units[cu_index]);
|
||||
if (!full_range_p)
|
||||
{
|
||||
warning (_(".gdb_index address table has a range (%s - %s) that"
|
||||
|
||||
@@ -382,6 +382,12 @@ struct obj_section
|
||||
return bfd_section_vma (this->the_bfd_section) + this->offset ();
|
||||
}
|
||||
|
||||
/* As addr, but returns an unrelocated address. */
|
||||
unrelocated_addr addr_unrel () const
|
||||
{
|
||||
return unrelocated_addr (bfd_section_vma (this->the_bfd_section));
|
||||
}
|
||||
|
||||
/* The one-passed-the-end memory address of the section
|
||||
(vma + size + offset). */
|
||||
CORE_ADDR endaddr () const
|
||||
@@ -389,12 +395,24 @@ struct obj_section
|
||||
return this->addr () + bfd_section_size (this->the_bfd_section);
|
||||
}
|
||||
|
||||
/* As endaddr, but returns an unrelocated address. */
|
||||
unrelocated_addr endaddr_unrel () const
|
||||
{
|
||||
return this->addr_unrel () + bfd_section_size (this->the_bfd_section);
|
||||
}
|
||||
|
||||
/* True if ADDR is in this obj_section, false otherwise. */
|
||||
bool contains (CORE_ADDR addr) const
|
||||
{
|
||||
return addr >= this->addr () && addr < endaddr ();
|
||||
}
|
||||
|
||||
/* As contains (CORE_ADDR), but for an unrelocated address. */
|
||||
bool contains (unrelocated_addr addr) const
|
||||
{
|
||||
return addr >= this->addr_unrel () && addr < endaddr_unrel ();
|
||||
}
|
||||
|
||||
/* BFD section pointer. This is nullptr if the corresponding BFD section is
|
||||
not allocatable (!SEC_ALLOC), in which case this obj_section can be
|
||||
considered NULL / empty. */
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define GDBSUPPORT_COMMON_TYPES_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "gdbsupport/offset-type.h"
|
||||
|
||||
/* * A byte from the program being debugged. */
|
||||
typedef unsigned char gdb_byte;
|
||||
@@ -29,10 +30,8 @@ typedef unsigned char gdb_byte;
|
||||
typedef uint64_t CORE_ADDR;
|
||||
|
||||
/* Like a CORE_ADDR, but not directly convertible. This is used to
|
||||
represent an unrelocated CORE_ADDR. DEFINE_OFFSET_TYPE is not used
|
||||
here because there's no need to add or subtract values of this
|
||||
type. */
|
||||
enum class unrelocated_addr : CORE_ADDR { };
|
||||
represent an unrelocated CORE_ADDR. */
|
||||
DEFINE_OFFSET_TYPE (unrelocated_addr, CORE_ADDR);
|
||||
|
||||
/* LONGEST must be at least as big as CORE_ADDR. */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user