Use special value when we refer a function symbol in some way other
than calling it.
This commit is contained in:
parent
cb615bc189
commit
ab5c9e90a6
30
gold/i386.cc
30
gold/i386.cc
@ -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.
|
||||
|
||||
|
@ -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()));
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user