std.debug: add riscv32-linux and riscv64-linux unwind support

This commit is contained in:
Alex Rønne Petersen 2025-10-01 23:24:53 +02:00
parent 8520e9312e
commit 97de46dc16
No known key found for this signature in database
3 changed files with 111 additions and 4 deletions

View file

@ -1432,6 +1432,7 @@ pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 {
.aarch64, .aarch64_be => 32, .aarch64, .aarch64_be => 32,
.arm, .armeb, .thumb, .thumbeb => 15, .arm, .armeb, .thumb, .thumbeb => 15,
.loongarch32, .loongarch64 => 32, .loongarch32, .loongarch64 => 32,
.riscv32, .riscv32be, .riscv64, .riscv64be => 32,
.x86 => 8, .x86 => 8,
.x86_64 => 16, .x86_64 => 16,
else => null, else => null,
@ -1443,6 +1444,7 @@ pub fn fpRegNum(arch: std.Target.Cpu.Arch) u16 {
.aarch64, .aarch64_be => 29, .aarch64, .aarch64_be => 29,
.arm, .armeb, .thumb, .thumbeb => 11, .arm, .armeb, .thumb, .thumbeb => 11,
.loongarch32, .loongarch64 => 22, .loongarch32, .loongarch64 => 22,
.riscv32, .riscv32be, .riscv64, .riscv64be => 8,
.x86 => 5, .x86 => 5,
.x86_64 => 6, .x86_64 => 6,
else => unreachable, else => unreachable,
@ -1454,6 +1456,7 @@ pub fn spRegNum(arch: std.Target.Cpu.Arch) u16 {
.aarch64, .aarch64_be => 31, .aarch64, .aarch64_be => 31,
.arm, .armeb, .thumb, .thumbeb => 13, .arm, .armeb, .thumb, .thumbeb => 13,
.loongarch32, .loongarch64 => 3, .loongarch32, .loongarch64 => 3,
.riscv32, .riscv32be, .riscv64, .riscv64be => 2,
.x86 => 4, .x86 => 4,
.x86_64 => 7, .x86_64 => 7,
else => unreachable, else => unreachable,
@ -1473,10 +1476,6 @@ pub fn supportsUnwinding(target: *const std.Target) bool {
.spirv64, .spirv64,
=> false, => false,
// Enabling this causes relocation errors such as:
// error: invalid relocation type R_RISCV_SUB32 at offset 0x20
.riscv64, .riscv64be, .riscv32, .riscv32be => false,
// Conservative guess. Feel free to update this logic with any targets // Conservative guess. Feel free to update this logic with any targets
// that are known to not support Dwarf unwinding. // that are known to not support Dwarf unwinding.
else => true, else => true,

View file

@ -88,6 +88,8 @@ pub const can_unwind: bool = s: {
.aarch64, .aarch64,
.aarch64_be, .aarch64_be,
.loongarch64, .loongarch64,
.riscv32,
.riscv64,
.x86, .x86,
.x86_64, .x86_64,
}, },

View file

@ -7,6 +7,7 @@ else switch (native_arch) {
.aarch64, .aarch64_be => Aarch64, .aarch64, .aarch64_be => Aarch64,
.arm, .armeb, .thumb, .thumbeb => Arm, .arm, .armeb, .thumb, .thumbeb => Arm,
.loongarch32, .loongarch64 => LoongArch, .loongarch32, .loongarch64 => LoongArch,
.riscv32, .riscv32be, .riscv64, .riscv64be => Riscv,
.x86 => X86, .x86 => X86,
.x86_64 => X86_64, .x86_64 => X86_64,
else => noreturn, else => noreturn,
@ -181,6 +182,13 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native {
}, },
else => null, else => null,
}, },
.riscv32, .riscv64 => switch (builtin.os.tag) {
.linux => .{
.r = [1]usize{0} ++ uc.mcontext.gregs[1..].*, // r0 position is used for pc; replace with zero
.pc = uc.mcontext.gregs[0],
},
else => null,
},
else => null, else => null,
}; };
} }
@ -571,6 +579,104 @@ pub const LoongArch = extern struct {
} }
}; };
/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
pub const Riscv = extern struct {
/// The numbered general-purpose registers r0 - r31. r0 must be zero.
r: [32]usize,
pc: usize,
pub inline fn current() Riscv {
var ctx: Riscv = undefined;
asm volatile (if (@sizeOf(usize) == 8)
\\ sd zero, 0(t0)
\\ sd ra, 8(t0)
\\ sd sp, 16(t0)
\\ sd gp, 24(t0)
\\ sd tp, 32(t0)
\\ sd t0, 40(t0)
\\ sd t1, 48(t0)
\\ sd t2, 56(t0)
\\ sd s0, 64(t0)
\\ sd s1, 72(t0)
\\ sd a0, 80(t0)
\\ sd a1, 88(t0)
\\ sd a2, 96(t0)
\\ sd a3, 104(t0)
\\ sd a4, 112(t0)
\\ sd a5, 120(t0)
\\ sd a6, 128(t0)
\\ sd a7, 136(t0)
\\ sd s2, 144(t0)
\\ sd s3, 152(t0)
\\ sd s4, 160(t0)
\\ sd s5, 168(t0)
\\ sd s6, 176(t0)
\\ sd s7, 184(t0)
\\ sd s8, 192(t0)
\\ sd s9, 200(t0)
\\ sd s10, 208(t0)
\\ sd s11, 216(t0)
\\ sd t3, 224(t0)
\\ sd t4, 232(t0)
\\ sd t5, 240(t0)
\\ sd t6, 248(t0)
\\ jal ra, 1f
\\1:
\\ sd ra, 256(t0)
\\ ld ra, 8(t0)
else
\\ sw zero, 0(t0)
\\ sw ra, 4(t0)
\\ sw sp, 8(t0)
\\ sw gp, 12(t0)
\\ sw tp, 16(t0)
\\ sw t0, 20(t0)
\\ sw t1, 24(t0)
\\ sw t2, 28(t0)
\\ sw s0, 32(t0)
\\ sw s1, 36(t0)
\\ sw a0, 40(t0)
\\ sw a1, 44(t0)
\\ sw a2, 48(t0)
\\ sw a3, 52(t0)
\\ sw a4, 56(t0)
\\ sw a5, 60(t0)
\\ sw a6, 64(t0)
\\ sw a7, 68(t0)
\\ sw s2, 72(t0)
\\ sw s3, 76(t0)
\\ sw s4, 80(t0)
\\ sw s5, 84(t0)
\\ sw s6, 88(t0)
\\ sw s7, 92(t0)
\\ sw s8, 96(t0)
\\ sw s9, 100(t0)
\\ sw s10, 104(t0)
\\ sw s11, 108(t0)
\\ sw t3, 112(t0)
\\ sw t4, 116(t0)
\\ sw t5, 120(t0)
\\ sw t6, 124(t0)
\\ jal ra, 1f
\\1:
\\ sw ra, 128(t0)
\\ lw ra, 4(t0)
:
: [gprs] "{t0}" (&ctx),
: .{ .memory = true });
return ctx;
}
pub fn dwarfRegisterBytes(ctx: *Riscv, register_num: u16) DwarfRegisterError![]u8 {
switch (register_num) {
0...31 => return @ptrCast(&ctx.r[register_num]),
32 => return @ptrCast(&ctx.pc),
else => return error.InvalidRegister,
}
}
};
const signal_ucontext_t = switch (native_os) { const signal_ucontext_t = switch (native_os) {
.linux => std.os.linux.ucontext_t, .linux => std.os.linux.ucontext_t,
.emscripten => std.os.emscripten.ucontext_t, .emscripten => std.os.emscripten.ucontext_t,