Import binutils-2.20
[dragonfly.git] / contrib / binutils-2.20 / bfd / compress.c
1 /* ELF attributes support (based on ARM EABI attributes).
2    Copyright 2008
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, bfd_size_type *size)
55 {
56 #ifndef HAVE_ZLIB_H
57   /* These are just to quiet gcc.  */
58   buffer = 0;
59   size = 0;
60   return FALSE;
61 #else
62   bfd_size_type compressed_size = *size;
63   bfd_byte *compressed_buffer = *buffer;
64   bfd_size_type uncompressed_size;
65   bfd_byte *uncompressed_buffer;
66   z_stream strm;
67   int rc;
68   bfd_size_type header_size = 12;
69
70   /* Read the zlib header.  In this case, it should be "ZLIB" followed
71      by the uncompressed section size, 8 bytes in big-endian order.  */
72   if (compressed_size < header_size
73       || ! CONST_STRNEQ ((char*) compressed_buffer, "ZLIB"))
74     return FALSE;
75   uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8;
76   uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8;
77   uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8;
78   uncompressed_size += compressed_buffer[7]; uncompressed_size <<= 8;
79   uncompressed_size += compressed_buffer[8]; uncompressed_size <<= 8;
80   uncompressed_size += compressed_buffer[9]; uncompressed_size <<= 8;
81   uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8;
82   uncompressed_size += compressed_buffer[11];
83
84   /* It is possible the section consists of several compressed
85      buffers concatenated together, so we uncompress in a loop.  */
86   strm.zalloc = NULL;
87   strm.zfree = NULL;
88   strm.opaque = NULL;
89   strm.avail_in = compressed_size - header_size;
90   strm.next_in = (Bytef*) compressed_buffer + header_size;
91   strm.avail_out = uncompressed_size;
92   uncompressed_buffer = (bfd_byte *) bfd_malloc (uncompressed_size);
93   if (! uncompressed_buffer)
94     return FALSE;
95
96   rc = inflateInit (&strm);
97   while (strm.avail_in > 0)
98     {
99       if (rc != Z_OK)
100         goto fail;
101       strm.next_out = ((Bytef*) uncompressed_buffer
102                        + (uncompressed_size - strm.avail_out));
103       rc = inflate (&strm, Z_FINISH);
104       if (rc != Z_STREAM_END)
105         goto fail;
106       rc = inflateReset (&strm);
107     }
108   rc = inflateEnd (&strm);
109   if (rc != Z_OK
110       || strm.avail_out != 0)
111     goto fail;
112
113   free (compressed_buffer);
114   *buffer = uncompressed_buffer;
115   *size = uncompressed_size;
116   return TRUE;
117
118  fail:
119   free (uncompressed_buffer);
120   return FALSE;
121 #endif  /* HAVE_ZLIB_H */
122 }