mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-27 19:09:47 +03:00
Merge pull request #19654 from jacobly0/wasi-ver
Target: add wasi os version
This commit is contained in:
+469
-436
@@ -81,14 +81,48 @@ pub const Os = struct {
|
||||
return tag == .solaris or tag == .illumos;
|
||||
}
|
||||
|
||||
pub fn exeFileExt(tag: Tag, arch: Cpu.Arch) [:0]const u8 {
|
||||
return switch (tag) {
|
||||
.windows => ".exe",
|
||||
.uefi => ".efi",
|
||||
.plan9 => arch.plan9Ext(),
|
||||
else => switch (arch) {
|
||||
.wasm32, .wasm64 => ".wasm",
|
||||
else => "",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn staticLibSuffix(tag: Tag, abi: Abi) [:0]const u8 {
|
||||
return switch (abi) {
|
||||
.msvc => ".lib",
|
||||
else => switch (tag) {
|
||||
.windows, .uefi => ".lib",
|
||||
else => ".a",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn dynamicLibSuffix(tag: Tag) [:0]const u8 {
|
||||
if (tag.isDarwin()) {
|
||||
return ".dylib";
|
||||
}
|
||||
switch (tag) {
|
||||
.windows => return ".dll",
|
||||
else => return ".so",
|
||||
}
|
||||
return switch (tag) {
|
||||
.windows, .uefi => ".dll",
|
||||
.ios, .macos, .watchos, .tvos => ".dylib",
|
||||
else => ".so",
|
||||
};
|
||||
}
|
||||
|
||||
pub fn libPrefix(tag: Os.Tag, abi: Abi) [:0]const u8 {
|
||||
return switch (abi) {
|
||||
.msvc => "",
|
||||
else => switch (tag) {
|
||||
.windows, .uefi => "",
|
||||
else => "lib",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn isGnuLibC(tag: Os.Tag, abi: Abi) bool {
|
||||
return tag == .linux and abi.isGnu();
|
||||
}
|
||||
|
||||
pub fn defaultVersionRange(tag: Tag, arch: Cpu.Arch) Os {
|
||||
@@ -97,6 +131,78 @@ pub const Os = struct {
|
||||
.version_range = VersionRange.default(tag, arch),
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn getVersionRangeTag(tag: Tag) @typeInfo(TaggedVersionRange).Union.tag_type.? {
|
||||
return switch (tag) {
|
||||
.freestanding,
|
||||
.ananas,
|
||||
.cloudabi,
|
||||
.fuchsia,
|
||||
.kfreebsd,
|
||||
.lv2,
|
||||
.zos,
|
||||
.haiku,
|
||||
.minix,
|
||||
.rtems,
|
||||
.nacl,
|
||||
.aix,
|
||||
.cuda,
|
||||
.nvcl,
|
||||
.amdhsa,
|
||||
.ps4,
|
||||
.ps5,
|
||||
.elfiamcu,
|
||||
.mesa3d,
|
||||
.contiki,
|
||||
.amdpal,
|
||||
.hermit,
|
||||
.hurd,
|
||||
.emscripten,
|
||||
.driverkit,
|
||||
.shadermodel,
|
||||
.liteos,
|
||||
.uefi,
|
||||
.opencl, // TODO: OpenCL versions
|
||||
.glsl450, // TODO: GLSL versions
|
||||
.vulkan,
|
||||
.plan9,
|
||||
.illumos,
|
||||
.other,
|
||||
=> .none,
|
||||
|
||||
.freebsd,
|
||||
.macos,
|
||||
.ios,
|
||||
.tvos,
|
||||
.watchos,
|
||||
.netbsd,
|
||||
.openbsd,
|
||||
.dragonfly,
|
||||
.solaris,
|
||||
.wasi,
|
||||
=> .semver,
|
||||
|
||||
.linux => .linux,
|
||||
|
||||
.windows => .windows,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn archName(tag: Tag, arch: Cpu.Arch) [:0]const u8 {
|
||||
return switch (tag) {
|
||||
.linux => switch (arch) {
|
||||
.arm, .armeb, .thumb, .thumbeb => "arm",
|
||||
.aarch64, .aarch64_be, .aarch64_32 => "aarch64",
|
||||
.mips, .mipsel, .mips64, .mips64el => "mips",
|
||||
.powerpc, .powerpcle, .powerpc64, .powerpc64le => "powerpc",
|
||||
.riscv32, .riscv64 => "riscv",
|
||||
.sparc, .sparcel, .sparc64 => "sparc",
|
||||
.x86, .x86_64 => "x86",
|
||||
else => @tagName(arch),
|
||||
},
|
||||
else => @tagName(arch),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Based on NTDDI version constants from
|
||||
@@ -142,52 +248,60 @@ pub const Os = struct {
|
||||
19042, //win10_fe aka win10_20h2
|
||||
};
|
||||
|
||||
/// Returns whether the first version `self` is newer (greater) than or equal to the second version `ver`.
|
||||
pub inline fn isAtLeast(self: WindowsVersion, ver: WindowsVersion) bool {
|
||||
return @intFromEnum(self) >= @intFromEnum(ver);
|
||||
/// Returns whether the first version `ver` is newer (greater) than or equal to the second version `ver`.
|
||||
pub inline fn isAtLeast(ver: WindowsVersion, min_ver: WindowsVersion) bool {
|
||||
return @intFromEnum(ver) >= @intFromEnum(min_ver);
|
||||
}
|
||||
|
||||
pub const Range = struct {
|
||||
min: WindowsVersion,
|
||||
max: WindowsVersion,
|
||||
|
||||
pub inline fn includesVersion(self: Range, ver: WindowsVersion) bool {
|
||||
return @intFromEnum(ver) >= @intFromEnum(self.min) and @intFromEnum(ver) <= @intFromEnum(self.max);
|
||||
pub inline fn includesVersion(range: Range, ver: WindowsVersion) bool {
|
||||
return @intFromEnum(ver) >= @intFromEnum(range.min) and
|
||||
@intFromEnum(ver) <= @intFromEnum(range.max);
|
||||
}
|
||||
|
||||
/// Checks if system is guaranteed to be at least `version` or older than `version`.
|
||||
/// Returns `null` if a runtime check is required.
|
||||
pub inline fn isAtLeast(self: Range, ver: WindowsVersion) ?bool {
|
||||
if (@intFromEnum(self.min) >= @intFromEnum(ver)) return true;
|
||||
if (@intFromEnum(self.max) < @intFromEnum(ver)) return false;
|
||||
pub inline fn isAtLeast(range: Range, min_ver: WindowsVersion) ?bool {
|
||||
if (@intFromEnum(range.min) >= @intFromEnum(min_ver)) return true;
|
||||
if (@intFromEnum(range.max) < @intFromEnum(min_ver)) return false;
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
pub fn parse(str: []const u8) !WindowsVersion {
|
||||
return std.meta.stringToEnum(WindowsVersion, str) orelse
|
||||
@enumFromInt(std.fmt.parseInt(u32, str, 0) catch
|
||||
return error.InvalidOperatingSystemVersion);
|
||||
}
|
||||
|
||||
/// This function is defined to serialize a Zig source code representation of this
|
||||
/// type, that, when parsed, will deserialize into the same data.
|
||||
pub fn format(
|
||||
self: WindowsVersion,
|
||||
comptime fmt: []const u8,
|
||||
ver: WindowsVersion,
|
||||
comptime fmt_str: []const u8,
|
||||
_: std.fmt.FormatOptions,
|
||||
out_stream: anytype,
|
||||
) !void {
|
||||
if (comptime std.mem.eql(u8, fmt, "s")) {
|
||||
if (@intFromEnum(self) >= @intFromEnum(WindowsVersion.nt4) and @intFromEnum(self) <= @intFromEnum(WindowsVersion.latest)) {
|
||||
try std.fmt.format(out_stream, ".{s}", .{@tagName(self)});
|
||||
} else {
|
||||
// TODO this code path breaks zig triples, but it is used in `builtin`
|
||||
try std.fmt.format(out_stream, "@enumFromInt(Target.Os.WindowsVersion, 0x{X:0>8})", .{@intFromEnum(self)});
|
||||
}
|
||||
} else if (fmt.len == 0) {
|
||||
if (@intFromEnum(self) >= @intFromEnum(WindowsVersion.nt4) and @intFromEnum(self) <= @intFromEnum(WindowsVersion.latest)) {
|
||||
try std.fmt.format(out_stream, "WindowsVersion.{s}", .{@tagName(self)});
|
||||
} else {
|
||||
try std.fmt.format(out_stream, "WindowsVersion(0x{X:0>8})", .{@intFromEnum(self)});
|
||||
}
|
||||
} else {
|
||||
std.fmt.invalidFmtError(fmt, self);
|
||||
}
|
||||
writer: anytype,
|
||||
) @TypeOf(writer).Error!void {
|
||||
const maybe_name = std.enums.tagName(WindowsVersion, ver);
|
||||
if (comptime std.mem.eql(u8, fmt_str, "s")) {
|
||||
if (maybe_name) |name|
|
||||
try writer.print(".{s}", .{name})
|
||||
else
|
||||
try writer.print(".{d}", .{@intFromEnum(ver)});
|
||||
} else if (comptime std.mem.eql(u8, fmt_str, "c")) {
|
||||
if (maybe_name) |name|
|
||||
try writer.print(".{s}", .{name})
|
||||
else
|
||||
try writer.print("@enumFromInt(0x{X:0>8})", .{@intFromEnum(ver)});
|
||||
} else if (fmt_str.len == 0) {
|
||||
if (maybe_name) |name|
|
||||
try writer.print("WindowsVersion.{s}", .{name})
|
||||
else
|
||||
try writer.print("WindowsVersion(0x{X:0>8})", .{@intFromEnum(ver)});
|
||||
} else std.fmt.invalidFmtError(fmt_str, ver);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -195,14 +309,14 @@ pub const Os = struct {
|
||||
range: std.SemanticVersion.Range,
|
||||
glibc: std.SemanticVersion,
|
||||
|
||||
pub inline fn includesVersion(self: LinuxVersionRange, ver: std.SemanticVersion) bool {
|
||||
return self.range.includesVersion(ver);
|
||||
pub inline fn includesVersion(range: LinuxVersionRange, ver: std.SemanticVersion) bool {
|
||||
return range.range.includesVersion(ver);
|
||||
}
|
||||
|
||||
/// Checks if system is guaranteed to be at least `version` or older than `version`.
|
||||
/// Returns `null` if a runtime check is required.
|
||||
pub inline fn isAtLeast(self: LinuxVersionRange, ver: std.SemanticVersion) ?bool {
|
||||
return self.range.isAtLeast(ver);
|
||||
pub inline fn isAtLeast(range: LinuxVersionRange, ver: std.SemanticVersion) ?bool {
|
||||
return range.range.isAtLeast(ver);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -239,7 +353,7 @@ pub const Os = struct {
|
||||
/// The default `VersionRange` represents the range that the Zig Standard Library
|
||||
/// bases its abstractions on.
|
||||
pub fn default(tag: Tag, arch: Cpu.Arch) VersionRange {
|
||||
switch (tag) {
|
||||
return switch (tag) {
|
||||
.freestanding,
|
||||
.ananas,
|
||||
.cloudabi,
|
||||
@@ -263,7 +377,6 @@ pub const Os = struct {
|
||||
.amdpal,
|
||||
.hermit,
|
||||
.hurd,
|
||||
.wasi,
|
||||
.emscripten,
|
||||
.driverkit,
|
||||
.shadermodel,
|
||||
@@ -275,15 +388,15 @@ pub const Os = struct {
|
||||
.plan9,
|
||||
.illumos,
|
||||
.other,
|
||||
=> return .{ .none = {} },
|
||||
=> .{ .none = {} },
|
||||
|
||||
.freebsd => return .{
|
||||
.freebsd => .{
|
||||
.semver = std.SemanticVersion.Range{
|
||||
.min = .{ .major = 12, .minor = 0, .patch = 0 },
|
||||
.max = .{ .major = 14, .minor = 0, .patch = 0 },
|
||||
},
|
||||
},
|
||||
.macos => return switch (arch) {
|
||||
.macos => switch (arch) {
|
||||
.aarch64 => VersionRange{
|
||||
.semver = .{
|
||||
.min = .{ .major = 11, .minor = 7, .patch = 1 },
|
||||
@@ -298,50 +411,56 @@ pub const Os = struct {
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
.ios => return .{
|
||||
.ios => .{
|
||||
.semver = .{
|
||||
.min = .{ .major = 12, .minor = 0, .patch = 0 },
|
||||
.max = .{ .major = 17, .minor = 1, .patch = 0 },
|
||||
},
|
||||
},
|
||||
.watchos => return .{
|
||||
.watchos => .{
|
||||
.semver = .{
|
||||
.min = .{ .major = 6, .minor = 0, .patch = 0 },
|
||||
.max = .{ .major = 10, .minor = 1, .patch = 0 },
|
||||
},
|
||||
},
|
||||
.tvos => return .{
|
||||
.tvos => .{
|
||||
.semver = .{
|
||||
.min = .{ .major = 13, .minor = 0, .patch = 0 },
|
||||
.max = .{ .major = 17, .minor = 1, .patch = 0 },
|
||||
},
|
||||
},
|
||||
.netbsd => return .{
|
||||
.netbsd => .{
|
||||
.semver = .{
|
||||
.min = .{ .major = 8, .minor = 0, .patch = 0 },
|
||||
.max = .{ .major = 10, .minor = 0, .patch = 0 },
|
||||
},
|
||||
},
|
||||
.openbsd => return .{
|
||||
.openbsd => .{
|
||||
.semver = .{
|
||||
.min = .{ .major = 6, .minor = 8, .patch = 0 },
|
||||
.max = .{ .major = 7, .minor = 4, .patch = 0 },
|
||||
},
|
||||
},
|
||||
.dragonfly => return .{
|
||||
.dragonfly => .{
|
||||
.semver = .{
|
||||
.min = .{ .major = 5, .minor = 8, .patch = 0 },
|
||||
.max = .{ .major = 6, .minor = 4, .patch = 0 },
|
||||
},
|
||||
},
|
||||
.solaris => return .{
|
||||
.solaris => .{
|
||||
.semver = .{
|
||||
.min = .{ .major = 5, .minor = 11, .patch = 0 },
|
||||
.max = .{ .major = 5, .minor = 11, .patch = 0 },
|
||||
},
|
||||
},
|
||||
.wasi => .{
|
||||
.semver = .{
|
||||
.min = .{ .major = 0, .minor = 1, .patch = 0 },
|
||||
.max = .{ .major = 0, .minor = 1, .patch = 0 },
|
||||
},
|
||||
},
|
||||
|
||||
.linux => return .{
|
||||
.linux => .{
|
||||
.linux = .{
|
||||
.range = .{
|
||||
.min = .{ .major = 4, .minor = 19, .patch = 0 },
|
||||
@@ -351,13 +470,13 @@ pub const Os = struct {
|
||||
},
|
||||
},
|
||||
|
||||
.windows => return .{
|
||||
.windows => .{
|
||||
.windows = .{
|
||||
.min = .win8_1,
|
||||
.max = WindowsVersion.latest,
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -370,38 +489,28 @@ pub const Os = struct {
|
||||
|
||||
/// Provides a tagged union. `Target` does not store the tag because it is
|
||||
/// redundant with the OS tag; this function abstracts that part away.
|
||||
pub inline fn getVersionRange(self: Os) TaggedVersionRange {
|
||||
switch (self.tag) {
|
||||
.linux => return TaggedVersionRange{ .linux = self.version_range.linux },
|
||||
.windows => return TaggedVersionRange{ .windows = self.version_range.windows },
|
||||
|
||||
.freebsd,
|
||||
.macos,
|
||||
.ios,
|
||||
.tvos,
|
||||
.watchos,
|
||||
.netbsd,
|
||||
.openbsd,
|
||||
.dragonfly,
|
||||
.solaris,
|
||||
=> return TaggedVersionRange{ .semver = self.version_range.semver },
|
||||
|
||||
else => return .none,
|
||||
}
|
||||
pub inline fn getVersionRange(os: Os) TaggedVersionRange {
|
||||
return switch (os.tag.getVersionRangeTag()) {
|
||||
.none => .{ .none = {} },
|
||||
.semver => .{ .semver = os.version_range.semver },
|
||||
.linux => .{ .linux = os.version_range.linux },
|
||||
.windows => .{ .windows = os.version_range.windows },
|
||||
};
|
||||
}
|
||||
|
||||
/// Checks if system is guaranteed to be at least `version` or older than `version`.
|
||||
/// Returns `null` if a runtime check is required.
|
||||
pub inline fn isAtLeast(self: Os, comptime tag: Tag, version: switch (tag) {
|
||||
else => std.SemanticVersion,
|
||||
pub inline fn isAtLeast(os: Os, comptime tag: Tag, ver: switch (tag.getVersionRangeTag()) {
|
||||
.none => void,
|
||||
.semver, .linux => std.SemanticVersion,
|
||||
.windows => WindowsVersion,
|
||||
}) ?bool {
|
||||
if (self.tag != tag) return false;
|
||||
|
||||
return switch (tag) {
|
||||
.linux => self.version_range.linux.isAtLeast(version),
|
||||
.windows => self.version_range.windows.isAtLeast(version),
|
||||
else => self.version_range.semver.isAtLeast(version),
|
||||
return if (os.tag != tag) false else switch (tag.getVersionRangeTag()) {
|
||||
.none => true,
|
||||
inline .semver,
|
||||
.linux,
|
||||
.windows,
|
||||
=> |field| @field(os.version_range, @tagName(field)).isAtLeast(ver),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -528,11 +637,8 @@ pub const Abi = enum {
|
||||
mesh,
|
||||
amplification,
|
||||
|
||||
pub fn default(arch: Cpu.Arch, target_os: Os) Abi {
|
||||
if (arch.isWasm()) {
|
||||
return .musl;
|
||||
}
|
||||
switch (target_os.tag) {
|
||||
pub fn default(arch: Cpu.Arch, os: Os) Abi {
|
||||
return if (arch.isWasm()) .musl else switch (os.tag) {
|
||||
.freestanding,
|
||||
.ananas,
|
||||
.cloudabi,
|
||||
@@ -554,7 +660,7 @@ pub const Abi = enum {
|
||||
.amdpal,
|
||||
.hermit,
|
||||
.other,
|
||||
=> return .eabi,
|
||||
=> .eabi,
|
||||
.openbsd,
|
||||
.freebsd,
|
||||
.fuchsia,
|
||||
@@ -563,12 +669,12 @@ pub const Abi = enum {
|
||||
.hurd,
|
||||
.haiku,
|
||||
.windows,
|
||||
=> return .gnu,
|
||||
.uefi => return .msvc,
|
||||
=> .gnu,
|
||||
.uefi => .msvc,
|
||||
.linux,
|
||||
.wasi,
|
||||
.emscripten,
|
||||
=> return .musl,
|
||||
=> .musl,
|
||||
.opencl, // TODO: SPIR-V ABIs with Linkage capability
|
||||
.glsl450,
|
||||
.vulkan,
|
||||
@@ -582,8 +688,8 @@ pub const Abi = enum {
|
||||
.liteos, // TODO: audit this
|
||||
.solaris,
|
||||
.illumos,
|
||||
=> return .none,
|
||||
}
|
||||
=> .none,
|
||||
};
|
||||
}
|
||||
|
||||
pub inline fn isGnu(abi: Abi) bool {
|
||||
@@ -635,7 +741,7 @@ pub const ObjectFormat = enum {
|
||||
/// Nvidia PTX format
|
||||
nvptx,
|
||||
|
||||
pub fn fileExt(of: ObjectFormat, cpu_arch: Cpu.Arch) [:0]const u8 {
|
||||
pub fn fileExt(of: ObjectFormat, arch: Cpu.Arch) [:0]const u8 {
|
||||
return switch (of) {
|
||||
.coff => ".obj",
|
||||
.elf, .macho, .wasm => ".o",
|
||||
@@ -643,18 +749,18 @@ pub const ObjectFormat = enum {
|
||||
.spirv => ".spv",
|
||||
.hex => ".ihex",
|
||||
.raw => ".bin",
|
||||
.plan9 => plan9Ext(cpu_arch),
|
||||
.plan9 => arch.plan9Ext(),
|
||||
.nvptx => ".ptx",
|
||||
.dxcontainer => ".dxil",
|
||||
};
|
||||
}
|
||||
|
||||
pub fn default(os_tag: Os.Tag, cpu_arch: Cpu.Arch) ObjectFormat {
|
||||
pub fn default(os_tag: Os.Tag, arch: Cpu.Arch) ObjectFormat {
|
||||
return switch (os_tag) {
|
||||
.windows, .uefi => .coff,
|
||||
.ios, .macos, .watchos, .tvos => .macho,
|
||||
.plan9 => .plan9,
|
||||
else => return switch (cpu_arch) {
|
||||
else => switch (arch) {
|
||||
.wasm32, .wasm64 => .wasm,
|
||||
.spirv32, .spirv64 => .spirv,
|
||||
.nvptx, .nvptx64 => .nvptx,
|
||||
@@ -725,14 +831,14 @@ pub const Cpu = struct {
|
||||
|
||||
pub fn isEnabled(set: Set, arch_feature_index: Index) bool {
|
||||
const usize_index = arch_feature_index / @bitSizeOf(usize);
|
||||
const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize)));
|
||||
const bit_index: ShiftInt = @intCast(arch_feature_index % @bitSizeOf(usize));
|
||||
return (set.ints[usize_index] & (@as(usize, 1) << bit_index)) != 0;
|
||||
}
|
||||
|
||||
/// Adds the specified feature but not its dependencies.
|
||||
pub fn addFeature(set: *Set, arch_feature_index: Index) void {
|
||||
const usize_index = arch_feature_index / @bitSizeOf(usize);
|
||||
const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize)));
|
||||
const bit_index: ShiftInt = @intCast(arch_feature_index % @bitSizeOf(usize));
|
||||
set.ints[usize_index] |= @as(usize, 1) << bit_index;
|
||||
}
|
||||
|
||||
@@ -751,7 +857,7 @@ pub const Cpu = struct {
|
||||
/// Removes the specified feature but not its dependents.
|
||||
pub fn removeFeature(set: *Set, arch_feature_index: Index) void {
|
||||
const usize_index = arch_feature_index / @bitSizeOf(usize);
|
||||
const bit_index = @as(ShiftInt, @intCast(arch_feature_index % @bitSizeOf(usize)));
|
||||
const bit_index: ShiftInt = @intCast(arch_feature_index % @bitSizeOf(usize));
|
||||
set.ints[usize_index] &= ~(@as(usize, 1) << bit_index);
|
||||
}
|
||||
|
||||
@@ -773,7 +879,7 @@ pub const Cpu = struct {
|
||||
var old = set.ints;
|
||||
while (true) {
|
||||
for (all_features_list, 0..) |feature, index_usize| {
|
||||
const index = @as(Index, @intCast(index_usize));
|
||||
const index: Index = @intCast(index_usize);
|
||||
if (set.isEnabled(index)) {
|
||||
set.addFeatureSet(feature.dependencies);
|
||||
}
|
||||
@@ -785,7 +891,7 @@ pub const Cpu = struct {
|
||||
}
|
||||
|
||||
pub fn asBytes(set: *const Set) *const [byte_count]u8 {
|
||||
return @as(*const [byte_count]u8, @ptrCast(&set.ints));
|
||||
return std.mem.sliceAsBytes(&set.ints)[0..byte_count];
|
||||
}
|
||||
|
||||
pub fn eql(set: Set, other_set: Set) bool {
|
||||
@@ -1231,7 +1337,7 @@ pub const Cpu = struct {
|
||||
}
|
||||
|
||||
/// Returns a name that matches the lib/std/target/* source file name.
|
||||
pub fn genericName(arch: Arch) []const u8 {
|
||||
pub fn genericName(arch: Arch) [:0]const u8 {
|
||||
return switch (arch) {
|
||||
.arm, .armeb, .thumb, .thumbeb => "arm",
|
||||
.aarch64, .aarch64_be, .aarch64_32 => "aarch64",
|
||||
@@ -1320,6 +1426,30 @@ pub const Cpu = struct {
|
||||
const finalized = array;
|
||||
return &finalized;
|
||||
}
|
||||
|
||||
/// 0c spim little-endian MIPS 3000 family
|
||||
/// 1c 68000 Motorola MC68000
|
||||
/// 2c 68020 Motorola MC68020
|
||||
/// 5c arm little-endian ARM
|
||||
/// 6c amd64 AMD64 and compatibles (e.g., Intel EM64T)
|
||||
/// 7c arm64 ARM64 (ARMv8)
|
||||
/// 8c 386 Intel x86, i486, Pentium, etc.
|
||||
/// kc sparc Sun SPARC
|
||||
/// qc power Power PC
|
||||
/// vc mips big-endian MIPS 3000 family
|
||||
pub fn plan9Ext(arch: Cpu.Arch) [:0]const u8 {
|
||||
return switch (arch) {
|
||||
.arm => ".5",
|
||||
.x86_64 => ".6",
|
||||
.aarch64 => ".7",
|
||||
.x86 => ".8",
|
||||
.sparc => ".k",
|
||||
.powerpc, .powerpcle => ".q",
|
||||
.mips, .mipsel => ".v",
|
||||
// ISAs without designated characters get 'X' for lack of a better option.
|
||||
else => ".X",
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const Model = struct {
|
||||
@@ -1399,112 +1529,76 @@ pub const Cpu = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub fn zigTriple(self: Target, allocator: Allocator) Allocator.Error![]u8 {
|
||||
return Query.fromTarget(self).zigTriple(allocator);
|
||||
pub fn zigTriple(target: Target, allocator: Allocator) Allocator.Error![]u8 {
|
||||
return Query.fromTarget(target).zigTriple(allocator);
|
||||
}
|
||||
|
||||
pub fn linuxTripleSimple(allocator: Allocator, cpu_arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 {
|
||||
return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ @tagName(cpu_arch), @tagName(os_tag), @tagName(abi) });
|
||||
pub fn linuxTripleSimple(allocator: Allocator, arch: Cpu.Arch, os_tag: Os.Tag, abi: Abi) ![]u8 {
|
||||
return std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ @tagName(arch), @tagName(os_tag), @tagName(abi) });
|
||||
}
|
||||
|
||||
pub fn linuxTriple(self: Target, allocator: Allocator) ![]u8 {
|
||||
return linuxTripleSimple(allocator, self.cpu.arch, self.os.tag, self.abi);
|
||||
pub fn linuxTriple(target: Target, allocator: Allocator) ![]u8 {
|
||||
return linuxTripleSimple(allocator, target.cpu.arch, target.os.tag, target.abi);
|
||||
}
|
||||
|
||||
pub fn exeFileExtSimple(cpu_arch: Cpu.Arch, os_tag: Os.Tag) [:0]const u8 {
|
||||
return switch (os_tag) {
|
||||
.windows => ".exe",
|
||||
.uefi => ".efi",
|
||||
.plan9 => plan9Ext(cpu_arch),
|
||||
else => switch (cpu_arch) {
|
||||
.wasm32, .wasm64 => ".wasm",
|
||||
else => "",
|
||||
},
|
||||
};
|
||||
pub fn exeFileExt(target: Target) [:0]const u8 {
|
||||
return target.os.tag.exeFileExt(target.cpu.arch);
|
||||
}
|
||||
|
||||
pub fn exeFileExt(self: Target) [:0]const u8 {
|
||||
return exeFileExtSimple(self.cpu.arch, self.os.tag);
|
||||
pub fn staticLibSuffix(target: Target) [:0]const u8 {
|
||||
return target.os.tag.staticLibSuffix(target.abi);
|
||||
}
|
||||
|
||||
pub fn staticLibSuffix_os_abi(os_tag: Os.Tag, abi: Abi) [:0]const u8 {
|
||||
if (abi == .msvc) {
|
||||
return ".lib";
|
||||
}
|
||||
switch (os_tag) {
|
||||
.windows, .uefi => return ".lib",
|
||||
else => return ".a",
|
||||
}
|
||||
pub fn dynamicLibSuffix(target: Target) [:0]const u8 {
|
||||
return target.os.tag.dynamicLibSuffix();
|
||||
}
|
||||
|
||||
pub fn staticLibSuffix(self: Target) [:0]const u8 {
|
||||
return staticLibSuffix_os_abi(self.os.tag, self.abi);
|
||||
pub fn libPrefix(target: Target) [:0]const u8 {
|
||||
return target.os.tag.libPrefix(target.abi);
|
||||
}
|
||||
|
||||
pub fn dynamicLibSuffix(self: Target) [:0]const u8 {
|
||||
return self.os.tag.dynamicLibSuffix();
|
||||
pub inline fn isMinGW(target: Target) bool {
|
||||
return target.os.tag == .windows and target.isGnu();
|
||||
}
|
||||
|
||||
pub fn libPrefix_os_abi(os_tag: Os.Tag, abi: Abi) [:0]const u8 {
|
||||
if (abi == .msvc) {
|
||||
return "";
|
||||
}
|
||||
switch (os_tag) {
|
||||
.windows, .uefi => return "",
|
||||
else => return "lib",
|
||||
}
|
||||
pub inline fn isGnu(target: Target) bool {
|
||||
return target.abi.isGnu();
|
||||
}
|
||||
|
||||
pub fn libPrefix(self: Target) [:0]const u8 {
|
||||
return libPrefix_os_abi(self.os.tag, self.abi);
|
||||
pub inline fn isMusl(target: Target) bool {
|
||||
return target.abi.isMusl();
|
||||
}
|
||||
|
||||
pub inline fn isMinGW(self: Target) bool {
|
||||
return self.os.tag == .windows and self.isGnu();
|
||||
pub inline fn isAndroid(target: Target) bool {
|
||||
return target.abi == .android;
|
||||
}
|
||||
|
||||
pub inline fn isGnu(self: Target) bool {
|
||||
return self.abi.isGnu();
|
||||
pub inline fn isWasm(target: Target) bool {
|
||||
return target.cpu.arch.isWasm();
|
||||
}
|
||||
|
||||
pub inline fn isMusl(self: Target) bool {
|
||||
return self.abi.isMusl();
|
||||
pub inline fn isDarwin(target: Target) bool {
|
||||
return target.os.tag.isDarwin();
|
||||
}
|
||||
|
||||
pub inline fn isAndroid(self: Target) bool {
|
||||
return self.abi == .android;
|
||||
pub inline fn isBSD(target: Target) bool {
|
||||
return target.os.tag.isBSD();
|
||||
}
|
||||
|
||||
pub inline fn isWasm(self: Target) bool {
|
||||
return self.cpu.arch.isWasm();
|
||||
pub inline fn isBpfFreestanding(target: Target) bool {
|
||||
return target.cpu.arch.isBpf() and target.os.tag == .freestanding;
|
||||
}
|
||||
|
||||
pub inline fn isDarwin(self: Target) bool {
|
||||
return self.os.tag.isDarwin();
|
||||
pub inline fn isGnuLibC(target: Target) bool {
|
||||
return target.os.tag.isGnuLibC(target.abi);
|
||||
}
|
||||
|
||||
pub inline fn isBSD(self: Target) bool {
|
||||
return self.os.tag.isBSD();
|
||||
pub inline fn supportsNewStackCall(target: Target) bool {
|
||||
return !target.cpu.arch.isWasm();
|
||||
}
|
||||
|
||||
pub inline fn isBpfFreestanding(self: Target) bool {
|
||||
return self.cpu.arch.isBpf() and self.os.tag == .freestanding;
|
||||
}
|
||||
|
||||
pub inline fn isGnuLibC_os_tag_abi(os_tag: Os.Tag, abi: Abi) bool {
|
||||
return os_tag == .linux and abi.isGnu();
|
||||
}
|
||||
|
||||
pub inline fn isGnuLibC(self: Target) bool {
|
||||
return isGnuLibC_os_tag_abi(self.os.tag, self.abi);
|
||||
}
|
||||
|
||||
pub inline fn supportsNewStackCall(self: Target) bool {
|
||||
return !self.cpu.arch.isWasm();
|
||||
}
|
||||
|
||||
pub inline fn isSpirV(self: Target) bool {
|
||||
return self.cpu.arch.isSpirV();
|
||||
pub inline fn isSpirV(target: Target) bool {
|
||||
return target.cpu.arch.isSpirV();
|
||||
}
|
||||
|
||||
pub const FloatAbi = enum {
|
||||
@@ -1512,15 +1606,15 @@ pub const FloatAbi = enum {
|
||||
soft,
|
||||
};
|
||||
|
||||
pub inline fn getFloatAbi(self: Target) FloatAbi {
|
||||
return self.abi.floatAbi();
|
||||
pub inline fn getFloatAbi(target: Target) FloatAbi {
|
||||
return target.abi.floatAbi();
|
||||
}
|
||||
|
||||
pub inline fn hasDynamicLinker(self: Target) bool {
|
||||
if (self.cpu.arch.isWasm()) {
|
||||
pub inline fn hasDynamicLinker(target: Target) bool {
|
||||
if (target.cpu.arch.isWasm()) {
|
||||
return false;
|
||||
}
|
||||
switch (self.os.tag) {
|
||||
switch (target.os.tag) {
|
||||
.freestanding,
|
||||
.ios,
|
||||
.tvos,
|
||||
@@ -1547,259 +1641,210 @@ pub const DynamicLinker = struct {
|
||||
|
||||
/// Used to construct the dynamic linker path. This field should not be used
|
||||
/// directly. See `get` and `set`.
|
||||
max_byte: ?u8,
|
||||
len: u8,
|
||||
|
||||
pub const none: DynamicLinker = .{
|
||||
.buffer = undefined,
|
||||
.max_byte = null,
|
||||
};
|
||||
pub const none: DynamicLinker = .{ .buffer = undefined, .len = 0 };
|
||||
|
||||
/// Asserts that the length is less than or equal to 255 bytes.
|
||||
pub fn init(dl_or_null: ?[]const u8) DynamicLinker {
|
||||
var result: DynamicLinker = undefined;
|
||||
result.set(dl_or_null);
|
||||
return result;
|
||||
pub fn init(maybe_path: ?[]const u8) DynamicLinker {
|
||||
var dl: DynamicLinker = undefined;
|
||||
dl.set(maybe_path);
|
||||
return dl;
|
||||
}
|
||||
|
||||
pub fn initFmt(comptime fmt_str: []const u8, args: anytype) !DynamicLinker {
|
||||
var dl: DynamicLinker = undefined;
|
||||
try dl.setFmt(fmt_str, args);
|
||||
return dl;
|
||||
}
|
||||
|
||||
/// The returned memory has the same lifetime as the `DynamicLinker`.
|
||||
pub fn get(self: *const DynamicLinker) ?[]const u8 {
|
||||
const m: usize = self.max_byte orelse return null;
|
||||
return self.buffer[0 .. m + 1];
|
||||
pub fn get(dl: *const DynamicLinker) ?[]const u8 {
|
||||
return if (dl.len > 0) dl.buffer[0..dl.len] else null;
|
||||
}
|
||||
|
||||
/// Asserts that the length is less than or equal to 255 bytes.
|
||||
pub fn set(self: *DynamicLinker, dl_or_null: ?[]const u8) void {
|
||||
if (dl_or_null) |dl| {
|
||||
@memcpy(self.buffer[0..dl.len], dl);
|
||||
self.max_byte = @intCast(dl.len - 1);
|
||||
} else {
|
||||
self.max_byte = null;
|
||||
}
|
||||
pub fn set(dl: *DynamicLinker, maybe_path: ?[]const u8) void {
|
||||
const path = maybe_path orelse "";
|
||||
@memcpy(dl.buffer[0..path.len], path);
|
||||
dl.len = @intCast(path.len);
|
||||
}
|
||||
|
||||
pub fn eql(a: DynamicLinker, b: DynamicLinker) bool {
|
||||
const a_m = a.max_byte orelse return b.max_byte == null;
|
||||
const b_m = b.max_byte orelse return false;
|
||||
if (a_m != b_m) return false;
|
||||
const a_s = a.buffer[0 .. a_m + 1];
|
||||
const b_s = b.buffer[0 .. a_m + 1];
|
||||
return std.mem.eql(u8, a_s, b_s);
|
||||
/// Asserts that the length is less than or equal to 255 bytes.
|
||||
pub fn setFmt(dl: *DynamicLinker, comptime fmt_str: []const u8, args: anytype) !void {
|
||||
dl.len = @intCast((try std.fmt.bufPrint(&dl.buffer, fmt_str, args)).len);
|
||||
}
|
||||
|
||||
pub fn eql(lhs: DynamicLinker, rhs: DynamicLinker) bool {
|
||||
return std.mem.eql(u8, lhs.buffer[0..lhs.len], rhs.buffer[0..rhs.len]);
|
||||
}
|
||||
|
||||
pub fn standard(cpu: Cpu, os_tag: Os.Tag, abi: Abi) DynamicLinker {
|
||||
return if (abi == .android) initFmt("/system/bin/linker{s}", .{
|
||||
if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else "",
|
||||
}) catch unreachable else if (abi.isMusl()) return initFmt("/lib/ld-musl-{s}{s}.so.1", .{
|
||||
@tagName(switch (cpu.arch) {
|
||||
.thumb => .arm,
|
||||
.thumbeb => .armeb,
|
||||
else => cpu.arch,
|
||||
}),
|
||||
if (cpu.arch.isArmOrThumb() and abi.floatAbi() == .hard) "hf" else "",
|
||||
}) catch unreachable else switch (os_tag) {
|
||||
.freebsd => init("/libexec/ld-elf.so.1"),
|
||||
.netbsd => init("/libexec/ld.elf_so"),
|
||||
.openbsd => init("/usr/libexec/ld.so"),
|
||||
.dragonfly => init("/libexec/ld-elf.so.2"),
|
||||
.solaris, .illumos => init("/lib/64/ld.so.1"),
|
||||
.linux => switch (cpu.arch) {
|
||||
.x86,
|
||||
.sparc,
|
||||
.sparcel,
|
||||
=> init("/lib/ld-linux.so.2"),
|
||||
|
||||
.aarch64 => init("/lib/ld-linux-aarch64.so.1"),
|
||||
.aarch64_be => init("/lib/ld-linux-aarch64_be.so.1"),
|
||||
.aarch64_32 => init("/lib/ld-linux-aarch64_32.so.1"),
|
||||
|
||||
.arm,
|
||||
.armeb,
|
||||
.thumb,
|
||||
.thumbeb,
|
||||
=> initFmt("/lib/ld-linux{s}.so.3", .{switch (abi.floatAbi()) {
|
||||
.hard => "-armhf",
|
||||
else => "",
|
||||
}}) catch unreachable,
|
||||
|
||||
.mips,
|
||||
.mipsel,
|
||||
.mips64,
|
||||
.mips64el,
|
||||
=> initFmt("/lib{s}/{s}", .{
|
||||
switch (abi) {
|
||||
.gnuabin32, .gnux32 => "32",
|
||||
.gnuabi64 => "64",
|
||||
else => "",
|
||||
},
|
||||
if (mips.featureSetHas(cpu.features, .nan2008))
|
||||
"ld-linux-mipsn8.so.1"
|
||||
else
|
||||
"ld.so.1",
|
||||
}) catch unreachable,
|
||||
|
||||
.powerpc, .powerpcle => init("/lib/ld.so.1"),
|
||||
.powerpc64, .powerpc64le => init("/lib64/ld64.so.2"),
|
||||
.s390x => init("/lib64/ld64.so.1"),
|
||||
.sparc64 => init("/lib64/ld-linux.so.2"),
|
||||
.x86_64 => init(switch (abi) {
|
||||
.gnux32 => "/libx32/ld-linux-x32.so.2",
|
||||
else => "/lib64/ld-linux-x86-64.so.2",
|
||||
}),
|
||||
|
||||
.riscv32 => init("/lib/ld-linux-riscv32-ilp32.so.1"),
|
||||
.riscv64 => init("/lib/ld-linux-riscv64-lp64.so.1"),
|
||||
|
||||
// Architectures in this list have been verified as not having a standard
|
||||
// dynamic linker path.
|
||||
.wasm32,
|
||||
.wasm64,
|
||||
.bpfel,
|
||||
.bpfeb,
|
||||
.nvptx,
|
||||
.nvptx64,
|
||||
.spu_2,
|
||||
.avr,
|
||||
.spirv32,
|
||||
.spirv64,
|
||||
=> none,
|
||||
|
||||
// TODO go over each item in this list and either move it to the above list, or
|
||||
// implement the standard dynamic linker path code for it.
|
||||
.arc,
|
||||
.csky,
|
||||
.hexagon,
|
||||
.m68k,
|
||||
.msp430,
|
||||
.r600,
|
||||
.amdgcn,
|
||||
.tce,
|
||||
.tcele,
|
||||
.xcore,
|
||||
.le32,
|
||||
.le64,
|
||||
.amdil,
|
||||
.amdil64,
|
||||
.hsail,
|
||||
.hsail64,
|
||||
.spir,
|
||||
.spir64,
|
||||
.kalimba,
|
||||
.shave,
|
||||
.lanai,
|
||||
.renderscript32,
|
||||
.renderscript64,
|
||||
.ve,
|
||||
.dxil,
|
||||
.loongarch32,
|
||||
.loongarch64,
|
||||
.xtensa,
|
||||
=> none,
|
||||
},
|
||||
|
||||
.ios,
|
||||
.tvos,
|
||||
.watchos,
|
||||
.macos,
|
||||
=> init("/usr/lib/dyld"),
|
||||
|
||||
// Operating systems in this list have been verified as not having a standard
|
||||
// dynamic linker path.
|
||||
.freestanding,
|
||||
.uefi,
|
||||
.windows,
|
||||
.emscripten,
|
||||
.wasi,
|
||||
.opencl,
|
||||
.glsl450,
|
||||
.vulkan,
|
||||
.other,
|
||||
.plan9,
|
||||
=> none,
|
||||
|
||||
// TODO revisit when multi-arch for Haiku is available
|
||||
.haiku => init("/system/runtime_loader"),
|
||||
|
||||
// TODO go over each item in this list and either move it to the above list, or
|
||||
// implement the standard dynamic linker path code for it.
|
||||
.ananas,
|
||||
.cloudabi,
|
||||
.fuchsia,
|
||||
.kfreebsd,
|
||||
.lv2,
|
||||
.zos,
|
||||
.minix,
|
||||
.rtems,
|
||||
.nacl,
|
||||
.aix,
|
||||
.cuda,
|
||||
.nvcl,
|
||||
.amdhsa,
|
||||
.ps4,
|
||||
.ps5,
|
||||
.elfiamcu,
|
||||
.mesa3d,
|
||||
.contiki,
|
||||
.amdpal,
|
||||
.hermit,
|
||||
.hurd,
|
||||
.driverkit,
|
||||
.shadermodel,
|
||||
.liteos,
|
||||
=> none,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {
|
||||
return standardDynamicLinkerPath_cpu_os_abi(target.cpu, target.os.tag, target.abi);
|
||||
}
|
||||
|
||||
pub fn standardDynamicLinkerPath_cpu_os_abi(cpu: Cpu, os_tag: Os.Tag, abi: Abi) DynamicLinker {
|
||||
var result = DynamicLinker.none;
|
||||
const S = struct {
|
||||
fn print(r: *DynamicLinker, comptime fmt: []const u8, args: anytype) DynamicLinker {
|
||||
r.max_byte = @as(u8, @intCast((std.fmt.bufPrint(&r.buffer, fmt, args) catch unreachable).len - 1));
|
||||
return r.*;
|
||||
}
|
||||
fn copy(r: *DynamicLinker, s: []const u8) DynamicLinker {
|
||||
@memcpy(r.buffer[0..s.len], s);
|
||||
r.max_byte = @as(u8, @intCast(s.len - 1));
|
||||
return r.*;
|
||||
}
|
||||
};
|
||||
const print = S.print;
|
||||
const copy = S.copy;
|
||||
|
||||
if (abi == .android) {
|
||||
const suffix = if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else "";
|
||||
return print(&result, "/system/bin/linker{s}", .{suffix});
|
||||
}
|
||||
|
||||
if (abi.isMusl()) {
|
||||
const is_arm = switch (cpu.arch) {
|
||||
.arm, .armeb, .thumb, .thumbeb => true,
|
||||
else => false,
|
||||
};
|
||||
const arch_part = switch (cpu.arch) {
|
||||
.arm, .thumb => "arm",
|
||||
.armeb, .thumbeb => "armeb",
|
||||
else => |arch| @tagName(arch),
|
||||
};
|
||||
const arch_suffix = if (is_arm and abi.floatAbi() == .hard) "hf" else "";
|
||||
return print(&result, "/lib/ld-musl-{s}{s}.so.1", .{ arch_part, arch_suffix });
|
||||
}
|
||||
|
||||
switch (os_tag) {
|
||||
.freebsd => return copy(&result, "/libexec/ld-elf.so.1"),
|
||||
.netbsd => return copy(&result, "/libexec/ld.elf_so"),
|
||||
.openbsd => return copy(&result, "/usr/libexec/ld.so"),
|
||||
.dragonfly => return copy(&result, "/libexec/ld-elf.so.2"),
|
||||
.solaris, .illumos => return copy(&result, "/lib/64/ld.so.1"),
|
||||
.linux => switch (cpu.arch) {
|
||||
.x86,
|
||||
.sparc,
|
||||
.sparcel,
|
||||
=> return copy(&result, "/lib/ld-linux.so.2"),
|
||||
|
||||
.aarch64 => return copy(&result, "/lib/ld-linux-aarch64.so.1"),
|
||||
.aarch64_be => return copy(&result, "/lib/ld-linux-aarch64_be.so.1"),
|
||||
.aarch64_32 => return copy(&result, "/lib/ld-linux-aarch64_32.so.1"),
|
||||
|
||||
.arm,
|
||||
.armeb,
|
||||
.thumb,
|
||||
.thumbeb,
|
||||
=> return copy(&result, switch (abi.floatAbi()) {
|
||||
.hard => "/lib/ld-linux-armhf.so.3",
|
||||
else => "/lib/ld-linux.so.3",
|
||||
}),
|
||||
|
||||
.mips,
|
||||
.mipsel,
|
||||
.mips64,
|
||||
.mips64el,
|
||||
=> {
|
||||
const lib_suffix = switch (abi) {
|
||||
.gnuabin32, .gnux32 => "32",
|
||||
.gnuabi64 => "64",
|
||||
else => "",
|
||||
};
|
||||
const is_nan_2008 = mips.featureSetHas(cpu.features, .nan2008);
|
||||
const loader = if (is_nan_2008) "ld-linux-mipsn8.so.1" else "ld.so.1";
|
||||
return print(&result, "/lib{s}/{s}", .{ lib_suffix, loader });
|
||||
},
|
||||
|
||||
.powerpc, .powerpcle => return copy(&result, "/lib/ld.so.1"),
|
||||
.powerpc64, .powerpc64le => return copy(&result, "/lib64/ld64.so.2"),
|
||||
.s390x => return copy(&result, "/lib64/ld64.so.1"),
|
||||
.sparc64 => return copy(&result, "/lib64/ld-linux.so.2"),
|
||||
.x86_64 => return copy(&result, switch (abi) {
|
||||
.gnux32 => "/libx32/ld-linux-x32.so.2",
|
||||
else => "/lib64/ld-linux-x86-64.so.2",
|
||||
}),
|
||||
|
||||
.riscv32 => return copy(&result, "/lib/ld-linux-riscv32-ilp32.so.1"),
|
||||
.riscv64 => return copy(&result, "/lib/ld-linux-riscv64-lp64.so.1"),
|
||||
|
||||
// Architectures in this list have been verified as not having a standard
|
||||
// dynamic linker path.
|
||||
.wasm32,
|
||||
.wasm64,
|
||||
.bpfel,
|
||||
.bpfeb,
|
||||
.nvptx,
|
||||
.nvptx64,
|
||||
.spu_2,
|
||||
.avr,
|
||||
.spirv32,
|
||||
.spirv64,
|
||||
=> return result,
|
||||
|
||||
// TODO go over each item in this list and either move it to the above list, or
|
||||
// implement the standard dynamic linker path code for it.
|
||||
.arc,
|
||||
.csky,
|
||||
.hexagon,
|
||||
.m68k,
|
||||
.msp430,
|
||||
.r600,
|
||||
.amdgcn,
|
||||
.tce,
|
||||
.tcele,
|
||||
.xcore,
|
||||
.le32,
|
||||
.le64,
|
||||
.amdil,
|
||||
.amdil64,
|
||||
.hsail,
|
||||
.hsail64,
|
||||
.spir,
|
||||
.spir64,
|
||||
.kalimba,
|
||||
.shave,
|
||||
.lanai,
|
||||
.renderscript32,
|
||||
.renderscript64,
|
||||
.ve,
|
||||
.dxil,
|
||||
.loongarch32,
|
||||
.loongarch64,
|
||||
.xtensa,
|
||||
=> return result,
|
||||
},
|
||||
|
||||
.ios,
|
||||
.tvos,
|
||||
.watchos,
|
||||
.macos,
|
||||
=> return copy(&result, "/usr/lib/dyld"),
|
||||
|
||||
// Operating systems in this list have been verified as not having a standard
|
||||
// dynamic linker path.
|
||||
.freestanding,
|
||||
.uefi,
|
||||
.windows,
|
||||
.emscripten,
|
||||
.wasi,
|
||||
.opencl,
|
||||
.glsl450,
|
||||
.vulkan,
|
||||
.other,
|
||||
.plan9,
|
||||
=> return result,
|
||||
|
||||
// TODO revisit when multi-arch for Haiku is available
|
||||
.haiku => return copy(&result, "/system/runtime_loader"),
|
||||
|
||||
// TODO go over each item in this list and either move it to the above list, or
|
||||
// implement the standard dynamic linker path code for it.
|
||||
.ananas,
|
||||
.cloudabi,
|
||||
.fuchsia,
|
||||
.kfreebsd,
|
||||
.lv2,
|
||||
.zos,
|
||||
.minix,
|
||||
.rtems,
|
||||
.nacl,
|
||||
.aix,
|
||||
.cuda,
|
||||
.nvcl,
|
||||
.amdhsa,
|
||||
.ps4,
|
||||
.ps5,
|
||||
.elfiamcu,
|
||||
.mesa3d,
|
||||
.contiki,
|
||||
.amdpal,
|
||||
.hermit,
|
||||
.hurd,
|
||||
.driverkit,
|
||||
.shadermodel,
|
||||
.liteos,
|
||||
=> return result,
|
||||
}
|
||||
}
|
||||
|
||||
/// 0c spim little-endian MIPS 3000 family
|
||||
/// 1c 68000 Motorola MC68000
|
||||
/// 2c 68020 Motorola MC68020
|
||||
/// 5c arm little-endian ARM
|
||||
/// 6c amd64 AMD64 and compatibles (e.g., Intel EM64T)
|
||||
/// 7c arm64 ARM64 (ARMv8)
|
||||
/// 8c 386 Intel x86, i486, Pentium, etc.
|
||||
/// kc sparc Sun SPARC
|
||||
/// qc power Power PC
|
||||
/// vc mips big-endian MIPS 3000 family
|
||||
pub fn plan9Ext(cpu_arch: Cpu.Arch) [:0]const u8 {
|
||||
return switch (cpu_arch) {
|
||||
.arm => ".5",
|
||||
.x86_64 => ".6",
|
||||
.aarch64 => ".7",
|
||||
.x86 => ".8",
|
||||
.sparc => ".k",
|
||||
.powerpc, .powerpcle => ".q",
|
||||
.mips, .mipsel => ".v",
|
||||
// ISAs without designated characters get 'X' for lack of a better option.
|
||||
else => ".X",
|
||||
};
|
||||
return DynamicLinker.standard(target.cpu, target.os.tag, target.abi);
|
||||
}
|
||||
|
||||
pub fn maxIntAlignment(target: Target) u16 {
|
||||
@@ -2076,7 +2121,7 @@ pub fn c_type_byte_size(t: Target, c_type: CType) u16 {
|
||||
16 => 2,
|
||||
32 => 4,
|
||||
64 => 8,
|
||||
80 => @as(u16, @intCast(std.mem.alignForward(usize, 10, c_type_alignment(t, .longdouble)))),
|
||||
80 => @intCast(std.mem.alignForward(usize, 10, c_type_alignment(t, .longdouble))),
|
||||
128 => 16,
|
||||
else => unreachable,
|
||||
},
|
||||
@@ -2419,7 +2464,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
|
||||
// Next-power-of-two-aligned, up to a maximum.
|
||||
return @min(
|
||||
std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),
|
||||
switch (target.cpu.arch) {
|
||||
@as(u16, switch (target.cpu.arch) {
|
||||
.arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {
|
||||
.netbsd => switch (target.abi) {
|
||||
.gnueabi,
|
||||
@@ -2431,7 +2476,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
|
||||
.musleabihf,
|
||||
=> 8,
|
||||
|
||||
else => @as(u16, 4),
|
||||
else => 4,
|
||||
},
|
||||
.ios, .tvos, .watchos => 4,
|
||||
else => 8,
|
||||
@@ -2501,7 +2546,7 @@ pub fn c_type_alignment(target: Target, c_type: CType) u16 {
|
||||
.wasm32,
|
||||
.wasm64,
|
||||
=> 16,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2559,8 +2604,8 @@ pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {
|
||||
// Next-power-of-two-aligned, up to a maximum.
|
||||
return @min(
|
||||
std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),
|
||||
switch (target.cpu.arch) {
|
||||
.msp430 => @as(u16, 2),
|
||||
@as(u16, switch (target.cpu.arch) {
|
||||
.msp430 => 2,
|
||||
|
||||
.csky,
|
||||
.xcore,
|
||||
@@ -2627,7 +2672,7 @@ pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {
|
||||
.wasm32,
|
||||
.wasm64,
|
||||
=> 16,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2767,19 +2812,7 @@ fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool {
|
||||
}
|
||||
|
||||
pub fn osArchName(target: std.Target) [:0]const u8 {
|
||||
return switch (target.os.tag) {
|
||||
.linux => switch (target.cpu.arch) {
|
||||
.arm, .armeb, .thumb, .thumbeb => "arm",
|
||||
.aarch64, .aarch64_be, .aarch64_32 => "aarch64",
|
||||
.mips, .mipsel, .mips64, .mips64el => "mips",
|
||||
.powerpc, .powerpcle, .powerpc64, .powerpc64le => "powerpc",
|
||||
.riscv32, .riscv64 => "riscv",
|
||||
.sparc, .sparcel, .sparc64 => "sparc",
|
||||
.x86, .x86_64 => "x86",
|
||||
else => @tagName(target.cpu.arch),
|
||||
},
|
||||
else => @tagName(target.cpu.arch),
|
||||
};
|
||||
return target.os.tag.archName(target.cpu.arch);
|
||||
}
|
||||
|
||||
const Target = @This();
|
||||
|
||||
+35
-139
@@ -124,71 +124,21 @@ pub fn fromTarget(target: Target) Query {
|
||||
}
|
||||
|
||||
fn updateOsVersionRange(self: *Query, os: Target.Os) void {
|
||||
switch (os.tag) {
|
||||
.freestanding,
|
||||
.ananas,
|
||||
.cloudabi,
|
||||
.fuchsia,
|
||||
.kfreebsd,
|
||||
.lv2,
|
||||
.solaris,
|
||||
.illumos,
|
||||
.zos,
|
||||
.haiku,
|
||||
.minix,
|
||||
.rtems,
|
||||
.nacl,
|
||||
.aix,
|
||||
.cuda,
|
||||
.nvcl,
|
||||
.amdhsa,
|
||||
.ps4,
|
||||
.ps5,
|
||||
.elfiamcu,
|
||||
.mesa3d,
|
||||
.contiki,
|
||||
.amdpal,
|
||||
.hermit,
|
||||
.hurd,
|
||||
.wasi,
|
||||
.emscripten,
|
||||
.driverkit,
|
||||
.shadermodel,
|
||||
.liteos,
|
||||
.uefi,
|
||||
.opencl,
|
||||
.glsl450,
|
||||
.vulkan,
|
||||
.plan9,
|
||||
.other,
|
||||
=> {
|
||||
self.os_version_min = .{ .none = {} };
|
||||
self.os_version_max = .{ .none = {} };
|
||||
self.os_version_min, self.os_version_max = switch (os.tag.getVersionRangeTag()) {
|
||||
.none => .{ .{ .none = {} }, .{ .none = {} } },
|
||||
.semver => .{
|
||||
.{ .semver = os.version_range.semver.min },
|
||||
.{ .semver = os.version_range.semver.max },
|
||||
},
|
||||
|
||||
.freebsd,
|
||||
.macos,
|
||||
.ios,
|
||||
.tvos,
|
||||
.watchos,
|
||||
.netbsd,
|
||||
.openbsd,
|
||||
.dragonfly,
|
||||
=> {
|
||||
self.os_version_min = .{ .semver = os.version_range.semver.min };
|
||||
self.os_version_max = .{ .semver = os.version_range.semver.max };
|
||||
.linux => .{
|
||||
.{ .semver = os.version_range.linux.range.min },
|
||||
.{ .semver = os.version_range.linux.range.max },
|
||||
},
|
||||
|
||||
.linux => {
|
||||
self.os_version_min = .{ .semver = os.version_range.linux.range.min };
|
||||
self.os_version_max = .{ .semver = os.version_range.linux.range.max };
|
||||
.windows => .{
|
||||
.{ .windows = os.version_range.windows.min },
|
||||
.{ .windows = os.version_range.windows.max },
|
||||
},
|
||||
|
||||
.windows => {
|
||||
self.os_version_min = .{ .windows = os.version_range.windows.min };
|
||||
self.os_version_max = .{ .windows = os.version_range.windows.max };
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub const ParseOptions = struct {
|
||||
@@ -278,7 +228,8 @@ pub fn parse(args: ParseOptions) !Query {
|
||||
|
||||
const abi_ver_text = abi_it.rest();
|
||||
if (abi_it.next() != null) {
|
||||
if (Target.isGnuLibC_os_tag_abi(result.os_tag orelse builtin.os.tag, abi)) {
|
||||
const tag = result.os_tag orelse builtin.os.tag;
|
||||
if (tag.isGnuLibC(abi)) {
|
||||
result.glibc_version = parseVersion(abi_ver_text) catch |err| switch (err) {
|
||||
error.Overflow => return error.InvalidAbiVersion,
|
||||
error.InvalidVersion => return error.InvalidAbiVersion,
|
||||
@@ -567,88 +518,33 @@ fn parseOs(result: *Query, diags: *ParseOptions.Diagnostics, text: []const u8) !
|
||||
diags.os_tag = tag;
|
||||
|
||||
const version_text = it.rest();
|
||||
if (it.next() == null) return;
|
||||
|
||||
switch (tag) {
|
||||
.freestanding,
|
||||
.ananas,
|
||||
.cloudabi,
|
||||
.fuchsia,
|
||||
.kfreebsd,
|
||||
.lv2,
|
||||
.solaris,
|
||||
.illumos,
|
||||
.zos,
|
||||
.haiku,
|
||||
.minix,
|
||||
.rtems,
|
||||
.nacl,
|
||||
.aix,
|
||||
.cuda,
|
||||
.nvcl,
|
||||
.amdhsa,
|
||||
.ps4,
|
||||
.ps5,
|
||||
.elfiamcu,
|
||||
.mesa3d,
|
||||
.contiki,
|
||||
.amdpal,
|
||||
.hermit,
|
||||
.hurd,
|
||||
.wasi,
|
||||
.emscripten,
|
||||
.uefi,
|
||||
.opencl,
|
||||
.glsl450,
|
||||
.vulkan,
|
||||
.plan9,
|
||||
.driverkit,
|
||||
.shadermodel,
|
||||
.liteos,
|
||||
.other,
|
||||
=> return error.InvalidOperatingSystemVersion,
|
||||
|
||||
.freebsd,
|
||||
.macos,
|
||||
.ios,
|
||||
.tvos,
|
||||
.watchos,
|
||||
.netbsd,
|
||||
.openbsd,
|
||||
.linux,
|
||||
.dragonfly,
|
||||
=> {
|
||||
if (version_text.len > 0) switch (tag.getVersionRangeTag()) {
|
||||
.none => return error.InvalidOperatingSystemVersion,
|
||||
.semver, .linux => range: {
|
||||
var range_it = mem.splitSequence(u8, version_text, "...");
|
||||
|
||||
const min_text = range_it.next().?;
|
||||
const min_ver = parseVersion(min_text) catch |err| switch (err) {
|
||||
error.Overflow => return error.InvalidOperatingSystemVersion,
|
||||
error.InvalidVersion => return error.InvalidOperatingSystemVersion,
|
||||
result.os_version_min = .{
|
||||
.semver = parseVersion(range_it.first()) catch |err| switch (err) {
|
||||
error.Overflow => return error.InvalidOperatingSystemVersion,
|
||||
error.InvalidVersion => return error.InvalidOperatingSystemVersion,
|
||||
},
|
||||
};
|
||||
result.os_version_min = .{ .semver = min_ver };
|
||||
|
||||
const max_text = range_it.next() orelse return;
|
||||
const max_ver = parseVersion(max_text) catch |err| switch (err) {
|
||||
error.Overflow => return error.InvalidOperatingSystemVersion,
|
||||
error.InvalidVersion => return error.InvalidOperatingSystemVersion,
|
||||
result.os_version_max = .{
|
||||
.semver = parseVersion(range_it.next() orelse break :range) catch |err| switch (err) {
|
||||
error.Overflow => return error.InvalidOperatingSystemVersion,
|
||||
error.InvalidVersion => return error.InvalidOperatingSystemVersion,
|
||||
},
|
||||
};
|
||||
result.os_version_max = .{ .semver = max_ver };
|
||||
},
|
||||
|
||||
.windows => {
|
||||
.windows => range: {
|
||||
var range_it = mem.splitSequence(u8, version_text, "...");
|
||||
|
||||
const min_text = range_it.first();
|
||||
const min_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, min_text) orelse
|
||||
return error.InvalidOperatingSystemVersion;
|
||||
result.os_version_min = .{ .windows = min_ver };
|
||||
|
||||
const max_text = range_it.next() orelse return;
|
||||
const max_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, max_text) orelse
|
||||
return error.InvalidOperatingSystemVersion;
|
||||
result.os_version_max = .{ .windows = max_ver };
|
||||
result.os_version_min = .{
|
||||
.windows = try Target.Os.WindowsVersion.parse(range_it.first()),
|
||||
};
|
||||
result.os_version_max = .{
|
||||
.windows = try Target.Os.WindowsVersion.parse(range_it.next() orelse break :range),
|
||||
};
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn eql(a: Query, b: Query) bool {
|
||||
|
||||
+22
-22
@@ -430,9 +430,9 @@ pub fn abiAndDynamicLinkerFromFile(
|
||||
query: Target.Query,
|
||||
) AbiAndDynamicLinkerFromFileError!Target {
|
||||
var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;
|
||||
_ = try preadMin(file, &hdr_buf, 0, hdr_buf.len);
|
||||
const hdr32 = @as(*elf.Elf32_Ehdr, @ptrCast(&hdr_buf));
|
||||
const hdr64 = @as(*elf.Elf64_Ehdr, @ptrCast(&hdr_buf));
|
||||
_ = try preadAtLeast(file, &hdr_buf, 0, hdr_buf.len);
|
||||
const hdr32: *elf.Elf32_Ehdr = @ptrCast(&hdr_buf);
|
||||
const hdr64: *elf.Elf64_Ehdr = @ptrCast(&hdr_buf);
|
||||
if (!mem.eql(u8, hdr32.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic;
|
||||
const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) {
|
||||
elf.ELFDATA2LSB => .little,
|
||||
@@ -469,7 +469,7 @@ pub fn abiAndDynamicLinkerFromFile(
|
||||
// Reserve some bytes so that we can deref the 64-bit struct fields
|
||||
// even when the ELF file is 32-bits.
|
||||
const ph_reserve: usize = @sizeOf(elf.Elf64_Phdr) - @sizeOf(elf.Elf32_Phdr);
|
||||
const ph_read_byte_len = try preadMin(file, ph_buf[0 .. ph_buf.len - ph_reserve], phoff, phentsize);
|
||||
const ph_read_byte_len = try preadAtLeast(file, ph_buf[0 .. ph_buf.len - ph_reserve], phoff, phentsize);
|
||||
var ph_buf_i: usize = 0;
|
||||
while (ph_buf_i < ph_read_byte_len and ph_i < phnum) : ({
|
||||
ph_i += 1;
|
||||
@@ -484,13 +484,13 @@ pub fn abiAndDynamicLinkerFromFile(
|
||||
const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
|
||||
const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
|
||||
if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;
|
||||
const filesz = @as(usize, @intCast(p_filesz));
|
||||
_ = try preadMin(file, result.dynamic_linker.buffer[0..filesz], p_offset, filesz);
|
||||
const filesz: usize = @intCast(p_filesz);
|
||||
_ = try preadAtLeast(file, result.dynamic_linker.buffer[0..filesz], p_offset, filesz);
|
||||
// PT_INTERP includes a null byte in filesz.
|
||||
const len = filesz - 1;
|
||||
// dynamic_linker.max_byte is "max", not "len".
|
||||
// We know it will fit in u8 because we check against dynamic_linker.buffer.len above.
|
||||
result.dynamic_linker.max_byte = @as(u8, @intCast(len - 1));
|
||||
result.dynamic_linker.len = @intCast(len);
|
||||
|
||||
// Use it to determine ABI.
|
||||
const full_ld_path = result.dynamic_linker.buffer[0..len];
|
||||
@@ -516,7 +516,7 @@ pub fn abiAndDynamicLinkerFromFile(
|
||||
// Reserve some bytes so that we can deref the 64-bit struct fields
|
||||
// even when the ELF file is 32-bits.
|
||||
const dyn_reserve: usize = @sizeOf(elf.Elf64_Dyn) - @sizeOf(elf.Elf32_Dyn);
|
||||
const dyn_read_byte_len = try preadMin(
|
||||
const dyn_read_byte_len = try preadAtLeast(
|
||||
file,
|
||||
dyn_buf[0 .. dyn_buf.len - dyn_reserve],
|
||||
dyn_off,
|
||||
@@ -556,14 +556,14 @@ pub fn abiAndDynamicLinkerFromFile(
|
||||
var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined;
|
||||
if (sh_buf.len < shentsize) return error.InvalidElfFile;
|
||||
|
||||
_ = try preadMin(file, &sh_buf, str_section_off, shentsize);
|
||||
_ = try preadAtLeast(file, &sh_buf, str_section_off, shentsize);
|
||||
const shstr32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf));
|
||||
const shstr64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf));
|
||||
const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset);
|
||||
const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);
|
||||
var strtab_buf: [4096:0]u8 = undefined;
|
||||
const shstrtab_len = @min(shstrtab_size, strtab_buf.len);
|
||||
const shstrtab_read_len = try preadMin(file, &strtab_buf, shstrtab_off, shstrtab_len);
|
||||
const shstrtab_read_len = try preadAtLeast(file, &strtab_buf, shstrtab_off, shstrtab_len);
|
||||
const shstrtab = strtab_buf[0..shstrtab_read_len];
|
||||
|
||||
const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum);
|
||||
@@ -572,7 +572,7 @@ pub fn abiAndDynamicLinkerFromFile(
|
||||
// Reserve some bytes so that we can deref the 64-bit struct fields
|
||||
// even when the ELF file is 32-bits.
|
||||
const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr);
|
||||
const sh_read_byte_len = try preadMin(
|
||||
const sh_read_byte_len = try preadAtLeast(
|
||||
file,
|
||||
sh_buf[0 .. sh_buf.len - sh_reserve],
|
||||
shoff,
|
||||
@@ -604,7 +604,7 @@ pub fn abiAndDynamicLinkerFromFile(
|
||||
const rp_max_size = ds.size - rpoff;
|
||||
|
||||
const strtab_len = @min(rp_max_size, strtab_buf.len);
|
||||
const strtab_read_len = try preadMin(file, &strtab_buf, rpoff_file, strtab_len);
|
||||
const strtab_read_len = try preadAtLeast(file, &strtab_buf, rpoff_file, strtab_len);
|
||||
const strtab = strtab_buf[0..strtab_read_len];
|
||||
|
||||
const rpath_list = mem.sliceTo(strtab, 0);
|
||||
@@ -814,9 +814,9 @@ fn glibcVerFromRPath(rpath: []const u8) !std.SemanticVersion {
|
||||
|
||||
fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
|
||||
var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;
|
||||
_ = try preadMin(file, &hdr_buf, 0, hdr_buf.len);
|
||||
const hdr32 = @as(*elf.Elf32_Ehdr, @ptrCast(&hdr_buf));
|
||||
const hdr64 = @as(*elf.Elf64_Ehdr, @ptrCast(&hdr_buf));
|
||||
_ = try preadAtLeast(file, &hdr_buf, 0, hdr_buf.len);
|
||||
const hdr32: *elf.Elf32_Ehdr = @ptrCast(&hdr_buf);
|
||||
const hdr64: *elf.Elf64_Ehdr = @ptrCast(&hdr_buf);
|
||||
if (!mem.eql(u8, hdr32.e_ident[0..4], elf.MAGIC)) return error.InvalidElfMagic;
|
||||
const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) {
|
||||
elf.ELFDATA2LSB => .little,
|
||||
@@ -838,14 +838,14 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
|
||||
var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined;
|
||||
if (sh_buf.len < shentsize) return error.InvalidElfFile;
|
||||
|
||||
_ = try preadMin(file, &sh_buf, str_section_off, shentsize);
|
||||
_ = try preadAtLeast(file, &sh_buf, str_section_off, shentsize);
|
||||
const shstr32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf));
|
||||
const shstr64: *elf.Elf64_Shdr = @ptrCast(@alignCast(&sh_buf));
|
||||
const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset);
|
||||
const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);
|
||||
var strtab_buf: [4096:0]u8 = undefined;
|
||||
const shstrtab_len = @min(shstrtab_size, strtab_buf.len);
|
||||
const shstrtab_read_len = try preadMin(file, &strtab_buf, shstrtab_off, shstrtab_len);
|
||||
const shstrtab_read_len = try preadAtLeast(file, &strtab_buf, shstrtab_off, shstrtab_len);
|
||||
const shstrtab = strtab_buf[0..shstrtab_read_len];
|
||||
const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum);
|
||||
var sh_i: u16 = 0;
|
||||
@@ -853,7 +853,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
|
||||
// Reserve some bytes so that we can deref the 64-bit struct fields
|
||||
// even when the ELF file is 32-bits.
|
||||
const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr);
|
||||
const sh_read_byte_len = try preadMin(
|
||||
const sh_read_byte_len = try preadAtLeast(
|
||||
file,
|
||||
sh_buf[0 .. sh_buf.len - sh_reserve],
|
||||
shoff,
|
||||
@@ -890,7 +890,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
|
||||
|
||||
const dynstr_size: usize = @intCast(dynstr.size);
|
||||
const dynstr_bytes = buf[0..dynstr_size];
|
||||
_ = try preadMin(file, dynstr_bytes, dynstr.offset, dynstr_bytes.len);
|
||||
_ = try preadAtLeast(file, dynstr_bytes, dynstr.offset, dynstr_bytes.len);
|
||||
var it = mem.splitScalar(u8, dynstr_bytes, 0);
|
||||
var max_ver: std.SemanticVersion = .{ .major = 2, .minor = 2, .patch = 5 };
|
||||
while (it.next()) |s| {
|
||||
@@ -1029,7 +1029,7 @@ fn detectAbiAndDynamicLinker(
|
||||
};
|
||||
errdefer file.close();
|
||||
|
||||
const len = preadMin(file, &buffer, 0, buffer.len) catch |err| switch (err) {
|
||||
const len = preadAtLeast(file, &buffer, 0, buffer.len) catch |err| switch (err) {
|
||||
error.UnexpectedEndOfFile,
|
||||
error.UnableToReadElfFile,
|
||||
=> break :blk file,
|
||||
@@ -1083,7 +1083,7 @@ fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Quer
|
||||
.abi = abi,
|
||||
.ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),
|
||||
.dynamic_linker = if (query.dynamic_linker.get() == null)
|
||||
Target.standardDynamicLinkerPath_cpu_os_abi(cpu, os.tag, abi)
|
||||
Target.DynamicLinker.standard(cpu, os.tag, abi)
|
||||
else
|
||||
query.dynamic_linker,
|
||||
};
|
||||
@@ -1094,7 +1094,7 @@ const LdInfo = struct {
|
||||
abi: Target.Abi,
|
||||
};
|
||||
|
||||
fn preadMin(file: fs.File, buf: []u8, offset: u64, min_read_len: usize) !usize {
|
||||
fn preadAtLeast(file: fs.File, buf: []u8, offset: u64, min_read_len: usize) !usize {
|
||||
var i: usize = 0;
|
||||
while (i < min_read_len) {
|
||||
const len = file.pread(buf[i..], offset + i) catch |err| switch (err) {
|
||||
|
||||
+3
-5
@@ -140,13 +140,11 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
|
||||
}),
|
||||
.windows => |windows| try buffer.writer().print(
|
||||
\\ .windows = .{{
|
||||
\\ .min = {s},
|
||||
\\ .max = {s},
|
||||
\\ .min = {c},
|
||||
\\ .max = {c},
|
||||
\\ }}}},
|
||||
\\
|
||||
,
|
||||
.{ windows.min, windows.max },
|
||||
),
|
||||
, .{ windows.min, windows.max }),
|
||||
}
|
||||
try buffer.appendSlice(
|
||||
\\};
|
||||
|
||||
Reference in New Issue
Block a user