* layout.cc (Layout::set_segment_offsets): Align the file offset
authorIan Lance Taylor <ian@airs.com>
Fri, 16 Oct 2009 05:00:29 +0000 (05:00 +0000)
committerIan Lance Taylor <ian@airs.com>
Fri, 16 Oct 2009 05:00:29 +0000 (05:00 +0000)
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
gold/layout.cc
gold/output.cc
gold/script-sections.cc

index b69da9f..6ebb5e8 100644 (file)
@@ -1,3 +1,16 @@
+2009-10-15  Ian Lance Taylor  <iant@google.com>
+
+       * 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  <dougkwan@google.com>
 
        * layout.cc (Layout::finish_dynamic_section): Generate tags
index ad3ee1b..0b62c18 100644 (file)
@@ -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,
index ae7b7b8..e2d7585 100644 (file)
@@ -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();
        }
index 15d22d6..7ecf142 100644 (file)
@@ -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