Go to main content

Oracle® Solaris 11.4 Linkers and Libraries Guide

Exit Print View

Updated: October 2019
 
 

Compressed Debug Sections

As discussed in Ancillary Objects, objects contain both allocable and non-allocable sections. Allocable sections are the sections that contain executable code and the data needed by that code at runtime. Non-allocable sections contain supplemental information that is not required to execute an object at runtime. These sections support the operation of debuggers and other observability tools, and are informally referred to as debug sections.

Depending on the level of debug information requested, debug sections can become very large relative to the code they describe. Ancillary objects, which write these sections to a separate file, offer one mechanism for dealing with these large sections. Compressed debug sections offer a second, complimentary, option for reducing debug section size.

Debug sections are compressed with the industry standard ZLIB compression library. Documentation for ZLIB may be found at http://www.zlib.net/.

The link-editor recognizes compressed debug sections within input objects, and automatically decompresses these sections. This operation is transparent to the user of the link-editor, and requires no special action.

By default, the link-editor does not compress debug sections in output objects. Use the –z compress-debug-sections option to enable the compression of debug sections in the output file.

$ cc .... -z compress-sections[=cmp-type] ....

The following values for cmp-type are recognized.

none

No compression is done. This option is equivalent to not specifying the –z compress-sections option.

zlib

Compress candidate sections using ZLIB compression. The resulting output sections have the SHF_COMPRESSED section flag set to identify the use of compression.

zlib-gnu

Compress all candidate sections using ZLIB compression, using the GNU section compression format. This format requires candidate sections to have a name that begins with .debug. The resulting output sections are renamed to start with .zdebug to identify the use of compression.

If cmp-type is omitted, the zlib style is used.

Compression for any section that would be larger in compressed form than the original non-compressed data is quietly skipped.

To be a candidate for compression, a section must be non-allocable, and belong to one of the following classes.

annotate

Annotate sections provide information that is used by memory access tools, and coverage related tools. These sections are identified by having a SHT_SUNW_ANNOTATE section type.

debug

Debug sections are identified by having a .compcom, .line, .stab*, .debug*, or .zdebug* section name. These sections are also identified by having an SHT_PROGBITS or SHT_SUNW_DEBUG* section type.

The zlib-gnu compression type is limited to sections with a name that starts with .debug. When zlib-gnu is used, sections that would otherwise be candidates for compression are not compressed. The underlying ZLIB compression is identical for the zlib and zlib-gnu styles, and both formats deliver the same amount of compression for a given input section. The two styles differ in the selection of candidate sections, the format of the compression header, and in how compressed sections are identified. See Section Compression. Unless there is a specific requirement to use the zlib-gnu style, the more general default zlib style is recommended.

The following program demonstrates the use of compressed debug sections. For the purpose of comparison, the program is built twice, once without compression, and once with compression.

$ cat hello.c
#include    <stdio.h>

int
main(int argc, char **argv) 
{ 
        (void) printf("hello, world\n");
        return (0);
}
% cc -g hello.c -o a.out.uncompressed
% cc -g hello.c -o a.out.compressed -z compress-sections

The section headers of the uncompressed, and compressed debug sections can now be compared.

$ elfdump -c a.out.uncompressed
....
Section Header[24]:  sh_name: .debug_info
    sh_addr:      0               sh_flags:   0
    sh_size:      0x17b           sh_type:    [ SHT_PROGBITS ]
    ....

Section Header[25]:  sh_name: .debug_line
    sh_addr:      0               sh_flags:   0
    sh_size:      0x4f            sh_type:    [ SHT_PROGBITS ]
    ....

Section Header[26]:  sh_name: .debug_abbrev
    sh_addr:      0               sh_flags:   0
    sh_size:      0x7c            sh_type:    [ SHT_PROGBITS ]
    ....

Section Header[27]:  sh_name: .debug_pubnames
    sh_addr:      0               sh_flags:   0
    sh_size:      0x1b            sh_type:    [ SHT_PROGBITS ]
    ....

$ elfdump -c a.out.compressed
....
Section Header[24]:  sh_name: .debug_info
    sh_addr:      0               sh_flags:   [ SHF_COMPRESSED ]
    sh_size:      0x14f           sh_type:    [ SHT_PROGBITS ]
    ....
    ch_size:      0x196           ch_type:    [ ELFCOMPRESS_ZLIB ]
    ch_addralign: 0x1       

Section Header[25]:  sh_name: .debug_line
    sh_addr:      0               sh_flags:   0
    sh_size:      0x4f            sh_type:    [ SHT_PROGBITS ]
    ....

Section Header[26]:  sh_name: .debug_abbrev
    sh_addr:      0               sh_flags:   [ SHF_COMPRESSED ]
    sh_size:      0x79            sh_type:    [ SHT_PROGBITS ]
    ....
    ch_size:      0x7c            ch_type:    [ ELFCOMPRESS_ZLIB ]
    ch_addralign: 0x1       

Section Header[27]:  sh_name: .debug_pubnames
    sh_addr:      0               sh_flags:   0
    sh_size:      0x1b            sh_type:    [ SHT_PROGBITS ]
    ....

Each compressed section, .debug_info, and .debug_abbrev, is identified with a SHF_COMPRESSED section flag. In addition, the section header information is accompanied with compression header structure information. The ch_size and ch_addralign fields provide size and alignment requirements for the uncompressed data. See Section Compression.

The .debug_line and .debug_pubnames sections would be larger compressed than in their original uncompressed form, and have therefore been left uncompressed.

Compression Costs And Benefits

The primary benefit of compressed debug sections is a size reduction of objects. However, compression imposes additional costs in runtime and memory use at all stages of development.

  • The compiler must produce each debug section in uncompressed form, allocate additional memory for the compressed version, and perform the compression.

  • When reading an input object, the link-editor must read the compressed data into memory, allocate additional memory to hold the decompressed data, and perform the decompression.

  • On output, the link-editor must create an uncompressed version of the resulting debug sections. If compression is requested, additional memory and time are used to create the compressed version.

  • When a debugger reads an object with compressed debug sections, the debugger must allocate additional memory to hold the decompressed data, and perform the decompression.

Furthermore, compressed debug sections allow for smaller files, but not for larger amounts of information. A common example involves 32-bit objects, which are fundamentally limited to 4 Gbytes due to the use of 32-bit file offsets and sizes within them. It is sometimes assumed that compressing debug data might allow for more debug information to be generated. However, the format of 32-bit debug data also contains 32-bit offsets, and so, is logically constrained to 4 Gbytes in uncompressed form.

For these reasons, compressed debug sections are not recommended for general development, where speed of the compile/link/debug cycle usually outweighs the benefits of smaller debug data. Compressed debug sections may be beneficial in cases where disk space is scarce, or for production objects that are copied widely and debugged rarely.