aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2007-10-18 17:46:23 +0000
committerIan Lance Taylor <iant@google.com>2007-10-18 17:46:23 +0000
commit87f9577614a90f155dcdf59864d21dbc3f106469 (patch)
treef8c50dbd3e92c4a509c500608e9510e666cc0904
parentba32f9896b4b1e79f36ae03ac383869127a461e0 (diff)
downloadgdb-87f9577614a90f155dcdf59864d21dbc3f106469.zip
gdb-87f9577614a90f155dcdf59864d21dbc3f106469.tar.gz
gdb-87f9577614a90f155dcdf59864d21dbc3f106469.tar.bz2
Correctly handle alignment in merge sections.
-rw-r--r--gold/merge.cc10
-rw-r--r--gold/merge.h18
-rw-r--r--gold/output.cc19
-rw-r--r--gold/output.h6
4 files changed, 32 insertions, 21 deletions
diff --git a/gold/merge.cc b/gold/merge.cc
index f31b44e..b5c836f 100644
--- a/gold/merge.cc
+++ b/gold/merge.cc
@@ -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
diff --git a/gold/merge.h b/gold/merge.h
index ab382a1..cc554f2 100644
--- a/gold/merge.h
+++ b/gold/merge.h
@@ -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
diff --git a/gold/output.cc b/gold/output.cc
index 9aaa7e9..acba77c 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -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;
diff --git a/gold/output.h b/gold/output.h
index c525a32..a615a71 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -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.