* configure.tgt (powerpc64-*): Fix targ_obj.
[binutils-gdb.git] / gold / object.cc
index d8f5ec8027492d2178404413e4f352d7b8dd05fc..6a23a6f1b6a0420e7ddaf7f49f473f3cde31d9ab 100644 (file)
@@ -37,6 +37,7 @@
 #include "reloc.h"
 #include "object.h"
 #include "dynobj.h"
+#include "plugin.h"
 
 namespace gold
 {
@@ -784,6 +785,34 @@ Sized_relobj<size, big_endian>::include_linkonce_section(
   return include1 && include2;
 }
 
+// Layout an input section.
+
+template<int size, bool big_endian>
+inline void
+Sized_relobj<size, big_endian>::layout_section(Layout* layout,
+                                               unsigned int shndx,
+                                               const char* name,
+                                               typename This::Shdr& shdr,
+                                               unsigned int reloc_shndx,
+                                               unsigned int reloc_type)
+{
+  off_t offset;
+  Output_section* os = layout->layout(this, shndx, name, shdr,
+                                         reloc_shndx, reloc_type, &offset);
+
+  this->output_sections()[shndx] = os;
+  if (offset == -1)
+    this->section_offsets_[shndx] = invalid_address;
+  else
+    this->section_offsets_[shndx] = convert_types<Address, off_t>(offset);
+
+  // If this section requires special handling, and if there are
+  // relocs that apply to it, then we must do the special handling
+  // before we apply the relocs.
+  if (offset == -1 && reloc_shndx != 0)
+    this->set_relocs_must_follow_section_writes();
+}
+
 // Lay out the input sections.  We walk through the sections and check
 // whether they should be included in the link.  If they should, we
 // pass them to the Layout object, which will return an output section
@@ -807,6 +836,13 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
   const unsigned char* pnamesu = sd->section_names->data();
   const char* pnames = reinterpret_cast<const char*>(pnamesu);
 
+  // If any input files have been claimed by plugins, we need to defer
+  // actual layout until the replacement files have arrived.
+  const bool should_defer_layout =
+      (parameters->options().has_plugins()
+       && parameters->options().plugins()->should_defer_layout());
+  unsigned int num_sections_to_defer = 0;
+
   // For each section, record the index of the reloc section if any.
   // Use 0 to mean that there is no reloc section, -1U to mean that
   // there is more than one.
@@ -818,6 +854,10 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
     {
       typename This::Shdr shdr(pshdrs);
 
+      // Count the number of sections whose layout will be deferred.
+      if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
+        ++num_sections_to_defer;
+
       unsigned int sh_type = shdr.get_sh_type();
       if (sh_type == elfcpp::SHT_REL || sh_type == elfcpp::SHT_RELA)
        {
@@ -856,6 +896,12 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
       return;
     }
 
+  if (num_sections_to_defer > 0)
+    {
+      parameters->options().plugins()->add_deferred_layout_object(this);
+      this->deferred_layout_.reserve(num_sections_to_defer);
+    }
+
   // Whether we've seen a .note.GNU-stack section.
   bool seen_gnu_stack = false;
   // The flags of a .note.GNU-stack section.
@@ -926,7 +972,7 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
        {
          // Do not include this section in the link.
          out_sections[i] = NULL;
-          out_section_offsets[i] = -1U;
+          out_section_offsets[i] = invalid_address;
          continue;
        }
 
@@ -960,22 +1006,22 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
          continue;
        }
 
-      off_t offset;
-      Output_section* os = layout->layout(this, i, name, shdr,
-                                         reloc_shndx[i], reloc_type[i],
-                                         &offset);
-
-      out_sections[i] = os;
-      if (offset == -1)
-        out_section_offsets[i] = -1U;
+      if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
+        {
+          this->deferred_layout_.push_back(Deferred_layout(i, name, pshdrs,
+                                                           reloc_shndx[i],
+                                                           reloc_type[i]));
+
+          // Put dummy values here; real values will be supplied by
+          // do_layout_deferred_sections.
+          out_sections[i] = reinterpret_cast<Output_section*>(1);
+          out_section_offsets[i] = invalid_address;
+        }
       else
-        out_section_offsets[i] = convert_types<Address, off_t>(offset);
-
-      // If this section requires special handling, and if there are
-      // relocs that apply to it, then we must do the special handling
-      // before we apply the relocs.
-      if (offset == -1 && reloc_shndx[i] != 0)
-       this->set_relocs_must_follow_section_writes();
+        {
+          this->layout_section(layout, i, name, shdr, reloc_shndx[i],
+                               reloc_type[i]);
+        }
     }
 
   layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags);
@@ -1004,7 +1050,7 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
       if (data_section == NULL)
        {
          out_sections[i] = NULL;
-          out_section_offsets[i] = -1U;
+          out_section_offsets[i] = invalid_address;
          continue;
        }
 
@@ -1014,7 +1060,7 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
       Output_section* os = layout->layout_reloc(this, i, shdr, data_section,
                                                rr);
       out_sections[i] = os;
-      out_section_offsets[i] = -1U;
+      out_section_offsets[i] = invalid_address;
     }
 
   // Handle the .eh_frame sections at the end.
@@ -1042,7 +1088,7 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
                                                   &offset);
       out_sections[i] = os;
       if (offset == -1)
-        out_section_offsets[i] = -1U;
+        out_section_offsets[i] = invalid_address;
       else
         out_section_offsets[i] = convert_types<Address, off_t>(offset);
 
@@ -1059,6 +1105,27 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
   sd->section_names = NULL;
 }
 
+// Layout sections whose layout was deferred while waiting for
+// input files from a plugin.
+
+template<int size, bool big_endian>
+void
+Sized_relobj<size, big_endian>::do_layout_deferred_sections(Layout* layout)
+{
+  typename std::vector<Deferred_layout>::iterator deferred;
+
+  for (deferred = this->deferred_layout_.begin();
+       deferred != this->deferred_layout_.end();
+       ++deferred)
+    {
+      typename This::Shdr shdr(deferred->shdr_data_);
+      this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(),
+                           shdr, deferred->reloc_shndx_, deferred->reloc_type_);
+    }
+
+  this->deferred_layout_.clear();
+}
+
 // Add the symbols to the symbol table.
 
 template<int size, bool big_endian>
@@ -1266,7 +1333,7 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
               // so we leave the input value unchanged here.
              continue;
            }
-         else if (out_offsets[shndx] == -1U)
+         else if (out_offsets[shndx] == invalid_address)
            {
              // This is a SHF_MERGE section or one which otherwise
              // requires special handling.  We get the output address
@@ -1349,9 +1416,13 @@ Sized_relobj<size, big_endian>::write_local_symbols(
     Output_symtab_xindex* symtab_xindex,
     Output_symtab_xindex* dynsym_xindex)
 {
-  if (parameters->options().strip_all()
-      && this->output_local_dynsym_count_ == 0)
-    return;
+  const bool strip_all = parameters->options().strip_all();
+  if (strip_all)
+    {
+      if (this->output_local_dynsym_count_ == 0)
+       return;
+      this->output_local_symbol_count_ = 0;
+    }
 
   gold_assert(this->symtab_shndx_ != -1U);
   if (this->symtab_shndx_ == 0)
@@ -1420,7 +1491,7 @@ Sized_relobj<size, big_endian>::write_local_symbols(
          st_shndx = out_sections[st_shndx]->out_shndx();
          if (st_shndx >= elfcpp::SHN_LORESERVE)
            {
-             if (lv.needs_output_symtab_entry())
+             if (lv.needs_output_symtab_entry() && !strip_all)
                symtab_xindex->add(lv.output_symtab_index(), st_shndx);
              if (lv.needs_output_dynsym_entry())
                dynsym_xindex->add(lv.output_dynsym_index(), st_shndx);
@@ -1429,8 +1500,7 @@ Sized_relobj<size, big_endian>::write_local_symbols(
        }
 
       // Write the symbol to the output symbol table.
-      if (!parameters->options().strip_all()
-         && lv.needs_output_symtab_entry())
+      if (!strip_all && lv.needs_output_symtab_entry())
         {
           elfcpp::Sym_write<size, big_endian> osym(ov);
 
@@ -1573,7 +1643,7 @@ Sized_relobj<size, big_endian>::map_to_kept_section(
       *found = true;
       Output_section* os = kept->object_->output_section(kept->shndx_);
       Address offset = kept->object_->get_output_section_offset(kept->shndx_);
-      gold_assert(os != NULL && offset != -1U);
+      gold_assert(os != NULL && offset != invalid_address);
       return os->address() + offset;
     }
   *found = false;