PR gold/5996
authorIan Lance Taylor <ian@airs.com>
Thu, 10 Apr 2008 01:02:46 +0000 (01:02 +0000)
committerIan Lance Taylor <ian@airs.com>
Thu, 10 Apr 2008 01:02:46 +0000 (01:02 +0000)
* script-sections.cc (Sections_element::allocate_to_segment): Add
orphan parameter.
(Output_section_definition::allocate_to_segment): Likewise.
(Orphan_output_section::allocate_to_segment): Likewise.
(Script_sections::attach_sections_using_phdrs_clause): Don't
propagate non-PT_LOAD segments to orphan sections.
* testsuite/Makefile.am (script_test_3.stdout): Generate using
readelf rather than objdump.
* testsuite/script_test_3.sh: Adjust accordingly.  Test that
.interp section and PT_INTERP segment are the same size.
* testsuite/Makefile.in: Rebuild.

gold/ChangeLog
gold/script-sections.cc
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/script_test_3.sh

index b6e2ac4..001760f 100644 (file)
@@ -1,5 +1,18 @@
 2008-04-09  Ian Lance Taylor  <iant@google.com>
 
+       PR gold/5996
+       * script-sections.cc (Sections_element::allocate_to_segment): Add
+       orphan parameter.
+       (Output_section_definition::allocate_to_segment): Likewise.
+       (Orphan_output_section::allocate_to_segment): Likewise.
+       (Script_sections::attach_sections_using_phdrs_clause): Don't
+       propagate non-PT_LOAD segments to orphan sections.
+       * testsuite/Makefile.am (script_test_3.stdout): Generate using
+       readelf rather than objdump.
+       * testsuite/script_test_3.sh: Adjust accordingly.  Test that
+       .interp section and PT_INTERP segment are the same size.
+       * testsuite/Makefile.in: Rebuild.
+
        * symtab.cc (Symbol_table::add_from_dynobj): Only look for weak
        aliases for symbols defined in the same object.
        * testsuite/Makefile.am (check_PROGRAMS): Add weak_alias_test.
index 340bf89..f6b6550 100644 (file)
@@ -105,11 +105,14 @@ class Sections_element
 
   // Get the list of segments to use for an allocated section when
   // using a PHDRS clause.  If this is an allocated section, return
-  // the Output_section, and set *PHDRS_LIST to the list of PHDRS to
-  // which it should be attached.  If the PHDRS were not specified,
-  // don't change *PHDRS_LIST.
+  // the Output_section, and set *PHDRS_LIST (the first parameter) to
+  // the list of PHDRS to which it should be attached.  If the PHDRS
+  // were not specified, don't change *PHDRS_LIST.  When not returning
+  // NULL, set *ORPHAN (the second parameter) according to whether
+  // this is an orphan section--one that is not mentioned in the
+  // linker script.
   virtual Output_section*
-  allocate_to_segment(String_list**)
+  allocate_to_segment(String_list**, bool*)
   { return NULL; }
 
   // Look for an output section by name and return the address, the
@@ -1263,12 +1266,9 @@ class Output_section_definition : public Sections_element
   alternate_constraint(Output_section_definition*, Section_constraint);
 
   // Get the list of segments to use for an allocated section when
-  // using a PHDRS clause.  If this is an allocated section, return
-  // the Output_section, and set *PHDRS_LIST to the list of PHDRS to
-  // which it should be attached.  If the PHDRS were not specified,
-  // don't change *PHDRS_LIST.
+  // using a PHDRS clause.
   Output_section*
-  allocate_to_segment(String_list** phdrs_list);
+  allocate_to_segment(String_list** phdrs_list, bool* orphan);
 
   // Look for an output section by name and return the address, the
   // load address, the alignment, and the size.  This is used when an
@@ -1834,18 +1834,17 @@ Output_section_definition::alternate_constraint(
 }
 
 // Get the list of segments to use for an allocated section when using
-// a PHDRS clause.  If this is an allocated section, return the
-// Output_section, and set *PHDRS_LIST to the list of PHDRS to which
-// it should be attached.  If the PHDRS were not specified, don't
-// change *PHDRS_LIST.
+// a PHDRS clause.
 
 Output_section*
-Output_section_definition::allocate_to_segment(String_list** phdrs_list)
+Output_section_definition::allocate_to_segment(String_list** phdrs_list,
+                                              bool* orphan)
 {
   if (this->output_section_ == NULL)
     return NULL;
   if ((this->output_section_->flags() & elfcpp::SHF_ALLOC) == 0)
     return NULL;
+  *orphan = false;
   if (this->phdrs_ != NULL)
     *phdrs_list = this->phdrs_;
   return this->output_section_;
@@ -1971,10 +1970,9 @@ class Orphan_output_section : public Sections_element
   set_section_addresses(Symbol_table*, Layout*, uint64_t*, uint64_t*);
 
   // Get the list of segments to use for an allocated section when
-  // using a PHDRS clause.  If this is an allocated section, return
-  // the Output_section.
+  // using a PHDRS clause.
   Output_section*
-  allocate_to_segment(String_list**);
+  allocate_to_segment(String_list**, bool*);
 
   // Print for debugging.
   void
@@ -2063,10 +2061,11 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*,
 // Output_section.  We don't change the list of segments.
 
 Output_section*
-Orphan_output_section::allocate_to_segment(String_list**)
+Orphan_output_section::allocate_to_segment(String_list**, bool* orphan)
 {
   if ((this->os_->flags() & elfcpp::SHF_ALLOC) == 0)
     return NULL;
+  *orphan = true;
   return this->os_;
 }
 
@@ -2890,7 +2889,8 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout)
        p != this->sections_elements_->end();
        ++p)
     {
-      Output_section* os = (*p)->allocate_to_segment(&phdr_names);
+      bool orphan;
+      Output_section* os = (*p)->allocate_to_segment(&phdr_names, &orphan);
       if (os == NULL)
        continue;
 
@@ -2900,6 +2900,27 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout)
          continue;
        }
 
+      // If this is an orphan section--one that was not explicitly
+      // mentioned in the linker script--then it should not inherit
+      // any segment type other than PT_LOAD.  Otherwise, e.g., the
+      // PT_INTERP segment will pick up following orphan sections,
+      // which does not make sense.  If this is not an orphan section,
+      // we trust the linker script.
+      if (orphan)
+       {
+         String_list::iterator q = phdr_names->begin();
+         while (q != phdr_names->end())
+           {
+             Name_to_segment::const_iterator r = name_to_segment.find(*q);
+             // We give errors about unknown segments below.
+             if (r == name_to_segment.end()
+                 || r->second->type() == elfcpp::PT_LOAD)
+               ++q;
+             else
+               q = phdr_names->erase(q);
+           }
+       }
+
       bool in_load_segment = false;
       for (String_list::const_iterator q = phdr_names->begin();
           q != phdr_names->end();
index ffb99c4..a27166e 100644 (file)
@@ -692,7 +692,7 @@ MOSTLYCLEANFILES += script_test_3.stdout
 script_test_3: basic_test.o gcctestdir/ld script_test_3.t
        $(CXXLINK) -Bgcctestdir/ basic_test.o -T $(srcdir)/script_test_3.t
 script_test_3.stdout: script_test_3
-       $(TEST_OBJDUMP) -p script_test_3 > script_test_3.stdout
+       $(TEST_READELF) -SlW script_test_3 > script_test_3.stdout
 
 endif GCC
 endif NATIVE_LINKER
index fea5a39..90f6d9e 100644 (file)
@@ -1970,7 +1970,7 @@ uninstall-am: uninstall-info-am
 @GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_3: basic_test.o gcctestdir/ld script_test_3.t
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_test.o -T $(srcdir)/script_test_3.t
 @GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_3.stdout: script_test_3
-@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_OBJDUMP) -p script_test_3 > script_test_3.stdout
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -SlW script_test_3 > script_test_3.stdout
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
index 338e5ce..cddb69a 100755 (executable)
@@ -52,8 +52,37 @@ check_count()
     fi
 }
 
-check_count script_test_3.stdout "INTERP off" 1
-check_count script_test_3.stdout "LOAD off" 3
-check_count script_test_3.stdout "DYNAMIC off" 1
+check_count script_test_3.stdout "^  INTERP" 1
+check_count script_test_3.stdout "^  LOAD" 3
+check_count script_test_3.stdout "^  DYNAMIC" 1
+
+# Make sure that the size of the INTERP segment is the same as the
+# size of the .interp section.
+section=`fgrep .interp script_test_3.stdout | grep PROGBITS`
+if test "$section" = ""; then
+  echo "Did not find .interp section"
+  echo ""
+  echo "Actual output below:"
+  cat script_test_3.stdout
+  exit 1
+fi
+# Remove the brackets around the section number, since they can give
+# an unpredictable number of fields.
+section=`echo "$section" | sed -e 's/[][]*//g'`
+section_size=`echo "$section" | awk '{ print $6; }'`
+
+segment=`grep '^  INTERP' script_test_3.stdout`
+# We already checked above that we have an INTERP segment.
+segment_size=`echo "$segment" | awk '{ print $5; }'`
+
+# Now $section_size looks like 000013 and $segment_size looks like
+# 0x00013.  Both numbers are in hex.
+section_size=`echo "$section_size" | sed -e 's/^0*//'`
+segment_size=`echo "$segment_size" | sed -e 's/^0x//' -e 's/^0*//'`
+
+if test "$section_size" != "$segment_size"; then
+  echo ".interp size $section_size != PT_INTERP size $segment_size"
+  exit 1
+fi
 
 exit 0