mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-12-05 02:47:05 +00:00
2013-07-22 Sterling Augustine <saugustine@google.com>
* dwarf_reader.cc (Dwarf_pubnames_table::read_section): Convert parameter shndx to local variable. Add parameters symtab and symtab_size. Scan over section names. Find relocation section corresponding to current section. Create and initialize reloc_mapper_ and reloc_type_. (Dwarf_pubnames_table::read_header): Add assertion. Change unit_length to off_t. Initialize member unit_length_. Fill in field cu_offset_. * dwarf_reader.h (Dwarf_pubnames_table::Dwarf_pubnames_table): Initialize new fields unit_length_ and cu_offset_. (Dwarf_pubnames_table::read_section): Update prototype. (Dwarf_pubnames_table::cu_offset): New member function. (Dwarf_pubnames_table::subsection_size): Likewise. (Dwarf_pubnames_table::cu_offset_, Dwarf_pubnames_table::unit_length): New fields. (Dwarf_info_reader::symtab, Dwarf_info_reader::symtab_size): Make member functions public. * gdb_index.cc (Gdb_index_info_reader::read_pubnames_and_pubtypes): Update comment. Rework logic. Move repeated parts to... (Gdb_index_info_reader::read_pubtable): ...here. New function. (Gdb_index::Gdb_index): Initialize new fields, pubnames_table_, pubtypes_table_, and stmt_list_offset. (Gdb_index::map_pubtable_to_dies, Gdb_index::find_pubname_offset, Gdb_index::find_pubtype_offset, Gdb_index::map_pubnames_and_types_to_dies): Define new functions. (Gdb_index::pubnames_read): Update prototype and rework logic. * gdb_index.h (Gdb_index_info_reader, Dwarf_pubnames_table): Forward declare. (Gdb_index::map_pubtable_to_dies, Gdb_index::find_pubname_offset, Gdb_index::find_pubtype_offset, Gdb_index::pubnames_table) Gdb_index::pubtypes_table, Gdb_index::map_pubnames_and_types_to_dies, Gdb_index::map_pubtable_to_dies): Declare functions. (Gdb_index::pubnames_read): Update declaration. (Gdb_index::Pubname_offset_map): New type. (Gdb_index::cu_pubname_map_, Gdb_index::cu_pubtype_map_, Gdb_index::pubnames_table_, Gdb_index::pubtypes_table_, Gdb_index::stmt_list_offset): Declare. (Gdb_index::pubnames_shndx_, Gdb_index::pubnames_offet_, Gdb_index::pubtypes_object_, Gdb_index::pubtypes_shndx_) Gdb_index::pubtypes_offset_): Remove.
This commit is contained in:
parent
c8f30dac8c
commit
234d4ab880
@ -1,3 +1,47 @@
|
||||
2013-07-22 Sterling Augustine <saugustine@google.com>
|
||||
|
||||
* dwarf_reader.cc (Dwarf_pubnames_table::read_section):
|
||||
Convert parameter shndx to local variable. Add parameters symtab
|
||||
and symtab_size. Scan over section names. Find relocation
|
||||
section corresponding to current section. Create and initialize
|
||||
reloc_mapper_ and reloc_type_.
|
||||
(Dwarf_pubnames_table::read_header): Add assertion. Change
|
||||
unit_length to off_t. Initialize member unit_length_. Fill in field
|
||||
cu_offset_.
|
||||
* dwarf_reader.h (Dwarf_pubnames_table::Dwarf_pubnames_table):
|
||||
Initialize new fields unit_length_ and cu_offset_.
|
||||
(Dwarf_pubnames_table::read_section): Update prototype.
|
||||
(Dwarf_pubnames_table::cu_offset): New member function.
|
||||
(Dwarf_pubnames_table::subsection_size): Likewise.
|
||||
(Dwarf_pubnames_table::cu_offset_, Dwarf_pubnames_table::unit_length):
|
||||
New fields.
|
||||
(Dwarf_info_reader::symtab, Dwarf_info_reader::symtab_size): Make
|
||||
member functions public.
|
||||
* gdb_index.cc (Gdb_index_info_reader::read_pubnames_and_pubtypes):
|
||||
Update comment. Rework logic. Move repeated parts to...
|
||||
(Gdb_index_info_reader::read_pubtable): ...here. New function.
|
||||
(Gdb_index::Gdb_index): Initialize new fields, pubnames_table_,
|
||||
pubtypes_table_, and stmt_list_offset.
|
||||
(Gdb_index::map_pubtable_to_dies, Gdb_index::find_pubname_offset,
|
||||
Gdb_index::find_pubtype_offset,
|
||||
Gdb_index::map_pubnames_and_types_to_dies): Define new functions.
|
||||
(Gdb_index::pubnames_read): Update prototype and rework logic.
|
||||
* gdb_index.h (Gdb_index_info_reader, Dwarf_pubnames_table):
|
||||
Forward declare.
|
||||
(Gdb_index::map_pubtable_to_dies, Gdb_index::find_pubname_offset,
|
||||
Gdb_index::find_pubtype_offset, Gdb_index::pubnames_table)
|
||||
Gdb_index::pubtypes_table, Gdb_index::map_pubnames_and_types_to_dies,
|
||||
Gdb_index::map_pubtable_to_dies):
|
||||
Declare functions.
|
||||
(Gdb_index::pubnames_read): Update declaration.
|
||||
(Gdb_index::Pubname_offset_map): New type.
|
||||
(Gdb_index::cu_pubname_map_, Gdb_index::cu_pubtype_map_,
|
||||
Gdb_index::pubnames_table_, Gdb_index::pubtypes_table_,
|
||||
Gdb_index::stmt_list_offset): Declare.
|
||||
(Gdb_index::pubnames_shndx_, Gdb_index::pubnames_offet_,
|
||||
Gdb_index::pubtypes_object_, Gdb_index::pubtypes_shndx_)
|
||||
Gdb_index::pubtypes_offset_): Remove.
|
||||
|
||||
2013-07-19 Roland McGrath <mcgrathr@google.com>
|
||||
|
||||
* options.h (General_options): Add -Trodata-segment option.
|
||||
|
@ -478,32 +478,31 @@ Dwarf_ranges_table::lookup_reloc(off_t off, off_t* target_off)
|
||||
|
||||
// class Dwarf_pubnames_table
|
||||
|
||||
// Read the pubnames section SHNDX from the object file.
|
||||
// Read the pubnames section from the object file.
|
||||
|
||||
bool
|
||||
Dwarf_pubnames_table::read_section(Relobj* object, unsigned int shndx)
|
||||
Dwarf_pubnames_table::read_section(Relobj* object, const unsigned char* symtab,
|
||||
off_t symtab_size)
|
||||
{
|
||||
section_size_type buffer_size;
|
||||
unsigned int shndx = 0;
|
||||
|
||||
// If we don't have relocations, shndx will be 0, and
|
||||
// we'll have to hunt for the .debug_pubnames/pubtypes section.
|
||||
if (shndx == 0)
|
||||
// Find the .debug_pubnames/pubtypes section.
|
||||
const char* name = (this->is_pubtypes_
|
||||
? ".debug_pubtypes"
|
||||
: ".debug_pubnames");
|
||||
for (unsigned int i = 1; i < object->shnum(); ++i)
|
||||
{
|
||||
const char* name = (this->is_pubtypes_
|
||||
? ".debug_pubtypes"
|
||||
: ".debug_pubnames");
|
||||
for (unsigned int i = 1; i < object->shnum(); ++i)
|
||||
{
|
||||
if (object->section_name(i) == name)
|
||||
{
|
||||
shndx = i;
|
||||
this->output_section_offset_ = object->output_section_offset(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (shndx == 0)
|
||||
return false;
|
||||
if (object->section_name(i) == name)
|
||||
{
|
||||
shndx = i;
|
||||
this->output_section_offset_ = object->output_section_offset(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (shndx == 0)
|
||||
return false;
|
||||
|
||||
|
||||
this->buffer_ = object->decompressed_section_contents(shndx,
|
||||
&buffer_size,
|
||||
@ -511,6 +510,30 @@ Dwarf_pubnames_table::read_section(Relobj* object, unsigned int shndx)
|
||||
if (this->buffer_ == NULL)
|
||||
return false;
|
||||
this->buffer_end_ = this->buffer_ + buffer_size;
|
||||
|
||||
// For incremental objects, we have no relocations.
|
||||
if (object->is_incremental())
|
||||
return true;
|
||||
|
||||
// Find the relocation section
|
||||
unsigned int reloc_shndx = 0;
|
||||
unsigned int reloc_type = 0;
|
||||
for (unsigned int i = 0; i < object->shnum(); ++i)
|
||||
{
|
||||
reloc_type = object->section_type(i);
|
||||
if ((reloc_type == elfcpp::SHT_REL
|
||||
|| reloc_type == elfcpp::SHT_RELA)
|
||||
&& object->section_info(i) == shndx)
|
||||
{
|
||||
reloc_shndx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this->reloc_mapper_ = make_elf_reloc_mapper(object, symtab, symtab_size);
|
||||
this->reloc_mapper_->initialize(reloc_shndx, reloc_type);
|
||||
this->reloc_type_ = reloc_type;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -519,6 +542,9 @@ Dwarf_pubnames_table::read_section(Relobj* object, unsigned int shndx)
|
||||
bool
|
||||
Dwarf_pubnames_table::read_header(off_t offset)
|
||||
{
|
||||
// Make sure we have actually read the section.
|
||||
gold_assert(this->buffer_ != NULL);
|
||||
|
||||
// Correct the offset. For incremental update links, we have a
|
||||
// relocated offset that is relative to the output section, but
|
||||
// here we need an offset relative to the input section.
|
||||
@ -530,16 +556,20 @@ Dwarf_pubnames_table::read_header(off_t offset)
|
||||
const unsigned char* pinfo = this->buffer_ + offset;
|
||||
|
||||
// Read the unit_length field.
|
||||
uint32_t unit_length = this->dwinfo_->read_from_pointer<32>(pinfo);
|
||||
uint64_t unit_length = this->dwinfo_->read_from_pointer<32>(pinfo);
|
||||
pinfo += 4;
|
||||
if (unit_length == 0xffffffff)
|
||||
{
|
||||
unit_length = this->dwinfo_->read_from_pointer<64>(pinfo);
|
||||
this->unit_length_ = unit_length + 12;
|
||||
pinfo += 8;
|
||||
this->offset_size_ = 8;
|
||||
}
|
||||
else
|
||||
this->offset_size_ = 4;
|
||||
{
|
||||
this->unit_length_ = unit_length + 4;
|
||||
this->offset_size_ = 4;
|
||||
}
|
||||
|
||||
// Check the version.
|
||||
unsigned int version = this->dwinfo_->read_from_pointer<16>(pinfo);
|
||||
@ -547,6 +577,9 @@ Dwarf_pubnames_table::read_header(off_t offset)
|
||||
if (version != 2)
|
||||
return false;
|
||||
|
||||
this->reloc_mapper_->get_reloc_target(pinfo - this->buffer_,
|
||||
&this->cu_offset_);
|
||||
|
||||
// Skip the debug_info_offset and debug_info_size fields.
|
||||
pinfo += 2 * this->offset_size_;
|
||||
|
||||
|
@ -400,7 +400,7 @@ class Dwarf_pubnames_table
|
||||
Dwarf_pubnames_table(Dwarf_info_reader* dwinfo, bool is_pubtypes)
|
||||
: dwinfo_(dwinfo), buffer_(NULL), buffer_end_(NULL), owns_buffer_(false),
|
||||
offset_size_(0), pinfo_(NULL), is_pubtypes_(is_pubtypes),
|
||||
output_section_offset_(0)
|
||||
output_section_offset_(0), unit_length_(0), cu_offset_(0)
|
||||
{ }
|
||||
|
||||
~Dwarf_pubnames_table()
|
||||
@ -409,14 +409,27 @@ class Dwarf_pubnames_table
|
||||
delete[] this->buffer_;
|
||||
}
|
||||
|
||||
// Read the pubnames section SHNDX from the object file.
|
||||
// Read the pubnames section from the object file, using the symbol
|
||||
// table for relocating it.
|
||||
bool
|
||||
read_section(Relobj* object, unsigned int shndx);
|
||||
read_section(Relobj* object, const unsigned char* symbol_table,
|
||||
off_t symtab_size);
|
||||
|
||||
// Read the header for the set at OFFSET.
|
||||
bool
|
||||
read_header(off_t offset);
|
||||
|
||||
// Return the offset to the cu within the info or types section.
|
||||
off_t
|
||||
cu_offset()
|
||||
{ return this->cu_offset_; }
|
||||
|
||||
// Return the size of this subsection of the table. The unit length
|
||||
// doesn't include the size of its own field.
|
||||
off_t
|
||||
subsection_size()
|
||||
{ return this->unit_length_; }
|
||||
|
||||
// Read the next name from the set.
|
||||
const char*
|
||||
next_name();
|
||||
@ -440,6 +453,15 @@ class Dwarf_pubnames_table
|
||||
// relocated data will be relative to the output section, and need
|
||||
// to be corrected before reading data from the input section.
|
||||
uint64_t output_section_offset_;
|
||||
// Fields read from the header.
|
||||
uint64_t unit_length_;
|
||||
off_t cu_offset_;
|
||||
|
||||
// Track relocations for this table so we can find the CUs that
|
||||
// correspond to the subsections.
|
||||
Elf_reloc_mapper* reloc_mapper_;
|
||||
// Type of the relocation section (SHT_REL or SHT_RELA).
|
||||
unsigned int reloc_type_;
|
||||
};
|
||||
|
||||
// This class represents a DWARF Debug Info Entry (DIE).
|
||||
@ -747,6 +769,21 @@ class Dwarf_info_reader
|
||||
set_abbrev_shndx(unsigned int abbrev_shndx)
|
||||
{ this->abbrev_shndx_ = abbrev_shndx; }
|
||||
|
||||
// Return a pointer to the object file's ELF symbol table.
|
||||
const unsigned char*
|
||||
symtab() const
|
||||
{ return this->symtab_; }
|
||||
|
||||
// Return the size of the object file's ELF symbol table.
|
||||
off_t
|
||||
symtab_size() const
|
||||
{ return this->symtab_size_; }
|
||||
|
||||
// Return the offset of the current compilation unit.
|
||||
off_t
|
||||
cu_offset() const
|
||||
{ return this->cu_offset_; }
|
||||
|
||||
protected:
|
||||
// Begin parsing the debug info. This calls visit_compilation_unit()
|
||||
// or visit_type_unit() for each compilation or type unit found in the
|
||||
@ -785,16 +822,6 @@ class Dwarf_info_reader
|
||||
object() const
|
||||
{ return this->object_; }
|
||||
|
||||
// Return a pointer to the object file's ELF symbol table.
|
||||
const unsigned char*
|
||||
symtab() const
|
||||
{ return this->symtab_; }
|
||||
|
||||
// Return the size of the object file's ELF symbol table.
|
||||
off_t
|
||||
symtab_size() const
|
||||
{ return this->symtab_size_; }
|
||||
|
||||
// Checkpoint the relocation tracker.
|
||||
uint64_t
|
||||
get_reloc_checkpoint() const
|
||||
|
@ -273,10 +273,14 @@ class Gdb_index_info_reader : public Dwarf_info_reader
|
||||
void
|
||||
record_cu_ranges(Dwarf_die* die);
|
||||
|
||||
// Read the .debug_pubnames and .debug_pubtypes tables.
|
||||
// Wrapper for read_pubtable.
|
||||
bool
|
||||
read_pubnames_and_pubtypes(Dwarf_die* die);
|
||||
|
||||
// Read the .debug_pubnames and .debug_pubtypes tables.
|
||||
bool
|
||||
read_pubtable(Dwarf_pubnames_table* table, off_t offset);
|
||||
|
||||
// Clear the declarations map.
|
||||
void
|
||||
clear_declarations();
|
||||
@ -851,69 +855,86 @@ Gdb_index_info_reader::record_cu_ranges(Dwarf_die* die)
|
||||
}
|
||||
}
|
||||
|
||||
// Read table and add the relevant names to the index. Returns true
|
||||
// if any names were added.
|
||||
|
||||
bool
|
||||
Gdb_index_info_reader::read_pubtable(Dwarf_pubnames_table* table, off_t offset)
|
||||
{
|
||||
// If we couldn't read the section when building the cu_pubname_map,
|
||||
// then we won't find any pubnames now.
|
||||
if (table == NULL)
|
||||
return false;
|
||||
|
||||
if (!table->read_header(offset))
|
||||
return false;
|
||||
while (true)
|
||||
{
|
||||
const char* name = table->next_name();
|
||||
if (name == NULL)
|
||||
break;
|
||||
|
||||
this->gdb_index_->add_symbol(this->cu_index_, name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read the .debug_pubnames and .debug_pubtypes tables for the CU or TU.
|
||||
// Returns TRUE if either a pubnames or pubtypes section was found.
|
||||
|
||||
bool
|
||||
Gdb_index_info_reader::read_pubnames_and_pubtypes(Dwarf_die* die)
|
||||
{
|
||||
bool ret = false;
|
||||
// We use stmt_list_off as a unique identifier for the
|
||||
// compilation unit and its associated type units.
|
||||
unsigned int shndx;
|
||||
off_t stmt_list_off = die->ref_attribute (elfcpp::DW_AT_stmt_list,
|
||||
&shndx);
|
||||
// Look for the attr as either a flag or a ref.
|
||||
off_t offset = die->ref_attribute(elfcpp::DW_AT_GNU_pubnames, &shndx);
|
||||
|
||||
// If we find a DW_AT_GNU_pubnames attribute, read the pubnames table.
|
||||
unsigned int pubnames_shndx;
|
||||
off_t pubnames_offset = die->ref_attribute(elfcpp::DW_AT_GNU_pubnames,
|
||||
&pubnames_shndx);
|
||||
if (pubnames_offset != -1)
|
||||
// Newer versions of GCC generate CUs, but not TUs, with
|
||||
// DW_AT_FORM_flag_present.
|
||||
unsigned int flag = die->uint_attribute(elfcpp::DW_AT_GNU_pubnames);
|
||||
if (offset == -1 && flag == 0)
|
||||
{
|
||||
if (this->gdb_index_->pubnames_read(this->object(), pubnames_shndx,
|
||||
pubnames_offset))
|
||||
ret = true;
|
||||
// Didn't find the attribute.
|
||||
if (die->tag() == elfcpp::DW_TAG_type_unit)
|
||||
{
|
||||
// If die is a TU, then it might correspond to a CU which we
|
||||
// have read. If it does, then no need to read the pubnames.
|
||||
// If it doesn't, then the caller will have to parse the
|
||||
// dies manually to find the names.
|
||||
return this->gdb_index_->pubnames_read(this->object(),
|
||||
stmt_list_off);
|
||||
}
|
||||
else
|
||||
{
|
||||
Dwarf_pubnames_table pubnames(this, false);
|
||||
if (!pubnames.read_section(this->object(), pubnames_shndx))
|
||||
return false;
|
||||
if (!pubnames.read_header(pubnames_offset))
|
||||
return false;
|
||||
while (true)
|
||||
{
|
||||
const char* name = pubnames.next_name();
|
||||
if (name == NULL)
|
||||
break;
|
||||
this->gdb_index_->add_symbol(this->cu_index_, name);
|
||||
}
|
||||
ret = true;
|
||||
}
|
||||
{
|
||||
// No attribute on the CU means that no pubnames were read.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If we find a DW_AT_GNU_pubtypes attribute, read the pubtypes table.
|
||||
unsigned int pubtypes_shndx;
|
||||
off_t pubtypes_offset = die->ref_attribute(elfcpp::DW_AT_GNU_pubtypes,
|
||||
&pubtypes_shndx);
|
||||
if (pubtypes_offset != -1)
|
||||
{
|
||||
if (this->gdb_index_->pubtypes_read(this->object(),
|
||||
pubtypes_shndx, pubtypes_offset))
|
||||
ret = true;
|
||||
else
|
||||
{
|
||||
Dwarf_pubnames_table pubtypes(this, true);
|
||||
if (!pubtypes.read_section(this->object(), pubtypes_shndx))
|
||||
return false;
|
||||
if (!pubtypes.read_header(pubtypes_offset))
|
||||
return false;
|
||||
while (true)
|
||||
{
|
||||
const char* name = pubtypes.next_name();
|
||||
if (name == NULL)
|
||||
break;
|
||||
this->gdb_index_->add_symbol(this->cu_index_, name);
|
||||
}
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
// We found the attribute, so we can check if the corresponding
|
||||
// pubnames have been read.
|
||||
if (this->gdb_index_->pubnames_read(this->object(), stmt_list_off))
|
||||
return true;
|
||||
|
||||
return ret;
|
||||
this->gdb_index_->set_pubnames_read(this->object(), stmt_list_off);
|
||||
|
||||
// We have an attribute, and the pubnames haven't been read, so read
|
||||
// them.
|
||||
bool names = false;
|
||||
// In some of the cases, we could rely on the previous value of
|
||||
// offset here, but sorting out which cases complicates the logic
|
||||
// enough that it isn't worth it. So just look up the offset again.
|
||||
offset = this->gdb_index_->find_pubname_offset(this->cu_offset());
|
||||
names = this->read_pubtable(this->gdb_index_->pubnames_table(), offset);
|
||||
|
||||
bool types = false;
|
||||
offset = this->gdb_index_->find_pubtype_offset(this->cu_offset());
|
||||
types = this->read_pubtable(this->gdb_index_->pubtypes_table(), offset);
|
||||
return names || types;
|
||||
}
|
||||
|
||||
// Clear the declarations map.
|
||||
@ -952,6 +973,8 @@ Gdb_index_info_reader::print_stats()
|
||||
|
||||
Gdb_index::Gdb_index(Output_section* gdb_index_section)
|
||||
: Output_section_data(4),
|
||||
pubnames_table_(NULL),
|
||||
pubtypes_table_(NULL),
|
||||
gdb_index_section_(gdb_index_section),
|
||||
comp_units_(),
|
||||
type_units_(),
|
||||
@ -965,11 +988,7 @@ Gdb_index::Gdb_index(Output_section* gdb_index_section)
|
||||
cu_pool_offset_(0),
|
||||
stringpool_offset_(0),
|
||||
pubnames_object_(NULL),
|
||||
pubnames_shndx_(0),
|
||||
pubnames_offset_(0),
|
||||
pubtypes_object_(NULL),
|
||||
pubtypes_shndx_(0),
|
||||
pubtypes_offset_(0)
|
||||
stmt_list_offset_(-1)
|
||||
{
|
||||
this->gdb_symtab_ = new Gdb_hashtab<Gdb_symbol>();
|
||||
}
|
||||
@ -983,6 +1002,93 @@ Gdb_index::~Gdb_index()
|
||||
delete this->cu_vector_list_[i];
|
||||
}
|
||||
|
||||
|
||||
// Scan the pubnames and pubtypes sections and build a map of the
|
||||
// various cus and tus they refer to, so we can process the entries
|
||||
// when we encounter the die for that cu or tu.
|
||||
// Return the just-read table so it can be cached.
|
||||
|
||||
Dwarf_pubnames_table*
|
||||
Gdb_index::map_pubtable_to_dies(unsigned int attr,
|
||||
Gdb_index_info_reader* dwinfo,
|
||||
Relobj* object,
|
||||
const unsigned char* symbols,
|
||||
off_t symbols_size)
|
||||
{
|
||||
uint64_t section_offset = 0;
|
||||
Dwarf_pubnames_table* table;
|
||||
Pubname_offset_map* map;
|
||||
|
||||
if (attr == elfcpp::DW_AT_GNU_pubnames)
|
||||
{
|
||||
table = new Dwarf_pubnames_table(dwinfo, false);
|
||||
map = &this->cu_pubname_map_;
|
||||
}
|
||||
else
|
||||
{
|
||||
table = new Dwarf_pubnames_table(dwinfo, true);
|
||||
map = &this->cu_pubtype_map_;
|
||||
}
|
||||
|
||||
map->clear();
|
||||
if (!table->read_section(object, symbols, symbols_size))
|
||||
return NULL;
|
||||
|
||||
while (table->read_header(section_offset))
|
||||
{
|
||||
map->insert(std::make_pair(table->cu_offset(), section_offset));
|
||||
section_offset += table->subsection_size();
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
// Wrapper for map_pubtable_to_dies
|
||||
|
||||
void
|
||||
Gdb_index::map_pubnames_and_types_to_dies(Gdb_index_info_reader* dwinfo,
|
||||
Relobj* object,
|
||||
const unsigned char* symbols,
|
||||
off_t symbols_size)
|
||||
{
|
||||
// This is a new object, so reset the relevant variables.
|
||||
this->pubnames_object_ = object;
|
||||
this->stmt_list_offset_ = -1;
|
||||
|
||||
delete this->pubnames_table_;
|
||||
this->pubnames_table_
|
||||
= this->map_pubtable_to_dies(elfcpp::DW_AT_GNU_pubnames, dwinfo,
|
||||
object, symbols, symbols_size);
|
||||
delete this->pubtypes_table_;
|
||||
this->pubtypes_table_
|
||||
= this->map_pubtable_to_dies(elfcpp::DW_AT_GNU_pubtypes, dwinfo,
|
||||
object, symbols, symbols_size);
|
||||
}
|
||||
|
||||
// Given a cu_offset, find the associated section of the pubnames
|
||||
// table.
|
||||
|
||||
off_t
|
||||
Gdb_index::find_pubname_offset(off_t cu_offset)
|
||||
{
|
||||
Pubname_offset_map::iterator it = this->cu_pubname_map_.find(cu_offset);
|
||||
if (it != this->cu_pubname_map_.end())
|
||||
return it->second;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Given a cu_offset, find the associated section of the pubnames
|
||||
// table.
|
||||
|
||||
off_t
|
||||
Gdb_index::find_pubtype_offset(off_t cu_offset)
|
||||
{
|
||||
Pubname_offset_map::iterator it = this->cu_pubtype_map_.find(cu_offset);
|
||||
if (it != this->cu_pubtype_map_.end())
|
||||
return it->second;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Scan a .debug_info or .debug_types input section.
|
||||
|
||||
void
|
||||
@ -998,6 +1104,8 @@ Gdb_index::scan_debug_info(bool is_type_unit,
|
||||
symbols, symbols_size,
|
||||
shndx, reloc_shndx,
|
||||
reloc_type, this);
|
||||
if (object != this->pubnames_object_)
|
||||
map_pubnames_and_types_to_dies(&dwinfo, object, symbols, symbols_size);
|
||||
dwinfo.parse();
|
||||
}
|
||||
|
||||
@ -1035,34 +1143,25 @@ Gdb_index::add_symbol(int cu_index, const char* sym_name)
|
||||
cu_vec->push_back(cu_index);
|
||||
}
|
||||
|
||||
// Return TRUE if we have already processed the pubnames set at
|
||||
// OFFSET in section SHNDX
|
||||
// Return TRUE if we have already processed the pubnames associated
|
||||
// with the statement list at the given OFFSET.
|
||||
|
||||
bool
|
||||
Gdb_index::pubnames_read(const Relobj* object, unsigned int shndx, off_t offset)
|
||||
Gdb_index::pubnames_read(const Relobj* object, off_t offset)
|
||||
{
|
||||
bool ret = (this->pubnames_object_ == object
|
||||
&& this->pubnames_shndx_ == shndx
|
||||
&& this->pubnames_offset_ == offset);
|
||||
this->pubnames_object_ = object;
|
||||
this->pubnames_shndx_ = shndx;
|
||||
this->pubnames_offset_ = offset;
|
||||
&& this->stmt_list_offset_ == offset);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Return TRUE if we have already processed the pubtypes set at
|
||||
// OFFSET in section SHNDX
|
||||
// Record that we have processed the pubnames associated with the
|
||||
// statement list for OBJECT at the given OFFSET.
|
||||
|
||||
bool
|
||||
Gdb_index::pubtypes_read(const Relobj* object, unsigned int shndx, off_t offset)
|
||||
void
|
||||
Gdb_index::set_pubnames_read(const Relobj* object, off_t offset)
|
||||
{
|
||||
bool ret = (this->pubtypes_object_ == object
|
||||
&& this->pubtypes_shndx_ == shndx
|
||||
&& this->pubtypes_offset_ == offset);
|
||||
this->pubtypes_object_ = object;
|
||||
this->pubtypes_shndx_ = shndx;
|
||||
this->pubtypes_offset_ = offset;
|
||||
return ret;
|
||||
this->pubnames_object_ = object;
|
||||
this->stmt_list_offset_ = offset;
|
||||
}
|
||||
|
||||
// Set the size of the .gdb_index section.
|
||||
|
@ -42,6 +42,8 @@ class Sized_relobj;
|
||||
class Dwarf_range_list;
|
||||
template <typename T>
|
||||
class Gdb_hashtab;
|
||||
class Gdb_index_info_reader;
|
||||
class Dwarf_pubnames_table;
|
||||
|
||||
// This class manages the .gdb_index section, which is a fast
|
||||
// lookup table for DWARF information used by the gdb debugger.
|
||||
@ -91,15 +93,35 @@ class Gdb_index : public Output_section_data
|
||||
void
|
||||
add_symbol(int cu_index, const char* sym_name);
|
||||
|
||||
// Return TRUE if we have already processed the pubnames set for
|
||||
// OBJECT at OFFSET in section SHNDX
|
||||
bool
|
||||
pubnames_read(const Relobj* object, unsigned int shndx, off_t offset);
|
||||
// Return the offset into the pubnames table for the cu at the given
|
||||
// offset.
|
||||
off_t
|
||||
find_pubname_offset(off_t cu_offset);
|
||||
|
||||
// Return TRUE if we have already processed the pubtypes set for
|
||||
// OBJECT at OFFSET in section SHNDX
|
||||
// Return the offset into the pubtypes table for the cu at the
|
||||
// given offset.
|
||||
off_t
|
||||
find_pubtype_offset(off_t cu_offset);
|
||||
|
||||
// Return TRUE if we have already processed the pubnames and types
|
||||
// set for OBJECT of the CUs and TUS associated with the statement
|
||||
// list at OFFSET.
|
||||
bool
|
||||
pubtypes_read(const Relobj* object, unsigned int shndx, off_t offset);
|
||||
pubnames_read(const Relobj* object, off_t offset);
|
||||
|
||||
// Record that we have already read the pubnames associated with
|
||||
// OBJECT and OFFSET.
|
||||
void
|
||||
set_pubnames_read(const Relobj* object, off_t offset);
|
||||
|
||||
// Return a pointer to the given table.
|
||||
Dwarf_pubnames_table*
|
||||
pubnames_table()
|
||||
{ return pubnames_table_; }
|
||||
|
||||
Dwarf_pubnames_table*
|
||||
pubtypes_table()
|
||||
{ return pubtypes_table_; }
|
||||
|
||||
// Print usage statistics.
|
||||
static void
|
||||
@ -125,6 +147,21 @@ class Gdb_index : public Output_section_data
|
||||
do_print_to_mapfile(Mapfile* mapfile) const
|
||||
{ mapfile->print_output_data(this, _("** gdb_index")); }
|
||||
|
||||
// Create a map from dies to pubnames.
|
||||
Dwarf_pubnames_table*
|
||||
map_pubtable_to_dies(unsigned int attr,
|
||||
Gdb_index_info_reader* dwinfo,
|
||||
Relobj* object,
|
||||
const unsigned char* symbols,
|
||||
off_t symbols_size);
|
||||
|
||||
// Wrapper for map_pubtable_to_dies
|
||||
void
|
||||
map_pubnames_and_types_to_dies(Gdb_index_info_reader* dwinfo,
|
||||
Relobj* object,
|
||||
const unsigned char* symbols,
|
||||
off_t symbols_size);
|
||||
|
||||
private:
|
||||
// An entry in the compilation unit list.
|
||||
struct Comp_unit
|
||||
@ -178,6 +215,21 @@ class Gdb_index : public Output_section_data
|
||||
|
||||
typedef std::vector<int> Cu_vector;
|
||||
|
||||
typedef Unordered_map<off_t, off_t> Pubname_offset_map;
|
||||
Pubname_offset_map cu_pubname_map_;
|
||||
Pubname_offset_map cu_pubtype_map_;
|
||||
|
||||
// Scan the given pubtable and build a map of the various dies it
|
||||
// refers to, so we can process the entries when we encounter the
|
||||
// die.
|
||||
void
|
||||
map_pubtable_to_dies(Dwarf_pubnames_table* table,
|
||||
Pubname_offset_map* map);
|
||||
|
||||
// Tables to store the pubnames section of the current object.
|
||||
Dwarf_pubnames_table* pubnames_table_;
|
||||
Dwarf_pubnames_table* pubtypes_table_;
|
||||
|
||||
// The .gdb_index section.
|
||||
Output_section* gdb_index_section_;
|
||||
// The list of DWARF compilation units.
|
||||
@ -200,14 +252,10 @@ class Gdb_index : public Output_section_data
|
||||
off_t symtab_offset_;
|
||||
off_t cu_pool_offset_;
|
||||
off_t stringpool_offset_;
|
||||
// Object, section index and offset of last read pubnames section.
|
||||
// Object, stmt list offset of the CUs and TUs associated with the
|
||||
// last read pubnames and pubtypes sections.
|
||||
const Relobj* pubnames_object_;
|
||||
unsigned int pubnames_shndx_;
|
||||
off_t pubnames_offset_;
|
||||
// Object, section index and offset of last read pubtypes section.
|
||||
const Relobj* pubtypes_object_;
|
||||
unsigned int pubtypes_shndx_;
|
||||
off_t pubtypes_offset_;
|
||||
off_t stmt_list_offset_;
|
||||
};
|
||||
|
||||
} // End namespace gold.
|
||||
|
Loading…
Reference in New Issue
Block a user