[PATCH] gold: Get alignment of uncompressed section from ch_addralign

H.J. Lu hjl.tools@gmail.com
Thu Nov 29 13:39:00 GMT 2018


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



More information about the Binutils mailing list