diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 64 | ||||
-rw-r--r-- | bfd/archive.c | 10 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 46 | ||||
-rw-r--r-- | bfd/bfd.c | 12 | ||||
-rw-r--r-- | bfd/compress.c | 396 | ||||
-rw-r--r-- | bfd/dwarf2.c | 174 | ||||
-rw-r--r-- | bfd/ecoff.c | 10 | ||||
-rw-r--r-- | bfd/elf.c | 46 | ||||
-rw-r--r-- | bfd/elflink.c | 4 | ||||
-rw-r--r-- | bfd/elfxx-target.h | 4 | ||||
-rw-r--r-- | bfd/libbfd-in.h | 10 | ||||
-rw-r--r-- | bfd/libbfd.c | 9 | ||||
-rw-r--r-- | bfd/libbfd.h | 10 | ||||
-rw-r--r-- | bfd/merge.c | 5 | ||||
-rw-r--r-- | bfd/reloc.c | 4 | ||||
-rw-r--r-- | bfd/section.c | 35 | ||||
-rw-r--r-- | bfd/simple.c | 14 |
17 files changed, 651 insertions, 202 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a45bac7..baec58b 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 1b3f692..ed40141 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 cbbb0f6..aec5c24 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 } @@ -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 fe1b0fd..171de77 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 1285833..e5d0103 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 37003d2..4349486 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, */ @@ -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 6726d46..590e324 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 57f352c..6695afc 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 91d3bbd..b7201bd 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 5146d95..a66d9c6 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 002937f..e706ce4 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 7aa088f..aef3cf3 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 4e95d85..5a428a2 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 6e13fdb..51c2196 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 9a8397f..03d1a15 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; } |