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.
// 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
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
}
// 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_;
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
// 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_;
}
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;
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();
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