On Thu, Jun 23, 2016 at 5:33 AM, Uros Bizjak <ubiz...@gmail.com> wrote: > On Thu, Jun 23, 2016 at 1:45 PM, H.J. Lu <hongjiu...@intel.com> wrote: >> i386 psABI has been updated to clarify that R_386_GOT32X and R_386_GOT32 >> relocations can be used to access GOT without base register when PIC is >> disabled: >> >> https://groups.google.com/forum/#!topic/ia32-abi/awsRSvJOJfs >> >> 32-bit x86 assembler and linker from binutils 2.26.1 and 2.27 support >> >> call/jmp *_start@GOT >> cmpl $0, bar@GOT >> >> for both normal and IFUNC functions. We check if 32-bit x86 assembler >> and linker have the fix for: >> >> https://sourceware.org/bugzilla/show_bug.cgi?id=20244 >> >> before accessing external function via GOT slot for -fno-plt in both PIC >> and non-PIC modes. >> >> Tested on i686 and x86-64. OK for trunk? >> >> >> H.J. >> ---- >> PR target/66232 >> PR target/67400 >> * configure.ac (HAVE_LD_IX86_GOT32X_RELOC): New. Defined to 1 >> if 32-bit assembler and linker support "jmp *_start@GOT" and >> "movl $0, bar@GOT". Otherise, defined to 0. >> * config.in: Regenerated. >> * configure: Likewise. >> * config/i386/i386.c (ix86_force_load_from_GOT_p): Return >> true if HAVE_LD_IX86_GOT32X_RELOC is 1 in 32-bit mode. >> (ix86_legitimate_address_p): Allow UNSPEC_GOT for -fno-plt >> if ix86_force_load_from_GOT_p returns true. >> (ix86_print_operand_address_as): Also support UNSPEC_GOT if >> ix86_force_load_from_GOT_p returns true. >> (ix86_expand_move): Generate UNSPEC_GOT in 32-bit mode to load >> the external function address via the GOT slot. >> (ix86_nopic_noplt_attribute_p): Check HAVE_LD_IX86_GOT32X_RELOC >> == 0 before returning false in 32-bit mode. >> (ix86_output_call_insn): Generate "%!jmp/call\t*%p0@GOT" in >> 32-bit mode if ix86_nopic_noplt_attribute_p returns true. >> >> gcc/testsuite/ >> >> PR target/66232 >> PR target/67400 >> * gcc.target/i386/pr66232-14.c: New file. >> * gcc.target/i386/pr66232-15.c: Likewise. >> * gcc.target/i386/pr66232-16.c: Likewise. >> * gcc.target/i386/pr66232-17.c: Likewise. >> * gcc.target/i386/pr67400-1.c: Don't disable for ia32. Scan for >> ia32 and if R_386_GOT32X relocation is supported. >> * gcc.target/i386/pr67400-2.c: Likewise. >> * gcc.target/i386/pr67400-3.c: Likewise. >> * gcc.target/i386/pr67400-4.c: Likewise. >> * gcc.target/i386/pr67400-6.c: Likewise. >> * gcc.target/i386/pr67400-7.c: Likewise. >> * lib/target-supports.exp (check_effective_target_got32x_reloc): >> New. >> --- >> gcc/config.in | 9 +++++- >> gcc/config/i386/i386.c | 35 ++++++++++++++++---- >> gcc/configure | 50 >> +++++++++++++++++++++++++++++ >> gcc/configure.ac | 42 ++++++++++++++++++++++++ >> gcc/testsuite/gcc.target/i386/pr66232-14.c | 13 ++++++++ >> gcc/testsuite/gcc.target/i386/pr66232-15.c | 14 ++++++++ >> gcc/testsuite/gcc.target/i386/pr66232-16.c | 13 ++++++++ >> gcc/testsuite/gcc.target/i386/pr66232-17.c | 13 ++++++++ >> gcc/testsuite/gcc.target/i386/pr67400-1.c | 8 +++-- >> gcc/testsuite/gcc.target/i386/pr67400-2.c | 8 +++-- >> gcc/testsuite/gcc.target/i386/pr67400-3.c | 3 +- >> gcc/testsuite/gcc.target/i386/pr67400-4.c | 5 +-- >> gcc/testsuite/gcc.target/i386/pr67400-6.c | 8 +++-- >> gcc/testsuite/gcc.target/i386/pr67400-7.c | 6 ++-- >> gcc/testsuite/lib/target-supports.exp | 51 >> ++++++++++++++++++++++++++++++ >> 15 files changed, 256 insertions(+), 22 deletions(-) >> create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-14.c >> create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-15.c >> create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-16.c >> create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-17.c >> >> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c >> index 9c7b015..a2dcf36 100644 >> --- a/gcc/config/i386/i386.c >> +++ b/gcc/config/i386/i386.c >> @@ -15125,7 +15125,8 @@ darwin_local_data_pic (rtx disp) >> bool >> ix86_force_load_from_GOT_p (rtx x) >> { >> - return (TARGET_64BIT && !TARGET_PECOFF && !TARGET_MACHO >> + return ((TARGET_64BIT || HAVE_LD_IX86_GOT32X_RELOC) >> + && !TARGET_PECOFF && !TARGET_MACHO >> && !flag_plt && !flag_pic >> && ix86_cmodel != CM_LARGE >> && GET_CODE (x) == SYMBOL_REF >> @@ -15606,6 +15607,14 @@ ix86_legitimate_address_p (machine_mode, rtx addr, >> bool strict) >> used. While ABI specify also 32bit relocations, we don't >> produce >> them at all and use IP relative instead. */ >> case UNSPEC_GOT: >> + gcc_assert (flag_pic >> + || ix86_force_load_from_GOT_p (XVECEXP (XEXP (disp, >> 0), 0, 0))); >> + if (!TARGET_64BIT) >> + goto is_legitimate_pic; >> + >> + /* 64bit address unspec. */ >> + return false; > > The above should read like: > > case UNSPEC_GOT: > if (!TARGET_64BIT > && ix86_force_load_from_GOT_p (XVECEXP (XEXP (disp, 0), 0, 0))) > goto is_legitimate_pic; > /* FALLTHRU */ > case UNSPEC_GOTOFF: > gcc_assert (flag_pic); > if (!TARGET_64BIT) > goto is_legitimate_pic; > > Please also update the comment above. > >> case UNSPEC_GOTOFF: >> gcc_assert (flag_pic); >> if (!TARGET_64BIT) >> @@ -18194,7 +18203,8 @@ ix86_print_operand_address_as (FILE *file, rtx addr, >> /* Load the external function address via the GOT slot to avoid PLT. >> */ >> else if (GET_CODE (disp) == CONST >> && GET_CODE (XEXP (disp, 0)) == UNSPEC >> - && XINT (XEXP (disp, 0), 1) == UNSPEC_GOTPCREL >> + && (XINT (XEXP (disp, 0), 1) == UNSPEC_GOTPCREL >> + || XINT (XEXP (disp, 0), 1) == UNSPEC_GOT) >> && ix86_force_load_from_GOT_p (XVECEXP (XEXP (disp, 0), 0, >> 0))) >> output_pic_addr_const (file, disp, 0); >> else if (flag_pic) >> @@ -19449,7 +19459,9 @@ ix86_expand_move (machine_mode mode, rtx operands[]) >> { >> /* Load the external function address via GOT slot to avoid PLT. >> */ >> op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op1), >> - UNSPEC_GOTPCREL); >> + (TARGET_64BIT >> + ? UNSPEC_GOTPCREL >> + : UNSPEC_GOT)); >> op1 = gen_rtx_CONST (Pmode, op1); >> op1 = gen_const_mem (Pmode, op1); >> set_mem_alias_set (op1, ix86_GOT_alias_set ()); >> @@ -28027,7 +28039,8 @@ static bool >> ix86_nopic_noplt_attribute_p (rtx call_op) >> { >> if (flag_pic || ix86_cmodel == CM_LARGE >> - || !TARGET_64BIT || TARGET_MACHO || TARGET_SEH || TARGET_PECOFF >> + || (!TARGET_64BIT && HAVE_LD_IX86_GOT32X_RELOC == 0) > > || !(TARGET_64BIT || HAVE_LD_IX86_GOT32X_RELOC) > >> + || TARGET_MACHO || TARGET_SEH || TARGET_PECOFF >> || SYMBOL_REF_LOCAL_P (call_op)) >> return false; >> >> @@ -28055,7 +28068,12 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op) >> if (direct_p) >> { >> if (ix86_nopic_noplt_attribute_p (call_op)) >> - xasm = "%!jmp\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR >> %p0@GOTPCREL[rip]]}"; >> + { >> + if (TARGET_64BIT) >> + xasm = "%!jmp\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR >> %p0@GOTPCREL[rip]]}"; >> + else >> + xasm = "%!jmp\t{*%p0@GOT|[DWORD PTR %p0@GOT]}"; >> + } >> else >> xasm = "%!jmp\t%P0"; >> } >> @@ -28103,7 +28121,12 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op) >> if (direct_p) >> { >> if (ix86_nopic_noplt_attribute_p (call_op)) >> - xasm = "%!call\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR >> %p0@GOTPCREL[rip]]}"; >> + { >> + if (TARGET_64BIT) >> + xasm = "%!call\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR >> %p0@GOTPCREL[rip]]}"; >> + else >> + xasm = "%!call\t{*%p0@GOT|[DWORD PTR %p0@GOT]}"; >> + } >> else >> xasm = "%!call\t%P0"; >> } >> diff --git a/gcc/configure.ac b/gcc/configure.ac >> index fabd48e..2506957 100644 >> --- a/gcc/configure.ac >> +++ b/gcc/configure.ac >> @@ -4200,6 +4200,48 @@ value:' >> [`if test $gcc_cv_as_ix86_tlsldm = yes; then echo 1; else echo 0; >> fi`], >> [Define to 1 if your assembler and linker support @tlsldm.]) >> >> + AC_CACHE_CHECK([linker for R_386_GOT32X relocation], >> + [gcc_cv_ld_ix86_got32x_reloc], >> + [gcc_cv_ld_ix86_got32x_reloc=no >> + if test x$gcc_cv_as != x -a x$gcc_cv_ld != x \ >> + -a x$gcc_cv_objdump != x -a x$gcc_cv_readelf != x; then >> + # Enforce 32-bit output with gas and gld. >> + if test x$gas = xyes; then >> + as_ix86_got32x_opt="--32" >> + fi >> + if echo "$ld_ver" | grep GNU > /dev/null; then >> + if $gcc_cv_ld -V 2>/dev/null | grep elf_i386_sol2 > /dev/null; >> then >> + ld_ix86_got32x_opt="-melf_i386_sol2" >> + else >> + ld_ix86_got32x_opt="-melf_i386" >> + fi >> + fi >> + cat > conftest.s <<EOF >> + .data >> +bar: >> + .byte 1 >> + .text >> + .global _start >> +_start: >> + movl \$0, bar@GOT >> + jmp *_start@GOT >> +EOF >> + if $gcc_cv_as $as_ix86_got32x_opt -o conftest.o conftest.s > >> /dev/null 2>&1 \ >> + && $gcc_cv_readelf --relocs --wide conftest.o 2>&1 \ >> + | grep R_386_GOT32X > /dev/null 2>&1 \ >> + && $gcc_cv_ld $ld_ix86_got32x_opt -o conftest conftest.o > >> /dev/null 2>&1; then >> + if $gcc_cv_objdump -dw conftest 2>&1 \ >> + | grep 0xffffff > /dev/null 2>&1; then >> + gcc_cv_ld_ix86_got32x_reloc=no >> + else >> + gcc_cv_ld_ix86_got32x_reloc=yes >> + fi >> + fi >> + fi >> + rm -f conftest conftest.s conftest.o]) >> + AC_DEFINE_UNQUOTED(HAVE_LD_IX86_GOT32X_RELOC, >> + [`if test x"$gcc_cv_ld_ix86_got32x_reloc" = xyes; then echo 1; else >> echo 0; fi`], >> + [Define 0/1 if Define if your linker supports R_386_GOT32X >> relocation.]) > > THe configure script already determined how to enforce 32bit output > with gas and gld, please rename and reuse as_ix86_tls_ldm_opt and > ld_ix86_tls_ldm_opt from the above check. Then define conftest_s and > call gcc_GAS_CHECK_FEATURE, as is the case with R_386_TLS_LDM reloc > check. > > Also, please name this variable in a similar way, HAVE_AS_IX86_GOT32X. > > Please repost v2 patch. >
Here is the updated patch. OK for trunk? Thanks. -- H.J.
From 10a37b1c3681a5d9432f98541fca76206b798b59 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.to...@gmail.com> Date: Fri, 28 Aug 2015 19:14:49 -0700 Subject: [PATCH] i386: Access external function via GOT slot for -fno-plt i386 psABI has been updated to clarify that R_386_GOT32X and R_386_GOT32 relocations can be used to access GOT without base register when PIC is disabled: https://groups.google.com/forum/#!topic/ia32-abi/awsRSvJOJfs 32-bit x86 assembler and linker from binutils 2.26.1 and 2.27 support call/jmp *_start@GOT cmpl $0, bar@GOT for both normal and IFUNC functions. We check if 32-bit x86 assembler and linker have the fix for: https://sourceware.org/bugzilla/show_bug.cgi?id=20244 before accessing external function via GOT slot for -fno-plt in both PIC and non-PIC modes. PR target/66232 PR target/67400 * configure.ac (as_ix86_tls_ldm_opt): Renamed to ... (as_ix86_gas_opt): This. (ld_ix86_tls_ldm_opt): Renamed to ... (ld_ix86_gld_opt): This. (R_386_TLS_LDM reloc): Updated. (R_386_GOT32X reloc): New assembler/linker check. (HAVE_AS_IX86_GOT32X): New. Defined to 1 if 32-bit assembler and linker support "jmp *_start@GOT" and "cmpl $0, bar@GOT". Otherise, defined to 0. * config.in: Regenerated. * configure: Likewise. * config/i386/i386.c (ix86_force_load_from_GOT_p): Return true if HAVE_AS_IX86_GOT32X is 1 in 32-bit mode. (ix86_legitimate_address_p): Allow UNSPEC_GOT for -fno-plt if ix86_force_load_from_GOT_p returns true. (ix86_print_operand_address_as): Also support UNSPEC_GOT if ix86_force_load_from_GOT_p returns true. (ix86_expand_move): Generate UNSPEC_GOT in 32-bit mode to load the external function address via the GOT slot. (ix86_nopic_noplt_attribute_p): Check both TARGET_64BIT and HAVE_AS_IX86_GOT32X before returning false. (ix86_output_call_insn): Generate "%!jmp/call\t*%p0@GOT" in 32-bit mode if ix86_nopic_noplt_attribute_p returns true. gcc/testsuite/ PR target/66232 PR target/67400 * gcc.target/i386/pr66232-14.c: New file. * gcc.target/i386/pr66232-15.c: Likewise. * gcc.target/i386/pr66232-16.c: Likewise. * gcc.target/i386/pr66232-17.c: Likewise. * gcc.target/i386/pr67400-1.c: Don't disable for ia32. Scan for ia32 if R_386_GOT32X relocation is supported. * gcc.target/i386/pr67400-2.c: Likewise. * gcc.target/i386/pr67400-3.c: Likewise. * gcc.target/i386/pr67400-4.c: Likewise. * gcc.target/i386/pr67400-6.c: Likewise. * gcc.target/i386/pr67400-7.c: Likewise. * lib/target-supports.exp (check_effective_target_got32x_reloc): New. --- gcc/config.in | 9 ++++- gcc/config/i386/i386.c | 51 ++++++++++++++++-------- gcc/configure | 62 +++++++++++++++++++++++++++--- gcc/configure.ac | 39 ++++++++++++++++--- gcc/testsuite/gcc.target/i386/pr66232-14.c | 13 +++++++ gcc/testsuite/gcc.target/i386/pr66232-15.c | 14 +++++++ gcc/testsuite/gcc.target/i386/pr66232-16.c | 13 +++++++ gcc/testsuite/gcc.target/i386/pr66232-17.c | 13 +++++++ gcc/testsuite/gcc.target/i386/pr67400-1.c | 8 ++-- gcc/testsuite/gcc.target/i386/pr67400-2.c | 8 ++-- gcc/testsuite/gcc.target/i386/pr67400-3.c | 3 +- gcc/testsuite/gcc.target/i386/pr67400-4.c | 5 ++- gcc/testsuite/gcc.target/i386/pr67400-6.c | 8 ++-- gcc/testsuite/gcc.target/i386/pr67400-7.c | 6 +-- gcc/testsuite/lib/target-supports.exp | 51 ++++++++++++++++++++++++ 15 files changed, 262 insertions(+), 41 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-14.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-15.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-16.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66232-17.c diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 9c7b015..f7944f9 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -15125,7 +15125,8 @@ darwin_local_data_pic (rtx disp) bool ix86_force_load_from_GOT_p (rtx x) { - return (TARGET_64BIT && !TARGET_PECOFF && !TARGET_MACHO + return ((TARGET_64BIT || HAVE_AS_IX86_GOT32X) + && !TARGET_PECOFF && !TARGET_MACHO && !flag_plt && !flag_pic && ix86_cmodel != CM_LARGE && GET_CODE (x) == SYMBOL_REF @@ -15602,10 +15603,16 @@ ix86_legitimate_address_p (machine_mode, rtx addr, bool strict) && XINT (XEXP (disp, 0), 1) != UNSPEC_MACHOPIC_OFFSET) switch (XINT (XEXP (disp, 0), 1)) { - /* Refuse GOTOFF and GOT in 64bit mode since it is always 64bit when - used. While ABI specify also 32bit relocations, we don't produce - them at all and use IP relative instead. */ + /* Refuse GOTOFF and GOT in 64bit mode since it is always 64bit + when used. While ABI specify also 32bit relocations, we + don't produce them at all and use IP relative instead. + Allow GOT in 32bit mode for both PIC and non-PIC if symbol + should be loaded via GOT. */ case UNSPEC_GOT: + if (!TARGET_64BIT + && ix86_force_load_from_GOT_p (XVECEXP (XEXP (disp, 0), 0, 0))) + goto is_legitimate_pic; + /* FALLTHRU */ case UNSPEC_GOTOFF: gcc_assert (flag_pic); if (!TARGET_64BIT) @@ -18194,7 +18201,8 @@ ix86_print_operand_address_as (FILE *file, rtx addr, /* Load the external function address via the GOT slot to avoid PLT. */ else if (GET_CODE (disp) == CONST && GET_CODE (XEXP (disp, 0)) == UNSPEC - && XINT (XEXP (disp, 0), 1) == UNSPEC_GOTPCREL + && (XINT (XEXP (disp, 0), 1) == UNSPEC_GOTPCREL + || XINT (XEXP (disp, 0), 1) == UNSPEC_GOT) && ix86_force_load_from_GOT_p (XVECEXP (XEXP (disp, 0), 0, 0))) output_pic_addr_const (file, disp, 0); else if (flag_pic) @@ -19449,7 +19457,9 @@ ix86_expand_move (machine_mode mode, rtx operands[]) { /* Load the external function address via GOT slot to avoid PLT. */ op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op1), - UNSPEC_GOTPCREL); + (TARGET_64BIT + ? UNSPEC_GOTPCREL + : UNSPEC_GOT)); op1 = gen_rtx_CONST (Pmode, op1); op1 = gen_const_mem (Pmode, op1); set_mem_alias_set (op1, ix86_GOT_alias_set ()); @@ -28016,18 +28026,19 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, return call; } -/* Return true if the function being called was marked with attribute "noplt" - or using -fno-plt and we are compiling for non-PIC and x86_64. We need to - handle the non-PIC case in the backend because there is no easy interface - for the front-end to force non-PLT calls to use the GOT. This is currently - used only with 64-bit ELF targets to call the function marked "noplt" - indirectly. */ +/* Return true if the function being called was marked with attribute + "noplt" or using -fno-plt and we are compiling for non-PIC. We need + to handle the non-PIC case in the backend because there is no easy + interface for the front-end to force non-PLT calls to use the GOT. + This is currently used only with 64-bit or 32-bit GOT32X ELF targets + to call the function marked "noplt" indirectly. */ static bool ix86_nopic_noplt_attribute_p (rtx call_op) { if (flag_pic || ix86_cmodel == CM_LARGE - || !TARGET_64BIT || TARGET_MACHO || TARGET_SEH || TARGET_PECOFF + || !(TARGET_64BIT || HAVE_AS_IX86_GOT32X) + || TARGET_MACHO || TARGET_SEH || TARGET_PECOFF || SYMBOL_REF_LOCAL_P (call_op)) return false; @@ -28055,7 +28066,12 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op) if (direct_p) { if (ix86_nopic_noplt_attribute_p (call_op)) - xasm = "%!jmp\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}"; + { + if (TARGET_64BIT) + xasm = "%!jmp\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}"; + else + xasm = "%!jmp\t{*%p0@GOT|[DWORD PTR %p0@GOT]}"; + } else xasm = "%!jmp\t%P0"; } @@ -28103,7 +28119,12 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op) if (direct_p) { if (ix86_nopic_noplt_attribute_p (call_op)) - xasm = "%!call\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}"; + { + if (TARGET_64BIT) + xasm = "%!call\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}"; + else + xasm = "%!call\t{*%p0@GOT|[DWORD PTR %p0@GOT]}"; + } else xasm = "%!call\t%P0"; } diff --git a/gcc/configure.ac b/gcc/configure.ac index fabd48e..db3c603 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -4164,13 +4164,13 @@ tls_ld: # Enforce 32-bit output with gas and gld. if test x$gas = xyes; then - as_ix86_tls_ldm_opt="--32" + as_ix86_gas_opt="--32" fi if echo "$ld_ver" | grep GNU > /dev/null; then if $gcc_cv_ld -V 2>/dev/null | grep elf_i386_sol2 > /dev/null; then - ld_ix86_tls_ldm_opt="-melf_i386_sol2" + ld_ix86_gld_opt="-melf_i386_sol2" else - ld_ix86_tls_ldm_opt="-melf_i386" + ld_ix86_gld_opt="-melf_i386" fi fi conftest_s=' @@ -4186,10 +4186,10 @@ _start: value:' gcc_GAS_CHECK_FEATURE([R_386_TLS_LDM reloc], gcc_cv_as_ix86_tlsldm,, - [$as_ix86_tls_ldm_opt], + [$as_ix86_gas_opt], [$conftest_s], [if test x$gcc_cv_ld != x && test x$gcc_cv_objdump != x \ - && $gcc_cv_ld $ld_ix86_tls_ldm_opt -o conftest conftest.o $ld_tls_libs -lc > /dev/null 2>&1; then + && $gcc_cv_ld $ld_ix86_gld_opt -o conftest conftest.o $ld_tls_libs -lc > /dev/null 2>&1; then if $gcc_cv_objdump -d conftest 2>/dev/null | grep nop > /dev/null \ || dis conftest 2>/dev/null | grep nop > /dev/null; then gcc_cv_as_ix86_tlsldm=yes @@ -4200,6 +4200,35 @@ value:' [`if test $gcc_cv_as_ix86_tlsldm = yes; then echo 1; else echo 0; fi`], [Define to 1 if your assembler and linker support @tlsldm.]) + conftest_s=' + .data +bar: + .byte 1 + .text + .global _start +_start: + cmpl $0, bar@GOT + jmp *_start@GOT' + gcc_GAS_CHECK_FEATURE([R_386_GOT32X reloc], + gcc_cv_as_ix86_got32x,, + [$as_ix86_gas_opt], + [$conftest_s], + [if test x$gcc_cv_ld != x && test x$gcc_cv_objdump != x \ + && test x$gcc_cv_readelf != x \ + && $gcc_cv_readelf --relocs --wide conftest.o 2>&1 \ + | grep R_386_GOT32X > /dev/null 2>&1 \ + && $gcc_cv_ld $ld_ix86_gld_opt -o conftest conftest.o > /dev/null 2>&1; then + if $gcc_cv_objdump -dw conftest 2>&1 \ + | grep 0xffffff > /dev/null 2>&1; then + gcc_cv_as_ix86_got32x=no + else + gcc_cv_as_ix86_got32x=yes + fi + fi + rm -f conftest]) + AC_DEFINE_UNQUOTED(HAVE_AS_IX86_GOT32X, + [`if test x"$gcc_cv_as_ix86_got32x" = xyes; then echo 1; else echo 0; fi`], + [Define 0/1 if your assembler and linker support @GOT.]) ;; ia64*-*-*) diff --git a/gcc/testsuite/gcc.target/i386/pr66232-14.c b/gcc/testsuite/gcc.target/i386/pr66232-14.c new file mode 100644 index 0000000..804e5a5 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66232-14.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fno-pic -fno-plt" } */ + +extern void bar (void); + +void +foo (void) +{ + bar (); +} + +/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOT" { target { ia32 && got32x_reloc } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr66232-15.c b/gcc/testsuite/gcc.target/i386/pr66232-15.c new file mode 100644 index 0000000..3d2f6da --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66232-15.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fno-pic -fno-plt" } */ + +extern void bar (void); + +int +foo (void) +{ + bar (); + return 0; +} + +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT" { target { ia32 && got32x_reloc } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr66232-16.c b/gcc/testsuite/gcc.target/i386/pr66232-16.c new file mode 100644 index 0000000..d67f1a5 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66232-16.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fno-pic -fno-plt" } */ + +extern int bar (void); + +int +foo (void) +{ + return bar (); +} + +/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "jmp\[ \t\]*.bar@GOT" { target { ia32 && got32x_reloc } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr66232-17.c b/gcc/testsuite/gcc.target/i386/pr66232-17.c new file mode 100644 index 0000000..bf6f375 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66232-17.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fno-pic -fno-plt" } */ + +extern int bar (void); + +int +foo (void) +{ + return bar () + 1; +} + +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "call\[ \t\]*.bar@GOT" { target { ia32 && got32x_reloc } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr67400-1.c b/gcc/testsuite/gcc.target/i386/pr67400-1.c index 18b3790..8af6650 100644 --- a/gcc/testsuite/gcc.target/i386/pr67400-1.c +++ b/gcc/testsuite/gcc.target/i386/pr67400-1.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */ +/* { dg-do compile { target *-*-linux* } } */ /* { dg-options "-O2 -fno-pic -fno-plt" } */ extern void bar (void); @@ -9,5 +9,7 @@ foo (void) return &bar; } -/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" } } */ -/* { dg-final { scan-assembler-not "\(mov|lea\)\(l|q\)\[ \t\]*\(\\\$|\)bar," } } */ +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */ +/* { dg-final { scan-assembler-not "\(mov|lea\)\(l|q\)\[ \t\]*\(\\\$|\)bar," { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "\(mov|lea\)l\[ \t\]*\(\\\$|\)bar," { target { ia32 && got32x_reloc } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr67400-2.c b/gcc/testsuite/gcc.target/i386/pr67400-2.c index 8f61c3f..23dd4bf 100644 --- a/gcc/testsuite/gcc.target/i386/pr67400-2.c +++ b/gcc/testsuite/gcc.target/i386/pr67400-2.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */ +/* { dg-do compile { target *-*-linux* } } */ /* { dg-options "-O2 -fno-pic -fno-plt" } */ extern void bar (void); @@ -10,5 +10,7 @@ foo (void) p = &bar; } -/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" } } */ -/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," } } */ +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */ +/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ia32 && got32x_reloc } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr67400-3.c b/gcc/testsuite/gcc.target/i386/pr67400-3.c index 40d3521..649c980 100644 --- a/gcc/testsuite/gcc.target/i386/pr67400-3.c +++ b/gcc/testsuite/gcc.target/i386/pr67400-3.c @@ -13,4 +13,5 @@ foo (void) } /* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*\\\$bar," } } */ -/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*bar@GOTPCREL" } } */ +/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr67400-4.c b/gcc/testsuite/gcc.target/i386/pr67400-4.c index a329bbf..5f6883d 100644 --- a/gcc/testsuite/gcc.target/i386/pr67400-4.c +++ b/gcc/testsuite/gcc.target/i386/pr67400-4.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */ +/* { dg-do compile { target *-*-linux* } } */ /* { dg-options "-O2 -fno-pic -fno-plt" } */ extern void bar (void) __attribute__ ((visibility ("hidden"))); @@ -10,4 +10,5 @@ foo (void) } /* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*\\\$bar," } } */ -/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*bar@GOTPCREL" } } */ +/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr67400-6.c b/gcc/testsuite/gcc.target/i386/pr67400-6.c index bb766cd..652add4 100644 --- a/gcc/testsuite/gcc.target/i386/pr67400-6.c +++ b/gcc/testsuite/gcc.target/i386/pr67400-6.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */ +/* { dg-do compile { target *-*-linux* } } */ /* { dg-options "-O2 -fno-pic -fno-plt" } */ extern int bar (void); @@ -9,5 +9,7 @@ check (void *p) return p != &bar; } -/* { dg-final { scan-assembler "cmp\(l|q\)\[ \t\]*.*bar@GOTPCREL" } } */ -/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," } } */ +/* { dg-final { scan-assembler "cmp\(l|q\)\[ \t\]*.*bar@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */ +/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ia32 && got32x_reloc } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr67400-7.c b/gcc/testsuite/gcc.target/i386/pr67400-7.c index 32ae85f..900e87a 100644 --- a/gcc/testsuite/gcc.target/i386/pr67400-7.c +++ b/gcc/testsuite/gcc.target/i386/pr67400-7.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */ +/* { dg-do compile { target *-*-linux* } } */ /* { dg-options "-O2 -fno-pic -fno-plt" } */ extern void bar (void); @@ -9,5 +9,5 @@ foo (void) return &bar+1; } -/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" } } */ -/* { dg-final { scan-assembler-not "\(mov|lea\)\(l|q\)\[ \t\]*\(\\\$|\)bar," } } */ +/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-not "\(mov|lea\)\(l|q\)\[ \t\]*\(\\\$|\)bar," { target { ! ia32 } } } } */ diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 1b1d03a..51042b5 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -6975,6 +6975,57 @@ proc check_effective_target_pie_copyreloc { } { return $pie_copyreloc_available_saved } +# Return 1 if the x86 target supports R_386_GOT32X relocation, 0 +# otherwise. Cache the result. + +proc check_effective_target_got32x_reloc { } { + global got32x_reloc_available_saved + global tool + global GCC_UNDER_TEST + + if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } { + return 0 + } + + # Need auto-host.h to check linker support. + if { ![file exists ../../auto-host.h ] } { + return 0 + } + + if [info exists got32x_reloc_available_saved] { + verbose "check_effective_target_got32x_reloc returning saved $got32x_reloc_available_saved" 2 + } else { + # Include the current process ID in the file names to prevent + # conflicts with invocations for multiple testsuites. + + set src got32x[pid].c + set obj got32x[pid].o + + set f [open $src "w"] + puts $f "#include \"../../auto-host.h\"" + puts $f "#if HAVE_AS_IX86_GOT32X == 0" + puts $f "# error Assembler does not support R_386_GOT32X." + puts $f "#endif" + close $f + + verbose "check_effective_target_got32x_reloc compiling testfile $src" 2 + set lines [${tool}_target_compile $src $obj object ""] + + file delete $src + file delete $obj + + if [string match "" $lines] then { + verbose "check_effective_target_got32x_reloc testfile compilation passed" 2 + set got32x_reloc_available_saved 1 + } else { + verbose "check_effective_target_got32x_reloc testfile compilation failed" 2 + set got32x_reloc_available_saved 0 + } + } + + return $got32x_reloc_available_saved +} + # Return 1 if the target uses comdat groups. proc check_effective_target_comdat_group {} { -- 2.5.5