diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2016-06-18 14:54:09 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2016-06-18 18:44:22 -0700 |
commit | 6614e881c6420aecbf83dff9e5d2ba3495ea9027 (patch) | |
tree | 97ba1e588e32b726d178cf54f96efd86055de9de | |
parent | 49f30d83f659591d7d2b14a18dc8308b3fdb8dd5 (diff) | |
download | binutils-gdb-users/hjl/pr20276.tar.gz |
Set non_ir_ref on common symbolusers/hjl/pr20276
Linker backend sets non_ir_ref during relocation scan. When relocations
are scanned after opening all input files, get_symbols in plugin.c
returns the incorrect symbol resulotion since non_ir_ref isn't set on
common symbols. plugin_notice should set non_ir_ref on common symbols.
Also, we shouldn't check alignment on symbol from plugin dummy input.
bfd/
PR ld/20276
* elflink.c (elf_link_add_object_symbols): Don't check alignment
on symbol from plugin dummy input.
ld/
PR ld/20276
* plugin.c (plugin_notice): Set non_ir_ref on common symbols.
* testsuite/ld-plugin/lto.exp (lto_link_tests): Add test for
PR ld/20276.
(lto_run_tests): Likewise.
* testsuite/ld-plugin/pass.out: New file.
* testsuite/ld-plugin/pr20276a.c: Likewise.
* testsuite/ld-plugin/pr20276b.c: Likewise.
-rw-r--r-- | bfd/elflink.c | 3 | ||||
-rw-r--r-- | ld/plugin.c | 98 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/lto.exp | 12 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/pass.out | 1 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/pr20276a.c | 12 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/pr20276b.c | 1 |
6 files changed, 80 insertions, 47 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c index 6d591de58da..d4e8db67ea5 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -4556,7 +4556,8 @@ error_free_dyn: symbol_align = ffs (h->root.u.def.value) - 1; if (h->root.u.def.section->owner != NULL - && (h->root.u.def.section->owner->flags & DYNAMIC) == 0) + && (h->root.u.def.section->owner->flags + & (DYNAMIC | BFD_PLUGIN)) == 0) { normal_align = h->root.u.def.section->alignment_power; if (normal_align > symbol_align) diff --git a/ld/plugin.c b/ld/plugin.c index cb6131841d6..abb685fb22f 100644 --- a/ld/plugin.c +++ b/ld/plugin.c @@ -1286,59 +1286,65 @@ plugin_notice (struct bfd_link_info *info, h = h->u.i.link; /* Nothing to do here if this def/ref is from an IR dummy BFD. */ - if (is_ir_dummy_bfd (abfd)) - ; - - /* Making an indirect symbol counts as a reference unless this - is a brand new symbol. */ - else if (bfd_is_ind_section (section) - || (flags & BSF_INDIRECT) != 0) + if (!is_ir_dummy_bfd (abfd)) { - /* ??? Some of this is questionable. See comments in - _bfd_generic_link_add_one_symbol for case IND. */ - if (h->type != bfd_link_hash_new) + /* Making an indirect symbol counts as a reference unless this + is a brand new symbol. */ + if (bfd_is_ind_section (section) + || (flags & BSF_INDIRECT) != 0) { - h->non_ir_ref = TRUE; - inh->non_ir_ref = TRUE; + /* ??? Some of this is questionable. See comments in + _bfd_generic_link_add_one_symbol for case IND. */ + if (h->type != bfd_link_hash_new) + { + h->non_ir_ref = TRUE; + inh->non_ir_ref = TRUE; + } + else if (inh->type == bfd_link_hash_new) + inh->non_ir_ref = TRUE; } - else if (inh->type == bfd_link_hash_new) - inh->non_ir_ref = TRUE; - } - /* Nothing to do here for warning symbols. */ - else if ((flags & BSF_WARNING) != 0) - ; + /* Nothing to do here for warning symbols. */ + else if ((flags & BSF_WARNING) != 0) + ; - /* Nothing to do here for constructor symbols. */ - else if ((flags & BSF_CONSTRUCTOR) != 0) - ; + /* Nothing to do here for constructor symbols. */ + else if ((flags & BSF_CONSTRUCTOR) != 0) + ; - /* If this is a ref, set non_ir_ref. */ - else if (bfd_is_und_section (section)) - { - /* Replace the undefined dummy bfd with the real one. */ - if ((h->type == bfd_link_hash_undefined - || h->type == bfd_link_hash_undefweak) - && (h->u.undef.abfd == NULL - || (h->u.undef.abfd->flags & BFD_PLUGIN) != 0)) - h->u.undef.abfd = abfd; - h->non_ir_ref = TRUE; - } + /* If this is a ref, set non_ir_ref. */ + else if (bfd_is_und_section (section)) + { + /* Replace the undefined dummy bfd with the real one. */ + if ((h->type == bfd_link_hash_undefined + || h->type == bfd_link_hash_undefweak) + && (h->u.undef.abfd == NULL + || (h->u.undef.abfd->flags & BFD_PLUGIN) != 0)) + h->u.undef.abfd = abfd; + h->non_ir_ref = TRUE; + } - /* Otherwise, it must be a new def. Ensure any symbol defined - in an IR dummy BFD takes on a new value from a real BFD. - Weak symbols are not normally overridden by a new weak - definition, and strong symbols will normally cause multiple - definition errors. Avoid this by making the symbol appear - to be undefined. */ - else if (((h->type == bfd_link_hash_defweak - || h->type == bfd_link_hash_defined) - && is_ir_dummy_bfd (sym_bfd = h->u.def.section->owner)) - || (h->type == bfd_link_hash_common - && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner))) - { - h->type = bfd_link_hash_undefweak; - h->u.undef.abfd = sym_bfd; + /* Otherwise, it must be a new def. Ensure any symbol defined + in an IR dummy BFD takes on a new value from a real BFD. + Weak symbols are not normally overridden by a new weak + definition, and strong symbols will normally cause multiple + definition errors. Avoid this by making the symbol appear + to be undefined. */ + else if (((h->type == bfd_link_hash_defweak + || h->type == bfd_link_hash_defined) + && is_ir_dummy_bfd (sym_bfd = h->u.def.section->owner)) + || (h->type == bfd_link_hash_common + && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner))) + { + h->type = bfd_link_hash_undefweak; + h->u.undef.abfd = sym_bfd; + } + + /* If this is a common symbol, set non_ir_ref so that we get + the corrrect symbol resulotion when it is overridden by IR + objects. */ + if (bfd_is_com_section (section)) + h->non_ir_ref = TRUE; } } diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp index 7a13abbfdb6..9fa73e19cad 100644 --- a/ld/testsuite/ld-plugin/lto.exp +++ b/ld/testsuite/ld-plugin/lto.exp @@ -183,6 +183,12 @@ set lto_link_tests [list \ [list "PR ld/19317 (1)" \ "$plug_opt" "-flto $lto_no_fat" \ {pr19317.c} {} "libpr19317.a"] \ + [list "Build pr20276a.o" \ + "" "-fno-lto" \ + {pr20276a.c}] \ + [list "Build pr20276b.o" \ + "$plug_opt" "-flto $lto_no_fat" \ + {pr20276b.c}] \ ] if { [at_least_gcc_version 4 7] } { @@ -332,6 +338,12 @@ set lto_run_tests [list \ [list "PR ld/19317 (3)" \ "-O2 -flto tmpdir/pr19317-r.o" "" \ {dummy.c} "pr19317.exe" "pr19317.out" "-flto -O2" "c"] \ + [list "PR ld/20267b" \ + "-O2 -flto tmpdir/pr19317-r.o" "" \ + {dummy.c} "pr19317.exe" "pr19317.out" "-flto -O2" "c"] \ + [list "Run pr20276" \ + "-O2 -flto tmpdir/pr20276a.o tmpdir/pr20267b.o" "" \ + {dummy.c} "pr20267" "pass.out" "-flto -O2" "c"] \ ] if { [at_least_gcc_version 4 7] } { diff --git a/ld/testsuite/ld-plugin/pass.out b/ld/testsuite/ld-plugin/pass.out new file mode 100644 index 00000000000..7ef22e9a431 --- /dev/null +++ b/ld/testsuite/ld-plugin/pass.out @@ -0,0 +1 @@ +PASS diff --git a/ld/testsuite/ld-plugin/pr20276a.c b/ld/testsuite/ld-plugin/pr20276a.c new file mode 100644 index 00000000000..0b37bc7d309 --- /dev/null +++ b/ld/testsuite/ld-plugin/pr20276a.c @@ -0,0 +1,12 @@ +#include <stdio.h> + +int global_var; +extern void abort (); + +int main(void) +{ + if (global_var != 20) + abort (); + printf ("PASS\n"); + return 0; +} diff --git a/ld/testsuite/ld-plugin/pr20276b.c b/ld/testsuite/ld-plugin/pr20276b.c new file mode 100644 index 00000000000..2ecbc2ca908 --- /dev/null +++ b/ld/testsuite/ld-plugin/pr20276b.c @@ -0,0 +1 @@ +int global_var = 20; |