This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

gold patch committed: Fix some linker script issues with -n


While experimenting with linker scripts, I found some issues when
using a linker script which starts at address 0 when using -n.

The first is that emitting the file headers may cause the file to be
misaligned with regard to what the first segment expects.  This is a
problem because the linker script assumes that the segment starts at
address zero, so it's possible for the alignment of the sections to
not match the alignment of the file offsets.  I fixed this by aligning
the file offset in this case.

The second is that gold simply crashes with a gold_unreachable if dot
moves backward when using a linker script.  I fixed this by producing
a more useful error message when using a linker script.

The third is that SHF_TLS/SHT_NOBITS sections do not take up any
address space, but the linker script calculations were not taking that
into account.

Committed.

Ian


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.


Index: layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.140
diff -p -u -r1.140 layout.cc
--- layout.cc	15 Oct 2009 18:17:48 -0000	1.140
+++ layout.cc	16 Oct 2009 04:59:57 -0000
@@ -2237,6 +2237,19 @@ Layout::set_segment_offsets(const Target
 	  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: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.99
diff -p -u -r1.99 output.cc
--- output.cc	14 Oct 2009 05:25:02 -0000	1.99
+++ output.cc	16 Oct 2009 04:59:58 -0000
@@ -3100,36 +3100,41 @@ Output_segment::add_output_section(Outpu
       && (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))
+	  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
 	    {
-	      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;
-	    }
+	      --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_address
 	{
 	  // 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: script-sections.cc
===================================================================
RCS file: /cvs/src/src/gold/script-sections.cc,v
retrieving revision 1.22
diff -p -u -r1.22 script-sections.cc
--- script-sections.cc	9 Oct 2009 23:18:19 -0000	1.22
+++ script-sections.cc	16 Oct 2009 04:59:59 -0000
@@ -1372,6 +1372,7 @@ Output_section_element_input::set_sectio
   // 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_sectio
 	  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_sectio
 						       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_addre
       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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]