aboutsummaryrefslogtreecommitdiff
path: root/gold/object.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2006-09-27 22:53:42 +0000
committerIan Lance Taylor <iant@google.com>2006-09-27 22:53:42 +0000
commit75f65a3e309b8cd885c782f6af106d1e2a1876f6 (patch)
tree0f21c32a5e40156d007fd6a676b5d74a8c423c90 /gold/object.cc
parent6b89cc2108a525fdc4186bae5365acc258e9c23c (diff)
downloadgdb-75f65a3e309b8cd885c782f6af106d1e2a1876f6.zip
gdb-75f65a3e309b8cd885c782f6af106d1e2a1876f6.tar.gz
gdb-75f65a3e309b8cd885c782f6af106d1e2a1876f6.tar.bz2
Finished layout code.
Diffstat (limited to 'gold/object.cc')
-rw-r--r--gold/object.cc176
1 files changed, 129 insertions, 47 deletions
diff --git a/gold/object.cc b/gold/object.cc
index 04a31bd..85019fb 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -47,7 +47,8 @@ Sized_object<size, big_endian>::Sized_object(
shoff_(ehdr.get_e_shoff()),
shstrndx_(0),
symtab_shnum_(0),
- symbols_(NULL)
+ symbols_(NULL),
+ local_symbol_offset_(0)
{
if (ehdr.get_e_ehsize() != This::ehdr_size)
{
@@ -70,6 +71,16 @@ Sized_object<size, big_endian>::~Sized_object()
{
}
+// Read the section header for section SHNUM.
+
+template<int size, bool big_endian>
+const unsigned char*
+Sized_object<size, big_endian>::section_header(unsigned int shnum)
+{
+ off_t symtabshdroff = this->shoff_ + shnum * This::shdr_size;
+ return this->get_view(symtabshdroff, This::shdr_size);
+}
+
// Set up an object file bsaed on the file header. This sets up the
// target and reads the section information.
@@ -94,8 +105,7 @@ Sized_object<size, big_endian>::setup(
if ((shnum == 0 || shstrndx == elfcpp::SHN_XINDEX)
&& this->shoff_ != 0)
{
- const unsigned char* p = this->get_view (this->shoff_, This::shdr_size);
- elfcpp::Shdr<size, big_endian> shdr(p);
+ typename This::Shdr shdr(this->section_header(0));
if (shnum == 0)
shnum = shdr.get_sh_size();
if (shstrndx == elfcpp::SHN_XINDEX)
@@ -114,7 +124,7 @@ Sized_object<size, big_endian>::setup(
p += This::shdr_size;
for (unsigned int i = 1; i < shnum; ++i)
{
- elfcpp::Shdr<size, big_endian> shdr(p);
+ typename This::Shdr shdr(p);
if (shdr.get_sh_type() == elfcpp::SHT_SYMTAB)
{
this->symtab_shnum_ = i;
@@ -136,23 +146,23 @@ Sized_object<size, big_endian>::do_read_symbols()
Read_symbols_data ret;
ret.symbols = NULL;
ret.symbols_size = 0;
- ret.first_global = 0;
ret.symbol_names = NULL;
ret.symbol_names_size = 0;
return ret;
}
- const int shdr_size = This::shdr_size;
-
// Read the symbol table section header.
- off_t symtabshdroff = this->shoff_ + (this->symtab_shnum_ * shdr_size);
- const unsigned char* psymtabshdr = this->get_view(symtabshdroff, shdr_size);
- elfcpp::Shdr<size, big_endian> symtabshdr(psymtabshdr);
+ typename This::Shdr symtabshdr(this->section_header(this->symtab_shnum_));
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;
+ off_t extoff = symtabshdr.get_sh_offset() + locsize;
+ off_t extsize = symtabshdr.get_sh_size() - locsize;
+
// Read the symbol table.
- File_view* fvsymtab = this->get_lasting_view(symtabshdr.get_sh_offset(),
- symtabshdr.get_sh_size());
+ File_view* fvsymtab = this->get_lasting_view(extoff, extsize);
// Read the section header for the symbol names.
unsigned int strtab_shnum = symtabshdr.get_sh_link();
@@ -162,9 +172,7 @@ Sized_object<size, big_endian>::do_read_symbols()
program_name, this->name().c_str(), strtab_shnum);
gold_exit(false);
}
- off_t strtabshdroff = this->shoff_ + (strtab_shnum * shdr_size);
- const unsigned char *pstrtabshdr = this->get_view(strtabshdroff, shdr_size);
- elfcpp::Shdr<size, big_endian> strtabshdr(pstrtabshdr);
+ typename This::Shdr strtabshdr(this->section_header(strtab_shnum));
if (strtabshdr.get_sh_type() != elfcpp::SHT_STRTAB)
{
fprintf(stderr,
@@ -180,8 +188,7 @@ Sized_object<size, big_endian>::do_read_symbols()
Read_symbols_data ret;
ret.symbols = fvsymtab;
- ret.symbols_size = symtabshdr.get_sh_size();
- ret.first_global = symtabshdr.get_sh_info();
+ ret.symbols_size = extsize;
ret.symbol_names = fvstrtab;
ret.symbol_names_size = strtabshdr.get_sh_size();
@@ -211,29 +218,14 @@ Sized_object<size, big_endian>::do_add_symbols(Symbol_table* symtab,
gold_exit(false);
}
- const char* sym_names =
- reinterpret_cast<const char*>(sd.symbol_names->data());
-
- // We only add the global symbols to the symbol table.
- if (symcount > sd.first_global)
- {
- this->symbols_ = new Symbol*[symcount - sd.first_global];
-
- const unsigned char* symdata = sd.symbols->data();
- symdata += sd.first_global * sym_size;
- const elfcpp::Sym<size, big_endian>* syms =
- reinterpret_cast<const elfcpp::Sym<size, big_endian>*>(symdata);
-
- symtab->add_from_object(this, syms, symcount - sd.first_global,
- sym_names, sd.symbol_names_size, this->symbols_);
- }
+ this->symbols_ = new Symbol*[symcount];
- // Add the names of the local symbols. FIXME: We shouldn't do this
- // if we are stripping symbols.
- const elfcpp::Sym<size, big_endian>* local_syms =
+ const elfcpp::Sym<size, big_endian>* syms =
reinterpret_cast<const elfcpp::Sym<size, big_endian>*>(sd.symbols->data());
- symtab->add_local_symbol_names(this, local_syms, sd.first_global,
- sym_names, sd.symbol_names_size);
+ 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;
@@ -279,9 +271,8 @@ Sized_object<size, big_endian>::include_section_group(
program_name, this->name().c_str(), index, shdr.get_sh_link());
gold_exit(false);
}
- off_t off = this->shoff_ + shdr.get_sh_link() * This::shdr_size;
- const unsigned char* psymshdr = this->get_view(off, This::shdr_size);
- elfcpp::Shdr<size, big_endian> symshdr(psymshdr);
+
+ typename This::Shdr symshdr(this->section_header(shdr.get_sh_link()));
// Read the symbol table entry.
if (shdr.get_sh_info() >= symshdr.get_sh_size() / This::sym_size)
@@ -302,10 +293,8 @@ Sized_object<size, big_endian>::include_section_group(
symshdr.get_sh_link());
gold_exit(false);
}
- off_t symnameoff = this->shoff_ + symshdr.get_sh_link() * This::shdr_size;
- const unsigned char* psymnamehdr = this->get_view(symnameoff,
- This::shdr_size);
- elfcpp::Shdr<size, big_endian> symnamehdr(psymnamehdr);
+
+ 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(),
@@ -396,7 +385,7 @@ Sized_object<size, big_endian>::do_layout(Layout* layout)
// Get the section names.
const unsigned char* pshdrnames = pshdrs + this->shstrndx_ * This::shdr_size;
- elfcpp::Shdr<size, big_endian> shdrnames(pshdrnames);
+ 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(),
@@ -411,7 +400,7 @@ Sized_object<size, big_endian>::do_layout(Layout* layout)
for (unsigned int i = 0; i < shnum; ++i)
{
- elfcpp::Shdr<size, big_endian> shdr(pshdrs);
+ typename This::Shdr shdr(pshdrs);
if (shdr.get_sh_name() >= names_size)
{
@@ -456,12 +445,105 @@ Sized_object<size, big_endian>::do_layout(Layout* layout)
}
}
+// Finalize the local symbols. Here we record the file offset at
+// which they should be output and we add their names to *POOL.
+// Return the new file offset. This function is always called from
+// the main thread. The actual output of the local symbols will occur
+// in a separate task.
+
+template<int size, bool big_endian>
+off_t
+Sized_object<size, big_endian>::do_finalize_local_symbols(off_t off,
+ Stringpool* pool)
+{
+ this->local_symbol_offset_ = off;
+
+ // Read the symbol table section header.
+ typename This::Shdr symtabshdr(this->section_header(this->symtab_shnum_));
+ 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;
+ off_t locsize = loccount * sym_size;
+ 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 char* pnames = reinterpret_cast<const char*>(pnamesu);
+
+ // Loop over the local symbols.
+
+ std::vector<Map_to_output>& mo(this->map_to_output());
+ unsigned int shnum = this->shnum();
+ // Skip the first, dummy, symbol.
+ psyms += sym_size;
+ for (unsigned int i = 1; i < loccount; ++i)
+ {
+ elfcpp::Sym<size, big_endian> sym(psyms);
+
+ unsigned int shndx = sym.get_st_shndx();
+
+ if (shndx >= elfcpp::SHN_LORESERVE)
+ {
+ if (shndx != elfcpp::SHN_ABS)
+ {
+ fprintf(stderr,
+ _("%s: %s: unknown section index %u "
+ "for local symbol %u\n"),
+ program_name, this->name().c_str(), shndx, i);
+ gold_exit(false);
+ }
+ // FIXME: Handle SHN_XINDEX.
+ }
+ else
+ {
+ if (shndx >= shnum)
+ {
+ fprintf(stderr,
+ _("%s: %s: local symbol %u section index %u "
+ "out of range\n"),
+ program_name, this->name().c_str(), i, shndx);
+ gold_exit(false);
+ }
+
+ if (mo[shndx].output_section == NULL)
+ continue;
+ }
+
+ pool->add(pnames + sym.get_st_name());
+ off += sym_size;
+
+ psyms += sym_size;
+ }
+
+ return off;
+}
+
// Input_objects methods.
void
Input_objects::add_object(Object* obj)
{
this->object_list_.push_back(obj);
+
+ Target* target = obj->target();
+ if (this->target_ == NULL)
+ this->target_ = target;
+ else if (this->target_ != target)
+ {
+ fprintf(stderr, "%s: %s: incompatible target\n",
+ program_name, obj->name().c_str());
+ gold_exit(false);
+ }
+
if (obj->is_dynamic())
this->any_dynamic_ = true;
}