Correctly handle alignment in merge sections.
authorIan Lance Taylor <iant@google.com>
Thu, 18 Oct 2007 17:46:23 +0000 (17:46 +0000)
committerIan Lance Taylor <iant@google.com>
Thu, 18 Oct 2007 17:46:23 +0000 (17:46 +0000)
gold/merge.cc
gold/merge.h
gold/output.cc
gold/output.h

index f31b44e805517f2da03259b1fec1d4b43d428287..b5c836f5f77e572ddc750815f933483c1c166b82 100644 (file)
@@ -23,6 +23,7 @@
 #include "gold.h"
 
 #include <cstdlib>
+#include <algorithm>
 
 #include "merge.h"
 
@@ -161,10 +162,11 @@ void
 Output_merge_data::add_constant(const unsigned char* p)
 {
   uint64_t entsize = this->entsize();
-  if (this->len_ + entsize > this->alc_)
+  uint64_t addsize = std::max(entsize, this->addralign());
+  if (this->len_ + addsize > this->alc_)
     {
       if (this->alc_ == 0)
-       this->alc_ = 128 * entsize;
+       this->alc_ = 128 * addsize;
       else
        this->alc_ *= 2;
       this->p_ = static_cast<unsigned char*>(realloc(this->p_, this->alc_));
@@ -173,7 +175,9 @@ Output_merge_data::add_constant(const unsigned char* p)
     }
 
   memcpy(this->p_ + this->len_, p, entsize);
-  this->len_ += entsize;
+  if (addsize > entsize)
+    memset(this->p_ + this->len_ + entsize, 0, addsize - entsize);
+  this->len_ += addsize;
 }
 
 // Add the input section SHNDX in OBJECT to a merged output section
index ab382a1165907274f707b14d581b2478f36a94ed..cc554f26f4dc3cc964a22dbfed692f826cab93b1 100644 (file)
@@ -37,8 +37,8 @@ namespace gold
 class Output_merge_base : public Output_section_data
 {
  public:
-  Output_merge_base(uint64_t entsize)
-    : Output_section_data(1), merge_map_(), entsize_(entsize)
+  Output_merge_base(uint64_t entsize, uint64_t addralign)
+    : Output_section_data(addralign), merge_map_(), entsize_(entsize)
   { }
 
   // Return the output address for an input address.
@@ -90,8 +90,8 @@ class Output_merge_base : public Output_section_data
 class Output_merge_data : public Output_merge_base
 {
  public:
-  Output_merge_data(uint64_t entsize)
-    : Output_merge_base(entsize), p_(NULL), len_(0), alc_(0),
+  Output_merge_data(uint64_t entsize, uint64_t addralign)
+    : Output_merge_base(entsize, addralign), p_(NULL), len_(0), alc_(0),
       hashtable_(128, Merge_data_hash(this), Merge_data_eq(this))
   { }
 
@@ -188,9 +188,13 @@ template<typename Char_type>
 class Output_merge_string : public Output_merge_base
 {
  public:
-  Output_merge_string()
-    : Output_merge_base(sizeof(Char_type)), stringpool_(), merged_strings_()
-  { this->stringpool_.set_no_zero_null(); }
+  Output_merge_string(uint64_t addralign)
+    : Output_merge_base(sizeof(Char_type), addralign), stringpool_(),
+      merged_strings_()
+  {
+    gold_assert(addralign <= sizeof(Char_type));
+    this->stringpool_.set_no_zero_null();
+  }
 
   // Add an input section.
   bool
index 9aaa7e97410f994b46044fb65804e12fe83640bf..acba77ce4595594ecf3dc7dc83bef192b45d682e 100644 (file)
@@ -1137,17 +1137,18 @@ Output_section::add_merge_input_section(Relobj* object, unsigned int shndx,
                                        uint64_t flags, uint64_t entsize,
                                        uint64_t addralign)
 {
-  // We only merge constants if the alignment is not more than the
-  // entry size.  This could be handled, but it's unusual.
-  if (addralign > entsize)
+  bool is_string = (flags & elfcpp::SHF_STRINGS) != 0;
+
+  // We only merge strings if the alignment is not more than the
+  // character size.  This could be handled, but it's unusual.
+  if (is_string && addralign > entsize)
     return false;
 
-  bool is_string = (flags & elfcpp::SHF_STRINGS) != 0;
   Input_section_list::iterator p;
   for (p = this->input_sections_.begin();
        p != this->input_sections_.end();
        ++p)
-    if (p->is_merge_section(is_string, entsize))
+    if (p->is_merge_section(is_string, entsize, addralign))
       break;
 
   // We handle the actual constant merging in Output_merge_data or
@@ -1158,13 +1159,13 @@ Output_section::add_merge_input_section(Relobj* object, unsigned int shndx,
     {
       Output_section_data* posd;
       if (!is_string)
-       posd = new Output_merge_data(entsize);
+       posd = new Output_merge_data(entsize, addralign);
       else if (entsize == 1)
-       posd = new Output_merge_string<char>();
+       posd = new Output_merge_string<char>(addralign);
       else if (entsize == 2)
-       posd = new Output_merge_string<uint16_t>();
+       posd = new Output_merge_string<uint16_t>(addralign);
       else if (entsize == 4)
-       posd = new Output_merge_string<uint32_t>();
+       posd = new Output_merge_string<uint32_t>(addralign);
       else
        return false;
 
index c525a329c038c78633c10b58c6f2f3ad6954be77..a615a71150eae6f5ff50776353418e8bb0345b42 100644 (file)
@@ -1436,12 +1436,14 @@ class Output_section : public Output_data
     // Return whether this is a merge section which matches the
     // parameters.
     bool
-    is_merge_section(bool is_string, uint64_t entsize) const
+    is_merge_section(bool is_string, uint64_t entsize,
+                     uint64_t addralign) const
     {
       return (this->shndx_ == (is_string
                               ? MERGE_STRING_SECTION_CODE
                               : MERGE_DATA_SECTION_CODE)
-             && this->u1_.entsize == entsize);
+             && this->u1_.entsize == entsize
+              && this->addralign() == addralign);
     }
 
     // Set the output section.