From 2cefc35727da245c5b39b51551a488ba7f211689 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 10 Apr 2008 01:02:46 +0000 Subject: [PATCH] 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. --- gold/ChangeLog | 13 +++++++++ gold/script-sections.cc | 59 ++++++++++++++++++++++++++++------------- gold/testsuite/Makefile.am | 2 +- gold/testsuite/Makefile.in | 2 +- gold/testsuite/script_test_3.sh | 35 +++++++++++++++++++++--- 5 files changed, 87 insertions(+), 24 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index b6e2ac4..001760f 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,5 +1,18 @@ 2008-04-09 Ian Lance Taylor + 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. diff --git a/gold/script-sections.cc b/gold/script-sections.cc index 340bf89..f6b6550 100644 --- a/gold/script-sections.cc +++ b/gold/script-sections.cc @@ -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(); diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index ffb99c4..a27166e 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -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 diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index fea5a39..90f6d9e 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -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: diff --git a/gold/testsuite/script_test_3.sh b/gold/testsuite/script_test_3.sh index 338e5ce..cddb69a 100755 --- a/gold/testsuite/script_test_3.sh +++ b/gold/testsuite/script_test_3.sh @@ -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 -- 2.7.4