authorgravatar for motiejus@jakstys.ltMotiejus Jakštys <motiejus@jakstys.lt> 2022-06-23 08:28:35+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-16 18:44:56-05:00
logb1b944a683a2143584055468ca7958d298a9742b
treeb7e969d756016f064f684070aaa6a2a7570e6323
parentf911c933b287bd9f27b6b5f977a671aef05ca6c9

[elf linker] add --sort-section

Tested by: created a "hello world" C file and compiled with: zig cc -v main.c -Wl,--sort-section=name -o main ... and verified the `--sort-section=name` is passed to ld.lld. Refs https://github.com/zigchroot/zig-chroot/issues/1

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

src/Compilation.zig+3
...@@ -989,6 +989,7 @@ pub const InitOptions = struct {...@@ -989,6 +989,7 @@ pub const InitOptions = struct {
989 linker_optimization: ?u8 = null,989 linker_optimization: ?u8 = null,
990 linker_compress_debug_sections: ?link.CompressDebugSections = null,990 linker_compress_debug_sections: ?link.CompressDebugSections = null,
991 linker_module_definition_file: ?[]const u8 = null,991 linker_module_definition_file: ?[]const u8 = null,
992 linker_sort_section: ?link.SortSection = null,
992 major_subsystem_version: ?u32 = null,993 major_subsystem_version: ?u32 = null,
993 minor_subsystem_version: ?u32 = null,994 minor_subsystem_version: ?u32 = null,
994 clang_passthrough_mode: bool = false,995 clang_passthrough_mode: bool = false,
...@@ -1853,6 +1854,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1853,6 +1854,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1853 .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,1854 .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false,
1854 .compress_debug_sections = options.linker_compress_debug_sections orelse .none,1855 .compress_debug_sections = options.linker_compress_debug_sections orelse .none,
1855 .module_definition_file = options.linker_module_definition_file,1856 .module_definition_file = options.linker_module_definition_file,
1857 .sort_section = options.linker_sort_section,
1856 .import_memory = options.linker_import_memory orelse false,1858 .import_memory = options.linker_import_memory orelse false,
1857 .import_symbols = options.linker_import_symbols,1859 .import_symbols = options.linker_import_symbols,
1858 .import_table = options.linker_import_table,1860 .import_table = options.linker_import_table,
...@@ -2684,6 +2686,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -2684,6 +2686,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
2684 man.hash.add(comp.bin_file.options.hash_style);2686 man.hash.add(comp.bin_file.options.hash_style);
2685 man.hash.add(comp.bin_file.options.compress_debug_sections);2687 man.hash.add(comp.bin_file.options.compress_debug_sections);
2686 man.hash.add(comp.bin_file.options.include_compiler_rt);2688 man.hash.add(comp.bin_file.options.include_compiler_rt);
2689 man.hash.addOptional(comp.bin_file.options.sort_section);
2687 if (comp.bin_file.options.link_libc) {2690 if (comp.bin_file.options.link_libc) {
2688 man.hash.add(comp.bin_file.options.libc_installation != null);2691 man.hash.add(comp.bin_file.options.libc_installation != null);
2689 if (comp.bin_file.options.libc_installation) |libc_installation| {2692 if (comp.bin_file.options.libc_installation) |libc_installation| {
src/link.zig+3
...@@ -25,6 +25,8 @@ pub const SystemLib = struct {...@@ -25,6 +25,8 @@ pub const SystemLib = struct {
25 weak: bool = false,25 weak: bool = false,
26};26};
2727
28pub const SortSection = enum { name, alignment };
29
28pub const CacheMode = enum { incremental, whole };30pub const CacheMode = enum { incremental, whole };
2931
30pub fn hashAddSystemLibs(32pub fn hashAddSystemLibs(
...@@ -159,6 +161,7 @@ pub const Options = struct {...@@ -159,6 +161,7 @@ pub const Options = struct {
159 disable_lld_caching: bool,161 disable_lld_caching: bool,
160 is_test: bool,162 is_test: bool,
161 hash_style: HashStyle,163 hash_style: HashStyle,
164 sort_section: ?SortSection,
162 major_subsystem_version: ?u32,165 major_subsystem_version: ?u32,
163 minor_subsystem_version: ?u32,166 minor_subsystem_version: ?u32,
164 gc_sections: ?bool = null,167 gc_sections: ?bool = null,
src/link/Elf.zig+6
...@@ -1324,6 +1324,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -1324,6 +1324,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
1324 man.hash.addOptionalBytes(self.base.options.entry);1324 man.hash.addOptionalBytes(self.base.options.entry);
1325 man.hash.addOptional(self.base.options.image_base_override);1325 man.hash.addOptional(self.base.options.image_base_override);
1326 man.hash.add(gc_sections);1326 man.hash.add(gc_sections);
1327 man.hash.addOptional(self.base.options.sort_section);
1327 man.hash.add(self.base.options.eh_frame_hdr);1328 man.hash.add(self.base.options.eh_frame_hdr);
1328 man.hash.add(self.base.options.emit_relocs);1329 man.hash.add(self.base.options.emit_relocs);
1329 man.hash.add(self.base.options.rdynamic);1330 man.hash.add(self.base.options.rdynamic);
...@@ -1488,6 +1489,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -1488,6 +1489,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
1488 try argv.append(linker_script);1489 try argv.append(linker_script);
1489 }1490 }
14901491
1492 if (self.base.options.sort_section) |how| {
1493 const arg = try std.fmt.allocPrint(arena, "--sort-section={s}", .{@tagName(how)});
1494 try argv.append(arg);
1495 }
1496
1491 if (gc_sections) {1497 if (gc_sections) {
1492 try argv.append("--gc-sections");1498 try argv.append("--gc-sections");
1493 }1499 }
src/main.zig+12
...@@ -509,6 +509,7 @@ const usage_build_generic =...@@ -509,6 +509,7 @@ const usage_build_generic =
509 \\ zlib Compression with deflate/inflate509 \\ zlib Compression with deflate/inflate
510 \\ --gc-sections Force removal of functions and data that are unreachable by the entry point or exported symbols510 \\ --gc-sections Force removal of functions and data that are unreachable by the entry point or exported symbols
511 \\ --no-gc-sections Don't force removal of unreachable functions and data511 \\ --no-gc-sections Don't force removal of unreachable functions and data
512 \\ --sort-section=[value] Sort wildcard section patterns by 'name' or 'alignment'
512 \\ --subsystem [subsystem] (Windows) /SUBSYSTEM:<subsystem> to the linker513 \\ --subsystem [subsystem] (Windows) /SUBSYSTEM:<subsystem> to the linker
513 \\ --stack [size] Override default stack size514 \\ --stack [size] Override default stack size
514 \\ --image-base [addr] Set base address for executable image515 \\ --image-base [addr] Set base address for executable image
...@@ -731,6 +732,7 @@ fn buildOutputType(...@@ -731,6 +732,7 @@ fn buildOutputType(
731 var linker_script: ?[]const u8 = null;732 var linker_script: ?[]const u8 = null;
732 var version_script: ?[]const u8 = null;733 var version_script: ?[]const u8 = null;
733 var disable_c_depfile = false;734 var disable_c_depfile = false;
735 var linker_sort_section: ?link.SortSection = null;
734 var linker_gc_sections: ?bool = null;736 var linker_gc_sections: ?bool = null;
735 var linker_compress_debug_sections: ?link.CompressDebugSections = null;737 var linker_compress_debug_sections: ?link.CompressDebugSections = null;
736 var linker_allow_shlib_undefined: ?bool = null;738 var linker_allow_shlib_undefined: ?bool = null;
...@@ -1894,6 +1896,15 @@ fn buildOutputType(...@@ -1894,6 +1896,15 @@ fn buildOutputType(
1894 linker_print_icf_sections = true;1896 linker_print_icf_sections = true;
1895 } else if (mem.eql(u8, arg, "--print-map")) {1897 } else if (mem.eql(u8, arg, "--print-map")) {
1896 linker_print_map = true;1898 linker_print_map = true;
1899 } else if (mem.eql(u8, arg, "--sort-section")) {
1900 i += 1;
1901 if (i >= linker_args.items.len) {
1902 fatal("expected linker arg after '{s}'", .{arg});
1903 }
1904 const arg1 = linker_args.items[i];
1905 linker_sort_section = std.meta.stringToEnum(link.SortSection, arg1) orelse {
1906 fatal("expected [name|alignment] after --sort-section, found '{s}'", .{arg1});
1907 };
1897 } else if (mem.eql(u8, arg, "--allow-shlib-undefined") or1908 } else if (mem.eql(u8, arg, "--allow-shlib-undefined") or
1898 mem.eql(u8, arg, "-allow-shlib-undefined"))1909 mem.eql(u8, arg, "-allow-shlib-undefined"))
1899 {1910 {
...@@ -3070,6 +3081,7 @@ fn buildOutputType(...@@ -3070,6 +3081,7 @@ fn buildOutputType(
3070 .version_script = version_script,3081 .version_script = version_script,
3071 .disable_c_depfile = disable_c_depfile,3082 .disable_c_depfile = disable_c_depfile,
3072 .soname = resolved_soname,3083 .soname = resolved_soname,
3084 .linker_sort_section = linker_sort_section,
3073 .linker_gc_sections = linker_gc_sections,3085 .linker_gc_sections = linker_gc_sections,
3074 .linker_allow_shlib_undefined = linker_allow_shlib_undefined,3086 .linker_allow_shlib_undefined = linker_allow_shlib_undefined,
3075 .linker_bind_global_refs_locally = linker_bind_global_refs_locally,3087 .linker_bind_global_refs_locally = linker_bind_global_refs_locally,