Skip to content

Commit 7cd1c88

Browse files
authored
Merge pull request #21160 from ziglang/link-thunks-test
2 parents 5bf9dc3 + fa79f53 commit 7cd1c88

File tree

4 files changed

+76
-50
lines changed

4 files changed

+76
-50
lines changed

src/link/MachO.zig

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1909,7 +1909,7 @@ fn calcSectionSizes(self: *MachO) !void {
19091909
}
19101910
}
19111911

1912-
// At this point, we can also calculate symtab and data-in-code linkedit section sizes
1912+
// At this point, we can also calculate most of the symtab and data-in-code linkedit section sizes
19131913
if (self.getZigObject()) |zo| {
19141914
tp.spawnWg(&wg, File.calcSymtabSize, .{ zo.asFile(), self });
19151915
}
@@ -2463,6 +2463,9 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {
24632463
if (self.getInternalObject()) |obj| {
24642464
tp.spawnWg(&wg, File.writeSymtab, .{ obj.asFile(), self, self });
24652465
}
2466+
if (self.requiresThunks()) for (self.thunks.items) |th| {
2467+
tp.spawnWg(&wg, Thunk.writeSymtab, .{ th, self, self });
2468+
};
24662469
}
24672470

24682471
if (self.has_errors.swap(false, .seq_cst)) return error.FlushFailure;
@@ -2725,6 +2728,14 @@ fn calcSymtabSize(self: *MachO) !void {
27252728
var nimports: u32 = 0;
27262729
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+
27282739
for (files.items) |index| {
27292740
const file = self.getFile(index).?;
27302741
const ctx = switch (file) {

src/link/MachO/thunks.zig

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ pub const Thunk = struct {
8585
value: u64 = 0,
8686
out_n_sect: u8 = 0,
8787
symbols: std.AutoArrayHashMapUnmanaged(MachO.Ref, void) = .{},
88+
output_symtab_ctx: MachO.SymtabCtx = .{},
8889

8990
pub fn deinit(thunk: *Thunk, allocator: Allocator) void {
9091
thunk.symbols.deinit(allocator);
@@ -116,6 +117,34 @@ pub const Thunk = struct {
116117
}
117118
}
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+
119148
pub fn format(
120149
thunk: Thunk,
121150
comptime unused_fmt_string: []const u8,

test/link/elf.zig

Lines changed: 20 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2973,44 +2973,27 @@ fn testStrip(b: *Build, opts: Options) *Step {
29732973
fn testThunks(b: *Build, opts: Options) *Step {
29742974
const test_step = addTestStep(b, "thunks", opts);
29752975

2976-
const src =
2977-
\\#include <stdio.h>
2978-
\\__attribute__((aligned(0x8000000))) int bar() {
2979-
\\ return 42;
2980-
\\}
2981-
\\int foobar();
2982-
\\int foo() {
2983-
\\ return bar() - foobar();
2984-
\\}
2985-
\\__attribute__((aligned(0x8000000))) int foobar() {
2986-
\\ return 42;
2987-
\\}
2988-
\\int main() {
2989-
\\ printf("bar=%d, foo=%d, foobar=%d", bar(), foo(), foobar());
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();
2976+
const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes =
2977+
\\void foo();
2978+
\\__attribute__((section(".bar"))) void bar() {
2979+
\\ return foo();
2980+
\\}
2981+
\\__attribute__((section(".foo"))) void foo() {
2982+
\\ return bar();
2983+
\\}
2984+
\\int main() {
2985+
\\ foo();
2986+
\\ bar();
2987+
\\ return 0;
2988+
\\}
2989+
});
30082990

3009-
const run = addRunArtifact(exe);
3010-
run.expectStdOutEqual("bar=42, foo=0, foobar=42");
3011-
run.expectExitCode(0);
3012-
test_step.dependOn(&run.step);
3013-
}
2991+
const check = exe.checkObject();
2992+
check.checkInSymtab();
2993+
check.checkContains("foo$thunk");
2994+
check.checkInSymtab();
2995+
check.checkContains("bar$thunk");
2996+
test_step.dependOn(&check.step);
30142997

30152998
return test_step;
30162999
}

test/link/macho.zig

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2204,25 +2204,28 @@ fn testThunks(b: *Build, opts: Options) *Step {
22042204

22052205
const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes =
22062206
\\#include <stdio.h>
2207-
\\__attribute__((aligned(0x8000000))) int bar() {
2208-
\\ return 42;
2207+
\\void bar() {
2208+
\\ printf("bar");
22092209
\\}
2210-
\\int foobar();
2211-
\\int foo() {
2212-
\\ return bar() - foobar();
2213-
\\}
2214-
\\__attribute__((aligned(0x8000000))) int foobar() {
2215-
\\ return 42;
2210+
\\void foo() {
2211+
\\ fprintf(stdout, "foo");
22162212
\\}
22172213
\\int main() {
2218-
\\ printf("bar=%d, foo=%d, foobar=%d", bar(), foo(), foobar());
2219-
\\ return foo();
2214+
\\ foo();
2215+
\\ bar();
2216+
\\ return 0;
22202217
\\}
22212218
});
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+
22232227
const run = addRunArtifact(exe);
2224-
run.expectStdOutEqual("bar=42, foo=0, foobar=42");
2225-
run.expectExitCode(0);
2228+
run.expectStdOutEqual("foobar");
22262229
test_step.dependOn(&run.step);
22272230

22282231
return test_step;

0 commit comments

Comments
 (0)