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