From 87f9577614a90f155dcdf59864d21dbc3f106469 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 18 Oct 2007 17:46:23 +0000 Subject: [PATCH] Correctly handle alignment in merge sections. --- gold/merge.cc | 10 +++++++--- gold/merge.h | 18 +++++++++++------- gold/output.cc | 19 ++++++++++--------- gold/output.h | 6 ++++-- 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/gold/merge.cc b/gold/merge.cc index f31b44e8055..b5c836f5f77 100644 --- a/gold/merge.cc +++ b/gold/merge.cc @@ -23,6 +23,7 @@ #include "gold.h" #include +#include #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(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 ab382a11659..cc554f26f4d 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 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 9aaa7e97410..acba77ce459 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(); + posd = new Output_merge_string(addralign); else if (entsize == 2) - posd = new Output_merge_string(); + posd = new Output_merge_string(addralign); else if (entsize == 4) - posd = new Output_merge_string(); + posd = new Output_merge_string(addralign); else return false; diff --git a/gold/output.h b/gold/output.h index c525a329c03..a615a71150e 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.