2016-12-11 Cary Coutant <ccoutant@gmail.com>
- * Makefile.in: Regenerate.
+ PR gold/16711
+ * output.cc (Output_section::set_final_data_size): Calculate data size
+ based on relative offset rather than file offset.
+ (Output_segment::set_section_addresses): Track file offset separately
+ from address offset.
+ (Output_segment::set_section_list_addresses): Add pfoff parameter.
+ Track file offset separately. Don't move file offset for BSS
+ sections.
+ * output.h (Output_segment::set_section_list_addresses): Add pfoff
+ parameter.
+ * script-sections.cc (Orphan_section_placement): Add PLACE_LAST_ALLOC.
+ (Orphan_section_placement::Orphan_section_placement): Initialize it.
+ (Orphan_section_placement::output_section_init): Track last allocated
+ section.
+ (Orphan_section_placement::find_place): Place BSS after last allocated
+ section.
+ (Output_section_element_input::set_section_addresses): Always override
+ input section alignment when SUBALIGN is specified.
+ (Output_section_definition::set_section_addresses): Override alignment
+ of output section when SUBALIGN is specified.
+
+ * testsuite/Makefile.am (script_test_15a, script_test_15b)
+ (script_test_15c): New test cases.
+ * testsuite/Makefile.in: Regenerate.
+ * testsuite/script_test_2.cc: Adjust expected layout.
+ * testsuite/script_test_15.c: New source file.
+ * testsuite/script_test_15a.sh: New shell script.
+ * testsuite/script_test_15a.t: New linker script.
+ * testsuite/script_test_15b.sh: New shell script.
+ * testsuite/script_test_15b.t: New linker script.
+ * testsuite/script_test_15c.sh: New shell script.
+ * testsuite/script_test_15c.t: New linker script.
2016-12-08 Alan Modra <amodra@gmail.com>
uint64_t address = this->address();
off_t startoff = this->offset();
- off_t off = startoff + this->first_input_offset_;
+ off_t off = this->first_input_offset_;
for (Input_section_list::iterator p = this->input_sections_.begin();
p != this->input_sections_.end();
++p)
{
off = align_address(off, p->addralign());
- p->set_address_and_file_offset(address + (off - startoff), off,
+ p->set_address_and_file_offset(address + off, startoff + off,
startoff);
off += p->data_size();
}
- data_size = off - startoff;
+ data_size = off;
}
// For full incremental links, we want to allocate some patch space
this->offset_ = orig_off;
off_t off = 0;
+ off_t foff = *poff;
uint64_t ret = 0;
for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
{
if (i == static_cast<int>(ORDER_RELRO_LAST))
{
*poff += last_relro_pad;
+ foff += last_relro_pad;
addr += last_relro_pad;
if (this->output_lists_[i].empty())
{
}
addr = this->set_section_list_addresses(layout, reset,
&this->output_lists_[i],
- addr, poff, pshndx, &in_tls);
- if (i < static_cast<int>(ORDER_SMALL_BSS))
- {
- this->filesz_ = *poff - orig_off;
- off = *poff;
- }
+ addr, poff, &foff, pshndx,
+ &in_tls);
+
+ // FOFF tracks the last offset used for the file image,
+ // and *POFF tracks the last offset used for the memory image.
+ // When not using a linker script, bss sections should all
+ // be processed in the ORDER_SMALL_BSS and later buckets.
+ gold_assert(*poff == foff
+ || i == static_cast<int>(ORDER_TLS_BSS)
+ || i >= static_cast<int>(ORDER_SMALL_BSS)
+ || layout->script_options()->saw_sections_clause());
+
+ this->filesz_ = foff - orig_off;
+ off = foff;
ret = addr;
}
Output_segment::set_section_list_addresses(Layout* layout, bool reset,
Output_data_list* pdl,
uint64_t addr, off_t* poff,
+ off_t* pfoff,
unsigned int* pshndx,
bool* in_tls)
{
off_t maxoff = startoff;
off_t off = startoff;
+ off_t foff = *pfoff;
for (Output_data_list::iterator p = pdl->begin();
p != pdl->end();
++p)
{
+ bool is_bss = (*p)->is_section_type(elfcpp::SHT_NOBITS);
+ bool is_tls = (*p)->is_section_flag_set(elfcpp::SHF_TLS);
+
if (reset)
(*p)->reset_address_and_file_offset();
{
uint64_t align = (*p)->addralign();
- if ((*p)->is_section_flag_set(elfcpp::SHF_TLS))
+ if (is_tls)
{
// Give the first TLS section the alignment of the
// entire TLS segment. Otherwise the TLS segment as a
if (!parameters->incremental_update())
{
+ gold_assert(off == foff || is_bss);
off = align_address(off, align);
- (*p)->set_address_and_file_offset(addr + (off - startoff), off);
+ if (is_tls || !is_bss)
+ foff = off;
+ (*p)->set_address_and_file_offset(addr + (off - startoff), foff);
}
else
{
(*p)->pre_finalize_data_size();
off_t current_size = (*p)->current_data_size();
off = layout->allocate(current_size, align, startoff);
+ foff = off;
if (off == -1)
{
gold_assert((*p)->output_section() != NULL);
"relink with --incremental-full"),
(*p)->output_section()->name());
}
- (*p)->set_address_and_file_offset(addr + (off - startoff), off);
+ (*p)->set_address_and_file_offset(addr + (off - startoff), foff);
if ((*p)->data_size() > current_size)
{
gold_assert((*p)->output_section() != NULL);
// For incremental updates, use the fixed offset for the
// high-water mark computation.
off = (*p)->offset();
+ foff = off;
}
else
{
// The script may have inserted a skip forward, but it
// better not have moved backward.
if ((*p)->address() >= addr + (off - startoff))
- off += (*p)->address() - (addr + (off - startoff));
+ {
+ if (!is_bss && off > foff)
+ gold_warning(_("script places BSS section in the middle "
+ "of a LOAD segment; space will be allocated "
+ "in the file"));
+ off += (*p)->address() - (addr + (off - startoff));
+ if (is_tls || !is_bss)
+ foff = off;
+ }
else
{
if (!layout->script_options()->saw_sections_clause())
os->name(), previous_dot, dot);
}
}
- (*p)->set_file_offset(off);
+ (*p)->set_file_offset(foff);
(*p)->finalize_data_size();
}
// We want to ignore the size of a SHF_TLS SHT_NOBITS
// section. Such a section does not affect the size of a
// PT_LOAD segment.
- if (!(*p)->is_section_flag_set(elfcpp::SHF_TLS)
- || !(*p)->is_section_type(elfcpp::SHT_NOBITS))
+ if (!is_tls || !is_bss)
off += (*p)->data_size();
+ // We don't allocate space in the file for SHT_NOBITS sections,
+ // unless a script has force-placed one in the middle of a segment.
+ if (!is_bss)
+ foff = off;
+
if (off > maxoff)
maxoff = off;
}
*poff = maxoff;
+ *pfoff = foff;
return addr + (maxoff - startoff);
}
// Set the section addresses in an Output_data_list.
uint64_t
set_section_list_addresses(Layout*, bool reset, Output_data_list*,
- uint64_t addr, off_t* poff, unsigned int* pshndx,
- bool* in_tls);
+ uint64_t addr, off_t* poff, off_t* fpoff,
+ unsigned int* pshndx, bool* in_tls);
// Return the number of Output_sections in an Output_data_list.
unsigned int
PLACE_TLS,
PLACE_TLS_BSS,
PLACE_BSS,
+ PLACE_LAST_ALLOC,
PLACE_REL,
PLACE_INTERP,
PLACE_NONALLOC,
this->initialize_place(PLACE_TLS, NULL);
this->initialize_place(PLACE_TLS_BSS, NULL);
this->initialize_place(PLACE_BSS, ".bss");
+ this->initialize_place(PLACE_LAST_ALLOC, NULL);
this->initialize_place(PLACE_REL, NULL);
this->initialize_place(PLACE_INTERP, ".interp");
this->initialize_place(PLACE_NONALLOC, NULL);
bool first_init = this->first_init_;
this->first_init_ = false;
+ // Remember the last allocated section. Any orphan bss sections
+ // will be placed after it.
+ if (os != NULL
+ && (os->flags() & elfcpp::SHF_ALLOC) != 0)
+ {
+ this->places_[PLACE_LAST_ALLOC].location = location;
+ this->places_[PLACE_LAST_ALLOC].have_location = true;
+ }
+
for (int i = 0; i < PLACE_MAX; ++i)
{
if (this->places_[i].name != NULL && this->places_[i].name == name)
follow = PLACE_TEXT;
break;
case PLACE_BSS:
- follow = PLACE_DATA;
+ follow = PLACE_LAST_ALLOC;
break;
case PLACE_REL:
follow = PLACE_TEXT;
p != matching_sections[i].end();
++p)
{
- // Override the original address alignment if SUBALIGN is specified
- // and is greater than the original alignment. We need to make a
- // copy of the input section to modify the alignment.
+ // Override the original address alignment if SUBALIGN is specified.
+ // We need to make a copy of the input section to modify the
+ // alignment.
Output_section::Input_section sis(p->input_section());
uint64_t this_subalign = sis.addralign();
if (!sis.is_input_section())
sis.output_section_data()->finalize_data_size();
uint64_t data_size = sis.data_size();
- if (this_subalign < subalign)
+ if (subalign > 0)
{
this_subalign = subalign;
sis.set_addralign(subalign);
this->output_section_->set_addralign(align);
}
+ uint64_t subalign;
+ if (this->subalign_ == NULL)
+ subalign = 0;
+ else
+ {
+ Output_section* subalign_section;
+ subalign = this->subalign_->eval_with_dot(symtab, layout, true,
+ *dot_value, NULL,
+ &subalign_section, NULL,
+ false);
+ if (subalign_section != NULL)
+ gold_warning(_("subalign of section %s is not absolute"),
+ this->name_.c_str());
+
+ // Reserve a value of 0 to mean there is no SUBALIGN property.
+ if (subalign == 0)
+ subalign = 1;
+
+ // The external alignment of the output section must be at least
+ // as large as that of the input sections. If there is no
+ // explicit ALIGN property, we set the output section alignment
+ // to match the input section alignment.
+ if (align < subalign || this->align_ == NULL)
+ {
+ align = subalign;
+ this->output_section_->set_addralign(align);
+ }
+ }
+
address = align_address(address, align);
uint64_t start_address = address;
this->evaluated_load_address_ = laddr;
- uint64_t subalign;
- if (this->subalign_ == NULL)
- subalign = 0;
- else
- {
- Output_section* subalign_section;
- subalign = this->subalign_->eval_with_dot(symtab, layout, true,
- *dot_value, NULL,
- &subalign_section, NULL,
- false);
- if (subalign_section != NULL)
- gold_warning(_("subalign of section %s is not absolute"),
- this->name_.c_str());
- }
-
std::string fill;
if (this->fill_ != NULL)
{
script_test_14.stdout: script_test_14
$(TEST_OBJDUMP) -s script_test_14 > $@
+# Test BSS section placement at end of segment.
+check_SCRIPTS += script_test_15a.sh
+check_DATA += script_test_15a.stdout
+MOSTLYCLEANFILES += script_test_15a
+script_test_15a: $(srcdir)/script_test_15a.t script_test_15.o gcctestdir/ld
+ gcctestdir/ld -o $@ script_test_15.o -T $(srcdir)/script_test_15a.t
+script_test_15a.stdout: script_test_15a
+ $(TEST_READELF) -lSW script_test_15a > $@
+
+# Test BSS section placement in middle of segment.
+check_SCRIPTS += script_test_15b.sh
+check_DATA += script_test_15b.stdout
+MOSTLYCLEANFILES += script_test_15b
+script_test_15b: $(srcdir)/script_test_15b.t script_test_15.o gcctestdir/ld
+ gcctestdir/ld -o $@ script_test_15.o -T $(srcdir)/script_test_15b.t
+script_test_15b.stdout: script_test_15b
+ $(TEST_READELF) -lSW script_test_15b > $@
+
+# Test orphan BSS section placement.
+check_SCRIPTS += script_test_15c.sh
+check_DATA += script_test_15c.stdout
+MOSTLYCLEANFILES += script_test_15c
+script_test_15c: $(srcdir)/script_test_15c.t script_test_15.o gcctestdir/ld
+ gcctestdir/ld -o $@ script_test_15.o -T $(srcdir)/script_test_15c.t
+script_test_15c.stdout: script_test_15c
+ $(TEST_READELF) -lSW script_test_15c > $@
+
# Test --dynamic-list, --dynamic-list-data, --dynamic-list-cpp-new,
# and --dynamic-list-cpp-typeinfo
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4 script_test_5 \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_6 script_test_7 \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_8 script_test_9 \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_14 dynamic_list \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@ dynamic_list.stdout libthin1.a \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@ libthin3.a libthinall.a \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_14 script_test_15a \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_15b script_test_15c \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ dynamic_list dynamic_list.stdout \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ libthin1.a libthin3.a \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ libthinall.a \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/thin_archive_test_2.o \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/thin_archive_test_4.o \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/libthin2.a alt/libthin4.a
# Test for SORT_BY_INIT_PRIORITY.
+# Test BSS section placement at end of segment.
+
+# Test BSS section placement in middle of segment.
+
+# Test orphan BSS section placement.
+
# Test --dynamic-list, --dynamic-list-data, --dynamic-list-cpp-new,
# and --dynamic-list-cpp-typeinfo
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_42 = \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_8.sh \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_9.sh \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_14.sh \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_15a.sh \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_15b.sh \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_15c.sh \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ dynamic_list.sh
# Create the data files that debug_msg.sh analyzes.
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_8.stdout \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_9.stdout \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_14.stdout \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_15a.stdout \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_15b.stdout \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_15c.stdout \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ dynamic_list.stdout
@GCC_FALSE@initpri1_DEPENDENCIES =
@NATIVE_LINKER_FALSE@initpri1_DEPENDENCIES =
@p='script_test_9.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
script_test_14.sh.log: script_test_14.sh
@p='script_test_14.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+script_test_15a.sh.log: script_test_15a.sh
+ @p='script_test_15a.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+script_test_15b.sh.log: script_test_15b.sh
+ @p='script_test_15b.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+script_test_15c.sh.log: script_test_15c.sh
+ @p='script_test_15c.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
dynamic_list.sh.log: dynamic_list.sh
@p='dynamic_list.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
plugin_test_1.sh.log: plugin_test_1.sh
@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -o $@ script_test_14.o -T $(srcdir)/script_test_14.t
@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_14.stdout: script_test_14
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_OBJDUMP) -s script_test_14 > $@
+@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_15a: $(srcdir)/script_test_15a.t script_test_15.o gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -o $@ script_test_15.o -T $(srcdir)/script_test_15a.t
+@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_15a.stdout: script_test_15a
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -lSW script_test_15a > $@
+@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_15b: $(srcdir)/script_test_15b.t script_test_15.o gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -o $@ script_test_15.o -T $(srcdir)/script_test_15b.t
+@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_15b.stdout: script_test_15b
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -lSW script_test_15b > $@
+@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_15c: $(srcdir)/script_test_15c.t script_test_15.o gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -o $@ script_test_15.o -T $(srcdir)/script_test_15c.t
+@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_15c.stdout: script_test_15c
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -lSW script_test_15c > $@
@GCC_TRUE@@NATIVE_LINKER_TRUE@dynamic_list: basic_test.o gcctestdir/ld $(srcdir)/dynamic_list.t
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_test.o \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ -Wl,--dynamic-list $(srcdir)/dynamic_list.t \
--- /dev/null
+int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+
+int extra[] __attribute__ ((section(".data.extra"))) = { 1, 2, 3, 4 };
+
+int zeroes[1024] = {0};
+
+int main(void)
+{
+ return 0;
+}
--- /dev/null
+#!/bin/sh
+
+# script_test_15a.sh -- test for .bss placement.
+
+# Copyright (C) 2016 Free Software Foundation, Inc.
+# Written by Cary Coutant <ccoutant@gmail.com>.
+
+# This file is part of gold.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+# Check that the .bss section is not allocated in the file image.
+
+check()
+{
+ if ! grep -q "$2" "$1"
+ then
+ echo "Did not find expected section in $1:"
+ echo " $2"
+ echo ""
+ echo "Actual output below:"
+ cat "$1"
+ exit 1
+ fi
+}
+
+check script_test_15a.stdout "LOAD.*0x0000.. 0x0010.. RW"
+check script_test_15a.stdout "01.*\\.data .*\\.data.extra .*\\.bss"
--- /dev/null
+/* script_test_15a.t -- linker script test 15a for gold
+
+ Copyright (C) 2016 Free Software Foundation, Inc.
+ Written by Cary Coutant <ccoutant@google.com>.
+
+ This file is part of gold.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* We won't try to run this program, just ensure that it links
+ as expected. */
+
+SECTIONS
+{
+ /* With luck this will be enough to get the program working. */
+ .interp : { *(.interp) }
+ .text : { *(.text .text.*) }
+ .rodata : { *(.rodata .rodata.*) }
+ /* Required by the ARM target. */
+ .ARM.extab : { *(.ARM.extab*) }
+ .ARM.exidx : { *(.ARM.exidx*) }
+ . = ALIGN(0x10000);
+ .dynamic : { *(.dynamic) }
+ .data : { *(.data) }
+ .got : { *(.got .toc) }
+ .bss : { *(.bss) }
+}
--- /dev/null
+#!/bin/sh
+
+# script_test_15b.sh -- test for .bss placement.
+
+# Copyright (C) 2016 Free Software Foundation, Inc.
+# Written by Cary Coutant <ccoutant@gmail.com>.
+
+# This file is part of gold.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+# Check that a .bss section placed in the middle of a segment
+# is allocated in the file image.
+
+check()
+{
+ if ! grep -q "$2" "$1"
+ then
+ echo "Did not find expected section in $1:"
+ echo " $2"
+ echo ""
+ echo "Actual output below:"
+ cat "$1"
+ exit 1
+ fi
+}
+
+check script_test_15b.stdout "LOAD.*0x0010.. 0x0010.. RW"
+check script_test_15b.stdout "01.*\\.bss .*\\.data .*\\.data.extra"
--- /dev/null
+/* script_test_15b.t -- linker script test 15b for gold
+
+ Copyright (C) 2016 Free Software Foundation, Inc.
+ Written by Cary Coutant <ccoutant@google.com>.
+
+ This file is part of gold.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* Test that a .bss section explicitly placed in the middle of a
+ segment has allocated file space. */
+
+/* We won't try to run this program, just ensure that it links
+ as expected. */
+
+PHDRS
+{
+ text PT_LOAD FLAGS(5);
+ data PT_LOAD FLAGS(6);
+}
+
+SECTIONS
+{
+ /* With luck this will be enough to get the program working. */
+ .interp : { *(.interp) } :text
+ .text : { *(.text .text.*) }
+ .rodata : { *(.rodata .rodata.*) }
+ /* Required by the ARM target. */
+ .ARM.extab : { *(.ARM.extab*) }
+ .ARM.exidx : { *(.ARM.exidx*) }
+ . = ALIGN(0x10000);
+ .dynamic : { *(.dynamic) }
+ .bss : { *(.bss) } :data
+ .data : { *(.data) }
+ .got : { *(.got .toc) }
+}
--- /dev/null
+#!/bin/sh
+
+# script_test_15c.sh -- test for .bss placement.
+
+# Copyright (C) 2016 Free Software Foundation, Inc.
+# Written by Cary Coutant <ccoutant@gmail.com>.
+
+# This file is part of gold.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+# Check that an orphan .bss section is placed at the end of a segment
+# and is not allocated in the file image.
+
+check()
+{
+ if ! grep -q "$2" "$1"
+ then
+ echo "Did not find expected section in $1:"
+ echo " $2"
+ echo ""
+ echo "Actual output below:"
+ cat "$1"
+ exit 1
+ fi
+}
+
+check script_test_15c.stdout "LOAD.*0x0000.. 0x0010.. RW"
+check script_test_15c.stdout "01.*\\.data .*\\.data.extra .*\\.bss"
--- /dev/null
+/* script_test_15c.t -- linker script test 15c for gold
+
+ Copyright (C) 2016 Free Software Foundation, Inc.
+ Written by Cary Coutant <ccoutant@google.com>.
+
+ This file is part of gold.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* Test that an orphan .bss section is placed at the end of the segment. */
+
+/* We won't try to run this program, just ensure that it links
+ as expected. */
+
+SECTIONS
+{
+ /* With luck this will be enough to get the program working. */
+ .interp : { *(.interp) }
+ .text : { *(.text .text.*) }
+ .rodata : { *(.rodata .rodata.*) }
+ /* Required by the ARM target. */
+ .ARM.extab : { *(.ARM.extab*) }
+ .ARM.exidx : { *(.ARM.exidx*) }
+ . = ALIGN(0x10000);
+ .dynamic : { *(.dynamic) }
+ .data : { *(.data) }
+ .got : { *(.got .toc) }
+}
main(int, char**)
{
assert(reinterpret_cast<uintptr_t>(start_test_area) == 0x20000001);
- assert(reinterpret_cast<uintptr_t>(start_test_area_1) == 0x20000010);
+ assert(reinterpret_cast<uintptr_t>(start_test_area_1) == 0x20000020);
- // We should see the string from script_test_2b.o next. The
- // subalign should move it up to 0x20000020.
- for (int i = 0; i < 16; ++i)
- assert(start_test_area_1[i] == 0);
- assert(strcmp(start_test_area_1 + 16, "test bb") == 0);
+ assert(strcmp(start_test_area_1, "test bb") == 0);
// Next the string from script_test_2a.o, after the subalign.
- for (int i = 16 + 7; i < 48; ++i)
+ for (int i = 7; i < 32; ++i)
assert(start_test_area_1[i] == 0);
- assert(strcmp(start_test_area_1 + 48, "test aa") == 0);
+ assert(strcmp(start_test_area_1 + 32, "test aa") == 0);
- // Move four bytes forward to start_data.
- assert(reinterpret_cast<uintptr_t>(start_test_area_1 + 48 + 8 + 4)
+ // Skip to start_data at relative offset 60.
+ for (int i = 32 + 7; i < 60; ++i)
+ assert(start_test_area_1[i] == 0);
+ assert(reinterpret_cast<uintptr_t>(start_test_area_1 + 60)
== reinterpret_cast<uintptr_t>(start_data));
assert(memcmp(start_data, "\1\2\0\4\0\0\0\010\0\0\0\0\0\0\0", 15) == 0
|| memcmp(start_data, "\1\0\2\0\0\0\4\0\0\0\0\0\0\0\010", 15) == 0);