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