Correctly handle alignment in merge sections.

This commit is contained in:
Ian Lance Taylor 2007-10-18 17:46:23 +00:00
parent ba32f9896b
commit 87f9577614
4 changed files with 32 additions and 21 deletions

View 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

View 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

View 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;

View 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.