Commit d97954a8ea

Alex Rønne Petersen <alex@alexrp.com>
2025-10-01 01:02:58
test: remove stack_iterator standalone test
Our new stack trace tests cover all the important parts of this.
1 parent 5a71e15
test/standalone/stack_iterator/build.zig
@@ -1,167 +0,0 @@
-const std = @import("std");
-const builtin = @import("builtin");
-
-pub fn build(b: *std.Build) void {
-    const test_step = b.step("test", "Test it");
-    b.default_step = test_step;
-
-    const target = b.standardTargetOptions(.{});
-    const optimize = b.standardOptimizeOption(.{});
-
-    if (target.result.cpu.arch.isRISCV() and target.result.os.tag == .linux) {
-        // https://github.com/ziglang/zig/issues/24310
-        return;
-    }
-
-    // Unwinding with a frame pointer
-    //
-    // getcontext version: zig std
-    //
-    // Unwind info type:
-    //   - ELF: DWARF .debug_frame
-    //   - MachO: __unwind_info encodings:
-    //     - x86_64: RBP_FRAME
-    //     - aarch64: FRAME, DWARF
-    {
-        const exe = b.addExecutable(.{
-            .name = "unwind_fp",
-            .root_module = b.createModule(.{
-                .root_source_file = b.path("unwind.zig"),
-                .target = target,
-                .optimize = optimize,
-                .unwind_tables = if (target.result.os.tag.isDarwin()) .async else null,
-                .omit_frame_pointer = false,
-            }),
-        });
-
-        const run_cmd = b.addRunArtifact(exe);
-        test_step.dependOn(&run_cmd.step);
-    }
-
-    // Unwinding without a frame pointer
-    //
-    // getcontext version: zig std
-    //
-    // Unwind info type:
-    //   - ELF: DWARF .eh_frame_hdr + .eh_frame
-    //   - MachO: __unwind_info encodings:
-    //     - x86_64: STACK_IMMD, STACK_IND
-    //     - aarch64: FRAMELESS, DWARF
-    {
-        const exe = b.addExecutable(.{
-            .name = "unwind_nofp",
-            .root_module = b.createModule(.{
-                .root_source_file = b.path("unwind.zig"),
-                .target = target,
-                .optimize = optimize,
-                .unwind_tables = .async,
-                .omit_frame_pointer = true,
-            }),
-            // self-hosted lacks omit_frame_pointer support
-            .use_llvm = true,
-        });
-
-        if (builtin.os.tag != .freebsd) {
-            const run_cmd = b.addRunArtifact(exe);
-            test_step.dependOn(&run_cmd.step);
-        } else {
-            test_step.dependOn(&exe.step);
-        }
-    }
-
-    // https://github.com/ziglang/zig/issues/24522
-    //// Unwinding through a C shared library without a frame pointer (libc)
-    ////
-    //// getcontext version: libc
-    ////
-    //// Unwind info type:
-    ////   - ELF: DWARF .eh_frame + .debug_frame
-    ////   - MachO: __unwind_info encodings:
-    ////     - x86_64: STACK_IMMD, STACK_IND
-    ////     - aarch64: FRAMELESS, DWARF
-    //{
-    //    const c_shared_lib = b.addLibrary(.{
-    //        .linkage = .dynamic,
-    //        .name = "c_shared_lib",
-    //        .root_module = b.createModule(.{
-    //            .root_source_file = null,
-    //            .target = target,
-    //            .optimize = optimize,
-    //            .link_libc = true,
-    //            .strip = false,
-    //        }),
-    //    });
-
-    //    if (target.result.os.tag == .windows)
-    //        c_shared_lib.root_module.addCMacro("LIB_API", "__declspec(dllexport)");
-
-    //    c_shared_lib.root_module.addCSourceFile(.{
-    //        .file = b.path("shared_lib.c"),
-    //        .flags = &.{"-fomit-frame-pointer"},
-    //    });
-
-    //    const exe = b.addExecutable(.{
-    //        .name = "shared_lib_unwind",
-    //        .root_module = b.createModule(.{
-    //            .root_source_file = b.path("shared_lib_unwind.zig"),
-    //            .target = target,
-    //            .optimize = optimize,
-    //            .unwind_tables = if (target.result.os.tag.isDarwin()) .async else null,
-    //            .omit_frame_pointer = true,
-    //        }),
-    //        // zig objcopy doesn't support incremental binaries
-    //        .use_llvm = true,
-    //    });
-
-    //    exe.root_module.linkLibrary(c_shared_lib);
-
-    //    const run_cmd = b.addRunArtifact(exe);
-    //    test_step.dependOn(&run_cmd.step);
-
-    //    // Separate debug info ELF file
-    //    if (target.result.ofmt == .elf) {
-    //        const filename = b.fmt("{s}_stripped", .{exe.out_filename});
-    //        const stripped_exe = b.addObjCopy(exe.getEmittedBin(), .{
-    //            .basename = filename, // set the name for the debuglink
-    //            .compress_debug = true,
-    //            .strip = .debug,
-    //            .extract_to_separate_file = true,
-    //        });
-
-    //        const run_stripped = std.Build.Step.Run.create(b, b.fmt("run {s}", .{filename}));
-    //        run_stripped.addFileArg(stripped_exe.getOutput());
-    //        test_step.dependOn(&run_stripped.step);
-    //    }
-    //}
-
-    // Unwinding without libc/posix
-    //
-    // No "getcontext" or "ucontext_t"
-    const no_os_targets = [_]std.Target.Os.Tag{ .freestanding, .other };
-    inline for (no_os_targets) |os_tag| {
-        const exe = b.addExecutable(.{
-            .name = "unwind_freestanding",
-            .root_module = b.createModule(.{
-                .root_source_file = b.path("unwind_freestanding.zig"),
-                .target = b.resolveTargetQuery(.{
-                    .cpu_arch = .x86_64,
-                    .os_tag = os_tag,
-                }),
-                .optimize = optimize,
-                .unwind_tables = null,
-                .omit_frame_pointer = false,
-            }),
-            // self-hosted lacks omit_frame_pointer support
-            .use_llvm = true,
-        });
-
-        // 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);
-        }
-    }
-}
test/standalone/stack_iterator/shared_lib.c
@@ -1,22 +0,0 @@
-#include <stdint.h>
-
-#ifndef LIB_API
-#define LIB_API
-#endif
-
-__attribute__((noinline)) void frame1(
-    void** expected,
-    void** unwound,
-    void (*frame2)(void** expected, void** unwound)) {
-    expected[3] = __builtin_extract_return_addr(__builtin_return_address(0));
-    frame2(expected, unwound);
-}
-
-LIB_API void frame0(
-    void** expected,
-    void** unwound,
-    void (*frame2)(void** expected, void** unwound)) {
-    expected[4] = __builtin_extract_return_addr(__builtin_return_address(0));
-    frame1(expected, unwound, frame2);
-}
-
test/standalone/stack_iterator/shared_lib_unwind.zig
@@ -1,48 +0,0 @@
-const std = @import("std");
-const builtin = @import("builtin");
-const debug = std.debug;
-const testing = std.testing;
-
-noinline fn frame4(expected: *[5]usize, unwound: *[5]usize) void {
-    expected[0] = @returnAddress();
-
-    var context: debug.ThreadContext = undefined;
-    testing.expect(debug.getContext(&context)) catch @panic("failed to getContext");
-
-    const debug_info = debug.getSelfDebugInfo() catch @panic("failed to openSelfDebugInfo");
-    var it = debug.StackIterator.initWithContext(expected[0], debug_info, &context) catch @panic("failed to initWithContext");
-    defer it.deinit();
-
-    for (unwound) |*addr| {
-        if (it.next()) |return_address| addr.* = return_address;
-    }
-}
-
-noinline fn frame3(expected: *[5]usize, unwound: *[5]usize) void {
-    expected[1] = @returnAddress();
-    frame4(expected, unwound);
-}
-
-fn frame2(expected: *[5]usize, unwound: *[5]usize) callconv(.c) void {
-    expected[2] = @returnAddress();
-    frame3(expected, unwound);
-}
-
-extern fn frame0(
-    expected: *[5]usize,
-    unwound: *[5]usize,
-    frame_2: *const fn (expected: *[5]usize, unwound: *[5]usize) callconv(.c) void,
-) void;
-
-pub fn main() !void {
-    // Disabled until the DWARF unwinder bugs on .aarch64 are solved
-    if (builtin.omit_frame_pointer and comptime builtin.target.os.tag.isDarwin() and builtin.cpu.arch == .aarch64) return;
-    if (builtin.target.os.tag.isDarwin() and builtin.cpu.arch == .x86_64) return; // https://github.com/ziglang/zig/issues/21337
-
-    if (!std.debug.have_ucontext or !std.debug.have_getcontext) return;
-
-    var expected: [5]usize = undefined;
-    var unwound: [5]usize = undefined;
-    frame0(&expected, &unwound, &frame2);
-    try testing.expectEqual(expected, unwound);
-}
test/standalone/stack_iterator/unwind.zig
@@ -1,101 +0,0 @@
-const std = @import("std");
-const builtin = @import("builtin");
-const fatal = std.process.fatal;
-
-noinline fn frame3(expected: *[4]usize, addr_buf: *[4]usize) std.builtin.StackTrace {
-    expected[0] = @returnAddress();
-    return std.debug.captureCurrentStackTrace(.{
-        .first_address = @returnAddress(),
-        .allow_unsafe_unwind = true,
-    }, addr_buf);
-}
-
-noinline fn frame2(expected: *[4]usize, addr_buf: *[4]usize) std.builtin.StackTrace {
-    // Exercise different __unwind_info / DWARF CFI encodings by forcing some registers to be restored
-    if (builtin.target.ofmt != .c) {
-        switch (builtin.target.cpu.arch) {
-            .x86 => {
-                if (builtin.omit_frame_pointer) {
-                    asm volatile (
-                        \\movl $3, %%ebx
-                        \\movl $1, %%ecx
-                        \\movl $2, %%edx
-                        \\movl $7, %%edi
-                        \\movl $6, %%esi
-                        \\movl $5, %%ebp
-                        ::: .{ .ebx = true, .ecx = true, .edx = true, .edi = true, .esi = true, .ebp = true });
-                } else {
-                    asm volatile (
-                        \\movl $3, %%ebx
-                        \\movl $1, %%ecx
-                        \\movl $2, %%edx
-                        \\movl $7, %%edi
-                        \\movl $6, %%esi
-                        ::: .{ .ebx = true, .ecx = true, .edx = true, .edi = true, .esi = true });
-                }
-            },
-            .x86_64 => {
-                if (builtin.omit_frame_pointer) {
-                    asm volatile (
-                        \\movq $3, %%rbx
-                        \\movq $12, %%r12
-                        \\movq $13, %%r13
-                        \\movq $14, %%r14
-                        \\movq $15, %%r15
-                        \\movq $6, %%rbp
-                        ::: .{ .rbx = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .rbp = true });
-                } else {
-                    asm volatile (
-                        \\movq $3, %%rbx
-                        \\movq $12, %%r12
-                        \\movq $13, %%r13
-                        \\movq $14, %%r14
-                        \\movq $15, %%r15
-                        ::: .{ .rbx = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true });
-                }
-            },
-            else => {},
-        }
-    }
-
-    expected[1] = @returnAddress();
-    return frame3(expected, addr_buf);
-}
-
-noinline fn frame1(expected: *[4]usize, addr_buf: *[4]usize) std.builtin.StackTrace {
-    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);
-
-    return frame2(expected, addr_buf);
-}
-
-noinline fn frame0(expected: *[4]usize, addr_buf: *[4]usize) std.builtin.StackTrace {
-    expected[3] = @returnAddress();
-    return frame1(expected, addr_buf);
-}
-
-pub fn main() void {
-    if (std.debug.cpu_context.Native == noreturn and builtin.omit_frame_pointer) {
-        // Stack unwinding is impossible.
-        return;
-    }
-
-    var expected: [4]usize = undefined;
-    var addr_buf: [4]usize = undefined;
-    const trace = frame0(&expected, &addr_buf);
-    // There may be *more* than 4 frames (due to the caller of `main`); that's okay.
-    if (trace.index < 4) {
-        fatal("expected at least 4 frames, got '{d}':\n{f}", .{ trace.index, &trace });
-    }
-    if (!std.mem.eql(usize, trace.instruction_addresses, &expected)) {
-        const expected_trace: std.builtin.StackTrace = .{
-            .index = 4,
-            .instruction_addresses = &expected,
-        };
-        fatal("expected trace:\n{f}\nactual trace:\n{f}", .{ &expected_trace, &trace });
-    }
-}
test/standalone/stack_iterator/unwind_freestanding.zig
@@ -1,66 +0,0 @@
-//! Test StackIterator on 'freestanding' target.  Based on unwind.zig.
-
-const std = @import("std");
-
-noinline fn frame3(expected: *[4]usize, addr_buf: *[4]usize) std.builtin.StackTrace {
-    expected[0] = @returnAddress();
-    return std.debug.captureCurrentStackTrace(.{
-        .first_address = @returnAddress(),
-        .allow_unsafe_unwind = true,
-    }, addr_buf);
-}
-
-noinline fn frame2(expected: *[4]usize, addr_buf: *[4]usize) std.builtin.StackTrace {
-    expected[1] = @returnAddress();
-    return frame3(expected, addr_buf);
-}
-
-noinline fn frame1(expected: *[4]usize, addr_buf: *[4]usize) std.builtin.StackTrace {
-    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);
-
-    return frame2(expected, addr_buf);
-}
-
-noinline fn frame0(expected: *[4]usize, addr_buf: *[4]usize) std.builtin.StackTrace {
-    expected[3] = @returnAddress();
-    return frame1(expected, addr_buf);
-}
-
-/// No-OS entrypoint
-export fn _start() callconv(.withStackAlign(.c, 1)) noreturn {
-    var expected: [4]usize = undefined;
-    var addr_buf: [4]usize = undefined;
-    const trace = frame0(&expected, &addr_buf);
-
-    // Since we can't print from this freestanding test, we'll just use the exit
-    // code to communicate error conditions.
-
-    // Unlike `unwind.zig`, we can expect *exactly* 4 frames, as we are the
-    // actual entry point and the frame pointer will be 0 on entry.
-    if (trace.index != 4) exit(1);
-    if (trace.instruction_addresses[0] != expected[0]) exit(2);
-    if (trace.instruction_addresses[1] != expected[1]) exit(3);
-    if (trace.instruction_addresses[2] != expected[2]) exit(4);
-    if (trace.instruction_addresses[3] != expected[3]) exit(5);
-
-    exit(0);
-}
-
-fn exit(code: u8) noreturn {
-    // We are intentionally compiling with the target OS being "freestanding" to
-    // exercise std.debug, but we still need to exit the process somehow; so do
-    // the appropriate x86_64-linux syscall.
-    asm volatile (
-        \\movl $60, %%eax
-        \\syscall
-        :
-        : [code] "{edi}" (code),
-        : .{ .edi = true, .eax = true });
-
-    unreachable;
-}
test/standalone/build.zig.zon
@@ -163,9 +163,6 @@
         .zerolength_check = .{
             .path = "zerolength_check",
         },
-        .stack_iterator = .{
-            .path = "stack_iterator",
-        },
         .coff_dwarf = .{
             .path = "coff_dwarf",
         },