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.
This commit is contained in:
Cary Coutant 2010-07-03 20:52:24 +00:00
parent 3a5530eaab
commit 0acf065b19
15 changed files with 441 additions and 58 deletions

View File

@ -1,3 +1,10 @@
2010-07-03 Cary Coutant <ccoutant@google.com>
* 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 <amodra@gmail.com> 2010-07-01 Alan Modra <amodra@gmail.com>
* elf64-ppc.c (ppc64_elf_edit_toc): Use SYMBOL_CALLS_LOCAL rather * elf64-ppc.c (ppc64_elf_edit_toc): Use SYMBOL_CALLS_LOCAL rather

View File

@ -1,4 +1,4 @@
/* ELF attributes support (based on ARM EABI attributes). /* Compressed section support (intended for debug sections).
Copyright 2008, 2010 Copyright 2008, 2010
Free Software Foundation, Inc. Free Software Foundation, Inc.

View File

@ -405,6 +405,54 @@ lookup_info_hash_table (struct info_hash_table *hash_table, const char *key)
return entry ? entry->head : NULL; 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 /* Read a section into its appropriate place in the dwarf2_debug
struct (indicated by SECTION_BUFFER and SECTION_SIZE). If SYMS is struct (indicated by SECTION_BUFFER and SECTION_SIZE). If SYMS is
not NULL, use bfd_simple_get_relocated_section_contents to read the 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; *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 (! read_and_uncompress_section (abfd, msec, section_is_compressed,
{ syms, section_buffer, section_size))
if (! bfd_uncompress_section_contents (section_buffer, section_size)) return FALSE;
{
(*_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 /* 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_size_type size = msec->size;
bfd_byte *buffer, *tmp; bfd_byte *buffer, *tmp;
bfd_boolean is_compressed =
strcmp (msec->name, DWARF2_COMPRESSED_DEBUG_INFO) == 0;
if (size == 0) if (size == 0)
continue; continue;
buffer = (bfd_simple_get_relocated_section_contents if (! read_and_uncompress_section (debug_bfd, msec,
(debug_bfd, msec, NULL, symbols)); is_compressed, symbols,
if (! buffer) &buffer, &size))
goto done; 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, tmp = (bfd_byte *) bfd_realloc (stash->info_ptr_memory,
total_size + size); total_size + size);
if (tmp == NULL) if (tmp == NULL)

View File

@ -1,3 +1,10 @@
2010-07-03 Cary Coutant <ccoutant@google.com>
* 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 <amodra@gmail.com> 2010-06-29 Alan Modra <amodra@gmail.com>
PR binutils/3166 PR binutils/3166

View File

@ -2205,14 +2205,8 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
section->size = bfd_get_section_size (sec); section->size = bfd_get_section_size (sec);
section->start = (unsigned char *) xmalloc (section->size); section->start = (unsigned char *) xmalloc (section->size);
if (is_relocatable && debug_displays [debug].relocate) ret = bfd_get_section_contents (abfd, sec, section->start, 0,
ret = bfd_simple_get_relocated_section_contents (abfd, section->size);
sec,
section->start,
syms) != NULL;
else
ret = bfd_get_section_contents (abfd, sec, section->start, 0,
section->size);
if (! ret) if (! ret)
{ {
@ -2234,6 +2228,30 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
section->size = size; 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; return 1;
} }

View File

@ -9962,8 +9962,11 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
return 0; return 0;
if (section_is_compressed) if (section_is_compressed)
if (! uncompress_section_contents (&section->start, &section->size)) {
return 0; if (! uncompress_section_contents (&section->start, &section->size))
return 0;
sec->sh_size = section->size;
}
if (debug_displays [debug].relocate) if (debug_displays [debug].relocate)
apply_relocations ((FILE *) file, sec, section->start); apply_relocations ((FILE *) file, sec, section->start);

View File

@ -1,3 +1,21 @@
2010-07-03 Cary Coutant <ccoutant@google.com>
* 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 <schwab@linux-m68k.org> 2010-07-03 Andreas Schwab <schwab@linux-m68k.org>
* config/tc-ppc.c (ppc_set_cpu): Cast PPC_OPCODE_xxx to ppc_cpu_t * config/tc-ppc.c (ppc_set_cpu): Cast PPC_OPCODE_xxx to ppc_cpu_t

View File

@ -43,6 +43,7 @@ GAS_CFILES = \
app.c \ app.c \
as.c \ as.c \
atof-generic.c \ atof-generic.c \
compress-debug.c \
cond.c \ cond.c \
depend.c \ depend.c \
dwarf2dbg.c \ dwarf2dbg.c \
@ -78,6 +79,7 @@ HFILES = \
bignum.h \ bignum.h \
bit_fix.h \ bit_fix.h \
cgen.h \ cgen.h \
compress-debug.h \
dwarf2dbg.h \ dwarf2dbg.h \
dw2gencfi.h \ dw2gencfi.h \
ecoff.h \ ecoff.h \

View File

@ -73,14 +73,14 @@ CONFIG_CLEAN_FILES = gdb.ini .gdbinit po/Makefile.in
CONFIG_CLEAN_VPATH_FILES = CONFIG_CLEAN_VPATH_FILES =
PROGRAMS = $(noinst_PROGRAMS) PROGRAMS = $(noinst_PROGRAMS)
am__objects_1 = app.$(OBJEXT) as.$(OBJEXT) atof-generic.$(OBJEXT) \ am__objects_1 = app.$(OBJEXT) as.$(OBJEXT) atof-generic.$(OBJEXT) \
cond.$(OBJEXT) depend.$(OBJEXT) dwarf2dbg.$(OBJEXT) \ compress-debug.$(OBJEXT) cond.$(OBJEXT) depend.$(OBJEXT) \
dw2gencfi.$(OBJEXT) ecoff.$(OBJEXT) ehopt.$(OBJEXT) \ dwarf2dbg.$(OBJEXT) dw2gencfi.$(OBJEXT) ecoff.$(OBJEXT) \
expr.$(OBJEXT) flonum-copy.$(OBJEXT) flonum-konst.$(OBJEXT) \ ehopt.$(OBJEXT) expr.$(OBJEXT) flonum-copy.$(OBJEXT) \
flonum-mult.$(OBJEXT) frags.$(OBJEXT) hash.$(OBJEXT) \ flonum-konst.$(OBJEXT) flonum-mult.$(OBJEXT) frags.$(OBJEXT) \
input-file.$(OBJEXT) input-scrub.$(OBJEXT) listing.$(OBJEXT) \ hash.$(OBJEXT) input-file.$(OBJEXT) input-scrub.$(OBJEXT) \
literal.$(OBJEXT) macro.$(OBJEXT) messages.$(OBJEXT) \ listing.$(OBJEXT) literal.$(OBJEXT) macro.$(OBJEXT) \
output-file.$(OBJEXT) read.$(OBJEXT) remap.$(OBJEXT) \ messages.$(OBJEXT) output-file.$(OBJEXT) read.$(OBJEXT) \
sb.$(OBJEXT) stabs.$(OBJEXT) subsegs.$(OBJEXT) \ remap.$(OBJEXT) sb.$(OBJEXT) stabs.$(OBJEXT) subsegs.$(OBJEXT) \
symbols.$(OBJEXT) write.$(OBJEXT) symbols.$(OBJEXT) write.$(OBJEXT)
am_as_new_OBJECTS = $(am__objects_1) am_as_new_OBJECTS = $(am__objects_1)
as_new_OBJECTS = $(am_as_new_OBJECTS) as_new_OBJECTS = $(am_as_new_OBJECTS)
@ -311,6 +311,7 @@ GAS_CFILES = \
app.c \ app.c \
as.c \ as.c \
atof-generic.c \ atof-generic.c \
compress-debug.c \
cond.c \ cond.c \
depend.c \ depend.c \
dwarf2dbg.c \ dwarf2dbg.c \
@ -345,6 +346,7 @@ HFILES = \
bignum.h \ bignum.h \
bit_fix.h \ bit_fix.h \
cgen.h \ cgen.h \
compress-debug.h \
dwarf2dbg.h \ dwarf2dbg.h \
dw2gencfi.h \ dw2gencfi.h \
ecoff.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)/atof-vax.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bfin-parse.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)/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)/cond.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/depend.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@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dw2gencfi.Po@am__quote@

View File

@ -437,7 +437,9 @@ parse_args (int * pargc, char *** pargv)
OPTION_AL, OPTION_AL,
OPTION_HASH_TABLE_SIZE, OPTION_HASH_TABLE_SIZE,
OPTION_REDUCE_MEMORY_OVERHEADS, 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 /* When you add options here, check that they do
not collide with OPTION_MD_BASE. See as.h. */ not collide with OPTION_MD_BASE. See as.h. */
}; };
@ -455,6 +457,8 @@ parse_args (int * pargc, char *** pargv)
,{"a", optional_argument, NULL, 'a'} ,{"a", optional_argument, NULL, 'a'}
/* Handle -al=<FILE>. */ /* Handle -al=<FILE>. */
,{"al", optional_argument, NULL, OPTION_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} ,{"debug-prefix-map", required_argument, NULL, OPTION_DEBUG_PREFIX_MAP}
,{"defsym", required_argument, NULL, OPTION_DEFSYM} ,{"defsym", required_argument, NULL, OPTION_DEFSYM}
,{"dump-config", no_argument, NULL, OPTION_DUMPCONFIG} ,{"dump-config", no_argument, NULL, OPTION_DUMPCONFIG}
@ -634,6 +638,14 @@ This program has absolutely no warranty.\n"));
#endif #endif
exit (EXIT_SUCCESS); 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: case OPTION_DEBUG_PREFIX_MAP:
add_debug_prefix_map (optarg); add_debug_prefix_map (optarg);
break; break;

View File

@ -365,6 +365,9 @@ COMMON int flag_strip_local_absolute;
/* True if we should generate a traditional format object file. */ /* True if we should generate a traditional format object file. */
COMMON int flag_traditional_format; 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 */ /* TRUE if .note.GNU-stack section with SEC_CODE should be created */
COMMON int flag_execstack; COMMON int flag_execstack;

View File

@ -114,6 +114,9 @@
/* Define to 1 if you have the `unlink' function. */ /* Define to 1 if you have the `unlink' function. */
#undef HAVE_UNLINK #undef HAVE_UNLINK
/* Define to 1 if you have the <zlib.h> header file. */
#undef HAVE_ZLIB_H
/* Using i386 COFF? */ /* Using i386 COFF? */
#undef I386COFF #undef I386COFF

92
gas/configure vendored
View File

@ -766,6 +766,7 @@ enable_werror
enable_build_warnings enable_build_warnings
enable_nls enable_nls
enable_maintainer_mode enable_maintainer_mode
with_zlib
' '
ac_precious_vars='build_alias ac_precious_vars='build_alias
host_alias host_alias
@ -1419,6 +1420,7 @@ Optional Packages:
--with-pic try to use only PIC/non-PIC objects [default=use --with-pic try to use only PIC/non-PIC objects [default=use
both] both]
--with-gnu-ld assume the C compiler uses GNU ld [default=no] --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: Some influential environment variables:
CC C compiler command CC C compiler command
@ -11193,7 +11195,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF cat > conftest.$ac_ext <<_LT_EOF
#line 11196 "configure" #line 11198 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
@ -11299,7 +11301,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF cat > conftest.$ac_ext <<_LT_EOF
#line 11302 "configure" #line 11304 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
@ -13984,6 +13986,92 @@ $as_echo "#define USE_BINARY_FOPEN 1" >>confdefs.h
;; ;;
esac 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 # Support for VMS timestamps via cross compile
if test "$ac_cv_header_time_h" = yes; then if test "$ac_cv_header_time_h" = yes; then

View File

@ -709,6 +709,9 @@ AC_CHECK_DECLS([vsnprintf])
BFD_BINARY_FOPEN 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 # Support for VMS timestamps via cross compile
if test "$ac_cv_header_time_h" = yes; then if test "$ac_cv_header_time_h" = yes; then

View File

@ -28,6 +28,7 @@
#include "output-file.h" #include "output-file.h"
#include "dwarf2dbg.h" #include "dwarf2dbg.h"
#include "libbfd.h" #include "libbfd.h"
#include "compress-debug.h"
#ifndef TC_ADJUST_RELOC_COUNT #ifndef TC_ADJUST_RELOC_COUNT
#define TC_ADJUST_RELOC_COUNT(FIX, COUNT) #define TC_ADJUST_RELOC_COUNT(FIX, COUNT)
@ -1288,6 +1289,194 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
#endif #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 static void
write_contents (bfd *abfd ATTRIBUTE_UNUSED, write_contents (bfd *abfd ATTRIBUTE_UNUSED,
asection *sec, asection *sec,
@ -1912,6 +2101,13 @@ write_object_file (void)
obj_frob_file_after_relocs (); obj_frob_file_after_relocs ();
#endif #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); bfd_map_over_sections (stdoutput, write_contents, (char *) 0);
} }