mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-21 01:12:32 +08:00
Correctly handle alignment in merge sections.
This commit is contained in:
parent
ba32f9896b
commit
87f9577614
@ -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
|
||||
|
18
gold/merge.h
18
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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user