From 496a067d3f7c2d48c68ff0adae389994e68b70ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 1 Oct 2024 03:53:27 +0200 Subject: [PATCH 1/7] std.elf: Define ET.(LOOS,HIOS) constants. --- lib/std/elf.zig | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/std/elf.zig b/lib/std/elf.zig index d92973c314..f09bbb63fb 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -453,10 +453,16 @@ pub const ET = enum(u16) { /// Core file CORE = 4, + /// Beginning of OS-specific codes + pub const LOOS = 0xfe00; + + /// End of OS-specific codes + pub const HIOS = 0xfeff; + /// Beginning of processor-specific codes pub const LOPROC = 0xff00; - /// Processor-specific + /// End of processor-specific codes pub const HIPROC = 0xffff; }; From 5db04e05951d46709dba0316bc7676a19399337e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 1 Oct 2024 03:53:58 +0200 Subject: [PATCH 2/7] std.elf: Define EI_(OSABI,ABIVERSION,PAD) constants. --- lib/std/elf.zig | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/std/elf.zig b/lib/std/elf.zig index f09bbb63fb..2215c1341b 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -663,21 +663,24 @@ pub fn int32(need_bswap: bool, int_32: anytype, comptime Int64: anytype) Int64 { } } -pub const EI_NIDENT = 16; - -pub const EI_CLASS = 4; pub const ELFCLASSNONE = 0; pub const ELFCLASS32 = 1; pub const ELFCLASS64 = 2; pub const ELFCLASSNUM = 3; -pub const EI_DATA = 5; pub const ELFDATANONE = 0; pub const ELFDATA2LSB = 1; pub const ELFDATA2MSB = 2; pub const ELFDATANUM = 3; +pub const EI_CLASS = 4; +pub const EI_DATA = 5; pub const EI_VERSION = 6; +pub const EI_OSABI = 7; +pub const EI_ABIVERSION = 8; +pub const EI_PAD = 9; + +pub const EI_NIDENT = 16; pub const Elf32_Half = u16; pub const Elf64_Half = u16; From 604ff131dd79064535f82b453c5dcb648add171d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 1 Oct 2024 03:54:22 +0200 Subject: [PATCH 3/7] std.elf: Add OSABI enum sourced from binutils. --- lib/std/elf.zig | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/lib/std/elf.zig b/lib/std/elf.zig index 2215c1341b..0f8d4d10f0 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -1103,6 +1103,57 @@ pub const Addr = switch (@sizeOf(usize)) { }; pub const Half = u16; +pub const OSABI = enum(u8) { + /// UNIX System V ABI + NONE = 0, + /// HP-UX operating system + HPUX = 1, + /// NetBSD + NETBSD = 2, + /// GNU (Hurd/Linux) + GNU = 3, + /// Solaris + SOLARIS = 6, + /// AIX + AIX = 7, + /// IRIX + IRIX = 8, + /// FreeBSD + FREEBSD = 9, + /// TRU64 UNIX + TRU64 = 10, + /// Novell Modesto + MODESTO = 11, + /// OpenBSD + OPENBSD = 12, + /// OpenVMS + OPENVMS = 13, + /// Hewlett-Packard Non-Stop Kernel + NSK = 14, + /// AROS + AROS = 15, + /// FenixOS + FENIXOS = 16, + /// Nuxi CloudABI + CLOUDABI = 17, + /// Stratus Technologies OpenVOS + OPENVOS = 18, + /// NVIDIA CUDA architecture + CUDA = 51, + /// AMD HSA Runtime + AMDGPU_HSA = 64, + /// AMD PAL Runtime + AMDGPU_PAL = 65, + /// AMD Mesa3D Runtime + AMDGPU_MESA3D = 66, + /// ARM + ARM = 97, + /// Standalone (embedded) application + STANDALONE = 255, + + _, +}; + /// Machine architectures. /// /// See current registered ELF machine architectures at: From 9bbfc864af0311403aa19538999b170dbd35b7dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 1 Oct 2024 03:54:42 +0200 Subject: [PATCH 4/7] std.elf: Parse and make available some extra fields on Header. Closes #19830. --- lib/std/elf.zig | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/lib/std/elf.zig b/lib/std/elf.zig index 0f8d4d10f0..0fedffdd14 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -468,9 +468,12 @@ pub const ET = enum(u16) { /// All integers are native endian. pub const Header = struct { - endian: std.builtin.Endian, - machine: EM, is_64: bool, + endian: std.builtin.Endian, + os_abi: OSABI, + abi_version: u8, + type: ET, + machine: EM, entry: u64, phoff: u64, shoff: u64, @@ -507,6 +510,12 @@ pub const Header = struct { if (!mem.eql(u8, hdr32.e_ident[0..4], MAGIC)) return error.InvalidElfMagic; if (hdr32.e_ident[EI_VERSION] != 1) return error.InvalidElfVersion; + const is_64 = switch (hdr32.e_ident[EI_CLASS]) { + ELFCLASS32 => false, + ELFCLASS64 => true, + else => return error.InvalidElfClass, + }; + const endian: std.builtin.Endian = switch (hdr32.e_ident[EI_DATA]) { ELFDATA2LSB => .little, ELFDATA2MSB => .big, @@ -514,11 +523,15 @@ pub const Header = struct { }; const need_bswap = endian != native_endian; - const is_64 = switch (hdr32.e_ident[EI_CLASS]) { - ELFCLASS32 => false, - ELFCLASS64 => true, - else => return error.InvalidElfClass, - }; + const os_abi: OSABI = @enumFromInt(hdr32.e_ident[EI_OSABI]); + + // The meaning of this value depends on `os_abi` so just make it available as `u8`. + const abi_version = hdr32.e_ident[EI_ABIVERSION]; + + const @"type" = if (need_bswap) blk: { + const value = @intFromEnum(hdr32.e_type); + break :blk @as(ET, @enumFromInt(@byteSwap(value))); + } else hdr32.e_type; const machine = if (need_bswap) blk: { const value = @intFromEnum(hdr32.e_machine); @@ -526,9 +539,12 @@ pub const Header = struct { } else hdr32.e_machine; return @as(Header, .{ - .endian = endian, - .machine = machine, .is_64 = is_64, + .endian = endian, + .os_abi = os_abi, + .abi_version = abi_version, + .type = @"type", + .machine = machine, .entry = int(is_64, need_bswap, hdr32.e_entry, hdr64.e_entry), .phoff = int(is_64, need_bswap, hdr32.e_phoff, hdr64.e_phoff), .shoff = int(is_64, need_bswap, hdr32.e_shoff, hdr64.e_shoff), From b569ead29ea4459d0d363bf5a878ddb53f8f14f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 1 Oct 2024 04:32:42 +0200 Subject: [PATCH 5/7] std.elf: Make int() and int32() functions private. These have no callers outside std.elf. Even if the standard library should provide functions like these, std.elf is probably not the place, given how general they are. --- lib/std/elf.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/elf.zig b/lib/std/elf.zig index 0fedffdd14..d948e8fcc5 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -659,7 +659,7 @@ pub fn SectionHeaderIterator(comptime ParseSource: anytype) type { }; } -pub fn int(is_64: bool, need_bswap: bool, int_32: anytype, int_64: anytype) @TypeOf(int_64) { +fn int(is_64: bool, need_bswap: bool, int_32: anytype, int_64: anytype) @TypeOf(int_64) { if (is_64) { if (need_bswap) { return @byteSwap(int_64); @@ -671,7 +671,7 @@ pub fn int(is_64: bool, need_bswap: bool, int_32: anytype, int_64: anytype) @Typ } } -pub fn int32(need_bswap: bool, int_32: anytype, comptime Int64: anytype) Int64 { +fn int32(need_bswap: bool, int_32: anytype, comptime Int64: anytype) Int64 { if (need_bswap) { return @byteSwap(int_32); } else { From 125c043abc208842cd7e1deb188136600eb5c3ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 1 Oct 2024 04:34:32 +0200 Subject: [PATCH 6/7] link.Elf: Set EI_OSABI value correctly depending on target arch/OS. --- src/link/Elf.zig | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/link/Elf.zig b/src/link/Elf.zig index f610f2519d..52929aa7a6 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -2589,11 +2589,28 @@ pub fn writeElfHeader(self: *Elf) !void { hdr_buf[index] = 1; // ELF version index += 1; - // OS ABI, often set to 0 regardless of target platform + hdr_buf[index] = @intFromEnum(@as(elf.OSABI, switch (target.cpu.arch) { + .amdgcn => switch (target.os.tag) { + .amdhsa => .AMDGPU_HSA, + .amdpal => .AMDGPU_PAL, + .mesa3d => .AMDGPU_MESA3D, + else => .NONE, + }, + .msp430 => .STANDALONE, + else => switch (target.os.tag) { + .freebsd, .ps4 => .FREEBSD, + .hermit => .STANDALONE, + .illumos, .solaris => .SOLARIS, + .openbsd => .OPENBSD, + else => .NONE, + }, + })); + index += 1; + // ABI Version, possibly used by glibc but not by static executables // padding - @memset(hdr_buf[index..][0..9], 0); - index += 9; + @memset(hdr_buf[index..][0..8], 0); + index += 8; assert(index == 16); From 710a3b37e2f51010dcb37e4d39ba9ac77eddbd82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Tue, 1 Oct 2024 02:06:24 +0200 Subject: [PATCH 7/7] link.MachO: Add exhaustive handling for all Apple target triples. --- src/link/MachO.zig | 47 ++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 13a33b4cfa..9e2dbf6007 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -3542,8 +3542,8 @@ pub fn requiresCodeSig(self: MachO) bool { const target = self.getTarget(); return switch (target.cpu.arch) { .aarch64 => switch (target.os.tag) { - .macos => true, - .watchos, .tvos, .ios, .visionos => target.abi == .simulator, + .bridgeos, .driverkit, .macos => true, + .ios, .tvos, .visionos, .watchos => target.abi == .simulator, else => false, }, .x86_64 => false, @@ -4172,36 +4172,38 @@ pub const Platform = struct { const cmd = lc.cast(macho.build_version_command).?; return .{ .os_tag = switch (cmd.platform) { - .MACOS => .macos, + .BRIDGEOS => .bridgeos, + .DRIVERKIT => .driverkit, .IOS, .IOSSIMULATOR => .ios, - .TVOS, .TVOSSIMULATOR => .tvos, - .WATCHOS, .WATCHOSSIMULATOR => .watchos, .MACCATALYST => .ios, + .MACOS => .macos, + .TVOS, .TVOSSIMULATOR => .tvos, .VISIONOS, .VISIONOSSIMULATOR => .visionos, + .WATCHOS, .WATCHOSSIMULATOR => .watchos, else => @panic("TODO"), }, .abi = switch (cmd.platform) { .MACCATALYST => .macabi, .IOSSIMULATOR, .TVOSSIMULATOR, - .WATCHOSSIMULATOR, .VISIONOSSIMULATOR, + .WATCHOSSIMULATOR, => .simulator, else => .none, }, .version = appleVersionToSemanticVersion(cmd.minos), }; }, - .VERSION_MIN_MACOSX, .VERSION_MIN_IPHONEOS, + .VERSION_MIN_MACOSX, .VERSION_MIN_TVOS, .VERSION_MIN_WATCHOS, => { const cmd = lc.cast(macho.version_min_command).?; return .{ .os_tag = switch (lc.cmd()) { - .VERSION_MIN_MACOSX => .macos, .VERSION_MIN_IPHONEOS => .ios, + .VERSION_MIN_MACOSX => .macos, .VERSION_MIN_TVOS => .tvos, .VERSION_MIN_WATCHOS => .watchos, else => unreachable, @@ -4228,15 +4230,17 @@ pub const Platform = struct { pub fn toApplePlatform(plat: Platform) macho.PLATFORM { return switch (plat.os_tag) { - .macos => .MACOS, + .bridgeos => .BRIDGEOS, + .driverkit => .DRIVERKIT, .ios => switch (plat.abi) { - .simulator => .IOSSIMULATOR, .macabi => .MACCATALYST, + .simulator => .IOSSIMULATOR, else => .IOS, }, + .macos => .MACOS, .tvos => if (plat.abi == .simulator) .TVOSSIMULATOR else .TVOS, - .watchos => if (plat.abi == .simulator) .WATCHOSSIMULATOR else .WATCHOS, .visionos => if (plat.abi == .simulator) .VISIONOSSIMULATOR else .VISIONOS, + .watchos => if (plat.abi == .simulator) .WATCHOSSIMULATOR else .WATCHOS, else => unreachable, }; } @@ -4305,15 +4309,18 @@ const SupportedPlatforms = struct { // Source: https://github.com/apple-oss-distributions/ld64/blob/59a99ab60399c5e6c49e6945a9e1049c42b71135/src/ld/PlatformSupport.cpp#L52 // zig fmt: off const supported_platforms = [_]SupportedPlatforms{ - .{ .macos, .none, 0xA0E00, 0xA0800 }, - .{ .ios, .none, 0xC0000, 0x70000 }, - .{ .tvos, .none, 0xC0000, 0x70000 }, - .{ .watchos, .none, 0x50000, 0x20000 }, - .{ .visionos, .none, 0x10000, 0x10000 }, - .{ .ios, .simulator, 0xD0000, 0x80000 }, - .{ .tvos, .simulator, 0xD0000, 0x80000 }, - .{ .watchos, .simulator, 0x60000, 0x20000 }, - .{ .visionos, .simulator, 0x10000, 0x10000 }, + .{ .bridgeos, .none, 0x010000, 0x010000 }, + .{ .driverkit, .none, 0x130000, 0x130000 }, + .{ .ios, .none, 0x0C0000, 0x070000 }, + .{ .ios, .macabi, 0x0D0000, 0x0D0000 }, + .{ .ios, .simulator, 0x0D0000, 0x080000 }, + .{ .macos, .none, 0x0A0E00, 0x0A0800 }, + .{ .tvos, .none, 0x0C0000, 0x070000 }, + .{ .tvos, .simulator, 0x0D0000, 0x080000 }, + .{ .visionos, .none, 0x010000, 0x010000 }, + .{ .visionos, .simulator, 0x010000, 0x010000 }, + .{ .watchos, .none, 0x050000, 0x020000 }, + .{ .watchos, .simulator, 0x060000, 0x020000 }, }; // zig fmt: on