]>
Commit | Line | Data |
---|---|---|
1b315056 CS |
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_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 | } |