/* Compressed section support (intended for debug sections).
- Copyright 2008, 2010, 2011, 2012
- Free Software Foundation, Inc.
+ Copyright (C) 2008-2015 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
+#include "safe-ctype.h"
#ifdef HAVE_ZLIB_H
static bfd_boolean
strm.next_in = (Bytef*) compressed_buffer + 12;
strm.avail_out = uncompressed_size;
+ BFD_ASSERT (Z_OK == 0);
rc = inflateInit (&strm);
while (strm.avail_in > 0 && strm.avail_out > 0)
{
if (rc != Z_OK)
- return FALSE;
+ break;
strm.next_out = ((Bytef*) uncompressed_buffer
+ (uncompressed_size - strm.avail_out));
rc = inflate (&strm, Z_FINISH);
if (rc != Z_STREAM_END)
- return FALSE;
+ break;
rc = inflateReset (&strm);
}
- rc = inflateEnd (&strm);
+ rc |= inflateEnd (&strm);
return rc == Z_OK && strm.avail_out == 0;
}
-#endif
-
-/*
-FUNCTION
- bfd_compress_section_contents
-
-SYNOPSIS
- bfd_boolean bfd_compress_section_contents
- (bfd *abfd, asection *section, bfd_byte *uncompressed_buffer,
- bfd_size_type uncompressed_size);
-DESCRIPTION
-
- Compress data of the size specified in @var{uncompressed_size}
- and pointed to by @var{uncompressed_buffer} using zlib and store
- as the contents field. This function assumes the contents
- field was allocated using bfd_malloc() or equivalent. If zlib
- is not installed on this machine, the input is unmodified.
+/* Compress data of the size specified in @var{uncompressed_size}
+ and pointed to by @var{uncompressed_buffer} using zlib and store
+ as the contents field. This function assumes the contents
+ field was allocated using bfd_malloc() or equivalent. If zlib
+ is not installed on this machine, the input is unmodified.
- Return @code{TRUE} if the full section contents is compressed
- successfully.
-*/
+ Return @code{TRUE} if the full section contents is compressed
+ successfully. */
-bfd_boolean
+static bfd_boolean
bfd_compress_section_contents (bfd *abfd ATTRIBUTE_UNUSED,
sec_ptr sec ATTRIBUTE_UNUSED,
bfd_byte *uncompressed_buffer ATTRIBUTE_UNUSED,
bfd_size_type uncompressed_size ATTRIBUTE_UNUSED)
{
-#ifndef HAVE_ZLIB_H
- bfd_set_error (bfd_error_invalid_operation);
- return FALSE;
-#else
uLong compressed_size;
bfd_byte *compressed_buffer;
sec->compress_status = COMPRESS_SECTION_DONE;
return TRUE;
-#endif /* HAVE_ZLIB_H */
}
+#endif /* HAVE_ZLIB_H */
/*
FUNCTION
return @var{*ptr} with memory malloc'd by this function.
Return @code{TRUE} if the full section contents is retrieved
- successfully.
+ successfully. If the section has no contents then this function
+ returns @code{TRUE} but @var{*ptr} is set to NULL.
*/
bfd_boolean
else
sz = sec->size;
if (sz == 0)
- return TRUE;
+ {
+ *ptr = NULL;
+ return TRUE;
+ }
switch (sec->compress_status)
{
if (p == NULL)
return FALSE;
}
+
if (!bfd_get_section_contents (abfd, sec, p, 0, sz))
{
if (*ptr != p)
#endif
case COMPRESS_SECTION_DONE:
+ if (sec->contents == NULL)
+ return FALSE;
if (p == NULL)
{
p = (bfd_byte *) bfd_malloc (sz);
return FALSE;
*ptr = p;
}
- memcpy (p, sec->contents, sz);
+ /* PR 17512; file: 5bc29788. */
+ if (p != sec->contents)
+ memcpy (p, sec->contents, sz);
return TRUE;
default:
compressed = (bfd_get_section_contents (abfd, sec, compressed_buffer, 0, 12)
&& CONST_STRNEQ ((char*) compressed_buffer, "ZLIB"));
+ /* Check for the pathalogical case of a debug string section that
+ contains the string ZLIB.... as the first entry. We assume that
+ no uncompressed .debug_str section would ever be big enough to
+ have the first byte of its (big-endian) size be non-zero. */
+ if (compressed
+ && strcmp (sec->name, ".debug_str") == 0
+ && ISPRINT (compressed_buffer[4]))
+ compressed = FALSE;
+
/* Restore compress_status. */
sec->compress_status = saved;
return compressed;
uncompressed_buffer,
uncompressed_size);
- free (uncompressed_buffer);
+ /* PR binutils/18087: If compression didn't make
+ the section smaller, just keep it uncompressed. */
+ if (ret && uncompressed_size < sec->size)
+ {
+ free (sec->contents);
+ sec->contents = uncompressed_buffer;
+ sec->size = uncompressed_size;
+ sec->compress_status = COMPRESS_SECTION_NONE;
+ }
+ else
+ free (uncompressed_buffer);
+
return ret;
#endif
}