do_plt_section_for_local(const Relobj*, unsigned int) const
{ return this->plt_section(); }
- // Adjust -fstack-split code which calls non-stack-split code.
+ // Adjust -fsplit-stack code which calls non-split-stack code.
void
do_calls_non_split(Relobj* object, unsigned int shndx,
section_offset_type fnoffset, section_size_type fnsize,
: issued_non_pic_error_(false)
{ }
+ static inline int
+ get_reference_flags(unsigned int r_type);
+
inline void
local(Symbol_table* symtab, Layout* layout, Target_x86_64* target,
Sized_relobj<64, false>* object,
}
}
+// Get the Reference_flags for a particular relocation.
+
+int
+Target_x86_64::Scan::get_reference_flags(unsigned int r_type)
+{
+ switch (r_type)
+ {
+ case elfcpp::R_X86_64_NONE:
+ case elfcpp::R_X86_64_GNU_VTINHERIT:
+ case elfcpp::R_X86_64_GNU_VTENTRY:
+ case elfcpp::R_X86_64_GOTPC32:
+ case elfcpp::R_X86_64_GOTPC64:
+ // No symbol reference.
+ return 0;
+
+ case elfcpp::R_X86_64_64:
+ case elfcpp::R_X86_64_32:
+ case elfcpp::R_X86_64_32S:
+ case elfcpp::R_X86_64_16:
+ case elfcpp::R_X86_64_8:
+ return Symbol::ABSOLUTE_REF;
+
+ case elfcpp::R_X86_64_PC64:
+ case elfcpp::R_X86_64_PC32:
+ case elfcpp::R_X86_64_PC16:
+ case elfcpp::R_X86_64_PC8:
+ case elfcpp::R_X86_64_GOTOFF64:
+ return Symbol::RELATIVE_REF;
+
+ case elfcpp::R_X86_64_PLT32:
+ case elfcpp::R_X86_64_PLTOFF64:
+ return Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF;
+
+ case elfcpp::R_X86_64_GOT64:
+ case elfcpp::R_X86_64_GOT32:
+ case elfcpp::R_X86_64_GOTPCREL64:
+ case elfcpp::R_X86_64_GOTPCREL:
+ case elfcpp::R_X86_64_GOTPLT64:
+ // Absolute in GOT.
+ return Symbol::ABSOLUTE_REF;
+
+ case elfcpp::R_X86_64_TLSGD: // Global-dynamic
+ case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url)
+ case elfcpp::R_X86_64_TLSDESC_CALL:
+ case elfcpp::R_X86_64_TLSLD: // Local-dynamic
+ case elfcpp::R_X86_64_DTPOFF32:
+ case elfcpp::R_X86_64_DTPOFF64:
+ case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
+ case elfcpp::R_X86_64_TPOFF32: // Local-exec
+ return Symbol::TLS_REF;
+
+ case elfcpp::R_X86_64_COPY:
+ case elfcpp::R_X86_64_GLOB_DAT:
+ case elfcpp::R_X86_64_JUMP_SLOT:
+ case elfcpp::R_X86_64_RELATIVE:
+ case elfcpp::R_X86_64_IRELATIVE:
+ case elfcpp::R_X86_64_TPOFF64:
+ case elfcpp::R_X86_64_DTPMOD64:
+ case elfcpp::R_X86_64_TLSDESC:
+ case elfcpp::R_X86_64_SIZE32:
+ case elfcpp::R_X86_64_SIZE64:
+ default:
+ // Not expected. We will give an error later.
+ return 0;
+ }
+}
+
// Report an unsupported relocation against a local symbol.
void
{
switch (r_type)
{
- // These are the relocation types supported by glibc for x86_64.
+ // These are the relocation types supported by glibc for x86_64
+ // which should always work.
case elfcpp::R_X86_64_RELATIVE:
case elfcpp::R_X86_64_IRELATIVE:
case elfcpp::R_X86_64_GLOB_DAT:
case elfcpp::R_X86_64_DTPOFF64:
case elfcpp::R_X86_64_TPOFF64:
case elfcpp::R_X86_64_64:
+ case elfcpp::R_X86_64_COPY:
+ return;
+
+ // glibc supports these reloc types, but they can overflow.
case elfcpp::R_X86_64_32:
case elfcpp::R_X86_64_PC32:
- case elfcpp::R_X86_64_COPY:
+ if (this->issued_non_pic_error_)
+ return;
+ gold_assert(parameters->options().output_is_position_independent());
+ object->error(_("requires dynamic reloc which may overflow at runtime; "
+ "recompile with -fPIC"));
+ this->issued_non_pic_error_ = true;
return;
default:
Target_x86_64::Scan::reloc_needs_plt_for_ifunc(Sized_relobj<64, false>* object,
unsigned int r_type)
{
- switch (r_type)
- {
- case elfcpp::R_X86_64_NONE:
- case elfcpp::R_X86_64_GNU_VTINHERIT:
- case elfcpp::R_X86_64_GNU_VTENTRY:
- return false;
-
- case elfcpp::R_X86_64_64:
- case elfcpp::R_X86_64_32:
- case elfcpp::R_X86_64_32S:
- case elfcpp::R_X86_64_16:
- case elfcpp::R_X86_64_8:
- case elfcpp::R_X86_64_PC64:
- case elfcpp::R_X86_64_PC32:
- case elfcpp::R_X86_64_PC16:
- case elfcpp::R_X86_64_PC8:
- case elfcpp::R_X86_64_PLT32:
- case elfcpp::R_X86_64_GOTPC32:
- case elfcpp::R_X86_64_GOTOFF64:
- case elfcpp::R_X86_64_GOTPC64:
- case elfcpp::R_X86_64_PLTOFF64:
- case elfcpp::R_X86_64_GOT64:
- case elfcpp::R_X86_64_GOT32:
- case elfcpp::R_X86_64_GOTPCREL64:
- case elfcpp::R_X86_64_GOTPCREL:
- case elfcpp::R_X86_64_GOTPLT64:
- return true;
-
- case elfcpp::R_X86_64_COPY:
- case elfcpp::R_X86_64_GLOB_DAT:
- case elfcpp::R_X86_64_JUMP_SLOT:
- case elfcpp::R_X86_64_RELATIVE:
- case elfcpp::R_X86_64_IRELATIVE:
- case elfcpp::R_X86_64_TPOFF64:
- case elfcpp::R_X86_64_DTPMOD64:
- case elfcpp::R_X86_64_TLSDESC:
- // We will give an error later.
- return false;
-
- case elfcpp::R_X86_64_TLSGD:
- case elfcpp::R_X86_64_GOTPC32_TLSDESC:
- case elfcpp::R_X86_64_TLSDESC_CALL:
- case elfcpp::R_X86_64_TLSLD:
- case elfcpp::R_X86_64_DTPOFF32:
- case elfcpp::R_X86_64_DTPOFF64:
- case elfcpp::R_X86_64_GOTTPOFF:
- case elfcpp::R_X86_64_TPOFF32:
- gold_error(_("%s: unsupported TLS reloc %u for IFUNC symbol"),
- object->name().c_str(), r_type);
- return false;
-
- case elfcpp::R_X86_64_SIZE32:
- case elfcpp::R_X86_64_SIZE64:
- default:
- // We will give an error later.
- return false;
- }
+ int flags = Scan::get_reference_flags(r_type);
+ if (flags & Symbol::TLS_REF)
+ gold_error(_("%s: unsupported TLS reloc %u for IFUNC symbol"),
+ object->name().c_str(), r_type);
+ return flags != 0;
}
// Scan a relocation for a local symbol.
gsym->set_needs_dynsym_value();
}
// Make a dynamic relocation if necessary.
- if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF))
+ if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
{
if (gsym->may_need_copy_reloc())
{
if (gsym->needs_plt_entry())
target->make_plt_entry(symtab, layout, gsym);
// Make a dynamic relocation if necessary.
- int flags = Symbol::NON_PIC_REF;
- if (gsym->is_func())
- flags |= Symbol::FUNCTION_CALL;
- if (gsym->needs_dynamic_reloc(flags))
+ if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
{
if (gsym->may_need_copy_reloc())
{
// Pick the value to use for symbols defined in the PLT.
Symbol_value<64> symval;
if (gsym != NULL
- && gsym->use_plt_offset(r_type == elfcpp::R_X86_64_PC64
- || r_type == elfcpp::R_X86_64_PC32
- || r_type == elfcpp::R_X86_64_PC16
- || r_type == elfcpp::R_X86_64_PC8))
+ && gsym->use_plt_offset(Scan::get_reference_flags(r_type)))
{
symval.set_output_value(target->plt_section()->address()
+ gsym->plt_offset());
}
// FNOFFSET in section SHNDX in OBJECT is the start of a function
-// compiled with -fstack-split. The function calls non-stack-split
+// compiled with -fsplit-stack. The function calls non-split-stack
// code. We have to change the function so that it always ensures
// that it has enough stack space to run some random function.