gdb/testsuite/
[binutils-gdb.git] / gold / merge.cc
index 25ecc40c0e17c14b7ef6605a98ad6c3f7065912a..6e44ddd44711440aa3b385a0c8531ea80c00bb5a 100644 (file)
@@ -204,6 +204,12 @@ Object_merge_map::initialize_input_to_output_map(
   Input_merge_map* map = this->get_input_merge_map(shndx);
   gold_assert(map != NULL);
 
+  gold_assert(initialize_map->empty());
+  // We know how many entries we are going to add.
+  // reserve_unordered_map takes an expected count of buckets, not a
+  // count of elements, so double it to try to reduce collisions.
+  reserve_unordered_map(initialize_map, map->entries.size() * 2);
+
   for (Input_merge_map::Entries::const_iterator p = map->entries.begin();
        p != map->entries.end();
        ++p)
@@ -298,6 +304,26 @@ Output_merge_base::do_is_merge_section_for(const Relobj* object,
   return this->merge_map_.is_merge_section_for(object, shndx);
 }
 
+// Record a merged input section for script processing.
+
+void
+Output_merge_base::record_input_section(Relobj* relobj, unsigned int shndx)
+{
+  gold_assert(this->keeps_input_sections_ && relobj != NULL);
+  // If this is the first input section, record it.  We need do this because
+  // this->input_sections_ is unordered.
+  if (this->first_relobj_ == NULL)
+    {
+      this->first_relobj_ = relobj;
+      this->first_shndx_ = shndx;
+    }
+
+  std::pair<Input_sections::iterator, bool> result =
+    this->input_sections_.insert(Section_id(relobj, shndx));
+  // We should insert a merge section once only.
+  gold_assert(result.second);
+}
+
 // Class Output_merge_data.
 
 // Compute the hash code for a fixed-size constant.
@@ -408,6 +434,10 @@ Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
       this->add_mapping(object, shndx, i, entsize, k);
     }
 
+  // For script processing, we keep the input sections.
+  if (this->keeps_input_sections())
+    record_input_section(object, shndx);
+
   return true;
 }
 
@@ -419,7 +449,10 @@ Output_merge_data::set_final_data_size()
 {
   // Release the memory we don't need.
   this->p_ = static_cast<unsigned char*>(realloc(this->p_, this->len_));
-  gold_assert(this->p_ != NULL);
+  // An Output_merge_data object may be empty and realloc is allowed
+  // to return a NULL pointer in this case.  An Output_merge_data is empty
+  // if all its input sections have sizes that are not multiples of entsize.
+  gold_assert(this->p_ != NULL || this->len_ == 0);
   this->set_data_size(this->len_);
 }
 
@@ -508,6 +541,10 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
 
   this->input_count_ += count;
 
+  // For script processing, we keep the input sections.
+  if (this->keeps_input_sections())
+    record_input_section(object, shndx);
+
   return true;
 }