aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
authorDoug Kwan <dougkwan@google.com>2010-03-01 21:43:50 +0000
committerDoug Kwan <dougkwan@google.com>2010-03-01 21:43:50 +0000
commit2a0ff005c89d674c7e233c7fa612aa2434bcd8df (patch)
treef7cdface7116bfdf3188bd6d8b844deff74b551d /gold
parenta6f5ef51d7c85bd0b950fd182284f6cbff5fecf0 (diff)
downloadgdb-2a0ff005c89d674c7e233c7fa612aa2434bcd8df.zip
gdb-2a0ff005c89d674c7e233c7fa612aa2434bcd8df.tar.gz
gdb-2a0ff005c89d674c7e233c7fa612aa2434bcd8df.tar.bz2
2010-03-01 Doug Kwan <dougkwan@google.com>
* layout.cc (Layout::Layout): Force section types of .init_array*, .preinit_array* and .fini_array* sections. * output.cc (Output_section::Input_section_sort_entry::has_priority): Fix check of return value of std::string::find.(). (Output_section::Input_section_sort_compare::operator()): Remove comment about .init_array. (Output_section::Input_section_sort_init_fini_compare::operator()): New method. (Output_section::sort_attached_input_sections): Handle .init_array and .fini_array specially. * output.h (Output_section::Inut_section_sort_compare): Update comment. (Output_section::Input_section_sort_init_fini_compare): New struct.
Diffstat (limited to 'gold')
-rw-r--r--gold/ChangeLog16
-rw-r--r--gold/layout.cc29
-rw-r--r--gold/output.cc49
-rw-r--r--gold/output.h10
4 files changed, 95 insertions, 9 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index d6e806d..514310d 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,19 @@
+2010-03-01 Doug Kwan <dougkwan@google.com>
+
+ * layout.cc (Layout::Layout): Force section types of .init_array*,
+ .preinit_array* and .fini_array* sections.
+ * output.cc (Output_section::Input_section_sort_entry::has_priority):
+ Fix check of return value of std::string::find.().
+ (Output_section::Input_section_sort_compare::operator()): Remove
+ comment about .init_array.
+ (Output_section::Input_section_sort_init_fini_compare::operator()):
+ New method.
+ (Output_section::sort_attached_input_sections): Handle .init_array
+ and .fini_array specially.
+ * output.h (Output_section::Inut_section_sort_compare): Update
+ comment.
+ (Output_section::Input_section_sort_init_fini_compare): New struct.
+
2010-02-26 Doug Kwan <dougkwan@google.com>
* arm.cc (Target_arm::Relocate::reloc_is_non_pic): Treat
diff --git a/gold/layout.cc b/gold/layout.cc
index c721ba6..f95813b 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -582,19 +582,40 @@ Layout::layout(Sized_relobj<size, big_endian>* object, unsigned int shndx,
Output_section* os;
+ // Sometimes .init_array*, .preinit_array* and .fini_array* do not have
+ // correct section types. Force them here.
+ elfcpp::Elf_Word sh_type = shdr.get_sh_type();
+ if (sh_type == elfcpp::SHT_PROGBITS)
+ {
+ static const char init_array_prefix[] = ".init_array";
+ static const char preinit_array_prefix[] = ".preinit_array";
+ static const char fini_array_prefix[] = ".fini_array";
+ static size_t init_array_prefix_size = sizeof(init_array_prefix) - 1;
+ static size_t preinit_array_prefix_size =
+ sizeof(preinit_array_prefix) - 1;
+ static size_t fini_array_prefix_size = sizeof(fini_array_prefix) - 1;
+
+ if (strncmp(name, init_array_prefix, init_array_prefix_size) == 0)
+ sh_type = elfcpp::SHT_INIT_ARRAY;
+ else if (strncmp(name, preinit_array_prefix, preinit_array_prefix_size)
+ == 0)
+ sh_type = elfcpp::SHT_PREINIT_ARRAY;
+ else if (strncmp(name, fini_array_prefix, fini_array_prefix_size) == 0)
+ sh_type = elfcpp::SHT_FINI_ARRAY;
+ }
+
// In a relocatable link a grouped section must not be combined with
// any other sections.
if (parameters->options().relocatable()
&& (shdr.get_sh_flags() & elfcpp::SHF_GROUP) != 0)
{
name = this->namepool_.add(name, true, NULL);
- os = this->make_output_section(name, shdr.get_sh_type(),
- shdr.get_sh_flags(), false, false,
- false, false, false);
+ os = this->make_output_section(name, sh_type, shdr.get_sh_flags(), false,
+ false, false, false, false);
}
else
{
- os = this->choose_output_section(object, name, shdr.get_sh_type(),
+ os = this->choose_output_section(object, name, sh_type,
shdr.get_sh_flags(), true, false,
false, false, false, false);
if (os == NULL)
diff --git a/gold/output.cc b/gold/output.cc
index 1c2533c..d49f08b 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -2695,7 +2695,7 @@ class Output_section::Input_section_sort_entry
has_priority() const
{
gold_assert(this->section_has_name_);
- return this->section_name_.find('.', 1);
+ return this->section_name_.find('.', 1) != std::string::npos;
}
// Return true if this an input file whose base name matches
@@ -2773,8 +2773,6 @@ Output_section::Input_section_sort_compare::operator()(
}
// A section with a priority follows a section without a priority.
- // The GNU linker does this for all but .init_array sections; until
- // further notice we'll assume that that is an mistake.
bool s1_has_priority = s1.has_priority();
bool s2_has_priority = s2.has_priority();
if (s1_has_priority && !s2_has_priority)
@@ -2791,6 +2789,42 @@ Output_section::Input_section_sort_compare::operator()(
return s1.index() < s2.index();
}
+// Return true if S1 should come before S2 in an .init_array or .fini_array
+// output section.
+
+bool
+Output_section::Input_section_sort_init_fini_compare::operator()(
+ const Output_section::Input_section_sort_entry& s1,
+ const Output_section::Input_section_sort_entry& s2) const
+{
+ // We sort all the sections with no names to the end.
+ if (!s1.section_has_name() || !s2.section_has_name())
+ {
+ if (s1.section_has_name())
+ return true;
+ if (s2.section_has_name())
+ return false;
+ return s1.index() < s2.index();
+ }
+
+ // A section without a priority follows a section with a priority.
+ // This is the reverse of .ctors and .dtors sections.
+ bool s1_has_priority = s1.has_priority();
+ bool s2_has_priority = s2.has_priority();
+ if (s1_has_priority && !s2_has_priority)
+ return true;
+ if (!s1_has_priority && s2_has_priority)
+ return false;
+
+ // Otherwise we sort by name.
+ int compare = s1.section_name().compare(s2.section_name());
+ if (compare != 0)
+ return compare < 0;
+
+ // Otherwise we keep the input order.
+ return s1.index() < s2.index();
+}
+
// Sort the input sections attached to an output section.
void
@@ -2819,7 +2853,14 @@ Output_section::sort_attached_input_sections()
sort_list.push_back(Input_section_sort_entry(*p, i));
// Sort the input sections.
- std::sort(sort_list.begin(), sort_list.end(), Input_section_sort_compare());
+ if (this->type() == elfcpp::SHT_PREINIT_ARRAY
+ || this->type() == elfcpp::SHT_INIT_ARRAY
+ || this->type() == elfcpp::SHT_FINI_ARRAY)
+ std::sort(sort_list.begin(), sort_list.end(),
+ Input_section_sort_init_fini_compare());
+ else
+ std::sort(sort_list.begin(), sort_list.end(),
+ Input_section_sort_compare());
// Copy the sorted input sections back to our list.
this->input_sections_.clear();
diff --git a/gold/output.h b/gold/output.h
index 9008bdd..a63f07c 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -3378,7 +3378,7 @@ class Output_section : public Output_data
// This class is used to sort the input sections.
class Input_section_sort_entry;
- // This is the sort comparison function.
+ // This is the sort comparison function for ctors and dtors.
struct Input_section_sort_compare
{
bool
@@ -3386,6 +3386,14 @@ class Output_section : public Output_data
const Input_section_sort_entry&) const;
};
+ // This is the sort comparison function for .init_array and .fini_array.
+ struct Input_section_sort_init_fini_compare
+ {
+ bool
+ operator()(const Input_section_sort_entry&,
+ const Input_section_sort_entry&) const;
+ };
+
// Fill data. This is used to fill in data between input sections.
// It is also used for data statements (BYTE, WORD, etc.) in linker
// scripts. When we have to keep track of the input sections, we