Ejemplo n.º 1
0
bfd_boolean
bfd_is_section_compressed (bfd *abfd, sec_ptr sec)
{
  int compression_header_size;
  return (bfd_is_section_compressed_with_header (abfd, sec,
						 &compression_header_size)
	  && compression_header_size >= 0);
}
Ejemplo n.º 2
0
static bfd_size_type
bfd_compress_section_contents (bfd *abfd, sec_ptr sec,
			       bfd_byte *uncompressed_buffer,
			       bfd_size_type uncompressed_size)
{
  uLong compressed_size;
  bfd_byte *buffer;
  bfd_size_type buffer_size;
  bfd_boolean decompress;
#if defined(__GNUC__) && GCC_VERSION < 4007
  /* Work around a GCC uninitialized warning bug fixed in GCC 4.7.  */
  int zlib_size = 0;
#else
  int zlib_size;
#endif
  int orig_compression_header_size;
  int compression_header_size
    = bfd_get_compression_header_size (abfd, NULL);
  bfd_boolean compressed
    = bfd_is_section_compressed_with_header (abfd, sec,
					     &orig_compression_header_size);

  if (compressed)
    {
      /* We shouldn't decompress unsupported compressed section.  */
      if (orig_compression_header_size < 0)
	abort ();

      /* Different compression schemes.  Just move the compressed section
	 contents to the right position. */
      if (orig_compression_header_size == 0)
	{
	  /* Convert it from .zdebug* section.  Get the uncompressed
	     size first.  */
	  zlib_size = uncompressed_size;
	  compressed_size = zlib_size + compression_header_size;
	  uncompressed_size = bfd_getb64 (uncompressed_buffer + 4);
	}
      else
	{
	  /* Convert it to .zdebug* section. */
	  zlib_size = uncompressed_size - orig_compression_header_size;
	  compressed_size = zlib_size;
	}
    }
  else
    compressed_size = compressBound (uncompressed_size) + 12;

  /* When converting from .zdebug* section, uncompress if it leads to
     smaller size.  */
  if (compressed
      && orig_compression_header_size == 0
      && compressed_size > uncompressed_size)
    {
      decompress = TRUE;
      buffer_size = uncompressed_size;
    }
  else
    {
      decompress = FALSE;
      buffer_size = compressed_size + compression_header_size;
    }
  buffer = (bfd_byte *) bfd_alloc (abfd, buffer_size);
  if (buffer == NULL)
    return 0;

  if (compressed)
    {
      sec->size = uncompressed_size;
      if (decompress)
	{
	  if (!decompress_contents (uncompressed_buffer, zlib_size,
				    buffer, uncompressed_size))
	    {
	      bfd_set_error (bfd_error_bad_value);
	      bfd_release (abfd, buffer);
	      return 0;
	    }
	  free (uncompressed_buffer);
	  sec->contents = buffer;
	  sec->compress_status = COMPRESS_SECTION_DONE;
	  return uncompressed_size;
	}
      else
	{
	  bfd_update_compression_header (abfd, buffer, sec);
	  memmove (buffer + compression_header_size,
		   uncompressed_buffer + orig_compression_header_size,
		   zlib_size);
	}
    }
  else
    {
      bfd_size_type size = uncompressed_size;
      int header_size = 12 + compression_header_size;
      if (compress ((Bytef*) buffer + header_size,
		    &compressed_size,
		    (const Bytef*) uncompressed_buffer,
		    uncompressed_size) != Z_OK)
	{
	  bfd_release (abfd, buffer);
	  bfd_set_error (bfd_error_bad_value);
	  return 0;
	}

      compressed_size += header_size;
      /* PR binutils/18087: If compression didn't make the section smaller,
	 just keep it uncompressed.  */
      if (compressed_size < uncompressed_size)
	{
	  bfd_update_compression_header (abfd, buffer, sec);

	  /* Write the zlib header.  In this case, it should be "ZLIB"
	     followed by the uncompressed section size, 8 bytes in
	     big-endian order.  */
	  memcpy (buffer + compression_header_size, "ZLIB", 4);
	  bfd_putb64 (size, buffer + compression_header_size + 4);
	}
      else
	{
	  /* NOTE: There is a small memory leak here since
	     uncompressed_buffer is malloced and won't be freed.  */
	  bfd_release (abfd, buffer);
	  sec->contents = uncompressed_buffer;
	  sec->compress_status = COMPRESS_SECTION_NONE;
	  return uncompressed_size;
	}
    }

  free (uncompressed_buffer);
  sec->contents = buffer;
  sec->size = compressed_size;
  sec->compress_status = COMPRESS_SECTION_DONE;

  return uncompressed_size;
}
Ejemplo n.º 3
0
static bfd_size_type
bfd_compress_section_contents (bfd *abfd, sec_ptr sec,
                               bfd_byte *uncompressed_buffer,
                               bfd_size_type uncompressed_size)
{
    uLong compressed_size;
    bfd_byte *buffer;
    bfd_size_type buffer_size;
    bfd_boolean decompress;
    int zlib_size = 0;
    int orig_compression_header_size;
    bfd_size_type orig_uncompressed_size;
    int header_size = bfd_get_compression_header_size (abfd, NULL);
    bfd_boolean compressed
        = bfd_is_section_compressed_with_header (abfd, sec,
                &orig_compression_header_size,
                &orig_uncompressed_size);

    /* Either ELF compression header or the 12-byte, "ZLIB" + 8-byte size,
       overhead in .zdebug* section.  */
    if (!header_size)
        header_size = 12;

    if (compressed)
    {
        /* We shouldn't decompress unsupported compressed section.  */
        if (orig_compression_header_size < 0)
            abort ();

        /* Different compression schemes.  Just move the compressed section
        contents to the right position. */
        if (orig_compression_header_size == 0)
        {
            /* Convert it from .zdebug* section.  Get the uncompressed
               size first.  We need to substract the 12-byte overhead in
               .zdebug* section.  Set orig_compression_header_size to
               the 12-bye overhead.  */
            orig_compression_header_size = 12;
            zlib_size = uncompressed_size - 12;
        }
        else
        {
            /* Convert it to .zdebug* section.  */
            zlib_size = uncompressed_size - orig_compression_header_size;
        }

        /* Add the header size.  */
        compressed_size = zlib_size + header_size;
    }
    else
        compressed_size = compressBound (uncompressed_size) + header_size;

    /* Uncompress if it leads to smaller size.  */
    if (compressed && compressed_size > orig_uncompressed_size)
    {
        decompress = TRUE;
        buffer_size = orig_uncompressed_size;
    }
    else
    {
        decompress = FALSE;
        buffer_size = compressed_size;
    }
    buffer = (bfd_byte *) bfd_alloc (abfd, buffer_size);
    if (buffer == NULL)
        return 0;

    if (compressed)
    {
        sec->size = orig_uncompressed_size;
        if (decompress)
        {
            if (!decompress_contents (uncompressed_buffer
                                      + orig_compression_header_size,
                                      zlib_size, buffer, buffer_size))
            {
                bfd_set_error (bfd_error_bad_value);
                bfd_release (abfd, buffer);
                return 0;
            }
            free (uncompressed_buffer);
            sec->contents = buffer;
            sec->compress_status = COMPRESS_SECTION_DONE;
            return orig_uncompressed_size;
        }
        else
        {
            bfd_update_compression_header (abfd, buffer, sec);
            memmove (buffer + header_size,
                     uncompressed_buffer + orig_compression_header_size,
                     zlib_size);
        }
    }
    else
    {
        if (compress ((Bytef*) buffer + header_size,
                      &compressed_size,
                      (const Bytef*) uncompressed_buffer,
                      uncompressed_size) != Z_OK)
        {
            bfd_release (abfd, buffer);
            bfd_set_error (bfd_error_bad_value);
            return 0;
        }

        compressed_size += header_size;
        /* PR binutils/18087: If compression didn't make the section smaller,
        just keep it uncompressed.  */
        if (compressed_size < uncompressed_size)
            bfd_update_compression_header (abfd, buffer, sec);
        else
        {
            /* NOTE: There is a small memory leak here since
               uncompressed_buffer is malloced and won't be freed.  */
            bfd_release (abfd, buffer);
            sec->contents = uncompressed_buffer;
            sec->compress_status = COMPRESS_SECTION_NONE;
            return uncompressed_size;
        }
    }

    free (uncompressed_buffer);
    sec->contents = buffer;
    sec->size = compressed_size;
    sec->compress_status = COMPRESS_SECTION_DONE;

    return uncompressed_size;
}