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 /gold/object.cc | |
parent | 9e59254c41b56b91b7640ed5b727430cc537daac (diff) | |
download | gdb-645f81233bd13bc6102580bac4b886c6056028e3.zip gdb-645f81233bd13bc6102580bac4b886c6056028e3.tar.gz gdb-645f81233bd13bc6102580bac4b886c6056028e3.tar.bz2 |
Add Elf_file interface which can be used by both Sized_relobj and
Sized_dynobj.
Diffstat (limited to 'gold/object.cc')
-rw-r--r-- | gold/object.cc | 227 |
1 files changed, 79 insertions, 148 deletions
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()); |