diff options
Diffstat (limited to 'gold/i386.cc')
-rw-r--r-- | gold/i386.cc | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/gold/i386.cc b/gold/i386.cc index 8d3b630..84b9f07 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -1985,9 +1985,24 @@ Target_i386::Scan::global(Symbol_table* symtab, // If this symbol is not fully resolved, we need to add a // GOT entry with a dynamic relocation. Reloc_section* rel_dyn = target->rel_dyn_section(layout); + + // Use a GLOB_DAT rather than a RELATIVE reloc if: + // + // 1) The symbol may be defined in some other module. + // + // 2) We are building a shared library and this is a + // protected symbol; using GLOB_DAT means that the dynamic + // linker can use the address of the PLT in the main + // executable when appropriate so that function address + // comparisons work. + // + // 3) This is a STT_GNU_IFUNC symbol in position dependent + // code, again so that function address comparisons work. if (gsym->is_from_dynobj() || gsym->is_undefined() || gsym->is_preemptible() + || (gsym->visibility() == elfcpp::STV_PROTECTED + && parameters->options().shared()) || (gsym->type() == elfcpp::STT_GNU_IFUNC && parameters->options().output_is_position_independent())) got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, |