From 0acf065b19253e02ea32188ea0cbdf4e80e3c42d Mon Sep 17 00:00:00 2001 From: Cary Coutant Date: Sat, 3 Jul 2010 20:52:24 +0000 Subject: [PATCH] bfd/ChangeLog: * compress.c (bfd_uncompress_section_contents): Add ATTRIBUTE_UNUSED. * dwarf2.c (read_and_uncompress_section): New function. (read_section): Call it. (find_line): Likewise. binutils/ChangeLog: * objdump.c (load_specific_debug_section): Decompress section contents before applying relocations. * readelf.c (load_specific_debug_section): Update section size after decompression. gas/ChangeLog: * Makefile.am: Add compress-debug.c and compress-debug.h. * Makefile.in: Regenerate. * config.in: Add HAVE_ZLIB_H. * configure.in: Check for zlib.h. * configure: Regenerate. * as.c (parse_args): Add --compress-debug-sections and --nocompress-debug-sections. * as.h (flag_compress_debug): New variable. * compress-debug.c: New file. * compress-debug.h: New file. * write.c: Include compress-debug.h. (compress_frag): New function. (compress_debug): New function. (write_object_file): Compress debug sections if requested. --- bfd/ChangeLog | 7 ++ bfd/compress.c | 2 +- bfd/dwarf2.c | 92 ++++++++++++--------- binutils/ChangeLog | 7 ++ binutils/objdump.c | 34 ++++++-- binutils/readelf.c | 7 +- gas/ChangeLog | 18 +++++ gas/Makefile.am | 2 + gas/Makefile.in | 19 +++-- gas/as.c | 14 +++- gas/as.h | 3 + gas/config.in | 3 + gas/configure | 92 ++++++++++++++++++++- gas/configure.in | 3 + gas/write.c | 196 +++++++++++++++++++++++++++++++++++++++++++++ 15 files changed, 441 insertions(+), 58 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 91ed31f8372..a18507fbc83 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2010-07-03 Cary Coutant + + * compress.c (bfd_uncompress_section_contents): Add ATTRIBUTE_UNUSED. + * dwarf2.c (read_and_uncompress_section): New function. + (read_section): Call it. + (find_line): Likewise. + 2010-07-01 Alan Modra * elf64-ppc.c (ppc64_elf_edit_toc): Use SYMBOL_CALLS_LOCAL rather diff --git a/bfd/compress.c b/bfd/compress.c index e074eca8e59..fe1b0fd3b33 100644 --- a/bfd/compress.c +++ b/bfd/compress.c @@ -1,4 +1,4 @@ -/* ELF attributes support (based on ARM EABI attributes). +/* Compressed section support (intended for debug sections). Copyright 2008, 2010 Free Software Foundation, Inc. diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c index 9b194aaa66b..ffe110857ef 100644 --- a/bfd/dwarf2.c +++ b/bfd/dwarf2.c @@ -405,6 +405,54 @@ lookup_info_hash_table (struct info_hash_table *hash_table, const char *key) return entry ? entry->head : NULL; } +/* Read a section, uncompress it if necessary, and relocate it. */ + +static bfd_boolean +read_and_uncompress_section (bfd * abfd, + asection * msec, + bfd_boolean section_is_compressed, + asymbol ** syms, + bfd_byte ** section_buffer, + bfd_size_type * section_size) +{ + /* Get the unrelocated contents of the section. */ + *section_buffer = (bfd_byte *) bfd_malloc (*section_size); + if (! *section_buffer) + return FALSE; + if (! bfd_get_section_contents (abfd, msec, *section_buffer, + 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."), + bfd_get_section_name (abfd, msec)); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + } + + if (syms) + { + /* We want to relocate the data we've already read (and + decompressed), so we store a pointer to the data in + the bfd_section, and tell it that the contents are + already in memory. */ + BFD_ASSERT (msec->contents == NULL && (msec->flags & SEC_IN_MEMORY) == 0); + msec->contents = *section_buffer; + msec->flags |= SEC_IN_MEMORY; + msec->size = *section_size; + *section_buffer + = bfd_simple_get_relocated_section_contents (abfd, msec, NULL, syms); + if (! *section_buffer) + return FALSE; + } + + return TRUE; +} + /* Read a section into its appropriate place in the dwarf2_debug struct (indicated by SECTION_BUFFER and SECTION_SIZE). If SYMS is not NULL, use bfd_simple_get_relocated_section_contents to read the @@ -440,32 +488,10 @@ read_section (bfd * abfd, } *section_size = msec->rawsize ? msec->rawsize : msec->size; - if (syms) - { - *section_buffer - = bfd_simple_get_relocated_section_contents (abfd, msec, NULL, syms); - if (! *section_buffer) - return FALSE; - } - else - { - *section_buffer = (bfd_byte *) bfd_malloc (*section_size); - if (! *section_buffer) - return FALSE; - if (! bfd_get_section_contents (abfd, msec, *section_buffer, - 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; - } - } + if (! read_and_uncompress_section (abfd, msec, section_is_compressed, + syms, section_buffer, section_size)) + return FALSE; } /* It is possible to get a bad value for the offset into the section @@ -3242,23 +3268,17 @@ find_line (bfd *abfd, { bfd_size_type size = msec->size; bfd_byte *buffer, *tmp; + bfd_boolean is_compressed = + strcmp (msec->name, DWARF2_COMPRESSED_DEBUG_INFO) == 0; if (size == 0) continue; - buffer = (bfd_simple_get_relocated_section_contents - (debug_bfd, msec, NULL, symbols)); - if (! buffer) + if (! read_and_uncompress_section (debug_bfd, msec, + is_compressed, symbols, + &buffer, &size)) 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) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 0007863a3e9..74d22edf998 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,10 @@ +2010-07-03 Cary Coutant + + * objdump.c (load_specific_debug_section): Decompress section contents + before applying relocations. + * readelf.c (load_specific_debug_section): Update section size after + decompression. + 2010-06-29 Alan Modra PR binutils/3166 diff --git a/binutils/objdump.c b/binutils/objdump.c index 2a419b7a1a0..f94dee968e2 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -2205,14 +2205,8 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, section->size = bfd_get_section_size (sec); section->start = (unsigned char *) xmalloc (section->size); - if (is_relocatable && debug_displays [debug].relocate) - ret = bfd_simple_get_relocated_section_contents (abfd, - sec, - section->start, - syms) != NULL; - else - ret = bfd_get_section_contents (abfd, sec, section->start, 0, - section->size); + ret = bfd_get_section_contents (abfd, sec, section->start, 0, + section->size); if (! ret) { @@ -2234,6 +2228,30 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, section->size = size; } + if (is_relocatable && debug_displays [debug].relocate) + { + /* We want to relocate the data we've already read (and + decompressed), so we store a pointer to the data in + the bfd_section, and tell it that the contents are + already in memory. */ + sec->contents = section->start; + sec->flags |= SEC_IN_MEMORY; + sec->size = section->size; + + ret = bfd_simple_get_relocated_section_contents (abfd, + sec, + section->start, + syms) != NULL; + + if (! ret) + { + free_debug_section (debug); + printf (_("\nCan't get contents for section '%s'.\n"), + section->name); + return 0; + } + } + return 1; } diff --git a/binutils/readelf.c b/binutils/readelf.c index d4f47ca7318..1c3cb8b2864 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -9962,8 +9962,11 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, return 0; if (section_is_compressed) - if (! uncompress_section_contents (§ion->start, §ion->size)) - return 0; + { + if (! uncompress_section_contents (§ion->start, §ion->size)) + return 0; + sec->sh_size = section->size; + } if (debug_displays [debug].relocate) apply_relocations ((FILE *) file, sec, section->start); diff --git a/gas/ChangeLog b/gas/ChangeLog index 86b3c35a4d9..50dd6c1c895 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,21 @@ +2010-07-03 Cary Coutant + + * Makefile.am: Add compress-debug.c and compress-debug.h. + * Makefile.in: Regenerate. + * config.in: Add HAVE_ZLIB_H. + * configure.in: Check for zlib.h. + * configure: Regenerate. + + * as.c (parse_args): Add --compress-debug-sections and + --nocompress-debug-sections. + * as.h (flag_compress_debug): New variable. + * compress-debug.c: New file. + * compress-debug.h: New file. + * write.c: Include compress-debug.h. + (compress_frag): New function. + (compress_debug): New function. + (write_object_file): Compress debug sections if requested. + 2010-07-03 Andreas Schwab * config/tc-ppc.c (ppc_set_cpu): Cast PPC_OPCODE_xxx to ppc_cpu_t diff --git a/gas/Makefile.am b/gas/Makefile.am index d23b472d7c5..6971f73c73b 100644 --- a/gas/Makefile.am +++ b/gas/Makefile.am @@ -43,6 +43,7 @@ GAS_CFILES = \ app.c \ as.c \ atof-generic.c \ + compress-debug.c \ cond.c \ depend.c \ dwarf2dbg.c \ @@ -78,6 +79,7 @@ HFILES = \ bignum.h \ bit_fix.h \ cgen.h \ + compress-debug.h \ dwarf2dbg.h \ dw2gencfi.h \ ecoff.h \ diff --git a/gas/Makefile.in b/gas/Makefile.in index 84e2f50d3f1..6793520a86c 100644 --- a/gas/Makefile.in +++ b/gas/Makefile.in @@ -73,14 +73,14 @@ CONFIG_CLEAN_FILES = gdb.ini .gdbinit po/Makefile.in CONFIG_CLEAN_VPATH_FILES = PROGRAMS = $(noinst_PROGRAMS) am__objects_1 = app.$(OBJEXT) as.$(OBJEXT) atof-generic.$(OBJEXT) \ - cond.$(OBJEXT) depend.$(OBJEXT) dwarf2dbg.$(OBJEXT) \ - dw2gencfi.$(OBJEXT) ecoff.$(OBJEXT) ehopt.$(OBJEXT) \ - expr.$(OBJEXT) flonum-copy.$(OBJEXT) flonum-konst.$(OBJEXT) \ - flonum-mult.$(OBJEXT) frags.$(OBJEXT) hash.$(OBJEXT) \ - input-file.$(OBJEXT) input-scrub.$(OBJEXT) listing.$(OBJEXT) \ - literal.$(OBJEXT) macro.$(OBJEXT) messages.$(OBJEXT) \ - output-file.$(OBJEXT) read.$(OBJEXT) remap.$(OBJEXT) \ - sb.$(OBJEXT) stabs.$(OBJEXT) subsegs.$(OBJEXT) \ + compress-debug.$(OBJEXT) cond.$(OBJEXT) depend.$(OBJEXT) \ + dwarf2dbg.$(OBJEXT) dw2gencfi.$(OBJEXT) ecoff.$(OBJEXT) \ + ehopt.$(OBJEXT) expr.$(OBJEXT) flonum-copy.$(OBJEXT) \ + flonum-konst.$(OBJEXT) flonum-mult.$(OBJEXT) frags.$(OBJEXT) \ + hash.$(OBJEXT) input-file.$(OBJEXT) input-scrub.$(OBJEXT) \ + listing.$(OBJEXT) literal.$(OBJEXT) macro.$(OBJEXT) \ + messages.$(OBJEXT) output-file.$(OBJEXT) read.$(OBJEXT) \ + remap.$(OBJEXT) sb.$(OBJEXT) stabs.$(OBJEXT) subsegs.$(OBJEXT) \ symbols.$(OBJEXT) write.$(OBJEXT) am_as_new_OBJECTS = $(am__objects_1) as_new_OBJECTS = $(am_as_new_OBJECTS) @@ -311,6 +311,7 @@ GAS_CFILES = \ app.c \ as.c \ atof-generic.c \ + compress-debug.c \ cond.c \ depend.c \ dwarf2dbg.c \ @@ -345,6 +346,7 @@ HFILES = \ bignum.h \ bit_fix.h \ cgen.h \ + compress-debug.h \ dwarf2dbg.h \ dw2gencfi.h \ ecoff.h \ @@ -771,6 +773,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atof-vax.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bfin-parse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cgen.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compress-debug.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cond.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/depend.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dw2gencfi.Po@am__quote@ diff --git a/gas/as.c b/gas/as.c index d617b3398d3..e494fa5fe17 100644 --- a/gas/as.c +++ b/gas/as.c @@ -437,7 +437,9 @@ parse_args (int * pargc, char *** pargv) OPTION_AL, OPTION_HASH_TABLE_SIZE, OPTION_REDUCE_MEMORY_OVERHEADS, - OPTION_WARN_FATAL + OPTION_WARN_FATAL, + OPTION_COMPRESS_DEBUG, + OPTION_NOCOMPRESS_DEBUG /* When you add options here, check that they do not collide with OPTION_MD_BASE. See as.h. */ }; @@ -455,6 +457,8 @@ parse_args (int * pargc, char *** pargv) ,{"a", optional_argument, NULL, 'a'} /* Handle -al=. */ ,{"al", optional_argument, NULL, OPTION_AL} + ,{"compress-debug-sections", no_argument, NULL, OPTION_COMPRESS_DEBUG} + ,{"nocompress-debug-sections", no_argument, NULL, OPTION_NOCOMPRESS_DEBUG} ,{"debug-prefix-map", required_argument, NULL, OPTION_DEBUG_PREFIX_MAP} ,{"defsym", required_argument, NULL, OPTION_DEFSYM} ,{"dump-config", no_argument, NULL, OPTION_DUMPCONFIG} @@ -634,6 +638,14 @@ This program has absolutely no warranty.\n")); #endif exit (EXIT_SUCCESS); + case OPTION_COMPRESS_DEBUG: + flag_compress_debug = 1; + break; + + case OPTION_NOCOMPRESS_DEBUG: + flag_compress_debug = 0; + break; + case OPTION_DEBUG_PREFIX_MAP: add_debug_prefix_map (optarg); break; diff --git a/gas/as.h b/gas/as.h index 2b2562e85e3..7c163826d90 100644 --- a/gas/as.h +++ b/gas/as.h @@ -365,6 +365,9 @@ COMMON int flag_strip_local_absolute; /* True if we should generate a traditional format object file. */ COMMON int flag_traditional_format; +/* TRUE if debug sections should be compressed. */ +COMMON int flag_compress_debug; + /* TRUE if .note.GNU-stack section with SEC_CODE should be created */ COMMON int flag_execstack; diff --git a/gas/config.in b/gas/config.in index 55f4c9c609c..c63b1c6eddb 100644 --- a/gas/config.in +++ b/gas/config.in @@ -114,6 +114,9 @@ /* Define to 1 if you have the `unlink' function. */ #undef HAVE_UNLINK +/* Define to 1 if you have the header file. */ +#undef HAVE_ZLIB_H + /* Using i386 COFF? */ #undef I386COFF diff --git a/gas/configure b/gas/configure index b466d5fd9f6..530fa0d1e95 100755 --- a/gas/configure +++ b/gas/configure @@ -766,6 +766,7 @@ enable_werror enable_build_warnings enable_nls enable_maintainer_mode +with_zlib ' ac_precious_vars='build_alias host_alias @@ -1419,6 +1420,7 @@ Optional Packages: --with-pic try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-zlib include zlib support (auto/yes/no) default=auto Some influential environment variables: CC C compiler command @@ -11193,7 +11195,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11196 "configure" +#line 11198 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11299,7 +11301,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11302 "configure" +#line 11304 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -13984,6 +13986,92 @@ $as_echo "#define USE_BINARY_FOPEN 1" >>confdefs.h ;; esac +# Link in zlib if we can. This allows us to write compressed debug sections. + + # See if the user specified whether he wants zlib support or not. + +# Check whether --with-zlib was given. +if test "${with_zlib+set}" = set; then : + withval=$with_zlib; +else + with_zlib=auto +fi + + + if test "$with_zlib" != "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing zlibVersion" >&5 +$as_echo_n "checking for library containing zlibVersion... " >&6; } +if test "${ac_cv_search_zlibVersion+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char zlibVersion (); +int +main () +{ +return zlibVersion (); + ; + return 0; +} +_ACEOF +for ac_lib in '' z; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_zlibVersion=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_zlibVersion+set}" = set; then : + break +fi +done +if test "${ac_cv_search_zlibVersion+set}" = set; then : + +else + ac_cv_search_zlibVersion=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_zlibVersion" >&5 +$as_echo "$ac_cv_search_zlibVersion" >&6; } +ac_res=$ac_cv_search_zlibVersion +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + for ac_header in zlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" +if test "x$ac_cv_header_zlib_h" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ZLIB_H 1 +_ACEOF + +fi + +done + +fi + + if test "$with_zlib" = "yes" -a "$ac_cv_header_zlib_h" != "yes"; then + as_fn_error "zlib (libz) library was explicitly requested but not found" "$LINENO" 5 + fi + fi + + # Support for VMS timestamps via cross compile if test "$ac_cv_header_time_h" = yes; then diff --git a/gas/configure.in b/gas/configure.in index 4fbf292c21d..0d5e3e175c9 100644 --- a/gas/configure.in +++ b/gas/configure.in @@ -709,6 +709,9 @@ AC_CHECK_DECLS([vsnprintf]) BFD_BINARY_FOPEN +# Link in zlib if we can. This allows us to write compressed debug sections. +AM_ZLIB + # Support for VMS timestamps via cross compile if test "$ac_cv_header_time_h" = yes; then diff --git a/gas/write.c b/gas/write.c index a148b248d20..71ac63562c9 100644 --- a/gas/write.c +++ b/gas/write.c @@ -28,6 +28,7 @@ #include "output-file.h" #include "dwarf2dbg.h" #include "libbfd.h" +#include "compress-debug.h" #ifndef TC_ADJUST_RELOC_COUNT #define TC_ADJUST_RELOC_COUNT(FIX, COUNT) @@ -1288,6 +1289,194 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED) #endif } +static int +compress_frag (struct z_stream_s *strm, const char *contents, int in_size, + fragS **last_newf, struct obstack *ob) +{ + int out_size; + int total_out_size = 0; + fragS *f = *last_newf; + char *next_out; + int avail_out; + + /* Call the compression routine repeatedly until it has finished + processing the frag. */ + while (in_size > 0) + { + /* Reserve all the space available in the current chunk. + If none is available, start a new frag. */ + avail_out = obstack_room (ob); + if (avail_out <= 0) + { + obstack_finish (ob); + f = frag_alloc (ob); + f->fr_type = rs_fill; + (*last_newf)->fr_next = f; + *last_newf = f; + avail_out = obstack_room (ob); + } + if (avail_out <= 0) + as_fatal (_("can't extend frag")); + next_out = obstack_next_free (ob); + obstack_blank_fast (ob, avail_out); + out_size = compress_data (strm, &contents, &in_size, + &next_out, &avail_out); + if (out_size < 0) + return -1; + + f->fr_fix += out_size; + total_out_size += out_size; + + /* Return unused space. */ + if (avail_out > 0) + obstack_blank_fast (ob, -avail_out); + } + + return total_out_size; +} + +static void +compress_debug (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED) +{ + segment_info_type *seginfo = seg_info (sec); + fragS *f; + fragS *first_newf; + fragS *last_newf; + struct obstack *ob = &seginfo->frchainP->frch_obstack; + bfd_size_type uncompressed_size = (bfd_size_type) sec->size; + bfd_size_type compressed_size; + const char *section_name; + char *compressed_name; + char *header; + struct z_stream_s *strm; + int x; + + if (seginfo == NULL + || !(bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS) + || (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)) + return; + + section_name = bfd_get_section_name (stdoutput, sec); + if (strncmp (section_name, ".debug_", 7) != 0) + return; + + strm = compress_init (); + if (strm == NULL) + return; + + /* Create a new frag to contain the "ZLIB" header. */ + first_newf = frag_alloc (ob); + if (obstack_room (ob) < 12) + first_newf = frag_alloc (ob); + if (obstack_room (ob) < 12) + as_fatal (_("can't extend frag %u chars"), 12); + last_newf = first_newf; + obstack_blank_fast (ob, 12); + last_newf->fr_type = rs_fill; + last_newf->fr_fix = 12; + header = last_newf->fr_literal; + memcpy (header, "ZLIB", 4); + header[11] = uncompressed_size; uncompressed_size >>= 8; + header[10] = uncompressed_size; uncompressed_size >>= 8; + header[9] = uncompressed_size; uncompressed_size >>= 8; + header[8] = uncompressed_size; uncompressed_size >>= 8; + header[7] = uncompressed_size; uncompressed_size >>= 8; + header[6] = uncompressed_size; uncompressed_size >>= 8; + header[5] = uncompressed_size; uncompressed_size >>= 8; + header[4] = uncompressed_size; + compressed_size = 12; + + /* Stream the frags through the compression engine, adding new frags + as necessary to accomodate the compressed output. */ + for (f = seginfo->frchainP->frch_root; + f; + f = f->fr_next) + { + offsetT fill_size; + char *fill_literal; + offsetT count; + int out_size; + + gas_assert (f->fr_type == rs_fill); + if (f->fr_fix) + { + out_size = compress_frag (strm, f->fr_literal, f->fr_fix, + &last_newf, ob); + if (out_size < 0) + return; + compressed_size += out_size; + } + fill_literal = f->fr_literal + f->fr_fix; + fill_size = f->fr_var; + count = f->fr_offset; + gas_assert (count >= 0); + if (fill_size && count) + { + while (count--) + { + out_size = compress_frag (strm, fill_literal, (int) fill_size, + &last_newf, ob); + if (out_size < 0) + return; + compressed_size += out_size; + } + } + } + + /* Flush the compression state. */ + for (;;) + { + int avail_out; + char *next_out; + int out_size; + + /* Reserve all the space available in the current chunk. + If none is available, start a new frag. */ + avail_out = obstack_room (ob); + if (avail_out <= 0) + { + fragS *newf; + + obstack_finish (ob); + newf = frag_alloc (ob); + newf->fr_type = rs_fill; + last_newf->fr_next = newf; + last_newf = newf; + avail_out = obstack_room (ob); + } + if (avail_out <= 0) + as_fatal (_("can't extend frag")); + next_out = obstack_next_free (ob); + obstack_blank_fast (ob, avail_out); + x = compress_finish (strm, &next_out, &avail_out, &out_size); + if (x < 0) + return; + + last_newf->fr_fix += out_size; + compressed_size += out_size; + + /* Return unused space. */ + if (avail_out > 0) + obstack_blank_fast (ob, -avail_out); + + if (x == 0) + break; + } + + /* Replace the uncompressed frag list with the compressed frag list. */ + seginfo->frchainP->frch_root = first_newf; + seginfo->frchainP->frch_last = last_newf; + + /* Update the section size and its name. */ + x = bfd_set_section_size (abfd, sec, compressed_size); + gas_assert (x); + compressed_name = (char *) xmalloc (strlen (section_name) + 2); + compressed_name[0] = '.'; + compressed_name[1] = 'z'; + strcpy (compressed_name + 2, section_name + 1); + bfd_section_name (stdoutput, sec) = compressed_name; +} + static void write_contents (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, @@ -1912,6 +2101,13 @@ write_object_file (void) obj_frob_file_after_relocs (); #endif + /* Once all relocations have been written, we can compress the + contents of the debug sections. This needs to be done before + we start writing any sections, because it will affect the file + layout, which is fixed once we start writing contents. */ + if (flag_compress_debug) + bfd_map_over_sections (stdoutput, compress_debug, (char *) 0); + bfd_map_over_sections (stdoutput, write_contents, (char *) 0); } -- 2.39.2