Delay converting linker script defined symbols from absolute

Giving linker script symbols defined outside of output sections a
section-relative value early, leads to them being used in expressions
as if they were defined inside an output section.  This can mean loss
of the section VMA, and wrong results.

ld/
	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.
ld/testsuite
	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.
This commit is contained in:
Alan Modra 2015-09-18 09:14:25 +09:30
parent b29b8669ad
commit 975f8a9e31
13 changed files with 142 additions and 8 deletions

View File

@ -1,3 +1,16 @@
2015-09-18 Alan Modra <amodra@gmail.com>
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 <nickc@redhat.com>
* po/zh_CN.po: Updated simplified Chinese translation.

View File

@ -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)
{

View File

@ -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

View File

@ -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 ();

View File

@ -1,3 +1,16 @@
2015-09-18 Alan Modra <amodra@gmail.com>
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 <hongjiu.lu@intel.com>
* ld-plugin/lto.exp (lto_link_tests): Add a "ld -r" test for

View File

@ -1,7 +1,7 @@
SECTIONS
{
. = 0x12300000;
PROVIDE_HIDDEN (foo = . + 0x11100000);
PROVIDE_HIDDEN (foo = ABSOLUTE (.) + 0x11100000);
.data : { *(.data) }
.got : { *(.got) }
.interp : { *(.interp) }

View File

@ -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

View File

@ -16,7 +16,7 @@ Disassembly of section \.text:
#...
Disassembly of section \.data:
00060000 <\.data>:
00060000 .*:
60000: 00068000 .*
#...
Disassembly of section \.got:

View File

@ -15,7 +15,7 @@ Disassembly of section \.text:
#...
Disassembly of section \.data:
0000000000060000 <\.data>:
0000000000060000 .*:
60000: 00000000 .*
60004: 00068000 .*
#...

View File

@ -15,7 +15,7 @@ Disassembly of section \.text:
#...
Disassembly of section \.data:
00060000 <\.data>:
00060000 .*:
60000: 00068000 .*
#...
Disassembly of section \.got:

View File

@ -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

View File

@ -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

View File

@ -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");