gdb/testsuite/
[binutils-gdb.git] / gold / object.cc
index b9d00280cec05733a198d80a4658047ab97347aa..b034ee209acc311f13516cbaec15c1cc6a538b3f 100644 (file)
 namespace gold
 {
 
+// Struct Read_symbols_data.
+
+// Destroy any remaining File_view objects.
+
+Read_symbols_data::~Read_symbols_data()
+{
+  if (this->section_headers != NULL)
+    delete this->section_headers;
+  if (this->section_names != NULL)
+    delete this->section_names;
+  if (this->symbols != NULL)
+    delete this->symbols;
+  if (this->symbol_names != NULL)
+    delete this->symbol_names;
+  if (this->versym != NULL)
+    delete this->versym;
+  if (this->verdef != NULL)
+    delete this->verdef;
+  if (this->verneed != NULL)
+    delete this->verneed;
+}
+
 // Class Xindex.
 
 // Initialize the symtab_xindex_ array.  Find the SHT_SYMTAB_SHNDX
@@ -1349,6 +1371,17 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
        }
 
       Output_section* data_section = out_sections[data_shndx];
+      if (data_section == reinterpret_cast<Output_section*>(2))
+        {
+          // The layout for the data section was deferred, so we need
+          // to defer the relocation section, too.
+         const char* name = pnames + shdr.get_sh_name();
+          this->deferred_layout_relocs_.push_back(
+              Deferred_layout(i, name, pshdr, 0, elfcpp::SHT_NULL));
+         out_sections[i] = reinterpret_cast<Output_section*>(2);
+          out_section_offsets[i] = invalid_address;
+          continue;
+        }
       if (data_section == NULL)
        {
          out_sections[i] = NULL;
@@ -1439,11 +1472,46 @@ Sized_relobj<size, big_endian>::do_layout_deferred_sections(Layout* layout)
        ++deferred)
     {
       typename This::Shdr shdr(deferred->shdr_data_);
+      // If the section is not included, it is because the garbage collector
+      // decided it is not needed.  Avoid reverting that decision.
+      if (!this->is_section_included(deferred->shndx_))
+        continue;
+
       this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(),
                            shdr, deferred->reloc_shndx_, deferred->reloc_type_);
     }
 
   this->deferred_layout_.clear();
+
+  // Now handle the deferred relocation sections.
+
+  Output_sections& out_sections(this->output_sections());
+  std::vector<Address>& out_section_offsets(this->section_offsets_);
+
+  for (deferred = this->deferred_layout_relocs_.begin();
+       deferred != this->deferred_layout_relocs_.end();
+       ++deferred)
+    {
+      unsigned int shndx = deferred->shndx_;
+      typename This::Shdr shdr(deferred->shdr_data_);
+      unsigned int data_shndx = this->adjust_shndx(shdr.get_sh_info());
+
+      Output_section* data_section = out_sections[data_shndx];
+      if (data_section == NULL)
+       {
+         out_sections[shndx] = NULL;
+          out_section_offsets[shndx] = invalid_address;
+         continue;
+       }
+
+      Relocatable_relocs* rr = new Relocatable_relocs();
+      this->set_relocatable_relocs(shndx, rr);
+
+      Output_section* os = layout->layout_reloc(this, shndx, shdr,
+                                               data_section, rr);
+      out_sections[shndx] = os;
+      out_section_offsets[shndx] = invalid_address;
+    }
 }
 
 // Add the symbols to the symbol table.
@@ -1800,7 +1868,12 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
                  const Output_section_data* posd =
                    os->find_relaxed_input_section(this, shndx);
                  if (posd != NULL)
-                   lv.set_output_value(posd->address());
+                   {
+                     Address relocatable_link_adjustment =
+                       relocatable ? os->address() : 0;
+                     lv.set_output_value(posd->address()
+                                         - relocatable_link_adjustment);
+                   }
                  else
                    lv.set_output_value(os->address());
                }
@@ -1808,9 +1881,14 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index,
                {
                  // We have to consider the addend to determine the
                  // value to use in a relocation.  START is the start
-                 // of this input section.
+                 // of this input section.  If we are doing a relocatable
+                 // link, use offset from start output section instead of
+                 // address.
+                 Address adjusted_start =
+                   relocatable ? start - os->address() : start;
                  Merged_symbol_value<size>* msv =
-                   new Merged_symbol_value<size>(lv.input_value(), start);
+                   new Merged_symbol_value<size>(lv.input_value(),
+                                                 adjusted_start);
                  lv.set_merged_symbol_value(msv);
                }
            }