forked from Imagelibrary/binutils-gdb
Add SHF_COMPRESSED support to gas and objcopy
This patch adds --compress-debug-sections={none|zlib|zlib-gnu|zlib-gabi}
options to gas and objcopy for ELF files. They control how DWARF debug
sections are compressed. --compress-debug-sections=none is equivalent to
--nocompress-debug-sections. --compress-debug-sections=zlib and
--compress-debug-sections=zlib-gnu are equivalent to
--compress-debug-sections. --compress-debug-sections=zlib-gabi compresses
DWARF debug sections with SHF_COMPRESSED from the ELF ABI. No linker
changes are required to support SHF_COMPRESSED.
bfd/
* archive.c (_bfd_get_elt_at_filepos): Also copy BFD_COMPRESS_GABI
bit.
* bfd.c (bfd::flags): Increase size to 18 bits.
(BFD_COMPRESS_GABI): New.
(BFD_FLAGS_SAVED): Add BFD_COMPRESS_GABI.
(BFD_FLAGS_FOR_BFD_USE_MASK): Likewise.
(bfd_update_compression_header): New fuction.
(bfd_check_compression_header): Likewise.
(bfd_get_compression_header_size): Likewise.
(bfd_is_section_compressed_with_header): Likewise.
* compress.c (MAX_COMPRESSION_HEADER_SIZE): New.
(bfd_compress_section_contents): Return the uncompressed size if
the full section contents is compressed successfully. Support
converting from/to .zdebug* sections.
(bfd_get_full_section_contents): Call
bfd_get_compression_header_size to get compression header size.
(bfd_is_section_compressed): Renamed to ...
(bfd_is_section_compressed_with_header): This. Add a pointer
argument to return compression header size.
(bfd_is_section_compressed): Use it.
(bfd_init_section_decompress_status): Call
bfd_get_compression_header_size to get compression header size.
Return FALSE if uncompressed section size is 0.
* elf.c (_bfd_elf_make_section_from_shdr): Support converting
from/to .zdebug* sections.
* bfd-in2.h: Regenerated.
binutils/
* objcopy.c (do_debug_sections): Add compress_zlib,
compress_gnu_zlib and compress_gabi_zlib.
(copy_options): Use optional_argument on compress-debug-sections.
(copy_usage): Update --compress-debug-sections.
(copy_file): Handle compress_zlib, compress_gnu_zlib and
compress_gabi_zlib.
(copy_main): Handle
--compress-debug-sections={none|zlib|zlib-gnu|zlib-gabi}.
* doc/binutils.texi: Document
--compress-debug-sections={none|zlib|zlib-gnu|zlib-gabi}.
binutils/testsuite/
* compress.exp: Add tests for
--compress-debug-sections={none|zlib|zlib-gnu|zlib-gabi}.
* binutils-all/dw2-3.rS: New file.
* binutils-all/dw2-3.rt: Likewise.
* binutils-all/libdw2-compressedgabi.out: Likewise.
gas/
* as.c (show_usage): Update --compress-debug-sections.
(std_longopts): Use optional_argument on compress-debug-sections.
(parse_args): Handle
--compress-debug-sections={none|zlib|zlib-gnu|zlib-gabi}.
* as.h (compressed_debug_section_type): New.
(flag_compress_debug): Change type to compressed_debug_section_type.
--compress-debug-sections={none|zlib|zlib-gnu|zlib-gabi}.
* write.c (compress_debug): Set BFD_COMPRESS_GABI for
--compress-debug-sections=zlib-gabi. Call
bfd_get_compression_header_size to get compression header size.
Don't rename section name for --compress-debug-sections=zlib-gabi.
* config/tc-i386.c (compressed_debug_section_type): Set to
COMPRESS_DEBUG_ZLIB.
* doc/as.texinfo: Document
--compress-debug-sections={none|zlib|zlib-gnu|zlib-gabi}.
gas/testsuite/
* gas/i386/dw2-compressed-1.d: New file.
* gas/i386/dw2-compressed-2.d: Likewise.
* gas/i386/dw2-compressed-3.d: Likewise.
* gas/i386/x86-64-dw2-compressed-2.d: Likewise.
* gas/i386/i386.exp: Run dw2-compressed-2, dw2-compressed-1,
dw2-compressed-3 and x86-64-dw2-compressed-2.
ld/testsuite/
* ld-elf/compress.exp: Add a test for
--compress-debug-sections=zlib-gabi.
(build_tests): Add 2 tests for --compress-debug-sections=zlib-gabi.
(run_tests): Likewise.
Verify linker output with zlib-gabi compressed debug input.
* ld-elf/compressed1a.d: New file.
* ld-elf/compressed1b.d: Likewise.
* ld-elf/compressed1c.d: Likewise.
This commit is contained in:
75
bfd/elf.c
75
bfd/elf.c
@@ -1042,26 +1042,35 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
|
||||
{
|
||||
enum { nothing, compress, decompress } action = nothing;
|
||||
char *new_name;
|
||||
int compression_header_size;
|
||||
bfd_boolean compressed
|
||||
= bfd_is_section_compressed_with_header (abfd, newsect,
|
||||
&compression_header_size);
|
||||
|
||||
if (bfd_is_section_compressed (abfd, newsect))
|
||||
if (compressed)
|
||||
{
|
||||
/* Compressed section. Check if we should decompress. */
|
||||
if ((abfd->flags & BFD_DECOMPRESS))
|
||||
action = decompress;
|
||||
}
|
||||
else
|
||||
|
||||
/* Compress the uncompressed section or convert from/to .zdebug*
|
||||
section. Check if we should compress. */
|
||||
if (action == nothing)
|
||||
{
|
||||
/* Normal section. Check if we should compress. */
|
||||
if ((abfd->flags & BFD_COMPRESS) && newsect->size != 0)
|
||||
if (newsect->size != 0
|
||||
&& (abfd->flags & BFD_COMPRESS)
|
||||
&& compression_header_size >= 0
|
||||
&& (!compressed
|
||||
|| ((compression_header_size > 0)
|
||||
!= ((abfd->flags & BFD_COMPRESS_GABI) != 0))))
|
||||
action = compress;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
new_name = NULL;
|
||||
switch (action)
|
||||
if (action == compress)
|
||||
{
|
||||
case nothing:
|
||||
break;
|
||||
case compress:
|
||||
if (!bfd_init_section_compress_status (abfd, newsect))
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
@@ -1069,25 +1078,9 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
|
||||
abfd, name);
|
||||
return FALSE;
|
||||
}
|
||||
/* PR binutils/18087: Compression does not always make a section
|
||||
smaller. So only rename the section when compression has
|
||||
actually taken place. */
|
||||
if (newsect->compress_status == COMPRESS_SECTION_DONE)
|
||||
{
|
||||
if (name[1] != 'z')
|
||||
{
|
||||
unsigned int len = strlen (name);
|
||||
|
||||
new_name = bfd_alloc (abfd, len + 2);
|
||||
if (new_name == NULL)
|
||||
return FALSE;
|
||||
new_name[0] = '.';
|
||||
new_name[1] = 'z';
|
||||
memcpy (new_name + 2, name + 1, len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case decompress:
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!bfd_init_section_decompress_status (abfd, newsect))
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
@@ -1095,6 +1088,13 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
|
||||
abfd, name);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
new_name = NULL;
|
||||
if (action == decompress
|
||||
|| (action == compress
|
||||
&& (abfd->flags & BFD_COMPRESS_GABI) != 0))
|
||||
{
|
||||
if (name[1] == 'z')
|
||||
{
|
||||
unsigned int len = strlen (name);
|
||||
@@ -1105,7 +1105,24 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
|
||||
new_name[0] = '.';
|
||||
memcpy (new_name + 1, name + 2, len - 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (action == compress
|
||||
&& newsect->compress_status == COMPRESS_SECTION_DONE)
|
||||
{
|
||||
/* PR binutils/18087: Compression does not always make a section
|
||||
smaller. So only rename the section when compression has
|
||||
actually taken place. */
|
||||
if (name[1] != 'z')
|
||||
{
|
||||
unsigned int len = strlen (name);
|
||||
|
||||
new_name = bfd_alloc (abfd, len + 2);
|
||||
if (new_name == NULL)
|
||||
return FALSE;
|
||||
new_name[0] = '.';
|
||||
new_name[1] = 'z';
|
||||
memcpy (new_name + 2, name + 1, len);
|
||||
}
|
||||
}
|
||||
if (new_name != NULL)
|
||||
bfd_rename_section (abfd, newsect, new_name);
|
||||
|
||||
Reference in New Issue
Block a user