X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gold%2Fx86_64.cc;h=5ba15c45d0e2512e37674fd565321bce04c81842;hb=29b2c556d2655b11483d07468d1eaf2dff1395ce;hp=4853603fdb96e414789c9e2937e71eb0ae0a3381;hpb=c95e9f279130c09af2c427065700e3e08500b168;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/x86_64.cc b/gold/x86_64.cc index 4853603fdb..5ba15c45d0 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -309,7 +309,7 @@ class Target_x86_64 : public Target_freebsd<64, false> 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, @@ -362,6 +362,9 @@ class Target_x86_64 : public Target_freebsd<64, false> : 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, @@ -1236,6 +1239,73 @@ Target_x86_64::optimize_tls_reloc(bool is_final, int r_type) } } +// 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 @@ -1259,7 +1329,8 @@ Target_x86_64::Scan::check_non_pic(Relobj* object, unsigned int r_type) { 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: @@ -1268,9 +1339,18 @@ Target_x86_64::Scan::check_non_pic(Relobj* object, unsigned int r_type) 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: @@ -1297,63 +1377,11 @@ bool 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. @@ -1779,7 +1807,7 @@ Target_x86_64::Scan::global(Symbol_table* symtab, 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()) { @@ -1836,10 +1864,7 @@ Target_x86_64::Scan::global(Symbol_table* symtab, 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()) { @@ -2242,10 +2267,7 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo, // 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()); @@ -3226,7 +3248,7 @@ Target_x86_64::do_reloc_addend(void* arg, unsigned int r_type, } // 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.