diff options
Diffstat (limited to 'gold/object.cc')
-rw-r--r-- | gold/object.cc | 167 |
1 files changed, 92 insertions, 75 deletions
diff --git a/gold/object.cc b/gold/object.cc index 6186f65..d8658e9 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -44,6 +44,7 @@ Sized_object<size, big_endian>::Sized_object( off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr) : Object(name, input_file, false, offset), + section_headers_(NULL), flags_(ehdr.get_e_flags()), shoff_(ehdr.get_e_shoff()), shstrndx_(0), @@ -105,6 +106,7 @@ Sized_object<size, big_endian>::setup( gold_exit(false); } 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) @@ -122,12 +124,19 @@ Sized_object<size, big_endian>::setup( if (shnum == 0) return; - // Find the SHT_SYMTAB section. - const unsigned char* p = this->get_view (this->shoff_, - shnum * This::shdr_size); + // We store the section headers in a File_view until do_read_symbols. + this->section_headers_ = this->get_lasting_view(this->shoff_, + shnum * This::shdr_size); + + // Find the SHT_SYMTAB section. The ELF standard says that maybe in + // the future there can be more than one SHT_SYMTAB section. Until + // somebody figures out how that could work, we assume there is only + // one. + const unsigned char* p = this->section_headers_->data(); + // Skip the first section, which is always empty. p += This::shdr_size; - for (unsigned int i = 1; i < shnum; ++i) + for (unsigned int i = 1; i < shnum; ++i, p += This::shdr_size) { typename This::Shdr shdr(p); if (shdr.get_sh_type() == elfcpp::SHT_SYMTAB) @@ -135,29 +144,40 @@ Sized_object<size, big_endian>::setup( this->symtab_shnum_ = i; break; } - p += This::shdr_size; } } -// Read the symbols and relocations from an object file. +// Read the sections and symbols from an object file. template<int size, bool big_endian> -Read_symbols_data -Sized_object<size, big_endian>::do_read_symbols() +void +Sized_object<size, big_endian>::do_read_symbols(Read_symbols_data* sd) { + // Transfer our view of the section headers to SD. + sd->section_headers = this->section_headers_; + this->section_headers_ = NULL; + + // Read the section names. + const unsigned char* pshdrs = sd->section_headers->data(); + const unsigned char* pshdrnames = pshdrs + this->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) { // No symbol table. Weird but legal. - Read_symbols_data ret; - ret.symbols = NULL; - ret.symbols_size = 0; - ret.symbol_names = NULL; - ret.symbol_names_size = 0; - return ret; + sd->symbols = NULL; + sd->symbols_size = 0; + sd->symbol_names = NULL; + sd->symbol_names_size = 0; + return; } - // Read the symbol table section header. - typename This::Shdr symtabshdr(this->section_header(this->symtab_shnum_)); + // Get the symbol table section header. + typename This::Shdr symtabshdr(pshdrs + + this->symtab_shnum_ * This::shdr_size); assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB); // We only need the external symbols. @@ -191,49 +211,10 @@ Sized_object<size, big_endian>::do_read_symbols() File_view* fvstrtab = this->get_lasting_view(strtabshdr.get_sh_offset(), strtabshdr.get_sh_size()); - Read_symbols_data ret; - ret.symbols = fvsymtab; - ret.symbols_size = extsize; - ret.symbol_names = fvstrtab; - ret.symbol_names_size = strtabshdr.get_sh_size(); - - return ret; -} - -// Add the symbols to the symbol table. - -template<int size, bool big_endian> -void -Sized_object<size, big_endian>::do_add_symbols(Symbol_table* symtab, - Read_symbols_data sd) -{ - if (sd.symbols == NULL) - { - assert(sd.symbol_names == NULL); - return; - } - - const int sym_size = This::sym_size; - size_t symcount = sd.symbols_size / sym_size; - if (symcount * sym_size != sd.symbols_size) - { - fprintf(stderr, - _("%s: %s: size of symbols is not multiple of symbol size\n"), - program_name, this->name().c_str()); - gold_exit(false); - } - - this->symbols_ = new Symbol*[symcount]; - - const elfcpp::Sym<size, big_endian>* syms = - reinterpret_cast<const elfcpp::Sym<size, big_endian>*>(sd.symbols->data()); - const char* sym_names = - reinterpret_cast<const char*>(sd.symbol_names->data()); - symtab->add_from_object(this, syms, symcount, sym_names, - sd.symbol_names_size, this->symbols_); - - delete sd.symbols; - delete sd.symbol_names; + sd->symbols = fvsymtab; + sd->symbols_size = extsize; + sd->symbol_names = fvstrtab; + sd->symbol_names_size = strtabshdr.get_sh_size(); } // Return whether to include a section group in the link. LAYOUT is @@ -377,24 +358,18 @@ Sized_object<size, big_endian>::include_linkonce_section( template<int size, bool big_endian> void -Sized_object<size, big_endian>::do_layout(Layout* layout) +Sized_object<size, big_endian>::do_layout(Layout* layout, + Read_symbols_data* sd) { - // This is always called from the main thread. Lock the file to - // keep the error checks happy. - Task_locker_obj<File_read> frl(this->input_file()->file()); + unsigned int shnum = this->shnum(); + if (shnum == 0) + return; // Get the section headers. - unsigned int shnum = this->shnum(); - const unsigned char* pshdrs = this->get_view(this->shoff_, - shnum * This::shdr_size); + const unsigned char* pshdrs = sd->section_headers->data(); // Get the section names. - const unsigned char* pshdrnames = pshdrs + this->shstrndx_ * This::shdr_size; - typename This::Shdr shdrnames(pshdrnames); - typename elfcpp::Elf_types<size>::Elf_WXword names_size = - shdrnames.get_sh_size(); - const unsigned char* pnamesu = this->get_view(shdrnames.get_sh_offset(), - shdrnames.get_sh_size()); + const unsigned char* pnamesu = sd->section_names->data(); const char* pnames = reinterpret_cast<const char*>(pnamesu); std::vector<Map_to_output>& map_sections(this->map_to_output()); @@ -403,11 +378,11 @@ Sized_object<size, big_endian>::do_layout(Layout* layout) // Keep track of which sections to omit. std::vector<bool> omit(shnum, false); - for (unsigned int i = 0; i < shnum; ++i) + for (unsigned int i = 0; i < shnum; ++i, pshdrs += This::shdr_size) { typename This::Shdr shdr(pshdrs); - if (shdr.get_sh_name() >= names_size) + if (shdr.get_sh_name() >= sd->section_names_size) { fprintf(stderr, _("%s: %s: bad section name offset for section %u: %lu\n"), @@ -445,9 +420,51 @@ Sized_object<size, big_endian>::do_layout(Layout* layout) map_sections[i].output_section = os; map_sections[i].offset = offset; + } + + delete sd->section_headers; + sd->section_headers = NULL; + delete sd->section_names; + sd->section_names = NULL; +} + +// Add the symbols to the symbol table. - pshdrs += This::shdr_size; +template<int size, bool big_endian> +void +Sized_object<size, big_endian>::do_add_symbols(Symbol_table* symtab, + Read_symbols_data* sd) +{ + if (sd->symbols == NULL) + { + assert(sd->symbol_names == NULL); + return; } + + const int sym_size = This::sym_size; + size_t symcount = sd->symbols_size / sym_size; + if (symcount * sym_size != sd->symbols_size) + { + fprintf(stderr, + _("%s: %s: size of symbols is not multiple of symbol size\n"), + program_name, this->name().c_str()); + gold_exit(false); + } + + this->symbols_ = new Symbol*[symcount]; + + const unsigned char* psyms = sd->symbols->data(); + const elfcpp::Sym<size, big_endian>* syms = + reinterpret_cast<const elfcpp::Sym<size, big_endian>*>(psyms); + const char* sym_names = + reinterpret_cast<const char*>(sd->symbol_names->data()); + symtab->add_from_object(this, syms, symcount, sym_names, + sd->symbol_names_size, this->symbols_); + + delete sd->symbols; + sd->symbols = NULL; + delete sd->symbol_names; + sd->symbol_names = NULL; } // Finalize the local symbols. Here we record the file offset at |