gdb/testsuite/
[binutils-gdb.git] / gold / merge.cc
index 654f3495fee34a3ee727e1a0ad518706b5197797..6e44ddd44711440aa3b385a0c8531ea80c00bb5a 100644 (file)
@@ -289,10 +289,10 @@ Merge_map::is_merge_section_for(const Relobj* object, unsigned int shndx) const
 bool
 Output_merge_base::do_output_offset(const Relobj* object,
                                    unsigned int shndx,
-                                   section_offset_type off,
+                                   section_offset_type offset,
                                    section_offset_type* poutput) const
 {
-  return this->merge_map_.get_output_offset(object, shndx, off, poutput);
+  return this->merge_map_.get_output_offset(object, shndx, offset, poutput);
 }
 
 // Return whether this is the merge section for SHNDX in OBJECT.
@@ -304,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.
@@ -354,10 +374,10 @@ Output_merge_data::Merge_data_eq::operator()(Merge_data_key k1,
 void
 Output_merge_data::add_constant(const unsigned char* p)
 {
-  section_size_type ent_size = convert_to_section_size_type(this->entsize());
-  section_size_type addr_align =
+  section_size_type entsize = convert_to_section_size_type(this->entsize());
+  section_size_type addralign =
     convert_to_section_size_type(this->addralign());
-  section_size_type addsize = std::max(ent_size, addr_align);
+  section_size_type addsize = std::max(entsize, addralign);
   if (this->len_ + addsize > this->alc_)
     {
       if (this->alc_ == 0)
@@ -369,9 +389,9 @@ Output_merge_data::add_constant(const unsigned char* p)
        gold_nomem();
     }
 
-  memcpy(this->p_ + this->len_, p, ent_size);
-  if (addsize > ent_size)
-    memset(this->p_ + this->len_ + ent_size, 0, addsize - ent_size);
+  memcpy(this->p_ + this->len_, p, entsize);
+  if (addsize > entsize)
+    memset(this->p_ + this->len_ + entsize, 0, addsize - entsize);
   this->len_ += addsize;
 }
 
@@ -386,14 +406,14 @@ Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
   section_size_type len;
   const unsigned char* p = object->section_contents(shndx, &len, false);
 
-  section_size_type ent_size = convert_to_section_size_type(this->entsize());
+  section_size_type entsize = convert_to_section_size_type(this->entsize());
 
-  if (len % ent_size != 0)
+  if (len % entsize != 0)
     return false;
 
-  this->input_count_ += len / ent_size;
+  this->input_count_ += len / entsize;
 
-  for (section_size_type i = 0; i < len; i += ent_size, p += ent_size)
+  for (section_size_type i = 0; i < len; i += entsize, p += entsize)
     {
       // Add the constant to the section contents.  If we find that it
       // is already in the hash table, we will remove it again.
@@ -406,14 +426,18 @@ Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
       if (!ins.second)
        {
          // Key was already present.  Remove the copy we just added.
-         this->len_ -= ent_size;
+         this->len_ -= entsize;
          k = *ins.first;
        }
 
       // Record the offset of this constant in the output section.
-      this->add_mapping(object, shndx, i, ent_size, k);
+      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;
 }
 
@@ -425,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_);
 }
 
@@ -514,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;
 }
 
@@ -531,9 +562,9 @@ Output_merge_string<Char_type>::finalize_merged_data()
        p != this->merged_strings_.end();
        ++p)
     {
-      section_offset_type soffset =
+      section_offset_type offset =
        this->stringpool_.get_offset_from_key(p->stringpool_key);
-      this->add_mapping(p->object, p->shndx, p->offset, p->length, soffset);
+      this->add_mapping(p->object, p->shndx, p->offset, p->length, offset);
     }
 
   // Save some memory.  This also ensures that this function will work