]>
Commit | Line | Data |
---|---|---|
0acf065b | 1 | /* Compressed section support (intended for debug sections). |
d87bef3a | 2 | Copyright (C) 2008-2023 Free Software Foundation, Inc. |
1b315056 CS |
3 | |
4 | This file is part of BFD, the Binary File Descriptor library. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 3 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
18 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, | |
19 | MA 02110-1301, USA. */ | |
20 | ||
1b315056 | 21 | #include "sysdep.h" |
243340ad | 22 | #include <zlib.h> |
2cac01e3 FS |
23 | #ifdef HAVE_ZSTD |
24 | #include <zstd.h> | |
25 | #endif | |
1b315056 | 26 | #include "bfd.h" |
2cac01e3 | 27 | #include "elf-bfd.h" |
1b315056 | 28 | #include "libbfd.h" |
a953eec9 | 29 | #include "safe-ctype.h" |
c3620d6d | 30 | #include "libiberty.h" |
1b315056 | 31 | |
151411f8 L |
32 | #define MAX_COMPRESSION_HEADER_SIZE 24 |
33 | ||
13917d93 AM |
34 | /* |
35 | CODE_FRAGMENT | |
c3620d6d AM |
36 | .{* Types of compressed DWARF debug sections. *} |
37 | .enum compressed_debug_section_type | |
38 | .{ | |
39 | . COMPRESS_DEBUG_NONE = 0, | |
40 | . COMPRESS_DEBUG_GNU_ZLIB = 1 << 1, | |
41 | . COMPRESS_DEBUG_GABI_ZLIB = 1 << 2, | |
42 | . COMPRESS_DEBUG_ZSTD = 1 << 3, | |
43 | . COMPRESS_UNKNOWN = 1 << 4 | |
44 | .}; | |
45 | . | |
46 | .{* Tuple for compressed_debug_section_type and their name. *} | |
47 | .struct compressed_type_tuple | |
48 | .{ | |
49 | . enum compressed_debug_section_type type; | |
50 | . const char *name; | |
51 | .}; | |
52 | . | |
53 | .{* Compression header ch_type values. *} | |
89dbeac7 AM |
54 | .enum compression_type |
55 | .{ | |
56 | . ch_none = 0, | |
57 | . ch_compress_zlib = 1 , {* Compressed with zlib. *} | |
58 | . ch_compress_zstd = 2 {* Compressed with zstd (www.zstandard.org). *} | |
59 | .}; | |
60 | . | |
13917d93 AM |
61 | .static inline char * |
62 | .bfd_debug_name_to_zdebug (bfd *abfd, const char *name) | |
63 | .{ | |
64 | . size_t len = strlen (name); | |
47afa56e | 65 | . char *new_name = (char *) bfd_alloc (abfd, len + 2); |
13917d93 AM |
66 | . if (new_name == NULL) |
67 | . return NULL; | |
68 | . new_name[0] = '.'; | |
69 | . new_name[1] = 'z'; | |
70 | . memcpy (new_name + 2, name + 1, len); | |
71 | . return new_name; | |
72 | .} | |
73 | . | |
74 | .static inline char * | |
75 | .bfd_zdebug_name_to_debug (bfd *abfd, const char *name) | |
76 | .{ | |
77 | . size_t len = strlen (name); | |
47afa56e | 78 | . char *new_name = (char *) bfd_alloc (abfd, len); |
13917d93 AM |
79 | . if (new_name == NULL) |
80 | . return NULL; | |
81 | . new_name[0] = '.'; | |
82 | . memcpy (new_name + 1, name + 2, len - 1); | |
83 | . return new_name; | |
84 | .} | |
85 | . | |
86 | */ | |
87 | ||
c3620d6d AM |
88 | /* Display texts for type of compressed DWARF debug sections. */ |
89 | static const struct compressed_type_tuple compressed_debug_section_names[] = | |
90 | { | |
91 | { COMPRESS_DEBUG_NONE, "none" }, | |
92 | { COMPRESS_DEBUG_GABI_ZLIB, "zlib" }, | |
93 | { COMPRESS_DEBUG_GNU_ZLIB, "zlib-gnu" }, | |
94 | { COMPRESS_DEBUG_GABI_ZLIB, "zlib-gabi" }, | |
95 | { COMPRESS_DEBUG_ZSTD, "zstd" }, | |
96 | }; | |
97 | ||
98 | /* | |
99 | FUNCTION | |
100 | bfd_get_compression_algorithm | |
101 | SYNOPSIS | |
102 | enum compressed_debug_section_type | |
103 | bfd_get_compression_algorithm (const char *name); | |
104 | DESCRIPTION | |
105 | Return compressed_debug_section_type from a string representation. | |
106 | */ | |
107 | enum compressed_debug_section_type | |
108 | bfd_get_compression_algorithm (const char *name) | |
109 | { | |
110 | for (unsigned i = 0; i < ARRAY_SIZE (compressed_debug_section_names); ++i) | |
111 | if (strcasecmp (compressed_debug_section_names[i].name, name) == 0) | |
112 | return compressed_debug_section_names[i].type; | |
113 | ||
114 | return COMPRESS_UNKNOWN; | |
115 | } | |
116 | ||
117 | /* | |
118 | FUNCTION | |
119 | bfd_get_compression_algorithm_name | |
120 | SYNOPSIS | |
121 | const char *bfd_get_compression_algorithm_name | |
122 | (enum compressed_debug_section_type type); | |
123 | DESCRIPTION | |
124 | Return compression algorithm name based on the type. | |
125 | */ | |
126 | const char * | |
127 | bfd_get_compression_algorithm_name (enum compressed_debug_section_type type) | |
128 | { | |
129 | for (unsigned i = 0; i < ARRAY_SIZE (compressed_debug_section_names); ++i) | |
130 | if (type == compressed_debug_section_names[i].type) | |
131 | return compressed_debug_section_names[i].name; | |
132 | ||
133 | return NULL; | |
134 | } | |
135 | ||
89dbeac7 AM |
136 | /* |
137 | FUNCTION | |
138 | bfd_update_compression_header | |
139 | ||
140 | SYNOPSIS | |
141 | void bfd_update_compression_header | |
142 | (bfd *abfd, bfd_byte *contents, asection *sec); | |
143 | ||
144 | DESCRIPTION | |
145 | Set the compression header at CONTENTS of SEC in ABFD and update | |
146 | elf_section_flags for compression. | |
147 | */ | |
148 | ||
149 | void | |
150 | bfd_update_compression_header (bfd *abfd, bfd_byte *contents, | |
151 | asection *sec) | |
152 | { | |
153 | if ((abfd->flags & BFD_COMPRESS) == 0) | |
154 | abort (); | |
155 | ||
156 | switch (bfd_get_flavour (abfd)) | |
157 | { | |
158 | case bfd_target_elf_flavour: | |
159 | if ((abfd->flags & BFD_COMPRESS_GABI) != 0) | |
160 | { | |
161 | const struct elf_backend_data *bed = get_elf_backend_data (abfd); | |
162 | struct bfd_elf_section_data * esd = elf_section_data (sec); | |
163 | enum compression_type ch_type = (abfd->flags & BFD_COMPRESS_ZSTD | |
164 | ? ch_compress_zstd | |
165 | : ch_compress_zlib); | |
166 | ||
167 | /* Set the SHF_COMPRESSED bit. */ | |
168 | elf_section_flags (sec) |= SHF_COMPRESSED; | |
169 | ||
170 | if (bed->s->elfclass == ELFCLASS32) | |
171 | { | |
172 | Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents; | |
173 | bfd_put_32 (abfd, ch_type, &echdr->ch_type); | |
174 | bfd_put_32 (abfd, sec->size, &echdr->ch_size); | |
175 | bfd_put_32 (abfd, 1u << sec->alignment_power, | |
176 | &echdr->ch_addralign); | |
177 | /* bfd_log2 (alignof (Elf32_Chdr)) */ | |
178 | bfd_set_section_alignment (sec, 2); | |
179 | esd->this_hdr.sh_addralign = 4; | |
180 | } | |
181 | else | |
182 | { | |
183 | Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents; | |
184 | bfd_put_32 (abfd, ch_type, &echdr->ch_type); | |
185 | bfd_put_32 (abfd, 0, &echdr->ch_reserved); | |
186 | bfd_put_64 (abfd, sec->size, &echdr->ch_size); | |
187 | bfd_put_64 (abfd, UINT64_C (1) << sec->alignment_power, | |
188 | &echdr->ch_addralign); | |
189 | /* bfd_log2 (alignof (Elf64_Chdr)) */ | |
190 | bfd_set_section_alignment (sec, 3); | |
191 | esd->this_hdr.sh_addralign = 8; | |
192 | } | |
193 | break; | |
194 | } | |
195 | ||
196 | /* Clear the SHF_COMPRESSED bit. */ | |
197 | elf_section_flags (sec) &= ~SHF_COMPRESSED; | |
198 | /* Fall through. */ | |
199 | ||
200 | default: | |
201 | /* Write the zlib header. It should be "ZLIB" followed by | |
202 | the uncompressed section size, 8 bytes in big-endian | |
203 | order. */ | |
204 | memcpy (contents, "ZLIB", 4); | |
205 | bfd_putb64 (sec->size, contents + 4); | |
206 | /* No way to keep the original alignment, just use 1 always. */ | |
207 | bfd_set_section_alignment (sec, 0); | |
208 | break; | |
209 | } | |
210 | } | |
211 | ||
212 | /* Check the compression header at CONTENTS of SEC in ABFD and store the | |
213 | ch_type in CH_TYPE, uncompressed size in UNCOMPRESSED_SIZE, and the | |
214 | uncompressed data alignment in UNCOMPRESSED_ALIGNMENT_POWER if the | |
215 | compression header is valid. */ | |
216 | ||
217 | static bool | |
218 | bfd_check_compression_header (bfd *abfd, bfd_byte *contents, | |
219 | asection *sec, | |
220 | enum compression_type *ch_type, | |
221 | bfd_size_type *uncompressed_size, | |
222 | unsigned int *uncompressed_alignment_power) | |
223 | { | |
224 | if (bfd_get_flavour (abfd) == bfd_target_elf_flavour | |
225 | && (elf_section_flags (sec) & SHF_COMPRESSED) != 0) | |
226 | { | |
227 | Elf_Internal_Chdr chdr; | |
228 | const struct elf_backend_data *bed = get_elf_backend_data (abfd); | |
229 | if (bed->s->elfclass == ELFCLASS32) | |
230 | { | |
231 | Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents; | |
232 | chdr.ch_type = bfd_get_32 (abfd, &echdr->ch_type); | |
233 | chdr.ch_size = bfd_get_32 (abfd, &echdr->ch_size); | |
234 | chdr.ch_addralign = bfd_get_32 (abfd, &echdr->ch_addralign); | |
235 | } | |
236 | else | |
237 | { | |
238 | Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents; | |
239 | chdr.ch_type = bfd_get_32 (abfd, &echdr->ch_type); | |
240 | chdr.ch_size = bfd_get_64 (abfd, &echdr->ch_size); | |
241 | chdr.ch_addralign = bfd_get_64 (abfd, &echdr->ch_addralign); | |
242 | } | |
243 | *ch_type = chdr.ch_type; | |
244 | if ((chdr.ch_type == ch_compress_zlib | |
245 | || chdr.ch_type == ch_compress_zstd) | |
246 | && chdr.ch_addralign == (chdr.ch_addralign & -chdr.ch_addralign)) | |
247 | { | |
248 | *uncompressed_size = chdr.ch_size; | |
249 | *uncompressed_alignment_power = bfd_log2 (chdr.ch_addralign); | |
250 | return true; | |
251 | } | |
252 | } | |
253 | ||
254 | return false; | |
255 | } | |
256 | ||
257 | /* | |
258 | FUNCTION | |
259 | bfd_get_compression_header_size | |
260 | ||
261 | SYNOPSIS | |
262 | int bfd_get_compression_header_size (bfd *abfd, asection *sec); | |
263 | ||
264 | DESCRIPTION | |
265 | Return the size of the compression header of SEC in ABFD. | |
89dbeac7 AM |
266 | */ |
267 | ||
268 | int | |
269 | bfd_get_compression_header_size (bfd *abfd, asection *sec) | |
270 | { | |
271 | if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) | |
272 | { | |
273 | if (sec == NULL) | |
274 | { | |
275 | if (!(abfd->flags & BFD_COMPRESS_GABI)) | |
276 | return 0; | |
277 | } | |
278 | else if (!(elf_section_flags (sec) & SHF_COMPRESSED)) | |
279 | return 0; | |
280 | ||
281 | if (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS32) | |
282 | return sizeof (Elf32_External_Chdr); | |
283 | else | |
284 | return sizeof (Elf64_External_Chdr); | |
285 | } | |
286 | ||
287 | return 0; | |
288 | } | |
289 | ||
290 | /* | |
291 | FUNCTION | |
7b5f66a1 | 292 | bfd_convert_section_setup |
89dbeac7 AM |
293 | |
294 | SYNOPSIS | |
7b5f66a1 AM |
295 | bool bfd_convert_section_setup |
296 | (bfd *ibfd, asection *isec, bfd *obfd, | |
297 | const char **new_name, bfd_size_type *new_size); | |
89dbeac7 AM |
298 | |
299 | DESCRIPTION | |
7b5f66a1 AM |
300 | Do early setup for objcopy, when copying @var{isec} in input |
301 | BFD @var{ibfd} to output BFD @var{obfd}. Returns the name and | |
302 | size of the output section. | |
89dbeac7 AM |
303 | */ |
304 | ||
7b5f66a1 AM |
305 | bool |
306 | bfd_convert_section_setup (bfd *ibfd, asection *isec, bfd *obfd, | |
307 | const char **new_name, bfd_size_type *new_size) | |
89dbeac7 AM |
308 | { |
309 | bfd_size_type hdr_size; | |
310 | ||
7b5f66a1 AM |
311 | if ((isec->flags & SEC_DEBUGGING) != 0 |
312 | && (isec->flags & SEC_HAS_CONTENTS) != 0) | |
313 | { | |
314 | const char *name = *new_name; | |
315 | ||
c3620d6d | 316 | if ((obfd->flags & (BFD_DECOMPRESS | BFD_COMPRESS_GABI)) != 0) |
7b5f66a1 AM |
317 | { |
318 | /* When we decompress or compress with SHF_COMPRESSED, | |
319 | convert section name from .zdebug_* to .debug_*. */ | |
320 | if (startswith (name, ".zdebug_")) | |
321 | { | |
322 | name = bfd_zdebug_name_to_debug (obfd, name); | |
323 | if (name == NULL) | |
324 | return false; | |
325 | } | |
326 | } | |
327 | ||
328 | /* PR binutils/18087: Compression does not always make a | |
329 | section smaller. So only rename the section when | |
330 | compression has actually taken place. If input section | |
331 | name is .zdebug_*, we should never compress it again. */ | |
332 | else if (isec->compress_status == COMPRESS_SECTION_DONE | |
333 | && startswith (name, ".debug_")) | |
334 | { | |
335 | name = bfd_debug_name_to_zdebug (obfd, name); | |
336 | if (name == NULL) | |
337 | return false; | |
338 | } | |
339 | *new_name = name; | |
340 | } | |
341 | *new_size = bfd_section_size (isec); | |
342 | ||
89dbeac7 AM |
343 | /* Do nothing if either input or output aren't ELF. */ |
344 | if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour | |
345 | || bfd_get_flavour (obfd) != bfd_target_elf_flavour) | |
7b5f66a1 | 346 | return true; |
89dbeac7 AM |
347 | |
348 | /* Do nothing if ELF classes of input and output are the same. */ | |
349 | if (get_elf_backend_data (ibfd)->s->elfclass | |
350 | == get_elf_backend_data (obfd)->s->elfclass) | |
7b5f66a1 | 351 | return true; |
89dbeac7 AM |
352 | |
353 | /* Convert GNU property size. */ | |
354 | if (startswith (isec->name, NOTE_GNU_PROPERTY_SECTION_NAME)) | |
7b5f66a1 AM |
355 | { |
356 | *new_size = _bfd_elf_convert_gnu_property_size (ibfd, obfd); | |
357 | return true; | |
358 | } | |
89dbeac7 AM |
359 | |
360 | /* Do nothing if input file will be decompressed. */ | |
361 | if ((ibfd->flags & BFD_DECOMPRESS)) | |
7b5f66a1 | 362 | return true; |
89dbeac7 AM |
363 | |
364 | /* Do nothing if the input section isn't a SHF_COMPRESSED section. */ | |
365 | hdr_size = bfd_get_compression_header_size (ibfd, isec); | |
366 | if (hdr_size == 0) | |
7b5f66a1 | 367 | return true; |
89dbeac7 AM |
368 | |
369 | /* Adjust the size of the output SHF_COMPRESSED section. */ | |
370 | if (hdr_size == sizeof (Elf32_External_Chdr)) | |
7b5f66a1 | 371 | *new_size += sizeof (Elf64_External_Chdr) - sizeof (Elf32_External_Chdr); |
89dbeac7 | 372 | else |
e2546673 | 373 | *new_size -= sizeof (Elf64_External_Chdr) - sizeof (Elf32_External_Chdr); |
7b5f66a1 | 374 | return true; |
89dbeac7 AM |
375 | } |
376 | ||
377 | /* | |
378 | FUNCTION | |
379 | bfd_convert_section_contents | |
380 | ||
381 | SYNOPSIS | |
382 | bool bfd_convert_section_contents | |
383 | (bfd *ibfd, asection *isec, bfd *obfd, | |
384 | bfd_byte **ptr, bfd_size_type *ptr_size); | |
385 | ||
386 | DESCRIPTION | |
387 | Convert the contents, stored in @var{*ptr}, of the section | |
388 | @var{isec} in input BFD @var{ibfd} to output BFD @var{obfd} | |
389 | if needed. The original buffer pointed to by @var{*ptr} may | |
390 | be freed and @var{*ptr} is returned with memory malloc'd by this | |
391 | function, and the new size written to @var{ptr_size}. | |
392 | */ | |
393 | ||
394 | bool | |
395 | bfd_convert_section_contents (bfd *ibfd, sec_ptr isec, bfd *obfd, | |
396 | bfd_byte **ptr, bfd_size_type *ptr_size) | |
397 | { | |
398 | bfd_byte *contents; | |
399 | bfd_size_type ihdr_size, ohdr_size, size; | |
400 | Elf_Internal_Chdr chdr; | |
401 | bool use_memmove; | |
402 | ||
403 | /* Do nothing if either input or output aren't ELF. */ | |
404 | if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour | |
405 | || bfd_get_flavour (obfd) != bfd_target_elf_flavour) | |
406 | return true; | |
407 | ||
408 | /* Do nothing if ELF classes of input and output are the same. */ | |
409 | if (get_elf_backend_data (ibfd)->s->elfclass | |
410 | == get_elf_backend_data (obfd)->s->elfclass) | |
411 | return true; | |
412 | ||
413 | /* Convert GNU properties. */ | |
414 | if (startswith (isec->name, NOTE_GNU_PROPERTY_SECTION_NAME)) | |
415 | return _bfd_elf_convert_gnu_properties (ibfd, isec, obfd, ptr, | |
416 | ptr_size); | |
417 | ||
418 | /* Do nothing if input file will be decompressed. */ | |
419 | if ((ibfd->flags & BFD_DECOMPRESS)) | |
420 | return true; | |
421 | ||
422 | /* Do nothing if the input section isn't a SHF_COMPRESSED section. */ | |
423 | ihdr_size = bfd_get_compression_header_size (ibfd, isec); | |
424 | if (ihdr_size == 0) | |
425 | return true; | |
426 | ||
427 | /* PR 25221. Check for corrupt input sections. */ | |
428 | if (ihdr_size > bfd_get_section_limit (ibfd, isec)) | |
429 | /* FIXME: Issue a warning about a corrupt | |
430 | compression header size field ? */ | |
431 | return false; | |
432 | ||
433 | contents = *ptr; | |
434 | ||
435 | /* Convert the contents of the input SHF_COMPRESSED section to | |
436 | output. Get the input compression header and the size of the | |
437 | output compression header. */ | |
438 | if (ihdr_size == sizeof (Elf32_External_Chdr)) | |
439 | { | |
440 | Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents; | |
441 | chdr.ch_type = bfd_get_32 (ibfd, &echdr->ch_type); | |
442 | chdr.ch_size = bfd_get_32 (ibfd, &echdr->ch_size); | |
443 | chdr.ch_addralign = bfd_get_32 (ibfd, &echdr->ch_addralign); | |
444 | ||
445 | ohdr_size = sizeof (Elf64_External_Chdr); | |
446 | ||
447 | use_memmove = false; | |
448 | } | |
449 | else if (ihdr_size != sizeof (Elf64_External_Chdr)) | |
450 | { | |
451 | /* FIXME: Issue a warning about a corrupt | |
452 | compression header size field ? */ | |
453 | return false; | |
454 | } | |
455 | else | |
456 | { | |
457 | Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents; | |
458 | chdr.ch_type = bfd_get_32 (ibfd, &echdr->ch_type); | |
459 | chdr.ch_size = bfd_get_64 (ibfd, &echdr->ch_size); | |
460 | chdr.ch_addralign = bfd_get_64 (ibfd, &echdr->ch_addralign); | |
461 | ||
462 | ohdr_size = sizeof (Elf32_External_Chdr); | |
463 | use_memmove = true; | |
464 | } | |
465 | ||
466 | size = bfd_section_size (isec) - ihdr_size + ohdr_size; | |
467 | if (!use_memmove) | |
468 | { | |
469 | contents = (bfd_byte *) bfd_malloc (size); | |
470 | if (contents == NULL) | |
471 | return false; | |
472 | } | |
473 | ||
474 | /* Write out the output compression header. */ | |
475 | if (ohdr_size == sizeof (Elf32_External_Chdr)) | |
476 | { | |
477 | Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents; | |
478 | bfd_put_32 (obfd, chdr.ch_type, &echdr->ch_type); | |
479 | bfd_put_32 (obfd, chdr.ch_size, &echdr->ch_size); | |
480 | bfd_put_32 (obfd, chdr.ch_addralign, &echdr->ch_addralign); | |
481 | } | |
482 | else | |
483 | { | |
484 | Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents; | |
485 | bfd_put_32 (obfd, chdr.ch_type, &echdr->ch_type); | |
486 | bfd_put_32 (obfd, 0, &echdr->ch_reserved); | |
487 | bfd_put_64 (obfd, chdr.ch_size, &echdr->ch_size); | |
488 | bfd_put_64 (obfd, chdr.ch_addralign, &echdr->ch_addralign); | |
489 | } | |
490 | ||
491 | /* Copy the compressed contents. */ | |
492 | if (use_memmove) | |
493 | memmove (contents + ohdr_size, *ptr + ihdr_size, size - ohdr_size); | |
494 | else | |
495 | { | |
496 | memcpy (contents + ohdr_size, *ptr + ihdr_size, size - ohdr_size); | |
497 | free (*ptr); | |
498 | *ptr = contents; | |
499 | } | |
500 | ||
501 | *ptr_size = size; | |
502 | return true; | |
503 | } | |
504 | ||
0a1b45a2 | 505 | static bool |
2cac01e3 | 506 | decompress_contents (bool is_zstd, bfd_byte *compressed_buffer, |
4a114e3e L |
507 | bfd_size_type compressed_size, |
508 | bfd_byte *uncompressed_buffer, | |
509 | bfd_size_type uncompressed_size) | |
510 | { | |
2cac01e3 FS |
511 | if (is_zstd) |
512 | { | |
513 | #ifdef HAVE_ZSTD | |
514 | size_t ret = ZSTD_decompress (uncompressed_buffer, uncompressed_size, | |
515 | compressed_buffer, compressed_size); | |
516 | return !ZSTD_isError (ret); | |
517 | #endif | |
518 | } | |
519 | ||
4a114e3e L |
520 | z_stream strm; |
521 | int rc; | |
522 | ||
523 | /* It is possible the section consists of several compressed | |
524 | buffers concatenated together, so we uncompress in a loop. */ | |
de13ef81 NC |
525 | /* PR 18313: The state field in the z_stream structure is supposed |
526 | to be invisible to the user (ie us), but some compilers will | |
527 | still complain about it being used without initialisation. So | |
528 | we first zero the entire z_stream structure and then set the fields | |
529 | that we need. */ | |
530 | memset (& strm, 0, sizeof strm); | |
dab394de L |
531 | strm.avail_in = compressed_size; |
532 | strm.next_in = (Bytef*) compressed_buffer; | |
4a114e3e | 533 | strm.avail_out = uncompressed_size; |
c5967f38 AM |
534 | /* FIXME: strm.avail_in and strm.avail_out are typically unsigned |
535 | int. Supporting sizes that don't fit in an unsigned int is | |
536 | possible but will require some rewriting of this function. */ | |
537 | if (strm.avail_in != compressed_size || strm.avail_out != uncompressed_size) | |
538 | return false; | |
4a114e3e | 539 | |
a253d456 | 540 | BFD_ASSERT (Z_OK == 0); |
4a114e3e | 541 | rc = inflateInit (&strm); |
a29a8af8 | 542 | while (strm.avail_in > 0 && strm.avail_out > 0) |
4a114e3e L |
543 | { |
544 | if (rc != Z_OK) | |
a253d456 | 545 | break; |
4a114e3e | 546 | strm.next_out = ((Bytef*) uncompressed_buffer |
07d6d2b8 | 547 | + (uncompressed_size - strm.avail_out)); |
4a114e3e L |
548 | rc = inflate (&strm, Z_FINISH); |
549 | if (rc != Z_STREAM_END) | |
a253d456 | 550 | break; |
4a114e3e L |
551 | rc = inflateReset (&strm); |
552 | } | |
ad92f33d | 553 | return inflateEnd (&strm) == Z_OK && rc == Z_OK && strm.avail_out == 0; |
4a114e3e | 554 | } |
4a114e3e | 555 | |
758dd750 | 556 | /* Compress section contents using zlib/zstd and store |
0b0732e1 | 557 | as the contents field. This function assumes the contents |
18ece1de | 558 | field was allocated using bfd_malloc() or equivalent. |
1b315056 | 559 | |
151411f8 L |
560 | Return the uncompressed size if the full section contents is |
561 | compressed successfully. Otherwise return 0. */ | |
1b315056 | 562 | |
151411f8 | 563 | static bfd_size_type |
758dd750 | 564 | bfd_compress_section_contents (bfd *abfd, sec_ptr sec) |
1b315056 | 565 | { |
758dd750 | 566 | bfd_byte *input_buffer; |
ae6a0217 | 567 | uLong compressed_size; |
151411f8 L |
568 | bfd_byte *buffer; |
569 | bfd_size_type buffer_size; | |
51509926 | 570 | int zlib_size = 0; |
758dd750 AM |
571 | int orig_header_size; |
572 | bfd_size_type uncompressed_size; | |
573 | unsigned int uncompressed_alignment_pow; | |
89dbeac7 | 574 | enum compression_type ch_type = ch_none; |
758dd750 | 575 | int new_header_size = bfd_get_compression_header_size (abfd, NULL); |
0a1b45a2 | 576 | bool compressed |
758dd750 AM |
577 | = bfd_is_section_compressed_info (abfd, sec, |
578 | &orig_header_size, | |
579 | &uncompressed_size, | |
580 | &uncompressed_alignment_pow, | |
581 | &ch_type); | |
582 | bool update = false; | |
583 | ||
584 | /* We shouldn't be trying to decompress unsupported compressed sections. */ | |
585 | if (compressed && orig_header_size < 0) | |
586 | abort (); | |
dab394de L |
587 | |
588 | /* Either ELF compression header or the 12-byte, "ZLIB" + 8-byte size, | |
589 | overhead in .zdebug* section. */ | |
758dd750 AM |
590 | if (!new_header_size) |
591 | new_header_size = 12; | |
89dbeac7 | 592 | if (ch_type == ch_none) |
758dd750 | 593 | orig_header_size = 12; |
151411f8 | 594 | |
758dd750 | 595 | input_buffer = sec->contents; |
151411f8 L |
596 | if (compressed) |
597 | { | |
758dd750 AM |
598 | zlib_size = sec->size - orig_header_size; |
599 | compressed_size = zlib_size + new_header_size; | |
4281caad | 600 | |
758dd750 AM |
601 | /* If we are converting between zlib-gnu and zlib-gabi then the |
602 | compressed contents just need to be moved. */ | |
89dbeac7 | 603 | update = (ch_type < ch_compress_zstd |
758dd750 | 604 | && (abfd->flags & BFD_COMPRESS_ZSTD) == 0); |
4a114e3e | 605 | |
758dd750 AM |
606 | /* Uncompress when not just moving contents or when compressed |
607 | is not smaller than uncompressed. */ | |
608 | if (!update || compressed_size >= uncompressed_size) | |
151411f8 | 609 | { |
758dd750 AM |
610 | buffer_size = uncompressed_size; |
611 | buffer = bfd_malloc (buffer_size); | |
612 | if (buffer == NULL) | |
613 | return 0; | |
614 | ||
89dbeac7 | 615 | if (!decompress_contents (ch_type == ch_compress_zstd, |
758dd750 AM |
616 | input_buffer + orig_header_size, |
617 | zlib_size, buffer, buffer_size)) | |
151411f8 L |
618 | { |
619 | bfd_set_error (bfd_error_bad_value); | |
758dd750 | 620 | free (buffer); |
151411f8 L |
621 | return 0; |
622 | } | |
758dd750 AM |
623 | free (input_buffer); |
624 | bfd_set_section_alignment (sec, uncompressed_alignment_pow); | |
151411f8 | 625 | sec->contents = buffer; |
206e9791 AM |
626 | sec->flags |= SEC_IN_MEMORY; |
627 | sec->compress_status = COMPRESS_SECTION_NONE; | |
758dd750 AM |
628 | sec->size = uncompressed_size; |
629 | input_buffer = buffer; | |
151411f8 | 630 | } |
8d001214 | 631 | } |
758dd750 AM |
632 | |
633 | if (!update) | |
634 | compressed_size = compressBound (uncompressed_size) + new_header_size; | |
635 | ||
636 | buffer_size = compressed_size; | |
637 | buffer = bfd_alloc (abfd, buffer_size); | |
638 | if (buffer == NULL) | |
639 | return 0; | |
640 | ||
641 | if (update) | |
642 | { | |
643 | if (compressed_size < uncompressed_size) | |
644 | memcpy (buffer + new_header_size, | |
645 | input_buffer + orig_header_size, | |
646 | zlib_size); | |
647 | } | |
8d001214 L |
648 | else |
649 | { | |
2cac01e3 FS |
650 | if (abfd->flags & BFD_COMPRESS_ZSTD) |
651 | { | |
652 | #if HAVE_ZSTD | |
758dd750 AM |
653 | compressed_size = ZSTD_compress (buffer + new_header_size, |
654 | compressed_size, | |
655 | input_buffer, | |
656 | uncompressed_size, | |
657 | ZSTD_CLEVEL_DEFAULT); | |
2cac01e3 FS |
658 | if (ZSTD_isError (compressed_size)) |
659 | { | |
660 | bfd_release (abfd, buffer); | |
661 | bfd_set_error (bfd_error_bad_value); | |
662 | return 0; | |
663 | } | |
664 | #endif | |
665 | } | |
758dd750 AM |
666 | else if (compress ((Bytef *) buffer + new_header_size, &compressed_size, |
667 | (const Bytef *) input_buffer, uncompressed_size) | |
2cac01e3 | 668 | != Z_OK) |
151411f8 | 669 | { |
030aeb75 | 670 | bfd_release (abfd, buffer); |
151411f8 L |
671 | bfd_set_error (bfd_error_bad_value); |
672 | return 0; | |
673 | } | |
674 | ||
758dd750 | 675 | compressed_size += new_header_size; |
8d001214 | 676 | } |
4a114e3e | 677 | |
758dd750 AM |
678 | /* If compression didn't make the section smaller, keep it uncompressed. */ |
679 | if (compressed_size >= uncompressed_size) | |
680 | { | |
681 | memcpy (buffer, input_buffer, uncompressed_size); | |
16fce1bd AM |
682 | if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) |
683 | elf_section_flags (sec) &= ~SHF_COMPRESSED; | |
758dd750 AM |
684 | sec->compress_status = COMPRESS_SECTION_NONE; |
685 | } | |
686 | else | |
687 | { | |
688 | sec->size = uncompressed_size; | |
689 | bfd_update_compression_header (abfd, buffer, sec); | |
690 | sec->size = compressed_size; | |
691 | sec->compress_status = COMPRESS_SECTION_DONE; | |
692 | } | |
151411f8 | 693 | sec->contents = buffer; |
206e9791 | 694 | sec->flags |= SEC_IN_MEMORY; |
758dd750 | 695 | free (input_buffer); |
151411f8 | 696 | return uncompressed_size; |
4a114e3e L |
697 | } |
698 | ||
699 | /* | |
700 | FUNCTION | |
701 | bfd_get_full_section_contents | |
702 | ||
703 | SYNOPSIS | |
0a1b45a2 | 704 | bool bfd_get_full_section_contents |
4a114e3e L |
705 | (bfd *abfd, asection *section, bfd_byte **ptr); |
706 | ||
707 | DESCRIPTION | |
708 | Read all data from @var{section} in BFD @var{abfd}, decompress | |
709 | if needed, and store in @var{*ptr}. If @var{*ptr} is NULL, | |
68ffbac6 | 710 | return @var{*ptr} with memory malloc'd by this function. |
4a114e3e L |
711 | |
712 | Return @code{TRUE} if the full section contents is retrieved | |
06614111 NC |
713 | successfully. If the section has no contents then this function |
714 | returns @code{TRUE} but @var{*ptr} is set to NULL. | |
4a114e3e L |
715 | */ |
716 | ||
0a1b45a2 | 717 | bool |
4a114e3e L |
718 | bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) |
719 | { | |
56ba7527 AM |
720 | bfd_size_type readsz = bfd_get_section_limit_octets (abfd, sec); |
721 | bfd_size_type allocsz = bfd_get_section_alloc_size (abfd, sec); | |
4a114e3e | 722 | bfd_byte *p = *ptr; |
0a1b45a2 | 723 | bool ret; |
38b774d2 AM |
724 | bfd_size_type save_size; |
725 | bfd_size_type save_rawsize; | |
4a114e3e | 726 | bfd_byte *compressed_buffer; |
151411f8 | 727 | unsigned int compression_header_size; |
2cac01e3 | 728 | const unsigned int compress_status = sec->compress_status; |
4a114e3e | 729 | |
56ba7527 | 730 | if (allocsz == 0) |
06614111 NC |
731 | { |
732 | *ptr = NULL; | |
0a1b45a2 | 733 | return true; |
06614111 | 734 | } |
4a114e3e | 735 | |
f7502dfe AM |
736 | if (p == NULL |
737 | && compress_status != COMPRESS_SECTION_DONE | |
738 | && _bfd_section_size_insane (abfd, sec)) | |
739 | { | |
740 | /* PR 24708: Avoid attempts to allocate a ridiculous amount | |
741 | of memory. */ | |
742 | _bfd_error_handler | |
743 | /* xgettext:c-format */ | |
744 | (_("error: %pB(%pA) is too large (%#" PRIx64 " bytes)"), | |
56ba7527 | 745 | abfd, sec, (uint64_t) readsz); |
f7502dfe AM |
746 | return false; |
747 | } | |
748 | ||
2cac01e3 | 749 | switch (compress_status) |
4a114e3e L |
750 | { |
751 | case COMPRESS_SECTION_NONE: | |
752 | if (p == NULL) | |
753 | { | |
56ba7527 | 754 | p = (bfd_byte *) bfd_malloc (allocsz); |
4a114e3e | 755 | if (p == NULL) |
a18590c3 NC |
756 | { |
757 | /* PR 20801: Provide a more helpful error message. */ | |
758 | if (bfd_get_error () == bfd_error_no_memory) | |
759 | _bfd_error_handler | |
760 | /* xgettext:c-format */ | |
2dcf00ce | 761 | (_("error: %pB(%pA) is too large (%#" PRIx64 " bytes)"), |
56ba7527 | 762 | abfd, sec, (uint64_t) allocsz); |
0a1b45a2 | 763 | return false; |
a18590c3 | 764 | } |
4a114e3e | 765 | } |
06614111 | 766 | |
56ba7527 | 767 | if (!bfd_get_section_contents (abfd, sec, p, 0, readsz)) |
82c6068a AM |
768 | { |
769 | if (*ptr != p) | |
770 | free (p); | |
0a1b45a2 | 771 | return false; |
82c6068a AM |
772 | } |
773 | *ptr = p; | |
0a1b45a2 | 774 | return true; |
4a114e3e | 775 | |
2cac01e3 FS |
776 | case DECOMPRESS_SECTION_ZLIB: |
777 | case DECOMPRESS_SECTION_ZSTD: | |
82c6068a | 778 | /* Read in the full compressed section contents. */ |
38b774d2 | 779 | compressed_buffer = (bfd_byte *) bfd_malloc (sec->compressed_size); |
82c6068a | 780 | if (compressed_buffer == NULL) |
0a1b45a2 | 781 | return false; |
38b774d2 AM |
782 | save_rawsize = sec->rawsize; |
783 | save_size = sec->size; | |
82c6068a AM |
784 | /* Clear rawsize, set size to compressed size and set compress_status |
785 | to COMPRESS_SECTION_NONE. If the compressed size is bigger than | |
786 | the uncompressed size, bfd_get_section_contents will fail. */ | |
787 | sec->rawsize = 0; | |
38b774d2 | 788 | sec->size = sec->compressed_size; |
82c6068a AM |
789 | sec->compress_status = COMPRESS_SECTION_NONE; |
790 | ret = bfd_get_section_contents (abfd, sec, compressed_buffer, | |
38b774d2 | 791 | 0, sec->compressed_size); |
82c6068a | 792 | /* Restore rawsize and size. */ |
38b774d2 AM |
793 | sec->rawsize = save_rawsize; |
794 | sec->size = save_size; | |
2cac01e3 | 795 | sec->compress_status = compress_status; |
82c6068a AM |
796 | if (!ret) |
797 | goto fail_compressed; | |
4a114e3e | 798 | |
38b774d2 | 799 | if (p == NULL) |
56ba7527 | 800 | p = (bfd_byte *) bfd_malloc (allocsz); |
38b774d2 | 801 | if (p == NULL) |
4a114e3e | 802 | goto fail_compressed; |
4a114e3e | 803 | |
151411f8 | 804 | compression_header_size = bfd_get_compression_header_size (abfd, sec); |
dab394de L |
805 | if (compression_header_size == 0) |
806 | /* Set header size to the zlib header size if it is a | |
807 | SHF_COMPRESSED section. */ | |
808 | compression_header_size = 12; | |
2cac01e3 FS |
809 | bool is_zstd = compress_status == DECOMPRESS_SECTION_ZSTD; |
810 | if (!decompress_contents ( | |
811 | is_zstd, compressed_buffer + compression_header_size, | |
56ba7527 | 812 | sec->compressed_size - compression_header_size, p, readsz)) |
82c6068a AM |
813 | { |
814 | bfd_set_error (bfd_error_bad_value); | |
38b774d2 AM |
815 | if (p != *ptr) |
816 | free (p); | |
82c6068a AM |
817 | fail_compressed: |
818 | free (compressed_buffer); | |
0a1b45a2 | 819 | return false; |
82c6068a | 820 | } |
4a114e3e | 821 | |
82c6068a | 822 | free (compressed_buffer); |
38b774d2 | 823 | *ptr = p; |
0a1b45a2 | 824 | return true; |
4a114e3e | 825 | |
82c6068a | 826 | case COMPRESS_SECTION_DONE: |
db6b071a | 827 | if (sec->contents == NULL) |
0a1b45a2 | 828 | return false; |
82c6068a AM |
829 | if (p == NULL) |
830 | { | |
56ba7527 | 831 | p = (bfd_byte *) bfd_malloc (allocsz); |
82c6068a | 832 | if (p == NULL) |
0a1b45a2 | 833 | return false; |
82c6068a AM |
834 | *ptr = p; |
835 | } | |
06614111 NC |
836 | /* PR 17512; file: 5bc29788. */ |
837 | if (p != sec->contents) | |
56ba7527 | 838 | memcpy (p, sec->contents, readsz); |
0a1b45a2 | 839 | return true; |
4a114e3e | 840 | |
82c6068a AM |
841 | default: |
842 | abort (); | |
843 | } | |
4a114e3e L |
844 | } |
845 | ||
846 | /* | |
847 | FUNCTION | |
758dd750 | 848 | bfd_is_section_compressed_info |
4a114e3e L |
849 | |
850 | SYNOPSIS | |
758dd750 | 851 | bool bfd_is_section_compressed_info |
151411f8 | 852 | (bfd *abfd, asection *section, |
758dd750 AM |
853 | int *compression_header_size_p, |
854 | bfd_size_type *uncompressed_size_p, | |
855 | unsigned int *uncompressed_alignment_power_p, | |
89dbeac7 | 856 | enum compression_type *ch_type); |
4a114e3e L |
857 | |
858 | DESCRIPTION | |
151411f8 | 859 | Return @code{TRUE} if @var{section} is compressed. Compression |
4207142d MW |
860 | header size is returned in @var{compression_header_size_p}, |
861 | uncompressed size is returned in @var{uncompressed_size_p} | |
862 | and the uncompressed data alignement power is returned in | |
863 | @var{uncompressed_align_pow_p}. If compression is | |
864 | unsupported, compression header size is returned with -1 | |
865 | and uncompressed size is returned with 0. | |
4a114e3e L |
866 | */ |
867 | ||
0a1b45a2 | 868 | bool |
758dd750 AM |
869 | bfd_is_section_compressed_info (bfd *abfd, sec_ptr sec, |
870 | int *compression_header_size_p, | |
871 | bfd_size_type *uncompressed_size_p, | |
872 | unsigned int *uncompressed_align_pow_p, | |
89dbeac7 | 873 | enum compression_type *ch_type) |
4a114e3e | 874 | { |
dab394de | 875 | bfd_byte header[MAX_COMPRESSION_HEADER_SIZE]; |
151411f8 | 876 | int compression_header_size; |
dab394de | 877 | int header_size; |
64f40162 | 878 | unsigned int saved = sec->compress_status; |
0a1b45a2 | 879 | bool compressed; |
64f40162 | 880 | |
131a5a64 L |
881 | *uncompressed_align_pow_p = 0; |
882 | ||
151411f8 L |
883 | compression_header_size = bfd_get_compression_header_size (abfd, sec); |
884 | if (compression_header_size > MAX_COMPRESSION_HEADER_SIZE) | |
885 | abort (); | |
dab394de | 886 | header_size = compression_header_size ? compression_header_size : 12; |
151411f8 | 887 | |
64f40162 L |
888 | /* Don't decompress the section. */ |
889 | sec->compress_status = COMPRESS_SECTION_NONE; | |
4a114e3e | 890 | |
dab394de L |
891 | /* Read the header. */ |
892 | if (bfd_get_section_contents (abfd, sec, header, 0, header_size)) | |
893 | { | |
894 | if (compression_header_size == 0) | |
07d6d2b8 | 895 | /* In this case, it should be "ZLIB" followed by the uncompressed |
dab394de | 896 | section size, 8 bytes in big-endian order. */ |
08dedd66 | 897 | compressed = startswith ((char*) header , "ZLIB"); |
dab394de | 898 | else |
0a1b45a2 | 899 | compressed = true; |
dab394de L |
900 | } |
901 | else | |
0a1b45a2 | 902 | compressed = false; |
64f40162 | 903 | |
dab394de | 904 | *uncompressed_size_p = sec->size; |
151411f8 L |
905 | if (compressed) |
906 | { | |
907 | if (compression_header_size != 0) | |
908 | { | |
758dd750 | 909 | if (!bfd_check_compression_header (abfd, header, sec, ch_type, |
4207142d MW |
910 | uncompressed_size_p, |
911 | uncompressed_align_pow_p)) | |
151411f8 L |
912 | compression_header_size = -1; |
913 | } | |
914 | /* Check for the pathalogical case of a debug string section that | |
915 | contains the string ZLIB.... as the first entry. We assume that | |
916 | no uncompressed .debug_str section would ever be big enough to | |
917 | have the first byte of its (big-endian) size be non-zero. */ | |
918 | else if (strcmp (sec->name, ".debug_str") == 0 | |
dab394de | 919 | && ISPRINT (header[4])) |
0a1b45a2 | 920 | compressed = false; |
dab394de L |
921 | else |
922 | *uncompressed_size_p = bfd_getb64 (header + 4); | |
151411f8 | 923 | } |
a953eec9 | 924 | |
64f40162 L |
925 | /* Restore compress_status. */ |
926 | sec->compress_status = saved; | |
151411f8 | 927 | *compression_header_size_p = compression_header_size; |
64f40162 | 928 | return compressed; |
4a114e3e L |
929 | } |
930 | ||
151411f8 L |
931 | /* |
932 | FUNCTION | |
933 | bfd_is_section_compressed | |
934 | ||
935 | SYNOPSIS | |
0a1b45a2 | 936 | bool bfd_is_section_compressed |
151411f8 L |
937 | (bfd *abfd, asection *section); |
938 | ||
939 | DESCRIPTION | |
940 | Return @code{TRUE} if @var{section} is compressed. | |
941 | */ | |
942 | ||
0a1b45a2 | 943 | bool |
151411f8 L |
944 | bfd_is_section_compressed (bfd *abfd, sec_ptr sec) |
945 | { | |
946 | int compression_header_size; | |
dab394de | 947 | bfd_size_type uncompressed_size; |
4207142d | 948 | unsigned int uncompressed_align_power; |
89dbeac7 | 949 | enum compression_type ch_type; |
758dd750 AM |
950 | return (bfd_is_section_compressed_info (abfd, sec, |
951 | &compression_header_size, | |
952 | &uncompressed_size, | |
953 | &uncompressed_align_power, | |
954 | &ch_type) | |
dab394de L |
955 | && compression_header_size >= 0 |
956 | && uncompressed_size > 0); | |
151411f8 L |
957 | } |
958 | ||
4a114e3e L |
959 | /* |
960 | FUNCTION | |
961 | bfd_init_section_decompress_status | |
962 | ||
963 | SYNOPSIS | |
0a1b45a2 | 964 | bool bfd_init_section_decompress_status |
4a114e3e L |
965 | (bfd *abfd, asection *section); |
966 | ||
967 | DESCRIPTION | |
968 | Record compressed section size, update section size with | |
969 | decompressed size and set compress_status to | |
2cac01e3 | 970 | DECOMPRESS_SECTION_{ZLIB,ZSTD}. |
4a114e3e L |
971 | |
972 | Return @code{FALSE} if the section is not a valid compressed | |
18ece1de | 973 | section. Otherwise, return @code{TRUE}. |
4a114e3e L |
974 | */ |
975 | ||
0a1b45a2 | 976 | bool |
243340ad | 977 | bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec) |
4a114e3e | 978 | { |
dab394de | 979 | bfd_byte header[MAX_COMPRESSION_HEADER_SIZE]; |
151411f8 | 980 | int compression_header_size; |
dab394de | 981 | int header_size; |
4a114e3e | 982 | bfd_size_type uncompressed_size; |
4207142d | 983 | unsigned int uncompressed_alignment_power = 0; |
89dbeac7 | 984 | enum compression_type ch_type; |
c5967f38 | 985 | z_stream strm; |
4a114e3e | 986 | |
151411f8 L |
987 | compression_header_size = bfd_get_compression_header_size (abfd, sec); |
988 | if (compression_header_size > MAX_COMPRESSION_HEADER_SIZE) | |
989 | abort (); | |
dab394de | 990 | header_size = compression_header_size ? compression_header_size : 12; |
151411f8 | 991 | |
dab394de | 992 | /* Read the header. */ |
4a114e3e L |
993 | if (sec->rawsize != 0 |
994 | || sec->contents != NULL | |
995 | || sec->compress_status != COMPRESS_SECTION_NONE | |
151411f8 | 996 | || !bfd_get_section_contents (abfd, sec, header, 0, header_size)) |
4a114e3e L |
997 | { |
998 | bfd_set_error (bfd_error_invalid_operation); | |
0a1b45a2 | 999 | return false; |
4a114e3e | 1000 | } |
1b315056 | 1001 | |
dab394de | 1002 | if (compression_header_size == 0) |
4a114e3e | 1003 | { |
dab394de L |
1004 | /* In this case, it should be "ZLIB" followed by the uncompressed |
1005 | section size, 8 bytes in big-endian order. */ | |
08dedd66 | 1006 | if (! startswith ((char*) header, "ZLIB")) |
dab394de L |
1007 | { |
1008 | bfd_set_error (bfd_error_wrong_format); | |
0a1b45a2 | 1009 | return false; |
dab394de L |
1010 | } |
1011 | uncompressed_size = bfd_getb64 (header + 4); | |
89dbeac7 | 1012 | ch_type = ch_none; |
4a114e3e | 1013 | } |
dab394de | 1014 | else if (!bfd_check_compression_header (abfd, header, sec, |
2cac01e3 | 1015 | &ch_type, |
4207142d MW |
1016 | &uncompressed_size, |
1017 | &uncompressed_alignment_power)) | |
151411f8 L |
1018 | { |
1019 | bfd_set_error (bfd_error_wrong_format); | |
0a1b45a2 | 1020 | return false; |
151411f8 | 1021 | } |
dab394de | 1022 | |
c5967f38 AM |
1023 | /* PR28530, reject sizes unsupported by decompress_contents. */ |
1024 | strm.avail_in = sec->size; | |
1025 | strm.avail_out = uncompressed_size; | |
1026 | if (strm.avail_in != sec->size || strm.avail_out != uncompressed_size) | |
1027 | { | |
1028 | bfd_set_error (bfd_error_nonrepresentable_section); | |
1029 | return false; | |
1030 | } | |
1031 | ||
4a114e3e L |
1032 | sec->compressed_size = sec->size; |
1033 | sec->size = uncompressed_size; | |
fd361982 | 1034 | bfd_set_section_alignment (sec, uncompressed_alignment_power); |
89dbeac7 | 1035 | sec->compress_status = (ch_type == ch_compress_zstd |
2cac01e3 | 1036 | ? DECOMPRESS_SECTION_ZSTD : DECOMPRESS_SECTION_ZLIB); |
1b315056 | 1037 | |
0a1b45a2 | 1038 | return true; |
4a114e3e L |
1039 | } |
1040 | ||
1041 | /* | |
1042 | FUNCTION | |
1043 | bfd_init_section_compress_status | |
1044 | ||
1045 | SYNOPSIS | |
0a1b45a2 | 1046 | bool bfd_init_section_compress_status |
4a114e3e L |
1047 | (bfd *abfd, asection *section); |
1048 | ||
1049 | DESCRIPTION | |
1050 | If open for read, compress section, update section size with | |
1051 | compressed size and set compress_status to COMPRESS_SECTION_DONE. | |
1052 | ||
1053 | Return @code{FALSE} if the section is not a valid compressed | |
18ece1de | 1054 | section. Otherwise, return @code{TRUE}. |
4a114e3e L |
1055 | */ |
1056 | ||
0a1b45a2 | 1057 | bool |
243340ad | 1058 | bfd_init_section_compress_status (bfd *abfd, sec_ptr sec) |
4a114e3e | 1059 | { |
4a114e3e L |
1060 | bfd_size_type uncompressed_size; |
1061 | bfd_byte *uncompressed_buffer; | |
4a114e3e L |
1062 | |
1063 | /* Error if not opened for read. */ | |
1064 | if (abfd->direction != read_direction | |
1065 | || sec->size == 0 | |
1066 | || sec->rawsize != 0 | |
1067 | || sec->contents != NULL | |
1068 | || sec->compress_status != COMPRESS_SECTION_NONE) | |
1b315056 | 1069 | { |
4a114e3e | 1070 | bfd_set_error (bfd_error_invalid_operation); |
0a1b45a2 | 1071 | return false; |
1b315056 | 1072 | } |
1b315056 | 1073 | |
4a114e3e L |
1074 | /* Read in the full section contents and compress it. */ |
1075 | uncompressed_size = sec->size; | |
1076 | uncompressed_buffer = (bfd_byte *) bfd_malloc (uncompressed_size); | |
e63d1232 NC |
1077 | /* PR 21431 */ |
1078 | if (uncompressed_buffer == NULL) | |
0a1b45a2 | 1079 | return false; |
e63d1232 | 1080 | |
4a114e3e L |
1081 | if (!bfd_get_section_contents (abfd, sec, uncompressed_buffer, |
1082 | 0, uncompressed_size)) | |
38990312 AM |
1083 | { |
1084 | free (uncompressed_buffer); | |
1085 | return false; | |
1086 | } | |
1b315056 | 1087 | |
758dd750 AM |
1088 | sec->contents = uncompressed_buffer; |
1089 | if (bfd_compress_section_contents (abfd, sec) == 0) | |
1090 | { | |
1091 | free (sec->contents); | |
1092 | sec->contents = NULL; | |
1093 | return false; | |
1094 | } | |
1095 | return true; | |
1b315056 | 1096 | } |
0ce398f1 L |
1097 | |
1098 | /* | |
1099 | FUNCTION | |
1100 | bfd_compress_section | |
1101 | ||
1102 | SYNOPSIS | |
0a1b45a2 | 1103 | bool bfd_compress_section |
0ce398f1 L |
1104 | (bfd *abfd, asection *section, bfd_byte *uncompressed_buffer); |
1105 | ||
1106 | DESCRIPTION | |
1107 | If open for write, compress section, update section size with | |
1108 | compressed size and set compress_status to COMPRESS_SECTION_DONE. | |
1109 | ||
1110 | Return @code{FALSE} if compression fail. Otherwise, return | |
758dd750 | 1111 | @code{TRUE}. UNCOMPRESSED_BUFFER is freed in both cases. |
0ce398f1 L |
1112 | */ |
1113 | ||
0a1b45a2 | 1114 | bool |
0ce398f1 L |
1115 | bfd_compress_section (bfd *abfd, sec_ptr sec, bfd_byte *uncompressed_buffer) |
1116 | { | |
1117 | bfd_size_type uncompressed_size = sec->size; | |
1118 | ||
1119 | /* Error if not opened for write. */ | |
1120 | if (abfd->direction != write_direction | |
1121 | || uncompressed_size == 0 | |
1122 | || uncompressed_buffer == NULL | |
1123 | || sec->contents != NULL | |
1124 | || sec->compressed_size != 0 | |
1125 | || sec->compress_status != COMPRESS_SECTION_NONE) | |
1126 | { | |
1127 | bfd_set_error (bfd_error_invalid_operation); | |
0a1b45a2 | 1128 | return false; |
0ce398f1 L |
1129 | } |
1130 | ||
758dd750 AM |
1131 | sec->contents = uncompressed_buffer; |
1132 | if (bfd_compress_section_contents (abfd, sec) == 0) | |
1133 | { | |
1134 | free (sec->contents); | |
1135 | sec->contents = NULL; | |
1136 | return false; | |
1137 | } | |
1138 | return true; | |
0ce398f1 | 1139 | } |