mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-28 04:25:10 +08:00
Mark the plugin symbol undefined
LTO may optimize out a plugin symbol, which is also referenced by a non-IR file. When that happens, we should mark the plugin symbol undefined. It isn't the problem since LTO already determined the symbols in the non-IR file aren't used. bfd/ PR ld/12365 PR ld/14272 * elflink.c (_bfd_elf_fix_symbol_flags): Mark the plugin symbol undefined if it is referenced from a non-IR file. ld/testsuite/ PR ld/12365 * ld-plugin/pr12365a.c: New file. * ld-plugin/pr12365b.c: Likewise. * ld-plugin/pr12365c.c: Likewise. * ld-plugin/lto.exp (lto_link_tests): Prepare for the PR ld/12365 test. Run the PR ld/12365 test.
This commit is contained in:
parent
9910b1c8f3
commit
60f7927512
@ -1,3 +1,10 @@
|
||||
2015-02-03 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/12365
|
||||
PR ld/14272
|
||||
* elflink.c (_bfd_elf_fix_symbol_flags): Mark the plugin symbol
|
||||
undefined if it is referenced from a non-IR file.
|
||||
|
||||
2015-02-03 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR binutils/17512
|
||||
|
@ -2423,6 +2423,20 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If a plugin symbol is referenced from a non-IR file, mark
|
||||
the symbol as undefined, except for symbol for linker
|
||||
created section. */
|
||||
if (h->root.non_ir_ref
|
||||
&& (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
&& (h->root.u.def.section->flags & SEC_LINKER_CREATED) == 0
|
||||
&& h->root.u.def.section->owner != NULL
|
||||
&& (h->root.u.def.section->owner->flags & BFD_PLUGIN) != 0)
|
||||
{
|
||||
h->root.type = bfd_link_hash_undefined;
|
||||
h->root.u.undef.abfd = h->root.u.def.section->owner;
|
||||
}
|
||||
|
||||
/* Unfortunately, NON_ELF is only correct if the symbol
|
||||
was first seen in a non-ELF file. Fortunately, if the symbol
|
||||
was first seen in an ELF file, we're probably OK unless the
|
||||
|
@ -1,3 +1,14 @@
|
||||
2015-02-03 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/12365
|
||||
* ld-plugin/pr12365a.c: New file.
|
||||
* ld-plugin/pr12365b.c: Likewise.
|
||||
* ld-plugin/pr12365c.c: Likewise.
|
||||
|
||||
* ld-plugin/lto.exp (lto_link_tests): Prepare for the PR ld/12365
|
||||
test.
|
||||
Run the PR ld/12365 test.
|
||||
|
||||
2015-02-03 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/14918
|
||||
|
@ -88,6 +88,9 @@ set lto_link_tests [list \
|
||||
[list "LTO 6" \
|
||||
"-O2 -flto -fuse-linker-plugin" "" \
|
||||
{lto-6.c} {} "lto-6.exe" "c"] \
|
||||
[list "Compile PR ld/12365" \
|
||||
"" "-flto -O2 $lto_fat" \
|
||||
{pr12365a.c pr12365b.c pr12365c.c} {} ""] \
|
||||
[list "Compile 9" \
|
||||
"" "-O2 -finline -flto" \
|
||||
{lto-9.cc} {} "" "c++"] \
|
||||
@ -380,6 +383,13 @@ if {![string match "" $catch_output]} {
|
||||
|
||||
if { [at_least_gcc_version 4 7] } {
|
||||
# Check expected LTO linker errors.
|
||||
set testname "PR ld/12365"
|
||||
set exec_output [run_host_cmd "$CC" "-O2 -flto -fuse-linker-plugin tmpdir/pr12365a.o tmpdir/pr12365b.o tmpdir/pr12365c.o"]
|
||||
if { [ regexp "undefined reference to `my_bcopy'" $exec_output ] } {
|
||||
pass $testname
|
||||
} {
|
||||
fail $testname
|
||||
}
|
||||
set testname "PR ld/12942 (3)"
|
||||
set exec_output [run_host_cmd "$CXX" "-O2 -flto -fuse-linker-plugin tmpdir/pr12942b.o tmpdir/pr12942a.o"]
|
||||
if { [ regexp "undefined reference to `link_error\\(\\)'" $exec_output ] } {
|
||||
|
25
ld/testsuite/ld-plugin/pr12365a.c
Normal file
25
ld/testsuite/ld-plugin/pr12365a.c
Normal file
@ -0,0 +1,25 @@
|
||||
extern void abort(void);
|
||||
extern void main_test (void);
|
||||
extern void abort (void);
|
||||
int inside_main;
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
inside_main = 1;
|
||||
main_test ();
|
||||
inside_main = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* When optimizing, all the constant cases should have been
|
||||
constant folded, so no calls to link_error should remain.
|
||||
In any case, link_error should not be called. */
|
||||
|
||||
#ifndef __OPTIMIZE__
|
||||
void
|
||||
link_error (void)
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
#endif
|
47
ld/testsuite/ld-plugin/pr12365b.c
Normal file
47
ld/testsuite/ld-plugin/pr12365b.c
Normal file
@ -0,0 +1,47 @@
|
||||
#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname)
|
||||
#define ASMNAME2(prefix, cname) STRING (prefix) cname
|
||||
#define STRING(x) #x
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
extern void abort (void);
|
||||
extern void *memcpy (void *, const void *, size_t)
|
||||
__asm (ASMNAME ("my_memcpy"));
|
||||
extern void bcopy (const void *, void *, size_t)
|
||||
__asm (ASMNAME ("my_bcopy"));
|
||||
extern void *memset (void *, int, size_t)
|
||||
__asm (ASMNAME ("my_memset"));
|
||||
extern void bzero (void *, size_t)
|
||||
__asm (ASMNAME ("my_bzero"));
|
||||
extern int memcmp (const void *, const void *, size_t);
|
||||
|
||||
struct A { char c[32]; } a = { "foobar" };
|
||||
char x[64] = "foobar", y[64];
|
||||
int i = 39, j = 6, k = 4;
|
||||
|
||||
extern int inside_main;
|
||||
|
||||
void
|
||||
main_test (void)
|
||||
{
|
||||
struct A b = a;
|
||||
struct A c = { { 'x' } };
|
||||
|
||||
inside_main = 1;
|
||||
|
||||
if (memcmp (b.c, x, 32) || c.c[0] != 'x' || memcmp (c.c + 1, x + 32, 31))
|
||||
abort ();
|
||||
if (__builtin_memcpy (y, x, i) != y || memcmp (x, y, 64))
|
||||
abort ();
|
||||
if (memcpy (y + 6, x, j) != y + 6
|
||||
|| memcmp (x, y, 6) || memcmp (x, y + 6, 58))
|
||||
abort ();
|
||||
if (__builtin_memset (y + 2, 'X', k) != y + 2
|
||||
|| memcmp (y, "foXXXXfoobar", 13))
|
||||
abort ();
|
||||
bcopy (y + 1, y + 2, 6);
|
||||
if (memcmp (y, "fooXXXXfobar", 13))
|
||||
abort ();
|
||||
__builtin_bzero (y + 4, 2);
|
||||
if (memcmp (y, "fooX\0\0Xfobar", 13))
|
||||
abort ();
|
||||
}
|
79
ld/testsuite/ld-plugin/pr12365c.c
Normal file
79
ld/testsuite/ld-plugin/pr12365c.c
Normal file
@ -0,0 +1,79 @@
|
||||
extern void abort (void);
|
||||
extern int inside_main;
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
#define TEST_ABORT if (inside_main) abort()
|
||||
|
||||
void *
|
||||
my_memcpy (void *d, const void *s, size_t n)
|
||||
{
|
||||
char *dst = (char *) d;
|
||||
const char *src = (const char *) s;
|
||||
while (n--)
|
||||
*dst++ = *src++;
|
||||
return (char *) d;
|
||||
}
|
||||
|
||||
void
|
||||
my_bcopy (const void *s, void *d, size_t n)
|
||||
{
|
||||
char *dst = (char *) d;
|
||||
const char *src = (const char *) s;
|
||||
if (src >= dst)
|
||||
while (n--)
|
||||
*dst++ = *src++;
|
||||
else
|
||||
{
|
||||
dst += n;
|
||||
src += n;
|
||||
while (n--)
|
||||
*--dst = *--src;
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
my_memset (void *d, int c, size_t n)
|
||||
{
|
||||
char *dst = (char *) d;
|
||||
while (n--)
|
||||
*dst++ = c;
|
||||
return (char *) d;
|
||||
}
|
||||
|
||||
void
|
||||
my_bzero (void *d, size_t n)
|
||||
{
|
||||
char *dst = (char *) d;
|
||||
while (n--)
|
||||
*dst++ = '\0';
|
||||
}
|
||||
|
||||
void *
|
||||
memcpy (void *d, const void *s, size_t n)
|
||||
{
|
||||
void *result = my_memcpy (d, s, n);
|
||||
TEST_ABORT;
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
bcopy (const void *s, void *d, size_t n)
|
||||
{
|
||||
my_bcopy (s, d, n);
|
||||
TEST_ABORT;
|
||||
}
|
||||
|
||||
void *
|
||||
memset (void *d, int c, size_t n)
|
||||
{
|
||||
void *result = my_memset (d, c, n);
|
||||
TEST_ABORT;
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
bzero (void *d, size_t n)
|
||||
{
|
||||
my_bzero (d, n);
|
||||
TEST_ABORT;
|
||||
}
|
Loading…
Reference in New Issue
Block a user