diff options
Diffstat (limited to 'gold/dwarf_reader.cc')
-rw-r--r-- | gold/dwarf_reader.cc | 75 |
1 files changed, 54 insertions, 21 deletions
diff --git a/gold/dwarf_reader.cc b/gold/dwarf_reader.cc index 4233954..3aad27f 100644 --- a/gold/dwarf_reader.cc +++ b/gold/dwarf_reader.cc @@ -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_; |