aboutsummaryrefslogtreecommitdiff
path: root/gold/output.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>2011-06-23 00:46:14 +0000
committerIan Lance Taylor <ian@airs.com>2011-06-23 00:46:14 +0000
commit5393d7415a71a6f2cf3752e02ef078d7ff6e5f0a (patch)
treea0c89965b041ce2f337110a23e6f7e552984c545 /gold/output.cc
parent1c23ac006028a1d2b12bdfec2fe73751fb7481ec (diff)
downloadgdb-5393d7415a71a6f2cf3752e02ef078d7ff6e5f0a.zip
gdb-5393d7415a71a6f2cf3752e02ef078d7ff6e5f0a.tar.gz
gdb-5393d7415a71a6f2cf3752e02ef078d7ff6e5f0a.tar.bz2
PR gold/12910
* options.h (class General_options): Add --ctors-in-init-array. * layout.cc (Layout::get_output_section): Treat SHT_INIT_ARRAY and friends as SHT_PROGBITS for merging sections. (Layout::layout): Remove special handling of .init_array and friends. Don't sort if doing relocatable link. Sort for .ctors and .dtors if ctors_in_init_array. (Layout::make_output_section): Force correct section types for .init_array and friends. Don't sort if doing relocatable link, Don't sort .ctors and .dtors if ctors_in_init_array. (Layout::section_name_mapping): Remove .ctors. and .dtorso. (Layout::output_section_name): Add relobj parameter. Change all callers. Handle .ctors. and .dtors. in code rather than table. Handle .ctors and .dtors if ctors_in_init_array. (Layout::match_file_name): New function, moved from output.cc. * layout.h (class Layout): Update declarations. * output.cc: Include "layout.h". (Input_section_sort_entry::get_priority): New function. (Input_section_sort_entry::match_file_name): Just call Layout::match_file_name. (Output_section::Input_section_sort_init_fini_compare::operator()): Handle .ctors and .dtors. Sort by explicit priority rather than by name. * configure.ac: Remove CONSTRUCTOR_PRIORITY test and conditional. * testsuite/initpri2.c: New test. * testsuite/Makefile.am: Don't test CONSTRUCTOR_PRIORITY. (check_PROGRAMS): Add initpri2. (initpri2_SOURCES, initpri2_DEPENDENCIES): New variables. (initpri2_LDFLAGS, initpri2_LDADD): New variables. * configure, testsuite/Makefile.in: Rebuild.
Diffstat (limited to 'gold/output.cc')
-rw-r--r--gold/output.cc67
1 files changed, 54 insertions, 13 deletions
diff --git a/gold/output.cc b/gold/output.cc
index c7d3e9f..8912c4e 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -42,6 +42,7 @@
#include "reloc.h"
#include "merge.h"
#include "descriptors.h"
+#include "layout.h"
#include "output.h"
// For systems without mmap support.
@@ -3017,7 +3018,7 @@ Output_section::do_set_tls_offset(uint64_t tls_base)
// priority ordering implemented by the GNU linker, in which the
// priority becomes part of the section name and the sections are
// sorted by name. We only do this for an output section if we see an
-// attached input section matching ".ctor.*", ".dtor.*",
+// attached input section matching ".ctors.*", ".dtors.*",
// ".init_array.*" or ".fini_array.*".
class Output_section::Input_section_sort_entry
@@ -3092,6 +3093,34 @@ class Output_section::Input_section_sort_entry
return this->section_name_.find('.', 1) != std::string::npos;
}
+ // Return the priority. Believe it or not, gcc encodes the priority
+ // differently for .ctors/.dtors and .init_array/.fini_array
+ // sections.
+ unsigned int
+ get_priority() const
+ {
+ gold_assert(this->section_has_name_);
+ bool is_ctors;
+ if (is_prefix_of(".ctors.", this->section_name_.c_str())
+ || is_prefix_of(".dtors.", this->section_name_.c_str()))
+ is_ctors = true;
+ else if (is_prefix_of(".init_array.", this->section_name_.c_str())
+ || is_prefix_of(".fini_array.", this->section_name_.c_str()))
+ is_ctors = false;
+ else
+ return 0;
+ char* end;
+ unsigned long prio = strtoul((this->section_name_.c_str()
+ + (is_ctors ? 7 : 12)),
+ &end, 10);
+ if (*end != '\0')
+ return 0;
+ else if (is_ctors)
+ return 65535 - prio;
+ else
+ return prio;
+ }
+
// Return true if this an input file whose base name matches
// FILE_NAME. The base name must have an extension of ".o", and
// must be exactly FILE_NAME.o or FILE_NAME, one character, ".o".
@@ -3100,18 +3129,8 @@ class Output_section::Input_section_sort_entry
// file name this way is a dreadful hack, but the GNU linker does it
// in order to better support gcc, and we need to be compatible.
bool
- match_file_name(const char* match_file_name) const
- {
- const std::string& file_name(this->input_section_.relobj()->name());
- const char* base_name = lbasename(file_name.c_str());
- size_t match_len = strlen(match_file_name);
- if (strncmp(base_name, match_file_name, match_len) != 0)
- return false;
- size_t base_len = strlen(base_name);
- if (base_len != match_len + 2 && base_len != match_len + 3)
- return false;
- return memcmp(base_name + base_len - 2, ".o", 2) == 0;
- }
+ match_file_name(const char* file_name) const
+ { return Layout::match_file_name(this->input_section_.relobj(), file_name); }
// Returns 1 if THIS should appear before S in section order, -1 if S
// appears before THIS and 0 if they are not comparable.
@@ -3233,6 +3252,28 @@ Output_section::Input_section_sort_init_fini_compare::operator()(
if (!s1_has_priority && s2_has_priority)
return false;
+ // .ctors and .dtors sections without priority come after
+ // .init_array and .fini_array sections without priority.
+ if (!s1_has_priority
+ && (s1.section_name() == ".ctors" || s1.section_name() == ".dtors")
+ && s1.section_name() != s2.section_name())
+ return false;
+ if (!s2_has_priority
+ && (s2.section_name() == ".ctors" || s2.section_name() == ".dtors")
+ && s2.section_name() != s1.section_name())
+ return true;
+
+ // Sort by priority if we can.
+ if (s1_has_priority)
+ {
+ unsigned int s1_prio = s1.get_priority();
+ unsigned int s2_prio = s2.get_priority();
+ if (s1_prio < s2_prio)
+ return true;
+ else if (s1_prio > s2_prio)
+ return false;
+ }
+
// Check if a section order exists for these sections through a section
// ordering file. If sequence_num is 0, an order does not exist.
int sequence_num = s1.compare_section_ordering(s2);