- /* Write the zlib header. In this case, it should be "ZLIB" followed
- by the uncompressed section size, 8 bytes in big-endian order. */
- memcpy (compressed_buffer, "ZLIB", 4);
- compressed_buffer[11] = uncompressed_size; uncompressed_size >>= 8;
- compressed_buffer[10] = uncompressed_size; uncompressed_size >>= 8;
- compressed_buffer[9] = uncompressed_size; uncompressed_size >>= 8;
- compressed_buffer[8] = uncompressed_size; uncompressed_size >>= 8;
- compressed_buffer[7] = uncompressed_size; uncompressed_size >>= 8;
- compressed_buffer[6] = uncompressed_size; uncompressed_size >>= 8;
- compressed_buffer[5] = uncompressed_size; uncompressed_size >>= 8;
- compressed_buffer[4] = uncompressed_size;
- compressed_size += 12;
-
- /* Free the uncompressed contents if we compress in place. */
- if (uncompressed_buffer == sec->contents)
- free (uncompressed_buffer);
-
- sec->contents = compressed_buffer;
+ 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);
+ bfd_set_section_alignment (sec, orig_uncompressed_alignment_pow);
+
+ 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;