OSDN Git Service

Add Elf_file interface which can be used by both Sized_relobj and
authoriant <iant>
Tue, 7 Nov 2006 18:51:39 +0000 (18:51 +0000)
committeriant <iant>
Tue, 7 Nov 2006 18:51:39 +0000 (18:51 +0000)
Sized_dynobj.

elfcpp/elfcpp.h
elfcpp/elfcpp_file.h [new file with mode: 0644]
gold/object.cc
gold/object.h
gold/po/gold.pot
gold/reloc.cc
gold/symtab.cc

index d92b46d..322afb4 100644 (file)
@@ -570,6 +570,12 @@ class Ehdr
     : p_(reinterpret_cast<const internal::Ehdr_data<size>*>(p))
   { }
 
+  template<typename File>
+  Ehdr(File* file, typename File::Location loc)
+    : p_(reinterpret_cast<const internal::Ehdr_data<size>*>(
+          file->view(loc.file_offset, loc.data_size).data()))
+  { }
+
   const unsigned char*
   get_e_ident() const
   { return this->p_->e_ident; }
@@ -710,6 +716,12 @@ class Shdr
     : p_(reinterpret_cast<const internal::Shdr_data<size>*>(p))
   { }
 
+  template<typename File>
+  Shdr(File* file, typename File::Location loc)
+    : p_(reinterpret_cast<const internal::Shdr_data<size>*>(
+          file->view(loc.file_offset, loc.data_size).data()))
+  { }
+
   Elf_Word
   get_sh_name() const
   { return Convert<32, big_endian>::convert_host(this->p_->sh_name); }
@@ -819,6 +831,12 @@ class Phdr
     : p_(reinterpret_cast<const internal::Phdr_data<size>*>(p))
   { }
 
+  template<typename File>
+  Phdr(File* file, typename File::Location loc)
+    : p_(reinterpret_cast<internal::Phdr_data<size>*>(
+          file->view(loc.file_offset, loc.data_size).data()))
+  { }
+
   Elf_Word
   get_p_type() const
   { return Convert<32, big_endian>::convert_host(this->p_->p_type); }
@@ -911,6 +929,12 @@ class Sym
     : p_(reinterpret_cast<const internal::Sym_data<size>*>(p))
   { }
 
+  template<typename File>
+  Sym(File* file, typename File::Location loc)
+    : p_(reinterpret_cast<const internal::Sym_data<size>*>(
+          file->view(loc.file_offset, loc.data_size).data()))
+  { }
+
   Elf_Word
   get_st_name() const
   { return Convert<32, big_endian>::convert_host(this->p_->st_name); }
@@ -1015,6 +1039,12 @@ class Rel
     : p_(reinterpret_cast<const internal::Rel_data<size>*>(p))
   { }
 
+  template<typename File>
+  Rel(File* file, typename File::Location loc)
+    : p_(reinterpret_cast<const internal::Rel_data<size>*>(
+          file->view(loc.file_offset, loc.data_size).data()))
+  { }
+
   typename Elf_types<size>::Elf_Addr
   get_r_offset() const
   { return Convert<size, big_endian>::convert_host(this->p_->r_offset); }
@@ -1035,6 +1065,12 @@ class Rela
     : p_(reinterpret_cast<const internal::Rela_data<size>*>(p))
   { }
 
+  template<typename File>
+  Rela(File* file, typename File::Location loc)
+    : p_(reinterpret_cast<const internal::Rela_data<size>*>(
+          file->view(loc.file_offset, loc.data_size).data()))
+  { }
+
   typename Elf_types<size>::Elf_Addr
   get_r_offset() const
   { return Convert<size, big_endian>::convert_host(this->p_->r_offset); }
diff --git a/elfcpp/elfcpp_file.h b/elfcpp/elfcpp_file.h
new file mode 100644 (file)
index 0000000..043c269
--- /dev/null
@@ -0,0 +1,255 @@
+// elfcpp_file.h -- file access for elfcpp   -*- C++ -*-
+
+// 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
+// type must have a subtype View.  This type must support two methods:
+//     View view(off_t file_offset, off_t data_size)
+// returns a View for the specified part of the file.
+//     void error(const char* printf_format, ...)
+// prints an error message and does not return.  The subtype View must
+// support a method
+//     const unsigned char* data()
+// which returns a pointer to a buffer containing the requested data.
+// This general interface is used to read data from the file.  Objects
+// of type View will never survive longer than the elfcpp function.
+
+// Some of these functions must return a reference to part of the
+// file.  To use these, the file interface must support a subtype
+// Location:
+//    Location(off_t file_offset, off_t data_size)
+// To use this in conjunction with the accessors types Shdr, etc., the
+// file interface should support an overload of view:
+//    View view(Location)
+// This permits writing
+//    elfcpp::Shdr shdr(file, ef.section_header(n));
+
+#ifndef ELFPCP_FILE_H
+#define ELFCPP_FILE_H
+
+#include <string>
+#include <cstring>
+
+namespace elfcpp
+{
+
+// This object is used to read an ELF file.
+//   SIZE: The size of file, 32 or 64.
+//   BIG_ENDIAN: Whether the file is in big-endian format.
+//   FILE: A file reading type as described above.
+
+template<int size, bool big_endian, typename File>
+class Elf_file
+{
+ private:
+  typedef Elf_file<size, big_endian, File> This;
+
+ public:
+  static const int ehdr_size = Elf_sizes<size>::ehdr_size;
+  static const int phdr_size = Elf_sizes<size>::phdr_size;
+  static const int shdr_size = Elf_sizes<size>::shdr_size;
+  static const int sym_size = Elf_sizes<size>::sym_size;
+  static const int rel_size = Elf_sizes<size>::rel_size;
+  static const int rela_size = Elf_sizes<size>::rela_size;
+
+  typedef Ehdr<size, big_endian> Ef_ehdr;
+  typedef Phdr<size, big_endian> Ef_phdr;
+  typedef Shdr<size, big_endian> Ef_shdr;
+  typedef Sym<size, big_endian> Ef_sym;
+
+  // Construct an Elf_file given an ELF file header.
+  Elf_file(File* file, const Ef_ehdr& ehdr)
+  { this->construct(file, ehdr); }
+
+  // Construct an ELF file.
+  inline
+  Elf_file(File* file);
+
+  // Return the file offset to the section headers.
+  off_t
+  shoff() const
+  { return this->shoff_; }
+
+  // Return the number of sections.
+  unsigned int
+  shnum()
+  {
+    this->initialize_shnum();
+    return this->shnum_;
+  }
+
+  // Return the section index of the section name string table.
+  unsigned int
+  shstrndx()
+  {
+    this->initialize_shnum();
+    return this->shstrndx_;
+  }
+
+  // Return the location of the header of section SHNDX.
+  typename File::Location
+  section_header(unsigned int shndx)
+  {
+    return typename File::Location(this->section_header_offset(shndx),
+                                  shdr_size);
+  }
+
+  // Return the name of section SHNDX.
+  std::string
+  section_name(unsigned int shndx);
+
+  // Return the location of the contents of section SHNDX.
+  typename File::Location
+  section_contents(unsigned int shndx);
+
+ private:
+  // Shared constructor code.
+  void
+  construct(File* file, const Ef_ehdr& ehdr);
+
+  // Initialize shnum_ and shstrndx_.
+  void
+  initialize_shnum();
+
+  // Return the file offset of the header of section SHNDX.
+  off_t
+  section_header_offset(unsigned int shndx);
+
+  // The file we are reading.
+  File* file_;
+  // The file offset to the section headers.
+  off_t shoff_;
+  // The number of sections.
+  unsigned int shnum_;
+  // The section index of the section name string table.
+  unsigned int shstrndx_;
+};
+
+// Template function definitions.
+
+// Construct an Elf_file given an ELF file header.
+
+template<int size, bool big_endian, typename File>
+void
+Elf_file<size, big_endian, File>::construct(File* file, const Ef_ehdr& ehdr)
+{
+  this->file_ = file;
+  this->shoff_ = ehdr.get_e_shoff();
+  this->shnum_ = ehdr.get_e_shnum();
+  this->shstrndx_ = ehdr.get_e_shstrndx();
+  if (ehdr.get_e_ehsize() != This::ehdr_size)
+    file->error(_("bad e_ehsize (%d != %d)"),
+               ehdr.get_e_ehsize(), This::ehdr_size);
+  if (ehdr.get_e_shentsize() != This::shdr_size)
+    file->error(_("bad e_shentsize (%d != %d)"),
+               ehdr.get_e_shentsize(), This::shdr_size);
+}
+
+// Construct an ELF file.
+
+template<int size, bool big_endian, typename File>
+inline
+Elf_file<size, big_endian, File>::Elf_file(File* file)
+{
+  typename File::View v(file->view(file_header_offset, This::ehdr_size));
+  this->construct(file, Ef_ehdr(v.data()));
+}
+
+// Initialize the shnum_ and shstrndx_ fields, handling overflow.
+
+template<int size, bool big_endian, typename File>
+void
+Elf_file<size, big_endian, File>::initialize_shnum()
+{
+  if ((this->shnum_ == 0 || this->shstrndx_ == SHN_XINDEX)
+      && this->shoff_ != 0)
+    {
+      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();
+    }
+}
+
+// Return the file offset of the section header of section SHNDX.
+
+template<int size, bool big_endian, typename File>
+off_t
+Elf_file<size, big_endian, File>::section_header_offset(unsigned int shndx)
+{
+  if (shndx >= this->shnum())
+    this->file_->error(_("section_header_offset: bad shndx %u >= %u"),
+                      shndx, this->shnum());
+  return this->shoff_ + This::shdr_size * shndx;
+}
+
+// Return the name of section SHNDX.
+
+template<int size, bool big_endian, typename File>
+std::string
+Elf_file<size, big_endian, File>::section_name(unsigned int shndx)
+{
+  File* const file = this->file_;
+
+  // Get the section name offset.
+  unsigned int sh_name;
+  {
+    typename File::View v(file->view(this->section_header_offset(shndx),
+                                    This::shdr_size));
+    Ef_shdr shdr(v.data());
+    sh_name = shdr.get_sh_name();
+  }
+
+  // Get the file offset for the section name string table data.
+  off_t shstr_off;
+  off_t shstr_size;
+  {
+    const unsigned int shstrndx = this->shstrndx_;
+    typename File::View v(file->view(this->section_header_offset(shstrndx),
+                                    This::shdr_size));
+    Ef_shdr shstr_shdr(v.data());
+    shstr_off = shstr_shdr.get_sh_offset();
+    shstr_size = shstr_shdr.get_sh_size();
+  }
+
+  if (sh_name >= shstr_size)
+    file->error(_("bad section name offset for section %u: %u"),
+               shndx, sh_name);
+
+  typename File::View v(file->view(shstr_off, shstr_size));
+
+  const unsigned char* datau = v.data();
+  const char* data = reinterpret_cast<const char*>(datau);
+  const void* p = ::memchr(data + sh_name, '\0', shstr_size - sh_name);
+  if (p == NULL)
+    file->error(_("missing null terminator for name of section %u"),
+               shndx);
+
+  size_t len = static_cast<const char*>(p) - (data + sh_name);
+
+  return std::string(data + sh_name, len);
+}
+
+// Return the contents of section SHNDX.
+
+template<int size, bool big_endian, typename File>
+typename File::Location
+Elf_file<size, big_endian, File>::section_contents(unsigned int shndx)
+{
+  File* const file = this->file_;
+
+  if (shndx >= this->shnum())
+    file->error(_("section_contents: 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 typename File::Location(shdr.get_sh_offset(), shdr.get_sh_size());
+}
+
+} // End namespace elfcpp.
+
+#endif // !defined(ELFCPP_FILE_H)
index 956366c..677c731 100644 (file)
@@ -5,6 +5,7 @@
 #include <cerrno>
 #include <cstring>
 #include <cassert>
+#include <cstdarg>
 
 #include "target-select.h"
 #include "layout.h"
 namespace gold
 {
 
+// Class Object.
+
+// Report an error for the elfcpp::Elf_file interface.
+
+void
+Object::error(const char* format, ...)
+{
+  va_list args;
+
+  fprintf(stderr, "%s: %s: ", program_name, this->name().c_str());
+  va_start(args, format);
+  vfprintf(stderr, format, args);
+  va_end(args);
+  putc('\n', stderr);
+
+  gold_exit(false);
+}
+
+// Return a view of the contents of a section.
+
+const unsigned char*
+Object::section_contents(unsigned int shndx, off_t* plen)
+{
+  Location loc(this->do_section_contents(shndx));
+  *plen = loc.data_size;
+  return this->get_view(loc.file_offset, loc.data_size);
+}
+
 // Class Sized_relobj.
 
 template<int size, bool big_endian>
@@ -25,31 +54,15 @@ Sized_relobj<size, big_endian>::Sized_relobj(
     off_t offset,
     const elfcpp::Ehdr<size, big_endian>& ehdr)
   : Relobj(name, input_file, offset),
+    elf_file_(this, ehdr),
     section_headers_(NULL),
-    flags_(ehdr.get_e_flags()),
-    shoff_(ehdr.get_e_shoff()),
-    shstrndx_(0),
-    symtab_shnum_(0),
+    symtab_shndx_(0),
     local_symbol_count_(0),
     output_local_symbol_count_(0),
     symbols_(NULL),
     local_symbol_offset_(0),
     values_(NULL)
 {
-  if (ehdr.get_e_ehsize() != This::ehdr_size)
-    {
-      fprintf(stderr, _("%s: %s: bad e_ehsize field (%d != %d)\n"),
-             program_name, this->name().c_str(), ehdr.get_e_ehsize(),
-             This::ehdr_size);
-      gold_exit(false);
-    }
-  if (ehdr.get_e_shentsize() != This::shdr_size)
-    {
-      fprintf(stderr, _("%s: %s: bad e_shentsize field (%d != %d)\n"),
-             program_name, this->name().c_str(), ehdr.get_e_shentsize(),
-             This::shdr_size);
-      gold_exit(false);
-    }
 }
 
 template<int size, bool big_endian>
@@ -57,59 +70,7 @@ Sized_relobj<size, big_endian>::~Sized_relobj()
 {
 }
 
-// Read the section header for section SHNUM.
-
-template<int size, bool big_endian>
-inline const unsigned char*
-Sized_relobj<size, big_endian>::section_header(unsigned int shnum)
-{
-  assert(shnum < this->shnum());
-  off_t symtabshdroff = this->shoff_ + shnum * This::shdr_size;
-  return this->get_view(symtabshdroff, This::shdr_size);
-}
-
-// Return the name of section SHNUM.  The object must already be
-// locked.
-
-template<int size, bool big_endian>
-std::string
-Sized_relobj<size, big_endian>::do_section_name(unsigned int shnum)
-{
-  // Read the section names.
-  typename This::Shdr shdrnames(this->section_header(this->shstrndx_));
-  const unsigned char* pnamesu = this->get_view(shdrnames.get_sh_offset(),
-                                               shdrnames.get_sh_size());
-  const char* pnames = reinterpret_cast<const char*>(pnamesu);
-
-  typename This::Shdr shdr(this->section_header(shnum));
-  if (shdr.get_sh_name() >= shdrnames.get_sh_size())
-    {
-      fprintf(stderr,
-             _("%s: %s: bad section name offset for section %u: %lu\n"),
-             program_name, this->name().c_str(), shnum,
-             static_cast<unsigned long>(shdr.get_sh_name()));
-      gold_exit(false);
-    }
-
-  return std::string(pnames + shdr.get_sh_name());
-}
-
-// Return a view of the contents of section SHNUM.  The object does
-// not have to be locked.
-
-template<int size, bool big_endian>
-const unsigned char*
-Sized_relobj<size, big_endian>::do_section_contents(unsigned int shnum,
-                                                   off_t* plen)
-{
-  Task_locker_obj<Object> tl(*this);
-
-  typename This::Shdr shdr(this->section_header(shnum));
-  *plen = shdr.get_sh_size();
-  return this->get_view(shdr.get_sh_offset(), shdr.get_sh_size());
-}
-
-// Set up an object file bsaed on the file header.  This sets up the
+// Set up an object file based on the file header.  This sets up the
 // target and reads the section information.
 
 template<int size, bool big_endian>
@@ -129,25 +90,14 @@ Sized_relobj<size, big_endian>::setup(
     }
   this->set_target(target);
 
-  unsigned int shnum = ehdr.get_e_shnum();
-  unsigned int shstrndx = ehdr.get_e_shstrndx();
-  if ((shnum == 0 || shstrndx == elfcpp::SHN_XINDEX)
-      && this->shoff_ != 0)
-    {
-      typename This::Shdr shdr(this->section_header(0));
-      if (shnum == 0)
-       shnum = shdr.get_sh_size();
-      if (shstrndx == elfcpp::SHN_XINDEX)
-       shstrndx = shdr.get_sh_link();
-    }
+  unsigned int shnum = this->elf_file_.shnum();
   this->set_shnum(shnum);
-  this->shstrndx_ = shstrndx;
-
   if (shnum == 0)
     return;
 
   // We store the section headers in a File_view until do_read_symbols.
-  this->section_headers_ = this->get_lasting_view(this->shoff_,
+  off_t shoff = this->elf_file_.shoff();
+  this->section_headers_ = this->get_lasting_view(shoff,
                                                  shnum * This::shdr_size);
 
   // Find the SHT_SYMTAB section.  The ELF standard says that maybe in
@@ -163,7 +113,7 @@ Sized_relobj<size, big_endian>::setup(
       typename This::Shdr shdr(p);
       if (shdr.get_sh_type() == elfcpp::SHT_SYMTAB)
        {
-         this->symtab_shnum_ = i;
+         this->symtab_shndx_ = i;
          break;
        }
     }
@@ -181,13 +131,15 @@ Sized_relobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
 
   // Read the section names.
   const unsigned char* pshdrs = sd->section_headers->data();
-  const unsigned char* pshdrnames = pshdrs + this->shstrndx_ * This::shdr_size;
+  const unsigned char* pshdrnames = (pshdrs
+                                    + (this->elf_file_.shstrndx()
+                                       * This::shdr_size));
   typename This::Shdr shdrnames(pshdrnames);
   sd->section_names_size = shdrnames.get_sh_size();
   sd->section_names = this->get_lasting_view(shdrnames.get_sh_offset(),
                                             sd->section_names_size);
 
-  if (this->symtab_shnum_ == 0)
+  if (this->symtab_shndx_ == 0)
     {
       // No symbol table.  Weird but legal.
       sd->symbols = NULL;
@@ -199,7 +151,7 @@ Sized_relobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
 
   // Get the symbol table section header.
   typename This::Shdr symtabshdr(pshdrs
-                                + this->symtab_shnum_ * This::shdr_size);
+                                + this->symtab_shndx_ * This::shdr_size);
   assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);
 
   // We only need the external symbols.
@@ -276,14 +228,8 @@ Sized_relobj<size, big_endian>::include_section_group(
 
   // Get the appropriate symbol table header (this will normally be
   // the single SHT_SYMTAB section, but in principle it need not be).
-  if (shdr.get_sh_link() >= this->shnum())
-    {
-      fprintf(stderr, _("%s: %s: section group %u link %u out of range\n"),
-             program_name, this->name().c_str(), index, shdr.get_sh_link());
-      gold_exit(false);
-    }
-
-  typename This::Shdr symshdr(this->section_header(shdr.get_sh_link()));
+  const unsigned int link = shdr.get_sh_link();
+  typename This::Shdr symshdr(this, this->elf_file_.section_header(link));
 
   // Read the symbol table entry.
   if (shdr.get_sh_info() >= symshdr.get_sh_size() / This::sym_size)
@@ -296,24 +242,14 @@ Sized_relobj<size, big_endian>::include_section_group(
   const unsigned char* psym = this->get_view(symoff, This::sym_size);
   elfcpp::Sym<size, big_endian> sym(psym);
 
-  // Read the section header for the symbol table names.
-  if (symshdr.get_sh_link() >= this->shnum())
-    {
-      fprintf(stderr, _("%s; %s: symtab section %u link %u out of range\n"),
-             program_name, this->name().c_str(), shdr.get_sh_link(),
-             symshdr.get_sh_link());
-      gold_exit(false);
-    }
-
-  typename This::Shdr symnamehdr(this->section_header(symshdr.get_sh_link()));
-
   // Read the symbol table names.
-  const unsigned char *psymnamesu = this->get_view(symnamehdr.get_sh_offset(),
-                                                  symnamehdr.get_sh_size());
+  off_t symnamelen;
+  const unsigned char* psymnamesu;
+  psymnamesu = this->section_contents(symshdr.get_sh_link(), &symnamelen);
   const char* psymnames = reinterpret_cast<const char*>(psymnamesu);
 
   // Get the section group signature.
-  if (sym.get_st_name() >= symnamehdr.get_sh_size())
+  if (sym.get_st_name() >= symnamelen)
     {
       fprintf(stderr, _("%s: %s: symbol %u name offset %u out of range\n"),
              program_name, this->name().c_str(), shdr.get_sh_info(),
@@ -327,26 +263,11 @@ Sized_relobj<size, big_endian>::include_section_group(
   // associated with a section symbol, and then fail to give a name to
   // the section symbol.  In such a case, use the name of the section.
   // FIXME.
-  if (signature[0] == '\0'
-      && sym.get_st_type() == elfcpp::STT_SECTION
-      && sym.get_st_shndx() < this->shnum())
+  std::string secname;
+  if (signature[0] == '\0' && sym.get_st_type() == elfcpp::STT_SECTION)
     {
-      typename This::Shdr shdrnames(this->section_header(this->shstrndx_));
-      const unsigned char* pnamesu = this->get_view(shdrnames.get_sh_offset(),
-                                                   shdrnames.get_sh_size());
-      const char* pnames = reinterpret_cast<const char*>(pnamesu);
-      
-      typename This::Shdr sechdr(this->section_header(sym.get_st_shndx()));
-      if (sechdr.get_sh_name() >= shdrnames.get_sh_size())
-       {
-         fprintf(stderr,
-                 _("%s: %s: bad section name offset for section %u: %lu\n"),
-                 program_name, this->name().c_str(), sym.get_st_shndx(),
-                 static_cast<unsigned long>(sechdr.get_sh_name()));
-         gold_exit(false);
-       }
-
-      signature = pnames + sechdr.get_sh_name();
+      secname = this->section_name(sym.get_st_shndx());
+      signature = secname.c_str();
     }
 
   // Record this section group, and see whether we've already seen one
@@ -543,7 +464,7 @@ off_t
 Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
                                                          Stringpool* pool)
 {
-  if (this->symtab_shnum_ == 0)
+  if (this->symtab_shndx_ == 0)
     {
       // This object has no symbols.  Weird but legal.
       return off;
@@ -554,7 +475,9 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
   this->local_symbol_offset_ = off;
 
   // Read the symbol table section header.
-  typename This::Shdr symtabshdr(this->section_header(this->symtab_shnum_));
+  const unsigned int symtab_shndx = this->symtab_shndx_;
+  typename This::Shdr symtabshdr(this,
+                                this->elf_file_.section_header(symtab_shndx));
   assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);
 
   // Read the local symbols.
@@ -567,14 +490,11 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
 
   this->values_ = new typename elfcpp::Elf_types<size>::Elf_Addr[loccount];
 
-  // Read the section header for the symbol names.
-  typename This::Shdr strtabshdr(
-    this->section_header(symtabshdr.get_sh_link()));
-  assert(strtabshdr.get_sh_type() == elfcpp::SHT_STRTAB);
-
   // Read the symbol names.
-  const unsigned char* pnamesu = this->get_view(strtabshdr.get_sh_offset(),
-                                               strtabshdr.get_sh_size());
+  const unsigned int strtab_shndx = symtabshdr.get_sh_link();
+  off_t strtab_size;
+  const unsigned char* pnamesu = this->section_contents(strtab_shndx,
+                                                       &strtab_size);
   const char* pnames = reinterpret_cast<const char*>(pnamesu);
 
   // Loop over the local symbols.
@@ -628,6 +548,17 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
 
       if (sym.get_st_type() != elfcpp::STT_SECTION)
        {
+         if (sym.get_st_name() >= strtab_size)
+           {
+             fprintf(stderr,
+                     _("%s: %s: local symbol %u section name "
+                       "out of range: %u >= %u\n"),
+                     program_name, this->name().c_str(),
+                     i, sym.get_st_name(),
+                     static_cast<unsigned int>(strtab_size));
+             gold_exit(false);
+           }
+
          pool->add(pnames + sym.get_st_name(), NULL);
          off += sym_size;
          ++count;
@@ -646,14 +577,16 @@ void
 Sized_relobj<size, big_endian>::write_local_symbols(Output_file* of,
                                                    const Stringpool* sympool)
 {
-  if (this->symtab_shnum_ == 0)
+  if (this->symtab_shndx_ == 0)
     {
       // This object has no symbols.  Weird but legal.
       return;
     }
 
   // Read the symbol table section header.
-  typename This::Shdr symtabshdr(this->section_header(this->symtab_shnum_));
+  const unsigned int symtab_shndx = this->symtab_shndx_;
+  typename This::Shdr symtabshdr(this,
+                                this->elf_file_.section_header(symtab_shndx));
   assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);
   const unsigned int loccount = this->local_symbol_count_;
   assert(loccount == symtabshdr.get_sh_info());
@@ -664,14 +597,11 @@ Sized_relobj<size, big_endian>::write_local_symbols(Output_file* of,
   const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
                                              locsize);
 
-  // Read the section header for the symbol names.
-  typename This::Shdr strtabshdr(
-    this->section_header(symtabshdr.get_sh_link()));
-  assert(strtabshdr.get_sh_type() == elfcpp::SHT_STRTAB);
-
   // Read the symbol names.
-  const unsigned char* pnamesu = this->get_view(strtabshdr.get_sh_offset(),
-                                               strtabshdr.get_sh_size());
+  const unsigned int strtab_shndx = symtabshdr.get_sh_link();
+  off_t strtab_size;
+  const unsigned char* pnamesu = this->section_contents(strtab_shndx,
+                                                       &strtab_size);
   const char* pnames = reinterpret_cast<const char*>(pnamesu);
 
   // Get a view into the output file.
@@ -701,6 +631,7 @@ Sized_relobj<size, big_endian>::write_local_symbols(Output_file* of,
 
       elfcpp::Sym_write<size, big_endian> osym(ov);
 
+      assert(isym.get_st_name() < strtab_size);
       osym.put_st_name(sympool->get_offset(pnames + isym.get_st_name()));
       osym.put_st_value(this->values_[i]);
       osym.put_st_size(isym.get_st_size());
index e1f56d2..54f0350 100644 (file)
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "elfcpp.h"
+#include "elfcpp_file.h"
 #include "fileread.h"
 #include "target.h"
 
@@ -147,8 +148,7 @@ class Object
   // Return a view of the contents of a section.  Set *PLEN to the
   // size.
   const unsigned char*
-  section_contents(unsigned int shnum, off_t* plen)
-  { return this->do_section_contents(shnum, plen); }
+  section_contents(unsigned int shndx, off_t* plen);
 
   // Return the name of a section given a section index.  This is only
   // used for error messages.
@@ -156,6 +156,52 @@ class Object
   section_name(unsigned int shnum)
   { return this->do_section_name(shnum); }
 
+  // Functions and types for the elfcpp::Elf_file interface.  This
+  // permit us to use Object as the File template parameter for
+  // elfcpp::Elf_file.
+
+  // The View class is returned by view.  It must support a single
+  // method, data().  This is trivial, because get_view does what we
+  // need.
+  class View
+  {
+   public:
+    View(const unsigned char* p)
+      : p_(p)
+    { }
+
+    const unsigned char*
+    data() const
+    { return this->p_; }
+
+   private:
+    const unsigned char* p_;
+  };
+
+  // Return a View.
+  View
+  view(off_t file_offset, off_t data_size)
+  { return View(this->get_view(file_offset, data_size)); }
+
+  // Report an error.
+  void
+  error(const char* format, ...) ATTRIBUTE_PRINTF_2;
+
+  // A location in the file.
+  struct Location
+  {
+    off_t file_offset;
+    off_t data_size;
+
+    Location(off_t fo, off_t ds)
+      : file_offset(fo), data_size(ds)
+    { }
+  };
+
+  // Get a View given a Location.
+  View view(Location loc)
+  { return View(this->get_view(loc.file_offset, loc.data_size)); }
+
  protected:
   // Read the symbols--implemented by child class.
   virtual void
@@ -171,10 +217,10 @@ class Object
   virtual void
   do_add_symbols(Symbol_table*, Read_symbols_data*) = 0;
 
-  // Return a view of the contents of a section.  Set *PLEN to the
-  // size.  Implemented by child class.
-  virtual const unsigned char*
-  do_section_contents(unsigned int shnum, off_t* plen) = 0;
+  // Return the location of the contents of a section.  Implemented by
+  // child class.
+  virtual Location
+  do_section_contents(unsigned int shnum) = 0;
 
   // Get the name of a section--implemented by child class.
   virtual std::string
@@ -411,12 +457,13 @@ class Sized_relobj : public Relobj
 
   // Get the name of a section.
   std::string
-  do_section_name(unsigned int shnum);
+  do_section_name(unsigned int shndx)
+  { return this->elf_file_.section_name(shndx); }
 
-  // Return a view of the contents of a section.  Set *PLEN to the
-  // size.
-  const unsigned char*
-  do_section_contents(unsigned int shnum, off_t* plen);
+  // Return the location of the contents of a section.
+  Location
+  do_section_contents(unsigned int shndx)
+  { return this->elf_file_.section_contents(shndx); }
 
   // Return the appropriate Sized_target structure.
   Sized_target<size, big_endian>*
@@ -435,10 +482,6 @@ class Sized_relobj : public Relobj
   static const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
   typedef elfcpp::Shdr<size, big_endian> Shdr;
 
-  // Read the section header for section SHNUM.
-  const unsigned char*
-  section_header(unsigned int shnum);
-
   // Whether to include a section group in the link.
   bool
   include_section_group(Layout*, unsigned int,
@@ -475,16 +518,12 @@ class Sized_relobj : public Relobj
   void
   write_local_symbols(Output_file*, const Stringpool*);
 
+  // General access to the ELF file.
+  elfcpp::Elf_file<size, big_endian, Object> elf_file_;
   // If non-NULL, a view of the section header data.
   File_view* section_headers_;
-  // ELF file header e_flags field.
-  unsigned int flags_;
-  // File offset of section header table.
-  off_t shoff_;
-  // Offset of SHT_STRTAB section holding section names.
-  unsigned int shstrndx_;
   // Index of SHT_SYMTAB section.
-  unsigned int symtab_shnum_;
+  unsigned int symtab_shndx_;
   // The number of local symbols.
   unsigned int local_symbol_count_;
   // The number of local symbols which go into the output file.
index c88ba7d..a6c2aa2 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2006-11-06 15:58-0800\n"
+"POT-Creation-Date: 2006-11-07 10:50-0800\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -195,113 +195,98 @@ msgstr ""
 msgid "%s: %s: TLS relocation against invalid instruction\n"
 msgstr ""
 
-#: object.cc:41
-#, c-format
-msgid "%s: %s: bad e_ehsize field (%d != %d)\n"
-msgstr ""
-
-#: object.cc:48
-#, c-format
-msgid "%s: %s: bad e_shentsize field (%d != %d)\n"
-msgstr ""
-
-#: object.cc:88 object.cc:343 object.cc:447
-#, c-format
-msgid "%s: %s: bad section name offset for section %u: %lu\n"
-msgstr ""
-
-#: object.cc:126
+#: object.cc:87
 #, c-format
 msgid "%s: %s: unsupported ELF machine number %d\n"
 msgstr ""
 
-#: object.cc:221
+#: object.cc:173
 #, c-format
 msgid "%s: %s: invalid symbol table name index: %u\n"
 msgstr ""
 
-#: object.cc:229
+#: object.cc:181
 #, c-format
 msgid "%s: %s: symbol table name section has wrong type: %u\n"
 msgstr ""
 
-#: object.cc:281
-#, c-format
-msgid "%s: %s: section group %u link %u out of range\n"
-msgstr ""
-
-#: object.cc:291
+#: object.cc:237
 #, c-format
 msgid "%s: %s: section group %u info %u out of range\n"
 msgstr ""
 
-#: object.cc:302
+#: object.cc:254
 #, c-format
-msgid "%s; %s: symtab section %u link %u out of range\n"
+msgid "%s: %s: symbol %u name offset %u out of range\n"
 msgstr ""
 
-#: object.cc:318
+#: object.cc:288
 #, c-format
-msgid "%s: %s: symbol %u name offset %u out of range\n"
+msgid "%s: %s: section %u in section group %u out of range"
 msgstr ""
 
-#: object.cc:367
+#: object.cc:368
 #, c-format
-msgid "%s: %s: section %u in section group %u out of range"
+msgid "%s: %s: bad section name offset for section %u: %lu\n"
 msgstr ""
 
-#: object.cc:515
+#: object.cc:436
 #, c-format
 msgid "%s: %s: size of symbols is not multiple of symbol size\n"
 msgstr ""
 
-#: object.cc:601
+#: object.cc:521
 #, c-format
 msgid "%s: %s: unknown section index %u for local symbol %u\n"
 msgstr ""
 
-#: object.cc:612
+#: object.cc:532
 #, c-format
 msgid "%s: %s: local symbol %u section index %u out of range\n"
 msgstr ""
 
+#: object.cc:554
+#, c-format
+msgid "%s: %s: local symbol %u section name out of range: %u >= %u\n"
+msgstr ""
+
 #. elfcpp::ET_DYN
-#: object.cc:800
+#: object.cc:731
 #, c-format
 msgid "%s: %s: dynamic objects are not yet supported\n"
 msgstr ""
 
-#: object.cc:824 object.cc:877 object.cc:898
+#: object.cc:755 object.cc:808 object.cc:829
 #, c-format
 msgid "%s: %s: ELF file too short\n"
 msgstr ""
 
-#: object.cc:833
+#: object.cc:764
 #, c-format
 msgid "%s: %s: invalid ELF version 0\n"
 msgstr ""
 
-#: object.cc:836
+#: object.cc:767
 #, c-format
 msgid "%s: %s: unsupported ELF version %d\n"
 msgstr ""
 
-#: object.cc:844
+#: object.cc:775
 #, c-format
 msgid "%s: %s: invalid ELF class 0\n"
 msgstr ""
 
-#: object.cc:851
+#: object.cc:782
 #, c-format
 msgid "%s: %s: unsupported ELF class %d\n"
 msgstr ""
 
-#: object.cc:859
+#: object.cc:790
 #, c-format
 msgid "%s: %s: invalid ELF data encoding\n"
 msgstr ""
 
-#: object.cc:866
+#: object.cc:797
 #, c-format
 msgid "%s: %s: unsupported ELF data encoding %d\n"
 msgstr ""
@@ -477,22 +462,22 @@ msgstr ""
 msgid "%s: %s: unsupported symbol binding %d for symbol %s\n"
 msgstr ""
 
-#: symtab.cc:440
+#: symtab.cc:441
 #, c-format
 msgid "%s: %s: mixing 32-bit and 64-bit ELF objects\n"
 msgstr ""
 
-#: symtab.cc:457
+#: symtab.cc:458
 #, c-format
 msgid "%s: %s: bad global symbol name offset %u at %lu\n"
 msgstr ""
 
-#: symtab.cc:882 symtab.cc:1021
+#: symtab.cc:883 symtab.cc:1022
 #, c-format
 msgid "%s: %s: unsupported symbol section 0x%x\n"
 msgstr ""
 
-#: symtab.cc:1131
+#: symtab.cc:1135
 #, c-format
 msgid "%s: %s: warning: %s\n"
 msgstr ""
index 7233266..bc38904 100644 (file)
@@ -150,7 +150,7 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
 
   rd->relocs.reserve(shnum / 2);
 
-  const unsigned char *pshdrs = this->get_view(this->shoff_,
+  const unsigned char *pshdrs = this->get_view(this->elf_file_.shoff(),
                                               shnum * This::shdr_size);
   // Skip the first, dummy, section.
   const unsigned char *ps = pshdrs + This::shdr_size;
@@ -181,7 +181,7 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
       if ((secshdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
        continue;
 
-      if (shdr.get_sh_link() != this->symtab_shnum_)
+      if (shdr.get_sh_link() != this->symtab_shndx_)
        {
          fprintf(stderr,
                  _("%s: %s: relocation section %u uses unexpected "
@@ -227,12 +227,12 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
     }
 
   // Read the local symbols.
-  if (this->symtab_shnum_ == 0 || this->local_symbol_count_ == 0)
+  if (this->symtab_shndx_ == 0 || this->local_symbol_count_ == 0)
     rd->local_symbols = NULL;
   else
     {
       typename This::Shdr symtabshdr(pshdrs
-                                    + this->symtab_shnum_ * This::shdr_size);
+                                    + this->symtab_shndx_ * This::shdr_size);
       assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);
       const int sym_size = This::sym_size;
       const unsigned int loccount = this->local_symbol_count_;
@@ -293,7 +293,7 @@ Sized_relobj<size, big_endian>::do_relocate(const General_options& options,
   unsigned int shnum = this->shnum();
 
   // Read the section headers.
-  const unsigned char* pshdrs = this->get_view(this->shoff_,
+  const unsigned char* pshdrs = this->get_view(this->elf_file_.shoff(),
                                               shnum * This::shdr_size);
 
   Views views;
@@ -419,7 +419,7 @@ Sized_relobj<size, big_endian>::relocate_sections(
 
       assert((*pviews)[index].view != NULL);
 
-      if (shdr.get_sh_link() != this->symtab_shnum_)
+      if (shdr.get_sh_link() != this->symtab_shndx_)
        {
          fprintf(stderr,
                  _("%s: %s: relocation section %u uses unexpected "
index 054e07f..ac14c01 100644 (file)
@@ -10,6 +10,7 @@
 #include "object.h"
 #include "output.h"
 #include "target.h"
+#include "workqueue.h"
 #include "symtab.h"
 
 namespace gold
@@ -1111,10 +1112,13 @@ Warnings::note_warnings(Symbol_table* symtab)
          // we relocate sections.  That means that we can not lock
          // the object then, as we might try to issue the same
          // warning multiple times simultaneously.
-         const unsigned char* c;
-         off_t len;
-         c = p->second.object->section_contents(p->second.shndx, &len);
-         p->second.set_text(reinterpret_cast<const char*>(c), len);
+         {
+           Task_locker_obj<Object> tl(*p->second.object);
+           const unsigned char* c;
+           off_t len;
+           c = p->second.object->section_contents(p->second.shndx, &len);
+           p->second.set_text(reinterpret_cast<const char*>(c), len);
+         }
        }
     }
 }