From 4c4555f730fd0ea82bc8ebaeefe971c92ead6e5d Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 19 Apr 2008 18:33:19 +0000 Subject: * elfcpp_file.h (class Elf_file): Add large_shndx_offset_ field. (Elf_file::large_shndx_offset): New function. (Elf_file::construct): Initialize large_shndx_offset_. (Elf_File::initialize_shnum): If necessary, adjust shstrndx_ and set large_shndx_offset_. --- elfcpp/ChangeLog | 8 ++++++++ elfcpp/elfcpp_file.h | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) (limited to 'elfcpp') diff --git a/elfcpp/ChangeLog b/elfcpp/ChangeLog index c543d830a1..63e0ac0267 100644 --- a/elfcpp/ChangeLog +++ b/elfcpp/ChangeLog @@ -1,3 +1,11 @@ +2008-04-19 Ian Lance Taylor + + * elfcpp_file.h (class Elf_file): Add large_shndx_offset_ field. + (Elf_file::large_shndx_offset): New function. + (Elf_file::construct): Initialize large_shndx_offset_. + (Elf_File::initialize_shnum): If necessary, adjust shstrndx_ and + set large_shndx_offset_. + 2008-04-16 David S. Miller * elfcpp.h (DF_1_NOW, DF_1_GLOBAL, DF_1_GROUP, diff --git a/elfcpp/elfcpp_file.h b/elfcpp/elfcpp_file.h index 431f8efabe..f1f4423a14 100644 --- a/elfcpp/elfcpp_file.h +++ b/elfcpp/elfcpp_file.h @@ -115,6 +115,15 @@ class Elf_file return this->shstrndx_; } + // Return the value to subtract from section indexes >= + // SHN_LORESERVE. See the comment in initialize_shnum. + int + large_shndx_offset() + { + this->initialize_shnum(); + return this->large_shndx_offset_; + } + // Return the location of the header of section SHNDX. typename File::Location section_header(unsigned int shndx) @@ -180,6 +189,8 @@ class Elf_file unsigned int shnum_; // The section index of the section name string table. unsigned int shstrndx_; + // Offset to add to sections larger than SHN_LORESERVE. + int large_shndx_offset_; }; // Template function definitions. @@ -194,6 +205,7 @@ Elf_file::construct(File* file, const Ef_ehdr& ehdr) this->shoff_ = ehdr.get_e_shoff(); this->shnum_ = ehdr.get_e_shnum(); this->shstrndx_ = ehdr.get_e_shstrndx(); + this->large_shndx_offset_ = 0; if (ehdr.get_e_ehsize() != This::ehdr_size) file->error(_("bad e_ehsize (%d != %d)"), ehdr.get_e_ehsize(), This::ehdr_size); @@ -223,10 +235,37 @@ Elf_file::initialize_shnum() { typename File::View v(this->file_->view(this->shoff_, This::shdr_size)); Ef_shdr shdr(v.data()); + if (this->shnum_ == 0) this->shnum_ = shdr.get_sh_size(); + if (this->shstrndx_ == SHN_XINDEX) - this->shstrndx_ = shdr.get_sh_link(); + { + this->shstrndx_ = shdr.get_sh_link(); + + // Versions of the GNU binutils between 2.12 and 2.18 did + // not handle objects with more than SHN_LORESERVE sections + // correctly. All large section indexes were offset by + // 0x100. Some information can be found here: + // http://sourceware.org/bugzilla/show_bug.cgi?id=5900 . + // Fortunately these object files are easy to detect, as the + // GNU binutils always put the section header string table + // near the end of the list of sections. Thus if the + // section header string table index is larger than the + // number of sections, then we know we have to subtract + // 0x100 to get the real section index. + if (this->shstrndx_ >= this->shnum_) + { + if (this->shstrndx_ >= elfcpp::SHN_LORESERVE + 0x100) + { + this->large_shndx_offset_ = - 0x100; + this->shstrndx_ -= 0x100; + } + if (this->shstrndx_ >= this->shnum_) + this->file_->error(_("bad shstrndx: %u >= %u"), + this->shstrndx_, this->shnum_); + } + } } } -- cgit v1.2.1