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.
This commit is contained in:
H.J. Lu 2015-04-14 22:01:25 -07:00
parent ecd272101d
commit 0ce398f106
25 changed files with 517 additions and 32 deletions

View File

@ -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> 2015-04-15 Alan Modra <amodra@gmail.com>
* elf32-rl78.c (rl78_elf_relocate_section): Typo fix. * elf32-rl78.c (rl78_elf_relocate_section): Typo fix.

View File

@ -437,6 +437,17 @@ extern void bfd_hash_traverse
this size. */ this size. */
extern unsigned long bfd_hash_set_default_size (unsigned long); 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 /* This structure is used to keep track of stabs in sections
information while linking. */ information while linking. */

View File

@ -444,6 +444,17 @@ extern void bfd_hash_traverse
this size. */ this size. */
extern unsigned long bfd_hash_set_default_size (unsigned long); 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 /* This structure is used to keep track of stabs in sections
information while linking. */ information while linking. */
@ -1378,6 +1389,10 @@ typedef struct bfd_section
executables or shared objects. This is for COFF only. */ executables or shared objects. This is for COFF only. */
#define SEC_COFF_SHARED 0x8000000 #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 /* 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 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, 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_boolean bfd_init_section_compress_status
(bfd *abfd, asection *section); (bfd *abfd, asection *section);
bfd_boolean bfd_compress_section
(bfd *abfd, asection *section, bfd_byte *uncompressed_buffer);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -72,7 +72,8 @@ decompress_contents (bfd_byte *compressed_buffer,
static bfd_size_type static bfd_size_type
bfd_compress_section_contents (bfd *abfd, sec_ptr sec, bfd_compress_section_contents (bfd *abfd, sec_ptr sec,
bfd_byte *uncompressed_buffer, bfd_byte *uncompressed_buffer,
bfd_size_type uncompressed_size) bfd_size_type uncompressed_size,
bfd_boolean write_compress)
{ {
uLong compressed_size; uLong compressed_size;
bfd_byte *buffer; bfd_byte *buffer;
@ -176,8 +177,11 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec,
compressed_size += header_size; compressed_size += header_size;
/* PR binutils/18087: If compression didn't make the section smaller, /* PR binutils/18087: If compression didn't make the section smaller,
just keep it uncompressed. */ just keep it uncompressed. We always generate .zdebug_* section
if (compressed_size < uncompressed_size) 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); 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_size = bfd_compress_section_contents (abfd, sec,
uncompressed_buffer, uncompressed_buffer,
uncompressed_size); uncompressed_size,
FALSE);
ret = uncompressed_size != 0; ret = uncompressed_size != 0;
} }
return ret; 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;
}

View File

@ -2752,6 +2752,7 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
struct bfd_elf_section_data *esd = elf_section_data (asect); struct bfd_elf_section_data *esd = elf_section_data (asect);
Elf_Internal_Shdr *this_hdr; Elf_Internal_Shdr *this_hdr;
unsigned int sh_type; unsigned int sh_type;
const char *name = asect->name;
if (arg->failed) if (arg->failed)
{ {
@ -2762,8 +2763,38 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
this_hdr = &esd->this_hdr; 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), 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) if (this_hdr->sh_name == (unsigned int) -1)
{ {
arg->failed = TRUE; 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) else if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
&& hdr->bfd_section == NULL) && 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_onesymtab (abfd)]
|| hdr == i_shdrpp[elf_symtab_shndx (abfd)] || hdr == i_shdrpp[elf_symtab_shndx (abfd)]
|| hdr == i_shdrpp[elf_strtab_sec (abfd)]) || hdr == i_shdrpp[elf_strtab_sec (abfd)])
@ -5365,6 +5399,9 @@ assign_file_positions_except_relocs (bfd *abfd,
hdr = *hdrpp; hdr = *hdrpp;
if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA) if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
&& hdr->bfd_section == NULL) && 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_onesymtab (abfd)
|| i == elf_symtab_shndx (abfd) || i == elf_symtab_shndx (abfd)
|| i == elf_strtab_sec (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 /* Assign file positions for all the reloc sections which are not part
of the loadable file image, and the file position of section headers. */ of the loadable file image, and the file position of section headers. */
static void static bfd_boolean
_bfd_elf_assign_file_positions_for_relocs (bfd *abfd) _bfd_elf_assign_file_positions_for_non_load (bfd *abfd)
{ {
file_ptr off; file_ptr off;
unsigned int i, num_sec; unsigned int i, num_sec;
@ -5535,9 +5572,30 @@ _bfd_elf_assign_file_positions_for_relocs (bfd *abfd)
Elf_Internal_Shdr *shdrp; Elf_Internal_Shdr *shdrp;
shdrp = *shdrpp; shdrp = *shdrpp;
if ((shdrp->sh_type == SHT_REL || shdrp->sh_type == SHT_RELA) if (shdrp->sh_offset == -1)
&& shdrp->sh_offset == -1) {
off = _bfd_elf_assign_file_position_for_section (shdrp, off, TRUE); 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. */ /* Place the section headers. */
@ -5547,6 +5605,8 @@ _bfd_elf_assign_file_positions_for_relocs (bfd *abfd)
i_ehdrp->e_shoff = off; i_ehdrp->e_shoff = off;
off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize; off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize;
elf_next_file_pos (abfd) = off; elf_next_file_pos (abfd) = off;
return TRUE;
} }
bfd_boolean bfd_boolean
@ -5569,7 +5629,8 @@ _bfd_elf_write_object_contents (bfd *abfd)
if (failed) if (failed)
return FALSE; 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... */ /* After writing the headers, we need to write the sections too... */
num_sec = elf_numsections (abfd); num_sec = elf_numsections (abfd);
@ -7922,7 +7983,21 @@ _bfd_elf_set_section_contents (bfd *abfd,
&& ! _bfd_elf_compute_section_file_positions (abfd, NULL)) && ! _bfd_elf_compute_section_file_positions (abfd, NULL))
return FALSE; return FALSE;
if (!count)
return TRUE;
hdr = &elf_section_data (section)->this_hdr; 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; pos = hdr->sh_offset + offset;
if (bfd_seek (abfd, pos, SEEK_SET) != 0 if (bfd_seek (abfd, pos, SEEK_SET) != 0
|| bfd_bwrite (location, count, abfd) != count) || bfd_bwrite (location, count, abfd) != count)

View File

@ -10890,6 +10890,21 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
to count upwards while actually outputting the relocations. */ to count upwards while actually outputting the relocations. */
esdo->rel.count = 0; esdo->rel.count = 0;
esdo->rela.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 /* We have now assigned file positions for all the sections except

View File

@ -25,6 +25,7 @@
#include "sysdep.h" #include "sysdep.h"
#include "bfd.h" #include "bfd.h"
#include "elf-bfd.h"
#include "libbfd.h" #include "libbfd.h"
#include "hashtab.h" #include "hashtab.h"
#include "libiberty.h" #include "libiberty.h"
@ -283,7 +284,8 @@ sec_merge_add (struct sec_merge_hash *tab, const char *str,
} }
static bfd_boolean 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; struct sec_merge_sec_info *secinfo = entry->secinfo;
asection *sec = secinfo->sec; asection *sec = secinfo->sec;
@ -306,7 +308,12 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry)
len = -off & (entry->alignment - 1); len = -off & (entry->alignment - 1);
if (len != 0) 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; goto err;
off += len; off += len;
} }
@ -314,7 +321,12 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry)
str = entry->root.string; str = entry->root.string;
len = entry->len; 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; goto err;
off += len; off += len;
@ -322,9 +334,13 @@ sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry)
/* Trailing alignment needed? */ /* Trailing alignment needed? */
off = sec->size - off; off = sec->size - off;
if (off != 0 if (off != 0)
&& bfd_bwrite (pad, off, abfd) != off) {
goto err; if (contents)
memcpy (contents + offset, pad, off);
else if (bfd_bwrite (pad, off, abfd) != off)
goto err;
}
if (pad != NULL) if (pad != NULL)
free (pad); free (pad);
@ -785,6 +801,8 @@ _bfd_write_merged_section (bfd *output_bfd, asection *sec, void *psecinfo)
{ {
struct sec_merge_sec_info *secinfo; struct sec_merge_sec_info *secinfo;
file_ptr pos; file_ptr pos;
unsigned char *contents;
Elf_Internal_Shdr *hdr;
secinfo = (struct sec_merge_sec_info *) psecinfo; secinfo = (struct sec_merge_sec_info *) psecinfo;
@ -795,11 +813,26 @@ _bfd_write_merged_section (bfd *output_bfd, asection *sec, void *psecinfo)
return TRUE; return TRUE;
/* FIXME: octets_per_byte. */ /* FIXME: octets_per_byte. */
pos = sec->output_section->filepos + sec->output_offset; hdr = &elf_section_data (sec->output_section)->this_hdr;
if (bfd_seek (output_bfd, pos, SEEK_SET) != 0) if (hdr->sh_offset == (file_ptr) -1)
return FALSE; {
/* 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 FALSE;
return TRUE; return TRUE;

View File

@ -334,6 +334,10 @@ CODE_FRAGMENT
. executables or shared objects. This is for COFF only. *} . executables or shared objects. This is for COFF only. *}
.#define SEC_COFF_SHARED 0x8000000 .#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 . {* 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 . 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, . boundary. If the size of the input section is one page or more,

View File

@ -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> 2015-04-14 Nick Clifton <nickc@redhat.com>
* config/tc-rl78.h (TC_LINKRELAX_FIXUP): Define. * config/tc-rl78.h (TC_LINKRELAX_FIXUP): Define.

View File

@ -370,16 +370,6 @@ COMMON int flag_strip_local_absolute;
/* True if we should generate a traditional format object file. */ /* True if we should generate a traditional format object file. */
COMMON int flag_traditional_format; COMMON int flag_traditional_format;
/* 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. */ /* Type of compressed debug sections we should generate. */
COMMON enum compressed_debug_section_type flag_compress_debug; COMMON enum compressed_debug_section_type flag_compress_debug;

View File

@ -1,3 +1,7 @@
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> 2015-04-14 H.J. Lu <hongjiu.lu@intel.com>
PR ld/pr17709 PR ld/pr17709

View File

@ -431,6 +431,9 @@ struct bfd_link_info
/* Separator between archive and filename in linker script filespecs. */ /* Separator between archive and filename in linker script filespecs. */
char path_separator; char path_separator;
/* Compress DWARF debug sections. */
enum compressed_debug_section_type compress_debug;
/* Default stack size. Zero means default (often zero itself), -1 /* Default stack size. Zero means default (often zero itself), -1
means explicitly zero-sized. */ means explicitly zero-sized. */
bfd_signed_vma stacksize; bfd_signed_vma stacksize;

View File

@ -1,3 +1,16 @@
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> 2015-04-14 H.J. Lu <hongjiu.lu@intel.com>
PR ld/pr17709 PR ld/pr17709

View File

@ -2110,6 +2110,7 @@ fragment <<EOF
#define OPTION_HASH_STYLE (OPTION_EXCLUDE_LIBS + 1) #define OPTION_HASH_STYLE (OPTION_EXCLUDE_LIBS + 1)
#define OPTION_BUILD_ID (OPTION_HASH_STYLE + 1) #define OPTION_BUILD_ID (OPTION_HASH_STYLE + 1)
#define OPTION_AUDIT (OPTION_BUILD_ID + 1) #define OPTION_AUDIT (OPTION_BUILD_ID + 1)
#define OPTION_COMPRESS_DEBUG (OPTION_AUDIT + 1)
static void static void
gld${EMULATION_NAME}_add_options gld${EMULATION_NAME}_add_options
@ -2137,6 +2138,7 @@ EOF
fi fi
fragment <<EOF fragment <<EOF
{"build-id", optional_argument, NULL, OPTION_BUILD_ID}, {"build-id", optional_argument, NULL, OPTION_BUILD_ID},
{"compress-debug-sections", required_argument, NULL, OPTION_COMPRESS_DEBUG},
EOF EOF
if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
fragment <<EOF fragment <<EOF
@ -2186,6 +2188,19 @@ gld${EMULATION_NAME}_handle_option (int optc)
emit_note_gnu_build_id = xstrdup (optarg); emit_note_gnu_build_id = xstrdup (optarg);
break; 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 EOF
if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then

View File

@ -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} the classic ELF @code{.hash} and new style GNU @code{.gnu.hash}
hash tables. The default is @code{sysv}. 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 @kindex --reduce-memory-overheads
@item --reduce-memory-overheads @item --reduce-memory-overheads
This option reduces memory requirements at ld runtime, at the expense of This option reduces memory requirements at ld runtime, at the expense of

View File

@ -425,6 +425,13 @@ main (int argc, char **argv)
else else
link_info.output_bfd->flags |= EXEC_P; 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 (); ldwrite ();
if (config.map_file != NULL) if (config.map_file != NULL)

View File

@ -1722,6 +1722,9 @@ elf_static_list_options (FILE *file)
fprintf (file, _("\ fprintf (file, _("\
--build-id[=STYLE] Generate build ID note\n")); --build-id[=STYLE] Generate build ID note\n"));
fprintf (file, _("\ 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")); -z common-page-size=SIZE Set common page size to SIZE\n"));
fprintf (file, _("\ fprintf (file, _("\
-z max-page-size=SIZE Set maximum page size to SIZE\n")); -z max-page-size=SIZE Set maximum page size to SIZE\n"));

View File

@ -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> 2015-04-15 Alan Modra <amodra@gmail.com>
* ld-gc/pr18223.d: xfail tic6x. * ld-gc/pr18223.d: xfail tic6x.

View File

@ -49,7 +49,8 @@ set build_tests {
"-shared" "-fPIC -g -Wa,--compress-debug-sections" "-shared" "-fPIC -g -Wa,--compress-debug-sections"
{foo.c} {} "libfoo.so"} {foo.c} {} "libfoo.so"}
{"Build libbar.so with compressed debug sections" {"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"} {begin.c end.c} {} "libbar.so"}
{"Build libfoozlib.so with compressed debug sections with zlib-gabi" {"Build libfoozlib.so with compressed debug sections with zlib-gabi"
"-shared" "-fPIC -g -Wa,--compress-debug-sections=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" {"Build libbarzlib.so with compressed debug sections with zlib-gabi"
"-shared" "-fPIC -g -Wa,--compress-debug-sections=zlib-gabi" "-shared" "-fPIC -g -Wa,--compress-debug-sections=zlib-gabi"
{begin.c end.c} {} "libbarzlib.so"} {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 { set run_tests {
@ -66,6 +91,15 @@ set run_tests {
{"Run normal with libfoo.so with compressed debug sections with zlib-gabi" {"Run normal with libfoo.so with compressed debug sections with zlib-gabi"
"tmpdir/begin.o tmpdir/libfoozlib.so tmpdir/end.o" "" "tmpdir/begin.o tmpdir/libfoozlib.so tmpdir/end.o" ""
{main.c} "normal" "normal.out" "-Wa,--compress-debug-sections=zlib-gabi"} {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 run_cc_link_tests $build_tests
@ -79,3 +113,134 @@ if { [catch {exec cmp tmpdir/libfoo.so tmpdir/libfoozlib.so}] } then {
} else { } else {
pass "$test_name" 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"
}

View File

@ -0,0 +1,4 @@
#...
+\[[0-9a-f]+\]: .*COMPRESSED
+ZLIB, [0-9a-f]+, 1
#pass

View File

@ -0,0 +1,4 @@
#...
+\[[0-9a-f]+\]: .*COMPRESSED
+ZLIB, [0-9a-f]+, 1
#pass

View File

@ -0,0 +1,3 @@
#...
+\[[ 0-9]+\] .zdebug_.* +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ [0-9a-f]+ +0 +0 +1
#pass

View File

@ -0,0 +1,3 @@
#...
+\[[ 0-9]+\] .zdebug_.* +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ [0-9a-f]+ +0 +0 +1
#pass

View File

@ -0,0 +1,3 @@
#...
+\[[ 0-9]+\] .zdebug_.* +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ [0-9a-f]+ +0 +0 +1
#pass

View File

@ -0,0 +1,3 @@
#...
+\[[ 0-9]+\] .zdebug_.* +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ [0-9a-f]+ +0 +0 +1
#pass