compress.c revision 1.3 1 1.1 christos /* Compressed section support (intended for debug sections).
2 1.3 christos Copyright (C) 2008-2015 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos This file is part of BFD, the Binary File Descriptor library.
5 1.1 christos
6 1.1 christos This program is free software; you can redistribute it and/or modify
7 1.1 christos it under the terms of the GNU General Public License as published by
8 1.1 christos the Free Software Foundation; either version 3 of the License, or
9 1.1 christos (at your option) any later version.
10 1.1 christos
11 1.1 christos This program is distributed in the hope that it will be useful,
12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 christos GNU General Public License for more details.
15 1.1 christos
16 1.1 christos You should have received a copy of the GNU General Public License
17 1.1 christos along with this program; if not, write to the Free Software
18 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 1.1 christos MA 02110-1301, USA. */
20 1.1 christos
21 1.1 christos #include "sysdep.h"
22 1.1 christos #include "bfd.h"
23 1.1 christos #include "libbfd.h"
24 1.1 christos #ifdef HAVE_ZLIB_H
25 1.1 christos #include <zlib.h>
26 1.1 christos #endif
27 1.3 christos #include "safe-ctype.h"
28 1.1 christos
29 1.1 christos #ifdef HAVE_ZLIB_H
30 1.1 christos static bfd_boolean
31 1.1 christos decompress_contents (bfd_byte *compressed_buffer,
32 1.1 christos bfd_size_type compressed_size,
33 1.1 christos bfd_byte *uncompressed_buffer,
34 1.1 christos bfd_size_type uncompressed_size)
35 1.1 christos {
36 1.1 christos z_stream strm;
37 1.1 christos int rc;
38 1.1 christos
39 1.1 christos /* It is possible the section consists of several compressed
40 1.1 christos buffers concatenated together, so we uncompress in a loop. */
41 1.1 christos strm.zalloc = NULL;
42 1.1 christos strm.zfree = NULL;
43 1.1 christos strm.opaque = NULL;
44 1.1 christos strm.avail_in = compressed_size - 12;
45 1.1 christos strm.next_in = (Bytef*) compressed_buffer + 12;
46 1.1 christos strm.avail_out = uncompressed_size;
47 1.1 christos
48 1.1 christos BFD_ASSERT (Z_OK == 0);
49 1.1 christos rc = inflateInit (&strm);
50 1.1 christos while (strm.avail_in > 0 && strm.avail_out > 0)
51 1.1 christos {
52 1.1 christos if (rc != Z_OK)
53 1.1 christos break;
54 1.1 christos strm.next_out = ((Bytef*) uncompressed_buffer
55 1.1 christos + (uncompressed_size - strm.avail_out));
56 1.1 christos rc = inflate (&strm, Z_FINISH);
57 1.1 christos if (rc != Z_STREAM_END)
58 1.1 christos break;
59 1.1 christos rc = inflateReset (&strm);
60 1.1 christos }
61 1.1 christos rc |= inflateEnd (&strm);
62 1.1 christos return rc == Z_OK && strm.avail_out == 0;
63 1.1 christos }
64 1.1 christos #endif
65 1.1 christos
66 1.1 christos /*
67 1.1 christos FUNCTION
68 1.1 christos bfd_compress_section_contents
69 1.1 christos
70 1.1 christos SYNOPSIS
71 1.1 christos bfd_boolean bfd_compress_section_contents
72 1.1 christos (bfd *abfd, asection *section, bfd_byte *uncompressed_buffer,
73 1.1 christos bfd_size_type uncompressed_size);
74 1.1 christos
75 1.1 christos DESCRIPTION
76 1.1 christos
77 1.1 christos Compress data of the size specified in @var{uncompressed_size}
78 1.1 christos and pointed to by @var{uncompressed_buffer} using zlib and store
79 1.1 christos as the contents field. This function assumes the contents
80 1.1 christos field was allocated using bfd_malloc() or equivalent. If zlib
81 1.1 christos is not installed on this machine, the input is unmodified.
82 1.1 christos
83 1.1 christos Return @code{TRUE} if the full section contents is compressed
84 1.1 christos successfully.
85 1.1 christos */
86 1.1 christos
87 1.1 christos bfd_boolean
88 1.1 christos bfd_compress_section_contents (bfd *abfd ATTRIBUTE_UNUSED,
89 1.1 christos sec_ptr sec ATTRIBUTE_UNUSED,
90 1.1 christos bfd_byte *uncompressed_buffer ATTRIBUTE_UNUSED,
91 1.1 christos bfd_size_type uncompressed_size ATTRIBUTE_UNUSED)
92 1.1 christos {
93 1.1 christos #ifndef HAVE_ZLIB_H
94 1.1 christos bfd_set_error (bfd_error_invalid_operation);
95 1.1 christos return FALSE;
96 1.1 christos #else
97 1.1 christos uLong compressed_size;
98 1.1 christos bfd_byte *compressed_buffer;
99 1.1 christos
100 1.1 christos compressed_size = compressBound (uncompressed_size) + 12;
101 1.1 christos compressed_buffer = (bfd_byte *) bfd_malloc (compressed_size);
102 1.1 christos
103 1.1 christos if (compressed_buffer == NULL)
104 1.1 christos return FALSE;
105 1.1 christos
106 1.1 christos if (compress ((Bytef*) compressed_buffer + 12,
107 1.1 christos &compressed_size,
108 1.1 christos (const Bytef*) uncompressed_buffer,
109 1.1 christos uncompressed_size) != Z_OK)
110 1.1 christos {
111 1.1 christos free (compressed_buffer);
112 1.1 christos bfd_set_error (bfd_error_bad_value);
113 1.1 christos return FALSE;
114 1.1 christos }
115 1.1 christos
116 1.1 christos /* Write the zlib header. In this case, it should be "ZLIB" followed
117 1.1 christos by the uncompressed section size, 8 bytes in big-endian order. */
118 1.1 christos memcpy (compressed_buffer, "ZLIB", 4);
119 1.1 christos compressed_buffer[11] = uncompressed_size; uncompressed_size >>= 8;
120 1.1 christos compressed_buffer[10] = uncompressed_size; uncompressed_size >>= 8;
121 1.1 christos compressed_buffer[9] = uncompressed_size; uncompressed_size >>= 8;
122 1.1 christos compressed_buffer[8] = uncompressed_size; uncompressed_size >>= 8;
123 1.1 christos compressed_buffer[7] = uncompressed_size; uncompressed_size >>= 8;
124 1.1 christos compressed_buffer[6] = uncompressed_size; uncompressed_size >>= 8;
125 1.1 christos compressed_buffer[5] = uncompressed_size; uncompressed_size >>= 8;
126 1.1 christos compressed_buffer[4] = uncompressed_size;
127 1.1 christos compressed_size += 12;
128 1.1 christos
129 1.1 christos /* Free the uncompressed contents if we compress in place. */
130 1.1 christos if (uncompressed_buffer == sec->contents)
131 1.1 christos free (uncompressed_buffer);
132 1.1 christos
133 1.1 christos sec->contents = compressed_buffer;
134 1.1 christos sec->size = compressed_size;
135 1.1 christos sec->compress_status = COMPRESS_SECTION_DONE;
136 1.1 christos
137 1.1 christos return TRUE;
138 1.1 christos #endif /* HAVE_ZLIB_H */
139 1.1 christos }
140 1.1 christos
141 1.1 christos /*
142 1.1 christos FUNCTION
143 1.1 christos bfd_get_full_section_contents
144 1.1 christos
145 1.1 christos SYNOPSIS
146 1.1 christos bfd_boolean bfd_get_full_section_contents
147 1.1 christos (bfd *abfd, asection *section, bfd_byte **ptr);
148 1.1 christos
149 1.1 christos DESCRIPTION
150 1.1 christos Read all data from @var{section} in BFD @var{abfd}, decompress
151 1.1 christos if needed, and store in @var{*ptr}. If @var{*ptr} is NULL,
152 1.1 christos return @var{*ptr} with memory malloc'd by this function.
153 1.1 christos
154 1.1 christos Return @code{TRUE} if the full section contents is retrieved
155 1.3 christos successfully. If the section has no contents then this function
156 1.3 christos returns @code{TRUE} but @var{*ptr} is set to NULL.
157 1.1 christos */
158 1.1 christos
159 1.1 christos bfd_boolean
160 1.1 christos bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
161 1.1 christos {
162 1.1 christos bfd_size_type sz;
163 1.1 christos bfd_byte *p = *ptr;
164 1.1 christos #ifdef HAVE_ZLIB_H
165 1.1 christos bfd_boolean ret;
166 1.1 christos bfd_size_type save_size;
167 1.1 christos bfd_size_type save_rawsize;
168 1.1 christos bfd_byte *compressed_buffer;
169 1.1 christos #endif
170 1.1 christos
171 1.1 christos if (abfd->direction != write_direction && sec->rawsize != 0)
172 1.1 christos sz = sec->rawsize;
173 1.1 christos else
174 1.1 christos sz = sec->size;
175 1.1 christos if (sz == 0)
176 1.3 christos {
177 1.3 christos *ptr = NULL;
178 1.3 christos return TRUE;
179 1.3 christos }
180 1.1 christos
181 1.1 christos switch (sec->compress_status)
182 1.1 christos {
183 1.1 christos case COMPRESS_SECTION_NONE:
184 1.1 christos if (p == NULL)
185 1.1 christos {
186 1.1 christos p = (bfd_byte *) bfd_malloc (sz);
187 1.1 christos if (p == NULL)
188 1.1 christos return FALSE;
189 1.1 christos }
190 1.3 christos
191 1.1 christos if (!bfd_get_section_contents (abfd, sec, p, 0, sz))
192 1.1 christos {
193 1.1 christos if (*ptr != p)
194 1.1 christos free (p);
195 1.1 christos return FALSE;
196 1.1 christos }
197 1.1 christos *ptr = p;
198 1.1 christos return TRUE;
199 1.1 christos
200 1.1 christos case DECOMPRESS_SECTION_SIZED:
201 1.1 christos #ifndef HAVE_ZLIB_H
202 1.1 christos bfd_set_error (bfd_error_invalid_operation);
203 1.1 christos return FALSE;
204 1.1 christos #else
205 1.1 christos /* Read in the full compressed section contents. */
206 1.1 christos compressed_buffer = (bfd_byte *) bfd_malloc (sec->compressed_size);
207 1.1 christos if (compressed_buffer == NULL)
208 1.1 christos return FALSE;
209 1.1 christos save_rawsize = sec->rawsize;
210 1.1 christos save_size = sec->size;
211 1.1 christos /* Clear rawsize, set size to compressed size and set compress_status
212 1.1 christos to COMPRESS_SECTION_NONE. If the compressed size is bigger than
213 1.1 christos the uncompressed size, bfd_get_section_contents will fail. */
214 1.1 christos sec->rawsize = 0;
215 1.1 christos sec->size = sec->compressed_size;
216 1.1 christos sec->compress_status = COMPRESS_SECTION_NONE;
217 1.1 christos ret = bfd_get_section_contents (abfd, sec, compressed_buffer,
218 1.1 christos 0, sec->compressed_size);
219 1.1 christos /* Restore rawsize and size. */
220 1.1 christos sec->rawsize = save_rawsize;
221 1.1 christos sec->size = save_size;
222 1.1 christos sec->compress_status = DECOMPRESS_SECTION_SIZED;
223 1.1 christos if (!ret)
224 1.1 christos goto fail_compressed;
225 1.1 christos
226 1.1 christos if (p == NULL)
227 1.1 christos p = (bfd_byte *) bfd_malloc (sz);
228 1.1 christos if (p == NULL)
229 1.1 christos goto fail_compressed;
230 1.1 christos
231 1.1 christos if (!decompress_contents (compressed_buffer, sec->compressed_size, p, sz))
232 1.1 christos {
233 1.1 christos bfd_set_error (bfd_error_bad_value);
234 1.1 christos if (p != *ptr)
235 1.1 christos free (p);
236 1.1 christos fail_compressed:
237 1.1 christos free (compressed_buffer);
238 1.1 christos return FALSE;
239 1.1 christos }
240 1.1 christos
241 1.1 christos free (compressed_buffer);
242 1.1 christos *ptr = p;
243 1.1 christos return TRUE;
244 1.1 christos #endif
245 1.1 christos
246 1.1 christos case COMPRESS_SECTION_DONE:
247 1.3 christos if (sec->contents == NULL)
248 1.3 christos return FALSE;
249 1.1 christos if (p == NULL)
250 1.1 christos {
251 1.1 christos p = (bfd_byte *) bfd_malloc (sz);
252 1.1 christos if (p == NULL)
253 1.1 christos return FALSE;
254 1.1 christos *ptr = p;
255 1.1 christos }
256 1.3 christos /* PR 17512; file: 5bc29788. */
257 1.3 christos if (p != sec->contents)
258 1.3 christos memcpy (p, sec->contents, sz);
259 1.1 christos return TRUE;
260 1.1 christos
261 1.1 christos default:
262 1.1 christos abort ();
263 1.1 christos }
264 1.1 christos }
265 1.1 christos
266 1.1 christos /*
267 1.1 christos FUNCTION
268 1.1 christos bfd_cache_section_contents
269 1.1 christos
270 1.1 christos SYNOPSIS
271 1.1 christos void bfd_cache_section_contents
272 1.1 christos (asection *sec, void *contents);
273 1.1 christos
274 1.1 christos DESCRIPTION
275 1.1 christos Stash @var(contents) so any following reads of @var(sec) do
276 1.1 christos not need to decompress again.
277 1.1 christos */
278 1.1 christos
279 1.1 christos void
280 1.1 christos bfd_cache_section_contents (asection *sec, void *contents)
281 1.1 christos {
282 1.1 christos if (sec->compress_status == DECOMPRESS_SECTION_SIZED)
283 1.1 christos sec->compress_status = COMPRESS_SECTION_DONE;
284 1.1 christos sec->contents = contents;
285 1.1 christos sec->flags |= SEC_IN_MEMORY;
286 1.1 christos }
287 1.1 christos
288 1.1 christos
289 1.1 christos /*
290 1.1 christos FUNCTION
291 1.1 christos bfd_is_section_compressed
292 1.1 christos
293 1.1 christos SYNOPSIS
294 1.1 christos bfd_boolean bfd_is_section_compressed
295 1.1 christos (bfd *abfd, asection *section);
296 1.1 christos
297 1.1 christos DESCRIPTION
298 1.1 christos Return @code{TRUE} if @var{section} is compressed.
299 1.1 christos */
300 1.1 christos
301 1.1 christos bfd_boolean
302 1.1 christos bfd_is_section_compressed (bfd *abfd, sec_ptr sec)
303 1.1 christos {
304 1.1 christos bfd_byte compressed_buffer [12];
305 1.1 christos unsigned int saved = sec->compress_status;
306 1.1 christos bfd_boolean compressed;
307 1.1 christos
308 1.1 christos /* Don't decompress the section. */
309 1.1 christos sec->compress_status = COMPRESS_SECTION_NONE;
310 1.1 christos
311 1.1 christos /* Read the zlib header. In this case, it should be "ZLIB" followed
312 1.1 christos by the uncompressed section size, 8 bytes in big-endian order. */
313 1.1 christos compressed = (bfd_get_section_contents (abfd, sec, compressed_buffer, 0, 12)
314 1.1 christos && CONST_STRNEQ ((char*) compressed_buffer, "ZLIB"));
315 1.1 christos
316 1.3 christos /* Check for the pathalogical case of a debug string section that
317 1.3 christos contains the string ZLIB.... as the first entry. We assume that
318 1.3 christos no uncompressed .debug_str section would ever be big enough to
319 1.3 christos have the first byte of its (big-endian) size be non-zero. */
320 1.3 christos if (compressed
321 1.3 christos && strcmp (sec->name, ".debug_str") == 0
322 1.3 christos && ISPRINT (compressed_buffer[4]))
323 1.3 christos compressed = FALSE;
324 1.3 christos
325 1.1 christos /* Restore compress_status. */
326 1.1 christos sec->compress_status = saved;
327 1.1 christos return compressed;
328 1.1 christos }
329 1.1 christos
330 1.1 christos /*
331 1.1 christos FUNCTION
332 1.1 christos bfd_init_section_decompress_status
333 1.1 christos
334 1.1 christos SYNOPSIS
335 1.1 christos bfd_boolean bfd_init_section_decompress_status
336 1.1 christos (bfd *abfd, asection *section);
337 1.1 christos
338 1.1 christos DESCRIPTION
339 1.1 christos Record compressed section size, update section size with
340 1.1 christos decompressed size and set compress_status to
341 1.1 christos DECOMPRESS_SECTION_SIZED.
342 1.1 christos
343 1.1 christos Return @code{FALSE} if the section is not a valid compressed
344 1.1 christos section or zlib is not installed on this machine. Otherwise,
345 1.1 christos return @code{TRUE}.
346 1.1 christos */
347 1.1 christos
348 1.1 christos bfd_boolean
349 1.1 christos bfd_init_section_decompress_status (bfd *abfd ATTRIBUTE_UNUSED,
350 1.1 christos sec_ptr sec ATTRIBUTE_UNUSED)
351 1.1 christos {
352 1.1 christos #ifndef HAVE_ZLIB_H
353 1.1 christos bfd_set_error (bfd_error_invalid_operation);
354 1.1 christos return FALSE;
355 1.1 christos #else
356 1.1 christos bfd_byte compressed_buffer [12];
357 1.1 christos bfd_size_type uncompressed_size;
358 1.1 christos
359 1.1 christos if (sec->rawsize != 0
360 1.1 christos || sec->contents != NULL
361 1.1 christos || sec->compress_status != COMPRESS_SECTION_NONE
362 1.1 christos || !bfd_get_section_contents (abfd, sec, compressed_buffer, 0, 12))
363 1.1 christos {
364 1.1 christos bfd_set_error (bfd_error_invalid_operation);
365 1.1 christos return FALSE;
366 1.1 christos }
367 1.1 christos
368 1.1 christos /* Read the zlib header. In this case, it should be "ZLIB" followed
369 1.1 christos by the uncompressed section size, 8 bytes in big-endian order. */
370 1.1 christos if (! CONST_STRNEQ ((char*) compressed_buffer, "ZLIB"))
371 1.1 christos {
372 1.1 christos bfd_set_error (bfd_error_wrong_format);
373 1.1 christos return FALSE;
374 1.1 christos }
375 1.1 christos
376 1.1 christos uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8;
377 1.1 christos uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8;
378 1.1 christos uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8;
379 1.1 christos uncompressed_size += compressed_buffer[7]; uncompressed_size <<= 8;
380 1.1 christos uncompressed_size += compressed_buffer[8]; uncompressed_size <<= 8;
381 1.1 christos uncompressed_size += compressed_buffer[9]; uncompressed_size <<= 8;
382 1.1 christos uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8;
383 1.1 christos uncompressed_size += compressed_buffer[11];
384 1.1 christos
385 1.1 christos sec->compressed_size = sec->size;
386 1.1 christos sec->size = uncompressed_size;
387 1.1 christos sec->compress_status = DECOMPRESS_SECTION_SIZED;
388 1.1 christos
389 1.1 christos return TRUE;
390 1.1 christos #endif
391 1.1 christos }
392 1.1 christos
393 1.1 christos /*
394 1.1 christos FUNCTION
395 1.1 christos bfd_init_section_compress_status
396 1.1 christos
397 1.1 christos SYNOPSIS
398 1.1 christos bfd_boolean bfd_init_section_compress_status
399 1.1 christos (bfd *abfd, asection *section);
400 1.1 christos
401 1.1 christos DESCRIPTION
402 1.1 christos If open for read, compress section, update section size with
403 1.1 christos compressed size and set compress_status to COMPRESS_SECTION_DONE.
404 1.1 christos
405 1.1 christos Return @code{FALSE} if the section is not a valid compressed
406 1.1 christos section or zlib is not installed on this machine. Otherwise,
407 1.1 christos return @code{TRUE}.
408 1.1 christos */
409 1.1 christos
410 1.1 christos bfd_boolean
411 1.1 christos bfd_init_section_compress_status (bfd *abfd ATTRIBUTE_UNUSED,
412 1.1 christos sec_ptr sec ATTRIBUTE_UNUSED)
413 1.1 christos {
414 1.1 christos #ifndef HAVE_ZLIB_H
415 1.1 christos bfd_set_error (bfd_error_invalid_operation);
416 1.1 christos return FALSE;
417 1.1 christos #else
418 1.1 christos bfd_size_type uncompressed_size;
419 1.1 christos bfd_byte *uncompressed_buffer;
420 1.1 christos bfd_boolean ret;
421 1.1 christos
422 1.1 christos /* Error if not opened for read. */
423 1.1 christos if (abfd->direction != read_direction
424 1.1 christos || sec->size == 0
425 1.1 christos || sec->rawsize != 0
426 1.1 christos || sec->contents != NULL
427 1.1 christos || sec->compress_status != COMPRESS_SECTION_NONE)
428 1.1 christos {
429 1.1 christos bfd_set_error (bfd_error_invalid_operation);
430 1.1 christos return FALSE;
431 1.1 christos }
432 1.1 christos
433 1.1 christos /* Read in the full section contents and compress it. */
434 1.1 christos uncompressed_size = sec->size;
435 1.1 christos uncompressed_buffer = (bfd_byte *) bfd_malloc (uncompressed_size);
436 1.1 christos if (!bfd_get_section_contents (abfd, sec, uncompressed_buffer,
437 1.1 christos 0, uncompressed_size))
438 1.1 christos ret = FALSE;
439 1.1 christos else
440 1.1 christos ret = bfd_compress_section_contents (abfd, sec,
441 1.1 christos uncompressed_buffer,
442 1.1 christos uncompressed_size);
443 1.1 christos
444 1.1 christos free (uncompressed_buffer);
445 1.1 christos return ret;
446 1.1 christos #endif
447 1.1 christos }
448