public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [patch] Add --compress-debug-sections option to gas
@ 2010-06-28 21:39 Cary Coutant
  2010-06-29  8:08 ` Alan Modra
  2010-07-09 19:51 ` H.J. Lu
  0 siblings, 2 replies; 34+ messages in thread
From: Cary Coutant @ 2010-06-28 21:39 UTC (permalink / raw)
  To: Binutils

[-- Attachment #1: Type: text/plain, Size: 2764 bytes --]

A couple of years ago, Craig Silverstein submitted a patch to add
support for compressed debug sections generated by the linker:

  http://sourceware.org/ml/binutils/2008-06/msg00203.html

The attached patch extends this support to the assembler, adding a new
--compress-debug-sections option to gas, and adding the necessary
support (and fixing a couple of bugs in the original patch) for
reading compressed sections in relocatables to bfd, objdump, and
readelf.

Tested on x86_64 by compiling with and without
-Wa,--compress-debug-sections, and comparing readelf -w output and
objdump -W output. No regressions in the test suite.

A patch for gold to read files with compressed debug sections is in progress.

I have to admit that I'm not happy with a couple of things:

(1) In both bfd/dwarf2.c and binutils/objdump.c, in order to
uncompress the section before relocating it, I call
bfd_get_section_contents() to get the unrelocated section contents,
then decompress the contents and put a pointer to the decompressed
contents in sec->contents, setting the SEC_IN_MEMORY flag so that
bfd_simple_get_relocated_section_contents() would not go read the
section again. I couldn't find a simpler way to apply relocations
after decompression.

(2) In gas/write.c, I used a similar trick to signal write_contents()
that the frags had already been collected and compressed. An
alternative I considered was to simply replace the frag list with a
single frag containing the entire compressed section contents, but
that seemed a bit more complicated.

Advice on these issues is welcome.

-cary

p.s. I'm not sure why my regenerated libbfd.h is different from the
original -- nothing changed except for parameters to
bfd_generic_get_relocated_section_contents() that used to be unnamed.
Did "make headers" change behavior since the last time that file was
regenerated? Should I just leave this out of the patch?


bfd/ChangeLog:

        * bfd-in2.h: Regenerate.
        * compress.c (bfd_compress_section_contents): New function.
        * dwarf2.c (read_and_uncompress_section): New function.
        (read_section): Call it.
        (find_line): Likewise.
        * libbfd.h: Regenerate.

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:

        * as.c (parse_args): Add --compress-debug-sections and
        --nocompress-debug-sections.
        * as.h (flag_compress_debug): New variable.
        * write.c (compress_debug): New function.
        (write_contents): Check for uncompressed section.
        (write_object_file): Compress debug sections if requested.

[-- Attachment #2: compress-debug-patch.txt --]
[-- Type: text/plain, Size: 15150 bytes --]

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 5c42128..bd648ce 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -5821,6 +5821,9 @@ bfd_byte *bfd_simple_get_relocated_section_contents
 bfd_boolean bfd_uncompress_section_contents
    (bfd_byte **buffer, bfd_size_type *size);
 
+bfd_boolean bfd_compress_section_contents
+   (bfd_byte **buffer, bfd_size_type *size);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/bfd/compress.c b/bfd/compress.c
index 5b6ee0e..7b334a0 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
    Free Software Foundation, Inc.
 
@@ -120,3 +120,73 @@ bfd_uncompress_section_contents (bfd_byte **buffer, bfd_size_type *size)
   return FALSE;
 #endif  /* HAVE_ZLIB_H */
 }
+
+/*
+FUNCTION
+	bfd_compress_section_contents
+
+SYNOPSIS
+	bfd_boolean bfd_compress_section_contents
+	  (bfd_byte **buffer, bfd_size_type *size);
+
+DESCRIPTION
+
+	Compresses a section using zlib, in place.  At the call to this
+	function, *@var{buffer} and *@var{size} should point to the section
+	contents to be compressed.  At the end of the function, *@var{buffer}
+	and *@var{size} will point to the compressed contents.  This function
+	assumes *BUFFER was allocated using bfd_malloc() or equivalent.  If
+	zlib is not installed on this machine, the input is unmodified.
+
+        Returns @code{FALSE} if unable to compress successfully; in that case
+        the input is unmodified.  Otherwise, returns @code{TRUE}.
+*/
+
+bfd_boolean
+bfd_compress_section_contents (bfd_byte **buffer, bfd_size_type *size)
+{
+#ifndef HAVE_ZLIB_H
+  /* These are just to quiet gcc.  */
+  buffer = 0;
+  size = 0;
+  return FALSE;
+#else
+  bfd_size_type uncompressed_size = *size;
+  bfd_byte *uncompressed_buffer = *buffer;
+  bfd_size_type compressed_size;
+  bfd_byte *compressed_buffer;
+  int rc;
+  bfd_size_type header_size = 12;
+
+  compressed_size = compressBound (uncompressed_size) + header_size;
+  compressed_buffer = (bfd_byte *) bfd_malloc (compressed_size);
+
+  rc = compress ((Bytef*) compressed_buffer + header_size,
+                 &compressed_size,
+                 (const Bytef*) uncompressed_buffer,
+                 uncompressed_size);
+  if (rc != Z_OK)
+    {
+      free (compressed_buffer);
+      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[4] = uncompressed_size >> 56;
+  compressed_buffer[5] = uncompressed_size >> 48;
+  compressed_buffer[6] = uncompressed_size >> 40;
+  compressed_buffer[7] = uncompressed_size >> 32;
+  compressed_buffer[8] = uncompressed_size >> 24;
+  compressed_buffer[9] = uncompressed_size >> 16;
+  compressed_buffer[10] = uncompressed_size >> 8;
+  compressed_buffer[11] = uncompressed_size;
+  compressed_size += header_size;
+
+  free (uncompressed_buffer);
+  *buffer = compressed_buffer;
+  *size = compressed_size;
+  return TRUE;
+#endif  /* HAVE_ZLIB_H */
+}
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index 9b194aa..ffe1108 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/bfd/libbfd.h b/bfd/libbfd.h
index 233891c..3da79d9 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -2243,12 +2243,12 @@ bfd_boolean bfd_generic_merge_sections
    (bfd *, struct bfd_link_info *);
 
 bfd_byte *bfd_generic_get_relocated_section_contents
-   (bfd *,
-    struct bfd_link_info *,
-    struct bfd_link_order *,
-    bfd_byte *,
-    bfd_boolean,
-    asymbol **);
+   (bfd *abfd,
+    struct bfd_link_info *link_info,
+    struct bfd_link_order *link_order,
+    bfd_byte *data,
+    bfd_boolean relocatable,
+    asymbol **symbols);
 
 /* Extracted from archures.c.  */
 extern const bfd_arch_info_type bfd_default_arch_struct;
diff --git a/binutils/objdump.c b/binutils/objdump.c
index 2a419b7..f94dee9 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 d4f47ca..1c3cb8b 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 (&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)
     apply_relocations ((FILE *) file, sec, section->start);
diff --git a/gas/as.c b/gas/as.c
index d617b33..e494fa5 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=<FILE>.  */
     ,{"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 2b2562e..7c16382 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/write.c b/gas/write.c
index a148b24..4fc27fc 100644
--- a/gas/write.c
+++ b/gas/write.c
@@ -1289,6 +1289,77 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
 }
 
 static void
+compress_debug (bfd *abfd ATTRIBUTE_UNUSED,
+		asection *sec,
+		void *xxx ATTRIBUTE_UNUSED)
+{
+  segment_info_type *seginfo = seg_info (sec);
+  addressT offset = 0;
+  fragS *f;
+  bfd_size_type section_size = (bfd_size_type) sec->size;
+  bfd_byte *contents;
+  const char *section_name;
+  char *compressed_name;
+  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;
+
+  /* Gather the frags into a contiguous buffer.  */
+  contents = (bfd_byte *) xmalloc (section_size);
+  for (f = seginfo->frchainP->frch_root;
+       f;
+       f = f->fr_next)
+    {
+      addressT fill_size;
+      char *fill_literal;
+      offsetT count;
+
+      gas_assert (f->fr_type == rs_fill);
+      if (f->fr_fix)
+	{
+	  memcpy (contents + offset, f->fr_literal, (size_t) f->fr_fix);
+	  offset += f->fr_fix;
+	}
+      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--)
+	    {
+	      memcpy (contents + offset, fill_literal, (size_t) fill_size);
+	      offset += fill_size;
+	    }
+	}
+    }
+
+  /* Compress the buffer.  */
+  if (!bfd_compress_section_contents (&contents, &section_size))
+    return;
+
+  /* Store the compressed contents in the section.  */
+  sec->contents = contents;
+  sec->flags |= SEC_IN_MEMORY;
+  x = bfd_set_section_size (abfd, sec, section_size);
+  gas_assert (x);
+
+  /* Change the section name.  */
+  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,
 		void *xxx ATTRIBUTE_UNUSED)
@@ -1297,6 +1368,20 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
   addressT offset = 0;
   fragS *f;
 
+  if (bfd_get_section_flags (abfd, sec) & SEC_IN_MEMORY)
+    {
+      /* We already gathered the frags and compressed the data.  */
+      int x;
+
+      x = bfd_set_section_contents (stdoutput, sec, sec->contents,
+				    (file_ptr) offset,
+				    (bfd_size_type) sec->size);
+      if (!x)
+	as_fatal (_("can't write %s: %s"), stdoutput->filename,
+		  bfd_errmsg (bfd_get_error ()));
+      return;
+    }
+
   /* Write out the frags.  */
   if (seginfo == NULL
       || !(bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS))
@@ -1912,6 +1997,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);
 }
 

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-06-28 21:39 [patch] Add --compress-debug-sections option to gas Cary Coutant
@ 2010-06-29  8:08 ` Alan Modra
  2010-06-29 18:42   ` Cary Coutant
  2010-07-02  1:03   ` Cary Coutant
  2010-07-09 19:51 ` H.J. Lu
  1 sibling, 2 replies; 34+ messages in thread
From: Alan Modra @ 2010-06-29  8:08 UTC (permalink / raw)
  To: Cary Coutant; +Cc: Binutils

On Mon, Jun 28, 2010 at 02:39:15PM -0700, Cary Coutant wrote:
> p.s. I'm not sure why my regenerated libbfd.h is different from the
> original -- nothing changed except for parameters to
> bfd_generic_get_relocated_section_contents() that used to be unnamed.

Someone hand edited the file.  Now fixed.

> +bfd_boolean
> +bfd_compress_section_contents (bfd_byte **buffer, bfd_size_type *size)
> +{
> +#ifndef HAVE_ZLIB_H
> +  /* These are just to quiet gcc.  */
> +  buffer = 0;
> +  size = 0;

Except they don't quiet gcc-4.6.  Just add ATTRIBUTE_UNUSED to the params.

> +  compressed_buffer[4] = uncompressed_size >> 56;

This is going to warn and thus break the build when bfd_size_type is
32-bits, as can happen on a 32-bit host supporting 32-bit targets.

> @@ -1297,6 +1368,20 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
>    addressT offset = 0;
>    fragS *f;
>  
> +  if (bfd_get_section_flags (abfd, sec) & SEC_IN_MEMORY)

SEC_IN_MEMORY isn't sufficient.  Other sections will be SEC_IN_MEMORY
too, eg. SHT_GROUP sections.  I think your alternate approach of
twiddling the frag list is indicated.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-06-29  8:08 ` Alan Modra
@ 2010-06-29 18:42   ` Cary Coutant
  2010-07-02  1:03   ` Cary Coutant
  1 sibling, 0 replies; 34+ messages in thread
From: Cary Coutant @ 2010-06-29 18:42 UTC (permalink / raw)
  To: Cary Coutant, Binutils

>> +bfd_boolean
>> +bfd_compress_section_contents (bfd_byte **buffer, bfd_size_type *size)
>> +{
>> +#ifndef HAVE_ZLIB_H
>> +  /* These are just to quiet gcc.  */
>> +  buffer = 0;
>> +  size = 0;
>
> Except they don't quiet gcc-4.6.  Just add ATTRIBUTE_UNUSED to the params.

Good idea, thanks.

>> +  compressed_buffer[4] = uncompressed_size >> 56;
>
> This is going to warn and thus break the build when bfd_size_type is
> 32-bits, as can happen on a 32-bit host supporting 32-bit targets.

OK, I'll fix it to fill in the buffer from the other direction,
shifting 8 bits at a time.

>> @@ -1297,6 +1368,20 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
>>    addressT offset = 0;
>>    fragS *f;
>>
>> +  if (bfd_get_section_flags (abfd, sec) & SEC_IN_MEMORY)
>
> SEC_IN_MEMORY isn't sufficient.  Other sections will be SEC_IN_MEMORY
> too, eg. SHT_GROUP sections.  I think your alternate approach of
> twiddling the frag list is indicated.

OK, I'll try that.

Thanks for the review!

-cary

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-06-29  8:08 ` Alan Modra
  2010-06-29 18:42   ` Cary Coutant
@ 2010-07-02  1:03   ` Cary Coutant
  2010-07-02  2:29     ` Alan Modra
  2010-07-14  1:02     ` H.J. Lu
  1 sibling, 2 replies; 34+ messages in thread
From: Cary Coutant @ 2010-07-02  1:03 UTC (permalink / raw)
  To: Binutils

[-- Attachment #1: Type: text/plain, Size: 1878 bytes --]

> SEC_IN_MEMORY isn't sufficient.  Other sections will be SEC_IN_MEMORY
> too, eg. SHT_GROUP sections.  I think your alternate approach of
> twiddling the frag list is indicated.

Here's an updated patch that builds a new frag list. Since a frag
requires the data to follow the struct immediately, it didn't work
with the nice clean interface I added to bfd. It did lead to a more
efficient way of compressing, however: I now just stream each frag
through the compression engine, building new compressed frags as the
compressed data comes out, using the same obstack. At the end, I
replace the old frag list with the new one. I had to move the
zlib-specific code into a separate source file, because I can't
include as.h and zlib.h in the same file.

-cary


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_debug): New function.
        (write_object_file): Compress debug sections if requested.

[-- Attachment #2: compress-debug-patch-2.txt --]
[-- Type: text/plain, Size: 26193 bytes --]

diff --git a/bfd/compress.c b/bfd/compress.c
index 5b6ee0e..323694c 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
    Free Software Foundation, Inc.
 
@@ -51,12 +51,10 @@ DESCRIPTION
 */
 
 bfd_boolean
-bfd_uncompress_section_contents (bfd_byte **buffer, bfd_size_type *size)
+bfd_uncompress_section_contents (bfd_byte **buffer ATTRIBUTE_UNUSED,
+				 bfd_size_type *size ATTRIBUTE_UNUSED)
 {
 #ifndef HAVE_ZLIB_H
-  /* These are just to quiet gcc.  */
-  buffer = 0;
-  size = 0;
   return FALSE;
 #else
   bfd_size_type compressed_size = *size;
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index 9b194aa..ffe1108 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/objdump.c b/binutils/objdump.c
index 2a419b7..f94dee9 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 d4f47ca..1c3cb8b 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 (&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)
     apply_relocations ((FILE *) file, sec, section->start);
diff --git a/gas/Makefile.am b/gas/Makefile.am
index 36ae957..f2c0fe8 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 5b3521b..0487170 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 \
@@ -773,6 +775,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 d617b33..e494fa5 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=<FILE>.  */
     ,{"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 2b2562e..7c16382 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/compress-debug.c b/gas/compress-debug.c
new file mode 100644
index 0000000..76dcc6e
--- /dev/null
+++ b/gas/compress-debug.c
@@ -0,0 +1,123 @@
+/* compress-debug.c - compress debug sections
+   Copyright 2010 Free Software Foundation, Inc.
+
+   This file is part of GAS, the GNU Assembler.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GAS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#include <stdio.h>
+
+#include "ansidecl.h"
+#include "obstack.h"
+
+#include "config.h"
+#include "compress-debug.h"
+
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
+
+/* Initialize the compression engine.  */
+struct z_stream_s *
+compress_init (void)
+{
+#ifndef HAVE_ZLIB_H
+  return NULL;
+#else
+  static struct z_stream_s strm;
+
+  strm.zalloc = NULL;
+  strm.zfree = NULL;
+  strm.opaque = NULL;
+  deflateInit (&strm, Z_DEFAULT_COMPRESSION);
+  return &strm;
+#endif /* HAVE_ZLIB_H */
+}
+
+/* Stream the contents of a frag to the compression engine.  Output
+   from the engine goes into the current frag on the obstack.  */
+int
+compress_frag (struct z_stream_s *strm ATTRIBUTE_UNUSED,
+	       char *contents ATTRIBUTE_UNUSED,
+	       int in_size ATTRIBUTE_UNUSED,
+	       struct obstack *ob ATTRIBUTE_UNUSED)
+{
+#ifndef HAVE_ZLIB_H
+  return -1;
+#else
+  int out_size = 0;
+  int room;
+  int x;
+
+  strm->next_in = (Bytef *) contents;
+  strm->avail_in = in_size;
+
+  /* Call the deflate routine repeatedly until
+     it has finished processing the frag.  */
+  while (strm->avail_in > 0)
+    {
+      /* Reserve all the space we can.  If none is available, force
+	 the obstack to grow by at least as many bytes as we have
+	 remaining in the input stream.  */
+      room = obstack_room (ob);
+      if (room <= 0)
+	room = strm->avail_in;
+      obstack_blank (ob, room);
+      strm->next_out = (Bytef *) obstack_next_free (ob) - room;
+      strm->avail_out = room;
+      x = deflate (strm, Z_NO_FLUSH);
+      if (x != Z_OK)
+	return -1;
+
+      /* Return unused space.  */
+      if (strm->avail_out > 0)
+	obstack_blank (ob, -((int) strm->avail_out));
+      out_size += room - strm->avail_out;
+    }
+
+  return out_size;
+#endif /* HAVE_ZLIB_H */
+}
+
+/* Finish the compression and consume the remaining compressed output.  */
+int
+compress_finish (struct z_stream_s *strm ATTRIBUTE_UNUSED,
+		 struct obstack *ob ATTRIBUTE_UNUSED)
+{
+#ifndef HAVE_ZLIB_H
+  return -1;
+#else
+  int out_size = 0;
+  int x;
+
+  for (;;)
+    {
+      obstack_blank (ob, 64);
+      strm->next_out = (Bytef *) obstack_next_free (ob) - 64;
+      strm->avail_out = 64;
+      x = deflate (strm, Z_FINISH);
+      out_size += 64 - strm->avail_out;
+      if (strm->avail_out > 0)
+	obstack_blank (ob, -((int) strm->avail_out));
+      if (x == Z_STREAM_END)
+	break;
+      if (strm->avail_out != 0)
+        return -1;
+    }
+  deflateEnd (strm);
+  return out_size;
+#endif /* HAVE_ZLIB_H */
+}
diff --git a/gas/compress-debug.h b/gas/compress-debug.h
new file mode 100644
index 0000000..c89d4f4
--- /dev/null
+++ b/gas/compress-debug.h
@@ -0,0 +1,39 @@
+/* compress-debug.h - Header file for compressed debug sections.
+   Copyright 2010 Free Software Foundation, Inc.
+
+   This file is part of GAS, the GNU Assembler.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GAS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#ifndef COMPRESS_DEBUG_H
+#define COMPRESS_DEBUG_H
+
+struct z_stream_s;
+
+/* Initialize the compression engine.  */
+extern struct z_stream_s *
+compress_init (void);
+
+/* Stream the contents of a frag to the compression engine.  Output
+   from the engine goes into the current frag on the obstack.  */
+extern int
+compress_frag (struct z_stream_s *, char *, int, struct obstack *);
+
+/* Finish the compression and consume the remaining compressed output.  */
+extern int
+compress_finish (struct z_stream_s *, struct obstack *ob);
+
+#endif /* COMPRESS_DEBUG_H */
diff --git a/gas/config.in b/gas/config.in
index 55f4c9c..c63b1c6 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 <zlib.h> header file. */
+#undef HAVE_ZLIB_H
+
 /* Using i386 COFF? */
 #undef I386COFF
 
diff --git a/gas/configure b/gas/configure
index 1781b4e..530fa0d 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
@@ -1869,8 +1871,10 @@ $as_echo "$ac_res" >&6; }
 ac_fn_c_check_decl ()
 {
   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $2 is declared" >&5
-$as_echo_n "checking whether $2 is declared... " >&6; }
+  as_decl_name=`echo $2|sed 's/ *(.*//'`
+  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
 if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
   $as_echo_n "(cached) " >&6
 else
@@ -1880,8 +1884,12 @@ $4
 int
 main ()
 {
-#ifndef $2
-  (void) $2;
+#ifndef $as_decl_name
+#ifdef __cplusplus
+  (void) $as_decl_use;
+#else
+  (void) $as_decl_name;
+#endif
 #endif
 
   ;
@@ -11187,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 11190 "configure"
+#line 11198 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11293,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 11296 "configure"
+#line 11304 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -13978,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 4fbf292..0d5e3e1 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 a148b24..d2c61bb 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)
@@ -1289,6 +1290,127 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
 }
 
 static void
+compress_debug (bfd *abfd ATTRIBUTE_UNUSED,
+		asection *sec ATTRIBUTE_UNUSED,
+		void *xxx ATTRIBUTE_UNUSED)
+{
+  segment_info_type *seginfo = seg_info (sec);
+  fragS *f;
+  fragS *first_newf;
+  fragS *last_newf;
+  fragS *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.  */
+  obstack_blank (ob, SIZEOF_STRUCT_FRAG + 12);
+  first_newf = (fragS *) obstack_finish (ob);
+  memset (first_newf, 0, SIZEOF_STRUCT_FRAG);
+  first_newf->fr_type = rs_fill;
+  first_newf->fr_fix = 12;
+  header = first_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;
+  last_newf = first_newf;
+  compressed_size = 12;
+
+  /* Stream the frags through the compression engine, adding a new
+     frag of compressed data for each uncompressed frag.  */
+  for (f = seginfo->frchainP->frch_root;
+       f;
+       f = f->fr_next)
+    {
+      offsetT fill_size;
+      char *fill_literal;
+      offsetT count;
+      offsetT out_size;
+      offsetT newf_size = 0;
+
+      obstack_blank (ob, SIZEOF_STRUCT_FRAG);
+
+      gas_assert (f->fr_type == rs_fill);
+      if (f->fr_fix)
+	{
+	  out_size = compress_frag (strm, f->fr_literal, f->fr_fix, ob);
+	  if (out_size < 0)
+	    return;
+	  newf_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, ob);
+	      if (out_size < 0)
+		return;
+	      newf_size += out_size;
+	    }
+	}
+
+      /* If this is the last frag, flush the compression state.  */
+      if (f->fr_next == NULL)
+        {
+	  out_size = compress_finish (strm, ob);
+	  if (out_size < 0)
+	    return;
+	  newf_size += out_size;
+	}
+
+      newf = (fragS *) obstack_finish (ob);
+      memset (newf, 0, SIZEOF_STRUCT_FRAG);
+      newf->fr_type = rs_fill;
+      newf->fr_fix = newf_size;
+      last_newf->fr_next = newf;
+      last_newf = newf;
+      compressed_size += newf_size;
+    }
+
+  /* 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,
 		void *xxx ATTRIBUTE_UNUSED)
@@ -1912,6 +2034,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);
 }
 

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-07-02  1:03   ` Cary Coutant
@ 2010-07-02  2:29     ` Alan Modra
  2010-07-02 20:46       ` Cary Coutant
  2010-07-14  1:02     ` H.J. Lu
  1 sibling, 1 reply; 34+ messages in thread
From: Alan Modra @ 2010-07-02  2:29 UTC (permalink / raw)
  To: Cary Coutant; +Cc: Binutils

On Thu, Jul 01, 2010 at 06:03:02PM -0700, Cary Coutant wrote:
[snip]
> +      /* Reserve all the space we can.  If none is available, force
> +	 the obstack to grow by at least as many bytes as we have
> +	 remaining in the input stream.  */
> +      room = obstack_room (ob);
> +      if (room <= 0)
> +	room = strm->avail_in;
> +      obstack_blank (ob, room);
obstack_blank_fast.  You don't really need to zero the mem do you?

> +      strm->next_out = (Bytef *) obstack_next_free (ob) - room;
> +      strm->avail_out = room;
> +      x = deflate (strm, Z_NO_FLUSH);
> +      if (x != Z_OK)
> +	return -1;
> +
> +      /* Return unused space.  */
> +      if (strm->avail_out > 0)
> +	obstack_blank (ob, -((int) strm->avail_out));

obstack_blank_fast again, similarly in compress_finish.

[snip]
> +  /* Create a new frag to contain the "ZLIB" header.  */
> +  obstack_blank (ob, SIZEOF_STRUCT_FRAG + 12);

You should use frag_alloc here and later where you create frags

> +  first_newf = (fragS *) obstack_finish (ob);
> +  memset (first_newf, 0, SIZEOF_STRUCT_FRAG);
> +  first_newf->fr_type = rs_fill;

otherwise these struct references might segfault on some architectures
due to misalignment.  With these issues fixed the patch is OK to
commit.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-07-02  2:29     ` Alan Modra
@ 2010-07-02 20:46       ` Cary Coutant
  2010-07-03 10:42         ` Alan Modra
  0 siblings, 1 reply; 34+ messages in thread
From: Cary Coutant @ 2010-07-02 20:46 UTC (permalink / raw)
  To: Binutils

[-- Attachment #1: Type: text/plain, Size: 3220 bytes --]

>> +      /* Reserve all the space we can.  If none is available, force
>> +      the obstack to grow by at least as many bytes as we have
>> +      remaining in the input stream.  */
>> +      room = obstack_room (ob);
>> +      if (room <= 0)
>> +     room = strm->avail_in;
>> +      obstack_blank (ob, room);
> obstack_blank_fast.  You don't really need to zero the mem do you?

In the (room <= 0) case, I needed to use obstack_blank so that it
would reallocate the current obstack object. I wasn't happy with that
approach anyway, since it didn't make effective use of the obstack, so
I've rewritten the patch to fill each new compressed frag until
there's no room left in the current obstack chunk, at which point it
will create another frag (instead of creating one new frag for each
original frag). With this rewrite, the isolation of the zlib interface
is also cleaner.

>> +  /* Create a new frag to contain the "ZLIB" header.  */
>> +  obstack_blank (ob, SIZEOF_STRUCT_FRAG + 12);
>
> You should use frag_alloc here and later where you create frags

I couldn't use frag_alloc because I was relying on obstack_blank
reallocating as necessary, and I needed the frag structure to get
reallocated with the data that followed. With this new patch, I can
now use frag_alloc as you suggest.

Since this new patch changes a bit more than you asked for, I'll wait
for a new approval.

(Side question: I'm puzzled by the alignment stuff in frag_alloc() --
it seems to be setting the alignment mask to 0 before calling
obstack_alloc(). Doesn't that mean that the frag structure will be
allocated on an arbitrary byte boundary?)

(Also: in relax_frag(), I found the following code:

      newf = frag_alloc (ob);
      obstack_blank_fast (ob, fragP->fr_var);
      obstack_finish (ob);

But I couldn't find any code that would guarantee that there was
enough room for the obstack_blank_fast call to succeed. Am I missing
something, or is there a potential bug there?)

Thanks so much for the quick and helpful reviews!

-cary


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.

[-- Attachment #2: compress-debug-patch-3.txt --]
[-- Type: text/plain, Size: 27612 bytes --]

diff --git a/bfd/compress.c b/bfd/compress.c
index 5b6ee0e..323694c 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
    Free Software Foundation, Inc.
 
@@ -51,12 +51,10 @@ DESCRIPTION
 */
 
 bfd_boolean
-bfd_uncompress_section_contents (bfd_byte **buffer, bfd_size_type *size)
+bfd_uncompress_section_contents (bfd_byte **buffer ATTRIBUTE_UNUSED,
+				 bfd_size_type *size ATTRIBUTE_UNUSED)
 {
 #ifndef HAVE_ZLIB_H
-  /* These are just to quiet gcc.  */
-  buffer = 0;
-  size = 0;
   return FALSE;
 #else
   bfd_size_type compressed_size = *size;
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index 9b194aa..ffe1108 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/objdump.c b/binutils/objdump.c
index 2a419b7..f94dee9 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 d4f47ca..1c3cb8b 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 (&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)
     apply_relocations ((FILE *) file, sec, section->start);
diff --git a/gas/Makefile.am b/gas/Makefile.am
index 36ae957..f2c0fe8 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 5b3521b..0487170 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 \
@@ -773,6 +775,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 d617b33..e494fa5 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=<FILE>.  */
     ,{"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 2b2562e..7c16382 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/compress-debug.c b/gas/compress-debug.c
new file mode 100644
index 0000000..c2a8d3d
--- /dev/null
+++ b/gas/compress-debug.c
@@ -0,0 +1,119 @@
+/* compress-debug.c - compress debug sections
+   Copyright 2010 Free Software Foundation, Inc.
+
+   This file is part of GAS, the GNU Assembler.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GAS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#include <stdio.h>
+
+#include "ansidecl.h"
+
+#include "config.h"
+#include "compress-debug.h"
+
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
+
+/* Initialize the compression engine.  */
+
+struct z_stream_s *
+compress_init (void)
+{
+#ifndef HAVE_ZLIB_H
+  return NULL;
+#else
+  static struct z_stream_s strm;
+
+  strm.zalloc = NULL;
+  strm.zfree = NULL;
+  strm.opaque = NULL;
+  deflateInit (&strm, Z_DEFAULT_COMPRESSION);
+  return &strm;
+#endif /* HAVE_ZLIB_H */
+}
+
+/* Stream the contents of a frag to the compression engine.  Output
+   from the engine goes into the current frag on the obstack.  */
+
+int
+compress_data (struct z_stream_s *strm ATTRIBUTE_UNUSED,
+	       const char **next_in ATTRIBUTE_UNUSED,
+	       int *avail_in ATTRIBUTE_UNUSED,
+	       char **next_out ATTRIBUTE_UNUSED,
+	       int *avail_out ATTRIBUTE_UNUSED)
+{
+#ifndef HAVE_ZLIB_H
+  return -1;
+#else
+  int out_size = 0;
+  int x;
+
+  strm->next_in = (Bytef *) (*next_in);
+  strm->avail_in = *avail_in;
+  strm->next_out = (Bytef *) (*next_out);
+  strm->avail_out = *avail_out;
+
+  x = deflate (strm, Z_NO_FLUSH);
+  if (x != Z_OK)
+    return -1;
+
+  out_size = *avail_out - strm->avail_out;
+  *next_in = (char *) (strm->next_in);
+  *avail_in = strm->avail_in;
+  *next_out = (char *) (strm->next_out);
+  *avail_out = strm->avail_out;
+
+  return out_size;
+#endif /* HAVE_ZLIB_H */
+}
+
+/* Finish the compression and consume the remaining compressed output.
+   Returns -1 for error, 0 when done, 1 when more output buffer is
+   needed.  */
+
+int
+compress_finish (struct z_stream_s *strm ATTRIBUTE_UNUSED,
+		 char **next_out ATTRIBUTE_UNUSED,
+		 int *avail_out ATTRIBUTE_UNUSED,
+		 int *out_size ATTRIBUTE_UNUSED)
+{
+#ifndef HAVE_ZLIB_H
+  return -1;
+#else
+  int x;
+
+  strm->avail_in = 0;
+  strm->next_out = (Bytef *) (*next_out);
+  strm->avail_out = *avail_out;
+
+  x = deflate (strm, Z_FINISH);
+
+  *out_size = *avail_out - strm->avail_out;
+  *next_out = (char *) (strm->next_out);
+  *avail_out = strm->avail_out;
+
+  if (x == Z_STREAM_END)
+    {
+      deflateEnd (strm);
+      return 0;
+    }
+  if (strm->avail_out != 0)
+    return -1;
+  return 1;
+#endif /* HAVE_ZLIB_H */
+}
diff --git a/gas/compress-debug.h b/gas/compress-debug.h
new file mode 100644
index 0000000..9d821e9
--- /dev/null
+++ b/gas/compress-debug.h
@@ -0,0 +1,39 @@
+/* compress-debug.h - Header file for compressed debug sections.
+   Copyright 2010 Free Software Foundation, Inc.
+
+   This file is part of GAS, the GNU Assembler.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GAS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#ifndef COMPRESS_DEBUG_H
+#define COMPRESS_DEBUG_H
+
+struct z_stream_s;
+
+/* Initialize the compression engine.  */
+extern struct z_stream_s *
+compress_init (void);
+
+/* Stream the contents of a frag to the compression engine.  Output
+   from the engine goes into the current frag on the obstack.  */
+extern int
+compress_data (struct z_stream_s *, const char **, int *, char **, int *);
+
+/* Finish the compression and consume the remaining compressed output.  */
+extern int
+compress_finish (struct z_stream_s *, char **, int *, int *);
+
+#endif /* COMPRESS_DEBUG_H */
diff --git a/gas/config.in b/gas/config.in
index 55f4c9c..c63b1c6 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 <zlib.h> header file. */
+#undef HAVE_ZLIB_H
+
 /* Using i386 COFF? */
 #undef I386COFF
 
diff --git a/gas/configure b/gas/configure
index 1781b4e..530fa0d 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
@@ -1869,8 +1871,10 @@ $as_echo "$ac_res" >&6; }
 ac_fn_c_check_decl ()
 {
   as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $2 is declared" >&5
-$as_echo_n "checking whether $2 is declared... " >&6; }
+  as_decl_name=`echo $2|sed 's/ *(.*//'`
+  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
 if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
   $as_echo_n "(cached) " >&6
 else
@@ -1880,8 +1884,12 @@ $4
 int
 main ()
 {
-#ifndef $2
-  (void) $2;
+#ifndef $as_decl_name
+#ifdef __cplusplus
+  (void) $as_decl_use;
+#else
+  (void) $as_decl_name;
+#endif
 #endif
 
   ;
@@ -11187,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 11190 "configure"
+#line 11198 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11293,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 11296 "configure"
+#line 11304 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -13978,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 4fbf292..0d5e3e1 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 a148b24..71ac635 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);
 }
 

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-07-02 20:46       ` Cary Coutant
@ 2010-07-03 10:42         ` Alan Modra
  2010-07-03 20:54           ` Cary Coutant
  0 siblings, 1 reply; 34+ messages in thread
From: Alan Modra @ 2010-07-03 10:42 UTC (permalink / raw)
  To: Cary Coutant; +Cc: Binutils

On Fri, Jul 02, 2010 at 01:45:51PM -0700, Cary Coutant wrote:
> In the (room <= 0) case, I needed to use obstack_blank so that it

OK, I was confused about what obstack_blank did anyway..

> (Side question: I'm puzzled by the alignment stuff in frag_alloc() --
> it seems to be setting the alignment mask to 0 before calling
> obstack_alloc(). Doesn't that mean that the frag structure will be
> allocated on an arbitrary byte boundary?)

No.  I haven't looked at this code in any detail for a long time, but
I think the idea is that the first obstack_alloc (ob, 0) call sets up
ob->next_free to the required boundary.  So when you alloc the actual
frag header with the next call it will be properly aligned.  The
alignment mask is zeroed for the header alloc so no padding is added
*after* the header.  We want the frag literal field following
immediately after the header.

>       newf = frag_alloc (ob);
>       obstack_blank_fast (ob, fragP->fr_var);
>       obstack_finish (ob);
> 
> But I couldn't find any code that would guarantee that there was
> enough room for the obstack_blank_fast call to succeed. Am I missing
> something, or is there a potential bug there?)

I think it's a bug.

> 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.

OK.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-07-03 10:42         ` Alan Modra
@ 2010-07-03 20:54           ` Cary Coutant
  2010-07-03 23:28             ` Hans-Peter Nilsson
  0 siblings, 1 reply; 34+ messages in thread
From: Cary Coutant @ 2010-07-03 20:54 UTC (permalink / raw)
  To: Cary Coutant, Binutils

>> 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.
>
> OK.

Thanks, committed.

-cary

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-07-03 20:54           ` Cary Coutant
@ 2010-07-03 23:28             ` Hans-Peter Nilsson
  2010-07-04 10:10               ` Alan Modra
  0 siblings, 1 reply; 34+ messages in thread
From: Hans-Peter Nilsson @ 2010-07-03 23:28 UTC (permalink / raw)
  To: Cary Coutant; +Cc: Binutils

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1853 bytes --]

On Sat, 3 Jul 2010, Cary Coutant wrote:
> >> 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.
> >
> > OK.
>
> Thanks, committed.

Looks like you forgot to commit compress-debug.[ch], my trusted
autotester got (cutnpasted linewrapped from my log):
gcc -O2 -m32 -DHAVE_CONFIG_H -I.
-I/tmp/hpautotest-binutils/bsrc/src/gas  -I.
-I/tmp/hpautotest-bin\
utils/bsrc/src/gas -I../bfd
-I/tmp/hpautotest-binutils/bsrc/src/gas/config
-I/tmp/hpautotest-binuti\
ls/bsrc/src/gas/../include
-I/tmp/hpautotest-binutils/bsrc/src/gas/..
-I/tmp/hpautotest-binutils/bs\
rc/src/gas/../bfd -DLOCALEDIR="\"/usr/local/share/locale\""  -W
-Wall -Wstrict-prototypes -Wmissing\
-prototypes -Wshadow -Werror -g -O2 -MT atof-generic.o -MD -MP
-MF .deps/atof-generic.Tpo -c -o ato\
f-generic.o /tmp/hpautotest-binutils/bsrc/src/gas/atof-generic.c
mv -f .deps/atof-generic.Tpo .deps/atof-generic.Po
make[4]: *** make[4]: Leaving directory
`/tmp/hpautotest-binutils/cris-axis-linux-gnu/gas'
No rule to make target `compress-debug.o', needed by `as-new'.
Stop.

and no trace of it when checking manually.

brgds, H-P
PS: usually a missing "cvs add"...

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-07-03 23:28             ` Hans-Peter Nilsson
@ 2010-07-04 10:10               ` Alan Modra
  0 siblings, 0 replies; 34+ messages in thread
From: Alan Modra @ 2010-07-04 10:10 UTC (permalink / raw)
  To: Hans-Peter Nilsson; +Cc: Cary Coutant, Binutils

On Sat, Jul 03, 2010 at 07:28:26PM -0400, Hans-Peter Nilsson wrote:
> Looks like you forgot to commit compress-debug.[ch]

Fixed.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-06-28 21:39 [patch] Add --compress-debug-sections option to gas Cary Coutant
  2010-06-29  8:08 ` Alan Modra
@ 2010-07-09 19:51 ` H.J. Lu
  2010-07-12 22:31   ` Cary Coutant
  1 sibling, 1 reply; 34+ messages in thread
From: H.J. Lu @ 2010-07-09 19:51 UTC (permalink / raw)
  To: Cary Coutant; +Cc: Binutils

On Mon, Jun 28, 2010 at 2:39 PM, Cary Coutant <ccoutant@google.com> wrote:
> A couple of years ago, Craig Silverstein submitted a patch to add
> support for compressed debug sections generated by the linker:
>
>  http://sourceware.org/ml/binutils/2008-06/msg00203.html
>
> The attached patch extends this support to the assembler, adding a new
> --compress-debug-sections option to gas, and adding the necessary
> support (and fixing a couple of bugs in the original patch) for
> reading compressed sections in relocatables to bfd, objdump, and
> readelf.
>
> Tested on x86_64 by compiling with and without
> -Wa,--compress-debug-sections, and comparing readelf -w output and
> objdump -W output. No regressions in the test suite.
>
> A patch for gold to read files with compressed debug sections is in progress.
>
> I have to admit that I'm not happy with a couple of things:
>
> (1) In both bfd/dwarf2.c and binutils/objdump.c, in order to
> uncompress the section before relocating it, I call
> bfd_get_section_contents() to get the unrelocated section contents,
> then decompress the contents and put a pointer to the decompressed
> contents in sec->contents, setting the SEC_IN_MEMORY flag so that
> bfd_simple_get_relocated_section_contents() would not go read the
> section again. I couldn't find a simpler way to apply relocations
> after decompression.
>
> (2) In gas/write.c, I used a similar trick to signal write_contents()
> that the frags had already been collected and compressed. An
> alternative I considered was to simply replace the frag list with a
> single frag containing the entire compressed section contents, but
> that seemed a bit more complicated.
>
> Advice on these issues is welcome.
>
> -cary
>
> p.s. I'm not sure why my regenerated libbfd.h is different from the
> original -- nothing changed except for parameters to
> bfd_generic_get_relocated_section_contents() that used to be unnamed.
> Did "make headers" change behavior since the last time that file was
> regenerated? Should I just leave this out of the patch?
>
>
> bfd/ChangeLog:
>
>        * bfd-in2.h: Regenerate.
>        * compress.c (bfd_compress_section_contents): New function.
>        * dwarf2.c (read_and_uncompress_section): New function.
>        (read_section): Call it.
>        (find_line): Likewise.
>        * libbfd.h: Regenerate.
>
> 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:
>
>        * as.c (parse_args): Add --compress-debug-sections and
>        --nocompress-debug-sections.
>        * as.h (flag_compress_debug): New variable.
>        * write.c (compress_debug): New function.
>        (write_contents): Check for uncompressed section.
>        (write_object_file): Compress debug sections if requested.
>

Hi Cary,

I think it should be mentioned on gas/NEWS. Also you should add
the new options to "as --help".

Thanks.



-- 
H.J.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-07-09 19:51 ` H.J. Lu
@ 2010-07-12 22:31   ` Cary Coutant
  2010-07-12 22:41     ` H.J. Lu
  2010-07-20 21:40     ` H.J. Lu
  0 siblings, 2 replies; 34+ messages in thread
From: Cary Coutant @ 2010-07-12 22:31 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Binutils

> I think it should be mentioned on gas/NEWS. Also you should add
> the new options to "as --help".

How does this look?

-cary


        * gas/NEWS: Add note about --compress-debug-sections.
        * gas/as.c (show_usage): Add --compress-debug-sections and
        --nocompress-debug-sections.


diff --git a/gas/NEWS b/gas/NEWS
index 1b7f9e9..db6b6d4 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -9,6 +9,11 @@

 * Add support for the Renesas RX processor.

+* New command line option, --compress-debug-sections, which requests
+  compression of DWARF debug information sections in the relocatable output
+  file.  Compressed debug sections are supported by readelf, objdump, and
+  gold, but not currently by Gnu ld.
+
 Changes in 2.20:

 * GNU/Linux targets now supports "gnu_unique_object" as a value in the .type
diff --git a/gas/as.c b/gas/as.c
index e494fa5..2457e8c 100644
--- a/gas/as.c
+++ b/gas/as.c
@@ -246,6 +246,10 @@ Options:\n\
   fprintf (stream, _("\
   --alternate             initially turn on alternate macro syntax\n"));
   fprintf (stream, _("\
+  --compress-debug-sections  compress DWARF debug sections using zlib\n"));
+  fprintf (stream, _("\
+  --nocompress-debug-sections  don't compress DWARF debug sections\n"));
+  fprintf (stream, _("\
   -D                      produce assembler debugging messages\n"));
   fprintf (stream, _("\
   --debug-prefix-map OLD=NEW  Map OLD to NEW in debug information\n"));

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-07-12 22:31   ` Cary Coutant
@ 2010-07-12 22:41     ` H.J. Lu
  2010-07-12 22:57       ` Cary Coutant
  2010-07-20 21:40     ` H.J. Lu
  1 sibling, 1 reply; 34+ messages in thread
From: H.J. Lu @ 2010-07-12 22:41 UTC (permalink / raw)
  To: Cary Coutant; +Cc: Binutils

On Mon, Jul 12, 2010 at 3:30 PM, Cary Coutant <ccoutant@google.com> wrote:
>> I think it should be mentioned on gas/NEWS. Also you should add
>> the new options to "as --help".
>
> How does this look?
>
> -cary
>
>
>        * gas/NEWS: Add note about --compress-debug-sections.
>        * gas/as.c (show_usage): Add --compress-debug-sections and
>        --nocompress-debug-sections.
>
>
> diff --git a/gas/NEWS b/gas/NEWS
> index 1b7f9e9..db6b6d4 100644
> --- a/gas/NEWS
> +++ b/gas/NEWS
> @@ -9,6 +9,11 @@
>
>  * Add support for the Renesas RX processor.
>
> +* New command line option, --compress-debug-sections, which requests
> +  compression of DWARF debug information sections in the relocatable output
> +  file.  Compressed debug sections are supported by readelf, objdump, and
> +  gold, but not currently by Gnu ld.
> +
>  Changes in 2.20:
>
>  * GNU/Linux targets now supports "gnu_unique_object" as a value in the .type
> diff --git a/gas/as.c b/gas/as.c
> index e494fa5..2457e8c 100644
> --- a/gas/as.c
> +++ b/gas/as.c
> @@ -246,6 +246,10 @@ Options:\n\
>   fprintf (stream, _("\
>   --alternate             initially turn on alternate macro syntax\n"));
>   fprintf (stream, _("\
> +  --compress-debug-sections  compress DWARF debug sections using zlib\n"));
> +  fprintf (stream, _("\
> +  --nocompress-debug-sections  don't compress DWARF debug sections\n"));
> +  fprintf (stream, _("\
>   -D                      produce assembler debugging messages\n"));
>   fprintf (stream, _("\
>   --debug-prefix-map OLD=NEW  Map OLD to NEW in debug information\n"));
>

It looks OK to me, except we should align the explanation text.  But I
can't approve it.

Thanks.


-- 
H.J.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-07-12 22:41     ` H.J. Lu
@ 2010-07-12 22:57       ` Cary Coutant
  2010-07-12 23:02         ` H.J. Lu
  0 siblings, 1 reply; 34+ messages in thread
From: Cary Coutant @ 2010-07-12 22:57 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Binutils

> It looks OK to me, except we should align the explanation text.  But I
> can't approve it.

OK, I can start the explanation text on the next line, like
--reduce-memory-overheads (but unlike --debug-prefix-map). Should I
fix --debug-prefix-map while I'm there?

-cary

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-07-12 22:57       ` Cary Coutant
@ 2010-07-12 23:02         ` H.J. Lu
  2010-07-12 23:34           ` Cary Coutant
  0 siblings, 1 reply; 34+ messages in thread
From: H.J. Lu @ 2010-07-12 23:02 UTC (permalink / raw)
  To: Cary Coutant; +Cc: Binutils

On Mon, Jul 12, 2010 at 3:57 PM, Cary Coutant <ccoutant@google.com> wrote:
>> It looks OK to me, except we should align the explanation text.  But I
>> can't approve it.
>
> OK, I can start the explanation text on the next line, like
> --reduce-memory-overheads (but unlike --debug-prefix-map). Should I
> fix --debug-prefix-map while I'm there?
>

Yes, that will be great.

Thanks.

-- 
H.J.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-07-12 23:02         ` H.J. Lu
@ 2010-07-12 23:34           ` Cary Coutant
  2010-07-15  4:50             ` Alan Modra
  0 siblings, 1 reply; 34+ messages in thread
From: Cary Coutant @ 2010-07-12 23:34 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Binutils

>> OK, I can start the explanation text on the next line, like
>> --reduce-memory-overheads (but unlike --debug-prefix-map). Should I
>> fix --debug-prefix-map while I'm there?
>
> Yes, that will be great.

OK, here's an updated patch...

-cary


gas/ChangeLog:

       * NEWS: Add note about --compress-debug-sections.
       * as.c (show_usage): Add --compress-debug-sections and
       --nocompress-debug-sections.


diff --git a/gas/NEWS b/gas/NEWS
index 1b7f9e9..db6b6d4 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -9,6 +9,11 @@

 * Add support for the Renesas RX processor.

+* New command line option, --compress-debug-sections, which requests
+  compression of DWARF debug information sections in the relocatable output
+  file.  Compressed debug sections are supported by readelf, objdump, and
+  gold, but not currently by Gnu ld.
+
 Changes in 2.20:

 * GNU/Linux targets now supports "gnu_unique_object" as a value in the .type
diff --git a/gas/as.c b/gas/as.c
index e494fa5..45acbaa 100644
--- a/gas/as.c
+++ b/gas/as.c
@@ -246,9 +246,16 @@ Options:\n\
   fprintf (stream, _("\
   --alternate             initially turn on alternate macro syntax\n"));
   fprintf (stream, _("\
+  --compress-debug-sections\n\
+                          compress DWARF debug sections using zlib\n"));
+  fprintf (stream, _("\
+  --nocompress-debug-sections\n\
+                          don't compress DWARF debug sections\n"));
+  fprintf (stream, _("\
   -D                      produce assembler debugging messages\n"));
   fprintf (stream, _("\
-  --debug-prefix-map OLD=NEW  Map OLD to NEW in debug information\n"));
+  --debug-prefix-map OLD=NEW\n\
+                          map OLD to NEW in debug information\n"));
   fprintf (stream, _("\
   --defsym SYM=VAL        define symbol SYM to given value\n"));
 #ifdef USE_EMULATIONS

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-07-02  1:03   ` Cary Coutant
  2010-07-02  2:29     ` Alan Modra
@ 2010-07-14  1:02     ` H.J. Lu
  1 sibling, 0 replies; 34+ messages in thread
From: H.J. Lu @ 2010-07-14  1:02 UTC (permalink / raw)
  To: Cary Coutant; +Cc: Binutils

On Thu, Jul 1, 2010 at 6:03 PM, Cary Coutant <ccoutant@google.com> wrote:
>> SEC_IN_MEMORY isn't sufficient.  Other sections will be SEC_IN_MEMORY
>> too, eg. SHT_GROUP sections.  I think your alternate approach of
>> twiddling the frag list is indicated.
>
> Here's an updated patch that builds a new frag list. Since a frag
> requires the data to follow the struct immediately, it didn't work
> with the nice clean interface I added to bfd. It did lead to a more
> efficient way of compressing, however: I now just stream each frag
> through the compression engine, building new compressed frags as the
> compressed data comes out, using the same obstack. At the end, I
> replace the old frag list with the new one. I had to move the
> zlib-specific code into a separate source file, because I can't
> include as.h and zlib.h in the same file.
>
> -cary
>
>
> 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.
>

This change caused:

http://www.sourceware.org/bugzilla/show_bug.cgi?id=11817

-- 
H.J.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-07-12 23:34           ` Cary Coutant
@ 2010-07-15  4:50             ` Alan Modra
  0 siblings, 0 replies; 34+ messages in thread
From: Alan Modra @ 2010-07-15  4:50 UTC (permalink / raw)
  To: Cary Coutant; +Cc: H.J. Lu, Binutils

On Mon, Jul 12, 2010 at 04:34:26PM -0700, Cary Coutant wrote:
>        * NEWS: Add note about --compress-debug-sections.
>        * as.c (show_usage): Add --compress-debug-sections and
>        --nocompress-debug-sections.

OK.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-07-12 22:31   ` Cary Coutant
  2010-07-12 22:41     ` H.J. Lu
@ 2010-07-20 21:40     ` H.J. Lu
  2010-07-20 23:32       ` Cary Coutant
  1 sibling, 1 reply; 34+ messages in thread
From: H.J. Lu @ 2010-07-20 21:40 UTC (permalink / raw)
  To: Cary Coutant; +Cc: Binutils

On Mon, Jul 12, 2010 at 3:30 PM, Cary Coutant <ccoutant@google.com> wrote:
>> I think it should be mentioned on gas/NEWS. Also you should add
>> the new options to "as --help".
>
> How does this look?
>
> -cary
>
>
>        * gas/NEWS: Add note about --compress-debug-sections.
>        * gas/as.c (show_usage): Add --compress-debug-sections and
>        --nocompress-debug-sections.
>
>

Hi Cary,

Sorry for not noticing it before. Did you update assembler document?

-- 
H.J.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-07-20 21:40     ` H.J. Lu
@ 2010-07-20 23:32       ` Cary Coutant
  2010-07-21 13:07         ` H.J. Lu
  0 siblings, 1 reply; 34+ messages in thread
From: Cary Coutant @ 2010-07-20 23:32 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Binutils

>>        * gas/NEWS: Add note about --compress-debug-sections.
>>        * gas/as.c (show_usage): Add --compress-debug-sections and
>>        --nocompress-debug-sections.
>
> Sorry for not noticing it before. Did you update assembler document?

No -- you mean doc/as.texinfo, right? Should the new options just go
into the main list of options, in alphabetical order?

-cary

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-07-20 23:32       ` Cary Coutant
@ 2010-07-21 13:07         ` H.J. Lu
  2010-08-04  2:22           ` Cary Coutant
  0 siblings, 1 reply; 34+ messages in thread
From: H.J. Lu @ 2010-07-21 13:07 UTC (permalink / raw)
  To: Cary Coutant; +Cc: Binutils

On Tue, Jul 20, 2010 at 4:31 PM, Cary Coutant <ccoutant@google.com> wrote:
>>>        * gas/NEWS: Add note about --compress-debug-sections.
>>>        * gas/as.c (show_usage): Add --compress-debug-sections and
>>>        --nocompress-debug-sections.
>>
>> Sorry for not noticing it before. Did you update assembler document?
>
> No -- you mean doc/as.texinfo, right? Should the new options just go
> into the main list of options, in alphabetical order?
>

I think alphabetical order should work.

Thanks.


-- 
H.J.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-07-21 13:07         ` H.J. Lu
@ 2010-08-04  2:22           ` Cary Coutant
  2010-08-04 16:41             ` Nick Clifton
  0 siblings, 1 reply; 34+ messages in thread
From: Cary Coutant @ 2010-08-04  2:22 UTC (permalink / raw)
  To: H.J. Lu, Nick Clifton; +Cc: Binutils

>>> Sorry for not noticing it before. Did you update assembler document?
>>
>> No -- you mean doc/as.texinfo, right? Should the new options just go
>> into the main list of options, in alphabetical order?
>
> I think alphabetical order should work.

I forgot about this until Nick reminded me. How's this?

Sorry for the delay.

-cary


        * doc/as.texinfo: Add --compress-debug-sections,
        --nocompress-debug-sections.


diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo
index a8327b8..f17c591 100644
--- a/gas/doc/as.texinfo
+++ b/gas/doc/as.texinfo
@@ -232,6 +232,7 @@ gcc(1), ld(1), and the Info entries for
@file{binutils} and @file{ld}.
 @smallexample
 @c man begin SYNOPSIS
 @value{AS} [@b{-a}[@b{cdghlns}][=@var{file}]] [@b{--alternate}] [@b{-D}]
+ [@b{--compress-debug-sections}]  [@b{--nocompress-debug-sections}]
  [@b{--debug-prefix-map} @var{old}=@var{new}]
  [@b{--defsym} @var{sym}=@var{val}] [@b{-f}] [@b{-g}] [@b{--gstabs}]
  [@b{--gstabs+}] [@b{--gdwarf-2}] [@b{--help}] [@b{-I} @var{dir}] [@b{-J}]
@@ -552,6 +553,14 @@ Begin in alternate macro mode.
 @xref{Altmacro,,@code{.altmacro}}.
 @end ifclear

+@item --compress-debug-sections
+Compress DWARF debug sections using zlib.  The debug sections are renamed
+to begin with @samp{.zdebug}, and the resulting object file may not be
+compatible with older linkers and object file utilities.
+
+@item --nocompress-debug-sections
+Do not compress DWARF debug sections.  This is the default.
+
 @item -D
 Ignored.  This option is accepted for script compatibility with calls to
 other assemblers.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-08-04  2:22           ` Cary Coutant
@ 2010-08-04 16:41             ` Nick Clifton
  2010-08-04 18:38               ` Cary Coutant
  0 siblings, 1 reply; 34+ messages in thread
From: Nick Clifton @ 2010-08-04 16:41 UTC (permalink / raw)
  To: Cary Coutant; +Cc: H.J. Lu, Binutils

Hi Cary,

> I forgot about this until Nick reminded me. How's this?

OK - except for one small detail...

> +@item --compress-debug-sections
> +Compress DWARF debug sections using zlib.  The debug sections are renamed
> +to begin with @samp{.zdebug}, and the resulting object file may not be
> +compatible with older linkers and object file utilities.

I think that you should mention that this feature is only available if 
the zlib library is available on the host machine.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-08-04 16:41             ` Nick Clifton
@ 2010-08-04 18:38               ` Cary Coutant
  2010-08-04 19:12                 ` H.J. Lu
  2010-08-05 10:33                 ` Nick Clifton
  0 siblings, 2 replies; 34+ messages in thread
From: Cary Coutant @ 2010-08-04 18:38 UTC (permalink / raw)
  To: Nick Clifton; +Cc: H.J. Lu, Binutils

>> +@item --compress-debug-sections
>> +Compress DWARF debug sections using zlib.  The debug sections are renamed
>> +to begin with @samp{.zdebug}, and the resulting object file may not be
>> +compatible with older linkers and object file utilities.
>
> I think that you should mention that this feature is only available if the
> zlib library is available on the host machine.

More specifically, if it was available when gas was configured and
built, right? How should I phrase that? Or would the following be
sufficient?

"... If the zlib library is not available on the host machine, this
option has no effect."

-cary

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-08-04 18:38               ` Cary Coutant
@ 2010-08-04 19:12                 ` H.J. Lu
  2010-08-05 10:33                 ` Nick Clifton
  1 sibling, 0 replies; 34+ messages in thread
From: H.J. Lu @ 2010-08-04 19:12 UTC (permalink / raw)
  To: Cary Coutant; +Cc: Nick Clifton, Binutils

On Wed, Aug 4, 2010 at 11:36 AM, Cary Coutant <ccoutant@google.com> wrote:
>>> +@item --compress-debug-sections
>>> +Compress DWARF debug sections using zlib.  The debug sections are renamed
>>> +to begin with @samp{.zdebug}, and the resulting object file may not be
>>> +compatible with older linkers and object file utilities.
>>
>> I think that you should mention that this feature is only available if the
>> zlib library is available on the host machine.
>
> More specifically, if it was available when gas was configured and
> built, right? How should I phrase that? Or would the following be
> sufficient?
>
> "... If the zlib library is not available on the host machine, this
> option has no effect."
>

zlib is in gcc source tree. Can we include it in binutils?


-- 
H.J.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-08-04 18:38               ` Cary Coutant
  2010-08-04 19:12                 ` H.J. Lu
@ 2010-08-05 10:33                 ` Nick Clifton
  2010-08-05 14:36                   ` Tristan Gingold
  2010-08-05 21:04                   ` Cary Coutant
  1 sibling, 2 replies; 34+ messages in thread
From: Nick Clifton @ 2010-08-05 10:33 UTC (permalink / raw)
  To: Cary Coutant; +Cc: H.J. Lu, Binutils

Hi Cary,

> More specifically, if it was available when gas was configured and
> built, right?

Right.

> How should I phrase that? Or would the following be
> sufficient?
>
> "... If the zlib library is not available on the host machine, this
> option has no effect."

Actually just looking at the code in write.c, is there actually any 
check for the absence of the zlibrary ?  Ie can the sources currently be 
compiled on a system with zlib installed ?

Also, if zlib is not installed, then it would be fairer to the user if 
the --compress-debug-section was not mentioned in the --help output, and 
produced a warning if used.  Otherwise someone could add 
--compress-debug-sections to their command line and then wonder why they 
are not getting any smaller binaries.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-08-05 10:33                 ` Nick Clifton
@ 2010-08-05 14:36                   ` Tristan Gingold
  2010-08-05 21:04                   ` Cary Coutant
  1 sibling, 0 replies; 34+ messages in thread
From: Tristan Gingold @ 2010-08-05 14:36 UTC (permalink / raw)
  To: Nick Clifton; +Cc: Cary Coutant, H.J. Lu, Binutils


On Aug 5, 2010, at 12:28 PM, Nick Clifton wrote:
> 
> Actually just looking at the code in write.c, is there actually any check for the absence of the zlibrary ?  Ie can the sources currently be compiled on a system with zlib installed ?

with zlib *not* installed ?  Yes, this is handled in compress-debug.c and yes I have tested that on vms :-)

> Also, if zlib is not installed, then it would be fairer to the user if the --compress-debug-section was not mentioned in the --help output, and produced a warning if used.  Otherwise someone could add --compress-debug-sections to their command line and then wonder why they are not getting any smaller binaries.

Indeed.

Tristan.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-08-05 10:33                 ` Nick Clifton
  2010-08-05 14:36                   ` Tristan Gingold
@ 2010-08-05 21:04                   ` Cary Coutant
  2010-08-06 13:42                     ` Nick Clifton
  1 sibling, 1 reply; 34+ messages in thread
From: Cary Coutant @ 2010-08-05 21:04 UTC (permalink / raw)
  To: Nick Clifton; +Cc: H.J. Lu, Binutils

> Actually just looking at the code in write.c, is there actually any check
> for the absence of the zlibrary ?  Ie can the sources currently be compiled
> on a system with zlib installed ?

Yes, the compression routines in compress-debug.c reduce to empty
stubs if zlib is not installed.

> Also, if zlib is not installed, then it would be fairer to the user if the
> --compress-debug-section was not mentioned in the --help output, and
> produced a warning if used.  Otherwise someone could add
> --compress-debug-sections to their command line and then wonder why they are
> not getting any smaller binaries.

Sounds better. Here's a revised patch.

-cary


        * as.c (show_usage): Don't list --compress-debug-sections if zlib not
        installed.
        (main): Warn if --compress-debug-sections requested and zlib not
        installed.
        * doc/as.texinfo: Add --compress-debug-sections,
        --nocompress-debug-sections.


diff --git a/gas/as.c b/gas/as.c
index 45acbaa..d9aa6e2 100644
--- a/gas/as.c
+++ b/gas/as.c
@@ -245,12 +245,14 @@ Options:\n\

   fprintf (stream, _("\
   --alternate             initially turn on alternate macro syntax\n"));
+#ifdef HAVE_ZLIB_H
   fprintf (stream, _("\
   --compress-debug-sections\n\
                           compress DWARF debug sections using zlib\n"));
   fprintf (stream, _("\
   --nocompress-debug-sections\n\
                           don't compress DWARF debug sections\n"));
+#endif /* HAVE_ZLIB_H */
   fprintf (stream, _("\
   -D                      produce assembler debugging messages\n"));
   fprintf (stream, _("\
@@ -646,7 +648,11 @@ This program has absolutely no warranty.\n"));
 	  exit (EXIT_SUCCESS);

 	case OPTION_COMPRESS_DEBUG:
+#ifdef HAVE_ZLIB_H
 	  flag_compress_debug = 1;
+#else
+	  as_warn (_("cannot compress debug sections (zlib not installed)"));
+#endif /* HAVE_ZLIB_H */
 	  break;

 	case OPTION_NOCOMPRESS_DEBUG:
diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo
index a8327b8..f17c591 100644
--- a/gas/doc/as.texinfo
+++ b/gas/doc/as.texinfo
@@ -232,6 +232,7 @@ gcc(1), ld(1), and the Info entries for
@file{binutils} and @file{ld}.
 @smallexample
 @c man begin SYNOPSIS
 @value{AS} [@b{-a}[@b{cdghlns}][=@var{file}]] [@b{--alternate}] [@b{-D}]
+ [@b{--compress-debug-sections}]  [@b{--nocompress-debug-sections}]
  [@b{--debug-prefix-map} @var{old}=@var{new}]
  [@b{--defsym} @var{sym}=@var{val}] [@b{-f}] [@b{-g}] [@b{--gstabs}]
  [@b{--gstabs+}] [@b{--gdwarf-2}] [@b{--help}] [@b{-I} @var{dir}] [@b{-J}]
@@ -552,6 +553,14 @@ Begin in alternate macro mode.
 @xref{Altmacro,,@code{.altmacro}}.
 @end ifclear

+@item --compress-debug-sections
+Compress DWARF debug sections using zlib.  The debug sections are renamed
+to begin with @samp{.zdebug}, and the resulting object file may not be
+compatible with older linkers and object file utilities.
+
+@item --nocompress-debug-sections
+Do not compress DWARF debug sections.  This is the default.
+
 @item -D
 Ignored.  This option is accepted for script compatibility with calls to
 other assemblers.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-08-05 21:04                   ` Cary Coutant
@ 2010-08-06 13:42                     ` Nick Clifton
  2010-08-06 16:36                       ` H.J. Lu
  2010-08-06 17:28                       ` Cary Coutant
  0 siblings, 2 replies; 34+ messages in thread
From: Nick Clifton @ 2010-08-06 13:42 UTC (permalink / raw)
  To: Cary Coutant; +Cc: H.J. Lu, Binutils

Hi Cary,

>          * as.c (show_usage): Don't list --compress-debug-sections if zlib not
>          installed.
>          (main): Warn if --compress-debug-sections requested and zlib not
>          installed.
>          * doc/as.texinfo: Add --compress-debug-sections,
>          --nocompress-debug-sections.

Good, although the documentation still does not mention that 
--compress-debug-sections may not be supported.  How about:

   @item --compress-debug-sections
   Compress DWARF debug sections using zlib.  The debug sections are renamed
   to begin with @samp{.zdebug}, and the resulting object file may not be
   compatible with older linkers and object file utilities.  This option is
   only supported if the host machine has the zlib compression library.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-08-06 13:42                     ` Nick Clifton
@ 2010-08-06 16:36                       ` H.J. Lu
  2010-08-06 17:37                         ` Cary Coutant
  2010-08-06 17:28                       ` Cary Coutant
  1 sibling, 1 reply; 34+ messages in thread
From: H.J. Lu @ 2010-08-06 16:36 UTC (permalink / raw)
  To: Nick Clifton; +Cc: Cary Coutant, Binutils

On Fri, Aug 6, 2010 at 1:54 AM, Nick Clifton <nickc@redhat.com> wrote:
> Hi Cary,
>
>>         * as.c (show_usage): Don't list --compress-debug-sections if zlib
>> not
>>         installed.
>>         (main): Warn if --compress-debug-sections requested and zlib not
>>         installed.
>>         * doc/as.texinfo: Add --compress-debug-sections,
>>         --nocompress-debug-sections.
>
> Good, although the documentation still does not mention that
> --compress-debug-sections may not be supported.  How about:
>
>  @item --compress-debug-sections
>  Compress DWARF debug sections using zlib.  The debug sections are renamed
>  to begin with @samp{.zdebug}, and the resulting object file may not be
>  compatible with older linkers and object file utilities.  This option is
>  only supported if the host machine has the zlib compression library.
>

The object files with compressed debug sections aren't compatible
with any binutils programs, except for gold:

http://sourceware.org/bugzilla/show_bug.cgi?id=11819


-- 
H.J.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-08-06 13:42                     ` Nick Clifton
  2010-08-06 16:36                       ` H.J. Lu
@ 2010-08-06 17:28                       ` Cary Coutant
  2010-08-09 12:09                         ` Nick Clifton
  1 sibling, 1 reply; 34+ messages in thread
From: Cary Coutant @ 2010-08-06 17:28 UTC (permalink / raw)
  To: Nick Clifton; +Cc: H.J. Lu, Binutils

> Good, although the documentation still does not mention that
> --compress-debug-sections may not be supported.  How about:
>
>  @item --compress-debug-sections
>  Compress DWARF debug sections using zlib.  The debug sections are renamed
>  to begin with @samp{.zdebug}, and the resulting object file may not be
>  compatible with older linkers and object file utilities.  This option is
>  only supported if the host machine has the zlib compression library.

Sorry, I forgot to incorporate that change into my patch. Is this
patch OK to apply with your suggested change?

-cary

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-08-06 16:36                       ` H.J. Lu
@ 2010-08-06 17:37                         ` Cary Coutant
  0 siblings, 0 replies; 34+ messages in thread
From: Cary Coutant @ 2010-08-06 17:37 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Nick Clifton, Binutils

> The object files with compressed debug sections aren't compatible
> with any binutils programs, except for gold:
>
> http://sourceware.org/bugzilla/show_bug.cgi?id=11819

I'm hoping that your patch will be approved soon to fix that.

Nick, is there any reason not to approve HJ's patch?

http://sourceware.org/ml/binutils/2010-07/msg00351.html

The objection raised to that patch was more an issue with the original
patch that adds the --compress-debug-sections option to gas, not with
HJ's patch to make the rest of binutils support the files that gas
produces.

-cary

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-08-06 17:28                       ` Cary Coutant
@ 2010-08-09 12:09                         ` Nick Clifton
  2010-08-09 19:37                           ` Cary Coutant
  0 siblings, 1 reply; 34+ messages in thread
From: Nick Clifton @ 2010-08-09 12:09 UTC (permalink / raw)
  To: Cary Coutant; +Cc: H.J. Lu, Binutils

Hi Cary,

>>   @item --compress-debug-sections
>>   Compress DWARF debug sections using zlib.  The debug sections are renamed
>>   to begin with @samp{.zdebug}, and the resulting object file may not be
>>   compatible with older linkers and object file utilities.  This option is
>>   only supported if the host machine has the zlib compression library.
>
> Sorry, I forgot to incorporate that change into my patch. Is this
> patch OK to apply with your suggested change?

Yes - please apply.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [patch] Add --compress-debug-sections option to gas
  2010-08-09 12:09                         ` Nick Clifton
@ 2010-08-09 19:37                           ` Cary Coutant
  0 siblings, 0 replies; 34+ messages in thread
From: Cary Coutant @ 2010-08-09 19:37 UTC (permalink / raw)
  To: Nick Clifton; +Cc: H.J. Lu, Binutils

>>>  @item --compress-debug-sections
>>>  Compress DWARF debug sections using zlib.  The debug sections are
>>> renamed
>>>  to begin with @samp{.zdebug}, and the resulting object file may not be
>>>  compatible with older linkers and object file utilities.  This option is
>>>  only supported if the host machine has the zlib compression library.
>>
>> Sorry, I forgot to incorporate that change into my patch. Is this
>> patch OK to apply with your suggested change?
>
> Yes - please apply.

Thanks! Applied.

-cary

^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2010-08-09 18:09 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-06-28 21:39 [patch] Add --compress-debug-sections option to gas Cary Coutant
2010-06-29  8:08 ` Alan Modra
2010-06-29 18:42   ` Cary Coutant
2010-07-02  1:03   ` Cary Coutant
2010-07-02  2:29     ` Alan Modra
2010-07-02 20:46       ` Cary Coutant
2010-07-03 10:42         ` Alan Modra
2010-07-03 20:54           ` Cary Coutant
2010-07-03 23:28             ` Hans-Peter Nilsson
2010-07-04 10:10               ` Alan Modra
2010-07-14  1:02     ` H.J. Lu
2010-07-09 19:51 ` H.J. Lu
2010-07-12 22:31   ` Cary Coutant
2010-07-12 22:41     ` H.J. Lu
2010-07-12 22:57       ` Cary Coutant
2010-07-12 23:02         ` H.J. Lu
2010-07-12 23:34           ` Cary Coutant
2010-07-15  4:50             ` Alan Modra
2010-07-20 21:40     ` H.J. Lu
2010-07-20 23:32       ` Cary Coutant
2010-07-21 13:07         ` H.J. Lu
2010-08-04  2:22           ` Cary Coutant
2010-08-04 16:41             ` Nick Clifton
2010-08-04 18:38               ` Cary Coutant
2010-08-04 19:12                 ` H.J. Lu
2010-08-05 10:33                 ` Nick Clifton
2010-08-05 14:36                   ` Tristan Gingold
2010-08-05 21:04                   ` Cary Coutant
2010-08-06 13:42                     ` Nick Clifton
2010-08-06 16:36                       ` H.J. Lu
2010-08-06 17:37                         ` Cary Coutant
2010-08-06 17:28                       ` Cary Coutant
2010-08-09 12:09                         ` Nick Clifton
2010-08-09 19:37                           ` Cary Coutant

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).