diff options
author | Ian Lance Taylor <iant@google.com> | 2006-11-07 18:51:39 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2006-11-07 18:51:39 +0000 |
commit | 645f81233bd13bc6102580bac4b886c6056028e3 (patch) | |
tree | e104ddfc8f2a1f52326b8a2fa9c3b5c50ae43fa0 | |
parent | 9e59254c41b56b91b7640ed5b727430cc537daac (diff) | |
download | fsf-binutils-gdb-645f81233bd13bc6102580bac4b886c6056028e3.zip fsf-binutils-gdb-645f81233bd13bc6102580bac4b886c6056028e3.tar.gz fsf-binutils-gdb-645f81233bd13bc6102580bac4b886c6056028e3.tar.bz2 |
Add Elf_file interface which can be used by both Sized_relobj and
Sized_dynobj.
-rw-r--r-- | elfcpp/elfcpp.h | 36 | ||||
-rw-r--r-- | elfcpp/elfcpp_file.h | 255 | ||||
-rw-r--r-- | gold/object.cc | 227 | ||||
-rw-r--r-- | gold/object.h | 83 | ||||
-rw-r--r-- | gold/po/gold.pot | 77 | ||||
-rw-r--r-- | gold/reloc.cc | 12 | ||||
-rw-r--r-- | gold/symtab.cc | 12 |
7 files changed, 476 insertions, 226 deletions
diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h index d92b46d..322afb4 100644 --- a/elfcpp/elfcpp.h +++ b/elfcpp/elfcpp.h @@ -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 index 0000000..043c269 --- /dev/null +++ b/elfcpp/elfcpp_file.h @@ -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) diff --git a/gold/object.cc b/gold/object.cc index 956366c..677c731 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -5,6 +5,7 @@ #include <cerrno> #include <cstring> #include <cassert> +#include <cstdarg> #include "target-select.h" #include "layout.h" @@ -16,6 +17,34 @@ 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()); diff --git a/gold/object.h b/gold/object.h index e1f56d2..54f0350 100644 --- a/gold/object.h +++ b/gold/object.h @@ -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. diff --git a/gold/po/gold.pot b/gold/po/gold.pot index c88ba7d..a6c2aa2 100644 --- a/gold/po/gold.pot +++ b/gold/po/gold.pot @@ -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 "" diff --git a/gold/reloc.cc b/gold/reloc.cc index 7233266..bc38904 100644 --- a/gold/reloc.cc +++ b/gold/reloc.cc @@ -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 " diff --git a/gold/symtab.cc b/gold/symtab.cc index 054e07f..ac14c01 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -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); + } } } } |