mirror of
https://github.com/ziglang/zig.git
synced 2025-12-30 18:13:19 +00:00
Merge pull request #20496 from ziglang/macos-tsan
This commit is contained in:
commit
de61540c2d
@ -185,9 +185,9 @@ libcxxabi_static_lib: ?CRTFile = null,
|
||||
/// Populated when we build the libunwind static library. A Job to build this is placed in the queue
|
||||
/// and resolved before calling linker.flush().
|
||||
libunwind_static_lib: ?CRTFile = null,
|
||||
/// Populated when we build the TSAN static library. A Job to build this is placed in the queue
|
||||
/// Populated when we build the TSAN library. A Job to build this is placed in the queue
|
||||
/// and resolved before calling linker.flush().
|
||||
tsan_static_lib: ?CRTFile = null,
|
||||
tsan_lib: ?CRTFile = null,
|
||||
/// Populated when we build the libc static library. A Job to build this is placed in the queue
|
||||
/// and resolved before calling linker.flush().
|
||||
libc_static_lib: ?CRTFile = null,
|
||||
|
||||
@ -25,10 +25,19 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
const root_name = "tsan";
|
||||
const output_mode = .Lib;
|
||||
const link_mode = .static;
|
||||
const target = comp.getTarget();
|
||||
const root_name = switch (target.os.tag) {
|
||||
// On Apple platforms, we use the same name as LLVM because the
|
||||
// TSAN library implementation hard-codes a check for these names.
|
||||
.macos => "clang_rt.tsan_osx_dynamic",
|
||||
.ios => switch (target.abi) {
|
||||
.simulator => "clang_rt.tsan_iossim_dynamic",
|
||||
else => "clang_rt.tsan_ios_dynamic",
|
||||
},
|
||||
else => "tsan",
|
||||
};
|
||||
const link_mode: std.builtin.LinkMode = if (target.isDarwin()) .dynamic else .static;
|
||||
const output_mode = .Lib;
|
||||
const basename = try std.zig.binNameAlloc(arena, .{
|
||||
.root_name = root_name,
|
||||
.target = target,
|
||||
@ -43,6 +52,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
|
||||
|
||||
const optimize_mode = comp.compilerRtOptMode();
|
||||
const strip = comp.compilerRtStrip();
|
||||
const link_libcpp = target.isDarwin();
|
||||
|
||||
const config = Compilation.Config.resolve(.{
|
||||
.output_mode = output_mode,
|
||||
@ -54,6 +64,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
|
||||
.root_optimize_mode = optimize_mode,
|
||||
.root_strip = strip,
|
||||
.link_libc = true,
|
||||
.link_libcpp = link_libcpp,
|
||||
}) catch |err| {
|
||||
comp.setMiscFailure(
|
||||
.libtsan,
|
||||
@ -272,6 +283,14 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
|
||||
});
|
||||
}
|
||||
|
||||
const skip_linker_dependencies = !target.isDarwin();
|
||||
const linker_allow_shlib_undefined = target.isDarwin();
|
||||
const install_name = if (target.isDarwin())
|
||||
try std.fmt.allocPrintZ(arena, "@rpath/{s}", .{basename})
|
||||
else
|
||||
null;
|
||||
// Workaround for https://github.com/llvm/llvm-project/issues/97627
|
||||
const headerpad_size: ?u32 = if (target.isDarwin()) 32 else null;
|
||||
const sub_compilation = Compilation.create(comp.gpa, arena, .{
|
||||
.local_cache_directory = comp.global_cache_directory,
|
||||
.global_cache_directory = comp.global_cache_directory,
|
||||
@ -294,7 +313,10 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
|
||||
.verbose_cimport = comp.verbose_cimport,
|
||||
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
|
||||
.clang_passthrough_mode = comp.clang_passthrough_mode,
|
||||
.skip_linker_dependencies = true,
|
||||
.skip_linker_dependencies = skip_linker_dependencies,
|
||||
.linker_allow_shlib_undefined = linker_allow_shlib_undefined,
|
||||
.install_name = install_name,
|
||||
.headerpad_size = headerpad_size,
|
||||
}) catch |err| {
|
||||
comp.setMiscFailure(
|
||||
.libtsan,
|
||||
@ -317,8 +339,8 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo
|
||||
},
|
||||
};
|
||||
|
||||
assert(comp.tsan_static_lib == null);
|
||||
comp.tsan_static_lib = try sub_compilation.toCrtFile();
|
||||
assert(comp.tsan_lib == null);
|
||||
comp.tsan_lib = try sub_compilation.toCrtFile();
|
||||
}
|
||||
|
||||
const tsan_sources = [_][]const u8{
|
||||
|
||||
@ -1145,7 +1145,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: std.Progress.Node) l
|
||||
|
||||
// TSAN
|
||||
if (comp.config.any_sanitize_thread) {
|
||||
try positionals.append(.{ .path = comp.tsan_static_lib.?.full_object_path });
|
||||
try positionals.append(.{ .path = comp.tsan_lib.?.full_object_path });
|
||||
}
|
||||
|
||||
// libc
|
||||
@ -1603,7 +1603,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
|
||||
}
|
||||
|
||||
if (comp.config.any_sanitize_thread) {
|
||||
try argv.append(comp.tsan_static_lib.?.full_object_path);
|
||||
try argv.append(comp.tsan_lib.?.full_object_path);
|
||||
}
|
||||
|
||||
// libc
|
||||
@ -2610,7 +2610,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, prog_node: std.Progress.Node) !void
|
||||
}
|
||||
|
||||
if (comp.config.any_sanitize_thread) {
|
||||
try argv.append(comp.tsan_static_lib.?.full_object_path);
|
||||
try argv.append(comp.tsan_lib.?.full_object_path);
|
||||
}
|
||||
|
||||
// libc
|
||||
|
||||
@ -192,7 +192,7 @@ pub fn createEmpty(
|
||||
null
|
||||
else
|
||||
try std.fmt.allocPrint(arena, "{s}.o", .{emit.sub_path});
|
||||
const allow_shlib_undefined = options.allow_shlib_undefined orelse comp.config.any_sanitize_thread;
|
||||
const allow_shlib_undefined = options.allow_shlib_undefined orelse false;
|
||||
|
||||
const self = try arena.create(MachO);
|
||||
self.* = .{
|
||||
@ -413,7 +413,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: std.Progress.Node)
|
||||
|
||||
// TSAN
|
||||
if (comp.config.any_sanitize_thread) {
|
||||
try positionals.append(.{ .path = comp.tsan_static_lib.?.full_object_path });
|
||||
try positionals.append(.{ .path = comp.tsan_lib.?.full_object_path });
|
||||
}
|
||||
|
||||
for (positionals.items) |obj| {
|
||||
@ -831,7 +831,9 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
|
||||
}
|
||||
|
||||
if (comp.config.any_sanitize_thread) {
|
||||
try argv.append(comp.tsan_static_lib.?.full_object_path);
|
||||
const path = comp.tsan_lib.?.full_object_path;
|
||||
try argv.append(path);
|
||||
try argv.appendSlice(&.{ "-rpath", std.fs.path.dirname(path) orelse "." });
|
||||
}
|
||||
|
||||
for (self.lib_dirs) |lib_dir| {
|
||||
@ -2959,7 +2961,8 @@ pub fn writeStrtab(self: *MachO, off: u32) !u32 {
|
||||
}
|
||||
|
||||
fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {
|
||||
const gpa = self.base.comp.gpa;
|
||||
const comp = self.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const needed_size = try load_commands.calcLoadCommandsSize(self, false);
|
||||
const buffer = try gpa.alloc(u8, needed_size);
|
||||
defer gpa.free(buffer);
|
||||
@ -3015,8 +3018,16 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {
|
||||
ncmds += 1;
|
||||
}
|
||||
|
||||
try load_commands.writeRpathLCs(self.base.rpath_list, writer);
|
||||
ncmds += self.base.rpath_list.len;
|
||||
for (self.base.rpath_list) |rpath| {
|
||||
try load_commands.writeRpathLC(rpath, writer);
|
||||
ncmds += 1;
|
||||
}
|
||||
if (comp.config.any_sanitize_thread) {
|
||||
const path = comp.tsan_lib.?.full_object_path;
|
||||
const rpath = std.fs.path.dirname(path) orelse ".";
|
||||
try load_commands.writeRpathLC(rpath, writer);
|
||||
ncmds += 1;
|
||||
}
|
||||
|
||||
try writer.writeStruct(macho.source_version_command{ .version = 0 });
|
||||
ncmds += 1;
|
||||
|
||||
@ -18,6 +18,9 @@ fn calcInstallNameLen(cmd_size: u64, name: []const u8, assume_max_path_len: bool
|
||||
}
|
||||
|
||||
pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) !u32 {
|
||||
const comp = macho_file.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
|
||||
var sizeofcmds: u64 = 0;
|
||||
|
||||
// LC_SEGMENT_64
|
||||
@ -48,7 +51,6 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) !u32
|
||||
}
|
||||
// LC_ID_DYLIB
|
||||
if (macho_file.base.isDynLib()) {
|
||||
const gpa = macho_file.base.comp.gpa;
|
||||
const emit = macho_file.base.emit;
|
||||
const install_name = macho_file.install_name orelse
|
||||
try emit.directory.join(gpa, &.{emit.sub_path});
|
||||
@ -68,6 +70,16 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) !u32
|
||||
assume_max_path_len,
|
||||
);
|
||||
}
|
||||
|
||||
if (comp.config.any_sanitize_thread) {
|
||||
const path = comp.tsan_lib.?.full_object_path;
|
||||
const rpath = std.fs.path.dirname(path) orelse ".";
|
||||
sizeofcmds += calcInstallNameLen(
|
||||
@sizeOf(macho.rpath_command),
|
||||
rpath,
|
||||
assume_max_path_len,
|
||||
);
|
||||
}
|
||||
}
|
||||
// LC_SOURCE_VERSION
|
||||
sizeofcmds += @sizeOf(macho.source_version_command);
|
||||
@ -245,24 +257,22 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: anytype) !void {
|
||||
}, writer);
|
||||
}
|
||||
|
||||
pub fn writeRpathLCs(rpaths: []const []const u8, writer: anytype) !void {
|
||||
for (rpaths) |rpath| {
|
||||
const rpath_len = rpath.len + 1;
|
||||
const cmdsize = @as(u32, @intCast(mem.alignForward(
|
||||
u64,
|
||||
@sizeOf(macho.rpath_command) + rpath_len,
|
||||
@sizeOf(u64),
|
||||
)));
|
||||
try writer.writeStruct(macho.rpath_command{
|
||||
.cmdsize = cmdsize,
|
||||
.path = @sizeOf(macho.rpath_command),
|
||||
});
|
||||
try writer.writeAll(rpath);
|
||||
try writer.writeByte(0);
|
||||
const padding = cmdsize - @sizeOf(macho.rpath_command) - rpath_len;
|
||||
if (padding > 0) {
|
||||
try writer.writeByteNTimes(0, padding);
|
||||
}
|
||||
pub fn writeRpathLC(rpath: []const u8, writer: anytype) !void {
|
||||
const rpath_len = rpath.len + 1;
|
||||
const cmdsize = @as(u32, @intCast(mem.alignForward(
|
||||
u64,
|
||||
@sizeOf(macho.rpath_command) + rpath_len,
|
||||
@sizeOf(u64),
|
||||
)));
|
||||
try writer.writeStruct(macho.rpath_command{
|
||||
.cmdsize = cmdsize,
|
||||
.path = @sizeOf(macho.rpath_command),
|
||||
});
|
||||
try writer.writeAll(rpath);
|
||||
try writer.writeByte(0);
|
||||
const padding = cmdsize - @sizeOf(macho.rpath_command) - rpath_len;
|
||||
if (padding > 0) {
|
||||
try writer.writeByteNTimes(0, padding);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user