summaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog64
-rw-r--r--bfd/archive.c10
-rw-r--r--bfd/bfd-in2.h46
-rw-r--r--bfd/bfd.c12
-rw-r--r--bfd/compress.c396
-rw-r--r--bfd/dwarf2.c174
-rw-r--r--bfd/ecoff.c10
-rw-r--r--bfd/elf.c46
-rw-r--r--bfd/elflink.c4
-rw-r--r--bfd/elfxx-target.h4
-rw-r--r--bfd/libbfd-in.h10
-rw-r--r--bfd/libbfd.c9
-rw-r--r--bfd/libbfd.h10
-rw-r--r--bfd/merge.c5
-rw-r--r--bfd/reloc.c4
-rw-r--r--bfd/section.c35
-rw-r--r--bfd/simple.c14
17 files changed, 651 insertions, 202 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index a45bac7cf7..baec58b485 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,67 @@
+2010-10-29 H.J. Lu <hongjiu.lu@intel.com>
+ Cary Coutant <ccoutant@google.com>
+
+ * archive.c (bfd_openr_next_archived_file): Copy BFD_COMPRESS
+ and BFD_DECOMPRESS.
+
+ * bfd.c (BFD_COMPRESS): New.
+ (BFD_DECOMPRESS): Likewise.
+ (BFD_FLAGS_SAVED): Likewise.
+ (bfd_preserve_save): Replace BFD_IN_MEMORY with BFD_FLAGS_SAVED.
+
+ * compress.c (bfd_uncompress_section_contents): Removed.
+ (get_uncompressed_size): New.
+ (decompress_contents): Likewise.
+ (bfd_compress_section_contents): Likewise.
+ (bfd_get_full_section_contents): Likewise.
+ (bfd_is_section_compressed): Likewise.
+ (bfd_init_section_decompress_status): Likewise.
+ (bfd_init_section_compress_status): Likewise.
+
+ * dwarf2.c (dwarf_debug_sections): New.
+ (dwarf_debug_section_enum): Likewise.
+ (read_section): Remove section_name and compressed_section_name.
+ Add dwarf_debug_section_enum. Try compressed debug section.
+ (read_indirect_string): Updated.
+ (read_abbrevs): Likewise.
+ (decode_line_info): Likewise.
+ (read_debug_ranges): Likewise.
+ (find_line): Updated.
+
+ * ecoff.c (bfd_debug_section): Add compress_status and
+ compressed_size.
+
+ * elf.c (_bfd_elf_make_section_from_shdr): Call
+ bfd_is_section_compressed to check if a DWARF debug section is
+ compressed. Call bfd_init_section_compress_status or
+ bfd_init_section_decompress_status if needed.
+
+ * elflink.c (elf_link_input_bfd): Replace bfd_get_section_contents
+ with bfd_get_full_section_contents.
+ * merge.c (_bfd_add_merge_section): Likewise.
+ * reloc.c (bfd_generic_get_relocated_section_contents): Likewise.
+ * simple.c (bfd_simple_get_relocated_section_contents): Likewise.
+
+ * elfxx-target.h (TARGET_BIG_SYM): Allow BFD_COMPRESS and
+ BFD_DECOMPRESS.
+ (TARGET_LITTLE_SYM): Likewise.
+
+ * libbfd-in.h (dwarf_debug_section): New.
+ (dwarf_debug_sections): Likewise.
+
+ * libbfd.c (_bfd_generic_get_section_contents): Issue an error
+ when getting contents on compressed/decompressed section.
+
+ * section.c (COMPRESS_SECTION_NONE): New.
+ (COMPRESS_SECTION_DONE): Likewise.
+ (DECOMPRESS_SECTION_SIZED): Likewise.
+ (BFD_FAKE_SECTION): Add compress_status and compressed_size.
+ (bfd_malloc_and_get_section): Replace bfd_get_section_contents
+ with bfd_get_full_section_contents.
+
+ * bfd-in2.h: Regenerated.
+ * libbfd.h: Likewise.
+
2010-10-29 Bernd Schmidt <bernds@codesourcery.com>
Joseph Myers <joseph@codesourcery.com>
diff --git a/bfd/archive.c b/bfd/archive.c
index 1b3f69215e..ed4014151d 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -697,6 +697,8 @@ DESCRIPTION
bfd *
bfd_openr_next_archived_file (bfd *archive, bfd *last_file)
{
+ bfd *abfd;
+
if ((bfd_get_format (archive) != bfd_archive)
|| (archive->direction == write_direction))
{
@@ -704,8 +706,14 @@ bfd_openr_next_archived_file (bfd *archive, bfd *last_file)
return NULL;
}
- return BFD_SEND (archive,
+ abfd = BFD_SEND (archive,
openr_next_archived_file, (archive, last_file));
+
+ /* Copy BFD_COMPRESS and BFD_DECOMPRESS flags. */
+ if (abfd)
+ abfd->flags |= archive->flags & (BFD_COMPRESS | BFD_DECOMPRESS);
+
+ return abfd;
}
bfd *
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index cbbb0f64b0..aec5c24d4e 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1353,6 +1353,12 @@ typedef struct bfd_section
/* Mark flag used by some linker backends for garbage collection. */
unsigned int gc_mark : 1;
+ /* Section compression status. */
+ unsigned int compress_status : 2;
+#define COMPRESS_SECTION_NONE 0
+#define COMPRESS_SECTION_DONE 1
+#define DECOMPRESS_SECTION_SIZED 2
+
/* The following flags are used by the ELF linker. */
/* Mark sections which have been allocated to segments. */
@@ -1409,6 +1415,9 @@ typedef struct bfd_section
section size calculated on a previous linker relaxation pass. */
bfd_size_type rawsize;
+ /* The compressed size of the section in octets. */
+ bfd_size_type compressed_size;
+
/* Relaxation table. */
struct relax_table *relax;
@@ -1642,17 +1651,17 @@ extern asection bfd_ind_section;
/* name, id, index, next, prev, flags, user_set_vma, */ \
{ NAME, IDX, 0, NULL, NULL, FLAGS, 0, \
\
- /* linker_mark, linker_has_input, gc_mark, segment_mark, */ \
+ /* linker_mark, linker_has_input, gc_mark, decompress_status, */ \
0, 0, 1, 0, \
\
- /* sec_info_type, use_rela_p, */ \
- 0, 0, \
+ /* segment_mark, sec_info_type, use_rela_p, */ \
+ 0, 0, 0, \
\
/* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5, */ \
0, 0, 0, 0, 0, 0, \
\
- /* vma, lma, size, rawsize, relax, relax_count, */ \
- 0, 0, 0, 0, 0, 0, \
+ /* vma, lma, size, rawsize, compressed_size, relax, relax_count, */ \
+ 0, 0, 0, 0, 0, 0, 0, \
\
/* output_offset, output_section, alignment_power, */ \
0, (struct bfd_section *) &SEC, 0, \
@@ -5062,6 +5071,16 @@ struct bfd
will be consistent from run to run. */
#define BFD_DETERMINISTIC_OUTPUT 0x4000
+ /* Compress sections in this BFD. */
+#define BFD_COMPRESS 0x8000
+
+ /* Decompress sections in this BFD. */
+#define BFD_DECOMPRESS 0x10000
+
+ /* Flags bits to be saved in bfd_preserve_save. */
+#define BFD_FLAGS_SAVED \
+ (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS)
+
/* Currently my_archive is tested before adding origin to
anything. I believe that this can become always an add of
origin, with origin set to 0 for non archive files. */
@@ -5893,8 +5912,21 @@ bfd_byte *bfd_simple_get_relocated_section_contents
(bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table);
/* Extracted from compress.c. */
-bfd_boolean bfd_uncompress_section_contents
- (bfd_byte **buffer, bfd_size_type *size);
+bfd_boolean bfd_compress_section_contents
+ (bfd *abfd, asection *section, bfd_byte *uncompressed_buffer,
+ bfd_size_type uncompressed_size);
+
+bfd_boolean bfd_get_full_section_contents
+ (bfd *abfd, asection *section, bfd_byte **ptr);
+
+bfd_boolean bfd_is_section_compressed
+ (bfd *abfd, asection *section);
+
+bfd_boolean bfd_init_section_decompress_status
+ (bfd *abfd, asection *section);
+
+bfd_boolean bfd_init_section_compress_status
+ (bfd *abfd, asection *section);
#ifdef __cplusplus
}
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 771989b758..3b2960320d 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -151,6 +151,16 @@ CODE_FRAGMENT
. will be consistent from run to run. *}
.#define BFD_DETERMINISTIC_OUTPUT 0x4000
.
+. {* Compress sections in this BFD. *}
+.#define BFD_COMPRESS 0x8000
+.
+. {* Decompress sections in this BFD. *}
+.#define BFD_DECOMPRESS 0x10000
+.
+. {* Flags bits to be saved in bfd_preserve_save. *}
+.#define BFD_FLAGS_SAVED \
+. (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS)
+.
. {* Currently my_archive is tested before adding origin to
. anything. I believe that this can become always an add of
. origin, with origin set to 0 for non archive files. *}
@@ -1628,7 +1638,7 @@ bfd_preserve_save (bfd *abfd, struct bfd_preserve *preserve)
abfd->tdata.any = NULL;
abfd->arch_info = &bfd_default_arch_struct;
- abfd->flags &= BFD_IN_MEMORY;
+ abfd->flags &= BFD_FLAGS_SAVED;
abfd->sections = NULL;
abfd->section_last = NULL;
abfd->section_count = 0;
diff --git a/bfd/compress.c b/bfd/compress.c
index fe1b0fd3b3..171de77f38 100644
--- a/bfd/compress.c
+++ b/bfd/compress.c
@@ -27,49 +27,309 @@
#include <zlib.h>
#endif
+#ifdef HAVE_ZLIB_H
+static bfd_boolean
+decompress_contents (bfd_byte *compressed_buffer,
+ bfd_size_type compressed_size,
+ bfd_byte *uncompressed_buffer,
+ bfd_size_type uncompressed_size)
+{
+ z_stream strm;
+ int rc;
+
+ /* It is possible the section consists of several compressed
+ buffers concatenated together, so we uncompress in a loop. */
+ strm.zalloc = NULL;
+ strm.zfree = NULL;
+ strm.opaque = NULL;
+ strm.avail_in = compressed_size - 12;
+ strm.next_in = (Bytef*) compressed_buffer + 12;
+ strm.avail_out = uncompressed_size;
+
+ rc = inflateInit (&strm);
+ while (strm.avail_in > 0)
+ {
+ if (rc != Z_OK)
+ return FALSE;
+ strm.next_out = ((Bytef*) uncompressed_buffer
+ + (uncompressed_size - strm.avail_out));
+ rc = inflate (&strm, Z_FINISH);
+ if (rc != Z_STREAM_END)
+ return FALSE;
+ rc = inflateReset (&strm);
+ }
+ rc = inflateEnd (&strm);
+ return rc != Z_OK || strm.avail_out != 0 ? FALSE: TRUE;
+}
+#endif
+
/*
FUNCTION
- bfd_uncompress_section_contents
+ bfd_compress_section_contents
SYNOPSIS
- bfd_boolean bfd_uncompress_section_contents
- (bfd_byte **buffer, bfd_size_type *size);
+ bfd_boolean bfd_compress_section_contents
+ (bfd *abfd, asection *section, bfd_byte *uncompressed_buffer,
+ bfd_size_type uncompressed_size);
DESCRIPTION
- Uncompresses a section that was compressed using zlib, in place. At
- the call to this function, *@var{buffer} and *@var{size} should point
- to the section contents to be uncompressed. At the end of the
- function, *@var{buffer} and *@var{size} will point to the uncompressed
- contents. This function assumes *BUFFER was allocated using
- bfd_malloc() or equivalent. If the section is not a valid compressed
- section, or zlib is not installed on this machine, the input is
- unmodified.
-
- Returns @code{FALSE} if unable to uncompress successfully; in that case
- the input is unmodified. Otherwise, returns @code{TRUE}.
+ 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.
*/
bfd_boolean
-bfd_uncompress_section_contents (bfd_byte **buffer ATTRIBUTE_UNUSED,
- bfd_size_type *size ATTRIBUTE_UNUSED)
+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
- bfd_size_type compressed_size = *size;
- bfd_byte *compressed_buffer = *buffer;
+ bfd_size_type compressed_size;
+ bfd_byte *compressed_buffer;
+
+ compressed_size = compressBound (uncompressed_size) + 12;
+ compressed_buffer = (bfd_byte *) bfd_malloc (compressed_size);
+
+ if (compress ((Bytef*) compressed_buffer + 12,
+ &compressed_size,
+ (const Bytef*) uncompressed_buffer,
+ uncompressed_size) != Z_OK)
+ {
+ free (compressed_buffer);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+
+ /* 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;
+ sec->size = compressed_size;
+ sec->compress_status = COMPRESS_SECTION_DONE;
+
+ return TRUE;
+#endif /* HAVE_ZLIB_H */
+}
+
+/*
+FUNCTION
+ bfd_get_full_section_contents
+
+SYNOPSIS
+ bfd_boolean bfd_get_full_section_contents
+ (bfd *abfd, asection *section, bfd_byte **ptr);
+
+DESCRIPTION
+ Read all data from @var{section} in BFD @var{abfd}, decompress
+ if needed, and store in @var{*ptr}. If @var{*ptr} is NULL,
+ return @var{*ptr} with memory malloc'd by this function.
+
+ Return @code{TRUE} if the full section contents is retrieved
+ successfully.
+*/
+
+bfd_boolean
+bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
+{
+ bfd_size_type sz = sec->rawsize ? sec->rawsize : sec->size;
+ bfd_byte *p = *ptr;
+ bfd_boolean need_free, ret;
+#ifdef HAVE_ZLIB_H
+ bfd_size_type compressed_size;
bfd_size_type uncompressed_size;
+ bfd_size_type rawsize;
+ bfd_byte *compressed_buffer;
bfd_byte *uncompressed_buffer;
- z_stream strm;
- int rc;
- bfd_size_type header_size = 12;
+#endif
+
+ if (sz == 0)
+ return TRUE;
+
+ switch (sec->compress_status)
+ {
+ case COMPRESS_SECTION_NONE:
+ if (p == NULL)
+ {
+ p = (bfd_byte *) bfd_malloc (sz);
+ if (p == NULL)
+ return FALSE;
+ need_free = TRUE;
+ *ptr = p;
+ }
+ else
+ need_free = FALSE;
+ ret = bfd_get_section_contents (abfd, sec, p, 0, sz);
+ if (!ret && need_free)
+ free (p);
+ return ret;
+
+ case COMPRESS_SECTION_DONE:
+ if (p)
+ memcpy (p, sec->contents, sz);
+ else
+ *ptr = sec->contents;
+ return TRUE;
+
+ case DECOMPRESS_SECTION_SIZED:
+ break;
+
+ default:
+ abort ();
+ }
+
+#ifndef HAVE_ZLIB_H
+ bfd_set_error (bfd_error_invalid_operation);
+ return FALSE;
+#else
+ /* Read in the full compressed section contents. */
+ uncompressed_size = sec->size;
+ compressed_size = sec->compressed_size;
+ compressed_buffer = (bfd_byte *) bfd_malloc (compressed_size);
+ rawsize = sec->rawsize;
+ /* 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 = compressed_size;
+ sec->compress_status = COMPRESS_SECTION_NONE;
+ ret = bfd_get_section_contents (abfd, sec, compressed_buffer,
+ 0, compressed_size);
+ /* Restore rawsize and size. */
+ sec->rawsize = rawsize;
+ sec->size = uncompressed_size;
+ if (!ret)
+ {
+fail_compressed:
+ sec->compress_status = DECOMPRESS_SECTION_SIZED;
+ free (compressed_buffer);
+ return ret;
+ }
+
+ /* Decompress to caller buffer directly if it is provided. */
+ if (p)
+ uncompressed_buffer = p;
+ else
+ {
+ uncompressed_buffer = (bfd_byte *) bfd_malloc (uncompressed_size);
+ if (uncompressed_buffer == NULL)
+ goto fail_compressed;
+ }
+
+ if (!decompress_contents (compressed_buffer, compressed_size,
+ uncompressed_buffer, uncompressed_size))
+ {
+ sec->compress_status = DECOMPRESS_SECTION_SIZED;
+ free (compressed_buffer);
+ if (p == NULL)
+ free (uncompressed_buffer);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+
+ free (compressed_buffer);
+ if (p == NULL)
+ *ptr = uncompressed_buffer;
+
+ sec->contents = uncompressed_buffer;
+ sec->compress_status = COMPRESS_SECTION_DONE;
+
+ return TRUE;
+#endif
+}
+
+/*
+FUNCTION
+ bfd_is_section_compressed
+
+SYNOPSIS
+ bfd_boolean bfd_is_section_compressed
+ (bfd *abfd, asection *section);
+
+DESCRIPTION
+ Return @code{TRUE} if @var{section} is compressed.
+*/
+
+bfd_boolean
+bfd_is_section_compressed (bfd *abfd, sec_ptr sec)
+{
+ bfd_byte compressed_buffer [12];
+
+ /* Read the zlib header. In this case, it should be "ZLIB" followed
+ by the uncompressed section size, 8 bytes in big-endian order. */
+ return (bfd_get_section_contents (abfd, sec, compressed_buffer, 0, 12)
+ && CONST_STRNEQ ((char*) compressed_buffer, "ZLIB"));
+}
+
+/*
+FUNCTION
+ bfd_init_section_decompress_status
+
+SYNOPSIS
+ bfd_boolean bfd_init_section_decompress_status
+ (bfd *abfd, asection *section);
+
+DESCRIPTION
+ Record compressed section size, update section size with
+ decompressed size and set compress_status to
+ DECOMPRESS_SECTION_SIZED.
+
+ Return @code{FALSE} if the section is not a valid compressed
+ section or zlib is not installed on this machine. Otherwise,
+ return @code{TRUE}.
+*/
+
+bfd_boolean
+bfd_init_section_decompress_status (bfd *abfd ATTRIBUTE_UNUSED,
+ sec_ptr sec ATTRIBUTE_UNUSED)
+{
+#ifndef HAVE_ZLIB_H
+ bfd_set_error (bfd_error_invalid_operation);
+ return FALSE;
+#else
+ bfd_byte compressed_buffer [12];
+ bfd_size_type uncompressed_size;
+
+ if (sec->rawsize != 0
+ || sec->contents != NULL
+ || sec->compress_status != COMPRESS_SECTION_NONE
+ || !bfd_get_section_contents (abfd, sec, compressed_buffer, 0, 12))
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return FALSE;
+ }
/* Read the zlib header. In this case, it should be "ZLIB" followed
by the uncompressed section size, 8 bytes in big-endian order. */
- if (compressed_size < header_size
- || ! CONST_STRNEQ ((char*) compressed_buffer, "ZLIB"))
- return FALSE;
+ if (! CONST_STRNEQ ((char*) compressed_buffer, "ZLIB"))
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return FALSE;
+ }
+
uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8;
uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8;
uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8;
@@ -79,42 +339,66 @@ bfd_uncompress_section_contents (bfd_byte **buffer ATTRIBUTE_UNUSED,
uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8;
uncompressed_size += compressed_buffer[11];
- /* It is possible the section consists of several compressed
- buffers concatenated together, so we uncompress in a loop. */
- strm.zalloc = NULL;
- strm.zfree = NULL;
- strm.opaque = NULL;
- strm.avail_in = compressed_size - header_size;
- strm.next_in = (Bytef*) compressed_buffer + header_size;
- strm.avail_out = uncompressed_size;
- uncompressed_buffer = (bfd_byte *) bfd_malloc (uncompressed_size);
- if (! uncompressed_buffer)
- return FALSE;
+ sec->compressed_size = sec->size;
+ sec->size = uncompressed_size;
+ sec->compress_status = DECOMPRESS_SECTION_SIZED;
- rc = inflateInit (&strm);
- while (strm.avail_in > 0)
+ return TRUE;
+#endif
+}
+
+/*
+FUNCTION
+ bfd_init_section_compress_status
+
+SYNOPSIS
+ bfd_boolean bfd_init_section_compress_status
+ (bfd *abfd, asection *section);
+
+DESCRIPTION
+ If open for read, compress section, update section size with
+ compressed size and set compress_status to COMPRESS_SECTION_DONE.
+
+ Return @code{FALSE} if the section is not a valid compressed
+ section or zlib is not installed on this machine. Otherwise,
+ return @code{TRUE}.
+*/
+
+bfd_boolean
+bfd_init_section_compress_status (bfd *abfd ATTRIBUTE_UNUSED,
+ sec_ptr sec ATTRIBUTE_UNUSED)
+{
+#ifndef HAVE_ZLIB_H
+ bfd_set_error (bfd_error_invalid_operation);
+ return FALSE;
+#else
+ bfd_size_type uncompressed_size;
+ bfd_byte *uncompressed_buffer;
+ bfd_boolean ret;
+
+ /* Error if not opened for read. */
+ if (abfd->direction != read_direction
+ || sec->size == 0
+ || sec->rawsize != 0
+ || sec->contents != NULL
+ || sec->compress_status != COMPRESS_SECTION_NONE)
{
- if (rc != Z_OK)
- goto fail;
- strm.next_out = ((Bytef*) uncompressed_buffer
- + (uncompressed_size - strm.avail_out));
- rc = inflate (&strm, Z_FINISH);
- if (rc != Z_STREAM_END)
- goto fail;
- rc = inflateReset (&strm);
+ bfd_set_error (bfd_error_invalid_operation);
+ return FALSE;
}
- rc = inflateEnd (&strm);
- if (rc != Z_OK
- || strm.avail_out != 0)
- goto fail;
- free (compressed_buffer);
- *buffer = uncompressed_buffer;
- *size = uncompressed_size;
- return TRUE;
+ /* Read in the full section contents and compress it. */
+ uncompressed_size = sec->size;
+ uncompressed_buffer = (bfd_byte *) bfd_malloc (uncompressed_size);
+ if (!bfd_get_section_contents (abfd, sec, uncompressed_buffer,
+ 0, uncompressed_size))
+ ret = FALSE;
+ else
+ ret = bfd_compress_section_contents (abfd, sec,
+ uncompressed_buffer,
+ uncompressed_size);
- fail:
free (uncompressed_buffer);
- return FALSE;
-#endif /* HAVE_ZLIB_H */
+ return ret;
+#endif
}
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index 12858338f6..e5d010349c 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -275,6 +275,60 @@ struct attr_abbrev
enum dwarf_form form;
};
+/* Map of uncompressed DWARF debug section name to compressed one. It
+ is terminated by NULL uncompressed_name. */
+
+struct dwarf_debug_section dwarf_debug_sections[] =
+{
+ { ".debug_abbrev", ".zdebug_abbrev" },
+ { ".debug_aranges", ".zdebug_aranges" },
+ { ".debug_frame", ".zdebug_frame" },
+ { ".debug_info", ".zdebug_info" },
+ { ".debug_line", ".zdebug_line" },
+ { ".debug_loc", ".zdebug_loc" },
+ { ".debug_macinfo", ".zdebug_macinfo" },
+ { ".debug_pubnames", ".zdebug_pubnames" },
+ { ".debug_pubtypes", ".zdebug_pubtypes" },
+ { ".debug_ranges", ".zdebug_ranges" },
+ { ".debug_static_func", ".zdebug_static_func" },
+ { ".debug_static_vars", ".zdebug_static_vars" },
+ { ".debug_str", ".zdebug_str", },
+ { ".debug_types", ".zdebug_types" },
+ /* GNU DWARF 1 extensions */
+ { ".debug_sfnames", ".zdebug_sfnames" },
+ { ".debug_srcinfo", ".zebug_srcinfo" },
+ /* SGI/MIPS DWARF 2 extensions */
+ { ".debug_funcnames", ".zdebug_funcnames" },
+ { ".debug_typenames", ".zdebug_typenames" },
+ { ".debug_varnames", ".zdebug_varnames" },
+ { ".debug_weaknames", ".zdebug_weaknames" },
+ { NULL, NULL },
+};
+
+enum dwarf_debug_section_enum
+{
+ debug_abbrev = 0,
+ debug_aranges,
+ debug_frame,
+ debug_info,
+ debug_line,
+ debug_loc,
+ debug_macinfo,
+ debug_pubnames,
+ debug_pubtypes,
+ debug_ranges,
+ debug_static_func,
+ debug_static_vars,
+ debug_str,
+ debug_types,
+ debug_sfnames,
+ debug_srcinfo,
+ debug_funcnames,
+ debug_typenames,
+ debug_varnames,
+ debug_weaknames
+};
+
#ifndef ABBREV_HASH_SIZE
#define ABBREV_HASH_SIZE 121
#endif
@@ -413,24 +467,23 @@ lookup_info_hash_table (struct info_hash_table *hash_table, const char *key)
static bfd_boolean
read_section (bfd * abfd,
- const char * section_name,
- const char * compressed_section_name,
+ enum dwarf_debug_section_enum sec,
asymbol ** syms,
bfd_uint64_t offset,
bfd_byte ** section_buffer,
bfd_size_type * section_size)
{
asection *msec;
- bfd_boolean section_is_compressed = FALSE;
+ const char *section_name = dwarf_debug_sections[sec].uncompressed_name;
/* read_section is a noop if the section has already been read. */
if (!*section_buffer)
{
msec = bfd_get_section_by_name (abfd, section_name);
- if (! msec && compressed_section_name)
+ if (! msec)
{
- msec = bfd_get_section_by_name (abfd, compressed_section_name);
- section_is_compressed = TRUE;
+ section_name = dwarf_debug_sections[sec].compressed_name;
+ msec = bfd_get_section_by_name (abfd, section_name);
}
if (! msec)
{
@@ -456,16 +509,6 @@ read_section (bfd * abfd,
0, *section_size))
return FALSE;
}
-
- if (section_is_compressed)
- {
- if (! bfd_uncompress_section_contents (section_buffer, section_size))
- {
- (*_bfd_error_handler) (_("Dwarf Error: unable to decompress %s section."), compressed_section_name);
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
- }
}
/* It is possible to get a bad value for the offset into the section
@@ -561,8 +604,7 @@ read_indirect_string (struct comp_unit * unit,
*bytes_read_ptr = unit->offset_size;
- if (! read_section (unit->abfd, ".debug_str", ".zdebug_str",
- stash->syms, offset,
+ if (! read_section (unit->abfd, debug_str, stash->syms, offset,
&stash->dwarf_str_buffer, &stash->dwarf_str_size))
return NULL;
@@ -644,8 +686,7 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash)
unsigned int abbrev_form, hash_number;
bfd_size_type amt;
- if (! read_section (abfd, ".debug_abbrev", ".zdebug_abbrev",
- stash->syms, offset,
+ if (! read_section (abfd, debug_abbrev, stash->syms, offset,
&stash->dwarf_abbrev_buffer, &stash->dwarf_abbrev_size))
return NULL;
@@ -1353,8 +1394,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash)
unsigned char op_code, extended_op, adj_opcode;
bfd_size_type amt;
- if (! read_section (abfd, ".debug_line", ".zdebug_line",
- stash->syms, unit->line_offset,
+ if (! read_section (abfd, debug_line, stash->syms, unit->line_offset,
&stash->dwarf_line_buffer, &stash->dwarf_line_size))
return NULL;
@@ -1769,8 +1809,7 @@ static bfd_boolean
read_debug_ranges (struct comp_unit *unit)
{
struct dwarf2_debug *stash = unit->stash;
- return read_section (unit->abfd, ".debug_ranges", ".zdebug_ranges",
- stash->syms, 0,
+ return read_section (unit->abfd, debug_ranges, stash->syms, 0,
&stash->dwarf_ranges_buffer, &stash->dwarf_ranges_size);
}
@@ -3192,86 +3231,37 @@ find_line (bfd *abfd,
{
/* Case 1: only one info section. */
total_size = msec->size;
- if (! read_section (debug_bfd, ".debug_info", ".zdebug_info",
- symbols, 0,
+ if (! read_section (debug_bfd, debug_info, symbols, 0,
&stash->info_ptr_memory, &total_size))
goto done;
}
else
{
- int all_uncompressed = 1;
+ /* Case 2: multiple sections. */
for (total_size = 0; msec; msec = find_debug_info (debug_bfd, msec))
- {
- total_size += msec->size;
- if (strcmp (msec->name, DWARF2_COMPRESSED_DEBUG_INFO) == 0)
- all_uncompressed = 0;
- }
- if (all_uncompressed)
- {
- /* Case 2: multiple sections, but none is compressed. */
- stash->info_ptr_memory = (bfd_byte *) bfd_malloc (total_size);
- if (stash->info_ptr_memory == NULL)
- goto done;
-
- total_size = 0;
- for (msec = find_debug_info (debug_bfd, NULL);
- msec;
- msec = find_debug_info (debug_bfd, msec))
- {
- bfd_size_type size;
-
- size = msec->size;
- if (size == 0)
- continue;
+ total_size += msec->size;
- if (!(bfd_simple_get_relocated_section_contents
- (debug_bfd, msec, stash->info_ptr_memory + total_size,
- symbols)))
- goto done;
+ stash->info_ptr_memory = (bfd_byte *) bfd_malloc (total_size);
+ if (stash->info_ptr_memory == NULL)
+ goto done;
- total_size += size;
- }
- }
- else
+ total_size = 0;
+ for (msec = find_debug_info (debug_bfd, NULL);
+ msec;
+ msec = find_debug_info (debug_bfd, msec))
{
- /* Case 3: multiple sections, some or all compressed. */
- stash->info_ptr_memory = NULL;
- total_size = 0;
- for (msec = find_debug_info (debug_bfd, NULL);
- msec;
- msec = find_debug_info (debug_bfd, msec))
- {
- bfd_size_type size = msec->size;
- bfd_byte *buffer, *tmp;
+ bfd_size_type size;
- if (size == 0)
- continue;
+ size = msec->size;
+ if (size == 0)
+ continue;
- buffer = (bfd_simple_get_relocated_section_contents
- (debug_bfd, msec, NULL, symbols));
- if (! buffer)
- goto done;
+ if (!(bfd_simple_get_relocated_section_contents
+ (debug_bfd, msec, stash->info_ptr_memory + total_size,
+ symbols)))
+ goto done;
- if (strcmp (msec->name, DWARF2_COMPRESSED_DEBUG_INFO) == 0)
- {
- if (! bfd_uncompress_section_contents (&buffer, &size))
- {
- free (buffer);
- goto done;
- }
- }
- tmp = (bfd_byte *) bfd_realloc (stash->info_ptr_memory,
- total_size + size);
- if (tmp == NULL)
- {
- free (buffer);
- goto done;
- }
- stash->info_ptr_memory = tmp;
- memcpy (stash->info_ptr_memory + total_size, buffer, size);
- free (buffer);
- total_size += size;
- }
+ total_size += size;
}
}
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index 37003d2a32..43494868d6 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -55,14 +55,14 @@ static asection bfd_debug_section =
{
/* name, id, index, next, prev, flags, user_set_vma, */
"*DEBUG*", 0, 0, NULL, NULL, 0, 0,
- /* linker_mark, linker_has_input, gc_mark, segment_mark, */
+ /* linker_mark, linker_has_input, gc_mark, compress_status, */
0, 0, 1, 0,
- /* sec_info_type, use_rela_p, */
- 0, 0,
+ /* segment_mark, sec_info_type, use_rela_p, */
+ 0, 0, 0,
/* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5, */
0, 0, 0, 0, 0, 0,
- /* vma, lma, size, rawsize, relax, relax_count, */
- 0, 0, 0, 0, 0, 0,
+ /* vma, lma, size, rawsize, compressed_size, relax, relax_count, */
+ 0, 0, 0, 0, 0, 0, 0,
/* output_offset, output_section, alignment_power, */
0, NULL, 0,
/* relocation, orelocation, reloc_count, filepos, rel_filepos, */
diff --git a/bfd/elf.c b/bfd/elf.c
index 4df0007725..4f326a7ae5 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1009,6 +1009,52 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
}
}
+ /* Compress/decompress DWARF debug sections with names: .debug_* and
+ .zdebug_*, after the section flags is set. */
+ if ((flags & SEC_DEBUGGING)
+ && ((name[1] == 'd' && name[6] == '_')
+ || (name[1] == 'z' && name[7] == '_')))
+ {
+ enum { nothing, compress, decompress } action = nothing;
+
+ if (bfd_is_section_compressed (abfd, newsect))
+ {
+ /* Compressed section. Check if we should decompress. */
+ if ((abfd->flags & BFD_DECOMPRESS))
+ action = decompress;
+ }
+ else
+ {
+ /* Normal section. Check if we should compress. */
+ if ((abfd->flags & BFD_COMPRESS))
+ action = compress;
+ }
+
+ switch (action)
+ {
+ case nothing:
+ break;
+ case compress:
+ if (!bfd_init_section_compress_status (abfd, newsect))
+ {
+ (*_bfd_error_handler)
+ (_("%B: unable to initialize commpress status for section %s"),
+ abfd, name);
+ return FALSE;
+ }
+ break;
+ case decompress:
+ if (!bfd_init_section_decompress_status (abfd, newsect))
+ {
+ (*_bfd_error_handler)
+ (_("%B: unable to initialize decommpress status for section %s"),
+ abfd, name);
+ return FALSE;
+ }
+ break;
+ }
+ }
+
return TRUE;
}
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 6726d464c6..590e3243cd 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -9354,10 +9354,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
contents = elf_section_data (o)->this_hdr.contents;
else
{
- bfd_size_type amt = o->rawsize ? o->rawsize : o->size;
-
contents = finfo->contents;
- if (! bfd_get_section_contents (input_bfd, o, contents, 0, amt))
+ if (! bfd_get_full_section_contents (input_bfd, o, &contents))
return FALSE;
}
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index 57f352c6ed..6695afcc63 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -785,7 +785,7 @@ const bfd_target TARGET_BIG_SYM =
/* object_flags: mask of all file flags */
(HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS
- | DYNAMIC | WP_TEXT | D_PAGED),
+ | DYNAMIC | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS),
/* section_flags: mask of all section flags */
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY
@@ -881,7 +881,7 @@ const bfd_target TARGET_LITTLE_SYM =
/* object_flags: mask of all file flags */
(HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS
- | DYNAMIC | WP_TEXT | D_PAGED),
+ | DYNAMIC | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS),
/* section_flags: mask of all section flags */
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
index 91d3bbd443..b7201bdde2 100644
--- a/bfd/libbfd-in.h
+++ b/bfd/libbfd-in.h
@@ -808,3 +808,13 @@ extern void bfd_section_already_linked_table_traverse
extern bfd_vma read_unsigned_leb128 (bfd *, bfd_byte *, unsigned int *);
extern bfd_signed_vma read_signed_leb128 (bfd *, bfd_byte *, unsigned int *);
+struct dwarf_debug_section
+{
+ const char *uncompressed_name;
+ const char *compressed_name;
+};
+
+/* Map of uncompressed DWARF debug section name to compressed one. It
+ is terminated by NULL uncompressed_name. */
+
+extern struct dwarf_debug_section dwarf_debug_sections[];
diff --git a/bfd/libbfd.c b/bfd/libbfd.c
index 5146d9525e..a66d9c6f07 100644
--- a/bfd/libbfd.c
+++ b/bfd/libbfd.c
@@ -857,6 +857,15 @@ _bfd_generic_get_section_contents (bfd *abfd,
if (count == 0)
return TRUE;
+ if (section->compress_status != COMPRESS_SECTION_NONE)
+ {
+ (*_bfd_error_handler)
+ (_("%B: unable to get decompressed section %A"),
+ abfd, section);
+ bfd_set_error (bfd_error_invalid_operation);
+ return FALSE;
+ }
+
sz = section->rawsize ? section->rawsize : section->size;
if (offset + count < count
|| offset + count > sz)
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 002937fdc4..e706ce4215 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -813,6 +813,16 @@ extern void bfd_section_already_linked_table_traverse
extern bfd_vma read_unsigned_leb128 (bfd *, bfd_byte *, unsigned int *);
extern bfd_signed_vma read_signed_leb128 (bfd *, bfd_byte *, unsigned int *);
+struct dwarf_debug_section
+{
+ const char *uncompressed_name;
+ const char *compressed_name;
+};
+
+/* Map of uncompressed DWARF debug section name to compressed one. It
+ is terminated by NULL uncompressed_name. */
+
+extern struct dwarf_debug_section dwarf_debug_sections[];
/* Extracted from init.c. */
/* Extracted from libbfd.c. */
bfd_boolean bfd_write_bigendian_4byte_int (bfd *, unsigned int);
diff --git a/bfd/merge.c b/bfd/merge.c
index 7aa088ff94..aef3cf35a5 100644
--- a/bfd/merge.c
+++ b/bfd/merge.c
@@ -348,6 +348,7 @@ _bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec,
struct sec_merge_sec_info *secinfo;
unsigned int align;
bfd_size_type amt;
+ bfd_byte *contents;
if ((abfd->flags & DYNAMIC) != 0
|| (sec->flags & SEC_MERGE) == 0)
@@ -432,8 +433,8 @@ _bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec,
sec->rawsize = sec->size;
if (sec->flags & SEC_STRINGS)
memset (secinfo->contents + sec->size, 0, sec->entsize);
- if (! bfd_get_section_contents (sec->owner, sec, secinfo->contents,
- 0, sec->size))
+ contents = secinfo->contents;
+ if (! bfd_get_full_section_contents (sec->owner, sec, &contents))
goto error_return;
return TRUE;
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 4e95d85f0b..5a428a26a3 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -5721,15 +5721,13 @@ bfd_generic_get_relocated_section_contents (bfd *abfd,
long reloc_size;
arelent **reloc_vector;
long reloc_count;
- bfd_size_type sz;
reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
if (reloc_size < 0)
return NULL;
/* Read in the section. */
- sz = input_section->rawsize ? input_section->rawsize : input_section->size;
- if (!bfd_get_section_contents (input_bfd, input_section, data, 0, sz))
+ if (!bfd_get_full_section_contents (input_bfd, input_section, &data))
return NULL;
if (reloc_size == 0)
diff --git a/bfd/section.c b/bfd/section.c
index 6e13fdb10e..51c2196bc4 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -364,6 +364,12 @@ CODE_FRAGMENT
. {* Mark flag used by some linker backends for garbage collection. *}
. unsigned int gc_mark : 1;
.
+. {* Section compression status. *}
+. unsigned int compress_status : 2;
+.#define COMPRESS_SECTION_NONE 0
+.#define COMPRESS_SECTION_DONE 1
+.#define DECOMPRESS_SECTION_SIZED 2
+.
. {* The following flags are used by the ELF linker. *}
.
. {* Mark sections which have been allocated to segments. *}
@@ -420,6 +426,9 @@ CODE_FRAGMENT
. section size calculated on a previous linker relaxation pass. *}
. bfd_size_type rawsize;
.
+. {* The compressed size of the section in octets. *}
+. bfd_size_type compressed_size;
+.
. {* Relaxation table. *}
. struct relax_table *relax;
.
@@ -653,17 +662,17 @@ CODE_FRAGMENT
. {* name, id, index, next, prev, flags, user_set_vma, *} \
. { NAME, IDX, 0, NULL, NULL, FLAGS, 0, \
. \
-. {* linker_mark, linker_has_input, gc_mark, segment_mark, *} \
+. {* linker_mark, linker_has_input, gc_mark, decompress_status, *} \
. 0, 0, 1, 0, \
. \
-. {* sec_info_type, use_rela_p, *} \
-. 0, 0, \
+. {* segment_mark, sec_info_type, use_rela_p, *} \
+. 0, 0, 0, \
. \
. {* sec_flg0, sec_flg1, sec_flg2, sec_flg3, sec_flg4, sec_flg5, *} \
. 0, 0, 0, 0, 0, 0, \
. \
-. {* vma, lma, size, rawsize, relax, relax_count, *} \
-. 0, 0, 0, 0, 0, 0, \
+. {* vma, lma, size, rawsize, compressed_size, relax, relax_count, *} \
+. 0, 0, 0, 0, 0, 0, 0, \
. \
. {* output_offset, output_section, alignment_power, *} \
. 0, (struct bfd_section *) &SEC, 0, \
@@ -1480,20 +1489,8 @@ DESCRIPTION
bfd_boolean
bfd_malloc_and_get_section (bfd *abfd, sec_ptr sec, bfd_byte **buf)
{
- bfd_size_type sz = sec->rawsize ? sec->rawsize : sec->size;
- bfd_byte *p = NULL;
-
- *buf = p;
- if (sz == 0)
- return TRUE;
-
- p = (bfd_byte *)
- bfd_malloc (sec->rawsize > sec->size ? sec->rawsize : sec->size);
- if (p == NULL)
- return FALSE;
- *buf = p;
-
- return bfd_get_section_contents (abfd, sec, p, 0, sz);
+ *buf = NULL;
+ return bfd_get_full_section_contents (abfd, sec, buf);
}
/*
FUNCTION
diff --git a/bfd/simple.c b/bfd/simple.c
index 9a8397f83e..03d1a15885 100644
--- a/bfd/simple.c
+++ b/bfd/simple.c
@@ -167,17 +167,9 @@ bfd_simple_get_relocated_section_contents (bfd *abfd,
if ((abfd->flags & (HAS_RELOC | EXEC_P | DYNAMIC)) != HAS_RELOC
|| ! (sec->flags & SEC_RELOC))
{
- bfd_size_type amt = sec->rawsize > sec->size ? sec->rawsize : sec->size;
- bfd_size_type size = sec->rawsize ? sec->rawsize : sec->size;
-
- if (outbuf == NULL)
- contents = (bfd_byte *) bfd_malloc (amt);
- else
- contents = outbuf;
-
- if (contents)
- bfd_get_section_contents (abfd, sec, contents, 0, size);
-
+ contents = outbuf;
+ if (!bfd_get_full_section_contents (abfd, sec, &contents))
+ return NULL;
return contents;
}