Merge pull request #19654 from jacobly0/wasi-ver

Target: add wasi os version
This commit is contained in:
Andrew Kelley 2024-04-15 16:14:22 -07:00 committed by GitHub
commit a2b834e8c7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 529 additions and 602 deletions

File diff suppressed because it is too large Load Diff

View File

@ -124,71 +124,21 @@ pub fn fromTarget(target: Target) Query {
} }
fn updateOsVersionRange(self: *Query, os: Target.Os) void { fn updateOsVersionRange(self: *Query, os: Target.Os) void {
switch (os.tag) { self.os_version_min, self.os_version_max = switch (os.tag.getVersionRangeTag()) {
.freestanding, .none => .{ .{ .none = {} }, .{ .none = {} } },
.ananas, .semver => .{
.cloudabi, .{ .semver = os.version_range.semver.min },
.fuchsia, .{ .semver = os.version_range.semver.max },
.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 = {} };
}, },
.linux => .{
.freebsd, .{ .semver = os.version_range.linux.range.min },
.macos, .{ .semver = os.version_range.linux.range.max },
.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 };
}, },
.windows => .{
.linux => { .{ .windows = os.version_range.windows.min },
self.os_version_min = .{ .semver = os.version_range.linux.range.min }; .{ .windows = os.version_range.windows.max },
self.os_version_max = .{ .semver = os.version_range.linux.range.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 { pub const ParseOptions = struct {
@ -278,7 +228,8 @@ pub fn parse(args: ParseOptions) !Query {
const abi_ver_text = abi_it.rest(); const abi_ver_text = abi_it.rest();
if (abi_it.next() != null) { 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) { result.glibc_version = parseVersion(abi_ver_text) catch |err| switch (err) {
error.Overflow => return error.InvalidAbiVersion, error.Overflow => return error.InvalidAbiVersion,
error.InvalidVersion => 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; diags.os_tag = tag;
const version_text = it.rest(); const version_text = it.rest();
if (it.next() == null) return; if (version_text.len > 0) switch (tag.getVersionRangeTag()) {
.none => return error.InvalidOperatingSystemVersion,
switch (tag) { .semver, .linux => range: {
.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,
=> {
var range_it = mem.splitSequence(u8, version_text, "..."); var range_it = mem.splitSequence(u8, version_text, "...");
result.os_version_min = .{
const min_text = range_it.next().?; .semver = parseVersion(range_it.first()) catch |err| switch (err) {
const min_ver = parseVersion(min_text) catch |err| switch (err) { error.Overflow => return error.InvalidOperatingSystemVersion,
error.Overflow => return error.InvalidOperatingSystemVersion, error.InvalidVersion => return error.InvalidOperatingSystemVersion,
error.InvalidVersion => return error.InvalidOperatingSystemVersion, },
}; };
result.os_version_min = .{ .semver = min_ver }; result.os_version_max = .{
.semver = parseVersion(range_it.next() orelse break :range) catch |err| switch (err) {
const max_text = range_it.next() orelse return; error.Overflow => return error.InvalidOperatingSystemVersion,
const max_ver = parseVersion(max_text) catch |err| switch (err) { error.InvalidVersion => return error.InvalidOperatingSystemVersion,
error.Overflow => return error.InvalidOperatingSystemVersion, },
error.InvalidVersion => return error.InvalidOperatingSystemVersion,
}; };
result.os_version_max = .{ .semver = max_ver };
}, },
.windows => range: {
.windows => {
var range_it = mem.splitSequence(u8, version_text, "..."); var range_it = mem.splitSequence(u8, version_text, "...");
result.os_version_min = .{
const min_text = range_it.first(); .windows = try Target.Os.WindowsVersion.parse(range_it.first()),
const min_ver = std.meta.stringToEnum(Target.Os.WindowsVersion, min_text) orelse };
return error.InvalidOperatingSystemVersion; result.os_version_max = .{
result.os_version_min = .{ .windows = min_ver }; .windows = try Target.Os.WindowsVersion.parse(range_it.next() orelse break :range),
};
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 };
}, },
} };
} }
pub fn eql(a: Query, b: Query) bool { pub fn eql(a: Query, b: Query) bool {

View File

@ -430,9 +430,9 @@ pub fn abiAndDynamicLinkerFromFile(
query: Target.Query, query: Target.Query,
) AbiAndDynamicLinkerFromFileError!Target { ) AbiAndDynamicLinkerFromFileError!Target {
var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined; var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;
_ = try preadMin(file, &hdr_buf, 0, hdr_buf.len); _ = try preadAtLeast(file, &hdr_buf, 0, hdr_buf.len);
const hdr32 = @as(*elf.Elf32_Ehdr, @ptrCast(&hdr_buf)); const hdr32: *elf.Elf32_Ehdr = @ptrCast(&hdr_buf);
const hdr64 = @as(*elf.Elf64_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; 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]) { const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) {
elf.ELFDATA2LSB => .little, elf.ELFDATA2LSB => .little,
@ -469,7 +469,7 @@ pub fn abiAndDynamicLinkerFromFile(
// Reserve some bytes so that we can deref the 64-bit struct fields // Reserve some bytes so that we can deref the 64-bit struct fields
// even when the ELF file is 32-bits. // even when the ELF file is 32-bits.
const ph_reserve: usize = @sizeOf(elf.Elf64_Phdr) - @sizeOf(elf.Elf32_Phdr); 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; var ph_buf_i: usize = 0;
while (ph_buf_i < ph_read_byte_len and ph_i < phnum) : ({ while (ph_buf_i < ph_read_byte_len and ph_i < phnum) : ({
ph_i += 1; 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_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); 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; if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;
const filesz = @as(usize, @intCast(p_filesz)); const filesz: usize = @intCast(p_filesz);
_ = try preadMin(file, result.dynamic_linker.buffer[0..filesz], p_offset, filesz); _ = try preadAtLeast(file, result.dynamic_linker.buffer[0..filesz], p_offset, filesz);
// PT_INTERP includes a null byte in filesz. // PT_INTERP includes a null byte in filesz.
const len = filesz - 1; const len = filesz - 1;
// dynamic_linker.max_byte is "max", not "len". // dynamic_linker.max_byte is "max", not "len".
// We know it will fit in u8 because we check against dynamic_linker.buffer.len above. // 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. // Use it to determine ABI.
const full_ld_path = result.dynamic_linker.buffer[0..len]; 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 // Reserve some bytes so that we can deref the 64-bit struct fields
// even when the ELF file is 32-bits. // even when the ELF file is 32-bits.
const dyn_reserve: usize = @sizeOf(elf.Elf64_Dyn) - @sizeOf(elf.Elf32_Dyn); 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, file,
dyn_buf[0 .. dyn_buf.len - dyn_reserve], dyn_buf[0 .. dyn_buf.len - dyn_reserve],
dyn_off, dyn_off,
@ -556,14 +556,14 @@ pub fn abiAndDynamicLinkerFromFile(
var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined; var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined;
if (sh_buf.len < shentsize) return error.InvalidElfFile; 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 shstr32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf));
const shstr64: *elf.Elf64_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_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); const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);
var strtab_buf: [4096:0]u8 = undefined; var strtab_buf: [4096:0]u8 = undefined;
const shstrtab_len = @min(shstrtab_size, strtab_buf.len); 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 shstrtab = strtab_buf[0..shstrtab_read_len];
const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum); 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 // Reserve some bytes so that we can deref the 64-bit struct fields
// even when the ELF file is 32-bits. // even when the ELF file is 32-bits.
const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr); 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, file,
sh_buf[0 .. sh_buf.len - sh_reserve], sh_buf[0 .. sh_buf.len - sh_reserve],
shoff, shoff,
@ -604,7 +604,7 @@ pub fn abiAndDynamicLinkerFromFile(
const rp_max_size = ds.size - rpoff; const rp_max_size = ds.size - rpoff;
const strtab_len = @min(rp_max_size, strtab_buf.len); 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 strtab = strtab_buf[0..strtab_read_len];
const rpath_list = mem.sliceTo(strtab, 0); 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 { fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined; var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;
_ = try preadMin(file, &hdr_buf, 0, hdr_buf.len); _ = try preadAtLeast(file, &hdr_buf, 0, hdr_buf.len);
const hdr32 = @as(*elf.Elf32_Ehdr, @ptrCast(&hdr_buf)); const hdr32: *elf.Elf32_Ehdr = @ptrCast(&hdr_buf);
const hdr64 = @as(*elf.Elf64_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; 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]) { const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) {
elf.ELFDATA2LSB => .little, 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; var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined;
if (sh_buf.len < shentsize) return error.InvalidElfFile; 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 shstr32: *elf.Elf32_Shdr = @ptrCast(@alignCast(&sh_buf));
const shstr64: *elf.Elf64_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_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); const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);
var strtab_buf: [4096:0]u8 = undefined; var strtab_buf: [4096:0]u8 = undefined;
const shstrtab_len = @min(shstrtab_size, strtab_buf.len); 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 shstrtab = strtab_buf[0..shstrtab_read_len];
const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum); const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum);
var sh_i: u16 = 0; 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 // Reserve some bytes so that we can deref the 64-bit struct fields
// even when the ELF file is 32-bits. // even when the ELF file is 32-bits.
const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr); 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, file,
sh_buf[0 .. sh_buf.len - sh_reserve], sh_buf[0 .. sh_buf.len - sh_reserve],
shoff, shoff,
@ -890,7 +890,7 @@ fn glibcVerFromSoFile(file: fs.File) !std.SemanticVersion {
const dynstr_size: usize = @intCast(dynstr.size); const dynstr_size: usize = @intCast(dynstr.size);
const dynstr_bytes = buf[0..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 it = mem.splitScalar(u8, dynstr_bytes, 0);
var max_ver: std.SemanticVersion = .{ .major = 2, .minor = 2, .patch = 5 }; var max_ver: std.SemanticVersion = .{ .major = 2, .minor = 2, .patch = 5 };
while (it.next()) |s| { while (it.next()) |s| {
@ -1029,7 +1029,7 @@ fn detectAbiAndDynamicLinker(
}; };
errdefer file.close(); 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.UnexpectedEndOfFile,
error.UnableToReadElfFile, error.UnableToReadElfFile,
=> break :blk file, => break :blk file,
@ -1083,7 +1083,7 @@ fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Quer
.abi = abi, .abi = abi,
.ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),
.dynamic_linker = if (query.dynamic_linker.get() == null) .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 else
query.dynamic_linker, query.dynamic_linker,
}; };
@ -1094,7 +1094,7 @@ const LdInfo = struct {
abi: Target.Abi, 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; var i: usize = 0;
while (i < min_read_len) { while (i < min_read_len) {
const len = file.pread(buf[i..], offset + i) catch |err| switch (err) { const len = file.pread(buf[i..], offset + i) catch |err| switch (err) {

View File

@ -140,13 +140,11 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
}), }),
.windows => |windows| try buffer.writer().print( .windows => |windows| try buffer.writer().print(
\\ .windows = .{{ \\ .windows = .{{
\\ .min = {s}, \\ .min = {c},
\\ .max = {s}, \\ .max = {c},
\\ }}}}, \\ }}}},
\\ \\
, , .{ windows.min, windows.max }),
.{ windows.min, windows.max },
),
} }
try buffer.appendSlice( try buffer.appendSlice(
\\}; \\};