Use special value when we refer a function symbol in some way other

than calling it.
This commit is contained in:
Ian Lance Taylor 2007-09-23 05:31:48 +00:00
parent cb615bc189
commit ab5c9e90a6
4 changed files with 76 additions and 12 deletions

View File

@ -74,6 +74,11 @@ class Target_i386 : public Sized_target<32, false>
void
do_finalize_sections(Layout*);
// Return the value to use for a dynamic which requires special
// treatment.
uint64_t
do_dynsym_value(const Symbol*) const;
// Relocate a section.
void
relocate_section(const Relocate_info<32, false>*,
@ -844,7 +849,18 @@ Target_i386::Scan::global(const General_options& options,
// function, we make a PLT entry. Otherwise we need to
// either generate a COPY reloc or copy this reloc.
if (gsym->type() == elfcpp::STT_FUNC)
target->make_plt_entry(symtab, layout, gsym);
{
target->make_plt_entry(symtab, layout, gsym);
// If this is not a PC relative reference, then we may
// be taking the address of the function. In that case
// we need to set the entry in the dynamic symbol table
// to the address of the PLT entry.
if (r_type != elfcpp::R_386_PC32
&& r_type != elfcpp::R_386_PC16
&& r_type != elfcpp::R_386_PC8)
gsym->set_needs_dynsym_value();
}
else
target->copy_reloc(&options, symtab, layout, object, data_shndx,
gsym, reloc);
@ -1507,6 +1523,18 @@ Target_i386::relocate_section(const Relocate_info<32, false>* relinfo,
view_size);
}
// Return the value to use for a dynamic which requires special
// treatment. This is how we support equality comparisons of function
// pointers across shared library boundaries, as described in the
// processor specific ABI supplement.
uint64_t
Target_i386::do_dynsym_value(const Symbol* gsym) const
{
gold_assert(gsym->is_from_dynobj() && gsym->has_plt_offset());
return this->plt_section()->address() + gsym->plt_offset();
}
// Return a string used to fill a code section with nops to take up
// the specified length.

View File

@ -1307,7 +1307,7 @@ Symbol_table::write_globals(const Target* target, const Stringpool* sympool,
template<int size, bool big_endian>
void
Symbol_table::sized_write_globals(const Target*,
Symbol_table::sized_write_globals(const Target* target,
const Stringpool* sympool,
const Stringpool* dynpool,
Output_file* of) const
@ -1359,6 +1359,7 @@ Symbol_table::sized_write_globals(const Target*,
}
unsigned int shndx;
typename elfcpp::Elf_types<32>::Elf_Addr value = sym->value();
switch (sym->source())
{
case Symbol::FROM_OBJECT:
@ -1377,7 +1378,8 @@ Symbol_table::sized_write_globals(const Target*,
Object* symobj = sym->object();
if (symobj->is_dynamic())
{
// FIXME.
if (sym->needs_dynsym_value())
value = target->dynsym_value(sym);
shndx = elfcpp::SHN_UNDEF;
}
else if (in_shndx == elfcpp::SHN_UNDEF
@ -1413,7 +1415,7 @@ Symbol_table::sized_write_globals(const Target*,
if (sym_index != -1U)
{
this->sized_write_symbol SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
sym, shndx, sympool, ps
sym, sym->value(), shndx, sympool, ps
SELECT_SIZE_ENDIAN(size, big_endian));
ps += sym_size;
}
@ -1424,7 +1426,7 @@ Symbol_table::sized_write_globals(const Target*,
gold_assert(dynsym_index < dynamic_count);
unsigned char* pd = dynamic_view + (dynsym_index * sym_size);
this->sized_write_symbol SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
sym, shndx, dynpool, pd
sym, value, shndx, dynpool, pd
SELECT_SIZE_ENDIAN(size, big_endian));
}
}
@ -1441,15 +1443,17 @@ Symbol_table::sized_write_globals(const Target*,
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
ACCEPT_SIZE_ENDIAN) const
Symbol_table::sized_write_symbol(
Sized_symbol<size>* sym,
typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned int shndx,
const Stringpool* pool,
unsigned char* p
ACCEPT_SIZE_ENDIAN) 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_value(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()));

View File

@ -323,6 +323,21 @@ class Symbol
this->plt_offset_ = plt_offset;
}
// Return whether this dynamic symbol needs a special value in the
// dynamic symbol table.
bool
needs_dynsym_value() const
{ return this->needs_dynsym_value_; }
// Set that this dynamic symbol needs a special value in the dynamic
// symbol table.
void
set_needs_dynsym_value()
{
gold_assert(this->object()->is_dynamic());
this->needs_dynsym_value_ = true;
}
// Return true if the final value of this symbol is known at link
// time.
bool
@ -528,6 +543,9 @@ class Symbol
bool has_got_offset_ : 1;
// True if the symbol has an entry in the PLT section.
bool has_plt_offset_ : 1;
// True if this is a dynamic symbol which needs a special value in
// the dynamic symbol table.
bool needs_dynsym_value_ : 1;
// True if there is a warning for this symbol.
bool has_warning_ : 1;
};
@ -1003,7 +1021,9 @@ class Symbol_table
// Write out a symbol to P.
template<int size, bool big_endian>
void
sized_write_symbol(Sized_symbol<size>*, unsigned int shndx,
sized_write_symbol(Sized_symbol<size>*,
typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned int shndx,
const Stringpool*, unsigned char* p
ACCEPT_SIZE_ENDIAN) const;

View File

@ -114,6 +114,13 @@ class Target
finalize_sections(Layout* layout)
{ return this->do_finalize_sections(layout); }
// Return the value to use for a global symbol which needs a special
// value in the dynamic symbol table. This will only be called if
// the backend first calls symbol->set_needs_dynsym_value().
uint64_t
dynsym_value(const Symbol* sym) const
{ return this->do_dynsym_value(sym); }
// Return a string to use to fill out a code section. This is
// basically one or more NOPS which must fill out the specified
// length in bytes.
@ -158,6 +165,11 @@ class Target
do_finalize_sections(Layout*)
{ }
// Virtual function which may be implemented by the child class.
virtual uint64_t
do_dynsym_value(const Symbol*) const
{ gold_unreachable(); }
// Virtual function which must be implemented by the child class if
// needed.
virtual std::string