authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-22 06:59:45+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-08-22 06:59:45+02:00
log7cd1c882c9dda18d333649462193e3e44e54196e
tree595e68221ef57cbfd4c09a368cee25e5d2f8d0b3
parent5bf9dc3850117c85fb124cc481d4a284e2c8504d
parentfa79f53f92cf41f30a84f4e8f5f059e15060ae2b
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #21160 from ziglang/link-thunks-test


4 files changed, 76 insertions(+), 50 deletions(-)

src/link/MachO.zig+12-1
...@@ -1909,7 +1909,7 @@ fn calcSectionSizes(self: *MachO) !void {...@@ -1909,7 +1909,7 @@ fn calcSectionSizes(self: *MachO) !void {
1909 }1909 }
1910 }1910 }
19111911
1912 // At this point, we can also calculate symtab and data-in-code linkedit section sizes1912 // At this point, we can also calculate most of the symtab and data-in-code linkedit section sizes
1913 if (self.getZigObject()) |zo| {1913 if (self.getZigObject()) |zo| {
1914 tp.spawnWg(&wg, File.calcSymtabSize, .{ zo.asFile(), self });1914 tp.spawnWg(&wg, File.calcSymtabSize, .{ zo.asFile(), self });
1915 }1915 }
...@@ -2463,6 +2463,9 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {...@@ -2463,6 +2463,9 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {
2463 if (self.getInternalObject()) |obj| {2463 if (self.getInternalObject()) |obj| {
2464 tp.spawnWg(&wg, File.writeSymtab, .{ obj.asFile(), self, self });2464 tp.spawnWg(&wg, File.writeSymtab, .{ obj.asFile(), self, self });
2465 }2465 }
2466 if (self.requiresThunks()) for (self.thunks.items) |th| {
2467 tp.spawnWg(&wg, Thunk.writeSymtab, .{ th, self, self });
2468 };
2466 }2469 }
24672470
2468 if (self.has_errors.swap(false, .seq_cst)) return error.FlushFailure;2471 if (self.has_errors.swap(false, .seq_cst)) return error.FlushFailure;
...@@ -2725,6 +2728,14 @@ fn calcSymtabSize(self: *MachO) !void {...@@ -2725,6 +2728,14 @@ fn calcSymtabSize(self: *MachO) !void {
2725 var nimports: u32 = 0;2728 var nimports: u32 = 0;
2726 var strsize: u32 = 1;2729 var strsize: u32 = 1;
27272730
2731 if (self.requiresThunks()) for (self.thunks.items) |*th| {
2732 th.output_symtab_ctx.ilocal = nlocals;
2733 th.output_symtab_ctx.stroff = strsize;
2734 th.calcSymtabSize(self);
2735 nlocals += th.output_symtab_ctx.nlocals;
2736 strsize += th.output_symtab_ctx.strsize;
2737 };
2738
2728 for (files.items) |index| {2739 for (files.items) |index| {
2729 const file = self.getFile(index).?;2740 const file = self.getFile(index).?;
2730 const ctx = switch (file) {2741 const ctx = switch (file) {
src/link/MachO/thunks.zig+29
...@@ -85,6 +85,7 @@ pub const Thunk = struct {...@@ -85,6 +85,7 @@ pub const Thunk = struct {
85 value: u64 = 0,85 value: u64 = 0,
86 out_n_sect: u8 = 0,86 out_n_sect: u8 = 0,
87 symbols: std.AutoArrayHashMapUnmanaged(MachO.Ref, void) = .{},87 symbols: std.AutoArrayHashMapUnmanaged(MachO.Ref, void) = .{},
88 output_symtab_ctx: MachO.SymtabCtx = .{},
8889
89 pub fn deinit(thunk: *Thunk, allocator: Allocator) void {90 pub fn deinit(thunk: *Thunk, allocator: Allocator) void {
90 thunk.symbols.deinit(allocator);91 thunk.symbols.deinit(allocator);
...@@ -116,6 +117,34 @@ pub const Thunk = struct {...@@ -116,6 +117,34 @@ pub const Thunk = struct {
116 }117 }
117 }118 }
118119
120 pub fn calcSymtabSize(thunk: *Thunk, macho_file: *MachO) void {
121 thunk.output_symtab_ctx.nlocals = @as(u32, @intCast(thunk.symbols.keys().len));
122 for (thunk.symbols.keys()) |ref| {
123 const sym = ref.getSymbol(macho_file).?;
124 thunk.output_symtab_ctx.strsize += @as(u32, @intCast(sym.getName(macho_file).len + "__thunk".len + 1));
125 }
126 }
127
128 pub fn writeSymtab(thunk: Thunk, macho_file: *MachO, ctx: anytype) void {
129 var n_strx = thunk.output_symtab_ctx.stroff;
130 for (thunk.symbols.keys(), thunk.output_symtab_ctx.ilocal..) |ref, ilocal| {
131 const sym = ref.getSymbol(macho_file).?;
132 const name = sym.getName(macho_file);
133 const out_sym = &ctx.symtab.items[ilocal];
134 out_sym.n_strx = n_strx;
135 @memcpy(ctx.strtab.items[n_strx..][0..name.len], name);
136 n_strx += @intCast(name.len);
137 @memcpy(ctx.strtab.items[n_strx..][0.."__thunk".len], "__thunk");
138 n_strx += @intCast("__thunk".len);
139 ctx.strtab.items[n_strx] = 0;
140 n_strx += 1;
141 out_sym.n_type = macho.N_SECT;
142 out_sym.n_sect = @intCast(thunk.out_n_sect + 1);
143 out_sym.n_value = @intCast(thunk.getTargetAddress(ref, macho_file));
144 out_sym.n_desc = 0;
145 }
146 }
147
119 pub fn format(148 pub fn format(
120 thunk: Thunk,149 thunk: Thunk,
121 comptime unused_fmt_string: []const u8,150 comptime unused_fmt_string: []const u8,
test/link/elf.zig+20-37
...@@ -2973,44 +2973,27 @@ fn testStrip(b: *Build, opts: Options) *Step {...@@ -2973,44 +2973,27 @@ fn testStrip(b: *Build, opts: Options) *Step {
2973fn testThunks(b: *Build, opts: Options) *Step {2973fn testThunks(b: *Build, opts: Options) *Step {
2974 const test_step = addTestStep(b, "thunks", opts);2974 const test_step = addTestStep(b, "thunks", opts);
29752975
2976 const src =2976 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes =
2977 \\#include <stdio.h>2977 \\void foo();
2978 \\__attribute__((aligned(0x8000000))) int bar() {2978 \\__attribute__((section(".bar"))) void bar() {
2979 \\ return 42;2979 \\ return foo();
2980 \\}2980 \\}
2981 \\int foobar();2981 \\__attribute__((section(".foo"))) void foo() {
2982 \\int foo() {2982 \\ return bar();
2983 \\ return bar() - foobar();2983 \\}
2984 \\}2984 \\int main() {
2985 \\__attribute__((aligned(0x8000000))) int foobar() {2985 \\ foo();
2986 \\ return 42;2986 \\ bar();
2987 \\}2987 \\ return 0;
2988 \\int main() {2988 \\}
2989 \\ printf("bar=%d, foo=%d, foobar=%d", bar(), foo(), foobar());2989 });
2990 \\ return foo();
2991 \\}
2992 ;
2993
2994 {
2995 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = src });
2996 exe.link_function_sections = true;
2997 exe.linkLibC();
2998
2999 const run = addRunArtifact(exe);
3000 run.expectStdOutEqual("bar=42, foo=0, foobar=42");
3001 run.expectExitCode(0);
3002 test_step.dependOn(&run.step);
3003 }
3004
3005 {
3006 const exe = addExecutable(b, opts, .{ .name = "main2", .c_source_bytes = src });
3007 exe.linkLibC();
30082990
3009 const run = addRunArtifact(exe);2991 const check = exe.checkObject();
3010 run.expectStdOutEqual("bar=42, foo=0, foobar=42");2992 check.checkInSymtab();
3011 run.expectExitCode(0);2993 check.checkContains("foo$thunk");
3012 test_step.dependOn(&run.step);2994 check.checkInSymtab();
3013 }2995 check.checkContains("bar$thunk");
2996 test_step.dependOn(&check.step);
30142997
3015 return test_step;2998 return test_step;
3016}2999}
test/link/macho.zig+15-12
...@@ -2204,25 +2204,28 @@ fn testThunks(b: *Build, opts: Options) *Step {...@@ -2204,25 +2204,28 @@ fn testThunks(b: *Build, opts: Options) *Step {
22042204
2205 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = 2205 const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes =
2206 \\#include <stdio.h>2206 \\#include <stdio.h>
2207 \\__attribute__((aligned(0x8000000))) int bar() {2207 \\void bar() {
2208 \\ return 42;2208 \\ printf("bar");
2209 \\}2209 \\}
2210 \\int foobar();2210 \\void foo() {
2211 \\int foo() {2211 \\ fprintf(stdout, "foo");
2212 \\ return bar() - foobar();
2213 \\}
2214 \\__attribute__((aligned(0x8000000))) int foobar() {
2215 \\ return 42;
2216 \\}2212 \\}
2217 \\int main() {2213 \\int main() {
2218 \\ printf("bar=%d, foo=%d, foobar=%d", bar(), foo(), foobar());2214 \\ foo();
2219 \\ return foo();2215 \\ bar();
2216 \\ return 0;
2220 \\}2217 \\}
2221 });2218 });
22222219
2220 const check = exe.checkObject();
2221 check.checkInSymtab();
2222 check.checkContains("_printf__thunk");
2223 check.checkInSymtab();
2224 check.checkContains("_fprintf__thunk");
2225 test_step.dependOn(&check.step);
2226
2223 const run = addRunArtifact(exe);2227 const run = addRunArtifact(exe);
2224 run.expectStdOutEqual("bar=42, foo=0, foobar=42");2228 run.expectStdOutEqual("foobar");
2225 run.expectExitCode(0);
2226 test_step.dependOn(&run.step);2229 test_step.dependOn(&run.step);
22272230
2228 return test_step;2231 return test_step;