ELF: understand -Wl,--compress-debug-sections

This argument is both a compiler and a linker flag. The linker flag was
not understood; now it is. Go likes to use it as a linker flag.

Tested with sqlite3. The size difference is significant, and I confirmed
gdb understands both binaries.

zlib: 3.66MB
------------

    CC="zig cc"
    CFLAGS="-Wl,--compress-debug-sections=zlib -O2"
    ./configure --disable-tcl
    make

        FILE SIZE        VM SIZE
     --------------  --------------
      39.1%  1.43Mi  88.4%  1.43Mi    .text
      19.6%   734Ki   0.0%       0    .debug_info
      16.4%   613Ki   0.0%       0    .debug_loc
      13.1%   492Ki   0.0%       0    .debug_line
       4.2%   157Ki   9.5%   157Ki    .rodata
       2.3%  87.6Ki   0.0%       0    .debug_ranges
       1.5%  56.2Ki   0.0%       0    .symtab
       1.1%  40.2Ki   0.0%       0    .strtab
       1.0%  38.2Ki   0.0%       0    .debug_str
       0.7%  26.2Ki   0.0%       0    .debug_frame
       0.4%  15.3Ki   0.9%  15.3Ki    .data
       0.1%  4.71Ki   0.3%  4.71Ki    .dynsym
       0.1%  3.65Ki   0.2%  3.26Ki    [16 Others]
       0.1%  2.55Ki   0.2%  2.55Ki    .rela.plt
       0.1%  2.12Ki   0.0%       0    [ELF Section Headers]
       0.0%       0   0.1%  2.02Ki    .bss
       0.0%  1.84Ki   0.1%  1.84Ki    .dynstr
       0.0%  1.72Ki   0.1%  1.72Ki    .plt
       0.0%  1.58Ki   0.1%  1.58Ki    .hash
       0.0%  1.17Ki   0.0%       0    .debug_abbrev
       0.0%  1.01Ki   0.1%  1.01Ki    .rela.dyn
     100.0%  3.66Mi 100.0%  1.62Mi    TOTAL

none: 8.56MB
------------

    CC="zig cc" CFLAGS="-O2" ./configure --disable-tcl
    make

        FILE SIZE        VM SIZE
     --------------  --------------
      41.1%  3.52Mi   0.0%       0    .debug_loc
      18.5%  1.59Mi   0.0%       0    .debug_info
      16.7%  1.43Mi  88.4%  1.43Mi    .text
      11.8%  1.01Mi   0.0%       0    .debug_line
       5.9%   515Ki   0.0%       0    .debug_ranges
       1.8%   157Ki   9.5%   157Ki    .rodata
       1.3%   118Ki   0.0%       0    .debug_frame
       1.3%   110Ki   0.0%       0    .debug_str
       0.6%  56.2Ki   0.0%       0    .symtab
       0.5%  40.2Ki   0.0%       0    .strtab
       0.2%  15.3Ki   0.9%  15.3Ki    .data
       0.1%  4.71Ki   0.3%  4.71Ki    .dynsym
       0.0%  3.64Ki   0.2%  3.26Ki    [16 Others]
       0.0%  2.98Ki   0.0%       0    .debug_abbrev
       0.0%  2.55Ki   0.2%  2.55Ki    .rela.plt
       0.0%  2.12Ki   0.0%       0    [ELF Section Headers]
       0.0%       0   0.1%  2.02Ki    .bss
       0.0%  1.84Ki   0.1%  1.84Ki    .dynstr
       0.0%  1.72Ki   0.1%  1.72Ki    .plt
       0.0%  1.58Ki   0.1%  1.58Ki    .hash
       0.0%  1.01Ki   0.1%  1.01Ki    .rela.dyn
     100.0%  8.56Mi 100.0%  1.62Mi    TOTAL
This commit is contained in:
Motiejus Jakštys 2022-06-14 14:41:47 +03:00 committed by Andrew Kelley
parent ade9bd9287
commit 1f410b500c
4 changed files with 30 additions and 0 deletions

View File

@ -860,6 +860,7 @@ pub const InitOptions = struct {
linker_nxcompat: bool = false,
linker_dynamicbase: bool = false,
linker_optimization: ?u8 = null,
linker_compress_debug_sections: ?link.CompressDebugSections = null,
major_subsystem_version: ?u32 = null,
minor_subsystem_version: ?u32 = null,
clang_passthrough_mode: bool = false,
@ -1687,6 +1688,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
.no_builtin = options.no_builtin,
.allow_shlib_undefined = options.linker_allow_shlib_undefined,
.bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,
.compress_debug_sections = options.linker_compress_debug_sections,
.import_memory = options.linker_import_memory orelse false,
.import_table = options.linker_import_table,
.export_table = options.linker_export_table,
@ -2459,6 +2461,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
man.hash.add(comp.bin_file.options.z_now);
man.hash.add(comp.bin_file.options.z_relro);
man.hash.add(comp.bin_file.options.hash_style);
man.hash.addOptional(comp.bin_file.options.compress_debug_sections);
man.hash.add(comp.bin_file.options.include_compiler_rt);
if (comp.bin_file.options.link_libc) {
man.hash.add(comp.bin_file.options.libc_installation != null);

View File

@ -123,6 +123,7 @@ pub const Options = struct {
nxcompat: bool,
dynamicbase: bool,
linker_optimization: u8,
compress_debug_sections: ?CompressDebugSections,
bind_global_refs_locally: bool,
import_memory: bool,
import_table: bool,
@ -219,6 +220,8 @@ pub const Options = struct {
pub const HashStyle = enum { sysv, gnu, both };
pub const CompressDebugSections = enum { none, zlib };
pub const File = struct {
tag: Tag,
options: Options,

View File

@ -1351,6 +1351,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
link.hashAddSystemLibs(&man.hash, self.base.options.system_libs);
man.hash.add(allow_shlib_undefined);
man.hash.add(self.base.options.bind_global_refs_locally);
man.hash.addOptional(self.base.options.compress_debug_sections);
man.hash.add(self.base.options.tsan);
man.hash.addOptionalBytes(self.base.options.sysroot);
man.hash.add(self.base.options.linker_optimization);
@ -1754,6 +1755,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
try argv.append("--allow-shlib-undefined");
}
if (self.base.options.compress_debug_sections) |how| {
const arg = try std.fmt.allocPrint(arena, "--compress-debug-sections={s}", .{@tagName(how)});
try argv.append(arg);
}
if (self.base.options.bind_global_refs_locally) {
try argv.append("-Bsymbolic");
}

View File

@ -443,6 +443,8 @@ const usage_build_generic =
\\ -dynamic Force output to be dynamically linked
\\ -static Force output to be statically linked
\\ -Bsymbolic Bind global references locally
\\ --compress-debug-sections= Compress DWARF debug sections
\\ none|zlib
\\ --subsystem [subsystem] (Windows) /SUBSYSTEM:<subsystem> to the linker
\\ --stack [size] Override default stack size
\\ --image-base [addr] Set base address for executable image
@ -657,6 +659,7 @@ fn buildOutputType(
var version_script: ?[]const u8 = null;
var disable_c_depfile = false;
var linker_gc_sections: ?bool = null;
var linker_compress_debug_sections: ?link.CompressDebugSections = null;
var linker_allow_shlib_undefined: ?bool = null;
var linker_bind_global_refs_locally: ?bool = null;
var linker_import_memory: ?bool = null;
@ -938,6 +941,11 @@ fn buildOutputType(
install_name = args_iter.next() orelse {
fatal("expected parameter after {s}", .{arg});
};
} else if (mem.startsWith(u8, arg, "--compress-debug-sections=")) {
const param = arg["--compress-debug-sections=".len..];
linker_compress_debug_sections = std.meta.stringToEnum(link.CompressDebugSections, param) orelse {
fatal("expected --compress-debug-sections=[none|zlib], found '{s}'", .{param});
};
} else if (mem.eql(u8, arg, "-pagezero_size")) {
const next_arg = args_iter.next() orelse {
fatal("expected parameter after {s}", .{arg});
@ -1776,6 +1784,15 @@ fn buildOutputType(
linker_global_base = parseIntSuffix(arg, "--global-base=".len);
} else if (mem.startsWith(u8, arg, "--export=")) {
try linker_export_symbol_names.append(arg["--export=".len..]);
} else if (mem.eql(u8, arg, "--compress-debug-sections")) {
i += 1;
if (i >= linker_args.items.len) {
fatal("expected linker arg after '{s}'", .{arg});
}
const arg1 = linker_args.items[i];
linker_compress_debug_sections = std.meta.stringToEnum(link.CompressDebugSections, arg1) orelse {
fatal("expected [none|zlib] after --compress-debug-sections, found '{s}'", .{arg1});
};
} else if (mem.eql(u8, arg, "-z")) {
i += 1;
if (i >= linker_args.items.len) {
@ -2849,6 +2866,7 @@ fn buildOutputType(
.linker_nxcompat = linker_nxcompat,
.linker_dynamicbase = linker_dynamicbase,
.linker_optimization = linker_optimization,
.linker_compress_debug_sections = linker_compress_debug_sections,
.major_subsystem_version = major_subsystem_version,
.minor_subsystem_version = minor_subsystem_version,
.link_eh_frame_hdr = link_eh_frame_hdr,