diff --git a/ld/ChangeLog b/ld/ChangeLog index 6369d9977d..96359f5a7c 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,16 @@ +2015-09-18 Alan Modra + + PR ld/18963 + * ldexp.h (struct ldexp_control): Add rel_from_abs. + (ldexp_finalize_syms): Declare. + * ldexp.c (new_rel_from_abs): Keep absolute for expressions + outside of output section statements. Set rel_from_abs. + (make_abs, exp_fold_tree, exp_fold_tree_no_dot): Clear rel_from_abs. + (struct definedness_hash_entry): Add final_sec, and comment. + (update_definedness): Set final_sec. + (set_sym_sections, ldexp_finalize_syms): New functions. + * ldlang.c (lang_process): Call ldexp_finalize_syms. + 2015-09-10 Nick Clifton * po/zh_CN.po: Updated simplified Chinese translation. diff --git a/ld/ldexp.c b/ld/ldexp.c index 1140881015..b7b6e6c57c 100644 --- a/ld/ldexp.c +++ b/ld/ldexp.c @@ -49,13 +49,25 @@ segment_type *segments; struct ldexp_control expld; /* This structure records symbols for which we need to keep track of - definedness for use in the DEFINED () test. */ + definedness for use in the DEFINED () test. It is also used in + making absolute symbols section relative late in the link. */ struct definedness_hash_entry { struct bfd_hash_entry root; + + /* If this symbol was assigned from "dot" outside of an output + section statement, the section we'd like it relative to. */ + asection *final_sec; + + /* Symbol was defined by an object file. */ unsigned int by_object : 1; + + /* Symbols was defined by a script. */ unsigned int by_script : 1; + + /* Low bit of iteration count. Symbols with matching iteration have + been defined in this pass over the script. */ unsigned int iteration : 1; }; @@ -174,6 +186,7 @@ make_abs (void) if (expld.result.section != NULL) expld.result.value += expld.result.section->vma; expld.result.section = bfd_abs_section_ptr; + expld.rel_from_abs = FALSE; } static void @@ -249,8 +262,7 @@ new_rel_from_abs (bfd_vma value) { asection *s = expld.section; - if (s == bfd_abs_section_ptr && expld.phase == lang_final_phase_enum) - s = section_for_dot (); + expld.rel_from_abs = TRUE; expld.result.valid_p = TRUE; expld.result.value = value - s->vma; expld.result.str = NULL; @@ -322,6 +334,11 @@ update_definedness (const char *name, struct bfd_link_hash_entry *h) defentry->by_script = 1; defentry->iteration = lang_statement_iteration; + defentry->final_sec = bfd_abs_section_ptr; + if (expld.phase == lang_final_phase_enum + && expld.rel_from_abs + && expld.result.section == bfd_abs_section_ptr) + defentry->final_sec = section_for_dot (); return ret; } @@ -1189,6 +1206,7 @@ exp_fold_tree_1 (etree_type *tree) void exp_fold_tree (etree_type *tree, asection *current_section, bfd_vma *dotp) { + expld.rel_from_abs = FALSE; expld.dot = *dotp; expld.dotp = dotp; expld.section = current_section; @@ -1198,6 +1216,7 @@ exp_fold_tree (etree_type *tree, asection *current_section, bfd_vma *dotp) void exp_fold_tree_no_dot (etree_type *tree) { + expld.rel_from_abs = FALSE; expld.dot = 0; expld.dotp = NULL; expld.section = bfd_abs_section_ptr; @@ -1581,6 +1600,36 @@ ldexp_init (void) einfo (_("%P%F: can not create hash table: %E\n")); } +/* Convert absolute symbols defined by a script from "dot" (also + SEGMENT_START or ORIGIN) outside of an output section statement, + to section relative. */ + +static bfd_boolean +set_sym_sections (struct bfd_hash_entry *bh, void *inf ATTRIBUTE_UNUSED) +{ + struct definedness_hash_entry *def = (struct definedness_hash_entry *) bh; + if (def->final_sec != bfd_abs_section_ptr) + { + struct bfd_link_hash_entry *h; + h = bfd_link_hash_lookup (link_info.hash, bh->string, + FALSE, FALSE, TRUE); + if (h != NULL + && h->type == bfd_link_hash_defined + && h->u.def.section == bfd_abs_section_ptr) + { + h->u.def.value -= def->final_sec->vma; + h->u.def.section = def->final_sec; + } + } + return TRUE; +} + +void +ldexp_finalize_syms (void) +{ + bfd_hash_traverse (&definedness_table, set_sym_sections, NULL); +} + void ldexp_finish (void) { diff --git a/ld/ldexp.h b/ld/ldexp.h index f61df6b459..bea804555b 100644 --- a/ld/ldexp.h +++ b/ld/ldexp.h @@ -138,6 +138,14 @@ struct ldexp_control { /* Principally used for diagnostics. */ bfd_boolean assigning_to_dot; + + /* Set if the current expression used "dot", SEGMENT_START or + ORIGIN, but not ABSOLUTE or combined symbols in a way that forces + an absolute result. Used in tracking symbols assigned from dot + outside of output section statements, in order to later convert + them from absolute. */ + bfd_boolean rel_from_abs; + /* If evaluating an assignment, the destination. Cleared if an etree_name NAME matches this, to signal a self-assignment. Note that an etree_name DEFINED does not clear this field, nor @@ -222,6 +230,7 @@ fill_type *exp_get_fill bfd_vma exp_get_abs_int (etree_type *, int, char *); void ldexp_init (void); +void ldexp_finalize_syms (void); void ldexp_finish (void); #endif diff --git a/ld/ldlang.c b/ld/ldlang.c index 3d2cc99495..29869812ac 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -6882,6 +6882,9 @@ lang_process (void) ldemul_finish (); + /* Convert absolute symbols to section relative. */ + ldexp_finalize_syms (); + /* Make sure that the section addresses make sense. */ if (command_line.check_section_addresses) lang_check_section_addresses (); diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 9629ddaaa5..575d0482c8 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,16 @@ +2015-09-18 Alan Modra + + PR ld/18963 + * ld-scripts/pr18963.d, + * ld-scripts/pr18963.t: New test. + * ld-scripts/expr.exp: Run it. + * ld-elf/provide-hidden-2.ld: Explicitly make "dot" absolute. + * ld-mips-elf/gp-hidden.sd: Don't care about _gp section. + * ld-mips-elf/no-shared-1-n32.d: Don't care about symbol shown at + start of .data section. + * ld-mips-elf/no-shared-1-n64.d: Likewise. + * ld-mips-elf/no-shared-1-o32.d: Likewise. + 2015-09-11 H.J. Lu * ld-plugin/lto.exp (lto_link_tests): Add a "ld -r" test for diff --git a/ld/testsuite/ld-elf/provide-hidden-2.ld b/ld/testsuite/ld-elf/provide-hidden-2.ld index 0b04c49971..17e526bff9 100644 --- a/ld/testsuite/ld-elf/provide-hidden-2.ld +++ b/ld/testsuite/ld-elf/provide-hidden-2.ld @@ -1,7 +1,7 @@ SECTIONS { . = 0x12300000; - PROVIDE_HIDDEN (foo = . + 0x11100000); + PROVIDE_HIDDEN (foo = ABSOLUTE (.) + 0x11100000); .data : { *(.data) } .got : { *(.got) } .interp : { *(.interp) } diff --git a/ld/testsuite/ld-mips-elf/gp-hidden.sd b/ld/testsuite/ld-mips-elf/gp-hidden.sd index 2e9cfbf8f2..620eb9a5da 100644 --- a/ld/testsuite/ld-mips-elf/gp-hidden.sd +++ b/ld/testsuite/ld-mips-elf/gp-hidden.sd @@ -5,5 +5,5 @@ Symbol table '.dynsym' contains [0-9]+ entries: Symbol table '.symtab' contains [0-9]+ entries: * Num: * Value * Size * Type * Bind * Vis * Ndx * Name #... - * [0-9a-f]+: * [0-9a-f]+ * 0 * NOTYPE * LOCAL * DEFAULT * ABS * _gp + * [0-9a-f]+: * [0-9a-f]+ * 0 * NOTYPE * LOCAL * DEFAULT .* _gp #pass diff --git a/ld/testsuite/ld-mips-elf/no-shared-1-n32.d b/ld/testsuite/ld-mips-elf/no-shared-1-n32.d index 04c466ea43..6a55008868 100644 --- a/ld/testsuite/ld-mips-elf/no-shared-1-n32.d +++ b/ld/testsuite/ld-mips-elf/no-shared-1-n32.d @@ -16,7 +16,7 @@ Disassembly of section \.text: #... Disassembly of section \.data: -00060000 <\.data>: +00060000 .*: 60000: 00068000 .* #... Disassembly of section \.got: diff --git a/ld/testsuite/ld-mips-elf/no-shared-1-n64.d b/ld/testsuite/ld-mips-elf/no-shared-1-n64.d index 0c919217f3..5813b30e36 100644 --- a/ld/testsuite/ld-mips-elf/no-shared-1-n64.d +++ b/ld/testsuite/ld-mips-elf/no-shared-1-n64.d @@ -15,7 +15,7 @@ Disassembly of section \.text: #... Disassembly of section \.data: -0000000000060000 <\.data>: +0000000000060000 .*: 60000: 00000000 .* 60004: 00068000 .* #... diff --git a/ld/testsuite/ld-mips-elf/no-shared-1-o32.d b/ld/testsuite/ld-mips-elf/no-shared-1-o32.d index b67737fd26..53bac9ef6c 100644 --- a/ld/testsuite/ld-mips-elf/no-shared-1-o32.d +++ b/ld/testsuite/ld-mips-elf/no-shared-1-o32.d @@ -15,7 +15,7 @@ Disassembly of section \.text: #... Disassembly of section \.data: -00060000 <\.data>: +00060000 .*: 60000: 00068000 .* #... Disassembly of section \.got: diff --git a/ld/testsuite/ld-scripts/expr.exp b/ld/testsuite/ld-scripts/expr.exp index 85242ed5fb..babbf435b7 100644 --- a/ld/testsuite/ld-scripts/expr.exp +++ b/ld/testsuite/ld-scripts/expr.exp @@ -25,3 +25,10 @@ run_dump_test sane1 run_dump_test assign-loc run_dump_test pr14962 run_dump_test pr14962-2 + +set old_ldflags $LDFLAGS +if { [istarget spu*-*-*] } { + set LDFLAGS "$LDFLAGS --no-overlays --local-store 0:0" +} +run_dump_test pr18963 +set LDFLAGS $old_ldflags diff --git a/ld/testsuite/ld-scripts/pr18963.d b/ld/testsuite/ld-scripts/pr18963.d new file mode 100644 index 0000000000..699db594ac --- /dev/null +++ b/ld/testsuite/ld-scripts/pr18963.d @@ -0,0 +1,15 @@ +# source: data.s +# ld: -T pr18963.t +# nm: -B -n + +#... +0+70000 A D +#... +0+70000 A E +#... +0+80000 T A +#... +0+90000 T B +#... +0+a0000 D C +#pass diff --git a/ld/testsuite/ld-scripts/pr18963.t b/ld/testsuite/ld-scripts/pr18963.t new file mode 100644 index 0000000000..b0cd7421eb --- /dev/null +++ b/ld/testsuite/ld-scripts/pr18963.t @@ -0,0 +1,25 @@ +SECTIONS +{ + . = 0x80000; + A = .; + .text : + { + _start = .; + . = 0x10000; + } + B = .; + .data : + { + . = 0x10000; + } + C = .; + .bss : + { + . = 0x10000; + } + D = A - C + B; + E = A + B - C; + /DISCARD/ : {*(*)} +} + +ASSERT(D == E, "Addition is not commutative");