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),
return this->get_view(symtabshdroff, This::shdr_size);
}
+// Return the name of section SHNUM.
+
+template<int size, bool big_endian>
+std::string
+Sized_object<size, big_endian>::do_section_name(unsigned int shnum)
+{
+ Task_lock_obj<Object> tl(*this);
+
+ // 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());
+}
+
// Set up an object file bsaed on the file header. This sets up the
// target and reads the section information.
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)
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)
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.
const int sym_size = This::sym_size;
- off_t locsize = symtabshdr.get_sh_info() * sym_size;
+ const unsigned int loccount = symtabshdr.get_sh_info();
+ this->local_symbol_count_ = loccount;
+ off_t locsize = loccount * sym_size;
off_t extoff = symtabshdr.get_sh_offset() + locsize;
off_t extsize = symtabshdr.get_sh_size() - locsize;
File_view* fvsymtab = this->get_lasting_view(extoff, extsize);
// Read the section header for the symbol names.
+ unsigned int shnum = this->shnum();
unsigned int strtab_shnum = symtabshdr.get_sh_link();
- if (strtab_shnum == 0 || strtab_shnum >= this->shnum())
+ if (strtab_shnum == 0 || strtab_shnum >= shnum)
{
fprintf(stderr, _("%s: %s: invalid symbol table name index: %u\n"),
program_name, this->name().c_str(), strtab_shnum);
gold_exit(false);
}
- typename This::Shdr strtabshdr(this->section_header(strtab_shnum));
+ typename This::Shdr strtabshdr(pshdrs + strtab_shnum * This::shdr_size);
if (strtabshdr.get_sh_type() != elfcpp::SHT_STRTAB)
{
fprintf(stderr,
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
const elfcpp::Shdr<size, big_endian>&)
{
const char* symname = strrchr(name, '.') + 1;
- bool omit1 = layout->add_comdat(symname, false);
- bool omit2 = layout->add_comdat(name, true);
- return omit1 || omit2;
+ bool include1 = layout->add_comdat(symname, false);
+ bool include2 = layout->add_comdat(name, true);
+ return include1 && include2;
}
// Lay out the input sections. We walk through the sections and check
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());
// 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"),
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
assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);
// Read the local symbols.
- unsigned int loccount = symtabshdr.get_sh_info();
const int sym_size = This::sym_size;
+ const unsigned int loccount = this->local_symbol_count_;
+ assert(loccount == symtabshdr.get_sh_info());
off_t locsize = loccount * sym_size;
const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
locsize);
- this->local_symbol_count_ = loccount;
-
this->values_ = new typename elfcpp::Elf_types<size>::Elf_Addr[loccount];
// Read the section header for the symbol names.
// Read the symbol table section header.
typename This::Shdr symtabshdr(this->section_header(this->symtab_shnum_));
assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);
- unsigned int local_symbol_count = this->local_symbol_count_;
- assert(local_symbol_count == symtabshdr.get_sh_info());
+ const unsigned int loccount = this->local_symbol_count_;
+ assert(loccount == symtabshdr.get_sh_info());
// Read the local symbols.
const int sym_size = This::sym_size;
- off_t locsize = local_symbol_count * sym_size;
+ off_t locsize = loccount * sym_size;
const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
locsize);
psyms += sym_size;
unsigned char* ov = oview;
- for (unsigned int i = 1; i < local_symbol_count; ++i, psyms += sym_size)
+ for (unsigned int i = 1; i < loccount; ++i, psyms += sym_size)
{
elfcpp::Sym<size, big_endian> isym(psyms);
elfcpp::Sym_write<size, big_endian> osym(ov);
this->any_dynamic_ = true;
}
+// Relocate_info methods.
+
+// Return a string describing the location of a relocation. This is
+// only used in error messages.
+
+template<int size, bool big_endian>
+std::string
+Relocate_info<size, big_endian>::location(size_t relnum, off_t) const
+{
+ std::string ret(this->object->name());
+ ret += ": reloc ";
+ char buf[100];
+ snprintf(buf, sizeof buf, "%zu", relnum);
+ ret += buf;
+ ret += " in reloc section ";
+ snprintf(buf, sizeof buf, "%u", this->reloc_shndx);
+ ret += buf;
+ ret += " (" + this->object->section_name(this->reloc_shndx);
+ ret += ") for section ";
+ snprintf(buf, sizeof buf, "%u", this->data_shndx);
+ ret += buf;
+ ret += " (" + this->object->section_name(this->data_shndx) + ")";
+ return ret;
+}
+
} // End namespace gold.
namespace
template
class Sized_object<64, true>;
+template
+struct Relocate_info<32, false>;
+
+template
+struct Relocate_info<32, true>;
+
+template
+struct Relocate_info<64, false>;
+
+template
+struct Relocate_info<64, true>;
+
} // End namespace gold.