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:
parent
ecd272101d
commit
0ce398f106
@ -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.
|
||||
|
11
bfd/bfd-in.h
11
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. */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
89
bfd/elf.c
89
bfd/elf.c
@ -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)
|
||||
|
@ -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
|
||||
|
53
bfd/merge.c
53
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;
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
10
gas/as.h
10
gas/as.h
@ -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;
|
||||
|
||||
|
@ -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>
|
||||
|
||||
PR ld/pr17709
|
||||
|
@ -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;
|
||||
|
13
ld/ChangeLog
13
ld/ChangeLog
@ -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>
|
||||
|
||||
PR ld/pr17709
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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"));
|
||||
|
@ -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.
|
||||
|
@ -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"
|
||||
}
|
||||
|
4
ld/testsuite/ld-elf/gabiend.rt
Normal file
4
ld/testsuite/ld-elf/gabiend.rt
Normal file
@ -0,0 +1,4 @@
|
||||
#...
|
||||
+\[[0-9a-f]+\]: .*COMPRESSED
|
||||
+ZLIB, [0-9a-f]+, 1
|
||||
#pass
|
4
ld/testsuite/ld-elf/gabinormal.rt
Normal file
4
ld/testsuite/ld-elf/gabinormal.rt
Normal file
@ -0,0 +1,4 @@
|
||||
#...
|
||||
+\[[0-9a-f]+\]: .*COMPRESSED
|
||||
+ZLIB, [0-9a-f]+, 1
|
||||
#pass
|
3
ld/testsuite/ld-elf/gnubegin.rS
Normal file
3
ld/testsuite/ld-elf/gnubegin.rS
Normal 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
|
3
ld/testsuite/ld-elf/gnunormal.rS
Normal file
3
ld/testsuite/ld-elf/gnunormal.rS
Normal 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
|
3
ld/testsuite/ld-elf/zlibbegin.rS
Normal file
3
ld/testsuite/ld-elf/zlibbegin.rS
Normal 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
|
3
ld/testsuite/ld-elf/zlibnormal.rS
Normal file
3
ld/testsuite/ld-elf/zlibnormal.rS
Normal 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
|
Loading…
Reference in New Issue
Block a user