H.J. Lu
2018-11-29 13:38:52 UTC
The ELF compression header has a field (ch_addralign) that is set to
the alignment of the uncompressed section. This way the section itself
can have a different alignment than the decompressed section. Update
decompress_input_section to get alignment of the decompressed section
and use it when merging decompressed strings.
PR binutils/23919
* compressed_output.cc (decompress_input_section): Add a palign
argument and store ch_addralign in *palign if it isn't NULL.
* compressed_output.h (decompress_input_section): Add a palign
argument and default it to NULL.
* merge.cc (Output_merge_string<Char_type>::do_add_input_section):
Get addralign from decompress_input_section.
* object.cc (Object::decompressed_section_contents): Add a palign
argument and pass it to decompress_input_section.
* object.h (Object::decompressed_section_contents): Add a palign
argument and default it to NULL.
---
gold/compressed_output.cc | 11 ++++++++++-
gold/compressed_output.h | 3 ++-
gold/merge.cc | 8 +++++---
gold/object.cc | 6 ++++--
gold/object.h | 2 +-
5 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/gold/compressed_output.cc b/gold/compressed_output.cc
index 4b3e09512a..590e1c1e36 100644
--- a/gold/compressed_output.cc
+++ b/gold/compressed_output.cc
@@ -143,7 +143,8 @@ decompress_input_section(const unsigned char* compressed_data,
unsigned long uncompressed_size,
int size,
bool big_endian,
- elfcpp::Elf_Xword sh_flags)
+ elfcpp::Elf_Xword sh_flags,
+ uint64_t *palign)
{
if ((sh_flags & elfcpp::SHF_COMPRESSED) != 0)
{
@@ -156,12 +157,16 @@ decompress_input_section(const unsigned char* compressed_data,
elfcpp::Chdr<32, true> chdr(compressed_data);
if (chdr.get_ch_type() != elfcpp::ELFCOMPRESS_ZLIB)
return false;
+ if (palign)
+ *palign = chdr.get_ch_addralign();
}
else
{
elfcpp::Chdr<32, false> chdr(compressed_data);
if (chdr.get_ch_type() != elfcpp::ELFCOMPRESS_ZLIB)
return false;
+ if (palign)
+ *palign = chdr.get_ch_addralign();
}
}
else if (size == 64)
@@ -172,12 +177,16 @@ decompress_input_section(const unsigned char* compressed_data,
elfcpp::Chdr<64, true> chdr(compressed_data);
if (chdr.get_ch_type() != elfcpp::ELFCOMPRESS_ZLIB)
return false;
+ if (palign)
+ *palign = chdr.get_ch_addralign();
}
else
{
elfcpp::Chdr<64, false> chdr(compressed_data);
if (chdr.get_ch_type() != elfcpp::ELFCOMPRESS_ZLIB)
return false;
+ if (palign)
+ *palign = chdr.get_ch_addralign();
}
}
else
diff --git a/gold/compressed_output.h b/gold/compressed_output.h
index cdec1b441c..ee09a60218 100644
--- a/gold/compressed_output.h
+++ b/gold/compressed_output.h
@@ -47,7 +47,8 @@ get_uncompressed_size(const unsigned char*, section_size_type);
extern bool
decompress_input_section(const unsigned char*, unsigned long, unsigned char*,
- unsigned long, int, bool, elfcpp::Elf_Xword);
+ unsigned long, int, bool, elfcpp::Elf_Xword,
+ uint64_t *palign = NULL);
// This is used for a section whose data should be compressed. It is
// a regular Output_section which computes its contents into a buffer
diff --git a/gold/merge.cc b/gold/merge.cc
index de00ee9ae9..d7de11789f 100644
--- a/gold/merge.cc
+++ b/gold/merge.cc
@@ -440,9 +440,11 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
{
section_size_type sec_len;
bool is_new;
+ uint64_t addralign = this->addralign();
const unsigned char* pdata = object->decompressed_section_contents(shndx,
&sec_len,
- &is_new);
+ &is_new,
+ &addralign);
const Char_type* p = reinterpret_cast<const Char_type*>(pdata);
const Char_type* pend = p + sec_len / sizeof(Char_type);
@@ -494,7 +496,7 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
// aligned, so each string within the section must retain the same
// modulo.
uintptr_t init_align_modulo = (reinterpret_cast<uintptr_t>(pdata)
- & (this->addralign() - 1));
+ & (addralign - 1));
bool has_misaligned_strings = false;
while (p < pend)
@@ -503,7 +505,7 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
// Within merge input section each string must be aligned.
if (len != 0
- && ((reinterpret_cast<uintptr_t>(p) & (this->addralign() - 1))
+ && ((reinterpret_cast<uintptr_t>(p) & (addralign - 1))
!= init_align_modulo))
has_misaligned_strings = true;
diff --git a/gold/object.cc b/gold/object.cc
index cbeddb9158..e7cb897512 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -3064,7 +3064,8 @@ const unsigned char*
Object::decompressed_section_contents(
unsigned int shndx,
section_size_type* plen,
- bool* is_new)
+ bool* is_new,
+ uint64_t *palign)
{
section_size_type buffer_size;
const unsigned char* buffer = this->do_section_contents(shndx, &buffer_size,
@@ -3101,7 +3102,8 @@ Object::decompressed_section_contents(
uncompressed_size,
elfsize(),
is_big_endian(),
- p->second.flag))
+ p->second.flag,
+ palign))
this->error(_("could not decompress section %s"),
this->do_section_name(shndx).c_str());
diff --git a/gold/object.h b/gold/object.h
index 0b786a5471..ecdf9b8f11 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -828,7 +828,7 @@ class Object
// by the caller.
const unsigned char*
decompressed_section_contents(unsigned int shndx, section_size_type* plen,
- bool* is_cached);
+ bool* is_cached, uint64_t *palign = NULL);
// Discard any buffers of decompressed sections. This is done
// at the end of the Add_symbols task.
the alignment of the uncompressed section. This way the section itself
can have a different alignment than the decompressed section. Update
decompress_input_section to get alignment of the decompressed section
and use it when merging decompressed strings.
PR binutils/23919
* compressed_output.cc (decompress_input_section): Add a palign
argument and store ch_addralign in *palign if it isn't NULL.
* compressed_output.h (decompress_input_section): Add a palign
argument and default it to NULL.
* merge.cc (Output_merge_string<Char_type>::do_add_input_section):
Get addralign from decompress_input_section.
* object.cc (Object::decompressed_section_contents): Add a palign
argument and pass it to decompress_input_section.
* object.h (Object::decompressed_section_contents): Add a palign
argument and default it to NULL.
---
gold/compressed_output.cc | 11 ++++++++++-
gold/compressed_output.h | 3 ++-
gold/merge.cc | 8 +++++---
gold/object.cc | 6 ++++--
gold/object.h | 2 +-
5 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/gold/compressed_output.cc b/gold/compressed_output.cc
index 4b3e09512a..590e1c1e36 100644
--- a/gold/compressed_output.cc
+++ b/gold/compressed_output.cc
@@ -143,7 +143,8 @@ decompress_input_section(const unsigned char* compressed_data,
unsigned long uncompressed_size,
int size,
bool big_endian,
- elfcpp::Elf_Xword sh_flags)
+ elfcpp::Elf_Xword sh_flags,
+ uint64_t *palign)
{
if ((sh_flags & elfcpp::SHF_COMPRESSED) != 0)
{
@@ -156,12 +157,16 @@ decompress_input_section(const unsigned char* compressed_data,
elfcpp::Chdr<32, true> chdr(compressed_data);
if (chdr.get_ch_type() != elfcpp::ELFCOMPRESS_ZLIB)
return false;
+ if (palign)
+ *palign = chdr.get_ch_addralign();
}
else
{
elfcpp::Chdr<32, false> chdr(compressed_data);
if (chdr.get_ch_type() != elfcpp::ELFCOMPRESS_ZLIB)
return false;
+ if (palign)
+ *palign = chdr.get_ch_addralign();
}
}
else if (size == 64)
@@ -172,12 +177,16 @@ decompress_input_section(const unsigned char* compressed_data,
elfcpp::Chdr<64, true> chdr(compressed_data);
if (chdr.get_ch_type() != elfcpp::ELFCOMPRESS_ZLIB)
return false;
+ if (palign)
+ *palign = chdr.get_ch_addralign();
}
else
{
elfcpp::Chdr<64, false> chdr(compressed_data);
if (chdr.get_ch_type() != elfcpp::ELFCOMPRESS_ZLIB)
return false;
+ if (palign)
+ *palign = chdr.get_ch_addralign();
}
}
else
diff --git a/gold/compressed_output.h b/gold/compressed_output.h
index cdec1b441c..ee09a60218 100644
--- a/gold/compressed_output.h
+++ b/gold/compressed_output.h
@@ -47,7 +47,8 @@ get_uncompressed_size(const unsigned char*, section_size_type);
extern bool
decompress_input_section(const unsigned char*, unsigned long, unsigned char*,
- unsigned long, int, bool, elfcpp::Elf_Xword);
+ unsigned long, int, bool, elfcpp::Elf_Xword,
+ uint64_t *palign = NULL);
// This is used for a section whose data should be compressed. It is
// a regular Output_section which computes its contents into a buffer
diff --git a/gold/merge.cc b/gold/merge.cc
index de00ee9ae9..d7de11789f 100644
--- a/gold/merge.cc
+++ b/gold/merge.cc
@@ -440,9 +440,11 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
{
section_size_type sec_len;
bool is_new;
+ uint64_t addralign = this->addralign();
const unsigned char* pdata = object->decompressed_section_contents(shndx,
&sec_len,
- &is_new);
+ &is_new,
+ &addralign);
const Char_type* p = reinterpret_cast<const Char_type*>(pdata);
const Char_type* pend = p + sec_len / sizeof(Char_type);
@@ -494,7 +496,7 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
// aligned, so each string within the section must retain the same
// modulo.
uintptr_t init_align_modulo = (reinterpret_cast<uintptr_t>(pdata)
- & (this->addralign() - 1));
+ & (addralign - 1));
bool has_misaligned_strings = false;
while (p < pend)
@@ -503,7 +505,7 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
// Within merge input section each string must be aligned.
if (len != 0
- && ((reinterpret_cast<uintptr_t>(p) & (this->addralign() - 1))
+ && ((reinterpret_cast<uintptr_t>(p) & (addralign - 1))
!= init_align_modulo))
has_misaligned_strings = true;
diff --git a/gold/object.cc b/gold/object.cc
index cbeddb9158..e7cb897512 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -3064,7 +3064,8 @@ const unsigned char*
Object::decompressed_section_contents(
unsigned int shndx,
section_size_type* plen,
- bool* is_new)
+ bool* is_new,
+ uint64_t *palign)
{
section_size_type buffer_size;
const unsigned char* buffer = this->do_section_contents(shndx, &buffer_size,
@@ -3101,7 +3102,8 @@ Object::decompressed_section_contents(
uncompressed_size,
elfsize(),
is_big_endian(),
- p->second.flag))
+ p->second.flag,
+ palign))
this->error(_("could not decompress section %s"),
this->do_section_name(shndx).c_str());
diff --git a/gold/object.h b/gold/object.h
index 0b786a5471..ecdf9b8f11 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -828,7 +828,7 @@ class Object
// by the caller.
const unsigned char*
decompressed_section_contents(unsigned int shndx, section_size_type* plen,
- bool* is_cached);
+ bool* is_cached, uint64_t *palign = NULL);
// Discard any buffers of decompressed sections. This is done
// at the end of the Add_symbols task.
--
2.19.1
2.19.1