From 0f2612037784570930dea433afef559ff6161b21 Mon Sep 17 00:00:00 2001 From: Michael Dusan Date: Sun, 16 May 2021 15:59:34 -0400 Subject: [PATCH] overhaul elf csu (c-runtime startup) logic - more support for linux, android, freebsd, netbsd, openbsd, dragonfly - centralize musl utils; musl logic is no longer intertwined with csu - fix musl compilation to build crti/crtn for full archs list - fix openbsd to support `zig build-lib -dynamic` - initial dragonfly linking success (with a warning) ancillary: - fix emutls (openbsd) tests to use `try` --- lib/std/Thread.zig | 3 + lib/std/c/dragonfly.zig | 4 + lib/std/child_process.zig | 16 +- lib/std/os/bits/dragonfly.zig | 26 +++ lib/std/special/compiler_rt/emutls.zig | 12 +- src/Compilation.zig | 4 +- src/libc_installation.zig | 6 +- src/link/Elf.zig | 233 ++++++++++++++++++++----- src/musl.zig | 53 ++++-- src/target.zig | 21 --- test/stack_traces.zig | 1 + 11 files changed, 288 insertions(+), 91 deletions(-) diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index ad82e4beef..fbb3d927e2 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -576,6 +576,9 @@ pub fn getCurrentThreadId() u64 { assert(c.pthread_threadid_np(null, &thread_id) == 0); return thread_id; }, + .dragonfly => { + return @bitCast(u32, c.lwp_gettid()); + }, .netbsd => { return @bitCast(u32, c._lwp_self()); }, diff --git a/lib/std/c/dragonfly.zig b/lib/std/c/dragonfly.zig index 4e6650094b..7d722dad44 100644 --- a/lib/std/c/dragonfly.zig +++ b/lib/std/c/dragonfly.zig @@ -18,6 +18,8 @@ pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int; pub const dl_iterate_phdr_callback = fn (info: *dl_phdr_info, size: usize, data: ?*c_void) callconv(.C) c_int; pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int; +pub extern "c" fn lwp_gettid() c_int; + pub extern "c" fn posix_memalign(memptr: *?*c_void, alignment: usize, size: usize) c_int; pub const pthread_mutex_t = extern struct { @@ -31,3 +33,5 @@ pub const pthread_attr_t = extern struct { // copied from freebsd __size: [56]u8, __align: c_long, }; + +pub const sem_t = ?*opaque {}; diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig index 5602f16f75..a4ba12ef2f 100644 --- a/lib/std/child_process.zig +++ b/lib/std/child_process.zig @@ -203,6 +203,10 @@ pub const ChildProcess = struct { // of space an ArrayList will allocate grows exponentially. const bump_amt = 512; + // TODO https://github.com/ziglang/zig/issues/8724 + // parent process does not receive POLLHUP events + const dragonfly_workaround = builtin.os.tag == .dragonfly; + while (dead_fds < poll_fds.len) { const events = try os.poll(&poll_fds, std.math.maxInt(i32)); if (events == 0) continue; @@ -215,7 +219,11 @@ pub const ChildProcess = struct { try stdout.ensureCapacity(new_capacity); const buf = stdout.unusedCapacitySlice(); if (buf.len == 0) return error.StdoutStreamTooLong; - stdout.items.len += try os.read(poll_fds[0].fd, buf); + const nread = try os.read(poll_fds[0].fd, buf); + stdout.items.len += nread; + + // insert POLLHUP event because dragonfly fails to do so + if (dragonfly_workaround and nread == 0) poll_fds[0].revents |= os.POLLHUP; } if (poll_fds[1].revents & os.POLLIN != 0) { // stderr is ready. @@ -223,7 +231,11 @@ pub const ChildProcess = struct { try stderr.ensureCapacity(new_capacity); const buf = stderr.unusedCapacitySlice(); if (buf.len == 0) return error.StderrStreamTooLong; - stderr.items.len += try os.read(poll_fds[1].fd, buf); + const nread = try os.read(poll_fds[1].fd, buf); + stderr.items.len += nread; + + // insert POLLHUP event because dragonfly fails to do so + if (dragonfly_workaround and nread == 0) poll_fds[1].revents |= os.POLLHUP; } // Exclude the fds that signaled an error. diff --git a/lib/std/os/bits/dragonfly.zig b/lib/std/os/bits/dragonfly.zig index 8c4aacd053..7d1921072a 100644 --- a/lib/std/os/bits/dragonfly.zig +++ b/lib/std/os/bits/dragonfly.zig @@ -767,3 +767,29 @@ pub const rlimit = extern struct { /// Hard limit max: rlim_t, }; + +pub const SHUT_RD = 0; +pub const SHUT_WR = 1; +pub const SHUT_RDWR = 2; + +pub const nfds_t = u32; + +pub const pollfd = extern struct { + fd: fd_t, + events: i16, + revents: i16, +}; + +/// Requestable events. +pub const POLLIN = 0x0001; +pub const POLLPRI = 0x0002; +pub const POLLOUT = 0x0004; +pub const POLLRDNORM = 0x0040; +pub const POLLWRNORM = POLLOUT; +pub const POLLRDBAND = 0x0080; +pub const POLLWRBAND = 0x0100; + +/// These events are set if they occur regardless of whether they were requested. +pub const POLLERR = 0x0008; +pub const POLLHUP = 0x0010; +pub const POLLNVAL = 0x0020; diff --git a/lib/std/special/compiler_rt/emutls.zig b/lib/std/special/compiler_rt/emutls.zig index 8871afe00b..46d0dd98e8 100644 --- a/lib/std/special/compiler_rt/emutls.zig +++ b/lib/std/special/compiler_rt/emutls.zig @@ -376,7 +376,7 @@ test "__emutls_get_address with default_value" { test "test default_value with differents sizes" { const testType = struct { - fn _testType(comptime T: type, value: T) void { + fn _testType(comptime T: type, value: T) !void { var def: T = value; var ctl = emutls_control.init(T, &def); var x = ctl.get_typed_pointer(T); @@ -384,11 +384,11 @@ test "test default_value with differents sizes" { } }._testType; - testType(usize, 1234); - testType(u32, 1234); - testType(i16, -12); - testType(f64, -12.0); - testType( + try testType(usize, 1234); + try testType(u32, 1234); + try testType(i16, -12); + try testType(f64, -12.0); + try testType( @TypeOf("012345678901234567890123456789"), "012345678901234567890123456789", ); diff --git a/src/Compilation.zig b/src/Compilation.zig index 50dc97a929..b96d30c204 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1407,7 +1407,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { } if (comp.wantBuildMuslFromSource()) { try comp.work_queue.ensureUnusedCapacity(6); - if (target_util.libc_needs_crti_crtn(comp.getTarget())) { + if (musl.needsCrtiCrtn(comp.getTarget())) { comp.work_queue.writeAssumeCapacity(&[_]Job{ .{ .musl_crt_file = .crti_o }, .{ .musl_crt_file = .crtn_o }, @@ -3180,7 +3180,7 @@ fn detectLibCIncludeDirs( const generic_name = target_util.libCGenericName(target); // Some architectures are handled by the same set of headers. const arch_name = if (target.abi.isMusl()) - target_util.archMuslName(target.cpu.arch) + musl.archMuslName(target.cpu.arch) else if (target.cpu.arch.isThumb()) // ARM headers are valid for Thumb too. switch (target.cpu.arch) { diff --git a/src/libc_installation.zig b/src/libc_installation.zig index a6826108d4..4fd55ab4e6 100644 --- a/src/libc_installation.zig +++ b/src/libc_installation.zig @@ -195,8 +195,8 @@ pub const LibCInstallation = struct { errdefer batch.wait() catch {}; batch.add(&async self.findNativeIncludeDirPosix(args)); switch (Target.current.os.tag) { - .freebsd, .netbsd, .openbsd => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/usr/lib"), - .linux, .dragonfly => batch.add(&async self.findNativeCrtDirPosix(args)), + .freebsd, .netbsd, .openbsd, .dragonfly => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/usr/lib"), + .linux => batch.add(&async self.findNativeCrtDirPosix(args)), .haiku => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/system/develop/lib"), else => {}, } @@ -523,7 +523,7 @@ pub const CCPrintFileNameOptions = struct { }; /// caller owns returned memory -fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { +pub fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { const allocator = args.allocator; const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe; diff --git a/src/link/Elf.zig b/src/link/Elf.zig index ae301788b4..693ae3f83c 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -23,6 +23,7 @@ const File = link.File; const build_options = @import("build_options"); const target_util = @import("../target.zig"); const glibc = @import("../glibc.zig"); +const musl = @import("../musl.zig"); const Cache = @import("../Cache.zig"); const llvm_backend = @import("../codegen/llvm.zig"); @@ -1278,7 +1279,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe; const have_dynamic_linker = self.base.options.link_libc and self.base.options.link_mode == .Dynamic and is_exe_or_dyn_lib; - const link_in_crt = self.base.options.link_libc and self.base.options.output_mode == .Exe; const target = self.base.options.target; const gc_sections = self.base.options.gc_sections orelse !is_obj; const stack_size = self.base.options.stack_size_override orelse 16777216; @@ -1499,40 +1499,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { try argv.append("-o"); try argv.append(full_out_path); - if (link_in_crt) { - const crt1o: []const u8 = o: { - if (target.os.tag == .netbsd) { - break :o "crt0.o"; - } else if (target.os.tag == .openbsd) { - if (self.base.options.link_mode == .Static) { - break :o "rcrt0.o"; - } else { - break :o "crt0.o"; - } - } else if (target.isAndroid()) { - if (self.base.options.link_mode == .Dynamic) { - break :o "crtbegin_dynamic.o"; - } else { - break :o "crtbegin_static.o"; - } - } else if (self.base.options.link_mode == .Static) { - if (self.base.options.pie) { - break :o "rcrt1.o"; - } else { - break :o "crt1.o"; - } - } else { - break :o "Scrt1.o"; - } - }; - try argv.append(try comp.get_libc_crt_file(arena, crt1o)); - if (target_util.libc_needs_crti_crtn(target)) { - try argv.append(try comp.get_libc_crt_file(arena, "crti.o")); - } - if (target.os.tag == .openbsd) { - try argv.append(try comp.get_libc_crt_file(arena, "crtbegin.o")); - } - } + // csu prelude + var csu = try CsuObjects.init(arena, self.base.options, comp); + if (csu.crt0) |v| try argv.append(v); + if (csu.crti) |v| try argv.append(v); + if (csu.crtbegin) |v| try argv.append(v); // rpaths var rpath_table = std.StringHashMap(void).init(self.base.allocator); @@ -1676,16 +1647,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { } } - // crt end - if (link_in_crt) { - if (target.isAndroid()) { - try argv.append(try comp.get_libc_crt_file(arena, "crtend_android.o")); - } else if (target.os.tag == .openbsd) { - try argv.append(try comp.get_libc_crt_file(arena, "crtend.o")); - } else if (target_util.libc_needs_crti_crtn(target)) { - try argv.append(try comp.get_libc_crt_file(arena, "crtn.o")); - } - } + // crt postlude + if (csu.crtend) |v| try argv.append(v); + if (csu.crtn) |v| try argv.append(v); if (allow_shlib_undefined) { try argv.append("--allow-shlib-undefined"); @@ -3237,3 +3201,182 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { return std.math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch std.math.maxInt(@TypeOf(actual_size)); } + +// Provide a blueprint of csu (c-runtime startup) objects for supported +// link modes. +// +// This is for cross-mode targets only. For host-mode targets the system +// compiler can be probed to produce a robust blueprint. +// +// Targets requiring a libc for which zig does not bundle a libc are +// host-mode targets. Unfortunately, host-mode probes are not yet +// implemented. For now the data is hard-coded here. Such targets are +// { freebsd, netbsd, openbsd, dragonfly }. +const CsuObjects = struct { + crt0: ?[]const u8 = null, + crti: ?[]const u8 = null, + crtbegin: ?[]const u8 = null, + crtend: ?[]const u8 = null, + crtn: ?[]const u8 = null, + + fn init(arena: *mem.Allocator, link_options: link.Options, comp: *const Compilation) !CsuObjects { + // crt objects are only required for libc. + if (!link_options.link_libc) return CsuObjects{}; + + var result: CsuObjects = .{}; + + // TODO: https://github.com/ziglang/zig/issues/4629 + // - use inline enum type + // - reduce to enum-literals for values + const Mode = enum { + dynamic_lib, + dynamic_exe, + dynamic_pie, + static_exe, + static_pie, + }; + + // Flatten crt case types. + const mode: Mode = switch (link_options.output_mode) { + .Obj => return CsuObjects{}, + .Lib => switch (link_options.link_mode) { + .Dynamic => Mode.dynamic_lib, + .Static => return CsuObjects{}, + }, + .Exe => switch (link_options.link_mode) { + .Dynamic => if (link_options.pie) Mode.dynamic_pie else Mode.dynamic_exe, + .Static => if (link_options.pie) Mode.static_pie else Mode.static_exe, + }, + }; + + if (link_options.target.isAndroid()) { + switch (mode) { + // zig fmt: off + .dynamic_lib => result.set( null, null, "crtbegin_so.o", "crtend_so.o", null ), + .dynamic_exe, + .dynamic_pie => result.set( null, null, "crtbegin_dynamic.o", "crtend_android.o", null ), + .static_exe, + .static_pie => result.set( null, null, "crtbegin_static.o", "crtend_android.o", null ), + // zig fmt: on + } + } else { + switch (link_options.target.os.tag) { + .linux => { + switch (mode) { + // zig fmt: off + .dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), + .dynamic_exe => result.set( "crt1.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), + .dynamic_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), + .static_exe => result.set( "crt1.o", "crti.o", "crtbeginT.o", "crtend.o", "crtn.o" ), + .static_pie => result.set( "rcrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), + // zig fmt: on + } + if (link_options.libc_installation) |_| { + // hosted-glibc provides crtbegin/end objects in platform/compiler-specific dirs + // and they are not known at comptime. For now null-out crtbegin/end objects; + // there is no feature loss, zig has never linked those objects in before. + // TODO: probe for paths, ie. `cc -print-file-name` + result.crtbegin = null; + result.crtend = null; + } else { + // Bundled glibc only has Scrt1.o . + if (result.crt0 != null and link_options.target.isGnuLibC()) result.crt0 = "Scrt1.o"; + } + }, + .dragonfly => switch (mode) { + // zig fmt: off + .dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), + .dynamic_exe => result.set( "crt1.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), + .dynamic_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), + .static_exe => result.set( "crt1.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), + .static_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), + // zig fmt: on + }, + .freebsd => switch (mode) { + // zig fmt: off + .dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), + .dynamic_exe => result.set( "crt1.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), + .dynamic_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), + .static_exe => result.set( "crt1.o", "crti.o", "crtbeginT.o", "crtend.o", "crtn.o" ), + .static_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), + // zig fmt: on + }, + .netbsd => switch (mode) { + // zig fmt: off + .dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), + .dynamic_exe => result.set( "crt0.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), + .dynamic_pie => result.set( "crt0.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), + .static_exe => result.set( "crt0.o", "crti.o", "crtbeginT.o", "crtend.o", "crtn.o" ), + .static_pie => result.set( "crt0.o", "crti.o", "crtbeginT.o", "crtendS.o", "crtn.o" ), + // zig fmt: on + }, + .openbsd => switch(mode) { + // zig fmt: off + .dynamic_lib => result.set( null, null, "crtbeginS.o", "crtendS.o", null ), + .dynamic_exe, + .dynamic_pie => result.set( "crt0.o", null, "crtbegin.o", "crtend.o", null ), + .static_exe, + .static_pie => result.set( "rcrt0.o", null, "crtbegin.o", "crtend.o", null ), + // zig fmt: on + }, + else => {}, + } + } + + // Convert each object to a full pathname. + if (link_options.libc_installation) |lci| { + const crt_dir_path = lci.crt_dir orelse return error.LibCInstallationMissingCRTDir; + switch (link_options.target.os.tag) { + .dragonfly => { + if (result.crt0) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); + if (result.crti) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); + if (result.crtn) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); + + var gccv: []const u8 = undefined; + if (link_options.target.os.version_range.semver.isAtLeast(.{ .major = 5, .minor = 4 }) orelse true) { + gccv = "gcc80"; + } else { + gccv = "gcc54"; + } + + if (result.crtbegin) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, gccv, obj.* }); + if (result.crtend) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, gccv, obj.* }); + }, + else => { + inline for (std.meta.fields(@TypeOf(result))) |f,i| { + if (@field(result, f.name)) |*obj| { + obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); + } + } + } + } + } else { + inline for (std.meta.fields(@TypeOf(result))) |f,i| { + if (@field(result, f.name)) |*obj| { + if (comp.crt_files.get(obj.*)) |crtf| { + obj.* = crtf.full_object_path; + } else { + @field(result, f.name) = null; + } + } + } + } + + return result; + } + + fn set( + self: *CsuObjects, + crt0: ?[]const u8, + crti: ?[]const u8, + crtbegin: ?[]const u8, + crtend: ?[]const u8, + crtn: ?[]const u8, + ) void { + self.crt0 = crt0; + self.crti = crti; + self.crtbegin = crtbegin; + self.crtend = crtend; + self.crtn = crtn; + } +}; diff --git a/src/musl.zig b/src/musl.zig index 0f0e3b271a..e2f1509d3f 100644 --- a/src/musl.zig +++ b/src/musl.zig @@ -30,7 +30,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { switch (crt_file) { .crti_o => { var args = std.ArrayList([]const u8).init(arena); - try add_cc_args(comp, arena, &args, false); + try addCcArgs(comp, arena, &args, false); try args.appendSlice(&[_][]const u8{ "-Qunused-arguments", }); @@ -43,7 +43,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { }, .crtn_o => { var args = std.ArrayList([]const u8).init(arena); - try add_cc_args(comp, arena, &args, false); + try addCcArgs(comp, arena, &args, false); try args.appendSlice(&[_][]const u8{ "-Qunused-arguments", }); @@ -56,7 +56,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { }, .crt1_o => { var args = std.ArrayList([]const u8).init(arena); - try add_cc_args(comp, arena, &args, false); + try addCcArgs(comp, arena, &args, false); try args.appendSlice(&[_][]const u8{ "-fno-stack-protector", "-DCRT", @@ -72,7 +72,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { }, .rcrt1_o => { var args = std.ArrayList([]const u8).init(arena); - try add_cc_args(comp, arena, &args, false); + try addCcArgs(comp, arena, &args, false); try args.appendSlice(&[_][]const u8{ "-fPIC", "-fno-stack-protector", @@ -89,7 +89,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { }, .scrt1_o => { var args = std.ArrayList([]const u8).init(arena); - try add_cc_args(comp, arena, &args, false); + try addCcArgs(comp, arena, &args, false); try args.appendSlice(&[_][]const u8{ "-fPIC", "-fno-stack-protector", @@ -108,7 +108,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { // When there is a src//foo.* then it should substitute for src/foo.* // Even a .s file can substitute for a .c file. const target = comp.getTarget(); - const arch_name = target_util.archMuslName(target.cpu.arch); + const arch_name = archMuslName(target.cpu.arch); var source_table = std.StringArrayHashMap(Ext).init(comp.gpa); defer source_table.deinit(); @@ -147,7 +147,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { var is_arch_specific = false; // Architecture-specific implementations are under a / folder. - if (is_musl_arch_name(dirbasename)) { + if (isMuslArchName(dirbasename)) { if (!mem.eql(u8, dirbasename, arch_name)) continue; // Not the architecture we're compiling for. is_arch_specific = true; @@ -177,7 +177,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { } var args = std.ArrayList([]const u8).init(arena); - try add_cc_args(comp, arena, &args, ext == .o3); + try addCcArgs(comp, arena, &args, ext == .o3); try args.appendSlice(&[_][]const u8{ "-Qunused-arguments", "-w", // disable all warnings @@ -248,7 +248,36 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { } } -fn is_musl_arch_name(name: []const u8) bool { +pub fn archMuslName(arch: std.Target.Cpu.Arch) [:0]const u8 { + switch (arch) { + .aarch64, .aarch64_be => return "aarch64", + .arm, .armeb, .thumb, .thumbeb => return "arm", + .i386 => return "i386", + .mips, .mipsel => return "mips", + .mips64el, .mips64 => return "mips64", + .powerpc => return "powerpc", + .powerpc64, .powerpc64le => return "powerpc64", + .riscv64 => return "riscv64", + .s390x => return "s390x", + .wasm32, .wasm64 => return "wasm", + .x86_64 => return "x86_64", + else => unreachable, + } +} + +// Return true if musl has arch-specific crti/crtn sources. +// See lib/libc/musl/crt/ARCH/crt?.s . +pub fn needsCrtiCrtn(target: std.Target) bool { + // zig fmt: off + return switch (target.cpu.arch) { + .riscv64, + .wasm32, .wasm64 => return false, + else => true, + }; + // zig fmt: on +} + +fn isMuslArchName(name: []const u8) bool { const musl_arch_names = [_][]const u8{ "aarch64", "arm", @@ -314,14 +343,14 @@ fn addSrcFile(arena: *Allocator, source_table: *std.StringArrayHashMap(Ext), fil source_table.putAssumeCapacityNoClobber(key, ext); } -fn add_cc_args( +fn addCcArgs( comp: *Compilation, arena: *Allocator, args: *std.ArrayList([]const u8), want_O3: bool, ) error{OutOfMemory}!void { const target = comp.getTarget(); - const arch_name = target_util.archMuslName(target.cpu.arch); + const arch_name = archMuslName(target.cpu.arch); const os_name = @tagName(target.os.tag); const triple = try std.fmt.allocPrint(arena, "{s}-{s}-musl", .{ arch_name, os_name }); const o_arg = if (want_O3) "-O3" else "-Os"; @@ -369,7 +398,7 @@ fn add_cc_args( fn start_asm_path(comp: *Compilation, arena: *Allocator, basename: []const u8) ![]const u8 { const target = comp.getTarget(); return comp.zig_lib_directory.join(arena, &[_][]const u8{ - "libc", "musl", "crt", target_util.archMuslName(target.cpu.arch), basename, + "libc", "musl", "crt", archMuslName(target.cpu.arch), basename, }); } diff --git a/src/target.zig b/src/target.zig index 35c3cd8560..e077d9629c 100644 --- a/src/target.zig +++ b/src/target.zig @@ -99,23 +99,6 @@ pub fn libCGenericName(target: std.Target) [:0]const u8 { } } -pub fn archMuslName(arch: std.Target.Cpu.Arch) [:0]const u8 { - switch (arch) { - .aarch64, .aarch64_be => return "aarch64", - .arm, .armeb, .thumb, .thumbeb => return "arm", - .mips, .mipsel => return "mips", - .mips64el, .mips64 => return "mips64", - .powerpc => return "powerpc", - .powerpc64, .powerpc64le => return "powerpc64", - .s390x => return "s390x", - .i386 => return "i386", - .x86_64 => return "x86_64", - .riscv64 => return "riscv64", - .wasm32, .wasm64 => return "wasm", - else => unreachable, - } -} - pub fn canBuildLibC(target: std.Target) bool { for (available_libcs) |libc| { if (target.cpu.arch == libc.arch and target.os.tag == libc.os and target.abi == libc.abi) { @@ -172,10 +155,6 @@ pub fn supports_fpic(target: std.Target) bool { return target.os.tag != .windows; } -pub fn libc_needs_crti_crtn(target: std.Target) bool { - return !(target.cpu.arch.isRISCV() or target.isAndroid() or target.os.tag == .openbsd); -} - pub fn isSingleThreaded(target: std.Target) bool { return target.isWasm(); } diff --git a/test/stack_traces.zig b/test/stack_traces.zig index 4b2d6bebfd..c40413f936 100644 --- a/test/stack_traces.zig +++ b/test/stack_traces.zig @@ -171,6 +171,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { cases.addCase(.{ .exclude_os = .{ + .openbsd, // integer overflow .windows, }, .name = "dumpCurrentStackTrace",