mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 00:26:57 +00:00
Default std.posix.system.ucontext_t is void
PR https://github.com/ziglang/zig/pull/20679 ("std.c reorganization") switched feature-detection code to use "T != void" checks in place of "@hasDecl". However, the std.posix.system struct is empty, so compile-time feature detection against symbols in there (specifically `std.posix.system.ucontext_t` in this case), fail at compile time on freestanding targets. This PR adds a void ucontext_t into the std.posix.system default. This PR also adds pseudo-"freestanding" variation of the StackIterator "unwind" test. It is sort of hacky (its freestanding, but assumes it can invoke a Linux exit syscall), but it does detect this problem. Fixes #20710
This commit is contained in:
parent
33c7984183
commit
e8503ecb65
@ -45,7 +45,9 @@ pub const system = if (use_libc)
|
||||
else switch (native_os) {
|
||||
.linux => linux,
|
||||
.plan9 => std.os.plan9,
|
||||
else => struct {},
|
||||
else => struct {
|
||||
pub const ucontext_t = void;
|
||||
},
|
||||
};
|
||||
|
||||
pub const AF = system.AF;
|
||||
|
@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const test_step = b.step("test", "Test it");
|
||||
@ -93,4 +94,30 @@ pub fn build(b: *std.Build) void {
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
test_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
||||
// Unwinding without libc/posix
|
||||
//
|
||||
// No "getcontext" or "ucontext_t"
|
||||
{
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "unwind_freestanding",
|
||||
.root_source_file = b.path("unwind_freestanding.zig"),
|
||||
.target = b.resolveTargetQuery(.{
|
||||
.cpu_arch = .x86_64,
|
||||
.os_tag = .freestanding,
|
||||
}),
|
||||
.optimize = optimize,
|
||||
.unwind_tables = null,
|
||||
.omit_frame_pointer = false,
|
||||
});
|
||||
|
||||
// This "freestanding" binary is runnable because it invokes the
|
||||
// Linux exit syscall directly.
|
||||
if (builtin.os.tag == .linux and builtin.cpu.arch == .x86_64) {
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
test_step.dependOn(&run_cmd.step);
|
||||
} else {
|
||||
test_step.dependOn(&exe.step);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
64
test/standalone/stack_iterator/unwind_freestanding.zig
Normal file
64
test/standalone/stack_iterator/unwind_freestanding.zig
Normal file
@ -0,0 +1,64 @@
|
||||
/// Test StackIterator on 'freestanding' target. Based on unwind.zig.
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const debug = std.debug;
|
||||
|
||||
noinline fn frame3(expected: *[4]usize, unwound: *[4]usize) void {
|
||||
expected[0] = @returnAddress();
|
||||
|
||||
var it = debug.StackIterator.init(@returnAddress(), @frameAddress());
|
||||
defer it.deinit();
|
||||
|
||||
// Save StackIterator's frame addresses into `unwound`:
|
||||
for (unwound) |*addr| {
|
||||
if (it.next()) |return_address| addr.* = return_address;
|
||||
}
|
||||
}
|
||||
|
||||
noinline fn frame2(expected: *[4]usize, unwound: *[4]usize) void {
|
||||
expected[1] = @returnAddress();
|
||||
frame3(expected, unwound);
|
||||
}
|
||||
|
||||
noinline fn frame1(expected: *[4]usize, unwound: *[4]usize) void {
|
||||
expected[2] = @returnAddress();
|
||||
|
||||
// Use a stack frame that is too big to encode in __unwind_info's stack-immediate encoding
|
||||
// to exercise the stack-indirect encoding path
|
||||
var pad: [std.math.maxInt(u8) * @sizeOf(usize) + 1]u8 = undefined;
|
||||
_ = std.mem.doNotOptimizeAway(&pad);
|
||||
|
||||
frame2(expected, unwound);
|
||||
}
|
||||
|
||||
noinline fn frame0(expected: *[4]usize, unwound: *[4]usize) void {
|
||||
expected[3] = @returnAddress();
|
||||
frame1(expected, unwound);
|
||||
}
|
||||
|
||||
// Freestanding entrypoint
|
||||
export fn _start() callconv(.C) noreturn {
|
||||
var expected: [4]usize = undefined;
|
||||
var unwound: [4]usize = undefined;
|
||||
frame0(&expected, &unwound);
|
||||
|
||||
// Verify result (no std.testing in freestanding)
|
||||
var missed: c_int = 0;
|
||||
for (expected, unwound) |expectFA, actualFA| {
|
||||
if (expectFA != actualFA) {
|
||||
missed += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Need to compile as "freestanding" to exercise the StackIterator code, but when run as a
|
||||
// regression test need to actually exit. So assume we're running on x86_64-linux ...
|
||||
asm volatile (
|
||||
\\movl $60, %%eax
|
||||
\\syscall
|
||||
:
|
||||
: [missed] "{edi}" (missed),
|
||||
: "edi", "eax"
|
||||
);
|
||||
|
||||
while (true) {} // unreached
|
||||
}
|
Loading…
Reference in New Issue
Block a user