* script-sections.cc (class Orphan_section_placement): Define
[binutils-gdb.git] / gold / output.cc
index 6374895a5e4bb1c6d4ed26d96d485fbf460e4ad4..0627cbe698fa64c87bd61fe2b4afb83275689398 100644 (file)
@@ -638,9 +638,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     unsigned int type,
     Output_data* od,
     Address address,
-    bool is_relative)
+    bool is_relative,
+    bool is_symbolless)
   : address_(address), local_sym_index_(GSYM_CODE), type_(type),
-    is_relative_(is_relative), is_section_symbol_(false), shndx_(INVALID_CODE)
+    is_relative_(is_relative), is_symbolless_(is_symbolless),
+    is_section_symbol_(false), shndx_(INVALID_CODE)
 {
   // this->type_ is a bitfield; make sure TYPE fits.
   gold_assert(this->type_ == type);
@@ -657,9 +659,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Sized_relobj<size, big_endian>* relobj,
     unsigned int shndx,
     Address address,
-    bool is_relative)
+    bool is_relative,
+    bool is_symbolless)
   : address_(address), local_sym_index_(GSYM_CODE), type_(type),
-    is_relative_(is_relative), is_section_symbol_(false), shndx_(shndx)
+    is_relative_(is_relative), is_symbolless_(is_symbolless),
+    is_section_symbol_(false), shndx_(shndx)
 {
   gold_assert(shndx != INVALID_CODE);
   // this->type_ is a bitfield; make sure TYPE fits.
@@ -680,10 +684,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Output_data* od,
     Address address,
     bool is_relative,
+    bool is_symbolless,
     bool is_section_symbol)
   : address_(address), local_sym_index_(local_sym_index), type_(type),
-    is_relative_(is_relative), is_section_symbol_(is_section_symbol),
-    shndx_(INVALID_CODE)
+    is_relative_(is_relative), is_symbolless_(is_symbolless),
+    is_section_symbol_(is_section_symbol), shndx_(INVALID_CODE)
 {
   gold_assert(local_sym_index != GSYM_CODE
               && local_sym_index != INVALID_CODE);
@@ -703,10 +708,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     unsigned int shndx,
     Address address,
     bool is_relative,
+    bool is_symbolless,
     bool is_section_symbol)
   : address_(address), local_sym_index_(local_sym_index), type_(type),
-    is_relative_(is_relative), is_section_symbol_(is_section_symbol),
-    shndx_(shndx)
+    is_relative_(is_relative), is_symbolless_(is_symbolless),
+    is_section_symbol_(is_section_symbol), shndx_(shndx)
 {
   gold_assert(local_sym_index != GSYM_CODE
               && local_sym_index != INVALID_CODE);
@@ -728,7 +734,8 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Output_data* od,
     Address address)
   : address_(address), local_sym_index_(SECTION_CODE), type_(type),
-    is_relative_(false), is_section_symbol_(true), shndx_(INVALID_CODE)
+    is_relative_(false), is_symbolless_(false),
+    is_section_symbol_(true), shndx_(INVALID_CODE)
 {
   // this->type_ is a bitfield; make sure TYPE fits.
   gold_assert(this->type_ == type);
@@ -748,7 +755,8 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     unsigned int shndx,
     Address address)
   : address_(address), local_sym_index_(SECTION_CODE), type_(type),
-    is_relative_(false), is_section_symbol_(true), shndx_(shndx)
+    is_relative_(false), is_symbolless_(false),
+    is_section_symbol_(true), shndx_(shndx)
 {
   gold_assert(shndx != INVALID_CODE);
   // this->type_ is a bitfield; make sure TYPE fits.
@@ -769,7 +777,8 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Output_data* od,
     Address address)
   : address_(address), local_sym_index_(0), type_(type),
-    is_relative_(false), is_section_symbol_(false), shndx_(INVALID_CODE)
+    is_relative_(false), is_symbolless_(false),
+    is_section_symbol_(false), shndx_(INVALID_CODE)
 {
   // this->type_ is a bitfield; make sure TYPE fits.
   gold_assert(this->type_ == type);
@@ -784,7 +793,8 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     unsigned int shndx,
     Address address)
   : address_(address), local_sym_index_(0), type_(type),
-    is_relative_(false), is_section_symbol_(false), shndx_(shndx)
+    is_relative_(false), is_symbolless_(false),
+    is_section_symbol_(false), shndx_(shndx)
 {
   gold_assert(shndx != INVALID_CODE);
   // this->type_ is a bitfield; make sure TYPE fits.
@@ -802,7 +812,8 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Output_data* od,
     Address address)
   : address_(address), local_sym_index_(TARGET_CODE), type_(type),
-    is_relative_(false), is_section_symbol_(false), shndx_(INVALID_CODE)
+    is_relative_(false), is_symbolless_(false),
+    is_section_symbol_(false), shndx_(INVALID_CODE)
 {
   // this->type_ is a bitfield; make sure TYPE fits.
   gold_assert(this->type_ == type);
@@ -818,7 +829,8 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     unsigned int shndx,
     Address address)
   : address_(address), local_sym_index_(TARGET_CODE), type_(type),
-    is_relative_(false), is_section_symbol_(false), shndx_(shndx)
+    is_relative_(false), is_symbolless_(false),
+    is_section_symbol_(false), shndx_(shndx)
 {
   gold_assert(shndx != INVALID_CODE);
   // this->type_ is a bitfield; make sure TYPE fits.
@@ -834,7 +846,7 @@ void
 Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::
 set_needs_dynsym_index()
 {
-  if (this->is_relative_)
+  if (this->is_symbolless_)
     return;
   switch (this->local_sym_index_)
     {
@@ -876,6 +888,8 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::get_symbol_index()
   const
 {
   unsigned int index;
+  if (this->is_symbolless_)
+    return 0;
   switch (this->local_sym_index_)
     {
     case INVALID_CODE:
@@ -995,7 +1009,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::write_rel(
     Write_rel* wr) const
 {
   wr->put_r_offset(this->get_address());
-  unsigned int sym_index = this->is_relative_ ? 0 : this->get_symbol_index();
+  unsigned int sym_index = this->get_symbol_index();
   wr->put_r_info(elfcpp::elf_r_info<size>(sym_index, this->type_));
 }
 
@@ -1097,7 +1111,7 @@ Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>::write(
   if (this->rel_.is_target_specific())
     addend = parameters->target().reloc_addend(this->rel_.target_arg(),
                                               this->rel_.type(), addend);
-  else if (this->rel_.is_relative())
+  else if (this->rel_.is_symbolless())
     addend = this->rel_.symbol_value(addend);
   else if (this->rel_.is_local_section_symbol())
     addend = this->rel_.local_section_offset(addend);
@@ -1560,6 +1574,8 @@ Output_data_dynamic::Dynamic_entry::write(
 
     case DYNAMIC_SECTION_SIZE:
       val = this->u_.od->data_size();
+      if (this->od2 != NULL)
+       val += this->od2->data_size();
       break;
 
     case DYNAMIC_SYMBOL:
@@ -1606,9 +1622,13 @@ Output_data_dynamic::set_final_data_size()
 {
   // Add the terminating entry if it hasn't been added.
   // Because of relaxation, we can run this multiple times.
-  if (this->entries_.empty()
-      || this->entries_.rbegin()->tag() != elfcpp::DT_NULL)
-    this->add_constant(elfcpp::DT_NULL, 0);
+  if (this->entries_.empty() || this->entries_.back().tag() != elfcpp::DT_NULL)
+    {
+      int extra = parameters->options().spare_dynamic_tags();
+      for (int i = 0; i < extra; ++i)
+       this->add_constant(elfcpp::DT_NULL, 0);
+      this->add_constant(elfcpp::DT_NULL, 0);
+    }
 
   int dyn_size;
   if (parameters->target().get_size() == 32)
@@ -1890,6 +1910,7 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
     is_dynamic_linker_section_(false),
     generate_code_fills_at_write_(false),
     is_entsize_zero_(false),
+    section_offsets_need_adjustment_(false),
     tls_offset_(0),
     checkpoint_(NULL),
     merge_section_map_(),
@@ -2678,7 +2699,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
@@ -2756,8 +2777,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)
@@ -2774,6 +2793,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
@@ -2802,7 +2857,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();
@@ -3043,12 +3105,12 @@ Output_section::get_input_sections(
   return data_size;
 }
 
-// Add an input section from a script.
+// Add an simple input section.
 
 void
-Output_section::add_input_section_for_script(const Simple_input_section& sis,
-                                            off_t data_size,
-                                            uint64_t addralign)
+Output_section::add_simple_input_section(const Simple_input_section& sis,
+                                        off_t data_size,
+                                        uint64_t addralign)
 {
   if (addralign > this->addralign_)
     this->addralign_ = addralign;
@@ -3067,7 +3129,7 @@ Output_section::add_input_section_for_script(const Simple_input_section& sis,
   this->input_sections_.push_back(is);
 }
 
-//
+// Save states for relaxation.
 
 void
 Output_section::save_states()
@@ -3082,6 +3144,19 @@ Output_section::save_states()
   gold_assert(this->fills_.empty());
 }
 
+void
+Output_section::discard_states()
+{
+  gold_assert(this->checkpoint_ != NULL);
+  delete this->checkpoint_;
+  this->checkpoint_ = NULL;
+  gold_assert(this->fills_.empty());
+
+  // Simply invalidate the relaxed input section map since we do not keep
+  // track of it.
+  this->is_relaxed_input_section_map_valid_ = false;
+}
+
 void
 Output_section::restore_states()
 {
@@ -3116,6 +3191,29 @@ Output_section::restore_states()
   this->is_relaxed_input_section_map_valid_ = false;
 }
 
+// Update the section offsets of input sections in this.  This is required if
+// relaxation causes some input sections to change sizes.
+
+void
+Output_section::adjust_section_offsets()
+{
+  if (!this->section_offsets_need_adjustment_)
+    return;
+
+  off_t off = 0;
+  for (Input_section_list::iterator p = this->input_sections_.begin();
+       p != this->input_sections_.end();
+       ++p)
+    {
+      off = align_address(off, p->addralign());
+      if (p->is_input_section())
+       p->relobj()->set_section_offset(p->shndx(), off);
+      off += p->data_size();
+    }
+
+  this->section_offsets_need_adjustment_ = false;
+}
+
 // Print to the map file.
 
 void