bfd/ChangeLog:
[external/binutils.git] / bfd / compress.c
1 /* Compressed section support (intended for debug sections).
2    Copyright 2008, 2010
3    Free Software Foundation, Inc.
4
5    This file is part of BFD, the Binary File Descriptor library.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21
22 #include "config.h"
23 #include "sysdep.h"
24 #include "bfd.h"
25 #include "libbfd.h"
26 #ifdef HAVE_ZLIB_H
27 #include <zlib.h>
28 #endif
29
30 /*
31 FUNCTION
32         bfd_uncompress_section_contents
33
34 SYNOPSIS
35         bfd_boolean bfd_uncompress_section_contents
36           (bfd_byte **buffer, bfd_size_type *size);
37
38 DESCRIPTION
39
40         Uncompresses a section that was compressed using zlib, in place.  At
41         the call to this function, *@var{buffer} and *@var{size} should point
42         to the section contents to be uncompressed.  At the end of the
43         function, *@var{buffer} and *@var{size} will point to the uncompressed
44         contents.  This function assumes *BUFFER was allocated using
45         bfd_malloc() or equivalent.  If the section is not a valid compressed
46         section, or zlib is not installed on this machine, the input is
47         unmodified.
48
49         Returns @code{FALSE} if unable to uncompress successfully; in that case
50         the input is unmodified.  Otherwise, returns @code{TRUE}.
51 */
52
53 bfd_boolean
54 bfd_uncompress_section_contents (bfd_byte **buffer ATTRIBUTE_UNUSED,
55                                  bfd_size_type *size ATTRIBUTE_UNUSED)
56 {
57 #ifndef HAVE_ZLIB_H
58   return FALSE;
59 #else
60   bfd_size_type compressed_size = *size;
61   bfd_byte *compressed_buffer = *buffer;
62   bfd_size_type uncompressed_size;
63   bfd_byte *uncompressed_buffer;
64   z_stream strm;
65   int rc;
66   bfd_size_type header_size = 12;
67
68   /* Read the zlib header.  In this case, it should be "ZLIB" followed
69      by the uncompressed section size, 8 bytes in big-endian order.  */
70   if (compressed_size < header_size
71       || ! CONST_STRNEQ ((char*) compressed_buffer, "ZLIB"))
72     return FALSE;
73   uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8;
74   uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8;
75   uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8;
76   uncompressed_size += compressed_buffer[7]; uncompressed_size <<= 8;
77   uncompressed_size += compressed_buffer[8]; uncompressed_size <<= 8;
78   uncompressed_size += compressed_buffer[9]; uncompressed_size <<= 8;
79   uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8;
80   uncompressed_size += compressed_buffer[11];
81
82   /* It is possible the section consists of several compressed
83      buffers concatenated together, so we uncompress in a loop.  */
84   strm.zalloc = NULL;
85   strm.zfree = NULL;
86   strm.opaque = NULL;
87   strm.avail_in = compressed_size - header_size;
88   strm.next_in = (Bytef*) compressed_buffer + header_size;
89   strm.avail_out = uncompressed_size;
90   uncompressed_buffer = (bfd_byte *) bfd_malloc (uncompressed_size);
91   if (! uncompressed_buffer)
92     return FALSE;
93
94   rc = inflateInit (&strm);
95   while (strm.avail_in > 0)
96     {
97       if (rc != Z_OK)
98         goto fail;
99       strm.next_out = ((Bytef*) uncompressed_buffer
100                        + (uncompressed_size - strm.avail_out));
101       rc = inflate (&strm, Z_FINISH);
102       if (rc != Z_STREAM_END)
103         goto fail;
104       rc = inflateReset (&strm);
105     }
106   rc = inflateEnd (&strm);
107   if (rc != Z_OK
108       || strm.avail_out != 0)
109     goto fail;
110
111   free (compressed_buffer);
112   *buffer = uncompressed_buffer;
113   *size = uncompressed_size;
114   return TRUE;
115
116  fail:
117   free (uncompressed_buffer);
118   return FALSE;
119 #endif  /* HAVE_ZLIB_H */
120 }