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 start address of RELRO segment


PR 11866 is about a bug revealed by stripping a shared library linked by
gold with -z relro.  When I looked into this, I found a problem in that
the start address of the RELRO segment might be incorrect, because the
list of sections attached to the segment is not necessarily in address
order.  I committed this patch to fix the problem.  I not sure whether
or not this is the same problem as seen by the reporter of PR 11866, as
the symptoms are different.

Ian


2010-08-02  Ian Lance Taylor  <iant@google.com>

	PR 11866
	* output.cc (Output_segment::set_offset): Search for the first and
	last sections rather than assuming that the list is in order.
	(Output_segment::find_first_and_last_list): New function.
	* output.h (class Output_segment): Update declarations.
	* testsuite/Makefile.am (check_PROGRAMS): Add relro_strip_test.
	(relro_strip_test_SOURCES): New variable.
	(relro_strip_test_DEPENDENCIES): New variable.
	(relro_strip_test_LDFLAGS): New variable.
	(relro_strip_test_LDADD): New variable.
	(relro_strip_test.so): New target.


Index: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.130
diff -p -u -r1.130 output.cc
--- output.cc	13 Jul 2010 20:07:08 -0000	1.130
+++ output.cc	2 Aug 2010 11:56:26 -0000
@@ -4042,11 +4042,14 @@ Output_segment::set_offset(unsigned int 
       return;
     }
 
-  const Output_data* first;
-  if (this->output_data_.empty())
-    first = this->output_bss_.front();
-  else
-    first = this->output_data_.front();
+  // Find the first and last section by address.  The sections may
+  // have been sorted for the PT_LOAD segment.
+  const Output_data* first = NULL;
+  const Output_data* last_data = NULL;
+  const Output_data* last_bss = NULL;
+  this->find_first_and_last_list(&this->output_data_, &first, &last_data);
+  this->find_first_and_last_list(&this->output_bss_, &first, &last_bss);
+
   this->vaddr_ = first->address();
   this->paddr_ = (first->has_load_address()
 		  ? first->load_address()
@@ -4057,18 +4060,11 @@ Output_segment::set_offset(unsigned int 
   if (this->output_data_.empty())
     this->filesz_ = 0;
   else
-    {
-      const Output_data* last_data = this->output_data_.back();
-      this->filesz_ = (last_data->address()
-		       + last_data->data_size()
-		       - this->vaddr_);
-    }
+    this->filesz_ = (last_data->address()
+		     + last_data->data_size()
+		     - this->vaddr_);
 
-  const Output_data* last;
-  if (this->output_bss_.empty())
-    last = this->output_data_.back();
-  else
-    last = this->output_bss_.back();
+  const Output_data* last = last_bss != NULL ? last_bss : last_data;
   this->memsz_ = (last->address()
 		  + last->data_size()
 		  - this->vaddr_);
@@ -4087,6 +4083,37 @@ Output_segment::set_offset(unsigned int 
     }
 }
 
+// Look through a list of Output_data objects and find the first and
+// last by address.
+
+void
+Output_segment::find_first_and_last_list(const Output_data_list* pdl,
+					 const Output_data** pfirst,
+					 const Output_data** plast) const
+{
+  const Output_data* first = *pfirst;
+  const Output_data* last = *plast;
+  for (Output_data_list::const_iterator p = pdl->begin(); p != pdl->end(); ++p)
+    {
+      if (first == NULL
+	  || (*p)->address() < first->address()
+	  || ((*p)->address() == first->address()
+	      && (*p)->data_size() < first->data_size()))
+	{
+	  first = *p;
+	  *pfirst = first;
+	}
+      if (last == NULL
+	  || (*p)->address() > last->address()
+	  || ((*p)->address() == last->address()
+	      && (*p)->data_size() > last->data_size()))
+	{
+	  last = *p;
+	  *plast = last;
+	}
+    }
+}
+
 // Set the TLS offsets of the sections in the PT_TLS segment.
 
 void
Index: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.109
diff -p -u -r1.109 output.h
--- output.h	13 Jul 2010 20:07:08 -0000	1.109
+++ output.h	2 Aug 2010 11:56:26 -0000
@@ -4023,6 +4023,12 @@ class Output_segment
 			      Output_section** found,
 			      uint64_t* found_lma) const;
 
+  // Find the first and last entries by address.
+  void
+  find_first_and_last_list(const Output_data_list* pdl,
+			   const Output_data** pfirst,
+			   const Output_data** plast) const;
+
   // Write the section headers in the list into V.
   template<int size, bool big_endian>
   unsigned char*
Index: testsuite/Makefile.am
===================================================================
RCS file: /cvs/src/src/gold/testsuite/Makefile.am,v
retrieving revision 1.138
diff -p -u -r1.138 Makefile.am
--- testsuite/Makefile.am	29 Jul 2010 18:57:28 -0000	1.138
+++ testsuite/Makefile.am	2 Aug 2010 11:56:26 -0000
@@ -1078,6 +1078,14 @@ relro_test.so: gcctestdir/ld relro_test_
 relro_test_pic.o: relro_test.cc
 	$(CXXCOMPILE) -c -fpic -o $@ $<
 
+check_PROGRAMS += relro_strip_test
+relro_strip_test_SOURCES = relro_test_main.cc
+relro_strip_test_DEPENDENCIES = gcctestdir/ld relro_strip_test.so
+relro_strip_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,.
+relro_strip_test_LDADD = relro_strip_test.so
+relro_strip_test.so: relro_test.so
+	$(TEST_STRIP) -o $@ $<
+
 check_PROGRAMS += relro_script_test
 relro_script_test_SOURCES = relro_test_main.cc
 relro_script_test_DEPENDENCIES = gcctestdir/ld relro_script_test.so

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