]>
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. | |
266 | ||
267 | RETURNS | |
268 | Return the size of the compression header in bytes. | |
269 | */ | |
270 | ||
271 | int | |
272 | bfd_get_compression_header_size (bfd *abfd, asection *sec) | |
273 | { | |
274 | if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) | |
275 | { | |
276 | if (sec == NULL) | |
277 | { | |
278 | if (!(abfd->flags & BFD_COMPRESS_GABI)) | |
279 | return 0; | |
280 | } | |
281 | else if (!(elf_section_flags (sec) & SHF_COMPRESSED)) | |
282 | return 0; | |
283 | ||
284 | if (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS32) | |
285 | return sizeof (Elf32_External_Chdr); | |
286 | else | |
287 | return sizeof (Elf64_External_Chdr); | |
288 | } | |
289 | ||
290 | return 0; | |
291 | } | |
292 | ||
293 | /* | |
294 | FUNCTION | |
7b5f66a1 | 295 | bfd_convert_section_setup |
89dbeac7 AM |
296 | |
297 | SYNOPSIS | |
7b5f66a1 AM |
298 | bool bfd_convert_section_setup |
299 | (bfd *ibfd, asection *isec, bfd *obfd, | |
300 | const char **new_name, bfd_size_type *new_size); | |
89dbeac7 AM |
301 | |
302 | DESCRIPTION | |
7b5f66a1 AM |
303 | Do early setup for objcopy, when copying @var{isec} in input |
304 | BFD @var{ibfd} to output BFD @var{obfd}. Returns the name and | |
305 | size of the output section. | |
89dbeac7 AM |
306 | */ |
307 | ||
7b5f66a1 AM |
308 | bool |
309 | bfd_convert_section_setup (bfd *ibfd, asection *isec, bfd *obfd, | |
310 | const char **new_name, bfd_size_type *new_size) | |
89dbeac7 AM |
311 | { |
312 | bfd_size_type hdr_size; | |
313 | ||
7b5f66a1 AM |
314 | if ((isec->flags & SEC_DEBUGGING) != 0 |
315 | && (isec->flags & SEC_HAS_CONTENTS) != 0) | |
316 | { | |
317 | const char *name = *new_name; | |
318 | ||
c3620d6d | 319 | if ((obfd->flags & (BFD_DECOMPRESS | BFD_COMPRESS_GABI)) != 0) |
7b5f66a1 AM |
320 | { |
321 | /* When we decompress or compress with SHF_COMPRESSED, | |
322 | convert section name from .zdebug_* to .debug_*. */ | |
323 | if (startswith (name, ".zdebug_")) | |
324 | { | |
325 | name = bfd_zdebug_name_to_debug (obfd, name); | |
326 | if (name == NULL) | |
327 | return false; | |
328 | } | |
329 | } | |
330 | ||
331 | /* PR binutils/18087: Compression does not always make a | |
332 | section smaller. So only rename the section when | |
333 | compression has actually taken place. If input section | |
334 | name is .zdebug_*, we should never compress it again. */ | |
335 | else if (isec->compress_status == COMPRESS_SECTION_DONE | |
336 | && startswith (name, ".debug_")) | |
337 | { | |
338 | name = bfd_debug_name_to_zdebug (obfd, name); | |
339 | if (name == NULL) | |
340 | return false; | |
341 | } | |
342 | *new_name = name; | |
343 | } | |
344 | *new_size = bfd_section_size (isec); | |
345 | ||
89dbeac7 AM |
346 | /* Do nothing if either input or output aren't ELF. */ |
347 | if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour | |
348 | || bfd_get_flavour (obfd) != bfd_target_elf_flavour) | |
7b5f66a1 | 349 | return true; |
89dbeac7 AM |
350 | |
351 | /* Do nothing if ELF classes of input and output are the same. */ | |
352 | if (get_elf_backend_data (ibfd)->s->elfclass | |
353 | == get_elf_backend_data (obfd)->s->elfclass) | |
7b5f66a1 | 354 | return true; |
89dbeac7 AM |
355 | |
356 | /* Convert GNU property size. */ | |
357 | if (startswith (isec->name, NOTE_GNU_PROPERTY_SECTION_NAME)) | |
7b5f66a1 AM |
358 | { |
359 | *new_size = _bfd_elf_convert_gnu_property_size (ibfd, obfd); | |
360 | return true; | |
361 | } | |
89dbeac7 AM |
362 | |
363 | /* Do nothing if input file will be decompressed. */ | |
364 | if ((ibfd->flags & BFD_DECOMPRESS)) | |
7b5f66a1 | 365 | return true; |
89dbeac7 AM |
366 | |
367 | /* Do nothing if the input section isn't a SHF_COMPRESSED section. */ | |
368 | hdr_size = bfd_get_compression_header_size (ibfd, isec); | |
369 | if (hdr_size == 0) | |
7b5f66a1 | 370 | return true; |
89dbeac7 AM |
371 | |
372 | /* Adjust the size of the output SHF_COMPRESSED section. */ | |
373 | if (hdr_size == sizeof (Elf32_External_Chdr)) | |
7b5f66a1 | 374 | *new_size += sizeof (Elf64_External_Chdr) - sizeof (Elf32_External_Chdr); |
89dbeac7 | 375 | else |
e2546673 | 376 | *new_size -= sizeof (Elf64_External_Chdr) - sizeof (Elf32_External_Chdr); |
7b5f66a1 | 377 | return true; |
89dbeac7 AM |
378 | } |
379 | ||
380 | /* | |
381 | FUNCTION | |
382 | bfd_convert_section_contents | |
383 | ||
384 | SYNOPSIS | |
385 | bool bfd_convert_section_contents | |
386 | (bfd *ibfd, asection *isec, bfd *obfd, | |
387 | bfd_byte **ptr, bfd_size_type *ptr_size); | |
388 | ||
389 | DESCRIPTION | |
390 | Convert the contents, stored in @var{*ptr}, of the section | |
391 | @var{isec} in input BFD @var{ibfd} to output BFD @var{obfd} | |
392 | if needed. The original buffer pointed to by @var{*ptr} may | |
393 | be freed and @var{*ptr} is returned with memory malloc'd by this | |
394 | function, and the new size written to @var{ptr_size}. | |
395 | */ | |
396 | ||
397 | bool | |
398 | bfd_convert_section_contents (bfd *ibfd, sec_ptr isec, bfd *obfd, | |
399 | bfd_byte **ptr, bfd_size_type *ptr_size) | |
400 | { | |
401 | bfd_byte *contents; | |
402 | bfd_size_type ihdr_size, ohdr_size, size; | |
403 | Elf_Internal_Chdr chdr; | |
404 | bool use_memmove; | |
405 | ||
406 | /* Do nothing if either input or output aren't ELF. */ | |
407 | if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour | |
408 | || bfd_get_flavour (obfd) != bfd_target_elf_flavour) | |
409 | return true; | |
410 | ||
411 | /* Do nothing if ELF classes of input and output are the same. */ | |
412 | if (get_elf_backend_data (ibfd)->s->elfclass | |
413 | == get_elf_backend_data (obfd)->s->elfclass) | |
414 | return true; | |
415 | ||
416 | /* Convert GNU properties. */ | |
417 | if (startswith (isec->name, NOTE_GNU_PROPERTY_SECTION_NAME)) | |
418 | return _bfd_elf_convert_gnu_properties (ibfd, isec, obfd, ptr, | |
419 | ptr_size); | |
420 | ||
421 | /* Do nothing if input file will be decompressed. */ | |
422 | if ((ibfd->flags & BFD_DECOMPRESS)) | |
423 | return true; | |
424 | ||
425 | /* Do nothing if the input section isn't a SHF_COMPRESSED section. */ | |
426 | ihdr_size = bfd_get_compression_header_size (ibfd, isec); | |
427 | if (ihdr_size == 0) | |
428 | return true; | |
429 | ||
430 | /* PR 25221. Check for corrupt input sections. */ | |
431 | if (ihdr_size > bfd_get_section_limit (ibfd, isec)) | |
432 | /* FIXME: Issue a warning about a corrupt | |
433 | compression header size field ? */ | |
434 | return false; | |
435 | ||
436 | contents = *ptr; | |
437 | ||
438 | /* Convert the contents of the input SHF_COMPRESSED section to | |
439 | output. Get the input compression header and the size of the | |
440 | output compression header. */ | |
441 | if (ihdr_size == sizeof (Elf32_External_Chdr)) | |
442 | { | |
443 | Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents; | |
444 | chdr.ch_type = bfd_get_32 (ibfd, &echdr->ch_type); | |
445 | chdr.ch_size = bfd_get_32 (ibfd, &echdr->ch_size); | |
446 | chdr.ch_addralign = bfd_get_32 (ibfd, &echdr->ch_addralign); | |
447 | ||
448 | ohdr_size = sizeof (Elf64_External_Chdr); | |
449 | ||
450 | use_memmove = false; | |
451 | } | |
452 | else if (ihdr_size != sizeof (Elf64_External_Chdr)) | |
453 | { | |
454 | /* FIXME: Issue a warning about a corrupt | |
455 | compression header size field ? */ | |
456 | return false; | |
457 | } | |
458 | else | |
459 | { | |
460 | Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents; | |
461 | chdr.ch_type = bfd_get_32 (ibfd, &echdr->ch_type); | |
462 | chdr.ch_size = bfd_get_64 (ibfd, &echdr->ch_size); | |
463 | chdr.ch_addralign = bfd_get_64 (ibfd, &echdr->ch_addralign); | |
464 | ||
465 | ohdr_size = sizeof (Elf32_External_Chdr); | |
466 | use_memmove = true; | |
467 | } | |
468 | ||
469 | size = bfd_section_size (isec) - ihdr_size + ohdr_size; | |
470 | if (!use_memmove) | |
471 | { | |
472 | contents = (bfd_byte *) bfd_malloc (size); | |
473 | if (contents == NULL) | |
474 | return false; | |
475 | } | |
476 | ||
477 | /* Write out the output compression header. */ | |
478 | if (ohdr_size == sizeof (Elf32_External_Chdr)) | |
479 | { | |
480 | Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents; | |
481 | bfd_put_32 (obfd, chdr.ch_type, &echdr->ch_type); | |
482 | bfd_put_32 (obfd, chdr.ch_size, &echdr->ch_size); | |
483 | bfd_put_32 (obfd, chdr.ch_addralign, &echdr->ch_addralign); | |
484 | } | |
485 | else | |
486 | { | |
487 | Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents; | |
488 | bfd_put_32 (obfd, chdr.ch_type, &echdr->ch_type); | |
489 | bfd_put_32 (obfd, 0, &echdr->ch_reserved); | |
490 | bfd_put_64 (obfd, chdr.ch_size, &echdr->ch_size); | |
491 | bfd_put_64 (obfd, chdr.ch_addralign, &echdr->ch_addralign); | |
492 | } | |
493 | ||
494 | /* Copy the compressed contents. */ | |
495 | if (use_memmove) | |
496 | memmove (contents + ohdr_size, *ptr + ihdr_size, size - ohdr_size); | |
497 | else | |
498 | { | |
499 | memcpy (contents + ohdr_size, *ptr + ihdr_size, size - ohdr_size); | |
500 | free (*ptr); | |
501 | *ptr = contents; | |
502 | } | |
503 | ||
504 | *ptr_size = size; | |
505 | return true; | |
506 | } | |
507 | ||
0a1b45a2 | 508 | static bool |
2cac01e3 | 509 | decompress_contents (bool is_zstd, bfd_byte *compressed_buffer, |
4a114e3e L |
510 | bfd_size_type compressed_size, |
511 | bfd_byte *uncompressed_buffer, | |
512 | bfd_size_type uncompressed_size) | |
513 | { | |
2cac01e3 FS |
514 | if (is_zstd) |
515 | { | |
516 | #ifdef HAVE_ZSTD | |
517 | size_t ret = ZSTD_decompress (uncompressed_buffer, uncompressed_size, | |
518 | compressed_buffer, compressed_size); | |
519 | return !ZSTD_isError (ret); | |
520 | #endif | |
521 | } | |
522 | ||
4a114e3e L |
523 | z_stream strm; |
524 | int rc; | |
525 | ||
526 | /* It is possible the section consists of several compressed | |
527 | buffers concatenated together, so we uncompress in a loop. */ | |
de13ef81 NC |
528 | /* PR 18313: The state field in the z_stream structure is supposed |
529 | to be invisible to the user (ie us), but some compilers will | |
530 | still complain about it being used without initialisation. So | |
531 | we first zero the entire z_stream structure and then set the fields | |
532 | that we need. */ | |
533 | memset (& strm, 0, sizeof strm); | |
dab394de L |
534 | strm.avail_in = compressed_size; |
535 | strm.next_in = (Bytef*) compressed_buffer; | |
4a114e3e | 536 | strm.avail_out = uncompressed_size; |
c5967f38 AM |
537 | /* FIXME: strm.avail_in and strm.avail_out are typically unsigned |
538 | int. Supporting sizes that don't fit in an unsigned int is | |
539 | possible but will require some rewriting of this function. */ | |
540 | if (strm.avail_in != compressed_size || strm.avail_out != uncompressed_size) | |
541 | return false; | |
4a114e3e | 542 | |
a253d456 | 543 | BFD_ASSERT (Z_OK == 0); |
4a114e3e | 544 | rc = inflateInit (&strm); |
a29a8af8 | 545 | while (strm.avail_in > 0 && strm.avail_out > 0) |
4a114e3e L |
546 | { |
547 | if (rc != Z_OK) | |
a253d456 | 548 | break; |
4a114e3e | 549 | strm.next_out = ((Bytef*) uncompressed_buffer |
07d6d2b8 | 550 | + (uncompressed_size - strm.avail_out)); |
4a114e3e L |
551 | rc = inflate (&strm, Z_FINISH); |
552 | if (rc != Z_STREAM_END) | |
a253d456 | 553 | break; |
4a114e3e L |
554 | rc = inflateReset (&strm); |
555 | } | |
ad92f33d | 556 | return inflateEnd (&strm) == Z_OK && rc == Z_OK && strm.avail_out == 0; |
4a114e3e | 557 | } |
4a114e3e | 558 | |
758dd750 | 559 | /* Compress section contents using zlib/zstd and store |
0b0732e1 | 560 | as the contents field. This function assumes the contents |
18ece1de | 561 | field was allocated using bfd_malloc() or equivalent. |
1b315056 | 562 | |
151411f8 L |
563 | Return the uncompressed size if the full section contents is |
564 | compressed successfully. Otherwise return 0. */ | |
1b315056 | 565 | |
151411f8 | 566 | static bfd_size_type |
758dd750 | 567 | bfd_compress_section_contents (bfd *abfd, sec_ptr sec) |
1b315056 | 568 | { |
758dd750 | 569 | bfd_byte *input_buffer; |
ae6a0217 | 570 | uLong compressed_size; |
151411f8 L |
571 | bfd_byte *buffer; |
572 | bfd_size_type buffer_size; | |
51509926 | 573 | int zlib_size = 0; |
758dd750 AM |
574 | int orig_header_size; |
575 | bfd_size_type uncompressed_size; | |
576 | unsigned int uncompressed_alignment_pow; | |
89dbeac7 | 577 | enum compression_type ch_type = ch_none; |
758dd750 | 578 | int new_header_size = bfd_get_compression_header_size (abfd, NULL); |
0a1b45a2 | 579 | bool compressed |
758dd750 AM |
580 | = bfd_is_section_compressed_info (abfd, sec, |
581 | &orig_header_size, | |
582 | &uncompressed_size, | |
583 | &uncompressed_alignment_pow, | |
584 | &ch_type); | |
585 | bool update = false; | |
586 | ||
587 | /* We shouldn't be trying to decompress unsupported compressed sections. */ | |
588 | if (compressed && orig_header_size < 0) | |
589 | abort (); | |
dab394de L |
590 | |
591 | /* Either ELF compression header or the 12-byte, "ZLIB" + 8-byte size, | |
592 | overhead in .zdebug* section. */ | |
758dd750 AM |
593 | if (!new_header_size) |
594 | new_header_size = 12; | |
89dbeac7 | 595 | if (ch_type == ch_none) |
758dd750 | 596 | orig_header_size = 12; |
151411f8 | 597 | |
758dd750 | 598 | input_buffer = sec->contents; |
151411f8 L |
599 | if (compressed) |
600 | { | |
758dd750 AM |
601 | zlib_size = sec->size - orig_header_size; |
602 | compressed_size = zlib_size + new_header_size; | |
4281caad | 603 | |
758dd750 AM |
604 | /* If we are converting between zlib-gnu and zlib-gabi then the |
605 | compressed contents just need to be moved. */ | |
89dbeac7 | 606 | update = (ch_type < ch_compress_zstd |
758dd750 | 607 | && (abfd->flags & BFD_COMPRESS_ZSTD) == 0); |
4a114e3e | 608 | |
758dd750 AM |
609 | /* Uncompress when not just moving contents or when compressed |
610 | is not smaller than uncompressed. */ | |
611 | if (!update || compressed_size >= uncompressed_size) | |
151411f8 | 612 | { |
758dd750 AM |
613 | buffer_size = uncompressed_size; |
614 | buffer = bfd_malloc (buffer_size); | |
615 | if (buffer == NULL) | |
616 | return 0; | |
617 | ||
89dbeac7 | 618 | if (!decompress_contents (ch_type == ch_compress_zstd, |
758dd750 AM |
619 | input_buffer + orig_header_size, |
620 | zlib_size, buffer, buffer_size)) | |
151411f8 L |
621 | { |
622 | bfd_set_error (bfd_error_bad_value); | |
758dd750 | 623 | free (buffer); |
151411f8 L |
624 | return 0; |
625 | } | |
758dd750 AM |
626 | free (input_buffer); |
627 | bfd_set_section_alignment (sec, uncompressed_alignment_pow); | |
151411f8 | 628 | sec->contents = buffer; |
206e9791 AM |
629 | sec->flags |= SEC_IN_MEMORY; |
630 | sec->compress_status = COMPRESS_SECTION_NONE; | |
758dd750 AM |
631 | sec->size = uncompressed_size; |
632 | input_buffer = buffer; | |
151411f8 | 633 | } |
8d001214 | 634 | } |
758dd750 AM |
635 | |
636 | if (!update) | |
637 | compressed_size = compressBound (uncompressed_size) + new_header_size; | |
638 | ||
639 | buffer_size = compressed_size; | |
640 | buffer = bfd_alloc (abfd, buffer_size); | |
641 | if (buffer == NULL) | |
642 | return 0; | |
643 | ||
644 | if (update) | |
645 | { | |
646 | if (compressed_size < uncompressed_size) | |
647 | memcpy (buffer + new_header_size, | |
648 | input_buffer + orig_header_size, | |
649 | zlib_size); | |
650 | } | |
8d001214 L |
651 | else |
652 | { | |
2cac01e3 FS |
653 | if (abfd->flags & BFD_COMPRESS_ZSTD) |
654 | { | |
655 | #if HAVE_ZSTD | |
758dd750 AM |
656 | compressed_size = ZSTD_compress (buffer + new_header_size, |
657 | compressed_size, | |
658 | input_buffer, | |
659 | uncompressed_size, | |
660 | ZSTD_CLEVEL_DEFAULT); | |
2cac01e3 FS |
661 | if (ZSTD_isError (compressed_size)) |
662 | { | |
663 | bfd_release (abfd, buffer); | |
664 | bfd_set_error (bfd_error_bad_value); | |
665 | return 0; | |
666 | } | |
667 | #endif | |
668 | } | |
758dd750 AM |
669 | else if (compress ((Bytef *) buffer + new_header_size, &compressed_size, |
670 | (const Bytef *) input_buffer, uncompressed_size) | |
2cac01e3 | 671 | != Z_OK) |
151411f8 | 672 | { |
030aeb75 | 673 | bfd_release (abfd, buffer); |
151411f8 L |
674 | bfd_set_error (bfd_error_bad_value); |
675 | return 0; | |
676 | } | |
677 | ||
758dd750 | 678 | compressed_size += new_header_size; |
8d001214 | 679 | } |
4a114e3e | 680 | |
758dd750 AM |
681 | /* If compression didn't make the section smaller, keep it uncompressed. */ |
682 | if (compressed_size >= uncompressed_size) | |
683 | { | |
684 | memcpy (buffer, input_buffer, uncompressed_size); | |
16fce1bd AM |
685 | if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) |
686 | elf_section_flags (sec) &= ~SHF_COMPRESSED; | |
758dd750 AM |
687 | sec->compress_status = COMPRESS_SECTION_NONE; |
688 | } | |
689 | else | |
690 | { | |
691 | sec->size = uncompressed_size; | |
692 | bfd_update_compression_header (abfd, buffer, sec); | |
693 | sec->size = compressed_size; | |
694 | sec->compress_status = COMPRESS_SECTION_DONE; | |
695 | } | |
151411f8 | 696 | sec->contents = buffer; |
206e9791 | 697 | sec->flags |= SEC_IN_MEMORY; |
758dd750 | 698 | free (input_buffer); |
151411f8 | 699 | return uncompressed_size; |
4a114e3e L |
700 | } |
701 | ||
702 | /* | |
703 | FUNCTION | |
704 | bfd_get_full_section_contents | |
705 | ||
706 | SYNOPSIS | |
0a1b45a2 | 707 | bool bfd_get_full_section_contents |
4a114e3e L |
708 | (bfd *abfd, asection *section, bfd_byte **ptr); |
709 | ||
710 | DESCRIPTION | |
711 | Read all data from @var{section} in BFD @var{abfd}, decompress | |
712 | if needed, and store in @var{*ptr}. If @var{*ptr} is NULL, | |
68ffbac6 | 713 | return @var{*ptr} with memory malloc'd by this function. |
4a114e3e L |
714 | |
715 | Return @code{TRUE} if the full section contents is retrieved | |
06614111 NC |
716 | successfully. If the section has no contents then this function |
717 | returns @code{TRUE} but @var{*ptr} is set to NULL. | |
4a114e3e L |
718 | */ |
719 | ||
0a1b45a2 | 720 | bool |
4a114e3e L |
721 | bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) |
722 | { | |
56ba7527 AM |
723 | bfd_size_type readsz = bfd_get_section_limit_octets (abfd, sec); |
724 | bfd_size_type allocsz = bfd_get_section_alloc_size (abfd, sec); | |
4a114e3e | 725 | bfd_byte *p = *ptr; |
0a1b45a2 | 726 | bool ret; |
38b774d2 AM |
727 | bfd_size_type save_size; |
728 | bfd_size_type save_rawsize; | |
4a114e3e | 729 | bfd_byte *compressed_buffer; |
151411f8 | 730 | unsigned int compression_header_size; |
2cac01e3 | 731 | const unsigned int compress_status = sec->compress_status; |
4a114e3e | 732 | |
56ba7527 | 733 | if (allocsz == 0) |
06614111 NC |
734 | { |
735 | *ptr = NULL; | |
0a1b45a2 | 736 | return true; |
06614111 | 737 | } |
4a114e3e | 738 | |
f7502dfe AM |
739 | if (p == NULL |
740 | && compress_status != COMPRESS_SECTION_DONE | |
741 | && _bfd_section_size_insane (abfd, sec)) | |
742 | { | |
743 | /* PR 24708: Avoid attempts to allocate a ridiculous amount | |
744 | of memory. */ | |
745 | _bfd_error_handler | |
746 | /* xgettext:c-format */ | |
747 | (_("error: %pB(%pA) is too large (%#" PRIx64 " bytes)"), | |
56ba7527 | 748 | abfd, sec, (uint64_t) readsz); |
f7502dfe AM |
749 | return false; |
750 | } | |
751 | ||
2cac01e3 | 752 | switch (compress_status) |
4a114e3e L |
753 | { |
754 | case COMPRESS_SECTION_NONE: | |
755 | if (p == NULL) | |
756 | { | |
56ba7527 | 757 | p = (bfd_byte *) bfd_malloc (allocsz); |
4a114e3e | 758 | if (p == NULL) |
a18590c3 NC |
759 | { |
760 | /* PR 20801: Provide a more helpful error message. */ | |
761 | if (bfd_get_error () == bfd_error_no_memory) | |
762 | _bfd_error_handler | |
763 | /* xgettext:c-format */ | |
2dcf00ce | 764 | (_("error: %pB(%pA) is too large (%#" PRIx64 " bytes)"), |
56ba7527 | 765 | abfd, sec, (uint64_t) allocsz); |
0a1b45a2 | 766 | return false; |
a18590c3 | 767 | } |
4a114e3e | 768 | } |
06614111 | 769 | |
56ba7527 | 770 | if (!bfd_get_section_contents (abfd, sec, p, 0, readsz)) |
82c6068a AM |
771 | { |
772 | if (*ptr != p) | |
773 | free (p); | |
0a1b45a2 | 774 | return false; |
82c6068a AM |
775 | } |
776 | *ptr = p; | |
0a1b45a2 | 777 | return true; |
4a114e3e | 778 | |
2cac01e3 FS |
779 | case DECOMPRESS_SECTION_ZLIB: |
780 | case DECOMPRESS_SECTION_ZSTD: | |
82c6068a | 781 | /* Read in the full compressed section contents. */ |
38b774d2 | 782 | compressed_buffer = (bfd_byte *) bfd_malloc (sec->compressed_size); |
82c6068a | 783 | if (compressed_buffer == NULL) |
0a1b45a2 | 784 | return false; |
38b774d2 AM |
785 | save_rawsize = sec->rawsize; |
786 | save_size = sec->size; | |
82c6068a AM |
787 | /* Clear rawsize, set size to compressed size and set compress_status |
788 | to COMPRESS_SECTION_NONE. If the compressed size is bigger than | |
789 | the uncompressed size, bfd_get_section_contents will fail. */ | |
790 | sec->rawsize = 0; | |
38b774d2 | 791 | sec->size = sec->compressed_size; |
82c6068a AM |
792 | sec->compress_status = COMPRESS_SECTION_NONE; |
793 | ret = bfd_get_section_contents (abfd, sec, compressed_buffer, | |
38b774d2 | 794 | 0, sec->compressed_size); |
82c6068a | 795 | /* Restore rawsize and size. */ |
38b774d2 AM |
796 | sec->rawsize = save_rawsize; |
797 | sec->size = save_size; | |
2cac01e3 | 798 | sec->compress_status = compress_status; |
82c6068a AM |
799 | if (!ret) |
800 | goto fail_compressed; | |
4a114e3e | 801 | |
38b774d2 | 802 | if (p == NULL) |
56ba7527 | 803 | p = (bfd_byte *) bfd_malloc (allocsz); |
38b774d2 | 804 | if (p == NULL) |
4a114e3e | 805 | goto fail_compressed; |
4a114e3e | 806 | |
151411f8 | 807 | compression_header_size = bfd_get_compression_header_size (abfd, sec); |
dab394de L |
808 | if (compression_header_size == 0) |
809 | /* Set header size to the zlib header size if it is a | |
810 | SHF_COMPRESSED section. */ | |
811 | compression_header_size = 12; | |
2cac01e3 FS |
812 | bool is_zstd = compress_status == DECOMPRESS_SECTION_ZSTD; |
813 | if (!decompress_contents ( | |
814 | is_zstd, compressed_buffer + compression_header_size, | |
56ba7527 | 815 | sec->compressed_size - compression_header_size, p, readsz)) |
82c6068a AM |
816 | { |
817 | bfd_set_error (bfd_error_bad_value); | |
38b774d2 AM |
818 | if (p != *ptr) |
819 | free (p); | |
82c6068a AM |
820 | fail_compressed: |
821 | free (compressed_buffer); | |
0a1b45a2 | 822 | return false; |
82c6068a | 823 | } |
4a114e3e | 824 | |
82c6068a | 825 | free (compressed_buffer); |
38b774d2 | 826 | *ptr = p; |
0a1b45a2 | 827 | return true; |
4a114e3e | 828 | |
82c6068a | 829 | case COMPRESS_SECTION_DONE: |
db6b071a | 830 | if (sec->contents == NULL) |
0a1b45a2 | 831 | return false; |
82c6068a AM |
832 | if (p == NULL) |
833 | { | |
56ba7527 | 834 | p = (bfd_byte *) bfd_malloc (allocsz); |
82c6068a | 835 | if (p == NULL) |
0a1b45a2 | 836 | return false; |
82c6068a AM |
837 | *ptr = p; |
838 | } | |
06614111 NC |
839 | /* PR 17512; file: 5bc29788. */ |
840 | if (p != sec->contents) | |
56ba7527 | 841 | memcpy (p, sec->contents, readsz); |
0a1b45a2 | 842 | return true; |
4a114e3e | 843 | |
82c6068a AM |
844 | default: |
845 | abort (); | |
846 | } | |
4a114e3e L |
847 | } |
848 | ||
849 | /* | |
850 | FUNCTION | |
758dd750 | 851 | bfd_is_section_compressed_info |
4a114e3e L |
852 | |
853 | SYNOPSIS | |
758dd750 | 854 | bool bfd_is_section_compressed_info |
151411f8 | 855 | (bfd *abfd, asection *section, |
758dd750 AM |
856 | int *compression_header_size_p, |
857 | bfd_size_type *uncompressed_size_p, | |
858 | unsigned int *uncompressed_alignment_power_p, | |
89dbeac7 | 859 | enum compression_type *ch_type); |
4a114e3e L |
860 | |
861 | DESCRIPTION | |
151411f8 | 862 | Return @code{TRUE} if @var{section} is compressed. Compression |
4207142d MW |
863 | header size is returned in @var{compression_header_size_p}, |
864 | uncompressed size is returned in @var{uncompressed_size_p} | |
865 | and the uncompressed data alignement power is returned in | |
866 | @var{uncompressed_align_pow_p}. If compression is | |
867 | unsupported, compression header size is returned with -1 | |
868 | and uncompressed size is returned with 0. | |
4a114e3e L |
869 | */ |
870 | ||
0a1b45a2 | 871 | bool |
758dd750 AM |
872 | bfd_is_section_compressed_info (bfd *abfd, sec_ptr sec, |
873 | int *compression_header_size_p, | |
874 | bfd_size_type *uncompressed_size_p, | |
875 | unsigned int *uncompressed_align_pow_p, | |
89dbeac7 | 876 | enum compression_type *ch_type) |
4a114e3e | 877 | { |
dab394de | 878 | bfd_byte header[MAX_COMPRESSION_HEADER_SIZE]; |
151411f8 | 879 | int compression_header_size; |
dab394de | 880 | int header_size; |
64f40162 | 881 | unsigned int saved = sec->compress_status; |
0a1b45a2 | 882 | bool compressed; |
64f40162 | 883 | |
131a5a64 L |
884 | *uncompressed_align_pow_p = 0; |
885 | ||
151411f8 L |
886 | compression_header_size = bfd_get_compression_header_size (abfd, sec); |
887 | if (compression_header_size > MAX_COMPRESSION_HEADER_SIZE) | |
888 | abort (); | |
dab394de | 889 | header_size = compression_header_size ? compression_header_size : 12; |
151411f8 | 890 | |
64f40162 L |
891 | /* Don't decompress the section. */ |
892 | sec->compress_status = COMPRESS_SECTION_NONE; | |
4a114e3e | 893 | |
dab394de L |
894 | /* Read the header. */ |
895 | if (bfd_get_section_contents (abfd, sec, header, 0, header_size)) | |
896 | { | |
897 | if (compression_header_size == 0) | |
07d6d2b8 | 898 | /* In this case, it should be "ZLIB" followed by the uncompressed |
dab394de | 899 | section size, 8 bytes in big-endian order. */ |
08dedd66 | 900 | compressed = startswith ((char*) header , "ZLIB"); |
dab394de | 901 | else |
0a1b45a2 | 902 | compressed = true; |
dab394de L |
903 | } |
904 | else | |
0a1b45a2 | 905 | compressed = false; |
64f40162 | 906 | |
dab394de | 907 | *uncompressed_size_p = sec->size; |
151411f8 L |
908 | if (compressed) |
909 | { | |
910 | if (compression_header_size != 0) | |
911 | { | |
758dd750 | 912 | if (!bfd_check_compression_header (abfd, header, sec, ch_type, |
4207142d MW |
913 | uncompressed_size_p, |
914 | uncompressed_align_pow_p)) | |
151411f8 L |
915 | compression_header_size = -1; |
916 | } | |
917 | /* Check for the pathalogical case of a debug string section that | |
918 | contains the string ZLIB.... as the first entry. We assume that | |
919 | no uncompressed .debug_str section would ever be big enough to | |
920 | have the first byte of its (big-endian) size be non-zero. */ | |
921 | else if (strcmp (sec->name, ".debug_str") == 0 | |
dab394de | 922 | && ISPRINT (header[4])) |
0a1b45a2 | 923 | compressed = false; |
dab394de L |
924 | else |
925 | *uncompressed_size_p = bfd_getb64 (header + 4); | |
151411f8 | 926 | } |
a953eec9 | 927 | |
64f40162 L |
928 | /* Restore compress_status. */ |
929 | sec->compress_status = saved; | |
151411f8 | 930 | *compression_header_size_p = compression_header_size; |
64f40162 | 931 | return compressed; |
4a114e3e L |
932 | } |
933 | ||
151411f8 L |
934 | /* |
935 | FUNCTION | |
936 | bfd_is_section_compressed | |
937 | ||
938 | SYNOPSIS | |
0a1b45a2 | 939 | bool bfd_is_section_compressed |
151411f8 L |
940 | (bfd *abfd, asection *section); |
941 | ||
942 | DESCRIPTION | |
943 | Return @code{TRUE} if @var{section} is compressed. | |
944 | */ | |
945 | ||
0a1b45a2 | 946 | bool |
151411f8 L |
947 | bfd_is_section_compressed (bfd *abfd, sec_ptr sec) |
948 | { | |
949 | int compression_header_size; | |
dab394de | 950 | bfd_size_type uncompressed_size; |
4207142d | 951 | unsigned int uncompressed_align_power; |
89dbeac7 | 952 | enum compression_type ch_type; |
758dd750 AM |
953 | return (bfd_is_section_compressed_info (abfd, sec, |
954 | &compression_header_size, | |
955 | &uncompressed_size, | |
956 | &uncompressed_align_power, | |
957 | &ch_type) | |
dab394de L |
958 | && compression_header_size >= 0 |
959 | && uncompressed_size > 0); | |
151411f8 L |
960 | } |
961 | ||
4a114e3e L |
962 | /* |
963 | FUNCTION | |
964 | bfd_init_section_decompress_status | |
965 | ||
966 | SYNOPSIS | |
0a1b45a2 | 967 | bool bfd_init_section_decompress_status |
4a114e3e L |
968 | (bfd *abfd, asection *section); |
969 | ||
970 | DESCRIPTION | |
971 | Record compressed section size, update section size with | |
972 | decompressed size and set compress_status to | |
2cac01e3 | 973 | DECOMPRESS_SECTION_{ZLIB,ZSTD}. |
4a114e3e L |
974 | |
975 | Return @code{FALSE} if the section is not a valid compressed | |
18ece1de | 976 | section. Otherwise, return @code{TRUE}. |
4a114e3e L |
977 | */ |
978 | ||
0a1b45a2 | 979 | bool |
243340ad | 980 | bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec) |
4a114e3e | 981 | { |
dab394de | 982 | bfd_byte header[MAX_COMPRESSION_HEADER_SIZE]; |
151411f8 | 983 | int compression_header_size; |
dab394de | 984 | int header_size; |
4a114e3e | 985 | bfd_size_type uncompressed_size; |
4207142d | 986 | unsigned int uncompressed_alignment_power = 0; |
89dbeac7 | 987 | enum compression_type ch_type; |
c5967f38 | 988 | z_stream strm; |
4a114e3e | 989 | |
151411f8 L |
990 | compression_header_size = bfd_get_compression_header_size (abfd, sec); |
991 | if (compression_header_size > MAX_COMPRESSION_HEADER_SIZE) | |
992 | abort (); | |
dab394de | 993 | header_size = compression_header_size ? compression_header_size : 12; |
151411f8 | 994 | |
dab394de | 995 | /* Read the header. */ |
4a114e3e L |
996 | if (sec->rawsize != 0 |
997 | || sec->contents != NULL | |
998 | || sec->compress_status != COMPRESS_SECTION_NONE | |
151411f8 | 999 | || !bfd_get_section_contents (abfd, sec, header, 0, header_size)) |
4a114e3e L |
1000 | { |
1001 | bfd_set_error (bfd_error_invalid_operation); | |
0a1b45a2 | 1002 | return false; |
4a114e3e | 1003 | } |
1b315056 | 1004 | |
dab394de | 1005 | if (compression_header_size == 0) |
4a114e3e | 1006 | { |
dab394de L |
1007 | /* In this case, it should be "ZLIB" followed by the uncompressed |
1008 | section size, 8 bytes in big-endian order. */ | |
08dedd66 | 1009 | if (! startswith ((char*) header, "ZLIB")) |
dab394de L |
1010 | { |
1011 | bfd_set_error (bfd_error_wrong_format); | |
0a1b45a2 | 1012 | return false; |
dab394de L |
1013 | } |
1014 | uncompressed_size = bfd_getb64 (header + 4); | |
89dbeac7 | 1015 | ch_type = ch_none; |
4a114e3e | 1016 | } |
dab394de | 1017 | else if (!bfd_check_compression_header (abfd, header, sec, |
2cac01e3 | 1018 | &ch_type, |
4207142d MW |
1019 | &uncompressed_size, |
1020 | &uncompressed_alignment_power)) | |
151411f8 L |
1021 | { |
1022 | bfd_set_error (bfd_error_wrong_format); | |
0a1b45a2 | 1023 | return false; |
151411f8 | 1024 | } |
dab394de | 1025 | |
c5967f38 AM |
1026 | /* PR28530, reject sizes unsupported by decompress_contents. */ |
1027 | strm.avail_in = sec->size; | |
1028 | strm.avail_out = uncompressed_size; | |
1029 | if (strm.avail_in != sec->size || strm.avail_out != uncompressed_size) | |
1030 | { | |
1031 | bfd_set_error (bfd_error_nonrepresentable_section); | |
1032 | return false; | |
1033 | } | |
1034 | ||
4a114e3e L |
1035 | sec->compressed_size = sec->size; |
1036 | sec->size = uncompressed_size; | |
fd361982 | 1037 | bfd_set_section_alignment (sec, uncompressed_alignment_power); |
89dbeac7 | 1038 | sec->compress_status = (ch_type == ch_compress_zstd |
2cac01e3 | 1039 | ? DECOMPRESS_SECTION_ZSTD : DECOMPRESS_SECTION_ZLIB); |
1b315056 | 1040 | |
0a1b45a2 | 1041 | return true; |
4a114e3e L |
1042 | } |
1043 | ||
1044 | /* | |
1045 | FUNCTION | |
1046 | bfd_init_section_compress_status | |
1047 | ||
1048 | SYNOPSIS | |
0a1b45a2 | 1049 | bool bfd_init_section_compress_status |
4a114e3e L |
1050 | (bfd *abfd, asection *section); |
1051 | ||
1052 | DESCRIPTION | |
1053 | If open for read, compress section, update section size with | |
1054 | compressed size and set compress_status to COMPRESS_SECTION_DONE. | |
1055 | ||
1056 | Return @code{FALSE} if the section is not a valid compressed | |
18ece1de | 1057 | section. Otherwise, return @code{TRUE}. |
4a114e3e L |
1058 | */ |
1059 | ||
0a1b45a2 | 1060 | bool |
243340ad | 1061 | bfd_init_section_compress_status (bfd *abfd, sec_ptr sec) |
4a114e3e | 1062 | { |
4a114e3e L |
1063 | bfd_size_type uncompressed_size; |
1064 | bfd_byte *uncompressed_buffer; | |
4a114e3e L |
1065 | |
1066 | /* Error if not opened for read. */ | |
1067 | if (abfd->direction != read_direction | |
1068 | || sec->size == 0 | |
1069 | || sec->rawsize != 0 | |
1070 | || sec->contents != NULL | |
1071 | || sec->compress_status != COMPRESS_SECTION_NONE) | |
1b315056 | 1072 | { |
4a114e3e | 1073 | bfd_set_error (bfd_error_invalid_operation); |
0a1b45a2 | 1074 | return false; |
1b315056 | 1075 | } |
1b315056 | 1076 | |
4a114e3e L |
1077 | /* Read in the full section contents and compress it. */ |
1078 | uncompressed_size = sec->size; | |
1079 | uncompressed_buffer = (bfd_byte *) bfd_malloc (uncompressed_size); | |
e63d1232 NC |
1080 | /* PR 21431 */ |
1081 | if (uncompressed_buffer == NULL) | |
0a1b45a2 | 1082 | return false; |
e63d1232 | 1083 | |
4a114e3e L |
1084 | if (!bfd_get_section_contents (abfd, sec, uncompressed_buffer, |
1085 | 0, uncompressed_size)) | |
0a1b45a2 | 1086 | return false; |
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 | } |