x86: Add ix86_ifunc_ref_local_ok
We can't always use the PLT entry as the function address for local IFUNC functions. When the PIC register is needed for PLT call, indirect call via the PLT entry will fail since the PIC register may not be set up properly for indirect call. Add ix86_ifunc_ref_local_ok to return false when the PLT entry can't be used as local IFUNC function pointers. gcc/ PR target/83782 * config/i386/i386.cc (ix86_ifunc_ref_local_ok): New. (TARGET_IFUNC_REF_LOCAL_OK): Use it. gcc/testsuite/ PR target/83782 * gcc.target/i386/pr83782-1.c: Require non-ia32. * gcc.target/i386/pr83782-2.c: Likewise. * gcc.target/i386/pr83782-3.c: New test.
This commit is contained in:
parent
32566720f3
commit
8092892014
@ -16070,6 +16070,19 @@ ix86_call_use_plt_p (rtx call_op)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Implement TARGET_IFUNC_REF_LOCAL_OK. If this hook returns true,
|
||||||
|
the PLT entry will be used as the function address for local IFUNC
|
||||||
|
functions. When the PIC register is needed for PLT call, indirect
|
||||||
|
call via the PLT entry will fail since the PIC register may not be
|
||||||
|
set up properly for indirect call. In this case, we should return
|
||||||
|
false. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
ix86_ifunc_ref_local_ok (void)
|
||||||
|
{
|
||||||
|
return !flag_pic || (TARGET_64BIT && ix86_cmodel != CM_LARGE_PIC);
|
||||||
|
}
|
||||||
|
|
||||||
/* Return true if the function being called was marked with attribute
|
/* 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
|
"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
|
to handle the non-PIC case in the backend because there is no easy
|
||||||
@ -24953,7 +24966,7 @@ ix86_libgcc_floating_mode_supported_p
|
|||||||
ix86_get_multilib_abi_name
|
ix86_get_multilib_abi_name
|
||||||
|
|
||||||
#undef TARGET_IFUNC_REF_LOCAL_OK
|
#undef TARGET_IFUNC_REF_LOCAL_OK
|
||||||
#define TARGET_IFUNC_REF_LOCAL_OK hook_bool_void_true
|
#define TARGET_IFUNC_REF_LOCAL_OK ix86_ifunc_ref_local_ok
|
||||||
|
|
||||||
#if !TARGET_MACHO && !TARGET_DLLIMPORT_DECL_ATTRIBUTES
|
#if !TARGET_MACHO && !TARGET_DLLIMPORT_DECL_ATTRIBUTES
|
||||||
# undef TARGET_ASM_RELOC_RW_MASK
|
# undef TARGET_ASM_RELOC_RW_MASK
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* { dg-do compile } */
|
/* { dg-do compile { target { ! ia32 } } } */
|
||||||
/* { dg-require-ifunc "" } */
|
/* { dg-require-ifunc "" } */
|
||||||
/* { dg-options "-O2 -fpic" } */
|
/* { dg-options "-O2 -fpic" } */
|
||||||
|
|
||||||
@ -20,7 +20,5 @@ bar(void)
|
|||||||
return foo;
|
return foo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* { dg-final { scan-assembler {leal[ \t]foo@GOTOFF\(%[^,]*\),[ \t]%eax} { target ia32 } } } */
|
/* { dg-final { scan-assembler {lea(?:l|q)[ \t]foo\(%rip\),[ \t]%(?:e|r)ax} } } */
|
||||||
/* { dg-final { scan-assembler {lea(?:l|q)[ \t]foo\(%rip\),[ \t]%(?:e|r)ax} { target { ! ia32 } } } } */
|
/* { dg-final { scan-assembler-not "foo@GOTPCREL\\\(" } } */
|
||||||
/* { dg-final { scan-assembler-not "foo@GOT\\\(" { target ia32 } } } */
|
|
||||||
/* { dg-final { scan-assembler-not "foo@GOTPCREL\\\(" { target { ! ia32 } } } } */
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* { dg-do compile } */
|
/* { dg-do compile { target { ! ia32 } } } */
|
||||||
/* { dg-require-ifunc "" } */
|
/* { dg-require-ifunc "" } */
|
||||||
/* { dg-options "-O2 -fpic" } */
|
/* { dg-options "-O2 -fpic" } */
|
||||||
|
|
||||||
@ -20,7 +20,5 @@ bar(void)
|
|||||||
return foo;
|
return foo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* { dg-final { scan-assembler {leal[ \t]foo@GOTOFF\(%[^,]*\),[ \t]%eax} { target ia32 } } } */
|
|
||||||
/* { dg-final { scan-assembler {lea(?:l|q)[ \t]foo\(%rip\),[ \t]%(?:e|r)ax} { target { ! ia32 } } } } */
|
/* { dg-final { scan-assembler {lea(?:l|q)[ \t]foo\(%rip\),[ \t]%(?:e|r)ax} { target { ! ia32 } } } } */
|
||||||
/* { dg-final { scan-assembler-not "foo@GOT\\\(" { target ia32 } } } */
|
|
||||||
/* { dg-final { scan-assembler-not "foo@GOTPCREL\\\(" { target { ! ia32 } } } } */
|
/* { dg-final { scan-assembler-not "foo@GOTPCREL\\\(" { target { ! ia32 } } } } */
|
||||||
|
32
gcc/testsuite/gcc.target/i386/pr83782-3.c
Normal file
32
gcc/testsuite/gcc.target/i386/pr83782-3.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* { dg-do run } */
|
||||||
|
/* { dg-require-ifunc "" } */
|
||||||
|
/* { dg-require-effective-target pie } */
|
||||||
|
/* { dg-options "-fpie -pie" } */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static int __attribute__((noinline))
|
||||||
|
implementation (void)
|
||||||
|
{
|
||||||
|
printf ("'ere I am JH\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __typeof__ (implementation) *resolver (void)
|
||||||
|
{
|
||||||
|
return (void *)implementation;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int magic (void) __attribute__ ((ifunc ("resolver")));
|
||||||
|
|
||||||
|
__attribute__ ((weak))
|
||||||
|
int
|
||||||
|
call_magic (int (*ptr) (void))
|
||||||
|
{
|
||||||
|
return ptr ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main ()
|
||||||
|
{
|
||||||
|
return call_magic (magic);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user