/src/binutils-gdb/bfd/compress.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Compressed section support (intended for debug sections). |
2 | | Copyright (C) 2008-2025 Free Software Foundation, Inc. |
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 | | |
21 | | #include "sysdep.h" |
22 | | #include <zlib.h> |
23 | | #ifdef HAVE_ZSTD |
24 | | #include <zstd.h> |
25 | | #endif |
26 | | #include "bfd.h" |
27 | | #include "elf-bfd.h" |
28 | | #include "libbfd.h" |
29 | | #include "safe-ctype.h" |
30 | | #include "libiberty.h" |
31 | | |
32 | 3.92M | #define MAX_COMPRESSION_HEADER_SIZE 24 |
33 | | |
34 | | /* |
35 | | EXTERNAL |
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. *} |
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 | | . |
61 | | .static inline char * |
62 | | .bfd_debug_name_to_zdebug (bfd *abfd, const char *name) |
63 | | .{ |
64 | | . size_t len = strlen (name); |
65 | | . char *new_name = (char *) bfd_alloc (abfd, len + 2); |
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); |
78 | | . char *new_name = (char *) bfd_alloc (abfd, len); |
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 | | |
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 | 0 | { |
110 | 0 | for (unsigned i = 0; i < ARRAY_SIZE (compressed_debug_section_names); ++i) |
111 | 0 | if (strcasecmp (compressed_debug_section_names[i].name, name) == 0) |
112 | 0 | return compressed_debug_section_names[i].type; |
113 | | |
114 | 0 | return COMPRESS_UNKNOWN; |
115 | 0 | } |
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 | 0 | { |
129 | 0 | for (unsigned i = 0; i < ARRAY_SIZE (compressed_debug_section_names); ++i) |
130 | 0 | if (type == compressed_debug_section_names[i].type) |
131 | 0 | return compressed_debug_section_names[i].name; |
132 | | |
133 | 0 | return NULL; |
134 | 0 | } |
135 | | |
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 | 19.3k | { |
153 | 19.3k | if ((abfd->flags & BFD_COMPRESS) == 0) |
154 | 0 | abort (); |
155 | | |
156 | 19.3k | switch (bfd_get_flavour (abfd)) |
157 | 19.3k | { |
158 | 10.6k | case bfd_target_elf_flavour: |
159 | 10.6k | if ((abfd->flags & BFD_COMPRESS_GABI) != 0) |
160 | 10.6k | { |
161 | 10.6k | const struct elf_backend_data *bed = get_elf_backend_data (abfd); |
162 | 10.6k | struct bfd_elf_section_data * esd = elf_section_data (sec); |
163 | 10.6k | enum compression_type ch_type = (abfd->flags & BFD_COMPRESS_ZSTD |
164 | 10.6k | ? ch_compress_zstd |
165 | 10.6k | : ch_compress_zlib); |
166 | | |
167 | | /* Set the SHF_COMPRESSED bit. */ |
168 | 10.6k | elf_section_flags (sec) |= SHF_COMPRESSED; |
169 | | |
170 | 10.6k | if (bed->s->elfclass == ELFCLASS32) |
171 | 699 | { |
172 | 699 | Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents; |
173 | 699 | bfd_put_32 (abfd, ch_type, &echdr->ch_type); |
174 | 699 | bfd_put_32 (abfd, sec->size, &echdr->ch_size); |
175 | 699 | bfd_put_32 (abfd, 1u << sec->alignment_power, |
176 | 699 | &echdr->ch_addralign); |
177 | | /* bfd_log2 (alignof (Elf32_Chdr)) */ |
178 | 699 | bfd_set_section_alignment (sec, 2); |
179 | 699 | esd->this_hdr.sh_addralign = 4; |
180 | 699 | } |
181 | 9.93k | else |
182 | 9.93k | { |
183 | 9.93k | Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents; |
184 | 9.93k | bfd_put_32 (abfd, ch_type, &echdr->ch_type); |
185 | 9.93k | bfd_put_32 (abfd, 0, &echdr->ch_reserved); |
186 | 9.93k | bfd_put_64 (abfd, sec->size, &echdr->ch_size); |
187 | 9.93k | bfd_put_64 (abfd, UINT64_C (1) << sec->alignment_power, |
188 | 9.93k | &echdr->ch_addralign); |
189 | | /* bfd_log2 (alignof (Elf64_Chdr)) */ |
190 | 9.93k | bfd_set_section_alignment (sec, 3); |
191 | 9.93k | esd->this_hdr.sh_addralign = 8; |
192 | 9.93k | } |
193 | 10.6k | break; |
194 | 10.6k | } |
195 | | |
196 | | /* Clear the SHF_COMPRESSED bit. */ |
197 | 0 | elf_section_flags (sec) &= ~SHF_COMPRESSED; |
198 | | /* Fall through. */ |
199 | |
|
200 | 8.71k | 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 | 8.71k | memcpy (contents, "ZLIB", 4); |
205 | 8.71k | bfd_putb64 (sec->size, contents + 4); |
206 | | /* No way to keep the original alignment, just use 1 always. */ |
207 | 8.71k | bfd_set_section_alignment (sec, 0); |
208 | 8.71k | break; |
209 | 19.3k | } |
210 | 19.3k | } |
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 | 20.7k | { |
224 | 20.7k | if (bfd_get_flavour (abfd) == bfd_target_elf_flavour |
225 | 20.7k | && (elf_section_flags (sec) & SHF_COMPRESSED) != 0) |
226 | 20.7k | { |
227 | 20.7k | Elf_Internal_Chdr chdr; |
228 | 20.7k | const struct elf_backend_data *bed = get_elf_backend_data (abfd); |
229 | 20.7k | if (bed->s->elfclass == ELFCLASS32) |
230 | 17.5k | { |
231 | 17.5k | Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents; |
232 | 17.5k | chdr.ch_type = bfd_get_32 (abfd, &echdr->ch_type); |
233 | 17.5k | chdr.ch_size = bfd_get_32 (abfd, &echdr->ch_size); |
234 | 17.5k | chdr.ch_addralign = bfd_get_32 (abfd, &echdr->ch_addralign); |
235 | 17.5k | } |
236 | 3.20k | else |
237 | 3.20k | { |
238 | 3.20k | Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents; |
239 | 3.20k | chdr.ch_type = bfd_get_32 (abfd, &echdr->ch_type); |
240 | 3.20k | chdr.ch_size = bfd_get_64 (abfd, &echdr->ch_size); |
241 | 3.20k | chdr.ch_addralign = bfd_get_64 (abfd, &echdr->ch_addralign); |
242 | 3.20k | } |
243 | 20.7k | *ch_type = chdr.ch_type; |
244 | 20.7k | if ((chdr.ch_type == ch_compress_zlib |
245 | 20.7k | || chdr.ch_type == ch_compress_zstd) |
246 | 20.7k | && chdr.ch_addralign == (chdr.ch_addralign & -chdr.ch_addralign)) |
247 | 1.94k | { |
248 | 1.94k | *uncompressed_size = chdr.ch_size; |
249 | 1.94k | *uncompressed_alignment_power = bfd_log2 (chdr.ch_addralign); |
250 | 1.94k | return true; |
251 | 1.94k | } |
252 | 20.7k | } |
253 | | |
254 | 18.7k | return false; |
255 | 20.7k | } |
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 | | |
268 | | int |
269 | | bfd_get_compression_header_size (bfd *abfd, asection *sec) |
270 | 3.94M | { |
271 | 3.94M | if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) |
272 | 968k | { |
273 | 968k | if (sec == NULL) |
274 | 12.7k | { |
275 | 12.7k | if (!(abfd->flags & BFD_COMPRESS_GABI)) |
276 | 0 | return 0; |
277 | 12.7k | } |
278 | 955k | else if (!(elf_section_flags (sec) & SHF_COMPRESSED)) |
279 | 928k | return 0; |
280 | | |
281 | 40.2k | if (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS32) |
282 | 19.4k | return sizeof (Elf32_External_Chdr); |
283 | 20.7k | else |
284 | 20.7k | return sizeof (Elf64_External_Chdr); |
285 | 40.2k | } |
286 | | |
287 | 2.97M | return 0; |
288 | 3.94M | } |
289 | | |
290 | | /* |
291 | | FUNCTION |
292 | | bfd_convert_section_setup |
293 | | |
294 | | SYNOPSIS |
295 | | bool bfd_convert_section_setup |
296 | | (bfd *ibfd, asection *isec, bfd *obfd, |
297 | | const char **new_name, bfd_size_type *new_size); |
298 | | |
299 | | DESCRIPTION |
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. |
303 | | */ |
304 | | |
305 | | bool |
306 | | bfd_convert_section_setup (bfd *ibfd, asection *isec, bfd *obfd, |
307 | | const char **new_name, bfd_size_type *new_size) |
308 | 8.21k | { |
309 | 8.21k | bfd_size_type hdr_size; |
310 | | |
311 | 8.21k | if ((isec->flags & SEC_DEBUGGING) != 0 |
312 | 8.21k | && (isec->flags & SEC_HAS_CONTENTS) != 0) |
313 | 394 | { |
314 | 394 | const char *name = *new_name; |
315 | | |
316 | 394 | if ((obfd->flags & (BFD_DECOMPRESS | BFD_COMPRESS_GABI)) != 0) |
317 | 137 | { |
318 | | /* When we decompress or compress with SHF_COMPRESSED, |
319 | | convert section name from .zdebug_* to .debug_*. */ |
320 | 137 | if (startswith (name, ".zdebug_")) |
321 | 0 | { |
322 | 0 | name = bfd_zdebug_name_to_debug (obfd, name); |
323 | 0 | if (name == NULL) |
324 | 0 | return false; |
325 | 0 | } |
326 | 137 | } |
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 | 257 | else if (isec->compress_status == COMPRESS_SECTION_DONE |
333 | 257 | && startswith (name, ".debug_")) |
334 | 10 | { |
335 | 10 | name = bfd_debug_name_to_zdebug (obfd, name); |
336 | 10 | if (name == NULL) |
337 | 0 | return false; |
338 | 10 | } |
339 | 394 | *new_name = name; |
340 | 394 | } |
341 | 8.21k | *new_size = bfd_section_size (isec); |
342 | | |
343 | | /* Do nothing if either input or output aren't ELF. */ |
344 | 8.21k | if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour |
345 | 8.21k | || bfd_get_flavour (obfd) != bfd_target_elf_flavour) |
346 | 5.08k | return true; |
347 | | |
348 | | /* Do nothing if ELF classes of input and output are the same. */ |
349 | 3.13k | if (get_elf_backend_data (ibfd)->s->elfclass |
350 | 3.13k | == get_elf_backend_data (obfd)->s->elfclass) |
351 | 3.13k | return true; |
352 | | |
353 | | /* Convert GNU property size. */ |
354 | 0 | if (startswith (isec->name, NOTE_GNU_PROPERTY_SECTION_NAME)) |
355 | 0 | { |
356 | 0 | *new_size = _bfd_elf_convert_gnu_property_size (ibfd, obfd); |
357 | 0 | return true; |
358 | 0 | } |
359 | | |
360 | | /* Do nothing if input file will be decompressed. */ |
361 | 0 | if ((ibfd->flags & BFD_DECOMPRESS)) |
362 | 0 | return true; |
363 | | |
364 | | /* Do nothing if the input section isn't a SHF_COMPRESSED section. */ |
365 | 0 | hdr_size = bfd_get_compression_header_size (ibfd, isec); |
366 | 0 | if (hdr_size == 0) |
367 | 0 | return true; |
368 | | |
369 | | /* Adjust the size of the output SHF_COMPRESSED section. */ |
370 | 0 | if (hdr_size == sizeof (Elf32_External_Chdr)) |
371 | 0 | *new_size += sizeof (Elf64_External_Chdr) - sizeof (Elf32_External_Chdr); |
372 | 0 | else |
373 | 0 | *new_size -= sizeof (Elf64_External_Chdr) - sizeof (Elf32_External_Chdr); |
374 | 0 | return true; |
375 | 0 | } |
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 | 2.46k | { |
398 | 2.46k | bfd_byte *contents; |
399 | 2.46k | bfd_size_type ihdr_size, ohdr_size, size; |
400 | 2.46k | Elf_Internal_Chdr chdr; |
401 | 2.46k | bool use_memmove; |
402 | | |
403 | | /* Do nothing if either input or output aren't ELF. */ |
404 | 2.46k | if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour |
405 | 2.46k | || bfd_get_flavour (obfd) != bfd_target_elf_flavour) |
406 | 277 | return true; |
407 | | |
408 | | /* Do nothing if ELF classes of input and output are the same. */ |
409 | 2.18k | if (get_elf_backend_data (ibfd)->s->elfclass |
410 | 2.18k | == get_elf_backend_data (obfd)->s->elfclass) |
411 | 2.18k | return true; |
412 | | |
413 | | /* Convert GNU properties. */ |
414 | 0 | if (startswith (isec->name, NOTE_GNU_PROPERTY_SECTION_NAME)) |
415 | 0 | return _bfd_elf_convert_gnu_properties (ibfd, isec, obfd, ptr, |
416 | 0 | ptr_size); |
417 | | |
418 | | /* Do nothing if input file will be decompressed. */ |
419 | 0 | if ((ibfd->flags & BFD_DECOMPRESS)) |
420 | 0 | return true; |
421 | | |
422 | | /* Do nothing if the input section isn't a SHF_COMPRESSED section. */ |
423 | 0 | ihdr_size = bfd_get_compression_header_size (ibfd, isec); |
424 | 0 | if (ihdr_size == 0) |
425 | 0 | return true; |
426 | | |
427 | | /* PR 25221. Check for corrupt input sections. */ |
428 | 0 | if (ihdr_size > bfd_get_section_limit (ibfd, isec)) |
429 | | /* FIXME: Issue a warning about a corrupt |
430 | | compression header size field ? */ |
431 | 0 | return false; |
432 | | |
433 | 0 | 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 | 0 | if (ihdr_size == sizeof (Elf32_External_Chdr)) |
439 | 0 | { |
440 | 0 | Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents; |
441 | 0 | chdr.ch_type = bfd_get_32 (ibfd, &echdr->ch_type); |
442 | 0 | chdr.ch_size = bfd_get_32 (ibfd, &echdr->ch_size); |
443 | 0 | chdr.ch_addralign = bfd_get_32 (ibfd, &echdr->ch_addralign); |
444 | |
|
445 | 0 | ohdr_size = sizeof (Elf64_External_Chdr); |
446 | |
|
447 | 0 | use_memmove = false; |
448 | 0 | } |
449 | 0 | else if (ihdr_size != sizeof (Elf64_External_Chdr)) |
450 | 0 | { |
451 | | /* FIXME: Issue a warning about a corrupt |
452 | | compression header size field ? */ |
453 | 0 | return false; |
454 | 0 | } |
455 | 0 | else |
456 | 0 | { |
457 | 0 | Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents; |
458 | 0 | chdr.ch_type = bfd_get_32 (ibfd, &echdr->ch_type); |
459 | 0 | chdr.ch_size = bfd_get_64 (ibfd, &echdr->ch_size); |
460 | 0 | chdr.ch_addralign = bfd_get_64 (ibfd, &echdr->ch_addralign); |
461 | |
|
462 | 0 | ohdr_size = sizeof (Elf32_External_Chdr); |
463 | 0 | use_memmove = true; |
464 | 0 | } |
465 | | |
466 | 0 | size = bfd_section_size (isec) - ihdr_size + ohdr_size; |
467 | 0 | if (!use_memmove) |
468 | 0 | { |
469 | 0 | contents = (bfd_byte *) bfd_malloc (size); |
470 | 0 | if (contents == NULL) |
471 | 0 | return false; |
472 | 0 | } |
473 | | |
474 | | /* Write out the output compression header. */ |
475 | 0 | if (ohdr_size == sizeof (Elf32_External_Chdr)) |
476 | 0 | { |
477 | 0 | Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents; |
478 | 0 | bfd_put_32 (obfd, chdr.ch_type, &echdr->ch_type); |
479 | 0 | bfd_put_32 (obfd, chdr.ch_size, &echdr->ch_size); |
480 | 0 | bfd_put_32 (obfd, chdr.ch_addralign, &echdr->ch_addralign); |
481 | 0 | } |
482 | 0 | else |
483 | 0 | { |
484 | 0 | Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents; |
485 | 0 | bfd_put_32 (obfd, chdr.ch_type, &echdr->ch_type); |
486 | 0 | bfd_put_32 (obfd, 0, &echdr->ch_reserved); |
487 | 0 | bfd_put_64 (obfd, chdr.ch_size, &echdr->ch_size); |
488 | 0 | bfd_put_64 (obfd, chdr.ch_addralign, &echdr->ch_addralign); |
489 | 0 | } |
490 | | |
491 | | /* Copy the compressed contents. */ |
492 | 0 | if (use_memmove) |
493 | 0 | memmove (contents + ohdr_size, *ptr + ihdr_size, size - ohdr_size); |
494 | 0 | else |
495 | 0 | { |
496 | 0 | memcpy (contents + ohdr_size, *ptr + ihdr_size, size - ohdr_size); |
497 | 0 | free (*ptr); |
498 | 0 | *ptr = contents; |
499 | 0 | } |
500 | |
|
501 | 0 | *ptr_size = size; |
502 | 0 | return true; |
503 | 0 | } |
504 | | |
505 | | static bool |
506 | | decompress_contents (bool is_zstd, bfd_byte *compressed_buffer, |
507 | | bfd_size_type compressed_size, |
508 | | bfd_byte *uncompressed_buffer, |
509 | | bfd_size_type uncompressed_size) |
510 | 137 | { |
511 | 137 | if (is_zstd) |
512 | 0 | { |
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 | 0 | } |
519 | | |
520 | | /* It is possible the section consists of several compressed |
521 | | buffers concatenated together, so we uncompress in a loop. */ |
522 | 137 | do |
523 | 137 | { |
524 | 137 | uLongf dst_len = uncompressed_size; |
525 | 137 | uLong src_len = compressed_size; |
526 | 137 | int rc = uncompress2 ((Bytef *) uncompressed_buffer, &dst_len, |
527 | 137 | (Bytef *) compressed_buffer, &src_len); |
528 | 137 | if (rc != Z_OK) |
529 | 135 | return false; |
530 | 2 | uncompressed_buffer += dst_len; |
531 | 2 | uncompressed_size -= dst_len; |
532 | 2 | compressed_buffer += src_len; |
533 | 2 | compressed_size -= src_len; |
534 | 2 | } |
535 | 137 | while (compressed_size > 0 && uncompressed_size > 0); |
536 | 2 | return compressed_size == 0 && uncompressed_size == 0; |
537 | 137 | } |
538 | | |
539 | | /* Compress section contents using zlib/zstd and store |
540 | | as the contents field. This function assumes the contents |
541 | | field was allocated using bfd_malloc() or equivalent. |
542 | | |
543 | | Return the uncompressed size if the full section contents is |
544 | | compressed successfully. Otherwise return (bfd_size_type) -1. */ |
545 | | |
546 | | static bfd_size_type |
547 | | bfd_compress_section_contents (bfd *abfd, sec_ptr sec) |
548 | 22.0k | { |
549 | 22.0k | bfd_byte *input_buffer; |
550 | 22.0k | uLong compressed_size; |
551 | 22.0k | bfd_byte *buffer; |
552 | 22.0k | bfd_size_type buffer_size; |
553 | 22.0k | int zlib_size = 0; |
554 | 22.0k | int orig_header_size; |
555 | 22.0k | bfd_size_type uncompressed_size; |
556 | 22.0k | unsigned int uncompressed_alignment_pow; |
557 | 22.0k | enum compression_type ch_type = ch_none; |
558 | 22.0k | int new_header_size = bfd_get_compression_header_size (abfd, NULL); |
559 | 22.0k | bool compressed |
560 | 22.0k | = bfd_is_section_compressed_info (abfd, sec, |
561 | 22.0k | &orig_header_size, |
562 | 22.0k | &uncompressed_size, |
563 | 22.0k | &uncompressed_alignment_pow, |
564 | 22.0k | &ch_type); |
565 | 22.0k | bool update = false; |
566 | | |
567 | | /* We shouldn't be trying to decompress unsupported compressed sections. */ |
568 | 22.0k | if (compressed && orig_header_size < 0) |
569 | 0 | abort (); |
570 | | |
571 | | /* PR 31455: Check for a corrupt uncompressed size. */ |
572 | 22.0k | if (uncompressed_size == (bfd_size_type) -1) |
573 | 0 | return uncompressed_size; |
574 | | |
575 | | /* Either ELF compression header or the 12-byte, "ZLIB" + 8-byte size, |
576 | | overhead in .zdebug* section. */ |
577 | 22.0k | if (!new_header_size) |
578 | 9.31k | new_header_size = 12; |
579 | 22.0k | if (ch_type == ch_none) |
580 | 22.0k | orig_header_size = 12; |
581 | | |
582 | 22.0k | input_buffer = sec->contents; |
583 | 22.0k | if (compressed) |
584 | 0 | { |
585 | 0 | zlib_size = sec->size - orig_header_size; |
586 | 0 | compressed_size = zlib_size + new_header_size; |
587 | | |
588 | | /* If we are converting between zlib-gnu and zlib-gabi then the |
589 | | compressed contents just need to be moved. */ |
590 | 0 | update = (ch_type < ch_compress_zstd |
591 | 0 | && (abfd->flags & BFD_COMPRESS_ZSTD) == 0); |
592 | | |
593 | | /* Uncompress when not just moving contents or when compressed |
594 | | is not smaller than uncompressed. */ |
595 | 0 | if (!update || compressed_size >= uncompressed_size) |
596 | 0 | { |
597 | 0 | buffer_size = uncompressed_size; |
598 | 0 | buffer = bfd_malloc (buffer_size); |
599 | 0 | if (buffer == NULL) |
600 | 0 | return (bfd_size_type) -1; |
601 | | |
602 | 0 | if (!decompress_contents (ch_type == ch_compress_zstd, |
603 | 0 | input_buffer + orig_header_size, |
604 | 0 | zlib_size, buffer, buffer_size)) |
605 | 0 | { |
606 | 0 | bfd_set_error (bfd_error_bad_value); |
607 | 0 | free (buffer); |
608 | 0 | return (bfd_size_type) -1; |
609 | 0 | } |
610 | 0 | free (input_buffer); |
611 | 0 | bfd_set_section_alignment (sec, uncompressed_alignment_pow); |
612 | 0 | sec->contents = buffer; |
613 | 0 | sec->flags |= SEC_IN_MEMORY; |
614 | 0 | sec->compress_status = COMPRESS_SECTION_NONE; |
615 | 0 | sec->size = uncompressed_size; |
616 | 0 | input_buffer = buffer; |
617 | 0 | } |
618 | 0 | } |
619 | | |
620 | 22.0k | if (!update) |
621 | 22.0k | compressed_size = compressBound (uncompressed_size) + new_header_size; |
622 | | |
623 | 22.0k | buffer_size = compressed_size; |
624 | 22.0k | buffer = bfd_alloc (abfd, buffer_size); |
625 | 22.0k | if (buffer == NULL) |
626 | 0 | return (bfd_size_type) -1; |
627 | | |
628 | 22.0k | if (update) |
629 | 0 | { |
630 | 0 | if (compressed_size < uncompressed_size) |
631 | 0 | memcpy (buffer + new_header_size, |
632 | 0 | input_buffer + orig_header_size, |
633 | 0 | zlib_size); |
634 | 0 | } |
635 | 22.0k | else |
636 | 22.0k | { |
637 | 22.0k | if (abfd->flags & BFD_COMPRESS_ZSTD) |
638 | 0 | { |
639 | | #if HAVE_ZSTD |
640 | | compressed_size = ZSTD_compress (buffer + new_header_size, |
641 | | compressed_size, |
642 | | input_buffer, |
643 | | uncompressed_size, |
644 | | ZSTD_CLEVEL_DEFAULT); |
645 | | if (ZSTD_isError (compressed_size)) |
646 | | { |
647 | | bfd_release (abfd, buffer); |
648 | | bfd_set_error (bfd_error_bad_value); |
649 | | return (bfd_size_type) -1; |
650 | | } |
651 | | #endif |
652 | 0 | } |
653 | 22.0k | else if (compress ((Bytef *) buffer + new_header_size, &compressed_size, |
654 | 22.0k | (const Bytef *) input_buffer, uncompressed_size) |
655 | 22.0k | != Z_OK) |
656 | 0 | { |
657 | 0 | bfd_release (abfd, buffer); |
658 | 0 | bfd_set_error (bfd_error_bad_value); |
659 | 0 | return (bfd_size_type) -1; |
660 | 0 | } |
661 | | |
662 | 22.0k | compressed_size += new_header_size; |
663 | 22.0k | } |
664 | | |
665 | | /* If compression didn't make the section smaller, keep it uncompressed. */ |
666 | 22.0k | if (compressed_size >= uncompressed_size) |
667 | 2.71k | { |
668 | 2.71k | memcpy (buffer, input_buffer, uncompressed_size); |
669 | 2.71k | if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) |
670 | 2.11k | elf_section_flags (sec) &= ~SHF_COMPRESSED; |
671 | 2.71k | sec->compress_status = COMPRESS_SECTION_NONE; |
672 | 2.71k | } |
673 | 19.3k | else |
674 | 19.3k | { |
675 | 19.3k | sec->size = uncompressed_size; |
676 | 19.3k | bfd_update_compression_header (abfd, buffer, sec); |
677 | 19.3k | sec->size = compressed_size; |
678 | 19.3k | sec->compress_status = COMPRESS_SECTION_DONE; |
679 | 19.3k | } |
680 | 22.0k | sec->alloced = 1; |
681 | 22.0k | sec->contents = buffer; |
682 | 22.0k | sec->flags |= SEC_IN_MEMORY; |
683 | 22.0k | free (input_buffer); |
684 | 22.0k | return uncompressed_size; |
685 | 22.0k | } |
686 | | |
687 | | /* |
688 | | FUNCTION |
689 | | bfd_get_full_section_contents |
690 | | |
691 | | SYNOPSIS |
692 | | bool bfd_get_full_section_contents |
693 | | (bfd *abfd, asection *section, bfd_byte **ptr); |
694 | | |
695 | | DESCRIPTION |
696 | | Read all data from @var{section} in BFD @var{abfd}, decompress |
697 | | if needed, and store in @var{*ptr}. If @var{*ptr} is NULL, |
698 | | return @var{*ptr} with memory malloc'd by this function. |
699 | | |
700 | | Return @code{TRUE} if the full section contents is retrieved |
701 | | successfully. If the section has no contents then this function |
702 | | returns @code{TRUE} but @var{*ptr} is set to NULL. |
703 | | */ |
704 | | |
705 | | bool |
706 | | bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) |
707 | 2.66M | { |
708 | 2.66M | bfd_size_type readsz = bfd_get_section_limit_octets (abfd, sec); |
709 | 2.66M | bfd_size_type allocsz = bfd_get_section_alloc_size (abfd, sec); |
710 | 2.66M | bfd_byte *p = *ptr; |
711 | 2.66M | bool ret; |
712 | 2.66M | bfd_size_type save_size; |
713 | 2.66M | bfd_size_type save_rawsize; |
714 | 2.66M | bfd_byte *compressed_buffer; |
715 | 2.66M | unsigned int compression_header_size; |
716 | 2.66M | const unsigned int compress_status = sec->compress_status; |
717 | | |
718 | 2.66M | if (allocsz == 0) |
719 | 2.68k | { |
720 | 2.68k | *ptr = NULL; |
721 | 2.68k | return true; |
722 | 2.68k | } |
723 | | |
724 | 2.66M | if (p == NULL |
725 | 2.66M | && compress_status != COMPRESS_SECTION_DONE |
726 | 2.66M | && bfd_section_size_insane (abfd, sec)) |
727 | 2.12M | { |
728 | | /* PR 24708: Avoid attempts to allocate a ridiculous amount |
729 | | of memory. */ |
730 | 2.12M | _bfd_error_handler |
731 | | /* xgettext:c-format */ |
732 | 2.12M | (_("error: %pB(%pA) is too large (%#" PRIx64 " bytes)"), |
733 | 2.12M | abfd, sec, (uint64_t) readsz); |
734 | 2.12M | return false; |
735 | 2.12M | } |
736 | | |
737 | 533k | switch (compress_status) |
738 | 533k | { |
739 | 533k | case COMPRESS_SECTION_NONE: |
740 | 533k | if (p == NULL && !sec->mmapped_p) |
741 | 508k | { |
742 | 508k | p = (bfd_byte *) bfd_malloc (allocsz); |
743 | 508k | if (p == NULL) |
744 | 6 | { |
745 | | /* PR 20801: Provide a more helpful error message. */ |
746 | 6 | if (bfd_get_error () == bfd_error_no_memory) |
747 | 6 | _bfd_error_handler |
748 | | /* xgettext:c-format */ |
749 | 6 | (_("error: %pB(%pA) is too large (%#" PRIx64 " bytes)"), |
750 | 6 | abfd, sec, (uint64_t) allocsz); |
751 | 6 | return false; |
752 | 6 | } |
753 | 508k | } |
754 | | |
755 | 533k | if (!bfd_get_section_contents (abfd, sec, p, 0, readsz)) |
756 | 2.92k | { |
757 | 2.92k | if (*ptr != p) |
758 | 2.90k | free (p); |
759 | 2.92k | return false; |
760 | 2.92k | } |
761 | 530k | *ptr = p; |
762 | 530k | return true; |
763 | | |
764 | 137 | case DECOMPRESS_SECTION_ZLIB: |
765 | 137 | case DECOMPRESS_SECTION_ZSTD: |
766 | | /* Read in the full compressed section contents. */ |
767 | 137 | compressed_buffer = (bfd_byte *) bfd_malloc (sec->compressed_size); |
768 | 137 | if (compressed_buffer == NULL) |
769 | 0 | return false; |
770 | 137 | save_rawsize = sec->rawsize; |
771 | 137 | save_size = sec->size; |
772 | | /* Clear rawsize, set size to compressed size and set compress_status |
773 | | to COMPRESS_SECTION_NONE. If the compressed size is bigger than |
774 | | the uncompressed size, bfd_get_section_contents will fail. */ |
775 | 137 | sec->rawsize = 0; |
776 | 137 | sec->size = sec->compressed_size; |
777 | 137 | sec->compress_status = COMPRESS_SECTION_NONE; |
778 | 137 | ret = bfd_get_section_contents (abfd, sec, compressed_buffer, |
779 | 137 | 0, sec->compressed_size); |
780 | | /* Restore rawsize and size. */ |
781 | 137 | sec->rawsize = save_rawsize; |
782 | 137 | sec->size = save_size; |
783 | 137 | sec->compress_status = compress_status; |
784 | 137 | if (!ret) |
785 | 0 | goto fail_compressed; |
786 | | |
787 | 137 | if (p == NULL) |
788 | 78 | p = (bfd_byte *) bfd_malloc (allocsz); |
789 | 137 | if (p == NULL) |
790 | 0 | goto fail_compressed; |
791 | | |
792 | 137 | compression_header_size = bfd_get_compression_header_size (abfd, sec); |
793 | 137 | if (compression_header_size == 0) |
794 | | /* Set header size to the zlib header size if it is a |
795 | | SHF_COMPRESSED section. */ |
796 | 1 | compression_header_size = 12; |
797 | 137 | bool is_zstd = compress_status == DECOMPRESS_SECTION_ZSTD; |
798 | 137 | if (!decompress_contents ( |
799 | 137 | is_zstd, compressed_buffer + compression_header_size, |
800 | 137 | sec->compressed_size - compression_header_size, p, readsz)) |
801 | 136 | { |
802 | 136 | bfd_set_error (bfd_error_bad_value); |
803 | 136 | if (p != *ptr) |
804 | 77 | free (p); |
805 | 136 | fail_compressed: |
806 | 136 | free (compressed_buffer); |
807 | 136 | return false; |
808 | 136 | } |
809 | | |
810 | 1 | free (compressed_buffer); |
811 | 1 | *ptr = p; |
812 | 1 | return true; |
813 | | |
814 | 121 | case COMPRESS_SECTION_DONE: |
815 | 121 | if (sec->contents == NULL) |
816 | 0 | return false; |
817 | 121 | if (p == NULL) |
818 | 121 | { |
819 | 121 | p = (bfd_byte *) bfd_malloc (allocsz); |
820 | 121 | if (p == NULL) |
821 | 0 | return false; |
822 | 121 | *ptr = p; |
823 | 121 | } |
824 | | /* PR 17512; file: 5bc29788. */ |
825 | 121 | if (p != sec->contents) |
826 | 121 | memcpy (p, sec->contents, readsz); |
827 | 121 | return true; |
828 | | |
829 | 0 | default: |
830 | 0 | abort (); |
831 | 533k | } |
832 | 533k | } |
833 | | |
834 | | /* |
835 | | FUNCTION |
836 | | bfd_is_section_compressed_info |
837 | | |
838 | | SYNOPSIS |
839 | | bool bfd_is_section_compressed_info |
840 | | (bfd *abfd, asection *section, |
841 | | int *compression_header_size_p, |
842 | | bfd_size_type *uncompressed_size_p, |
843 | | unsigned int *uncompressed_alignment_power_p, |
844 | | enum compression_type *ch_type); |
845 | | |
846 | | DESCRIPTION |
847 | | Return @code{TRUE} if @var{section} is compressed. Compression |
848 | | header size is returned in @var{compression_header_size_p}, |
849 | | uncompressed size is returned in @var{uncompressed_size_p} |
850 | | and the uncompressed data alignement power is returned in |
851 | | @var{uncompressed_align_pow_p}. If compression is |
852 | | unsupported, compression header size is returned with -1 |
853 | | and uncompressed size is returned with 0. |
854 | | */ |
855 | | |
856 | | bool |
857 | | bfd_is_section_compressed_info (bfd *abfd, sec_ptr sec, |
858 | | int *compression_header_size_p, |
859 | | bfd_size_type *uncompressed_size_p, |
860 | | unsigned int *uncompressed_align_pow_p, |
861 | | enum compression_type *ch_type) |
862 | 3.92M | { |
863 | 3.92M | bfd_byte header[MAX_COMPRESSION_HEADER_SIZE]; |
864 | 3.92M | int compression_header_size; |
865 | 3.92M | int header_size; |
866 | 3.92M | unsigned int saved = sec->compress_status; |
867 | 3.92M | bool compressed; |
868 | | |
869 | 3.92M | *uncompressed_align_pow_p = 0; |
870 | | |
871 | 3.92M | compression_header_size = bfd_get_compression_header_size (abfd, sec); |
872 | 3.92M | if (compression_header_size > MAX_COMPRESSION_HEADER_SIZE) |
873 | 0 | abort (); |
874 | 3.92M | header_size = compression_header_size ? compression_header_size : 12; |
875 | | |
876 | | /* Don't decompress the section. */ |
877 | 3.92M | sec->compress_status = COMPRESS_SECTION_NONE; |
878 | | |
879 | | /* Read the header. */ |
880 | 3.92M | if (bfd_get_section_contents (abfd, sec, header, 0, header_size)) |
881 | 1.21M | { |
882 | 1.21M | if (compression_header_size == 0) |
883 | | /* In this case, it should be "ZLIB" followed by the uncompressed |
884 | | section size, 8 bytes in big-endian order. */ |
885 | 1.19M | compressed = startswith ((char*) header , "ZLIB"); |
886 | 19.8k | else |
887 | 19.8k | compressed = true; |
888 | 1.21M | } |
889 | 2.70M | else |
890 | 2.70M | compressed = false; |
891 | | |
892 | 3.92M | *uncompressed_size_p = sec->size; |
893 | 3.92M | if (compressed) |
894 | 21.6k | { |
895 | 21.6k | if (compression_header_size != 0) |
896 | 19.8k | { |
897 | 19.8k | if (!bfd_check_compression_header (abfd, header, sec, ch_type, |
898 | 19.8k | uncompressed_size_p, |
899 | 19.8k | uncompressed_align_pow_p)) |
900 | 18.5k | compression_header_size = -1; |
901 | 19.8k | } |
902 | | /* Check for the pathalogical case of a debug string section that |
903 | | contains the string ZLIB.... as the first entry. We assume that |
904 | | no uncompressed .debug_str section would ever be big enough to |
905 | | have the first byte of its (big-endian) size be non-zero. */ |
906 | 1.76k | else if (strcmp (sec->name, ".debug_str") == 0 |
907 | 1.76k | && ISPRINT (header[4])) |
908 | 14 | compressed = false; |
909 | 1.75k | else |
910 | 1.75k | *uncompressed_size_p = bfd_getb64 (header + 4); |
911 | 21.6k | } |
912 | | |
913 | | /* Restore compress_status. */ |
914 | 3.92M | sec->compress_status = saved; |
915 | 3.92M | *compression_header_size_p = compression_header_size; |
916 | 3.92M | return compressed; |
917 | 3.92M | } |
918 | | |
919 | | /* |
920 | | FUNCTION |
921 | | bfd_is_section_compressed |
922 | | |
923 | | SYNOPSIS |
924 | | bool bfd_is_section_compressed |
925 | | (bfd *abfd, asection *section); |
926 | | |
927 | | DESCRIPTION |
928 | | Return @code{TRUE} if @var{section} is compressed. |
929 | | */ |
930 | | |
931 | | bool |
932 | | bfd_is_section_compressed (bfd *abfd, sec_ptr sec) |
933 | 3.69M | { |
934 | 3.69M | int compression_header_size; |
935 | 3.69M | bfd_size_type uncompressed_size; |
936 | 3.69M | unsigned int uncompressed_align_power; |
937 | 3.69M | enum compression_type ch_type; |
938 | 3.69M | return (bfd_is_section_compressed_info (abfd, sec, |
939 | 3.69M | &compression_header_size, |
940 | 3.69M | &uncompressed_size, |
941 | 3.69M | &uncompressed_align_power, |
942 | 3.69M | &ch_type) |
943 | 3.69M | && compression_header_size >= 0 |
944 | 3.69M | && uncompressed_size > 0); |
945 | 3.69M | } |
946 | | |
947 | | /* |
948 | | FUNCTION |
949 | | bfd_init_section_decompress_status |
950 | | |
951 | | SYNOPSIS |
952 | | bool bfd_init_section_decompress_status |
953 | | (bfd *abfd, asection *section); |
954 | | |
955 | | DESCRIPTION |
956 | | Record compressed section size, update section size with |
957 | | decompressed size and set compress_status to |
958 | | DECOMPRESS_SECTION_{ZLIB,ZSTD}. |
959 | | |
960 | | Return @code{FALSE} if the section is not a valid compressed |
961 | | section. Otherwise, return @code{TRUE}. |
962 | | */ |
963 | | |
964 | | bool |
965 | | bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec) |
966 | 883 | { |
967 | 883 | bfd_byte header[MAX_COMPRESSION_HEADER_SIZE]; |
968 | 883 | int compression_header_size; |
969 | 883 | int header_size; |
970 | 883 | bfd_size_type uncompressed_size; |
971 | 883 | unsigned int uncompressed_alignment_power = 0; |
972 | 883 | enum compression_type ch_type; |
973 | | |
974 | 883 | compression_header_size = bfd_get_compression_header_size (abfd, sec); |
975 | 883 | if (compression_header_size > MAX_COMPRESSION_HEADER_SIZE) |
976 | 0 | abort (); |
977 | 883 | header_size = compression_header_size ? compression_header_size : 12; |
978 | | |
979 | | /* Read the header. */ |
980 | 883 | if (sec->rawsize != 0 |
981 | 883 | || sec->contents != NULL |
982 | 883 | || sec->compress_status != COMPRESS_SECTION_NONE |
983 | 883 | || !bfd_get_section_contents (abfd, sec, header, 0, header_size)) |
984 | 0 | { |
985 | 0 | bfd_set_error (bfd_error_invalid_operation); |
986 | 0 | return false; |
987 | 0 | } |
988 | | |
989 | 883 | if (compression_header_size == 0) |
990 | 55 | { |
991 | | /* In this case, it should be "ZLIB" followed by the uncompressed |
992 | | section size, 8 bytes in big-endian order. */ |
993 | 55 | if (! startswith ((char*) header, "ZLIB")) |
994 | 0 | { |
995 | 0 | bfd_set_error (bfd_error_wrong_format); |
996 | 0 | return false; |
997 | 0 | } |
998 | 55 | uncompressed_size = bfd_getb64 (header + 4); |
999 | 55 | ch_type = ch_none; |
1000 | 55 | } |
1001 | 828 | else if (!bfd_check_compression_header (abfd, header, sec, |
1002 | 828 | &ch_type, |
1003 | 828 | &uncompressed_size, |
1004 | 828 | &uncompressed_alignment_power)) |
1005 | 270 | { |
1006 | 270 | bfd_set_error (bfd_error_wrong_format); |
1007 | 270 | return false; |
1008 | 270 | } |
1009 | | |
1010 | | /* PR28530, reject sizes unsupported by decompress_contents. zlib |
1011 | | supports only up to 4 GiB input on machines whose long is 32 bits. */ |
1012 | 613 | if (ch_type == ch_compress_zlib |
1013 | 613 | && (sec->size != (uLong) sec->size |
1014 | 557 | || uncompressed_size != (uLongf) uncompressed_size)) |
1015 | 0 | { |
1016 | 0 | bfd_set_error (bfd_error_nonrepresentable_section); |
1017 | 0 | return false; |
1018 | 0 | } |
1019 | | |
1020 | 613 | sec->compressed_size = sec->size; |
1021 | 613 | sec->size = uncompressed_size; |
1022 | 613 | bfd_set_section_alignment (sec, uncompressed_alignment_power); |
1023 | 613 | sec->compress_status = (ch_type == ch_compress_zstd |
1024 | 613 | ? DECOMPRESS_SECTION_ZSTD : DECOMPRESS_SECTION_ZLIB); |
1025 | | |
1026 | 613 | return true; |
1027 | 613 | } |
1028 | | |
1029 | | /* |
1030 | | FUNCTION |
1031 | | bfd_init_section_compress_status |
1032 | | |
1033 | | SYNOPSIS |
1034 | | bool bfd_init_section_compress_status |
1035 | | (bfd *abfd, asection *section); |
1036 | | |
1037 | | DESCRIPTION |
1038 | | If open for read, compress section, update section size with |
1039 | | compressed size and set compress_status to COMPRESS_SECTION_DONE. |
1040 | | |
1041 | | Return @code{FALSE} if the section is not a valid compressed |
1042 | | section. Otherwise, return @code{TRUE}. |
1043 | | */ |
1044 | | |
1045 | | bool |
1046 | | bfd_init_section_compress_status (bfd *abfd, sec_ptr sec) |
1047 | 22.9k | { |
1048 | 22.9k | bfd_size_type uncompressed_size; |
1049 | 22.9k | bfd_byte *uncompressed_buffer; |
1050 | | |
1051 | | /* Error if not opened for read. */ |
1052 | 22.9k | if (abfd->direction != read_direction |
1053 | 22.9k | || sec->size == 0 |
1054 | 22.9k | || sec->rawsize != 0 |
1055 | 22.9k | || sec->contents != NULL |
1056 | 22.9k | || sec->compress_status != COMPRESS_SECTION_NONE |
1057 | 22.9k | || bfd_section_size_insane (abfd, sec)) |
1058 | 903 | { |
1059 | 903 | bfd_set_error (bfd_error_invalid_operation); |
1060 | 903 | return false; |
1061 | 903 | } |
1062 | | |
1063 | | /* Read in the full section contents and compress it. */ |
1064 | 22.0k | uncompressed_size = sec->size; |
1065 | 22.0k | uncompressed_buffer = (bfd_byte *) bfd_malloc (uncompressed_size); |
1066 | | /* PR 21431 */ |
1067 | 22.0k | if (uncompressed_buffer == NULL) |
1068 | 0 | return false; |
1069 | | |
1070 | 22.0k | if (!bfd_get_section_contents (abfd, sec, uncompressed_buffer, |
1071 | 22.0k | 0, uncompressed_size)) |
1072 | 0 | { |
1073 | 0 | free (uncompressed_buffer); |
1074 | 0 | return false; |
1075 | 0 | } |
1076 | | |
1077 | 22.0k | sec->contents = uncompressed_buffer; |
1078 | 22.0k | if (bfd_compress_section_contents (abfd, sec) == (bfd_size_type) -1) |
1079 | 0 | { |
1080 | 0 | free (sec->contents); |
1081 | 0 | sec->contents = NULL; |
1082 | 0 | return false; |
1083 | 0 | } |
1084 | 22.0k | return true; |
1085 | 22.0k | } |
1086 | | |
1087 | | /* |
1088 | | FUNCTION |
1089 | | bfd_compress_section |
1090 | | |
1091 | | SYNOPSIS |
1092 | | bool bfd_compress_section |
1093 | | (bfd *abfd, asection *section, bfd_byte *uncompressed_buffer); |
1094 | | |
1095 | | DESCRIPTION |
1096 | | If open for write, compress section, update section size with |
1097 | | compressed size and set compress_status to COMPRESS_SECTION_DONE. |
1098 | | |
1099 | | Return @code{FALSE} if compression fail. Otherwise, return |
1100 | | @code{TRUE}. UNCOMPRESSED_BUFFER is freed in both cases. |
1101 | | */ |
1102 | | |
1103 | | bool |
1104 | | bfd_compress_section (bfd *abfd, sec_ptr sec, bfd_byte *uncompressed_buffer) |
1105 | 0 | { |
1106 | 0 | bfd_size_type uncompressed_size = sec->size; |
1107 | | |
1108 | | /* Error if not opened for write. */ |
1109 | 0 | if (abfd->direction != write_direction |
1110 | 0 | || uncompressed_size == 0 |
1111 | 0 | || uncompressed_buffer == NULL |
1112 | 0 | || sec->contents != NULL |
1113 | 0 | || sec->compressed_size != 0 |
1114 | 0 | || sec->compress_status != COMPRESS_SECTION_NONE) |
1115 | 0 | { |
1116 | 0 | bfd_set_error (bfd_error_invalid_operation); |
1117 | 0 | return false; |
1118 | 0 | } |
1119 | | |
1120 | 0 | sec->contents = uncompressed_buffer; |
1121 | 0 | if (bfd_compress_section_contents (abfd, sec) == (bfd_size_type) -1) |
1122 | 0 | { |
1123 | 0 | free (sec->contents); |
1124 | 0 | sec->contents = NULL; |
1125 | 0 | return false; |
1126 | 0 | } |
1127 | 0 | return true; |
1128 | 0 | } |