diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2015-04-14 22:01:25 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2015-04-14 22:01:38 -0700 |
commit | 0ce398f106dac65c3a1d2f7d254213fa652af089 (patch) | |
tree | 6ab688c878a7eac3183247b29dd9add73bf1dec6 | |
parent | ecd272101d27ed8d654cbab9972aa05c124f981c (diff) | |
download | gdb-0ce398f106dac65c3a1d2f7d254213fa652af089.zip gdb-0ce398f106dac65c3a1d2f7d254213fa652af089.tar.gz gdb-0ce398f106dac65c3a1d2f7d254213fa652af089.tar.bz2 |
Add --compress-debug-sections=[none|zlib|zlib-gnu|zlib-gabi]
This patch adds --compress-debug-sections=[none|zlib|zlib-gnu|zlib-gabi]
to ld for ELF targets to support generating compressed DWARF debug
sections. We always generate .zdebug_* section since section names have
been finalized and they can't be changed easily when compression is
being performed.
bfd/
* bfd-in.h (compressed_debug_section_type): New.
* compress.c (bfd_compress_section_contents): Add an argument
for linker write compression and always generate .zdebug_*
section when linking.
(bfd_init_section_compress_status): Pass FALSE to
bfd_compress_section_contents.
(bfd_compress_section): New function.
* elf.c (elf_fake_sections): For linking, set SEC_ELF_COMPRESS
on DWARF debug sections if COMPRESS_DEBUG is set and rename
section if COMPRESS_DEBUG_GABI_ZLIB isn't set.
(assign_file_positions_for_non_load_sections): Set sh_offset
to -1 if SEC_ELF_COMPRESS is set.
(assign_file_positions_except_relocs): Likwise.
(_bfd_elf_assign_file_positions_for_relocs): Renamed to ...
(_bfd_elf_assign_file_positions_for_non_load): This. Change
return time to bfd_boolean. Compress the section if
SEC_ELF_COMPRESS is set.
(_bfd_elf_write_object_contents): Updated.
(_bfd_elf_set_section_contents): Write section contents to
the buffer if SEC_ELF_COMPRESS is set.
* merge.c: Include "elf-bfd.h".
(sec_merge_emit): Add arguments for contents and offset. Write
to contents with offset if contents isn't NULL.
(_bfd_write_merged_section): Write section contents to the
buffer if SEC_ELF_COMPRESS is set. Pass contents and
output_offset to sec_merge_emit.
* elflink.c (bfd_elf_final_link): Allocate the buffer for
output section contents if SEC_ELF_COMPRESS is set.
* section.c (SEC_ELF_COMPRESS): New.
* bfd-in2.h: Regenerated.
gas/
* as.h (compressed_debug_section_type): Removed.
include/
* bfdlink.h (bfd_link_info): Add compress_debug.
ld/
* ld.texinfo: Document --compress-debug-sections=.
* ldmain.c (main): Set BFD_COMPRESS on output_bfd if
COMPRESS_DEBUG is set. Set BFD_COMPRESS_GABI on output_bfd
for COMPRESS_DEBUG_GABI_ZLIB.
* lexsup.c (elf_static_list_options): Add
--compress-debug-sections=.
* emultempl/elf32.em (OPTION_COMPRESS_DEBUG): New.
(xtra_long): Add "compress-debug-sections".
(gld${EMULATION_NAME}_handle_option): Handle
OPTION_COMPRESS_DEBUG.
ld/testsuite/
* ld-elf/compress.exp (build_tests): Add tests for
--compress-debug-sections=.
(run_tests): Likewise.
Add additonal tests for --compress-debug-sections=.
* ld-elf/gabiend.rt: New file.
* ld-elf/gabinormal.rt: Likewise.
* ld-elf/gnubegin.rS: Likewise.
* ld-elf/gnunormal.rS: Likewise.
* ld-elf/zlibbegin.rS: Likewise.
* ld-elf/zlibnormal.rS: Likewise.
-rw-r--r-- | bfd/ChangeLog | 33 | ||||
-rw-r--r-- | bfd/bfd-in.h | 11 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 18 | ||||
-rw-r--r-- | bfd/compress.c | 51 | ||||
-rw-r--r-- | bfd/elf.c | 89 | ||||
-rw-r--r-- | bfd/elflink.c | 15 | ||||
-rw-r--r-- | bfd/merge.c | 53 | ||||
-rw-r--r-- | bfd/section.c | 4 | ||||
-rw-r--r-- | gas/ChangeLog | 4 | ||||
-rw-r--r-- | gas/as.h | 10 | ||||
-rw-r--r-- | include/ChangeLog | 4 | ||||
-rw-r--r-- | include/bfdlink.h | 3 | ||||
-rw-r--r-- | ld/ChangeLog | 13 | ||||
-rw-r--r-- | ld/emultempl/elf32.em | 15 | ||||
-rw-r--r-- | ld/ld.texinfo | 16 | ||||
-rw-r--r-- | ld/ldmain.c | 7 | ||||
-rw-r--r-- | ld/lexsup.c | 3 | ||||
-rw-r--r-- | ld/testsuite/ChangeLog | 13 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/compress.exp | 167 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/gabiend.rt | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/gabinormal.rt | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/gnubegin.rS | 3 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/gnunormal.rS | 3 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/zlibbegin.rS | 3 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/zlibnormal.rS | 3 |
25 files changed, 517 insertions, 32 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 17610e0..abb87dc 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,36 @@ +2015-04-14 H.J. Lu <hongjiu.lu@intel.com> + + * bfd-in.h (compressed_debug_section_type): New. + * compress.c (bfd_compress_section_contents): Add an argument + for linker write compression and always generate .zdebug_* + section when linking. + (bfd_init_section_compress_status): Pass FALSE to + bfd_compress_section_contents. + (bfd_compress_section): New function. + * elf.c (elf_fake_sections): For linking, set SEC_ELF_COMPRESS + on DWARF debug sections if COMPRESS_DEBUG is set and rename + section if COMPRESS_DEBUG_GABI_ZLIB isn't set. + (assign_file_positions_for_non_load_sections): Set sh_offset + to -1 if SEC_ELF_COMPRESS is set. + (assign_file_positions_except_relocs): Likwise. + (_bfd_elf_assign_file_positions_for_relocs): Renamed to ... + (_bfd_elf_assign_file_positions_for_non_load): This. Change + return time to bfd_boolean. Compress the section if + SEC_ELF_COMPRESS is set. + (_bfd_elf_write_object_contents): Updated. + (_bfd_elf_set_section_contents): Write section contents to + the buffer if SEC_ELF_COMPRESS is set. + * merge.c: Include "elf-bfd.h". + (sec_merge_emit): Add arguments for contents and offset. Write + to contents with offset if contents isn't NULL. + (_bfd_write_merged_section): Write section contents to the + buffer if SEC_ELF_COMPRESS is set. Pass contents and + output_offset to sec_merge_emit. + * elflink.c (bfd_elf_final_link): Allocate the buffer for + output section contents if SEC_ELF_COMPRESS is set. + * section.c (SEC_ELF_COMPRESS): New. + * bfd-in2.h: Regenerated. + 2015-04-15 Alan Modra <amodra@gmail.com> * elf32-rl78.c (rl78_elf_relocate_section): Typo fix. diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h index 1f8a72c..2e324cd 100644 --- a/bfd/bfd-in.h +++ b/bfd/bfd-in.h @@ -437,6 +437,17 @@ extern void bfd_hash_traverse this size. */ extern unsigned long bfd_hash_set_default_size (unsigned long); +/* Types of compressed DWARF debug sections. We currently support + zlib. */ +enum compressed_debug_section_type +{ + COMPRESS_DEBUG_NONE = 0, + COMPRESS_DEBUG = 1 << 0, + COMPRESS_DEBUG_ZLIB = COMPRESS_DEBUG | 1 << 1, + COMPRESS_DEBUG_GNU_ZLIB = COMPRESS_DEBUG | 1 << 2, + COMPRESS_DEBUG_GABI_ZLIB = COMPRESS_DEBUG | 1 << 3 +}; + /* This structure is used to keep track of stabs in sections information while linking. */ diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 679595e..122caa0 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -444,6 +444,17 @@ extern void bfd_hash_traverse this size. */ extern unsigned long bfd_hash_set_default_size (unsigned long); +/* Types of compressed DWARF debug sections. We currently support + zlib. */ +enum compressed_debug_section_type +{ + COMPRESS_DEBUG_NONE = 0, + COMPRESS_DEBUG = 1 << 0, + COMPRESS_DEBUG_ZLIB = COMPRESS_DEBUG | 1 << 1, + COMPRESS_DEBUG_GNU_ZLIB = COMPRESS_DEBUG | 1 << 2, + COMPRESS_DEBUG_GABI_ZLIB = COMPRESS_DEBUG | 1 << 3 +}; + /* This structure is used to keep track of stabs in sections information while linking. */ @@ -1378,6 +1389,10 @@ typedef struct bfd_section executables or shared objects. This is for COFF only. */ #define SEC_COFF_SHARED 0x8000000 + /* This section should be compressed. This is for ELF linker + internal use only. */ +#define SEC_ELF_COMPRESS 0x8000000 + /* When a section with this flag is being linked, then if the size of the input section is less than a page, it should not cross a page boundary. If the size of the input section is one page or more, @@ -7316,6 +7331,9 @@ bfd_boolean bfd_init_section_decompress_status bfd_boolean bfd_init_section_compress_status (bfd *abfd, asection *section); +bfd_boolean bfd_compress_section + (bfd *abfd, asection *section, bfd_byte *uncompressed_buffer); + #ifdef __cplusplus } #endif diff --git a/bfd/compress.c b/bfd/compress.c index 770ea57..dfde50e 100644 --- a/bfd/compress.c +++ b/bfd/compress.c @@ -72,7 +72,8 @@ decompress_contents (bfd_byte *compressed_buffer, static bfd_size_type bfd_compress_section_contents (bfd *abfd, sec_ptr sec, bfd_byte *uncompressed_buffer, - bfd_size_type uncompressed_size) + bfd_size_type uncompressed_size, + bfd_boolean write_compress) { uLong compressed_size; bfd_byte *buffer; @@ -176,8 +177,11 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec, compressed_size += header_size; /* PR binutils/18087: If compression didn't make the section smaller, - just keep it uncompressed. */ - if (compressed_size < uncompressed_size) + just keep it uncompressed. We always generate .zdebug_* section + when linking since section names have been finalized and they + can't be changed easily. */ + if ((write_compress && compression_header_size == 0) + || compressed_size < uncompressed_size) { bfd_update_compression_header (abfd, buffer, sec); @@ -543,9 +547,48 @@ bfd_init_section_compress_status (bfd *abfd, sec_ptr sec) { uncompressed_size = bfd_compress_section_contents (abfd, sec, uncompressed_buffer, - uncompressed_size); + uncompressed_size, + FALSE); ret = uncompressed_size != 0; } return ret; } + +/* +FUNCTION + bfd_compress_section + +SYNOPSIS + bfd_boolean bfd_compress_section + (bfd *abfd, asection *section, bfd_byte *uncompressed_buffer); + +DESCRIPTION + If open for write, compress section, update section size with + compressed size and set compress_status to COMPRESS_SECTION_DONE. + + Return @code{FALSE} if compression fail. Otherwise, return + @code{TRUE}. +*/ + +bfd_boolean +bfd_compress_section (bfd *abfd, sec_ptr sec, bfd_byte *uncompressed_buffer) +{ + bfd_size_type uncompressed_size = sec->size; + + /* Error if not opened for write. */ + if (abfd->direction != write_direction + || uncompressed_size == 0 + || uncompressed_buffer == NULL + || sec->contents != NULL + || sec->compressed_size != 0 + || sec->compress_status != COMPRESS_SECTION_NONE) + { + bfd_set_error (bfd_error_invalid_operation); + return FALSE; + } + + /* Compress it. */ + return bfd_compress_section_contents (abfd, sec, uncompressed_buffer, + uncompressed_size, TRUE) != 0; +} @@ -2752,6 +2752,7 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg) struct bfd_elf_section_data *esd = elf_section_data (asect); Elf_Internal_Shdr *this_hdr; unsigned int sh_type; + const char *name = asect->name; if (arg->failed) { @@ -2762,8 +2763,38 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg) this_hdr = &esd->this_hdr; + /* For linking, compress DWARF debug sections with names: .debug_*. */ + if (arg->link_info + && (arg->link_info->compress_debug & COMPRESS_DEBUG) + && (asect->flags & SEC_DEBUGGING) + && name[1] == 'd' + && name[6] == '_') + { + /* Set SEC_ELF_COMPRESS to indicate this section should be + compressed. */ + asect->flags |= SEC_ELF_COMPRESS; + + if (arg->link_info->compress_debug != COMPRESS_DEBUG_GABI_ZLIB) + { + /* If SHF_COMPRESSED isn't used, rename compressed DWARF + debug section to .zdebug_*. */ + unsigned int len = strlen (name); + char *new_name = bfd_alloc (abfd, len + 2); + if (new_name == NULL) + { + arg->failed = TRUE; + return; + } + new_name[0] = '.'; + new_name[1] = 'z'; + memcpy (new_name + 2, name + 1, len); + bfd_rename_section (abfd, asect, new_name); + name = asect->name; + } + } + this_hdr->sh_name = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), - asect->name, FALSE); + name, FALSE); if (this_hdr->sh_name == (unsigned int) -1) { arg->failed = TRUE; @@ -5116,6 +5147,9 @@ assign_file_positions_for_non_load_sections (bfd *abfd, } else if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA) && hdr->bfd_section == NULL) + || (hdr->bfd_section != NULL + && (hdr->bfd_section->flags & SEC_ELF_COMPRESS)) + /* Compress DWARF debug sections. */ || hdr == i_shdrpp[elf_onesymtab (abfd)] || hdr == i_shdrpp[elf_symtab_shndx (abfd)] || hdr == i_shdrpp[elf_strtab_sec (abfd)]) @@ -5365,6 +5399,9 @@ assign_file_positions_except_relocs (bfd *abfd, hdr = *hdrpp; if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA) && hdr->bfd_section == NULL) + || (hdr->bfd_section != NULL + && (hdr->bfd_section->flags & SEC_ELF_COMPRESS)) + /* Compress DWARF debug sections. */ || i == elf_onesymtab (abfd) || i == elf_symtab_shndx (abfd) || i == elf_strtab_sec (abfd)) @@ -5518,8 +5555,8 @@ prep_headers (bfd *abfd) /* Assign file positions for all the reloc sections which are not part of the loadable file image, and the file position of section headers. */ -static void -_bfd_elf_assign_file_positions_for_relocs (bfd *abfd) +static bfd_boolean +_bfd_elf_assign_file_positions_for_non_load (bfd *abfd) { file_ptr off; unsigned int i, num_sec; @@ -5535,9 +5572,30 @@ _bfd_elf_assign_file_positions_for_relocs (bfd *abfd) Elf_Internal_Shdr *shdrp; shdrp = *shdrpp; - if ((shdrp->sh_type == SHT_REL || shdrp->sh_type == SHT_RELA) - && shdrp->sh_offset == -1) - off = _bfd_elf_assign_file_position_for_section (shdrp, off, TRUE); + if (shdrp->sh_offset == -1) + { + bfd_boolean is_rel = (shdrp->sh_type == SHT_REL + || shdrp->sh_type == SHT_RELA); + if (is_rel + || (shdrp->bfd_section != NULL + && (shdrp->bfd_section->flags & SEC_ELF_COMPRESS))) + { + if (!is_rel) + { + /* Compress DWARF debug sections. */ + if (!bfd_compress_section (abfd, shdrp->bfd_section, + shdrp->contents)) + return FALSE; + /* Update section size and contents. */ + shdrp->sh_size = shdrp->bfd_section->size; + shdrp->contents = shdrp->bfd_section->contents; + shdrp->bfd_section->contents = NULL; + } + off = _bfd_elf_assign_file_position_for_section (shdrp, + off, + TRUE); + } + } } /* Place the section headers. */ @@ -5547,6 +5605,8 @@ _bfd_elf_assign_file_positions_for_relocs (bfd *abfd) i_ehdrp->e_shoff = off; off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize; elf_next_file_pos (abfd) = off; + + return TRUE; } bfd_boolean @@ -5569,7 +5629,8 @@ _bfd_elf_write_object_contents (bfd *abfd) if (failed) return FALSE; - _bfd_elf_assign_file_positions_for_relocs (abfd); + if (!_bfd_elf_assign_file_positions_for_non_load (abfd)) + return FALSE; /* After writing the headers, we need to write the sections too... */ num_sec = elf_numsections (abfd); @@ -7922,7 +7983,21 @@ _bfd_elf_set_section_contents (bfd *abfd, && ! _bfd_elf_compute_section_file_positions (abfd, NULL)) return FALSE; + if (!count) + return TRUE; + hdr = &elf_section_data (section)->this_hdr; + if (hdr->sh_offset == (file_ptr) -1) + { + /* We must compress this section. Write output to the buffer. */ + unsigned char *contents = hdr->contents; + if ((offset + count) > hdr->sh_size + || (section->flags & SEC_ELF_COMPRESS) == 0 + || contents == NULL) + abort (); + memcpy (contents + offset, location, count); + return TRUE; + } pos = hdr->sh_offset + offset; if (bfd_seek (abfd, pos, SEEK_SET) != 0 || bfd_bwrite (location, count, abfd) != count) diff --git a/bfd/elflink.c b/bfd/elflink.c index ea9246b..6efe1e4 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -10890,6 +10890,21 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) to count upwards while actually outputting the relocations. */ esdo->rel.count = 0; esdo->rela.count = 0; + + if (esdo->this_hdr.sh_offset == (file_ptr) -1) + { + /* Cache the section contents so that they can be compressed + later. Use bfd_malloc since it will be freed by + bfd_compress_section_contents. */ + unsigned char *contents = esdo->this_hdr.contents; + if ((o->flags & SEC_ELF_COMPRESS) == 0 || contents != NULL) + abort (); + contents + = (unsigned char *) bfd_malloc (esdo->this_hdr.sh_size); + if (contents == NULL) + goto error_return; + esdo->this_hdr.contents = contents; + } } /* We have now assigned file positions for all the sections except diff --git a/bfd/merge.c b/bfd/merge.c index 5f45ba6..174ec90 100644 --- a/bfd/merge.c +++ b/bfd/merge.c @@ -25,6 +25,7 @@ #include "sysdep.h" #include "bfd.h" +#include "elf-bfd.h" #include "libbfd.h" #include "hashtab.h" #include "libiberty.h" @@ -283,7 +284,8 @@ sec_merge_add (struct sec_merge_hash *tab, const char *str, } static bfd_boolean -sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry) +sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry, + unsigned char *contents, file_ptr offset) { struct sec_merge_sec_info *secinfo = entry->secinfo; asection *sec = secinfo->sec; @@ -306,7 +308,12 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry) len = -off & (entry->alignment - 1); if (len != 0) { - if (bfd_bwrite (pad, len, abfd) != len) + if (contents) + { + memcpy (contents + offset, pad, len); + offset += len; + } + else if (bfd_bwrite (pad, len, abfd) != len) goto err; off += len; } @@ -314,7 +321,12 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry) str = entry->root.string; len = entry->len; - if (bfd_bwrite (str, len, abfd) != len) + if (contents) + { + memcpy (contents + offset, str, len); + offset += len; + } + else if (bfd_bwrite (str, len, abfd) != len) goto err; off += len; @@ -322,9 +334,13 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry) /* Trailing alignment needed? */ off = sec->size - off; - if (off != 0 - && bfd_bwrite (pad, off, abfd) != off) - goto err; + if (off != 0) + { + if (contents) + memcpy (contents + offset, pad, off); + else if (bfd_bwrite (pad, off, abfd) != off) + goto err; + } if (pad != NULL) free (pad); @@ -785,6 +801,8 @@ _bfd_write_merged_section (bfd *output_bfd, asection *sec, void *psecinfo) { struct sec_merge_sec_info *secinfo; file_ptr pos; + unsigned char *contents; + Elf_Internal_Shdr *hdr; secinfo = (struct sec_merge_sec_info *) psecinfo; @@ -795,11 +813,26 @@ _bfd_write_merged_section (bfd *output_bfd, asection *sec, void *psecinfo) return TRUE; /* FIXME: octets_per_byte. */ - pos = sec->output_section->filepos + sec->output_offset; - if (bfd_seek (output_bfd, pos, SEEK_SET) != 0) - return FALSE; + hdr = &elf_section_data (sec->output_section)->this_hdr; + if (hdr->sh_offset == (file_ptr) -1) + { + /* We must compress this section. Write output to the + buffer. */ + contents = hdr->contents; + if ((sec->output_section->flags & SEC_ELF_COMPRESS) == 0 + || contents == NULL) + abort (); + } + else + { + contents = NULL; + pos = sec->output_section->filepos + sec->output_offset; + if (bfd_seek (output_bfd, pos, SEEK_SET) != 0) + return FALSE; + } - if (! sec_merge_emit (output_bfd, secinfo->first_str)) + if (! sec_merge_emit (output_bfd, secinfo->first_str, contents, + sec->output_offset)) return FALSE; return TRUE; diff --git a/bfd/section.c b/bfd/section.c index 4a6f2e4..d59a0e3 100644 --- a/bfd/section.c +++ b/bfd/section.c @@ -334,6 +334,10 @@ CODE_FRAGMENT . executables or shared objects. This is for COFF only. *} .#define SEC_COFF_SHARED 0x8000000 . +. {* This section should be compressed. This is for ELF linker +. internal use only. *} +.#define SEC_ELF_COMPRESS 0x8000000 +. . {* When a section with this flag is being linked, then if the size of . the input section is less than a page, it should not cross a page . boundary. If the size of the input section is one page or more, diff --git a/gas/ChangeLog b/gas/ChangeLog index c90f98c..d42aa75 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,7 @@ +2015-04-14 H.J. Lu <hongjiu.lu@intel.com> + + * as.h (compressed_debug_section_type): Removed. + 2015-04-14 Nick Clifton <nickc@redhat.com> * config/tc-rl78.h (TC_LINKRELAX_FIXUP): Define. @@ -370,16 +370,6 @@ COMMON int flag_strip_local_absolute; /* True if we should generate a traditional format object file. */ COMMON int flag_traditional_format; -/* Types of compressed debug sections. We currently support zlib. */ -enum compressed_debug_section_type -{ - COMPRESS_DEBUG_NONE = 0, - COMPRESS_DEBUG, - COMPRESS_DEBUG_ZLIB, - COMPRESS_DEBUG_GNU_ZLIB, - COMPRESS_DEBUG_GABI_ZLIB -}; - /* Type of compressed debug sections we should generate. */ COMMON enum compressed_debug_section_type flag_compress_debug; diff --git a/include/ChangeLog b/include/ChangeLog index 7d4919d..9afcc62 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,5 +1,9 @@ 2015-04-14 H.J. Lu <hongjiu.lu@intel.com> + * bfdlink.h (bfd_link_info): Add compress_debug. + +2015-04-14 H.J. Lu <hongjiu.lu@intel.com> + PR ld/pr17709 * bfdlink.h (bfd_link_info): Add extern_protected_data. diff --git a/include/bfdlink.h b/include/bfdlink.h index 1b15826..3989c60 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -431,6 +431,9 @@ struct bfd_link_info /* Separator between archive and filename in linker script filespecs. */ char path_separator; + /* Compress DWARF debug sections. */ + enum compressed_debug_section_type compress_debug; + /* Default stack size. Zero means default (often zero itself), -1 means explicitly zero-sized. */ bfd_signed_vma stacksize; diff --git a/ld/ChangeLog b/ld/ChangeLog index 3e944fe..bad213b 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,18 @@ 2015-04-14 H.J. Lu <hongjiu.lu@intel.com> + * ld.texinfo: Document --compress-debug-sections=. + * ldmain.c (main): Set BFD_COMPRESS on output_bfd if + COMPRESS_DEBUG is set. Set BFD_COMPRESS_GABI on output_bfd + for COMPRESS_DEBUG_GABI_ZLIB. + * lexsup.c (elf_static_list_options): Add + --compress-debug-sections=. + * emultempl/elf32.em (OPTION_COMPRESS_DEBUG): New. + (xtra_long): Add "compress-debug-sections". + (gld${EMULATION_NAME}_handle_option): Handle + OPTION_COMPRESS_DEBUG. + +2015-04-14 H.J. Lu <hongjiu.lu@intel.com> + PR ld/pr17709 * ld.texinfo: Document "-z noextern-protected-data". * ldmain.c (main): Initialize link_info.extern_protected_data diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 5db5a93..0802d76 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -2110,6 +2110,7 @@ fragment <<EOF #define OPTION_HASH_STYLE (OPTION_EXCLUDE_LIBS + 1) #define OPTION_BUILD_ID (OPTION_HASH_STYLE + 1) #define OPTION_AUDIT (OPTION_BUILD_ID + 1) +#define OPTION_COMPRESS_DEBUG (OPTION_AUDIT + 1) static void gld${EMULATION_NAME}_add_options @@ -2137,6 +2138,7 @@ EOF fi fragment <<EOF {"build-id", optional_argument, NULL, OPTION_BUILD_ID}, + {"compress-debug-sections", required_argument, NULL, OPTION_COMPRESS_DEBUG}, EOF if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then fragment <<EOF @@ -2186,6 +2188,19 @@ gld${EMULATION_NAME}_handle_option (int optc) emit_note_gnu_build_id = xstrdup (optarg); break; + case OPTION_COMPRESS_DEBUG: + if (strcasecmp (optarg, "none") == 0) + link_info.compress_debug = COMPRESS_DEBUG_NONE; + else if (strcasecmp (optarg, "zlib") == 0) + link_info.compress_debug = COMPRESS_DEBUG_ZLIB; + else if (strcasecmp (optarg, "zlib-gnu") == 0) + link_info.compress_debug = COMPRESS_DEBUG_GNU_ZLIB; + else if (strcasecmp (optarg, "zlib-gabi") == 0) + link_info.compress_debug = COMPRESS_DEBUG_GABI_ZLIB; + else + einfo (_("%P%F: invalid --compress-debug-sections option: \`%s'\n"), + optarg); + break; EOF if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 4348c88..77c02d6 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -2201,6 +2201,22 @@ new style GNU @code{.gnu.hash} section or @code{both} for both the classic ELF @code{.hash} and new style GNU @code{.gnu.hash} hash tables. The default is @code{sysv}. +@kindex --compress-debug-sections=none +@kindex --compress-debug-sections=zlib +@kindex --compress-debug-sections=zlib-gnu +@kindex --compress-debug-sections=zlib-gabi +@item --compress-debug-sections=none +@itemx --compress-debug-sections=zlib +@itemx --compress-debug-sections=zlib-gnu +@itemx --compress-debug-sections=zlib-gabi +On ELF platforms , these options control how DWARF debug sections are +compressed using zlib. @option{--compress-debug-sections=none} doesn't +compress DWARF debug sections. @option{--compress-debug-sections=zlib} +and @option{--compress-debug-sections=zlib-gnu} compress DWARF debug +sections and rename debug section names to begin with @samp{.zdebug} +instead of @samp{.debug}. @option{--compress-debug-sections=zlib-gabi} +compresses DWARF debug sections with SHF_COMPRESSED from the ELF ABI. + @kindex --reduce-memory-overheads @item --reduce-memory-overheads This option reduces memory requirements at ld runtime, at the expense of diff --git a/ld/ldmain.c b/ld/ldmain.c index 2ecb92d..a7b72bd 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -425,6 +425,13 @@ main (int argc, char **argv) else link_info.output_bfd->flags |= EXEC_P; + if ((link_info.compress_debug & COMPRESS_DEBUG)) + { + link_info.output_bfd->flags |= BFD_COMPRESS; + if (link_info.compress_debug == COMPRESS_DEBUG_GABI_ZLIB) + link_info.output_bfd->flags |= BFD_COMPRESS_GABI; + } + ldwrite (); if (config.map_file != NULL) diff --git a/ld/lexsup.c b/ld/lexsup.c index 4a71ba4..b618241 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -1722,6 +1722,9 @@ elf_static_list_options (FILE *file) fprintf (file, _("\ --build-id[=STYLE] Generate build ID note\n")); fprintf (file, _("\ + --compress-debug-sections=[none|zlib|zlib-gnu|zlib-gabi]\n\ + Compress DWARF debug sections using zlib\n")); + fprintf (file, _("\ -z common-page-size=SIZE Set common page size to SIZE\n")); fprintf (file, _("\ -z max-page-size=SIZE Set maximum page size to SIZE\n")); diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index c2ed134..54ae0ae 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,16 @@ +2015-04-14 H.J. Lu <hongjiu.lu@intel.com> + + * ld-elf/compress.exp (build_tests): Add tests for + --compress-debug-sections=. + (run_tests): Likewise. + Add additonal tests for --compress-debug-sections=. + * ld-elf/gabiend.rt: New file. + * ld-elf/gabinormal.rt: Likewise. + * ld-elf/gnubegin.rS: Likewise. + * ld-elf/gnunormal.rS: Likewise. + * ld-elf/zlibbegin.rS: Likewise. + * ld-elf/zlibnormal.rS: Likewise. + 2015-04-15 Alan Modra <amodra@gmail.com> * ld-gc/pr18223.d: xfail tic6x. diff --git a/ld/testsuite/ld-elf/compress.exp b/ld/testsuite/ld-elf/compress.exp index adb7fc2..e2448b9 100644 --- a/ld/testsuite/ld-elf/compress.exp +++ b/ld/testsuite/ld-elf/compress.exp @@ -49,7 +49,8 @@ set build_tests { "-shared" "-fPIC -g -Wa,--compress-debug-sections" {foo.c} {} "libfoo.so"} {"Build libbar.so with compressed debug sections" - "-shared" "-fPIC -g -Wa,--compress-debug-sections" + "-shared -Wl,--compress-debug-sections=none" + "-fPIC -g -Wa,--compress-debug-sections" {begin.c end.c} {} "libbar.so"} {"Build libfoozlib.so with compressed debug sections with zlib-gabi" "-shared" "-fPIC -g -Wa,--compress-debug-sections=zlib-gabi" @@ -57,6 +58,30 @@ set build_tests { {"Build libbarzlib.so with compressed debug sections with zlib-gabi" "-shared" "-fPIC -g -Wa,--compress-debug-sections=zlib-gabi" {begin.c end.c} {} "libbarzlib.so"} + {"Build libzlibfoo.so with zlib compressed debug sections" + "-shared -Wl,--compress-debug-sections=zlib" + "-fPIC -g -Wa,--compress-debug-sections=zlib" + {foo.c} {} "libzlibfoo.so"} + {"Build libgnufoo.so with zlib-gnu compressed debug sections" + "-shared -Wl,--compress-debug-sections=zlib-gnu" + "-fPIC -g -Wa,--compress-debug-sections=zlib-gnu" + {foo.c} {} "libgnufoo.so"} + {"Build libgabifoo.so with zlib-gabi compressed debug sections" + "-shared -Wl,--compress-debug-sections=zlib-gabi" + "-fPIC -g -Wa,--compress-debug-sections=zlib-gabi" + {foo.c} {} "libgabifoo.so"} + {"Build zlibbegin.o with zlib compressed debug sections" + "-r -nostdlib -Wl,--compress-debug-sections=zlib" + "-g -Wa,--compress-debug-sections=zlib" + {begin.c} {} "zlibbegin.o"} + {"Build gnubegin.o with zlib-gnu compressed debug sections" + "-r -nostdlib -Wl,--compress-debug-sections=zlib-gnu" + "-g -Wa,--compress-debug-sections=zlib-gnu" + {begin.c} {} "gnubegin.o"} + {"Build gabiend.o with zlib-gabi compressed debug sections" + "-r -nostdlib -Wl,--compress-debug-sections=zlib-gabi" + "-g -Wa,--compress-debug-sections=zlib-gnu" + {end.c} {} "gabiend.o"} } set run_tests { @@ -66,6 +91,15 @@ set run_tests { {"Run normal with libfoo.so with compressed debug sections with zlib-gabi" "tmpdir/begin.o tmpdir/libfoozlib.so tmpdir/end.o" "" {main.c} "normal" "normal.out" "-Wa,--compress-debug-sections=zlib-gabi"} + {"Run zlibnormal with libzlibfoo.so with zlib compressed debug sections" + "tmpdir/begin.o tmpdir/libzlibfoo.so tmpdir/end.o --compress-debug-sections=zlib" "" + {main.c} "zlibnormal" "normal.out" "-Wa,--compress-debug-sections=zlib"} + {"Run gnunormal with libgnufoo.so with zlib-gnu compressed debug sections" + "tmpdir/gnubegin.o tmpdir/libgnufoo.so tmpdir/end.o --compress-debug-sections=zlib-gnu" "" + {main.c} "gnunormal" "normal.out" "-Wa,--compress-debug-sections=zlib-gnu"} + {"Run gabinormal with libgabifoo.so with zlib-gabi compressed debug sections" + "tmpdir/zlibbegin.o tmpdir/libgabifoo.so tmpdir/gabiend.o --compress-debug-sections=zlib-gabi" "" + {main.c} "gabinormal" "normal.out" "-Wa,--compress-debug-sections=zlib-gabi"} } run_cc_link_tests $build_tests @@ -79,3 +113,134 @@ if { [catch {exec cmp tmpdir/libfoo.so tmpdir/libfoozlib.so}] } then { } else { pass "$test_name" } + +global READELF + +set test_name "Link -r with zlib compressed debug output" +set test zlibbegin +send_log "$READELF -S -W tmpdir/$test.o > tmpdir/$test.out\n" +set got [remote_exec host "$READELF -S -W tmpdir/$test.o" "" "/dev/null" "tmpdir/$test.out"] +if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then { + send_log "$got\n" + unresolved "$test_name" +} +if { [regexp_diff tmpdir/$test.out $srcdir/$subdir/$test.rS] } then { + fail "$test_name" +} else { + pass "$test_name" +} + +set test_name "Link -r with zlib-gnu compressed debug output" +set test gnubegin +send_log "$READELF -S -W tmpdir/$test.o > tmpdir/$test.out\n" +set got [remote_exec host "$READELF -S -W tmpdir/$test.o" "" "/dev/null" "tmpdir/$test.out"] +if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then { + send_log "$got\n" + unresolved "$test_name" +} +if { [regexp_diff tmpdir/$test.out $srcdir/$subdir/$test.rS] } then { + fail "$test_name" +} else { + pass "$test_name" +} + +set test_name "Link -r with zlib-gabi compressed debug output" +set test gabiend +send_log "$READELF -t -W tmpdir/$test.o > tmpdir/$test.out\n" +set got [remote_exec host "$READELF -t -W tmpdir/$test.o" "" "/dev/null" "tmpdir/$test.out"] +if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then { + send_log "$got\n" + unresolved "$test_name" +} +if { [regexp_diff tmpdir/$test.out $srcdir/$subdir/$test.rt] } then { + fail "$test_name" +} else { + pass "$test_name" +} + +set test_name "Link with zlib compressed debug output" +set test normal +send_log "$READELF -w tmpdir/$test > tmpdir/$test.out\n" +set got [remote_exec host "$READELF -w tmpdir/$test" "" "/dev/null" "tmpdir/$test.out"] +if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then { + send_log "$got\n" + unresolved "$test_name" +} + +set test_name "Link with zlib compressed debug output" +set test zlibnormal +send_log "$READELF -w tmpdir/$test | sed -e \"s/.zdebug_/.debug_/\" > tmpdir/$test.out\n" +set got [remote_exec host "$READELF -w tmpdir/$test | sed -e \"s/.zdebug_/.debug_/\"" "" "/dev/null" "tmpdir/$test.out"] +if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then { + send_log "$got\n" + unresolved "$test_name" +} +if { [catch {exec cmp tmpdir/normal.out tmpdir/$test.out}] } then { + send_log "tmpdir/normal.out tmpdir/$test.out differ.\n" + fail "$test_name" +} else { + pass "$test_name" +} +send_log "$READELF -S -W tmpdir/$test' > tmpdir/$test.out\n" +set got [remote_exec host "$READELF -S -W tmpdir/$test" "" "/dev/null" "tmpdir/$test.out"] +if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then { + send_log "$got\n" + unresolved "$test_name" +} +if { [regexp_diff tmpdir/$test.out $srcdir/$subdir/$test.rS] } then { + fail "$test_name" +} else { + pass "$test_name" +} + +set test_name "Link with zlib-gnu compressed debug output" +set test gnunormal +send_log "$READELF -w tmpdir/$test | sed -e \"s/.zdebug_/.debug_/\" > tmpdir/$test.out\n" +set got [remote_exec host "$READELF -w tmpdir/$test | sed -e \"s/.zdebug_/.debug_/\"" "" "/dev/null" "tmpdir/$test.out"] +if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then { + send_log "$got\n" + unresolved "$test_name" +} +if { [catch {exec cmp tmpdir/normal.out tmpdir/$test.out}] } then { + send_log "tmpdir/normal.out tmpdir/$test.out differ.\n" + fail "$test_name" +} else { + pass "$test_name" +} +send_log "$READELF -S -W tmpdir/$test' > tmpdir/$test.out\n" +set got [remote_exec host "$READELF -S -W tmpdir/$test" "" "/dev/null" "tmpdir/$test.out"] +if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then { + send_log "$got\n" + unresolved "$test_name" +} +if { [regexp_diff tmpdir/$test.out $srcdir/$subdir/$test.rS] } then { + fail "$test_name" +} else { + pass "$test_name" +} + +set test gabinormal +set test_name "Link with zlib-gabi compressed debug output" +send_log "$READELF -w tmpdir/$test > tmpdir/$test.out\n" +set got [remote_exec host "$READELF -w tmpdir/$test" "" "/dev/null" "tmpdir/$test.out"] +if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then { + send_log "$got\n" + unresolved "$test_name" +} +if { [catch {exec cmp tmpdir/normal.out tmpdir/$test.out}] } then { + send_log "tmpdir/normal.out tmpdir/$test.out differ.\n" + fail "$test_name" +} else { + pass "$test_name" +} +send_log "$READELF -t -W tmpdir/$test > tmpdir/$test.out\n" +set got [remote_exec host "$READELF -t -W tmpdir/$test" "" "/dev/null" "tmpdir/$test.out"] +if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then { + send_log "$got\n" + unresolved "$test_name" +} +if { [regexp_diff tmpdir/$test.out $srcdir/$subdir/$test.rt] } then { + fail "$test_name" +} else { + pass "$test_name" +} diff --git a/ld/testsuite/ld-elf/gabiend.rt b/ld/testsuite/ld-elf/gabiend.rt new file mode 100644 index 0000000..23bc36c --- /dev/null +++ b/ld/testsuite/ld-elf/gabiend.rt @@ -0,0 +1,4 @@ +#... + +\[[0-9a-f]+\]: .*COMPRESSED + +ZLIB, [0-9a-f]+, 1 +#pass diff --git a/ld/testsuite/ld-elf/gabinormal.rt b/ld/testsuite/ld-elf/gabinormal.rt new file mode 100644 index 0000000..23bc36c --- /dev/null +++ b/ld/testsuite/ld-elf/gabinormal.rt @@ -0,0 +1,4 @@ +#... + +\[[0-9a-f]+\]: .*COMPRESSED + +ZLIB, [0-9a-f]+, 1 +#pass diff --git a/ld/testsuite/ld-elf/gnubegin.rS b/ld/testsuite/ld-elf/gnubegin.rS new file mode 100644 index 0000000..54de24c --- /dev/null +++ b/ld/testsuite/ld-elf/gnubegin.rS @@ -0,0 +1,3 @@ +#... + +\[[ 0-9]+\] .zdebug_.* +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ [0-9a-f]+ +0 +0 +1 +#pass diff --git a/ld/testsuite/ld-elf/gnunormal.rS b/ld/testsuite/ld-elf/gnunormal.rS new file mode 100644 index 0000000..54de24c --- /dev/null +++ b/ld/testsuite/ld-elf/gnunormal.rS @@ -0,0 +1,3 @@ +#... + +\[[ 0-9]+\] .zdebug_.* +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ [0-9a-f]+ +0 +0 +1 +#pass diff --git a/ld/testsuite/ld-elf/zlibbegin.rS b/ld/testsuite/ld-elf/zlibbegin.rS new file mode 100644 index 0000000..54de24c --- /dev/null +++ b/ld/testsuite/ld-elf/zlibbegin.rS @@ -0,0 +1,3 @@ +#... + +\[[ 0-9]+\] .zdebug_.* +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ [0-9a-f]+ +0 +0 +1 +#pass diff --git a/ld/testsuite/ld-elf/zlibnormal.rS b/ld/testsuite/ld-elf/zlibnormal.rS new file mode 100644 index 0000000..54de24c --- /dev/null +++ b/ld/testsuite/ld-elf/zlibnormal.rS @@ -0,0 +1,3 @@ +#... + +\[[ 0-9]+\] .zdebug_.* +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ [0-9a-f]+ +0 +0 +1 +#pass |