From 661be1e21e12f87f58c14d0ef8caaee770857297 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 16 Oct 2009 05:00:29 +0000 Subject: [PATCH] * layout.cc (Layout::set_segment_offsets): Align the file offset to the segment aligment for -N or -n with no load segment. * output.cc (Output_segment::add_output_section): Don't crash if the first section is a TLS section. (Output_segment::set_section_list_addresses): Print an error message if the address moves backward in a linker script. * script-sections.cc (Output_section_element_input::set_section_addresses): Don't increase *dot_value for a SHF_TLS/SHT_NOBITS section. (Orphan_output_section::set_section_addresses): Likewise. --- gold/ChangeLog | 13 +++++++ gold/layout.cc | 13 +++++++ gold/output.cc | 77 ++++++++++++++++++++++++++--------------- gold/script-sections.cc | 32 ++++++++++++----- 4 files changed, 99 insertions(+), 36 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index b69da9f2a9a..6ebb5e8ba39 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,16 @@ +2009-10-15 Ian Lance Taylor + + * layout.cc (Layout::set_segment_offsets): Align the file offset + to the segment aligment for -N or -n with no load segment. + * output.cc (Output_segment::add_output_section): Don't crash if + the first section is a TLS section. + (Output_segment::set_section_list_addresses): Print an error + message if the address moves backward in a linker script. + * script-sections.cc + (Output_section_element_input::set_section_addresses): Don't + increase *dot_value for a SHF_TLS/SHT_NOBITS section. + (Orphan_output_section::set_section_addresses): Likewise. + 2009-10-15 Doug Kwan * layout.cc (Layout::finish_dynamic_section): Generate tags diff --git a/gold/layout.cc b/gold/layout.cc index ad3ee1b45b4..0b62c18b30e 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -2237,6 +2237,19 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, if (!parameters->options().nmagic() && !parameters->options().omagic()) off = align_file_offset(off, addr, abi_pagesize); + else if (load_seg == NULL) + { + // This is -N or -n with a section script which prevents + // us from using a load segment. We need to ensure that + // the file offset is aligned to the alignment of the + // segment. This is because the linker script + // implicitly assumed a zero offset. If we don't align + // here, then the alignment of the sections in the + // linker script may not match the alignment of the + // sections in the set_section_addresses call below, + // causing an error about dot moving backward. + off = align_address(off, (*p)->maximum_alignment()); + } unsigned int shndx_hold = *pshndx; uint64_t new_addr = (*p)->set_section_addresses(this, false, addr, diff --git a/gold/output.cc b/gold/output.cc index ae7b7b8686f..e2d758520c2 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -3100,36 +3100,41 @@ Output_segment::add_output_section(Output_section* os, && (os->flags() & elfcpp::SHF_TLS) != 0) { pdl = &this->output_data_; - bool nobits = os->type() == elfcpp::SHT_NOBITS; - bool sawtls = false; - Output_segment::Output_data_list::iterator p = pdl->end(); - do + if (!pdl->empty()) { - --p; - bool insert; - if ((*p)->is_section_flag_set(elfcpp::SHF_TLS)) - { - sawtls = true; - // Put a NOBITS section after the first TLS section. - // Put a PROGBITS section after the first TLS/PROGBITS - // section. - insert = nobits || !(*p)->is_section_type(elfcpp::SHT_NOBITS); - } - else + bool nobits = os->type() == elfcpp::SHT_NOBITS; + bool sawtls = false; + Output_segment::Output_data_list::iterator p = pdl->end(); + gold_assert(p != pdl->begin()); + do { - // If we've gone past the TLS sections, but we've seen a - // TLS section, then we need to insert this section now. - insert = sawtls; - } + --p; + bool insert; + if ((*p)->is_section_flag_set(elfcpp::SHF_TLS)) + { + sawtls = true; + // Put a NOBITS section after the first TLS section. + // Put a PROGBITS section after the first + // TLS/PROGBITS section. + insert = nobits || !(*p)->is_section_type(elfcpp::SHT_NOBITS); + } + else + { + // If we've gone past the TLS sections, but we've + // seen a TLS section, then we need to insert this + // section now. + insert = sawtls; + } - if (insert) - { - ++p; - pdl->insert(p, os); - return; + if (insert) + { + ++p; + pdl->insert(p, os); + return; + } } + while (p != pdl->begin()); } - while (p != pdl->begin()); // There are no TLS sections yet; put this one at the requested // location in the section list. @@ -3489,8 +3494,26 @@ Output_segment::set_section_list_addresses(const Layout* layout, bool reset, { // The script may have inserted a skip forward, but it // better not have moved backward. - gold_assert((*p)->address() >= addr + (off - startoff)); - off += (*p)->address() - (addr + (off - startoff)); + if ((*p)->address() >= addr + (off - startoff)) + off += (*p)->address() - (addr + (off - startoff)); + else + { + if (!layout->script_options()->saw_sections_clause()) + gold_unreachable(); + else + { + Output_section* os = (*p)->output_section(); + if (os == NULL) + gold_error(_("dot moves backward in linker script " + "from 0x%llx to 0x%llx"), + addr + (off - startoff), (*p)->address()); + else + gold_error(_("address of section '%s' moves backward " + "from 0x%llx to 0x%llx"), + os->name(), addr + (off - startoff), + (*p)->address()); + } + } (*p)->set_file_offset(off); (*p)->finalize_data_size(); } diff --git a/gold/script-sections.cc b/gold/script-sections.cc index 15d22d68774..7ecf1424dd4 100644 --- a/gold/script-sections.cc +++ b/gold/script-sections.cc @@ -1372,6 +1372,7 @@ Output_section_element_input::set_section_addresses( // sections are otherwise equal. Add each input section to the // output section. + uint64_t dot = *dot_value; for (size_t i = 0; i < input_pattern_count; ++i) { if (matching_sections[i].empty()) @@ -1396,12 +1397,12 @@ Output_section_element_input::set_section_addresses( if (this_subalign < subalign) this_subalign = subalign; - uint64_t address = align_address(*dot_value, this_subalign); + uint64_t address = align_address(dot, this_subalign); - if (address > *dot_value && !fill->empty()) + if (address > dot && !fill->empty()) { section_size_type length = - convert_to_section_size_type(address - *dot_value); + convert_to_section_size_type(address - dot); std::string this_fill = this->get_fill_string(fill, length); Output_section_data* posd = new Output_data_const(this_fill, 0); output_section->add_output_section_data(posd); @@ -1412,10 +1413,17 @@ Output_section_element_input::set_section_addresses( p->size(), this_subalign); - *dot_value = address + p->size(); + dot = address + p->size(); } } + // An SHF_TLS/SHT_NOBITS section does not take up any + // address space. + if (output_section == NULL + || (output_section->flags() & elfcpp::SHF_TLS) == 0 + || output_section->type() != elfcpp::SHT_NOBITS) + *dot_value = dot; + this->final_dot_value_ = *dot_value; this->final_dot_section_ = *dot_section; } @@ -2311,12 +2319,18 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*, address += size; } - if (!have_load_address) - *load_address = address; - else - *load_address += address - *dot_value; + // An SHF_TLS/SHT_NOBITS section does not take up any address space. + if (this->os_ == NULL + || (this->os_->flags() & elfcpp::SHF_TLS) == 0 + || this->os_->type() != elfcpp::SHT_NOBITS) + { + if (!have_load_address) + *load_address = address; + else + *load_address += address - *dot_value; - *dot_value = address; + *dot_value = address; + } } // Get the list of segments to use for an allocated section when using -- 2.30.2