compress.c revision 1.1 1 1.1 christos /* Compressed section support (intended for debug sections).
2 1.1 christos Copyright 2008, 2010, 2011, 2012
3 1.1 christos Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos This file is part of BFD, the Binary File Descriptor library.
6 1.1 christos
7 1.1 christos This program is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3 of the License, or
10 1.1 christos (at your option) any later version.
11 1.1 christos
12 1.1 christos This program is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program; if not, write to the Free Software
19 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 1.1 christos MA 02110-1301, USA. */
21 1.1 christos
22 1.1 christos #include "sysdep.h"
23 1.1 christos #include "bfd.h"
24 1.1 christos #include "libbfd.h"
25 1.1 christos #ifdef HAVE_ZLIB_H
26 1.1 christos #include <zlib.h>
27 1.1 christos #endif
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.1 christos successfully.
156 1.1 christos */
157 1.1 christos
158 1.1 christos bfd_boolean
159 1.1 christos bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
160 1.1 christos {
161 1.1 christos bfd_size_type sz;
162 1.1 christos bfd_byte *p = *ptr;
163 1.1 christos #ifdef HAVE_ZLIB_H
164 1.1 christos bfd_boolean ret;
165 1.1 christos bfd_size_type save_size;
166 1.1 christos bfd_size_type save_rawsize;
167 1.1 christos bfd_byte *compressed_buffer;
168 1.1 christos #endif
169 1.1 christos
170 1.1 christos if (abfd->direction != write_direction && sec->rawsize != 0)
171 1.1 christos sz = sec->rawsize;
172 1.1 christos else
173 1.1 christos sz = sec->size;
174 1.1 christos if (sz == 0)
175 1.1 christos return TRUE;
176 1.1 christos
177 1.1 christos switch (sec->compress_status)
178 1.1 christos {
179 1.1 christos case COMPRESS_SECTION_NONE:
180 1.1 christos if (p == NULL)
181 1.1 christos {
182 1.1 christos p = (bfd_byte *) bfd_malloc (sz);
183 1.1 christos if (p == NULL)
184 1.1 christos return FALSE;
185 1.1 christos }
186 1.1 christos if (!bfd_get_section_contents (abfd, sec, p, 0, sz))
187 1.1 christos {
188 1.1 christos if (*ptr != p)
189 1.1 christos free (p);
190 1.1 christos return FALSE;
191 1.1 christos }
192 1.1 christos *ptr = p;
193 1.1 christos return TRUE;
194 1.1 christos
195 1.1 christos case DECOMPRESS_SECTION_SIZED:
196 1.1 christos #ifndef HAVE_ZLIB_H
197 1.1 christos bfd_set_error (bfd_error_invalid_operation);
198 1.1 christos return FALSE;
199 1.1 christos #else
200 1.1 christos /* Read in the full compressed section contents. */
201 1.1 christos compressed_buffer = (bfd_byte *) bfd_malloc (sec->compressed_size);
202 1.1 christos if (compressed_buffer == NULL)
203 1.1 christos return FALSE;
204 1.1 christos save_rawsize = sec->rawsize;
205 1.1 christos save_size = sec->size;
206 1.1 christos /* Clear rawsize, set size to compressed size and set compress_status
207 1.1 christos to COMPRESS_SECTION_NONE. If the compressed size is bigger than
208 1.1 christos the uncompressed size, bfd_get_section_contents will fail. */
209 1.1 christos sec->rawsize = 0;
210 1.1 christos sec->size = sec->compressed_size;
211 1.1 christos sec->compress_status = COMPRESS_SECTION_NONE;
212 1.1 christos ret = bfd_get_section_contents (abfd, sec, compressed_buffer,
213 1.1 christos 0, sec->compressed_size);
214 1.1 christos /* Restore rawsize and size. */
215 1.1 christos sec->rawsize = save_rawsize;
216 1.1 christos sec->size = save_size;
217 1.1 christos sec->compress_status = DECOMPRESS_SECTION_SIZED;
218 1.1 christos if (!ret)
219 1.1 christos goto fail_compressed;
220 1.1 christos
221 1.1 christos if (p == NULL)
222 1.1 christos p = (bfd_byte *) bfd_malloc (sz);
223 1.1 christos if (p == NULL)
224 1.1 christos goto fail_compressed;
225 1.1 christos
226 1.1 christos if (!decompress_contents (compressed_buffer, sec->compressed_size, p, sz))
227 1.1 christos {
228 1.1 christos bfd_set_error (bfd_error_bad_value);
229 1.1 christos if (p != *ptr)
230 1.1 christos free (p);
231 1.1 christos fail_compressed:
232 1.1 christos free (compressed_buffer);
233 1.1 christos return FALSE;
234 1.1 christos }
235 1.1 christos
236 1.1 christos free (compressed_buffer);
237 1.1 christos *ptr = p;
238 1.1 christos return TRUE;
239 1.1 christos #endif
240 1.1 christos
241 1.1 christos case COMPRESS_SECTION_DONE:
242 1.1 christos if (p == NULL)
243 1.1 christos {
244 1.1 christos p = (bfd_byte *) bfd_malloc (sz);
245 1.1 christos if (p == NULL)
246 1.1 christos return FALSE;
247 1.1 christos *ptr = p;
248 1.1 christos }
249 1.1 christos memcpy (p, sec->contents, sz);
250 1.1 christos return TRUE;
251 1.1 christos
252 1.1 christos default:
253 1.1 christos abort ();
254 1.1 christos }
255 1.1 christos }
256 1.1 christos
257 1.1 christos /*
258 1.1 christos FUNCTION
259 1.1 christos bfd_cache_section_contents
260 1.1 christos
261 1.1 christos SYNOPSIS
262 1.1 christos void bfd_cache_section_contents
263 1.1 christos (asection *sec, void *contents);
264 1.1 christos
265 1.1 christos DESCRIPTION
266 1.1 christos Stash @var(contents) so any following reads of @var(sec) do
267 1.1 christos not need to decompress again.
268 1.1 christos */
269 1.1 christos
270 1.1 christos void
271 1.1 christos bfd_cache_section_contents (asection *sec, void *contents)
272 1.1 christos {
273 1.1 christos if (sec->compress_status == DECOMPRESS_SECTION_SIZED)
274 1.1 christos sec->compress_status = COMPRESS_SECTION_DONE;
275 1.1 christos sec->contents = contents;
276 1.1 christos sec->flags |= SEC_IN_MEMORY;
277 1.1 christos }
278 1.1 christos
279 1.1 christos
280 1.1 christos /*
281 1.1 christos FUNCTION
282 1.1 christos bfd_is_section_compressed
283 1.1 christos
284 1.1 christos SYNOPSIS
285 1.1 christos bfd_boolean bfd_is_section_compressed
286 1.1 christos (bfd *abfd, asection *section);
287 1.1 christos
288 1.1 christos DESCRIPTION
289 1.1 christos Return @code{TRUE} if @var{section} is compressed.
290 1.1 christos */
291 1.1 christos
292 1.1 christos bfd_boolean
293 1.1 christos bfd_is_section_compressed (bfd *abfd, sec_ptr sec)
294 1.1 christos {
295 1.1 christos bfd_byte compressed_buffer [12];
296 1.1 christos unsigned int saved = sec->compress_status;
297 1.1 christos bfd_boolean compressed;
298 1.1 christos
299 1.1 christos /* Don't decompress the section. */
300 1.1 christos sec->compress_status = COMPRESS_SECTION_NONE;
301 1.1 christos
302 1.1 christos /* Read the zlib header. In this case, it should be "ZLIB" followed
303 1.1 christos by the uncompressed section size, 8 bytes in big-endian order. */
304 1.1 christos compressed = (bfd_get_section_contents (abfd, sec, compressed_buffer, 0, 12)
305 1.1 christos && CONST_STRNEQ ((char*) compressed_buffer, "ZLIB"));
306 1.1 christos
307 1.1 christos /* Restore compress_status. */
308 1.1 christos sec->compress_status = saved;
309 1.1 christos return compressed;
310 1.1 christos }
311 1.1 christos
312 1.1 christos /*
313 1.1 christos FUNCTION
314 1.1 christos bfd_init_section_decompress_status
315 1.1 christos
316 1.1 christos SYNOPSIS
317 1.1 christos bfd_boolean bfd_init_section_decompress_status
318 1.1 christos (bfd *abfd, asection *section);
319 1.1 christos
320 1.1 christos DESCRIPTION
321 1.1 christos Record compressed section size, update section size with
322 1.1 christos decompressed size and set compress_status to
323 1.1 christos DECOMPRESS_SECTION_SIZED.
324 1.1 christos
325 1.1 christos Return @code{FALSE} if the section is not a valid compressed
326 1.1 christos section or zlib is not installed on this machine. Otherwise,
327 1.1 christos return @code{TRUE}.
328 1.1 christos */
329 1.1 christos
330 1.1 christos bfd_boolean
331 1.1 christos bfd_init_section_decompress_status (bfd *abfd ATTRIBUTE_UNUSED,
332 1.1 christos sec_ptr sec ATTRIBUTE_UNUSED)
333 1.1 christos {
334 1.1 christos #ifndef HAVE_ZLIB_H
335 1.1 christos bfd_set_error (bfd_error_invalid_operation);
336 1.1 christos return FALSE;
337 1.1 christos #else
338 1.1 christos bfd_byte compressed_buffer [12];
339 1.1 christos bfd_size_type uncompressed_size;
340 1.1 christos
341 1.1 christos if (sec->rawsize != 0
342 1.1 christos || sec->contents != NULL
343 1.1 christos || sec->compress_status != COMPRESS_SECTION_NONE
344 1.1 christos || !bfd_get_section_contents (abfd, sec, compressed_buffer, 0, 12))
345 1.1 christos {
346 1.1 christos bfd_set_error (bfd_error_invalid_operation);
347 1.1 christos return FALSE;
348 1.1 christos }
349 1.1 christos
350 1.1 christos /* Read the zlib header. In this case, it should be "ZLIB" followed
351 1.1 christos by the uncompressed section size, 8 bytes in big-endian order. */
352 1.1 christos if (! CONST_STRNEQ ((char*) compressed_buffer, "ZLIB"))
353 1.1 christos {
354 1.1 christos bfd_set_error (bfd_error_wrong_format);
355 1.1 christos return FALSE;
356 1.1 christos }
357 1.1 christos
358 1.1 christos uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8;
359 1.1 christos uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8;
360 1.1 christos uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8;
361 1.1 christos uncompressed_size += compressed_buffer[7]; uncompressed_size <<= 8;
362 1.1 christos uncompressed_size += compressed_buffer[8]; uncompressed_size <<= 8;
363 1.1 christos uncompressed_size += compressed_buffer[9]; uncompressed_size <<= 8;
364 1.1 christos uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8;
365 1.1 christos uncompressed_size += compressed_buffer[11];
366 1.1 christos
367 1.1 christos sec->compressed_size = sec->size;
368 1.1 christos sec->size = uncompressed_size;
369 1.1 christos sec->compress_status = DECOMPRESS_SECTION_SIZED;
370 1.1 christos
371 1.1 christos return TRUE;
372 1.1 christos #endif
373 1.1 christos }
374 1.1 christos
375 1.1 christos /*
376 1.1 christos FUNCTION
377 1.1 christos bfd_init_section_compress_status
378 1.1 christos
379 1.1 christos SYNOPSIS
380 1.1 christos bfd_boolean bfd_init_section_compress_status
381 1.1 christos (bfd *abfd, asection *section);
382 1.1 christos
383 1.1 christos DESCRIPTION
384 1.1 christos If open for read, compress section, update section size with
385 1.1 christos compressed size and set compress_status to COMPRESS_SECTION_DONE.
386 1.1 christos
387 1.1 christos Return @code{FALSE} if the section is not a valid compressed
388 1.1 christos section or zlib is not installed on this machine. Otherwise,
389 1.1 christos return @code{TRUE}.
390 1.1 christos */
391 1.1 christos
392 1.1 christos bfd_boolean
393 1.1 christos bfd_init_section_compress_status (bfd *abfd ATTRIBUTE_UNUSED,
394 1.1 christos sec_ptr sec ATTRIBUTE_UNUSED)
395 1.1 christos {
396 1.1 christos #ifndef HAVE_ZLIB_H
397 1.1 christos bfd_set_error (bfd_error_invalid_operation);
398 1.1 christos return FALSE;
399 1.1 christos #else
400 1.1 christos bfd_size_type uncompressed_size;
401 1.1 christos bfd_byte *uncompressed_buffer;
402 1.1 christos bfd_boolean ret;
403 1.1 christos
404 1.1 christos /* Error if not opened for read. */
405 1.1 christos if (abfd->direction != read_direction
406 1.1 christos || sec->size == 0
407 1.1 christos || sec->rawsize != 0
408 1.1 christos || sec->contents != NULL
409 1.1 christos || sec->compress_status != COMPRESS_SECTION_NONE)
410 1.1 christos {
411 1.1 christos bfd_set_error (bfd_error_invalid_operation);
412 1.1 christos return FALSE;
413 1.1 christos }
414 1.1 christos
415 1.1 christos /* Read in the full section contents and compress it. */
416 1.1 christos uncompressed_size = sec->size;
417 1.1 christos uncompressed_buffer = (bfd_byte *) bfd_malloc (uncompressed_size);
418 1.1 christos if (!bfd_get_section_contents (abfd, sec, uncompressed_buffer,
419 1.1 christos 0, uncompressed_size))
420 1.1 christos ret = FALSE;
421 1.1 christos else
422 1.1 christos ret = bfd_compress_section_contents (abfd, sec,
423 1.1 christos uncompressed_buffer,
424 1.1 christos uncompressed_size);
425 1.1 christos
426 1.1 christos free (uncompressed_buffer);
427 1.1 christos return ret;
428 1.1 christos #endif
429 1.1 christos }
430