#include "gold.h"
#include <cstdlib>
+#include <algorithm>
#include "merge.h"
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_));
}
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
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.
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))
{ }
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
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
{
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;
// 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.