aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/binutils/binutils/0022-Handle-ELF-compressed-header-alignment-correctly-by-.patch
blob: 650de9b9a39d456cc02045e33417006955c95caa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
From bb9c8cc3c5f4ffd6019a8c53adead429954162e1 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mark@klomp.org>
Date: Tue, 27 Nov 2018 11:59:10 +0000
Subject: [PATCH 1/2] Handle ELF compressed header alignment correctly by
 setting up the section alignment correctly for the Elf32_Chdr or Elf64_Chdr
 type and respect the ch_addralign field when decompressing the section data.

	PR binutils/23919
binutils* readelf.c (dump_sections_as_strings): Remove bogus addralign check.
	(dump_sections_as_bytes): Likewise.
	(load_specific_debug_sections): Likewise.
	* testsuite/binutils-all/dw2-3.rS: Adjust alignment.
	* testsuite/binutils-all/dw2-3.rt: Likewise.

bfd	* bfd.c (bfd_update_compression_header): Explicitly set alignment.
	(bfd_check_compression_header): Add uncompressed_alignment_power
	argument. Check ch_addralign is a power of 2.
	* bfd-in2.h: Regenerated.
	* compress.c (bfd_compress_section_contents): Get and set
	orig_uncompressed_alignment_pow if section is decompressed.
	(bfd_is_section_compressed_with_header): Add and get
	uncompressed_align_pow_p argument.
	(bfd_is_section_compressed): Add uncompressed_align_power argument
	to bfd_is_section_compressed_with_header call.
	(bfd_init_section_decompress_status): Get and set
	uncompressed_alignment_power.
	* elf.c (_bfd_elf_make_section_from_shdr): Add
	uncompressed_align_power argument to
	bfd_is_section_compressed_with_header call.
---
 bfd/bfd-in2.h                            |  6 ++--
 bfd/bfd.c                                | 20 ++++++++++----
 bfd/compress.c                           | 35 +++++++++++++++++-------
 bfd/elf.c                                |  5 ++--
 binutils/readelf.c                       | 18 ------------
 binutils/testsuite/binutils-all/dw2-3.rS |  2 +-
 binutils/testsuite/binutils-all/dw2-3.rt |  2 +-
 7 files changed, 49 insertions(+), 39 deletions(-)

Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=4207142d6a5d2359170c5f9a140fc1a2351fbda9]
Signed-off-by: Khem Raj <raj.khem@gmail.com>

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index f53dbb5e8c..d0c2190d0b 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -7279,7 +7279,8 @@ void bfd_update_compression_header
 
 bfd_boolean bfd_check_compression_header
    (bfd *abfd, bfd_byte *contents, asection *sec,
-    bfd_size_type *uncompressed_size);
+    bfd_size_type *uncompressed_size,
+    unsigned int *uncompressed_alignment_power);
 
 int bfd_get_compression_header_size (bfd *abfd, asection *sec);
 
@@ -7855,7 +7856,8 @@ void bfd_cache_section_contents
 bfd_boolean bfd_is_section_compressed_with_header
    (bfd *abfd, asection *section,
     int *compression_header_size_p,
-    bfd_size_type *uncompressed_size_p);
+    bfd_size_type *uncompressed_size_p,
+    unsigned int *uncompressed_alignment_power_p);
 
 bfd_boolean bfd_is_section_compressed
    (bfd *abfd, asection *section);
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 851710401e..ea10d7b185 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -2332,6 +2332,8 @@ bfd_update_compression_header (bfd *abfd, bfd_byte *contents,
 		  bfd_put_32 (abfd, sec->size, &echdr->ch_size);
 		  bfd_put_32 (abfd, 1 << sec->alignment_power,
 			      &echdr->ch_addralign);
+		  /* bfd_log2 (alignof (Elf32_Chdr)) */
+		  bfd_set_section_alignment (abfd, sec, 2);
 		}
 	      else
 		{
@@ -2342,6 +2344,8 @@ bfd_update_compression_header (bfd *abfd, bfd_byte *contents,
 		  bfd_put_64 (abfd, sec->size, &echdr->ch_size);
 		  bfd_put_64 (abfd, 1 << sec->alignment_power,
 			      &echdr->ch_addralign);
+		  /* bfd_log2 (alignof (Elf64_Chdr)) */
+		  bfd_set_section_alignment (abfd, sec, 3);
 		}
 	    }
 	  else
@@ -2354,6 +2358,8 @@ bfd_update_compression_header (bfd *abfd, bfd_byte *contents,
 		 order.  */
 	      memcpy (contents, "ZLIB", 4);
 	      bfd_putb64 (sec->size, contents + 4);
+	      /* No way to keep the original alignment, just use 1 always. */
+	      bfd_set_section_alignment (abfd, sec, 0);
 	    }
 	}
     }
@@ -2368,12 +2374,14 @@ bfd_update_compression_header (bfd *abfd, bfd_byte *contents,
    SYNOPSIS
 	bfd_boolean bfd_check_compression_header
 	  (bfd *abfd, bfd_byte *contents, asection *sec,
-	  bfd_size_type *uncompressed_size);
+	  bfd_size_type *uncompressed_size,
+	  unsigned int *uncompressed_alignment_power);
 
 DESCRIPTION
 	Check the compression header at CONTENTS of SEC in ABFD and
-	store the uncompressed size in UNCOMPRESSED_SIZE if the
-	compression header is valid.
+	store the uncompressed size in UNCOMPRESSED_SIZE and the
+	uncompressed data alignment in UNCOMPRESSED_ALIGNMENT_POWER
+	if the compression header is valid.
 
 RETURNS
 	Return TRUE if the compression header is valid.
@@ -2382,7 +2390,8 @@ RETURNS
 bfd_boolean
 bfd_check_compression_header (bfd *abfd, bfd_byte *contents,
 			      asection *sec,
-			      bfd_size_type *uncompressed_size)
+			      bfd_size_type *uncompressed_size,
+			      unsigned int *uncompressed_alignment_power)
 {
   if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
       && (elf_section_flags (sec) & SHF_COMPRESSED) != 0)
@@ -2404,9 +2413,10 @@ bfd_check_compression_header (bfd *abfd, bfd_byte *contents,
 	  chdr.ch_addralign = bfd_get_64 (abfd, &echdr->ch_addralign);
 	}
       if (chdr.ch_type == ELFCOMPRESS_ZLIB
-	  && chdr.ch_addralign == 1U << sec->alignment_power)
+	  && chdr.ch_addralign == (1U << bfd_log2 (chdr.ch_addralign)))
 	{
 	  *uncompressed_size = chdr.ch_size;
+	  *uncompressed_alignment_power = bfd_log2 (chdr.ch_addralign);
 	  return TRUE;
 	}
     }
diff --git a/bfd/compress.c b/bfd/compress.c
index 53e566e498..97ea624eb8 100644
--- a/bfd/compress.c
+++ b/bfd/compress.c
@@ -84,11 +84,13 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec,
   int zlib_size = 0;
   int orig_compression_header_size;
   bfd_size_type orig_uncompressed_size;
+  unsigned int orig_uncompressed_alignment_pow;
   int header_size = bfd_get_compression_header_size (abfd, NULL);
   bfd_boolean compressed
     = bfd_is_section_compressed_with_header (abfd, sec,
 					     &orig_compression_header_size,
-					     &orig_uncompressed_size);
+					     &orig_uncompressed_size,
+					     &orig_uncompressed_alignment_pow);
 
   /* Either ELF compression header or the 12-byte, "ZLIB" + 8-byte size,
      overhead in .zdebug* section.  */
@@ -153,6 +155,9 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec,
 	      return 0;
 	    }
 	  free (uncompressed_buffer);
+	  bfd_set_section_alignment (abfd, sec,
+				     orig_uncompressed_alignment_pow);
+
 	  sec->contents = buffer;
 	  sec->compress_status = COMPRESS_SECTION_DONE;
 	  return orig_uncompressed_size;
@@ -364,20 +369,24 @@ SYNOPSIS
 	bfd_boolean bfd_is_section_compressed_with_header
 	  (bfd *abfd, asection *section,
 	  int *compression_header_size_p,
-	  bfd_size_type *uncompressed_size_p);
+	  bfd_size_type *uncompressed_size_p,
+	  unsigned int *uncompressed_alignment_power_p);
 
 DESCRIPTION
 	Return @code{TRUE} if @var{section} is compressed.  Compression
-	header size is returned in @var{compression_header_size_p} and
-	uncompressed size is returned in @var{uncompressed_size_p}.  If
-	compression is unsupported, compression header size is returned
-	with -1 and uncompressed size is returned with 0.
+	header size is returned in @var{compression_header_size_p},
+	uncompressed size is returned in @var{uncompressed_size_p}
+	and the uncompressed data alignement power is returned in
+	@var{uncompressed_align_pow_p}.  If compression is
+	unsupported, compression header size is returned with -1
+	and uncompressed size is returned with 0.
 */
 
 bfd_boolean
 bfd_is_section_compressed_with_header (bfd *abfd, sec_ptr sec,
 				       int *compression_header_size_p,
-				       bfd_size_type *uncompressed_size_p)
+				       bfd_size_type *uncompressed_size_p,
+				       unsigned int *uncompressed_align_pow_p)
 {
   bfd_byte header[MAX_COMPRESSION_HEADER_SIZE];
   int compression_header_size;
@@ -412,7 +421,8 @@ bfd_is_section_compressed_with_header (bfd *abfd, sec_ptr sec,
       if (compression_header_size != 0)
 	{
 	  if (!bfd_check_compression_header (abfd, header, sec,
-					     uncompressed_size_p))
+					     uncompressed_size_p,
+					     uncompressed_align_pow_p))
 	    compression_header_size = -1;
 	}
       /* Check for the pathalogical case of a debug string section that
@@ -449,9 +459,11 @@ bfd_is_section_compressed (bfd *abfd, sec_ptr sec)
 {
   int compression_header_size;
   bfd_size_type uncompressed_size;
+  unsigned int uncompressed_align_power;
   return (bfd_is_section_compressed_with_header (abfd, sec,
 						 &compression_header_size,
-						 &uncompressed_size)
+						 &uncompressed_size,
+						 &uncompressed_align_power)
 	  && compression_header_size >= 0
 	  && uncompressed_size > 0);
 }
@@ -480,6 +492,7 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec)
   int compression_header_size;
   int header_size;
   bfd_size_type uncompressed_size;
+  unsigned int uncompressed_alignment_power = 0;
 
   compression_header_size = bfd_get_compression_header_size (abfd, sec);
   if (compression_header_size > MAX_COMPRESSION_HEADER_SIZE)
@@ -508,7 +521,8 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec)
       uncompressed_size = bfd_getb64 (header + 4);
     }
   else if (!bfd_check_compression_header (abfd, header, sec,
-					 &uncompressed_size))
+					  &uncompressed_size,
+					  &uncompressed_alignment_power))
     {
       bfd_set_error (bfd_error_wrong_format);
       return FALSE;
@@ -516,6 +530,7 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec)
 
   sec->compressed_size = sec->size;
   sec->size = uncompressed_size;
+  bfd_set_section_alignment (abfd, sec, uncompressed_alignment_power);
   sec->compress_status = DECOMPRESS_SECTION_SIZED;
 
   return TRUE;
diff --git a/bfd/elf.c b/bfd/elf.c
index 828241d48a..c4f131ddcf 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1177,11 +1177,12 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
       enum { nothing, compress, decompress } action = nothing;
       int compression_header_size;
       bfd_size_type uncompressed_size;
+      unsigned int uncompressed_align_power;
       bfd_boolean compressed
 	= bfd_is_section_compressed_with_header (abfd, newsect,
 						 &compression_header_size,
-						 &uncompressed_size);
-
+						 &uncompressed_size,
+						 &uncompressed_align_power);
       if (compressed)
 	{
 	  /* Compressed section.  Check if we should decompress.  */
diff --git a/binutils/readelf.c b/binutils/readelf.c
index f4df697a7d..4b0efa884f 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -13345,12 +13345,6 @@ dump_section_as_strings (Elf_Internal_Shdr * section, Filedata * filedata)
 		    printable_section_name (filedata, section), chdr.ch_type);
 	      return FALSE;
 	    }
-	  else if (chdr.ch_addralign != section->sh_addralign)
-	    {
-	      warn (_("compressed section '%s' is corrupted\n"),
-		    printable_section_name (filedata, section));
-	      return FALSE;
-	    }
 	  uncompressed_size = chdr.ch_size;
 	  start += compression_header_size;
 	  new_size -= compression_header_size;
@@ -13492,12 +13486,6 @@ dump_section_as_bytes (Elf_Internal_Shdr *  section,
 		    printable_section_name (filedata, section), chdr.ch_type);
 	      return FALSE;
 	    }
-	  else if (chdr.ch_addralign != section->sh_addralign)
-	    {
-	      warn (_("compressed section '%s' is corrupted\n"),
-		    printable_section_name (filedata, section));
-	      return FALSE;
-	    }
 	  uncompressed_size = chdr.ch_size;
 	  start += compression_header_size;
 	  new_size -= compression_header_size;
@@ -13667,12 +13655,6 @@ load_specific_debug_section (enum dwarf_section_display_enum  debug,
 		    section->name, chdr.ch_type);
 	      return FALSE;
 	    }
-	  else if (chdr.ch_addralign != sec->sh_addralign)
-	    {
-	      warn (_("compressed section '%s' is corrupted\n"),
-		    section->name);
-	      return FALSE;
-	    }
 	  uncompressed_size = chdr.ch_size;
 	  start += compression_header_size;
 	  size -= compression_header_size;
diff --git a/binutils/testsuite/binutils-all/dw2-3.rS b/binutils/testsuite/binutils-all/dw2-3.rS
index f1637e9149..86bc73d9a2 100644
--- a/binutils/testsuite/binutils-all/dw2-3.rS
+++ b/binutils/testsuite/binutils-all/dw2-3.rS
@@ -1,3 +1,3 @@
 #...
- +\[[ 0-9]+\] .debug_info +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ [0-9a-f]+ +C +0 +0 +1
+ +\[[ 0-9]+\] .debug_info +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ [0-9a-f]+ +C +0 +0 +(4|8)
 #pass
diff --git a/binutils/testsuite/binutils-all/dw2-3.rt b/binutils/testsuite/binutils-all/dw2-3.rt
index f59cbaa22b..74e7f8deca 100644
--- a/binutils/testsuite/binutils-all/dw2-3.rt
+++ b/binutils/testsuite/binutils-all/dw2-3.rt
@@ -1,6 +1,6 @@
 #...
  +\[[ 0-9]+\] .debug_info
- +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0 +0 +1
+ +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0 +0 +(4|8)
  +\[0+800\]: COMPRESSED
  +ZLIB, 0+9d, 1
 #pass
-- 
2.20.1