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;
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 ())
{
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"
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
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. */
#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;
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. */