Home | History | Annotate | Line # | Download | only in bfd
compress.c revision 1.1
      1  1.1  christos /* Compressed section support (intended for debug sections).
      2  1.1  christos    Copyright 2008, 2010, 2011, 2012
      3  1.1  christos    Free Software Foundation, Inc.
      4  1.1  christos 
      5  1.1  christos    This file is part of BFD, the Binary File Descriptor library.
      6  1.1  christos 
      7  1.1  christos    This program is free software; you can redistribute it and/or modify
      8  1.1  christos    it under the terms of the GNU General Public License as published by
      9  1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10  1.1  christos    (at your option) any later version.
     11  1.1  christos 
     12  1.1  christos    This program is distributed in the hope that it will be useful,
     13  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  1.1  christos    GNU General Public License for more details.
     16  1.1  christos 
     17  1.1  christos    You should have received a copy of the GNU General Public License
     18  1.1  christos    along with this program; if not, write to the Free Software
     19  1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20  1.1  christos    MA 02110-1301, USA.  */
     21  1.1  christos 
     22  1.1  christos #include "sysdep.h"
     23  1.1  christos #include "bfd.h"
     24  1.1  christos #include "libbfd.h"
     25  1.1  christos #ifdef HAVE_ZLIB_H
     26  1.1  christos #include <zlib.h>
     27  1.1  christos #endif
     28  1.1  christos 
     29  1.1  christos #ifdef HAVE_ZLIB_H
     30  1.1  christos static bfd_boolean
     31  1.1  christos decompress_contents (bfd_byte *compressed_buffer,
     32  1.1  christos 		     bfd_size_type compressed_size,
     33  1.1  christos 		     bfd_byte *uncompressed_buffer,
     34  1.1  christos 		     bfd_size_type uncompressed_size)
     35  1.1  christos {
     36  1.1  christos   z_stream strm;
     37  1.1  christos   int rc;
     38  1.1  christos 
     39  1.1  christos   /* It is possible the section consists of several compressed
     40  1.1  christos      buffers concatenated together, so we uncompress in a loop.  */
     41  1.1  christos   strm.zalloc = NULL;
     42  1.1  christos   strm.zfree = NULL;
     43  1.1  christos   strm.opaque = NULL;
     44  1.1  christos   strm.avail_in = compressed_size - 12;
     45  1.1  christos   strm.next_in = (Bytef*) compressed_buffer + 12;
     46  1.1  christos   strm.avail_out = uncompressed_size;
     47  1.1  christos 
     48  1.1  christos   BFD_ASSERT (Z_OK == 0);
     49  1.1  christos   rc = inflateInit (&strm);
     50  1.1  christos   while (strm.avail_in > 0 && strm.avail_out > 0)
     51  1.1  christos     {
     52  1.1  christos       if (rc != Z_OK)
     53  1.1  christos 	break;
     54  1.1  christos       strm.next_out = ((Bytef*) uncompressed_buffer
     55  1.1  christos                        + (uncompressed_size - strm.avail_out));
     56  1.1  christos       rc = inflate (&strm, Z_FINISH);
     57  1.1  christos       if (rc != Z_STREAM_END)
     58  1.1  christos 	break;
     59  1.1  christos       rc = inflateReset (&strm);
     60  1.1  christos     }
     61  1.1  christos   rc |= inflateEnd (&strm);
     62  1.1  christos   return rc == Z_OK && strm.avail_out == 0;
     63  1.1  christos }
     64  1.1  christos #endif
     65  1.1  christos 
     66  1.1  christos /*
     67  1.1  christos FUNCTION
     68  1.1  christos 	bfd_compress_section_contents
     69  1.1  christos 
     70  1.1  christos SYNOPSIS
     71  1.1  christos 	bfd_boolean bfd_compress_section_contents
     72  1.1  christos 	  (bfd *abfd, asection *section, bfd_byte *uncompressed_buffer,
     73  1.1  christos 	   bfd_size_type uncompressed_size);
     74  1.1  christos 
     75  1.1  christos DESCRIPTION
     76  1.1  christos 
     77  1.1  christos 	Compress data of the size specified in @var{uncompressed_size}
     78  1.1  christos 	and pointed to by @var{uncompressed_buffer} using zlib and store
     79  1.1  christos 	as the contents field.  This function assumes the contents
     80  1.1  christos 	field was allocated using bfd_malloc() or equivalent.  If zlib
     81  1.1  christos 	is not installed on this machine, the input is unmodified.
     82  1.1  christos 
     83  1.1  christos 	Return @code{TRUE} if the full section contents is compressed
     84  1.1  christos 	successfully.
     85  1.1  christos */
     86  1.1  christos 
     87  1.1  christos bfd_boolean
     88  1.1  christos bfd_compress_section_contents (bfd *abfd ATTRIBUTE_UNUSED,
     89  1.1  christos 			       sec_ptr sec ATTRIBUTE_UNUSED,
     90  1.1  christos 			       bfd_byte *uncompressed_buffer ATTRIBUTE_UNUSED,
     91  1.1  christos 			       bfd_size_type uncompressed_size ATTRIBUTE_UNUSED)
     92  1.1  christos {
     93  1.1  christos #ifndef HAVE_ZLIB_H
     94  1.1  christos   bfd_set_error (bfd_error_invalid_operation);
     95  1.1  christos   return FALSE;
     96  1.1  christos #else
     97  1.1  christos   uLong compressed_size;
     98  1.1  christos   bfd_byte *compressed_buffer;
     99  1.1  christos 
    100  1.1  christos   compressed_size = compressBound (uncompressed_size) + 12;
    101  1.1  christos   compressed_buffer = (bfd_byte *) bfd_malloc (compressed_size);
    102  1.1  christos 
    103  1.1  christos   if (compressed_buffer == NULL)
    104  1.1  christos     return FALSE;
    105  1.1  christos 
    106  1.1  christos   if (compress ((Bytef*) compressed_buffer + 12,
    107  1.1  christos 		&compressed_size,
    108  1.1  christos 		(const Bytef*) uncompressed_buffer,
    109  1.1  christos 		uncompressed_size) != Z_OK)
    110  1.1  christos     {
    111  1.1  christos       free (compressed_buffer);
    112  1.1  christos       bfd_set_error (bfd_error_bad_value);
    113  1.1  christos       return FALSE;
    114  1.1  christos     }
    115  1.1  christos 
    116  1.1  christos   /* Write the zlib header.  In this case, it should be "ZLIB" followed
    117  1.1  christos      by the uncompressed section size, 8 bytes in big-endian order.  */
    118  1.1  christos   memcpy (compressed_buffer, "ZLIB", 4);
    119  1.1  christos   compressed_buffer[11] = uncompressed_size; uncompressed_size >>= 8;
    120  1.1  christos   compressed_buffer[10] = uncompressed_size; uncompressed_size >>= 8;
    121  1.1  christos   compressed_buffer[9] = uncompressed_size; uncompressed_size >>= 8;
    122  1.1  christos   compressed_buffer[8] = uncompressed_size; uncompressed_size >>= 8;
    123  1.1  christos   compressed_buffer[7] = uncompressed_size; uncompressed_size >>= 8;
    124  1.1  christos   compressed_buffer[6] = uncompressed_size; uncompressed_size >>= 8;
    125  1.1  christos   compressed_buffer[5] = uncompressed_size; uncompressed_size >>= 8;
    126  1.1  christos   compressed_buffer[4] = uncompressed_size;
    127  1.1  christos   compressed_size += 12;
    128  1.1  christos 
    129  1.1  christos   /* Free the uncompressed contents if we compress in place.  */
    130  1.1  christos   if (uncompressed_buffer == sec->contents)
    131  1.1  christos     free (uncompressed_buffer);
    132  1.1  christos 
    133  1.1  christos   sec->contents = compressed_buffer;
    134  1.1  christos   sec->size = compressed_size;
    135  1.1  christos   sec->compress_status = COMPRESS_SECTION_DONE;
    136  1.1  christos 
    137  1.1  christos   return TRUE;
    138  1.1  christos #endif  /* HAVE_ZLIB_H */
    139  1.1  christos }
    140  1.1  christos 
    141  1.1  christos /*
    142  1.1  christos FUNCTION
    143  1.1  christos 	bfd_get_full_section_contents
    144  1.1  christos 
    145  1.1  christos SYNOPSIS
    146  1.1  christos 	bfd_boolean bfd_get_full_section_contents
    147  1.1  christos 	  (bfd *abfd, asection *section, bfd_byte **ptr);
    148  1.1  christos 
    149  1.1  christos DESCRIPTION
    150  1.1  christos 	Read all data from @var{section} in BFD @var{abfd}, decompress
    151  1.1  christos 	if needed, and store in @var{*ptr}.  If @var{*ptr} is NULL,
    152  1.1  christos 	return @var{*ptr} with memory malloc'd by this function.
    153  1.1  christos 
    154  1.1  christos 	Return @code{TRUE} if the full section contents is retrieved
    155  1.1  christos 	successfully.
    156  1.1  christos */
    157  1.1  christos 
    158  1.1  christos bfd_boolean
    159  1.1  christos bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
    160  1.1  christos {
    161  1.1  christos   bfd_size_type sz;
    162  1.1  christos   bfd_byte *p = *ptr;
    163  1.1  christos #ifdef HAVE_ZLIB_H
    164  1.1  christos   bfd_boolean ret;
    165  1.1  christos   bfd_size_type save_size;
    166  1.1  christos   bfd_size_type save_rawsize;
    167  1.1  christos   bfd_byte *compressed_buffer;
    168  1.1  christos #endif
    169  1.1  christos 
    170  1.1  christos   if (abfd->direction != write_direction && sec->rawsize != 0)
    171  1.1  christos     sz = sec->rawsize;
    172  1.1  christos   else
    173  1.1  christos     sz = sec->size;
    174  1.1  christos   if (sz == 0)
    175  1.1  christos     return TRUE;
    176  1.1  christos 
    177  1.1  christos   switch (sec->compress_status)
    178  1.1  christos     {
    179  1.1  christos     case COMPRESS_SECTION_NONE:
    180  1.1  christos       if (p == NULL)
    181  1.1  christos 	{
    182  1.1  christos 	  p = (bfd_byte *) bfd_malloc (sz);
    183  1.1  christos 	  if (p == NULL)
    184  1.1  christos 	    return FALSE;
    185  1.1  christos 	}
    186  1.1  christos       if (!bfd_get_section_contents (abfd, sec, p, 0, sz))
    187  1.1  christos 	{
    188  1.1  christos 	  if (*ptr != p)
    189  1.1  christos 	    free (p);
    190  1.1  christos 	  return FALSE;
    191  1.1  christos 	}
    192  1.1  christos       *ptr = p;
    193  1.1  christos       return TRUE;
    194  1.1  christos 
    195  1.1  christos     case DECOMPRESS_SECTION_SIZED:
    196  1.1  christos #ifndef HAVE_ZLIB_H
    197  1.1  christos       bfd_set_error (bfd_error_invalid_operation);
    198  1.1  christos       return FALSE;
    199  1.1  christos #else
    200  1.1  christos       /* Read in the full compressed section contents.  */
    201  1.1  christos       compressed_buffer = (bfd_byte *) bfd_malloc (sec->compressed_size);
    202  1.1  christos       if (compressed_buffer == NULL)
    203  1.1  christos 	return FALSE;
    204  1.1  christos       save_rawsize = sec->rawsize;
    205  1.1  christos       save_size = sec->size;
    206  1.1  christos       /* Clear rawsize, set size to compressed size and set compress_status
    207  1.1  christos 	 to COMPRESS_SECTION_NONE.  If the compressed size is bigger than
    208  1.1  christos 	 the uncompressed size, bfd_get_section_contents will fail.  */
    209  1.1  christos       sec->rawsize = 0;
    210  1.1  christos       sec->size = sec->compressed_size;
    211  1.1  christos       sec->compress_status = COMPRESS_SECTION_NONE;
    212  1.1  christos       ret = bfd_get_section_contents (abfd, sec, compressed_buffer,
    213  1.1  christos 				      0, sec->compressed_size);
    214  1.1  christos       /* Restore rawsize and size.  */
    215  1.1  christos       sec->rawsize = save_rawsize;
    216  1.1  christos       sec->size = save_size;
    217  1.1  christos       sec->compress_status = DECOMPRESS_SECTION_SIZED;
    218  1.1  christos       if (!ret)
    219  1.1  christos 	goto fail_compressed;
    220  1.1  christos 
    221  1.1  christos       if (p == NULL)
    222  1.1  christos 	p = (bfd_byte *) bfd_malloc (sz);
    223  1.1  christos       if (p == NULL)
    224  1.1  christos 	goto fail_compressed;
    225  1.1  christos 
    226  1.1  christos       if (!decompress_contents (compressed_buffer, sec->compressed_size, p, sz))
    227  1.1  christos 	{
    228  1.1  christos 	  bfd_set_error (bfd_error_bad_value);
    229  1.1  christos 	  if (p != *ptr)
    230  1.1  christos 	    free (p);
    231  1.1  christos 	fail_compressed:
    232  1.1  christos 	  free (compressed_buffer);
    233  1.1  christos 	  return FALSE;
    234  1.1  christos 	}
    235  1.1  christos 
    236  1.1  christos       free (compressed_buffer);
    237  1.1  christos       *ptr = p;
    238  1.1  christos       return TRUE;
    239  1.1  christos #endif
    240  1.1  christos 
    241  1.1  christos     case COMPRESS_SECTION_DONE:
    242  1.1  christos       if (p == NULL)
    243  1.1  christos 	{
    244  1.1  christos 	  p = (bfd_byte *) bfd_malloc (sz);
    245  1.1  christos 	  if (p == NULL)
    246  1.1  christos 	    return FALSE;
    247  1.1  christos 	  *ptr = p;
    248  1.1  christos 	}
    249  1.1  christos       memcpy (p, sec->contents, sz);
    250  1.1  christos       return TRUE;
    251  1.1  christos 
    252  1.1  christos     default:
    253  1.1  christos       abort ();
    254  1.1  christos     }
    255  1.1  christos }
    256  1.1  christos 
    257  1.1  christos /*
    258  1.1  christos FUNCTION
    259  1.1  christos 	bfd_cache_section_contents
    260  1.1  christos 
    261  1.1  christos SYNOPSIS
    262  1.1  christos 	void bfd_cache_section_contents
    263  1.1  christos 	  (asection *sec, void *contents);
    264  1.1  christos 
    265  1.1  christos DESCRIPTION
    266  1.1  christos 	Stash @var(contents) so any following reads of @var(sec) do
    267  1.1  christos 	not need to decompress again.
    268  1.1  christos */
    269  1.1  christos 
    270  1.1  christos void
    271  1.1  christos bfd_cache_section_contents (asection *sec, void *contents)
    272  1.1  christos {
    273  1.1  christos   if (sec->compress_status == DECOMPRESS_SECTION_SIZED)
    274  1.1  christos     sec->compress_status = COMPRESS_SECTION_DONE;
    275  1.1  christos   sec->contents = contents;
    276  1.1  christos   sec->flags |= SEC_IN_MEMORY;
    277  1.1  christos }
    278  1.1  christos 
    279  1.1  christos 
    280  1.1  christos /*
    281  1.1  christos FUNCTION
    282  1.1  christos 	bfd_is_section_compressed
    283  1.1  christos 
    284  1.1  christos SYNOPSIS
    285  1.1  christos 	bfd_boolean bfd_is_section_compressed
    286  1.1  christos 	  (bfd *abfd, asection *section);
    287  1.1  christos 
    288  1.1  christos DESCRIPTION
    289  1.1  christos 	Return @code{TRUE} if @var{section} is compressed.
    290  1.1  christos */
    291  1.1  christos 
    292  1.1  christos bfd_boolean
    293  1.1  christos bfd_is_section_compressed (bfd *abfd, sec_ptr sec)
    294  1.1  christos {
    295  1.1  christos   bfd_byte compressed_buffer [12];
    296  1.1  christos   unsigned int saved = sec->compress_status;
    297  1.1  christos   bfd_boolean compressed;
    298  1.1  christos 
    299  1.1  christos   /* Don't decompress the section.  */
    300  1.1  christos   sec->compress_status = COMPRESS_SECTION_NONE;
    301  1.1  christos 
    302  1.1  christos   /* Read the zlib header.  In this case, it should be "ZLIB" followed
    303  1.1  christos      by the uncompressed section size, 8 bytes in big-endian order.  */
    304  1.1  christos   compressed = (bfd_get_section_contents (abfd, sec, compressed_buffer, 0, 12)
    305  1.1  christos 		&& CONST_STRNEQ ((char*) compressed_buffer, "ZLIB"));
    306  1.1  christos 
    307  1.1  christos   /* Restore compress_status.  */
    308  1.1  christos   sec->compress_status = saved;
    309  1.1  christos   return compressed;
    310  1.1  christos }
    311  1.1  christos 
    312  1.1  christos /*
    313  1.1  christos FUNCTION
    314  1.1  christos 	bfd_init_section_decompress_status
    315  1.1  christos 
    316  1.1  christos SYNOPSIS
    317  1.1  christos 	bfd_boolean bfd_init_section_decompress_status
    318  1.1  christos 	  (bfd *abfd, asection *section);
    319  1.1  christos 
    320  1.1  christos DESCRIPTION
    321  1.1  christos 	Record compressed section size, update section size with
    322  1.1  christos 	decompressed size and set compress_status to
    323  1.1  christos 	DECOMPRESS_SECTION_SIZED.
    324  1.1  christos 
    325  1.1  christos 	Return @code{FALSE} if the section is not a valid compressed
    326  1.1  christos 	section or zlib is not installed on this machine.  Otherwise,
    327  1.1  christos 	return @code{TRUE}.
    328  1.1  christos */
    329  1.1  christos 
    330  1.1  christos bfd_boolean
    331  1.1  christos bfd_init_section_decompress_status (bfd *abfd ATTRIBUTE_UNUSED,
    332  1.1  christos 				    sec_ptr sec ATTRIBUTE_UNUSED)
    333  1.1  christos {
    334  1.1  christos #ifndef HAVE_ZLIB_H
    335  1.1  christos   bfd_set_error (bfd_error_invalid_operation);
    336  1.1  christos   return FALSE;
    337  1.1  christos #else
    338  1.1  christos   bfd_byte compressed_buffer [12];
    339  1.1  christos   bfd_size_type uncompressed_size;
    340  1.1  christos 
    341  1.1  christos   if (sec->rawsize != 0
    342  1.1  christos       || sec->contents != NULL
    343  1.1  christos       || sec->compress_status != COMPRESS_SECTION_NONE
    344  1.1  christos       || !bfd_get_section_contents (abfd, sec, compressed_buffer, 0, 12))
    345  1.1  christos     {
    346  1.1  christos       bfd_set_error (bfd_error_invalid_operation);
    347  1.1  christos       return FALSE;
    348  1.1  christos     }
    349  1.1  christos 
    350  1.1  christos   /* Read the zlib header.  In this case, it should be "ZLIB" followed
    351  1.1  christos      by the uncompressed section size, 8 bytes in big-endian order.  */
    352  1.1  christos   if (! CONST_STRNEQ ((char*) compressed_buffer, "ZLIB"))
    353  1.1  christos     {
    354  1.1  christos       bfd_set_error (bfd_error_wrong_format);
    355  1.1  christos       return FALSE;
    356  1.1  christos     }
    357  1.1  christos 
    358  1.1  christos   uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8;
    359  1.1  christos   uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8;
    360  1.1  christos   uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8;
    361  1.1  christos   uncompressed_size += compressed_buffer[7]; uncompressed_size <<= 8;
    362  1.1  christos   uncompressed_size += compressed_buffer[8]; uncompressed_size <<= 8;
    363  1.1  christos   uncompressed_size += compressed_buffer[9]; uncompressed_size <<= 8;
    364  1.1  christos   uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8;
    365  1.1  christos   uncompressed_size += compressed_buffer[11];
    366  1.1  christos 
    367  1.1  christos   sec->compressed_size = sec->size;
    368  1.1  christos   sec->size = uncompressed_size;
    369  1.1  christos   sec->compress_status = DECOMPRESS_SECTION_SIZED;
    370  1.1  christos 
    371  1.1  christos   return TRUE;
    372  1.1  christos #endif
    373  1.1  christos }
    374  1.1  christos 
    375  1.1  christos /*
    376  1.1  christos FUNCTION
    377  1.1  christos 	bfd_init_section_compress_status
    378  1.1  christos 
    379  1.1  christos SYNOPSIS
    380  1.1  christos 	bfd_boolean bfd_init_section_compress_status
    381  1.1  christos 	  (bfd *abfd, asection *section);
    382  1.1  christos 
    383  1.1  christos DESCRIPTION
    384  1.1  christos 	If open for read, compress section, update section size with
    385  1.1  christos 	compressed size and set compress_status to COMPRESS_SECTION_DONE.
    386  1.1  christos 
    387  1.1  christos 	Return @code{FALSE} if the section is not a valid compressed
    388  1.1  christos 	section or zlib is not installed on this machine.  Otherwise,
    389  1.1  christos 	return @code{TRUE}.
    390  1.1  christos */
    391  1.1  christos 
    392  1.1  christos bfd_boolean
    393  1.1  christos bfd_init_section_compress_status (bfd *abfd ATTRIBUTE_UNUSED,
    394  1.1  christos 				  sec_ptr sec ATTRIBUTE_UNUSED)
    395  1.1  christos {
    396  1.1  christos #ifndef HAVE_ZLIB_H
    397  1.1  christos   bfd_set_error (bfd_error_invalid_operation);
    398  1.1  christos   return FALSE;
    399  1.1  christos #else
    400  1.1  christos   bfd_size_type uncompressed_size;
    401  1.1  christos   bfd_byte *uncompressed_buffer;
    402  1.1  christos   bfd_boolean ret;
    403  1.1  christos 
    404  1.1  christos   /* Error if not opened for read.  */
    405  1.1  christos   if (abfd->direction != read_direction
    406  1.1  christos       || sec->size == 0
    407  1.1  christos       || sec->rawsize != 0
    408  1.1  christos       || sec->contents != NULL
    409  1.1  christos       || sec->compress_status != COMPRESS_SECTION_NONE)
    410  1.1  christos     {
    411  1.1  christos       bfd_set_error (bfd_error_invalid_operation);
    412  1.1  christos       return FALSE;
    413  1.1  christos     }
    414  1.1  christos 
    415  1.1  christos   /* Read in the full section contents and compress it.  */
    416  1.1  christos   uncompressed_size = sec->size;
    417  1.1  christos   uncompressed_buffer = (bfd_byte *) bfd_malloc (uncompressed_size);
    418  1.1  christos   if (!bfd_get_section_contents (abfd, sec, uncompressed_buffer,
    419  1.1  christos 				 0, uncompressed_size))
    420  1.1  christos     ret = FALSE;
    421  1.1  christos   else
    422  1.1  christos     ret = bfd_compress_section_contents (abfd, sec,
    423  1.1  christos 					 uncompressed_buffer,
    424  1.1  christos 					 uncompressed_size);
    425  1.1  christos 
    426  1.1  christos   free (uncompressed_buffer);
    427  1.1  christos   return ret;
    428  1.1  christos #endif
    429  1.1  christos }
    430