aboutsummaryrefslogtreecommitdiff
path: root/gold/symtab.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2006-12-01 16:51:25 +0000
committerIan Lance Taylor <iant@google.com>2006-12-01 16:51:25 +0000
commit16649710df23ad9038e0057035882a92e783f7e6 (patch)
tree7d4db6bb5578f6c90193108bc525a39f09ab379d /gold/symtab.cc
parent8a82f7e3921015b4cbadf29379d8af9d9f6af891 (diff)
downloadfsf-binutils-gdb-16649710df23ad9038e0057035882a92e783f7e6.zip
fsf-binutils-gdb-16649710df23ad9038e0057035882a92e783f7e6.tar.gz
fsf-binutils-gdb-16649710df23ad9038e0057035882a92e783f7e6.tar.bz2
Can now dynamically link hello, world.
Diffstat (limited to 'gold/symtab.cc')
-rw-r--r--gold/symtab.cc141
1 files changed, 100 insertions, 41 deletions
diff --git a/gold/symtab.cc b/gold/symtab.cc
index 4d2bb1a..21192c1 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -55,7 +55,7 @@ Symbol::init_base(const char* name, const char* version, Object* object,
sym.get_st_visibility(), sym.get_st_nonvis());
this->u_.from_object.object = object;
// FIXME: Handle SHN_XINDEX.
- this->u_.from_object.shnum = sym.get_st_shndx();
+ this->u_.from_object.shndx = sym.get_st_shndx();
this->source_ = FROM_OBJECT;
this->in_dyn_ = object->is_dynamic();
}
@@ -258,7 +258,7 @@ Symbol_table::resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from
esym.put_st_size(from->symsize());
esym.put_st_info(from->binding(), from->type());
esym.put_st_other(from->visibility(), from->nonvis());
- esym.put_st_shndx(from->shnum());
+ esym.put_st_shndx(from->shndx());
Symbol_table::resolve(to, esym.sym(), from->object());
}
@@ -717,9 +717,9 @@ Symbol_table::define_special_symbol(Target* target, const char* name,
sym = this->get_sized_symbol SELECT_SIZE_NAME(size) (oldsym
SELECT_SIZE(size));
gold_assert(sym->source() == Symbol::FROM_OBJECT);
- const int old_shnum = sym->shnum();
- if (old_shnum != elfcpp::SHN_UNDEF
- && old_shnum != elfcpp::SHN_COMMON
+ const int old_shndx = sym->shndx();
+ if (old_shndx != elfcpp::SHN_UNDEF
+ && old_shndx != elfcpp::SHN_COMMON
&& !sym->object()->is_dynamic())
{
fprintf(stderr, "%s: linker defined: multiple definition of %s\n",
@@ -969,7 +969,14 @@ Symbol_table::set_dynsym_indexes(unsigned int index,
++p)
{
Symbol* sym = p->second;
- if (sym->needs_dynsym_entry())
+
+ // Note that SYM may already have a dynamic symbol index, since
+ // some symbols appear more than once in the symbol table, with
+ // and without a version.
+
+ if (!sym->needs_dynsym_entry())
+ sym->set_dynsym_index(-1U);
+ else if (!sym->has_dynsym_index())
{
sym->set_dynsym_index(index);
++index;
@@ -986,13 +993,19 @@ Symbol_table::set_dynsym_indexes(unsigned int index,
// OFF. Add their names to POOL. Return the new file offset.
off_t
-Symbol_table::finalize(unsigned int index, off_t off, Stringpool* pool)
+Symbol_table::finalize(unsigned int index, off_t off, off_t dynoff,
+ size_t dyn_global_index, size_t dyncount,
+ Stringpool* pool)
{
off_t ret;
gold_assert(index != 0);
this->first_global_index_ = index;
+ this->dynamic_offset_ = dynoff;
+ this->first_dynamic_global_index_ = dyn_global_index;
+ this->dynamic_count_ = dyncount;
+
if (this->size_ == 32)
ret = this->sized_finalize<32>(index, off, pool);
else if (this->size_ == 64)
@@ -1041,14 +1054,14 @@ Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool)
{
case Symbol::FROM_OBJECT:
{
- unsigned int shnum = sym->shnum();
+ unsigned int shndx = sym->shndx();
// FIXME: We need some target specific support here.
- if (shnum >= elfcpp::SHN_LORESERVE
- && shnum != elfcpp::SHN_ABS)
+ if (shndx >= elfcpp::SHN_LORESERVE
+ && shndx != elfcpp::SHN_ABS)
{
fprintf(stderr, _("%s: %s: unsupported symbol section 0x%x\n"),
- program_name, sym->name(), shnum);
+ program_name, sym->name(), shndx);
gold_exit(false);
}
@@ -1056,21 +1069,22 @@ Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool)
if (symobj->is_dynamic())
{
value = 0;
- shnum = elfcpp::SHN_UNDEF;
+ shndx = elfcpp::SHN_UNDEF;
}
- else if (shnum == elfcpp::SHN_UNDEF)
+ else if (shndx == elfcpp::SHN_UNDEF)
value = 0;
- else if (shnum == elfcpp::SHN_ABS)
+ else if (shndx == elfcpp::SHN_ABS)
value = sym->value();
else
{
Relobj* relobj = static_cast<Relobj*>(symobj);
off_t secoff;
- Output_section* os = relobj->output_section(shnum, &secoff);
+ Output_section* os = relobj->output_section(shndx, &secoff);
if (os == NULL)
{
sym->set_symtab_index(-1U);
+ gold_assert(sym->dynsym_index() == -1U);
continue;
}
@@ -1132,21 +1146,21 @@ Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool)
void
Symbol_table::write_globals(const Target* target, const Stringpool* sympool,
- Output_file* of) const
+ const Stringpool* dynpool, Output_file* of) const
{
if (this->size_ == 32)
{
if (target->is_big_endian())
- this->sized_write_globals<32, true>(target, sympool, of);
+ this->sized_write_globals<32, true>(target, sympool, dynpool, of);
else
- this->sized_write_globals<32, false>(target, sympool, of);
+ this->sized_write_globals<32, false>(target, sympool, dynpool, of);
}
else if (this->size_ == 64)
{
if (target->is_big_endian())
- this->sized_write_globals<64, true>(target, sympool, of);
+ this->sized_write_globals<64, true>(target, sympool, dynpool, of);
else
- this->sized_write_globals<64, false>(target, sympool, of);
+ this->sized_write_globals<64, false>(target, sympool, dynpool, of);
}
else
gold_unreachable();
@@ -1158,12 +1172,22 @@ template<int size, bool big_endian>
void
Symbol_table::sized_write_globals(const Target*,
const Stringpool* sympool,
+ const Stringpool* dynpool,
Output_file* of) const
{
const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
unsigned int index = this->first_global_index_;
const off_t oview_size = this->output_count_ * sym_size;
- unsigned char* psyms = of->get_output_view(this->offset_, oview_size);
+ unsigned char* const psyms = of->get_output_view(this->offset_, oview_size);
+
+ unsigned int dynamic_count = this->dynamic_count_;
+ off_t dynamic_size = dynamic_count * sym_size;
+ unsigned int first_dynamic_global_index = this->first_dynamic_global_index_;
+ unsigned char* dynamic_view;
+ if (this->dynamic_offset_ == 0)
+ dynamic_view = NULL;
+ else
+ dynamic_view = of->get_output_view(this->dynamic_offset_, dynamic_size);
unsigned char* ps = psyms;
for (Symbol_table_type::const_iterator p = this->table_.begin();
@@ -1173,33 +1197,43 @@ Symbol_table::sized_write_globals(const Target*,
Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(p->second);
unsigned int sym_index = sym->symtab_index();
- if (sym_index == -1U)
+ unsigned int dynsym_index;
+ if (dynamic_view == NULL)
+ dynsym_index = -1U;
+ else
+ dynsym_index = sym->dynsym_index();
+
+ if (sym_index == -1U && dynsym_index == -1U)
{
// This symbol is not included in the output file.
continue;
}
- if (sym_index != index)
+
+ if (sym_index == index)
+ ++index;
+ else if (sym_index != -1U)
{
// We have already seen this symbol, because it has a
// default version.
gold_assert(sym_index < index);
- continue;
+ if (dynsym_index == -1U)
+ continue;
+ sym_index = -1U;
}
- ++index;
unsigned int shndx;
switch (sym->source())
{
case Symbol::FROM_OBJECT:
{
- unsigned int shnum = sym->shnum();
+ unsigned int in_shndx = sym->shndx();
// FIXME: We need some target specific support here.
- if (shnum >= elfcpp::SHN_LORESERVE
- && shnum != elfcpp::SHN_ABS)
+ if (in_shndx >= elfcpp::SHN_LORESERVE
+ && in_shndx != elfcpp::SHN_ABS)
{
fprintf(stderr, _("%s: %s: unsupported symbol section 0x%x\n"),
- program_name, sym->name(), sym->shnum());
+ program_name, sym->name(), in_shndx);
gold_exit(false);
}
@@ -1209,13 +1243,14 @@ Symbol_table::sized_write_globals(const Target*,
// FIXME.
shndx = elfcpp::SHN_UNDEF;
}
- else if (shnum == elfcpp::SHN_UNDEF || shnum == elfcpp::SHN_ABS)
- shndx = shnum;
+ else if (in_shndx == elfcpp::SHN_UNDEF
+ || in_shndx == elfcpp::SHN_ABS)
+ shndx = in_shndx;
else
{
Relobj* relobj = static_cast<Relobj*>(symobj);
off_t secoff;
- Output_section* os = relobj->output_section(shnum, &secoff);
+ Output_section* os = relobj->output_section(in_shndx, &secoff);
gold_assert(os != NULL);
shndx = os->out_shndx();
}
@@ -1238,21 +1273,45 @@ Symbol_table::sized_write_globals(const Target*,
gold_unreachable();
}
- elfcpp::Sym_write<size, big_endian> osym(ps);
- osym.put_st_name(sympool->get_offset(sym->name()));
- osym.put_st_value(sym->value());
- osym.put_st_size(sym->symsize());
- osym.put_st_info(elfcpp::elf_st_info(sym->binding(), sym->type()));
- osym.put_st_other(elfcpp::elf_st_other(sym->visibility(),
- sym->nonvis()));
- osym.put_st_shndx(shndx);
+ if (sym_index != -1U)
+ {
+ this->sized_write_symbol<size, big_endian>(sym, shndx, sympool, ps);
+ ps += sym_size;
+ }
- ps += sym_size;
+ if (dynsym_index != -1U)
+ {
+ dynsym_index -= first_dynamic_global_index;
+ gold_assert(dynsym_index < dynamic_count);
+ unsigned char* pd = dynamic_view + (dynsym_index * sym_size);
+ this->sized_write_symbol<size, big_endian>(sym, shndx, dynpool, pd);
+ }
}
gold_assert(ps - psyms == oview_size);
of->write_output_view(this->offset_, oview_size, psyms);
+ if (dynamic_view != NULL)
+ of->write_output_view(this->dynamic_offset_, dynamic_size, dynamic_view);
+}
+
+// Write out the symbol SYM, in section SHNDX, to P. POOL is the
+// strtab holding the name.
+
+template<int size, bool big_endian>
+void
+Symbol_table::sized_write_symbol(Sized_symbol<size>* sym,
+ unsigned int shndx,
+ const Stringpool* pool,
+ unsigned char* p) const
+{
+ elfcpp::Sym_write<size, big_endian> osym(p);
+ osym.put_st_name(pool->get_offset(sym->name()));
+ osym.put_st_value(sym->value());
+ osym.put_st_size(sym->symsize());
+ osym.put_st_info(elfcpp::elf_st_info(sym->binding(), sym->type()));
+ osym.put_st_other(elfcpp::elf_st_other(sym->visibility(), sym->nonvis()));
+ osym.put_st_shndx(shndx);
}
// Write out a section symbol. Return the update offset.