| author | |
| committer | |
| log | 7cd1c882c9dda18d333649462193e3e44e54196e |
| tree | 595e68221ef57cbfd4c09a368cee25e5d2f8d0b3 |
| parent | 5bf9dc3850117c85fb124cc481d4a284e2c8504d |
| parent | fa79f53f92cf41f30a84f4e8f5f059e15060ae2b |
| signature |
4 files changed, 76 insertions(+), 50 deletions(-)
src/link/MachO.zig+12-1| ... | ... | @@ -1909,7 +1909,7 @@ fn calcSectionSizes(self: *MachO) !void { |
| 1909 | 1909 | } |
| 1910 | 1910 | } |
| 1911 | 1911 | |
| 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 | |
| 1913 | 1913 | if (self.getZigObject()) |zo| { |
| 1914 | 1914 | tp.spawnWg(&wg, File.calcSymtabSize, .{ zo.asFile(), self }); |
| 1915 | 1915 | } |
| ... | ... | @@ -2463,6 +2463,9 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void { |
| 2463 | 2463 | if (self.getInternalObject()) |obj| { |
| 2464 | 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 | } |
| 2467 | 2470 | |
| 2468 | 2471 | if (self.has_errors.swap(false, .seq_cst)) return error.FlushFailure; |
| ... | ... | @@ -2725,6 +2728,14 @@ fn calcSymtabSize(self: *MachO) !void { |
| 2725 | 2728 | var nimports: u32 = 0; |
| 2726 | 2729 | var strsize: u32 = 1; |
| 2727 | 2730 | |
| 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 | 2739 | for (files.items) |index| { |
| 2729 | 2740 | const file = self.getFile(index).?; |
| 2730 | 2741 | const ctx = switch (file) { |
src/link/MachO/thunks.zig+29| ... | ... | @@ -85,6 +85,7 @@ pub const Thunk = struct { |
| 85 | 85 | value: u64 = 0, |
| 86 | 86 | out_n_sect: u8 = 0, |
| 87 | 87 | symbols: std.AutoArrayHashMapUnmanaged(MachO.Ref, void) = .{}, |
| 88 | output_symtab_ctx: MachO.SymtabCtx = .{}, | |
| 88 | 89 | |
| 89 | 90 | pub fn deinit(thunk: *Thunk, allocator: Allocator) void { |
| 90 | 91 | thunk.symbols.deinit(allocator); |
| ... | ... | @@ -116,6 +117,34 @@ pub const Thunk = struct { |
| 116 | 117 | } |
| 117 | 118 | } |
| 118 | 119 | |
| 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 | 148 | pub fn format( |
| 120 | 149 | thunk: Thunk, |
| 121 | 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 | 2973 | fn testThunks(b: *Build, opts: Options) *Step { |
| 2974 | 2974 | const test_step = addTestStep(b, "thunks", opts); |
| 2975 | 2975 | |
| 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 | }); | |
| 3008 | 2990 | |
| 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); | |
| 3014 | 2997 | |
| 3015 | 2998 | return test_step; |
| 3016 | 2999 | } |
test/link/macho.zig+15-12| ... | ... | @@ -2204,25 +2204,28 @@ fn testThunks(b: *Build, opts: Options) *Step { |
| 2204 | 2204 | |
| 2205 | 2205 | const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = |
| 2206 | 2206 | \\#include <stdio.h> |
| 2207 | \\__attribute__((aligned(0x8000000))) int bar() { | |
| 2208 | \\ return 42; | |
| 2207 | \\void bar() { | |
| 2208 | \\ printf("bar"); | |
| 2209 | 2209 | \\} |
| 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"); | |
| 2216 | 2212 | \\} |
| 2217 | 2213 | \\int main() { |
| 2218 | \\ printf("bar=%d, foo=%d, foobar=%d", bar(), foo(), foobar()); | |
| 2219 | \\ return foo(); | |
| 2214 | \\ foo(); | |
| 2215 | \\ bar(); | |
| 2216 | \\ return 0; | |
| 2220 | 2217 | \\} |
| 2221 | 2218 | }); |
| 2222 | 2219 | |
| 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 | 2227 | const run = addRunArtifact(exe); |
| 2224 | run.expectStdOutEqual("bar=42, foo=0, foobar=42"); | |
| 2225 | run.expectExitCode(0); | |
| 2228 | run.expectStdOutEqual("foobar"); | |
| 2226 | 2229 | test_step.dependOn(&run.step); |
| 2227 | 2230 | |
| 2228 | 2231 | return test_step; |