Commit 85f94374 authored by Alan Modra's avatar Alan Modra

Remove powerpc.cc copy of use_plt_offset

(cherry picked from commit 88b8e63904fda25c029deaf25d7b4e489b351470)
parent a9ca6f4e
2013-11-15 Alan Modra <amodra@gmail.com>
Apply changes from mainline to 2.24
2013-11-04 Alan Modra <amodra@gmail.com>
* symtab.h (Symbol::Reference_flags): Add FUNC_DESC_ABI.
(Symbol::needs_dynamic_reloc): Test new flag.
* powerpc.cc (needs_dynamic_reloc, use_plt_offset): Delete.
(Target_powerpc::Scan::get_reference_flags): Add target param.
Return FUNC_DESC_ABI for 64-bit ELFv1.
(Target_powerpc::Branch_info::make_stub): Adjust get_reference_flags
call.
(Target_powerpc::Scan::global): Use Symbol::needs_dynamic_reloc.
(Target_powerpc::Relocate::relocate): Use Symbol::use_plt_offset.
2013-10-30 Alan Modra <amodra@gmail.com>
* powerpc.cc (Powerpc_relobj::abiversion, set_abiversion,
ppc64_local_entry_offset, ppc64_local_entry_offset,
......
......@@ -918,7 +918,7 @@ class Target_powerpc : public Sized_target<size, big_endian>
{ }
static inline int
get_reference_flags(unsigned int r_type);
get_reference_flags(unsigned int r_type, const Target_powerpc* target);
inline void
local(Symbol_table* symtab, Layout* layout, Target_powerpc* target,
......@@ -1429,102 +1429,6 @@ at_tls_transform(uint32_t insn, unsigned int reg)
return insn;
}
// Modified version of symtab.h class Symbol member
// Given a direct absolute or pc-relative static relocation against
// the global symbol, this function returns whether a dynamic relocation
// is needed.
template<int size>
bool
needs_dynamic_reloc(const Symbol* gsym, int flags)
{
// No dynamic relocations in a static link!
if (parameters->doing_static_link())
return false;
// A reference to an undefined symbol from an executable should be
// statically resolved to 0, and does not need a dynamic relocation.
// This matches gnu ld behavior.
if (gsym->is_undefined() && !parameters->options().shared())
return false;
// A reference to an absolute symbol does not need a dynamic relocation.
if (gsym->is_absolute())
return false;
// An absolute reference within a position-independent output file
// will need a dynamic relocation.
if ((flags & Symbol::ABSOLUTE_REF)
&& parameters->options().output_is_position_independent())
return true;
// A function call that can branch to a local PLT entry does not need
// a dynamic relocation.
if ((flags & Symbol::FUNCTION_CALL) && gsym->has_plt_offset())
return false;
// A reference to any PLT entry in a non-position-independent executable
// does not need a dynamic relocation.
// Except due to having function descriptors on powerpc64 we don't define
// functions to their plt code in an executable, so this doesn't apply.
if (size == 32
&& !parameters->options().output_is_position_independent()
&& gsym->has_plt_offset())
return false;
// A reference to a symbol defined in a dynamic object or to a
// symbol that is preemptible will need a dynamic relocation.
if (gsym->is_from_dynobj()
|| gsym->is_undefined()
|| gsym->is_preemptible())
return true;
// For all other cases, return FALSE.
return false;
}
// Modified version of symtab.h class Symbol member
// Whether we should use the PLT offset associated with a symbol for
// a relocation. FLAGS is a set of Reference_flags.
template<int size>
bool
use_plt_offset(const Symbol* gsym, int flags)
{
// If the symbol doesn't have a PLT offset, then naturally we
// don't want to use it.
if (!gsym->has_plt_offset())
return false;
// For a STT_GNU_IFUNC symbol we always have to use the PLT entry.
if (gsym->type() == elfcpp::STT_GNU_IFUNC)
return true;
// If we are going to generate a dynamic relocation, then we will
// wind up using that, so no need to use the PLT entry.
if (needs_dynamic_reloc<size>(gsym, flags))
return false;
// If the symbol is from a dynamic object, we need to use the PLT
// entry.
if (gsym->is_from_dynobj())
return true;
// If we are generating a shared object, and this symbol is
// undefined or preemptible, we need to use the PLT entry.
if (parameters->options().shared()
&& (gsym->is_undefined() || gsym->is_preemptible()))
return true;
// If this is a call to a weak undefined symbol, we need to use
// the PLT entry; the symbol may be defined by a library loaded
// at runtime.
if ((flags & Symbol::FUNCTION_CALL) && gsym->is_weak_undefined())
return true;
// Otherwise we can use the regular definition.
return false;
}
template<int size, bool big_endian>
class Powerpc_relocate_functions
......@@ -2619,8 +2523,11 @@ Target_powerpc<size, big_endian>::Branch_info::make_stub(
if (sym != NULL && sym->is_forwarder())
sym = symtab->resolve_forwards(sym);
const Sized_symbol<size>* gsym = static_cast<const Sized_symbol<size>*>(sym);
Target_powerpc<size, big_endian>* target =
static_cast<Target_powerpc<size, big_endian>*>(
parameters->sized_target<size, big_endian>());
if (gsym != NULL
? use_plt_offset<size>(gsym, Scan::get_reference_flags(this->r_type_))
? gsym->use_plt_offset(Scan::get_reference_flags(this->r_type_, target))
: this->object_->local_has_plt_offset(this->r_sym_))
{
if (stub_table == NULL)
......@@ -2706,9 +2613,6 @@ Target_powerpc<size, big_endian>::Branch_info::make_stub(
if (size == 64 && is_branch_reloc(this->r_type_))
{
unsigned int dest_shndx;
Target_powerpc<size, big_endian>* target =
static_cast<Target_powerpc<size, big_endian>*>(
parameters->sized_target<size, big_endian>());
to = target->symval_for_branch(symtab, to, gsym,
this->object_, &dest_shndx);
}
......@@ -5002,8 +4906,12 @@ Target_powerpc<size, big_endian>::tlsld_got_offset(
template<int size, bool big_endian>
int
Target_powerpc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
Target_powerpc<size, big_endian>::Scan::get_reference_flags(
unsigned int r_type,
const Target_powerpc* target)
{
int ref = 0;
switch (r_type)
{
case elfcpp::R_POWERPC_NONE:
......@@ -5011,7 +4919,7 @@ Target_powerpc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
case elfcpp::R_POWERPC_GNU_VTENTRY:
case elfcpp::R_PPC64_TOC:
// No symbol reference.
return 0;
break;
case elfcpp::R_PPC64_ADDR64:
case elfcpp::R_PPC64_UADDR64:
......@@ -5022,13 +4930,15 @@ Target_powerpc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
case elfcpp::R_POWERPC_ADDR16_LO:
case elfcpp::R_POWERPC_ADDR16_HI:
case elfcpp::R_POWERPC_ADDR16_HA:
return Symbol::ABSOLUTE_REF;
ref = Symbol::ABSOLUTE_REF;
break;
case elfcpp::R_POWERPC_ADDR24:
case elfcpp::R_POWERPC_ADDR14:
case elfcpp::R_POWERPC_ADDR14_BRTAKEN:
case elfcpp::R_POWERPC_ADDR14_BRNTAKEN:
return Symbol::FUNCTION_CALL | Symbol::ABSOLUTE_REF;
ref = Symbol::FUNCTION_CALL | Symbol::ABSOLUTE_REF;
break;
case elfcpp::R_PPC64_REL64:
case elfcpp::R_POWERPC_REL32:
......@@ -5037,14 +4947,16 @@ Target_powerpc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
case elfcpp::R_POWERPC_REL16_LO:
case elfcpp::R_POWERPC_REL16_HI:
case elfcpp::R_POWERPC_REL16_HA:
return Symbol::RELATIVE_REF;
ref = Symbol::RELATIVE_REF;
break;
case elfcpp::R_POWERPC_REL24:
case elfcpp::R_PPC_PLTREL24:
case elfcpp::R_POWERPC_REL14:
case elfcpp::R_POWERPC_REL14_BRTAKEN:
case elfcpp::R_POWERPC_REL14_BRNTAKEN:
return Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF;
ref = Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF;
break;
case elfcpp::R_POWERPC_GOT16:
case elfcpp::R_POWERPC_GOT16_LO:
......@@ -5059,11 +4971,13 @@ Target_powerpc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
case elfcpp::R_PPC64_TOC16_DS:
case elfcpp::R_PPC64_TOC16_LO_DS:
// Absolute in GOT.
return Symbol::ABSOLUTE_REF;
ref = Symbol::ABSOLUTE_REF;
break;
case elfcpp::R_POWERPC_GOT_TPREL16:
case elfcpp::R_POWERPC_TLS:
return Symbol::TLS_REF;
ref = Symbol::TLS_REF;
break;
case elfcpp::R_POWERPC_COPY:
case elfcpp::R_POWERPC_GLOB_DAT:
......@@ -5072,8 +4986,12 @@ Target_powerpc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
case elfcpp::R_POWERPC_DTPMOD:
default:
// Not expected. We will give an error later.
return 0;
break;
}
if (size == 64 && target->abiversion() < 2)
ref |= Symbol::FUNC_DESC_ABI;
return ref;
}
// Report an unsupported relocation against a local symbol.
......@@ -5764,7 +5682,7 @@ Target_powerpc<size, big_endian>::Scan::global(
gsym->set_needs_dynsym_value();
}
// Make a dynamic relocation if necessary.
if (needs_dynamic_reloc<size>(gsym, Scan::get_reference_flags(r_type))
if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type, target))
|| (size == 64 && is_ifunc))
{
if (gsym->may_need_copy_reloc())
......@@ -5824,7 +5742,7 @@ Target_powerpc<size, big_endian>::Scan::global(
case elfcpp::R_PPC64_REL64:
case elfcpp::R_POWERPC_REL32:
// Make a dynamic relocation if necessary.
if (needs_dynamic_reloc<size>(gsym, Scan::get_reference_flags(r_type)))
if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type, target)))
{
if (gsym->may_need_copy_reloc())
{
......@@ -6601,7 +6519,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
bool has_plt_value = false;
unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
if ((gsym != NULL
? use_plt_offset<size>(gsym, Scan::get_reference_flags(r_type))
? gsym->use_plt_offset(Scan::get_reference_flags(r_type, target))
: object->local_has_plt_offset(r_sym))
&& (!psymval->is_ifunc_symbol()
|| Scan::reloc_needs_plt_for_ifunc(object, r_type, false)))
......
......@@ -638,7 +638,10 @@ class Symbol
// A TLS-related reference.
TLS_REF = 4,
// A reference that can always be treated as a function call.
FUNCTION_CALL = 8
FUNCTION_CALL = 8,
// When set, says that dynamic relocations are needed even if a
// symbol has a plt entry.
FUNC_DESC_ABI = 16,
};
// Given a direct absolute or pc-relative static relocation against
......@@ -675,7 +678,8 @@ class Symbol
// A reference to any PLT entry in a non-position-independent executable
// does not need a dynamic relocation.
if (!parameters->options().output_is_position_independent()
if (!(flags & FUNC_DESC_ABI)
&& !parameters->options().output_is_position_independent()
&& this->has_plt_offset())
return false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment