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.
This commit is contained in:
parent
a4bb589a17
commit
2cefc35727
@ -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.
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user