mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-09-11 16:46:14 +08:00
Use special value when we refer a function symbol in some way other
than calling it.
This commit is contained in:
30
gold/i386.cc
30
gold/i386.cc
@ -74,6 +74,11 @@ class Target_i386 : public Sized_target<32, false>
|
|||||||
void
|
void
|
||||||
do_finalize_sections(Layout*);
|
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.
|
// Relocate a section.
|
||||||
void
|
void
|
||||||
relocate_section(const Relocate_info<32, false>*,
|
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
|
// function, we make a PLT entry. Otherwise we need to
|
||||||
// either generate a COPY reloc or copy this reloc.
|
// either generate a COPY reloc or copy this reloc.
|
||||||
if (gsym->type() == elfcpp::STT_FUNC)
|
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
|
else
|
||||||
target->copy_reloc(&options, symtab, layout, object, data_shndx,
|
target->copy_reloc(&options, symtab, layout, object, data_shndx,
|
||||||
gsym, reloc);
|
gsym, reloc);
|
||||||
@ -1507,6 +1523,18 @@ Target_i386::relocate_section(const Relocate_info<32, false>* relinfo,
|
|||||||
view_size);
|
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
|
// Return a string used to fill a code section with nops to take up
|
||||||
// the specified length.
|
// the specified length.
|
||||||
|
|
||||||
|
@ -1307,7 +1307,7 @@ Symbol_table::write_globals(const Target* target, const Stringpool* sympool,
|
|||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
void
|
void
|
||||||
Symbol_table::sized_write_globals(const Target*,
|
Symbol_table::sized_write_globals(const Target* target,
|
||||||
const Stringpool* sympool,
|
const Stringpool* sympool,
|
||||||
const Stringpool* dynpool,
|
const Stringpool* dynpool,
|
||||||
Output_file* of) const
|
Output_file* of) const
|
||||||
@ -1359,6 +1359,7 @@ Symbol_table::sized_write_globals(const Target*,
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned int shndx;
|
unsigned int shndx;
|
||||||
|
typename elfcpp::Elf_types<32>::Elf_Addr value = sym->value();
|
||||||
switch (sym->source())
|
switch (sym->source())
|
||||||
{
|
{
|
||||||
case Symbol::FROM_OBJECT:
|
case Symbol::FROM_OBJECT:
|
||||||
@ -1377,7 +1378,8 @@ Symbol_table::sized_write_globals(const Target*,
|
|||||||
Object* symobj = sym->object();
|
Object* symobj = sym->object();
|
||||||
if (symobj->is_dynamic())
|
if (symobj->is_dynamic())
|
||||||
{
|
{
|
||||||
// FIXME.
|
if (sym->needs_dynsym_value())
|
||||||
|
value = target->dynsym_value(sym);
|
||||||
shndx = elfcpp::SHN_UNDEF;
|
shndx = elfcpp::SHN_UNDEF;
|
||||||
}
|
}
|
||||||
else if (in_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)
|
if (sym_index != -1U)
|
||||||
{
|
{
|
||||||
this->sized_write_symbol SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
|
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));
|
SELECT_SIZE_ENDIAN(size, big_endian));
|
||||||
ps += sym_size;
|
ps += sym_size;
|
||||||
}
|
}
|
||||||
@ -1424,7 +1426,7 @@ Symbol_table::sized_write_globals(const Target*,
|
|||||||
gold_assert(dynsym_index < dynamic_count);
|
gold_assert(dynsym_index < dynamic_count);
|
||||||
unsigned char* pd = dynamic_view + (dynsym_index * sym_size);
|
unsigned char* pd = dynamic_view + (dynsym_index * sym_size);
|
||||||
this->sized_write_symbol SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
|
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));
|
SELECT_SIZE_ENDIAN(size, big_endian));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1441,15 +1443,17 @@ Symbol_table::sized_write_globals(const Target*,
|
|||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
void
|
void
|
||||||
Symbol_table::sized_write_symbol(Sized_symbol<size>* sym,
|
Symbol_table::sized_write_symbol(
|
||||||
unsigned int shndx,
|
Sized_symbol<size>* sym,
|
||||||
const Stringpool* pool,
|
typename elfcpp::Elf_types<size>::Elf_Addr value,
|
||||||
unsigned char* p
|
unsigned int shndx,
|
||||||
ACCEPT_SIZE_ENDIAN) const
|
const Stringpool* pool,
|
||||||
|
unsigned char* p
|
||||||
|
ACCEPT_SIZE_ENDIAN) const
|
||||||
{
|
{
|
||||||
elfcpp::Sym_write<size, big_endian> osym(p);
|
elfcpp::Sym_write<size, big_endian> osym(p);
|
||||||
osym.put_st_name(pool->get_offset(sym->name()));
|
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_size(sym->symsize());
|
||||||
osym.put_st_info(elfcpp::elf_st_info(sym->binding(), sym->type()));
|
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_other(elfcpp::elf_st_other(sym->visibility(), sym->nonvis()));
|
||||||
|
@ -323,6 +323,21 @@ class Symbol
|
|||||||
this->plt_offset_ = plt_offset;
|
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
|
// Return true if the final value of this symbol is known at link
|
||||||
// time.
|
// time.
|
||||||
bool
|
bool
|
||||||
@ -528,6 +543,9 @@ class Symbol
|
|||||||
bool has_got_offset_ : 1;
|
bool has_got_offset_ : 1;
|
||||||
// True if the symbol has an entry in the PLT section.
|
// True if the symbol has an entry in the PLT section.
|
||||||
bool has_plt_offset_ : 1;
|
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.
|
// True if there is a warning for this symbol.
|
||||||
bool has_warning_ : 1;
|
bool has_warning_ : 1;
|
||||||
};
|
};
|
||||||
@ -1003,7 +1021,9 @@ class Symbol_table
|
|||||||
// Write out a symbol to P.
|
// Write out a symbol to P.
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
void
|
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
|
const Stringpool*, unsigned char* p
|
||||||
ACCEPT_SIZE_ENDIAN) const;
|
ACCEPT_SIZE_ENDIAN) const;
|
||||||
|
|
||||||
|
@ -114,6 +114,13 @@ class Target
|
|||||||
finalize_sections(Layout* layout)
|
finalize_sections(Layout* layout)
|
||||||
{ return this->do_finalize_sections(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
|
// Return a string to use to fill out a code section. This is
|
||||||
// basically one or more NOPS which must fill out the specified
|
// basically one or more NOPS which must fill out the specified
|
||||||
// length in bytes.
|
// length in bytes.
|
||||||
@ -158,6 +165,11 @@ class Target
|
|||||||
do_finalize_sections(Layout*)
|
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
|
// Virtual function which must be implemented by the child class if
|
||||||
// needed.
|
// needed.
|
||||||
virtual std::string
|
virtual std::string
|
||||||
|
Reference in New Issue
Block a user