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: Put .interp section in PT_INTERP segment


This patch changes gold such that if creating a shared library, and
there is a .interp section, then gold will create a PT_INTERP segment
which holds the .interp section.  Also, if creating a shared library,
the --dynamic-linker option will cause gold to put the option value into
a .interp section in a PT_INTERP segment.  The --dynamic-linker option
overrides.  This is approximately what GNU ld does.  GNU ld behaves
oddly if there is a .interp section and the --dynamic-linker is used: it
seems to keep the contents of the .interp sectin with the length of the
--dynamic-linker option.  I did not attempt to recreate that.

Ian


2011-06-17  Ian Lance Taylor  <iant@google.com>

	PR gold/12880
	* layout.h (class Layout): Add interp_segment_ field.
	* layout.cc (Layout::Layout): Initialize interp_segment_ field.
	(Layout::attach_allocated_section_to_segment): If making shared
	library, put .interp section in PT_INTERP segment.
	(Layout::finalize): Also call create_interp if -dynamic-linker
	option was used.
	(Layout::create_interp): Assert that there is no PT_INTERP
	segment.  If not using a SECTIONS clause, use make_output_section.
	(Layout::make_output_segment): Set interp_segment_ if PT_INTERP.
	* script-sections.cc
	(Script_sections::create_note_and_tls_segments): If making shared
	library, put .interp section in PT_INTERP segment.


Index: layout.h
===================================================================
RCS file: /cvs/src/src/gold/layout.h,v
retrieving revision 1.91
diff -u -p -r1.91 layout.h
--- layout.h	24 May 2011 21:41:10 -0000	1.91
+++ layout.h	17 Jun 2011 12:57:44 -0000
@@ -1,6 +1,6 @@
 // layout.h -- lay out output file sections for gold  -*- C++ -*-
 
-// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -1168,6 +1168,8 @@ class Layout
   Output_segment* tls_segment_;
   // A pointer to the PT_GNU_RELRO segment if there is one.
   Output_segment* relro_segment_;
+  // A pointer to the PT_INTERP segment if there is one.
+  Output_segment* interp_segment_;
   // A backend may increase the size of the PT_GNU_RELRO segment if
   // there is one.  This is the amount to increase it by.
   unsigned int increase_relro_;
Index: layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.199
diff -u -p -r1.199 layout.cc
--- layout.cc	8 Jun 2011 04:43:28 -0000	1.199
+++ layout.cc	17 Jun 2011 12:57:44 -0000
@@ -360,6 +360,7 @@ Layout::Layout(int number_of_input_files
     section_headers_(NULL),
     tls_segment_(NULL),
     relro_segment_(NULL),
+    interp_segment_(NULL),
     increase_relro_(0),
     symtab_section_(NULL),
     symtab_xindex_(NULL),
@@ -618,11 +619,8 @@ Layout::find_output_segment(elfcpp::PT t
 
 // Return the output section to use for section NAME with type TYPE
 // and section flags FLAGS.  NAME must be canonicalized in the string
-// pool, and NAME_KEY is the key.  IS_INTERP is true if this is the
-// .interp section.  IS_DYNAMIC_LINKER_SECTION is true if this section
-// is used by the dynamic linker.  IS_RELRO is true for a relro
-// section.  IS_LAST_RELRO is true for the last relro section.
-// IS_FIRST_NON_RELRO is true for the first non-relro section.
+// pool, and NAME_KEY is the key.  ORDER is where this should appear
+// in the output sections.  IS_RELRO is true for a relro section.
 
 Output_section*
 Layout::get_output_section(const char* name, Stringpool::Key name_key,
@@ -687,12 +685,9 @@ Layout::get_output_section(const char* n
 // RELOBJ, with type TYPE and flags FLAGS.  RELOBJ may be NULL for a
 // linker created section.  IS_INPUT_SECTION is true if we are
 // choosing an output section for an input section found in a input
-// file.  IS_INTERP is true if this is the .interp section.
-// IS_DYNAMIC_LINKER_SECTION is true if this section is used by the
-// dynamic linker.  IS_RELRO is true for a relro section.
-// IS_LAST_RELRO is true for the last relro section.
-// IS_FIRST_NON_RELRO is true for the first non-relro section.  This
-// will return NULL if the input section should be discarded.
+// file.  ORDER is where this section should appear in the output
+// sections.  IS_RELRO is true for a relro section.  This will return
+// NULL if the input section should be discarded.
 
 Output_section*
 Layout::choose_output_section(const Relobj* relobj, const char* name,
@@ -1541,6 +1536,21 @@ Layout::attach_allocated_section_to_segm
 	this->make_output_segment(elfcpp::PT_GNU_RELRO, seg_flags);
       this->relro_segment_->add_output_section_to_nonload(os, seg_flags);
     }
+
+  // If we are making a shared library, and we see a section named
+  // .interp, and the -dynamic-linker option was not used, then put
+  // the .interp section into a PT_INTERP segment.  This is for GNU ld
+  // compatibility.  If making an executable, or if the
+  // -dynamic-linker option was used, we will create the section and
+  // segment in Layout::create_interp.
+  if (strcmp(os->name(), ".interp") == 0
+      && parameters->options().shared()
+      && parameters->options().dynamic_linker() == NULL)
+    {
+      if (this->interp_segment_ == NULL)
+	this->make_output_segment(elfcpp::PT_INTERP, seg_flags);
+      this->interp_segment_->add_output_section_to_nonload(os, seg_flags);
+    }
 }
 
 // Make an output section for a script.
@@ -2164,7 +2174,8 @@ Layout::finalize(const Input_objects* in
 
       // Create the .interp section to hold the name of the
       // interpreter, and put it in a PT_INTERP segment.
-      if (!parameters->options().shared())
+      if (!parameters->options().shared()
+	  || parameters->options().dynamic_linker() != NULL)
         this->create_interp(target);
 
       // Finish the .dynamic section to hold the dynamic data, and put
@@ -3845,6 +3856,8 @@ Layout::sized_create_version_sections(
 void
 Layout::create_interp(const Target* target)
 {
+  gold_assert(this->interp_segment_ == NULL);
+
   const char* interp = parameters->options().dynamic_linker();
   if (interp == NULL)
     {
@@ -3856,11 +3869,23 @@ Layout::create_interp(const Target* targ
 
   Output_section_data* odata = new Output_data_const(interp, len, 1);
 
-  Output_section* osec = this->choose_output_section(NULL, ".interp",
-						     elfcpp::SHT_PROGBITS,
-						     elfcpp::SHF_ALLOC,
-						     false, ORDER_INTERP,
-						     false);
+  Output_section* osec;
+
+  // If we are using a SECTIONS clause, let it decide where the
+  // .interp section should go.  Otherwise always create a new section
+  // so that this .interp section does not get confused with any
+  // section of the same name in the program.
+  if (this->script_options_->saw_sections_clause())
+    osec = this->choose_output_section(NULL, ".interp", elfcpp::SHT_PROGBITS,
+				       elfcpp::SHF_ALLOC, false, ORDER_INTERP,
+				       false);
+  else
+    {
+      const char* n = this->namepool_.add("interp", false, NULL);
+      osec = this->make_output_section(n, elfcpp::SHT_PROGBITS,
+				       elfcpp::SHF_ALLOC, ORDER_INTERP, false);
+    }
+
   osec->add_output_section_data(odata);
 
   if (!this->script_options_->saw_phdrs_clause())
@@ -4389,6 +4414,8 @@ Layout::make_output_segment(elfcpp::Elf_
     this->tls_segment_ = oseg;
   else if (type == elfcpp::PT_GNU_RELRO)
     this->relro_segment_ = oseg;
+  else if (type == elfcpp::PT_INTERP)
+    this->interp_segment_ = oseg;
 
   return oseg;
 }
Index: script-sections.cc
===================================================================
RCS file: /cvs/src/src/gold/script-sections.cc,v
retrieving revision 1.50
diff -u -p -r1.50 script-sections.cc
--- script-sections.cc	9 Jun 2011 19:25:02 -0000	1.50
+++ script-sections.cc	17 Jun 2011 12:57:44 -0000
@@ -3936,6 +3936,21 @@ Script_sections::create_note_and_tls_seg
 
 	  saw_tls = true;
 	}
+
+      // If we are making a shared library, and we see a section named
+      // .interp, and the -dynamic-linker option was not used, then
+      // put the .interp section in a PT_INTERP segment.  This is for
+      // GNU ld compatibility.
+      if (strcmp((*p)->name(), ".interp") == 0
+	  && parameters->options().shared()
+	  && parameters->options().dynamic_linker() == NULL)
+	{
+	  elfcpp::Elf_Word seg_flags =
+	    Layout::section_flags_to_segment((*p)->flags());
+	  Output_segment* oseg = layout->make_output_segment(elfcpp::PT_INTERP,
+							     seg_flags);
+	  oseg->add_output_section_to_nonload(*p, seg_flags);
+	}
     }
 }
 

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