commit 69ce7f0e085b5fb3bf7356e9999940c60c79cfe2 (tree)
parent 3bcdca07a37d29256c56c2b681d43d74cd0f88b5
Author: Jakub Konka <kubkon@jakubkonka.com>
Date: Thu, 3 Oct 2024 15:19:58 +0200
Merge pull request #21573 from alexrp/elf-header
Some additions to `std.elf` addressing #19830, plus some zld improvements
Diffstat:
3 files changed, 137 insertions(+), 37 deletions(-)
diff --git a/lib/std/elf.zig b/lib/std/elf.zig
@@ -453,18 +453,27 @@ 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;
};
/// All integers are native endian.
pub const Header = struct {
+ is_64: bool,
endian: std.builtin.Endian,
+ os_abi: OSABI,
+ abi_version: u8,
+ type: ET,
machine: EM,
- is_64: bool,
entry: u64,
phoff: u64,
shoff: u64,
@@ -501,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,
@@ -508,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);
@@ -520,9 +539,12 @@ pub const Header = struct {
} else hdr32.e_machine;
return @as(Header, .{
+ .is_64 = is_64,
.endian = endian,
+ .os_abi = os_abi,
+ .abi_version = abi_version,
+ .type = @"type",
.machine = machine,
- .is_64 = is_64,
.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),
@@ -637,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);
@@ -649,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 {
@@ -657,21 +679,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;
@@ -1094,6 +1119,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:
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
@@ -2584,11 +2584,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);
diff --git 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