diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2015-10-28 09:15:17 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2015-10-28 09:15:40 -0700 |
commit | 3043c1aba16b1b5bfdf6813d90ec661988ddfa3f (patch) | |
tree | edd7a887608668e498675ee58023b14917e6f48b /gold/i386.cc | |
parent | a3718e9efd2e0035dc0c008c754309edd8d5ae28 (diff) | |
download | fsf-binutils-gdb-3043c1aba16b1b5bfdf6813d90ec661988ddfa3f.zip fsf-binutils-gdb-3043c1aba16b1b5bfdf6813d90ec661988ddfa3f.tar.gz fsf-binutils-gdb-3043c1aba16b1b5bfdf6813d90ec661988ddfa3f.tar.bz2 |
Check R_386_GOT32/R_386_GOT32X without base register
The R_386_GOT32 and R_386_GOT32X relocations may be used without base
register:
movl bar@GOT, %eax
Its calculation is G + A, instead of G + A - GOT, and it can only used
to generate non-PIC executable. Include the .got.plt section address
for R_386_GOT32 and R_386_GOT32X relocations without base register.
Don't allow R_386_GOT32 and R_386_GOT32X relocations without base
register when making a PIC output.
PR gold/19177
* i386.cc (Target_i386::Relocate::relocate): Check R_386_GOT32
and R_386_GOT32X relocations without base register.
Diffstat (limited to 'gold/i386.cc')
-rw-r--r-- | gold/i386.cc | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/gold/i386.cc b/gold/i386.cc index 36c5724..4c18de0 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -2790,6 +2790,8 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo, } } + bool baseless; + switch (r_type) { case elfcpp::R_386_NONE: @@ -2839,6 +2841,22 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo, case elfcpp::R_386_GOT32: case elfcpp::R_386_GOT32X: + baseless = (view[-1] & 0xc7) == 0x5; + // R_386_GOT32 and R_386_GOT32X don't work without base register + // when generating a position-independent output file. + if (baseless + && parameters->options().output_is_position_independent()) + { + if(gsym) + gold_error_at_location(relinfo, relnum, rel.get_r_offset(), + _("unexpected reloc %u against global symbol %s without base register in object file when generating a position-independent output file"), + r_type, gsym->demangled_name().c_str()); + else + gold_error_at_location(relinfo, relnum, rel.get_r_offset(), + _("unexpected reloc %u against local symbol without base register in object file when generating a position-independent output file"), + r_type); + } + // Convert // mov foo@GOT(%reg), %reg // to @@ -2852,8 +2870,11 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo, { view[-2] = 0x8d; elfcpp::Elf_types<32>::Elf_Addr value; - value = (psymval->value(object, 0) - - target->got_plt_section()->address()); + value = psymval->value(object, 0); + // Don't subtract the .got.plt section address for baseless + // addressing. + if (!baseless) + value -= target->got_plt_section()->address(); Relocate_functions<32, false>::rel32(view, value); } else @@ -2875,6 +2896,9 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo, got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD) - target->got_size()); } + // Add the .got.plt section address for baseless addressing. + if (baseless) + got_offset += target->got_plt_section()->address(); Relocate_functions<32, false>::rel32(view, got_offset); } break; |