2013-04-12 Cary Coutant gold/ * symtab.cc (Symbol_table::sized_write_globals): Subtract section starting address for relocatable link. * testsuite/Makefile.am (script_test_11): New test. * testsuite/Makefile.in: Regenerate. * testsuite/script_test_11.c: New source file. * testsuite/script_test_11.t: New linker script. commit 47b9c2557118fc6e6305cc7b286221811b2669c6 Author: Cary Coutant Date: Fri Apr 12 15:43:16 2013 -0700 Fix problem with -r and dot assignment in scripts. diff --git a/gold/symtab.cc b/gold/symtab.cc index 17a0f55..2e17529 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -2940,15 +2940,24 @@ Symbol_table::sized_write_globals(const Stringpool* sympool, break; case Symbol::IN_OUTPUT_DATA: - shndx = sym->output_data()->out_shndx(); - if (shndx >= elfcpp::SHN_LORESERVE) - { - if (sym_index != -1U) - symtab_xindex->add(sym_index, shndx); - if (dynsym_index != -1U) - dynsym_xindex->add(dynsym_index, shndx); - shndx = elfcpp::SHN_XINDEX; - } + { + Output_data* od = sym->output_data(); + + shndx = od->out_shndx(); + if (shndx >= elfcpp::SHN_LORESERVE) + { + if (sym_index != -1U) + symtab_xindex->add(sym_index, shndx); + if (dynsym_index != -1U) + dynsym_xindex->add(dynsym_index, shndx); + shndx = elfcpp::SHN_XINDEX; + } + + // In object files symbol values are section + // relative. + if (parameters->options().relocatable()) + sym_value -= od->address(); + } break; case Symbol::IN_OUTPUT_SEGMENT: diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index 5b5c86b..3096759 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -2218,6 +2218,17 @@ script_test_10: $(srcdir)/script_test_10.t script_test_10.o gcctestdir/ld script_test_10.stdout: script_test_10 $(TEST_READELF) -SW script_test_10 > $@ +# Test scripts with a relocatable link. +# The -g option is necessary to trigger a bug where a section +# declared in a script file is assigned a non-zero starting address. +check_PROGRAMS += script_test_11 +script_test_11.o: script_test_11.c + $(COMPILE) -c -g -o $@ $< +script_test_11_r.o: $(srcdir)/script_test_11.t script_test_11.o gcctestdir/ld + gcctestdir/ld -r -o $@ -T $(srcdir)/script_test_11.t script_test_11.o +script_test_11: script_test_11_r.o gcctestdir/ld + $(LINK) -Bgcctestdir/ script_test_11_r.o + # These tests work with cross linkers only. if DEFAULT_TARGET_I386 diff --git a/gold/testsuite/script_test_11.c b/gold/testsuite/script_test_11.c new file mode 100644 index 0000000..d932813 --- /dev/null +++ b/gold/testsuite/script_test_11.c @@ -0,0 +1,16 @@ +static unsigned int buffer1[256] __attribute((used)); +static unsigned int buffer2[256] __attribute((used)) = { 1 }; + +unsigned int foo __attribute__((section(".foo"))); +extern char __foo_start; +extern char __foo_end; + +int +main (void) +{ + if (&__foo_end - &__foo_start != sizeof(foo)) + return 1; + if (&__foo_start != (char *)&foo) + return 2; + return 0; +} diff --git a/gold/testsuite/script_test_11.t b/gold/testsuite/script_test_11.t new file mode 100644 index 0000000..0ec6bcd --- /dev/null +++ b/gold/testsuite/script_test_11.t @@ -0,0 +1,8 @@ +SECTIONS +{ + .foo : { + __foo_start = .; + KEEP(*(.foo)) + __foo_end = .; + } +}