| 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 | } |