Workaround a C++ bug in GCC 4.2 in gold test
[deliverable/binutils-gdb.git] / gold / output.cc
index 516e01daff1e8de30a737b01be218168f5d4da6a..077e2c4481ecb8445028c773eba51506846e957e 100644 (file)
@@ -1,6 +1,6 @@
 // output.cc -- manage the output file for gold
 
-// Copyright (C) 2006-2015 Free Software Foundation, Inc.
+// Copyright (C) 2006-2016 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -1252,6 +1252,19 @@ Output_data_reloc_base<sh_type, dynamic, size, big_endian>
     os->set_should_link_to_dynsym();
 }
 
+// Standard relocation writer, which just calls Output_reloc::write().
+
+template<int sh_type, bool dynamic, int size, bool big_endian>
+struct Output_reloc_writer
+{
+  typedef Output_reloc<sh_type, dynamic, size, big_endian> Output_reloc_type;
+  typedef std::vector<Output_reloc_type> Relocs;
+
+  static void
+  write(typename Relocs::const_iterator p, unsigned char* pov)
+  { p->write(pov); }
+};
+
 // Write out relocation data.
 
 template<int sh_type, bool dynamic, int size, bool big_endian>
@@ -1259,32 +1272,8 @@ void
 Output_data_reloc_base<sh_type, dynamic, size, big_endian>::do_write(
     Output_file* of)
 {
-  const off_t off = this->offset();
-  const off_t oview_size = this->data_size();
-  unsigned char* const oview = of->get_output_view(off, oview_size);
-
-  if (this->sort_relocs())
-    {
-      gold_assert(dynamic);
-      std::sort(this->relocs_.begin(), this->relocs_.end(),
-               Sort_relocs_comparison());
-    }
-
-  unsigned char* pov = oview;
-  for (typename Relocs::const_iterator p = this->relocs_.begin();
-       p != this->relocs_.end();
-       ++p)
-    {
-      p->write(pov);
-      pov += reloc_size;
-    }
-
-  gold_assert(pov - oview == oview_size);
-
-  of->write_output_view(off, oview_size, oview);
-
-  // We no longer need the relocation entries.
-  this->relocs_.clear();
+  typedef Output_reloc_writer<sh_type, dynamic, size, big_endian> Writer;
+  this->do_write_generic<Writer>(of);
 }
 
 // Class Output_relocatable_relocs.
@@ -1437,7 +1426,7 @@ Output_data_got<got_size, big_endian>::Got_entry::write(
          val = parameters->target().plt_address_for_local(object, lsi);
        else
          {
-           uint64_t lval = object->local_symbol_value(lsi, 0);
+           uint64_t lval = object->local_symbol_value(lsi, this->addend_);
            val = convert_types<Valtype, uint64_t>(lval);
            if (this->use_plt_or_tls_offset_ && is_tls)
              val += parameters->target().tls_offset_for_local(object, lsi,
@@ -1548,6 +1537,27 @@ Output_data_got<got_size, big_endian>::add_local(
   return true;
 }
 
+// Add an entry for a local symbol plus ADDEND to the GOT.  This returns
+// true if this is a new GOT entry, false if the symbol already has a GOT
+// entry.
+
+template<int got_size, bool big_endian>
+bool
+Output_data_got<got_size, big_endian>::add_local(
+    Relobj* object,
+    unsigned int symndx,
+    unsigned int got_type,
+    uint64_t addend)
+{
+  if (object->local_has_got_offset(symndx, got_type, addend))
+    return false;
+
+  unsigned int got_offset = this->add_got_entry(Got_entry(object, symndx,
+                                                         false, addend));
+  object->set_local_got_offset(symndx, got_type, got_offset, addend);
+  return true;
+}
+
 // Like add_local, but use the PLT offset.
 
 template<int got_size, bool big_endian>
@@ -1586,6 +1596,27 @@ Output_data_got<got_size, big_endian>::add_local_with_rel(
   rel_dyn->add_local_generic(object, symndx, r_type, this, got_offset, 0);
 }
 
+// Add an entry for a local symbol plus ADDEND to the GOT, and add a dynamic
+// relocation of type R_TYPE for the GOT entry.
+
+template<int got_size, bool big_endian>
+void
+Output_data_got<got_size, big_endian>::add_local_with_rel(
+    Relobj* object,
+    unsigned int symndx,
+    unsigned int got_type,
+    Output_data_reloc_generic* rel_dyn,
+    unsigned int r_type, uint64_t addend)
+{
+  if (object->local_has_got_offset(symndx, got_type, addend))
+    return;
+
+  unsigned int got_offset = this->add_got_entry(Got_entry());
+  object->set_local_got_offset(symndx, got_type, got_offset, addend);
+  rel_dyn->add_local_generic(object, symndx, r_type, this, got_offset,
+                             addend);
+}
+
 // Add a pair of entries for a local symbol to the GOT, and add
 // a dynamic relocation of type R_TYPE using the section symbol of
 // the output section to which input section SHNDX maps, on the first.
@@ -1612,6 +1643,32 @@ Output_data_got<got_size, big_endian>::add_local_pair_with_rel(
   rel_dyn->add_output_section_generic(os, r_type, this, got_offset, 0);
 }
 
+// Add a pair of entries for a local symbol plus ADDEND to the GOT, and add
+// a dynamic relocation of type R_TYPE using the section symbol of
+// the output section to which input section SHNDX maps, on the first.
+// The first got entry will have a value of zero, the second the
+// value of the local symbol.
+template<int got_size, bool big_endian>
+void
+Output_data_got<got_size, big_endian>::add_local_pair_with_rel(
+    Relobj* object,
+    unsigned int symndx,
+    unsigned int shndx,
+    unsigned int got_type,
+    Output_data_reloc_generic* rel_dyn,
+    unsigned int r_type, uint64_t addend)
+{
+  if (object->local_has_got_offset(symndx, got_type, addend))
+    return;
+
+  unsigned int got_offset =
+      this->add_got_entry_pair(Got_entry(),
+                              Got_entry(object, symndx, false, addend));
+  object->set_local_got_offset(symndx, got_type, got_offset, addend);
+  Output_section* os = object->output_section(shndx);
+  rel_dyn->add_output_section_generic(os, r_type, this, got_offset, addend);
+}
+
 // Add a pair of entries for a local symbol to the GOT, and add
 // a dynamic relocation of type R_TYPE using STN_UNDEF on the first.
 // The first got entry will have a value of zero, the second the
@@ -2201,18 +2258,6 @@ Output_section::Input_section::output_offset(
     }
 }
 
-// Return whether this is the merge section for the input section
-// SHNDX in OBJECT.
-
-inline bool
-Output_section::Input_section::is_merge_section_for(const Relobj* object,
-                                                   unsigned int shndx) const
-{
-  if (this->is_input_section())
-    return false;
-  return object->is_merge_section_for(this->u2_.posd, shndx);
-}
-
 // Write out the data.  We don't have to do anything for an input
 // section--they are handled via Object::relocate--but this is where
 // we write out the data for an Output_section_data.
@@ -2698,9 +2743,6 @@ Output_section::add_merge_input_section(Relobj* object, unsigned int shndx,
          this->lookup_maps_->add_merge_section(msp, pomb);
        }
 
-      // Add input section to new merge section and link input section to new
-      // merge section in map.
-      this->lookup_maps_->add_merge_input_section(object, shndx, pomb);
       return true;
     }
   else
@@ -2857,17 +2899,15 @@ Output_section::update_flags_for_input_section(elfcpp::Elf_Xword flags)
 // Find the merge section into which an input section with index SHNDX in
 // OBJECT has been added.  Return NULL if none found.
 
-Output_section_data*
+const Output_section_data*
 Output_section::find_merge_section(const Relobj* object,
                                   unsigned int shndx) const
 {
-  if (!this->lookup_maps_->is_valid())
-    this->build_lookup_maps();
-  return this->lookup_maps_->find_merge_section(object, shndx);
+  return object->find_merge_section(shndx);
 }
 
-// Build the lookup maps for merge and relaxed sections.  This is needs
-// to be declared as a const methods so that it is callable with a const
+// Build the lookup maps for relaxed sections.  This needs
+// to be declared as a const method so that it is callable with a const
 // Output_section pointer.  The method only updates states of the maps.
 
 void
@@ -2878,24 +2918,7 @@ Output_section::build_lookup_maps() const
        p != this->input_sections_.end();
        ++p)
     {
-      if (p->is_merge_section())
-       {
-         Output_merge_base* pomb = p->output_merge_base();
-         Merge_section_properties msp(pomb->is_string(), pomb->entsize(),
-                                      pomb->addralign());
-         this->lookup_maps_->add_merge_section(msp, pomb);
-         for (Output_merge_base::Input_sections::const_iterator is =
-                pomb->input_sections_begin();
-              is != pomb->input_sections_end();
-              ++is)
-           {
-             const Const_section_id& csid = *is;
-           this->lookup_maps_->add_merge_input_section(csid.first,
-                                                       csid.second, pomb);
-           }
-
-       }
-      else if (p->is_relaxed_input_section())
+      if (p->is_relaxed_input_section())
        {
          Output_relaxed_input_section* poris = p->relaxed_input_section();
          this->lookup_maps_->add_relaxed_input_section(poris->relobj(),
@@ -2935,7 +2958,10 @@ Output_section::is_input_address_mapped(const Relobj* object,
     {
       section_offset_type output_offset;
       bool found = posd->output_offset(object, shndx, offset, &output_offset);
-      gold_assert(found);
+      // By default we assume that the address is mapped. See comment at the
+      // end.
+      if (!found)
+        return true;
       return output_offset != -1;
     }
 
@@ -3045,6 +3071,10 @@ Output_section::find_starting_output_address(const Relobj* object,
                                             unsigned int shndx,
                                             uint64_t* paddr) const
 {
+  const Output_section_data* data = this->find_merge_section(object, shndx);
+  if (data == NULL)
+    return false;
+
   // FIXME: This becomes a bottle-neck if we have many relaxed sections.
   // Looking up the merge section map does not always work as we sometimes
   // find a merge section without its address set.
@@ -3059,7 +3089,7 @@ Output_section::find_starting_output_address(const Relobj* object,
       // method to get the output offset of input offset 0.
       // Unfortunately we don't know for sure that input offset 0 is
       // mapped at all.
-      if (p->is_merge_section_for(object, shndx))
+      if (!p->is_input_section() && p->output_section_data() == data)
        {
          *paddr = addr;
          return true;
@@ -3530,7 +3560,7 @@ Output_section::update_section_layout(
       if (p->is_input_section()
          || p->is_relaxed_input_section())
        {
-         Object* obj = (p->is_input_section()
+         Relobj* obj = (p->is_input_section()
                         ? p->relobj()
                         : p->relaxed_input_section()->relobj());
          unsigned int shndx = p->shndx();
@@ -3885,20 +3915,7 @@ Output_section::add_script_input_section(const Input_section& sis)
   // Update fast lookup maps if necessary.
   if (this->lookup_maps_->is_valid())
     {
-      if (sis.is_merge_section())
-       {
-         Output_merge_base* pomb = sis.output_merge_base();
-         Merge_section_properties msp(pomb->is_string(), pomb->entsize(),
-                                      pomb->addralign());
-         this->lookup_maps_->add_merge_section(msp, pomb);
-         for (Output_merge_base::Input_sections::const_iterator p =
-                pomb->input_sections_begin();
-              p != pomb->input_sections_end();
-              ++p)
-           this->lookup_maps_->add_merge_input_section(p->first, p->second,
-                                                       pomb);
-       }
-      else if (sis.is_relaxed_input_section())
+      if (sis.is_relaxed_input_section())
        {
          Output_relaxed_input_section* poris = sis.relaxed_input_section();
          this->lookup_maps_->add_relaxed_input_section(poris->relobj(),
This page took 0.030353 seconds and 4 git commands to generate.