Discussion:
[PATCH] gold: Get alignment of uncompressed section from ch_addralign
H.J. Lu
2018-11-29 13:38:52 UTC
Permalink
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.
--
2.19.1
H.J. Lu
2018-11-29 17:52:13 UTC
Permalink
Post by H.J. Lu
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.
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.
This is the updated patch.
--
H.J.
Cary Coutant
2018-12-02 01:06:59 UTC
Permalink
if (is_zcompressed)
{
// Skip over the ".zdebug" prefix.
name += 7;
uncompressed_size = get_uncompressed_size(contents, len);
+ info.addralign = shdr.get_sh_flags();

This should be shdr.get_sh_addralign().

Object::decompressed_section_contents(
unsigned int shndx,
section_size_type* plen,
- bool* is_new)
+ bool* is_new,
+ uint64_t *palign)

Should be "uint64_t* palign".

bool
section_is_compressed(unsigned int shndx,
- section_size_type* uncompressed_size) const
+ section_size_type* uncompressed_size,
+ elfcpp::Elf_Xword *palign = NULL) const

Likewise.

const unsigned char*
decompressed_section_contents(unsigned int shndx, section_size_type* plen,
- bool* is_cached);
+ bool* is_cached, uint64_t *palign = NULL);

Likewise.

-cary
H.J. Lu
2018-12-02 02:30:38 UTC
Permalink
Post by Cary Coutant
if (is_zcompressed)
{
// Skip over the ".zdebug" prefix.
name += 7;
uncompressed_size = get_uncompressed_size(contents, len);
+ info.addralign = shdr.get_sh_flags();
This should be shdr.get_sh_addralign().
Object::decompressed_section_contents(
unsigned int shndx,
section_size_type* plen,
- bool* is_new)
+ bool* is_new,
+ uint64_t *palign)
Should be "uint64_t* palign".
bool
section_is_compressed(unsigned int shndx,
- section_size_type* uncompressed_size) const
+ section_size_type* uncompressed_size,
+ elfcpp::Elf_Xword *palign = NULL) const
Likewise.
const unsigned char*
decompressed_section_contents(unsigned int shndx, section_size_type* plen,
- bool* is_cached);
+ bool* is_cached, uint64_t *palign = NULL);
Likewise.
-cary
Like this?

H.J.
---
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
* merge.cc (Output_merge_string<Char_type>::do_add_input_section):
Get addralign from decompressed_section_contents.
* object.cc (build_compressed_section_map): Set info.addralign.
(Object::decompressed_section_contents): Add a palign
argument and store p->second.addralign in *palign if it isn't
NULL.
* object.h (Compressed_section_info): Add addralign.
(section_is_compressed): Add a palign argument, default it
to NULL, store p->second.addralign in *palign if it isn't NULL.
(Object::decompressed_section_contents): Likewise.
* output.cc (Output_section::add_input_section): Get addralign
from section_is_compressed.
---
gold/merge.cc | 8 +++++---
gold/object.cc | 11 +++++++++--
gold/object.h | 8 ++++++--
gold/output.cc | 11 ++++++-----
4 files changed, 26 insertions(+), 12 deletions(-)

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..7930de66fe 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -751,11 +751,13 @@ build_compressed_section_map(
const unsigned char* contents =
obj->section_contents(i, &len, false);
uint64_t uncompressed_size;
+ Compressed_section_info info;
if (is_zcompressed)
{
// Skip over the ".zdebug" prefix.
name += 7;
uncompressed_size = get_uncompressed_size(contents, len);
+ info.addralign = shdr.get_sh_addralign();
}
else
{
@@ -763,8 +765,8 @@ build_compressed_section_map(
name += 6;
elfcpp::Chdr<size, big_endian> chdr(contents);
uncompressed_size = chdr.get_ch_size();
+ info.addralign = chdr.get_ch_addralign();
}
- Compressed_section_info info;
info.size = convert_to_section_size_type(uncompressed_size);
info.flag = shdr.get_sh_flags();
info.contents = NULL;
@@ -3064,7 +3066,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,
@@ -3091,6 +3094,8 @@ Object::decompressed_section_contents(
{
*plen = uncompressed_size;
*is_new = false;
+ if (palign != NULL)
+ *palign = p->second.addralign;
return p->second.contents;
}

@@ -3112,6 +3117,8 @@ Object::decompressed_section_contents(
// once in this pass.
*plen = uncompressed_size;
*is_new = true;
+ if (palign != NULL)
+ *palign = p->second.addralign;
return uncompressed_data;
}

diff --git a/gold/object.h b/gold/object.h
index 0b786a5471..b99548463d 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -373,6 +373,7 @@ struct Compressed_section_info
{
section_size_type size;
elfcpp::Elf_Xword flag;
+ uint64_t addralign;
const unsigned char* contents;
};
typedef std::map<unsigned int, Compressed_section_info> Compressed_section_map;
@@ -808,7 +809,8 @@ class Object

bool
section_is_compressed(unsigned int shndx,
- section_size_type* uncompressed_size) const
+ section_size_type* uncompressed_size,
+ elfcpp::Elf_Xword* palign = NULL) const
{
if (this->compressed_sections_ == NULL)
return false;
@@ -818,6 +820,8 @@ class Object
{
if (uncompressed_size != NULL)
*uncompressed_size = p->second.size;
+ if (palign != NULL)
+ *palign = p->second.addralign;
return true;
}
return false;
@@ -828,7 +832,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.
diff --git a/gold/output.cc b/gold/output.cc
index 8c71f0217c..24db722214 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -2448,7 +2448,13 @@ Output_section::add_input_section(Layout* layout,
unsigned int reloc_shndx,
bool have_sections_script)
{
+ section_size_type input_section_size = shdr.get_sh_size();
+ section_size_type uncompressed_size;
elfcpp::Elf_Xword addralign = shdr.get_sh_addralign();
+ if (object->section_is_compressed(shndx, &uncompressed_size,
+ &addralign))
+ input_section_size = uncompressed_size;
+
if ((addralign & (addralign - 1)) != 0)
{
object->error(_("invalid alignment %lu for section \"%s\""),
@@ -2498,11 +2504,6 @@ Output_section::add_input_section(Layout* layout,
}
}

- section_size_type input_section_size = shdr.get_sh_size();
- section_size_type uncompressed_size;
- if (object->section_is_compressed(shndx, &uncompressed_size))
- input_section_size = uncompressed_size;
-
off_t offset_in_section;

if (this->has_fixed_layout())
--
2.19.2
Cary Coutant
2018-12-02 05:50:56 UTC
Permalink
Post by H.J. Lu
PR binutils/23919
Get addralign from decompressed_section_contents.
* object.cc (build_compressed_section_map): Set info.addralign.
(Object::decompressed_section_contents): Add a palign
argument and store p->second.addralign in *palign if it isn't
NULL.
* object.h (Compressed_section_info): Add addralign.
(section_is_compressed): Add a palign argument, default it
to NULL, store p->second.addralign in *palign if it isn't NULL.
(Object::decompressed_section_contents): Likewise.
* output.cc (Output_section::add_input_section): Get addralign
from section_is_compressed.
This is OK. Thanks!

-cary

Loading...