Exemple #1
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;
}
Exemple #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;
    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;
}
Exemple #3
0
bfd_boolean
bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
{
  bfd_size_type sz;
  bfd_byte *p = *ptr;
  bfd_boolean ret;
  bfd_size_type save_size;
  bfd_size_type save_rawsize;
  bfd_byte *compressed_buffer;
  unsigned int compression_header_size;

  if (abfd->direction != write_direction && sec->rawsize != 0)
    sz = sec->rawsize;
  else
    sz = sec->size;
  if (sz == 0)
    {
      *ptr = NULL;
      return TRUE;
    }

  switch (sec->compress_status)
    {
    case COMPRESS_SECTION_NONE:
      if (p == NULL)
	{
	  p = (bfd_byte *) bfd_malloc (sz);
	  if (p == NULL)
	    return FALSE;
	}

      if (!bfd_get_section_contents (abfd, sec, p, 0, sz))
	{
	  if (*ptr != p)
	    free (p);
	  return FALSE;
	}
      *ptr = p;
      return TRUE;

    case DECOMPRESS_SECTION_SIZED:
      /* Read in the full compressed section contents.  */
      compressed_buffer = (bfd_byte *) bfd_malloc (sec->compressed_size);
      if (compressed_buffer == NULL)
	return FALSE;
      save_rawsize = sec->rawsize;
      save_size = sec->size;
      /* Clear rawsize, set size to compressed size and set compress_status
	 to COMPRESS_SECTION_NONE.  If the compressed size is bigger than
	 the uncompressed size, bfd_get_section_contents will fail.  */
      sec->rawsize = 0;
      sec->size = sec->compressed_size;
      sec->compress_status = COMPRESS_SECTION_NONE;
      ret = bfd_get_section_contents (abfd, sec, compressed_buffer,
				      0, sec->compressed_size);
      /* Restore rawsize and size.  */
      sec->rawsize = save_rawsize;
      sec->size = save_size;
      sec->compress_status = DECOMPRESS_SECTION_SIZED;
      if (!ret)
	goto fail_compressed;

      if (p == NULL)
	p = (bfd_byte *) bfd_malloc (sz);
      if (p == NULL)
	goto fail_compressed;

      compression_header_size = bfd_get_compression_header_size (abfd, sec);
      if (!decompress_contents (compressed_buffer + compression_header_size,
				sec->compressed_size, p, sz))
	{
	  bfd_set_error (bfd_error_bad_value);
	  if (p != *ptr)
	    free (p);
	fail_compressed:
	  free (compressed_buffer);
	  return FALSE;
	}

      free (compressed_buffer);
      *ptr = p;
      return TRUE;

    case COMPRESS_SECTION_DONE:
      if (sec->contents == NULL)
	return FALSE;
      if (p == NULL)
	{
	  p = (bfd_byte *) bfd_malloc (sz);
	  if (p == NULL)
	    return FALSE;
	  *ptr = p;
	}
      /* PR 17512; file: 5bc29788.  */
      if (p != sec->contents)
	memcpy (p, sec->contents, sz);
      return TRUE;

    default:
      abort ();
    }
}
Exemple #4
0
bfd_boolean
bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
{
    bfd_size_type sz;
    bfd_byte *p = *ptr;
    bfd_boolean ret;
    bfd_size_type save_size;
    bfd_size_type save_rawsize;
    bfd_byte *compressed_buffer;
    unsigned int compression_header_size;

    if (abfd->direction != write_direction && sec->rawsize != 0)
        sz = sec->rawsize;
    else
        sz = sec->size;
    if (sz == 0)
    {
        *ptr = NULL;
        return TRUE;
    }

    switch (sec->compress_status)
    {
    case COMPRESS_SECTION_NONE:
        if (p == NULL)
        {
            p = (bfd_byte *) bfd_malloc (sz);
            if (p == NULL)
            {
                /* PR 20801: Provide a more helpful error message.  */
                if (bfd_get_error () == bfd_error_no_memory)
                    _bfd_error_handler
                    /* xgettext:c-format */
                    (_("error: %B(%A) is too large (%#lx bytes)"),
                     abfd, sec, (long) sz);
                return FALSE;
            }
        }

        if (!bfd_get_section_contents (abfd, sec, p, 0, sz))
        {
            if (*ptr != p)
                free (p);
            return FALSE;
        }
        *ptr = p;
        return TRUE;

    case DECOMPRESS_SECTION_SIZED:
        /* Read in the full compressed section contents.  */
        compressed_buffer = (bfd_byte *) bfd_malloc (sec->compressed_size);
        if (compressed_buffer == NULL)
            return FALSE;
        save_rawsize = sec->rawsize;
        save_size = sec->size;
        /* Clear rawsize, set size to compressed size and set compress_status
        to COMPRESS_SECTION_NONE.  If the compressed size is bigger than
         the uncompressed size, bfd_get_section_contents will fail.  */
        sec->rawsize = 0;
        sec->size = sec->compressed_size;
        sec->compress_status = COMPRESS_SECTION_NONE;
        ret = bfd_get_section_contents (abfd, sec, compressed_buffer,
                                        0, sec->compressed_size);
        /* Restore rawsize and size.  */
        sec->rawsize = save_rawsize;
        sec->size = save_size;
        sec->compress_status = DECOMPRESS_SECTION_SIZED;
        if (!ret)
            goto fail_compressed;

        if (p == NULL)
            p = (bfd_byte *) bfd_malloc (sz);
        if (p == NULL)
            goto fail_compressed;

        compression_header_size = bfd_get_compression_header_size (abfd, sec);
        if (compression_header_size == 0)
            /* Set header size to the zlib header size if it is a
               SHF_COMPRESSED section.  */
            compression_header_size = 12;
        if (!decompress_contents (compressed_buffer + compression_header_size,
                                  sec->compressed_size, p, sz))
        {
            bfd_set_error (bfd_error_bad_value);
            if (p != *ptr)
                free (p);
fail_compressed:
            free (compressed_buffer);
            return FALSE;
        }

        free (compressed_buffer);
        *ptr = p;
        return TRUE;

    case COMPRESS_SECTION_DONE:
        if (sec->contents == NULL)
            return FALSE;
        if (p == NULL)
        {
            p = (bfd_byte *) bfd_malloc (sz);
            if (p == NULL)
                return FALSE;
            *ptr = p;
        }
        /* PR 17512; file: 5bc29788.  */
        if (p != sec->contents)
            memcpy (p, sec->contents, sz);
        return TRUE;

    default:
        abort ();
    }
}