* dwarf2loc.c (dwarf_expr_frame_base): Error out on missing
[deliverable/binutils-gdb.git] / elfcpp / elfcpp_file.h
index c9563eeed74f496f5b4e056d0f8ba37880ad4340..f1f4423a14e88f790b025f732105a3f4d7cfa171 100644 (file)
@@ -1,5 +1,34 @@
 // elfcpp_file.h -- file access for elfcpp   -*- C++ -*-
 
+// Copyright 2006, 2007, Free Software Foundation, Inc.
+// Written by Ian Lance Taylor <iant@google.com>.
+
+// This file is part of elfcpp.
+   
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public License
+// as published by the Free Software Foundation; either version 2, or
+// (at your option) any later version.
+
+// In addition to the permissions in the GNU Library General Public
+// License, the Free Software Foundation gives you unlimited
+// permission to link the compiled version of this file into
+// combinations with other programs, and to distribute those
+// combinations without any restriction coming from the use of this
+// file.  (The Library Public License restrictions do apply in other
+// respects; for example, they cover modification of the file, and
+/// distribution when not linked into a combined executable.)
+
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+
+// You should have received a copy of the GNU Library General Public
+// License along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+// 02110-1301, USA.
+
 // This header file defines the class Elf_file which can be used to
 // read useful data from an ELF file.  The functions here are all
 // templates which take a file interface object as a parameter.  This
@@ -86,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)
@@ -102,10 +140,34 @@ class Elf_file
   typename File::Location
   section_contents(unsigned int shndx);
 
+  // Return the size of section SHNDX.
+  typename Elf_types<size>::Elf_WXword
+  section_size(unsigned int shndx);
+
   // Return the flags of section SHNDX.
   typename Elf_types<size>::Elf_WXword
   section_flags(unsigned int shndx);
 
+  // Return the address of section SHNDX.
+  typename Elf_types<size>::Elf_Addr
+  section_addr(unsigned int shndx);
+
+  // Return the type of section SHNDX.
+  Elf_Word
+  section_type(unsigned int shndx);
+
+  // Return the link field of section SHNDX.
+  Elf_Word
+  section_link(unsigned int shndx);
+
+  // Return the info field of section SHNDX.
+  Elf_Word
+  section_info(unsigned int shndx);
+
+  // Return the addralign field of section SHNDX.
+  typename Elf_types<size>::Elf_WXword
+  section_addralign(unsigned int shndx);
+
  private:
   // Shared constructor code.
   void
@@ -127,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.
@@ -141,6 +205,7 @@ Elf_file<size, big_endian, 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);
@@ -170,10 +235,37 @@ Elf_file<size, big_endian, 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_);
+           }
+       }
     }
 }
 
@@ -254,6 +346,25 @@ Elf_file<size, big_endian, File>::section_contents(unsigned int shndx)
   return typename File::Location(shdr.get_sh_offset(), shdr.get_sh_size());
 }
 
+// Get the size of section SHNDX.
+
+template<int size, bool big_endian, typename File>
+typename Elf_types<size>::Elf_WXword
+Elf_file<size, big_endian, File>::section_size(unsigned int shndx)
+{
+  File* const file = this->file_;
+
+  if (shndx >= this->shnum())
+    file->error(_("section_size: bad shndx %u >= %u"),
+               shndx, this->shnum());
+
+  typename File::View v(file->view(this->section_header_offset(shndx),
+                                  This::shdr_size));
+
+  Ef_shdr shdr(v.data());
+  return shdr.get_sh_size();
+}
+
 // Return the section flags of section SHNDX.
 
 template<int size, bool big_endian, typename File>
@@ -273,6 +384,101 @@ Elf_file<size, big_endian, File>::section_flags(unsigned int shndx)
   return shdr.get_sh_flags();
 }
 
+// Return the address of section SHNDX.
+
+template<int size, bool big_endian, typename File>
+typename Elf_types<size>::Elf_Addr
+Elf_file<size, big_endian, File>::section_addr(unsigned int shndx)
+{
+  File* const file = this->file_;
+
+  if (shndx >= this->shnum())
+    file->error(_("section_flags: bad shndx %u >= %u"),
+               shndx, this->shnum());
+
+  typename File::View v(file->view(this->section_header_offset(shndx),
+                                  This::shdr_size));
+
+  Ef_shdr shdr(v.data());
+  return shdr.get_sh_addr();
+}
+
+// Return the type of section SHNDX.
+
+template<int size, bool big_endian, typename File>
+Elf_Word
+Elf_file<size, big_endian, File>::section_type(unsigned int shndx)
+{
+  File* const file = this->file_;
+
+  if (shndx >= this->shnum())
+    file->error(_("section_type: bad shndx %u >= %u"),
+               shndx, this->shnum());
+
+  typename File::View v(file->view(this->section_header_offset(shndx),
+                                  This::shdr_size));
+
+  Ef_shdr shdr(v.data());
+  return shdr.get_sh_type();
+}
+
+// Return the sh_link field of section SHNDX.
+
+template<int size, bool big_endian, typename File>
+Elf_Word
+Elf_file<size, big_endian, File>::section_link(unsigned int shndx)
+{
+  File* const file = this->file_;
+
+  if (shndx >= this->shnum())
+    file->error(_("section_link: bad shndx %u >= %u"),
+               shndx, this->shnum());
+
+  typename File::View v(file->view(this->section_header_offset(shndx),
+                                  This::shdr_size));
+
+  Ef_shdr shdr(v.data());
+  return shdr.get_sh_link();
+}
+
+// Return the sh_info field of section SHNDX.
+
+template<int size, bool big_endian, typename File>
+Elf_Word
+Elf_file<size, big_endian, File>::section_info(unsigned int shndx)
+{
+  File* const file = this->file_;
+
+  if (shndx >= this->shnum())
+    file->error(_("section_info: bad shndx %u >= %u"),
+               shndx, this->shnum());
+
+  typename File::View v(file->view(this->section_header_offset(shndx),
+                                  This::shdr_size));
+
+  Ef_shdr shdr(v.data());
+  return shdr.get_sh_info();
+}
+
+// Return the sh_addralign field of section SHNDX.
+
+template<int size, bool big_endian, typename File>
+typename Elf_types<size>::Elf_WXword
+Elf_file<size, big_endian, File>::section_addralign(unsigned int shndx)
+{
+  File* const file = this->file_;
+
+  if (shndx >= this->shnum())
+    file->error(_("section_addralign: bad shndx %u >= %u"),
+               shndx, this->shnum());
+
+  typename File::View v(file->view(this->section_header_offset(shndx),
+                                  This::shdr_size));
+
+  Ef_shdr shdr(v.data());
+  return shdr.get_sh_addralign();
+}
+
 } // End namespace elfcpp.
 
 #endif // !defined(ELFCPP_FILE_H)
This page took 0.028395 seconds and 4 git commands to generate.