authorgravatar for motiejus@jakstys.ltMotiejus Jakštys <motiejus@jakstys.lt> 2022-06-14 14:41:47+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-11 13:55:29-07:00
log1f410b500c8dbe33191a54a4ae02a6fb0febec46
tree7948dd086ed915e1dbd2d94a32e314ea6bb9af10
parentade9bd9287fcdd730a7562811d0e50a6899a6cf2

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

4 files changed, 30 insertions(+), 0 deletions(-)

src/Compilation.zig+3
...@@ -860,6 +860,7 @@ pub const InitOptions = struct {...@@ -860,6 +860,7 @@ pub const InitOptions = struct {
860 linker_nxcompat: bool = false,860 linker_nxcompat: bool = false,
861 linker_dynamicbase: bool = false,861 linker_dynamicbase: bool = false,
862 linker_optimization: ?u8 = null,862 linker_optimization: ?u8 = null,
863 linker_compress_debug_sections: ?link.CompressDebugSections = null,
863 major_subsystem_version: ?u32 = null,864 major_subsystem_version: ?u32 = null,
864 minor_subsystem_version: ?u32 = null,865 minor_subsystem_version: ?u32 = null,
865 clang_passthrough_mode: bool = false,866 clang_passthrough_mode: bool = false,
...@@ -1687,6 +1688,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1687,6 +1688,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1687 .no_builtin = options.no_builtin,1688 .no_builtin = options.no_builtin,
1688 .allow_shlib_undefined = options.linker_allow_shlib_undefined,1689 .allow_shlib_undefined = options.linker_allow_shlib_undefined,
1689 .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,1690 .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,
1691 .compress_debug_sections = options.linker_compress_debug_sections,
1690 .import_memory = options.linker_import_memory orelse false,1692 .import_memory = options.linker_import_memory orelse false,
1691 .import_table = options.linker_import_table,1693 .import_table = options.linker_import_table,
1692 .export_table = options.linker_export_table,1694 .export_table = options.linker_export_table,
...@@ -2459,6 +2461,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -2459,6 +2461,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
2459 man.hash.add(comp.bin_file.options.z_now);2461 man.hash.add(comp.bin_file.options.z_now);
2460 man.hash.add(comp.bin_file.options.z_relro);2462 man.hash.add(comp.bin_file.options.z_relro);
2461 man.hash.add(comp.bin_file.options.hash_style);2463 man.hash.add(comp.bin_file.options.hash_style);
2464 man.hash.addOptional(comp.bin_file.options.compress_debug_sections);
2462 man.hash.add(comp.bin_file.options.include_compiler_rt);2465 man.hash.add(comp.bin_file.options.include_compiler_rt);
2463 if (comp.bin_file.options.link_libc) {2466 if (comp.bin_file.options.link_libc) {
2464 man.hash.add(comp.bin_file.options.libc_installation != null);2467 man.hash.add(comp.bin_file.options.libc_installation != null);
src/link.zig+3
...@@ -123,6 +123,7 @@ pub const Options = struct {...@@ -123,6 +123,7 @@ pub const Options = struct {
123 nxcompat: bool,123 nxcompat: bool,
124 dynamicbase: bool,124 dynamicbase: bool,
125 linker_optimization: u8,125 linker_optimization: u8,
126 compress_debug_sections: ?CompressDebugSections,
126 bind_global_refs_locally: bool,127 bind_global_refs_locally: bool,
127 import_memory: bool,128 import_memory: bool,
128 import_table: bool,129 import_table: bool,
...@@ -219,6 +220,8 @@ pub const Options = struct {...@@ -219,6 +220,8 @@ pub const Options = struct {
219220
220pub const HashStyle = enum { sysv, gnu, both };221pub const HashStyle = enum { sysv, gnu, both };
221222
223pub const CompressDebugSections = enum { none, zlib };
224
222pub const File = struct {225pub const File = struct {
223 tag: Tag,226 tag: Tag,
224 options: Options,227 options: Options,
src/link/Elf.zig+6
...@@ -1351,6 +1351,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -1351,6 +1351,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
1351 link.hashAddSystemLibs(&man.hash, self.base.options.system_libs);1351 link.hashAddSystemLibs(&man.hash, self.base.options.system_libs);
1352 man.hash.add(allow_shlib_undefined);1352 man.hash.add(allow_shlib_undefined);
1353 man.hash.add(self.base.options.bind_global_refs_locally);1353 man.hash.add(self.base.options.bind_global_refs_locally);
1354 man.hash.addOptional(self.base.options.compress_debug_sections);
1354 man.hash.add(self.base.options.tsan);1355 man.hash.add(self.base.options.tsan);
1355 man.hash.addOptionalBytes(self.base.options.sysroot);1356 man.hash.addOptionalBytes(self.base.options.sysroot);
1356 man.hash.add(self.base.options.linker_optimization);1357 man.hash.add(self.base.options.linker_optimization);
...@@ -1754,6 +1755,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -1754,6 +1755,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
1754 try argv.append("--allow-shlib-undefined");1755 try argv.append("--allow-shlib-undefined");
1755 }1756 }
17561757
1758 if (self.base.options.compress_debug_sections) |how| {
1759 const arg = try std.fmt.allocPrint(arena, "--compress-debug-sections={s}", .{@tagName(how)});
1760 try argv.append(arg);
1761 }
1762
1757 if (self.base.options.bind_global_refs_locally) {1763 if (self.base.options.bind_global_refs_locally) {
1758 try argv.append("-Bsymbolic");1764 try argv.append("-Bsymbolic");
1759 }1765 }
src/main.zig+18
...@@ -443,6 +443,8 @@ const usage_build_generic =...@@ -443,6 +443,8 @@ const usage_build_generic =
443 \\ -dynamic Force output to be dynamically linked443 \\ -dynamic Force output to be dynamically linked
444 \\ -static Force output to be statically linked444 \\ -static Force output to be statically linked
445 \\ -Bsymbolic Bind global references locally445 \\ -Bsymbolic Bind global references locally
446 \\ --compress-debug-sections= Compress DWARF debug sections
447 \\ none|zlib
446 \\ --subsystem [subsystem] (Windows) /SUBSYSTEM:<subsystem> to the linker448 \\ --subsystem [subsystem] (Windows) /SUBSYSTEM:<subsystem> to the linker
447 \\ --stack [size] Override default stack size449 \\ --stack [size] Override default stack size
448 \\ --image-base [addr] Set base address for executable image450 \\ --image-base [addr] Set base address for executable image
...@@ -657,6 +659,7 @@ fn buildOutputType(...@@ -657,6 +659,7 @@ fn buildOutputType(
657 var version_script: ?[]const u8 = null;659 var version_script: ?[]const u8 = null;
658 var disable_c_depfile = false;660 var disable_c_depfile = false;
659 var linker_gc_sections: ?bool = null;661 var linker_gc_sections: ?bool = null;
662 var linker_compress_debug_sections: ?link.CompressDebugSections = null;
660 var linker_allow_shlib_undefined: ?bool = null;663 var linker_allow_shlib_undefined: ?bool = null;
661 var linker_bind_global_refs_locally: ?bool = null;664 var linker_bind_global_refs_locally: ?bool = null;
662 var linker_import_memory: ?bool = null;665 var linker_import_memory: ?bool = null;
...@@ -938,6 +941,11 @@ fn buildOutputType(...@@ -938,6 +941,11 @@ fn buildOutputType(
938 install_name = args_iter.next() orelse {941 install_name = args_iter.next() orelse {
939 fatal("expected parameter after {s}", .{arg});942 fatal("expected parameter after {s}", .{arg});
940 };943 };
944 } else if (mem.startsWith(u8, arg, "--compress-debug-sections=")) {
945 const param = arg["--compress-debug-sections=".len..];
946 linker_compress_debug_sections = std.meta.stringToEnum(link.CompressDebugSections, param) orelse {
947 fatal("expected --compress-debug-sections=[none|zlib], found '{s}'", .{param});
948 };
941 } else if (mem.eql(u8, arg, "-pagezero_size")) {949 } else if (mem.eql(u8, arg, "-pagezero_size")) {
942 const next_arg = args_iter.next() orelse {950 const next_arg = args_iter.next() orelse {
943 fatal("expected parameter after {s}", .{arg});951 fatal("expected parameter after {s}", .{arg});
...@@ -1776,6 +1784,15 @@ fn buildOutputType(...@@ -1776,6 +1784,15 @@ fn buildOutputType(
1776 linker_global_base = parseIntSuffix(arg, "--global-base=".len);1784 linker_global_base = parseIntSuffix(arg, "--global-base=".len);
1777 } else if (mem.startsWith(u8, arg, "--export=")) {1785 } else if (mem.startsWith(u8, arg, "--export=")) {
1778 try linker_export_symbol_names.append(arg["--export=".len..]);1786 try linker_export_symbol_names.append(arg["--export=".len..]);
1787 } else if (mem.eql(u8, arg, "--compress-debug-sections")) {
1788 i += 1;
1789 if (i >= linker_args.items.len) {
1790 fatal("expected linker arg after '{s}'", .{arg});
1791 }
1792 const arg1 = linker_args.items[i];
1793 linker_compress_debug_sections = std.meta.stringToEnum(link.CompressDebugSections, arg1) orelse {
1794 fatal("expected [none|zlib] after --compress-debug-sections, found '{s}'", .{arg1});
1795 };
1779 } else if (mem.eql(u8, arg, "-z")) {1796 } else if (mem.eql(u8, arg, "-z")) {
1780 i += 1;1797 i += 1;
1781 if (i >= linker_args.items.len) {1798 if (i >= linker_args.items.len) {
...@@ -2849,6 +2866,7 @@ fn buildOutputType(...@@ -2849,6 +2866,7 @@ fn buildOutputType(
2849 .linker_nxcompat = linker_nxcompat,2866 .linker_nxcompat = linker_nxcompat,
2850 .linker_dynamicbase = linker_dynamicbase,2867 .linker_dynamicbase = linker_dynamicbase,
2851 .linker_optimization = linker_optimization,2868 .linker_optimization = linker_optimization,
2869 .linker_compress_debug_sections = linker_compress_debug_sections,
2852 .major_subsystem_version = major_subsystem_version,2870 .major_subsystem_version = major_subsystem_version,
2853 .minor_subsystem_version = minor_subsystem_version,2871 .minor_subsystem_version = minor_subsystem_version,
2854 .link_eh_frame_hdr = link_eh_frame_hdr,2872 .link_eh_frame_hdr = link_eh_frame_hdr,