authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-10-01 23:24:53+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-10-01 23:47:47+02:00
log97de46dc16b584f5bd7aa2ae9afb2bb77970cd22
tree67cdb1aaf5dc90c873c6b0c36b53a80c8856a67f
parent8520e9312eed3b3b8d7f95d4844c83105c91ead1
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

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


3 files changed, 111 insertions(+), 4 deletions(-)

lib/std/debug/Dwarf.zig+3-4
...@@ -1432,6 +1432,7 @@ pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 {...@@ -1432,6 +1432,7 @@ pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 {
1432 .aarch64, .aarch64_be => 32,1432 .aarch64, .aarch64_be => 32,
1433 .arm, .armeb, .thumb, .thumbeb => 15,1433 .arm, .armeb, .thumb, .thumbeb => 15,
1434 .loongarch32, .loongarch64 => 32,1434 .loongarch32, .loongarch64 => 32,
1435 .riscv32, .riscv32be, .riscv64, .riscv64be => 32,
1435 .x86 => 8,1436 .x86 => 8,
1436 .x86_64 => 16,1437 .x86_64 => 16,
1437 else => null,1438 else => null,
...@@ -1443,6 +1444,7 @@ pub fn fpRegNum(arch: std.Target.Cpu.Arch) u16 {...@@ -1443,6 +1444,7 @@ pub fn fpRegNum(arch: std.Target.Cpu.Arch) u16 {
1443 .aarch64, .aarch64_be => 29,1444 .aarch64, .aarch64_be => 29,
1444 .arm, .armeb, .thumb, .thumbeb => 11,1445 .arm, .armeb, .thumb, .thumbeb => 11,
1445 .loongarch32, .loongarch64 => 22,1446 .loongarch32, .loongarch64 => 22,
1447 .riscv32, .riscv32be, .riscv64, .riscv64be => 8,
1446 .x86 => 5,1448 .x86 => 5,
1447 .x86_64 => 6,1449 .x86_64 => 6,
1448 else => unreachable,1450 else => unreachable,
...@@ -1454,6 +1456,7 @@ pub fn spRegNum(arch: std.Target.Cpu.Arch) u16 {...@@ -1454,6 +1456,7 @@ pub fn spRegNum(arch: std.Target.Cpu.Arch) u16 {
1454 .aarch64, .aarch64_be => 31,1456 .aarch64, .aarch64_be => 31,
1455 .arm, .armeb, .thumb, .thumbeb => 13,1457 .arm, .armeb, .thumb, .thumbeb => 13,
1456 .loongarch32, .loongarch64 => 3,1458 .loongarch32, .loongarch64 => 3,
1459 .riscv32, .riscv32be, .riscv64, .riscv64be => 2,
1457 .x86 => 4,1460 .x86 => 4,
1458 .x86_64 => 7,1461 .x86_64 => 7,
1459 else => unreachable,1462 else => unreachable,
...@@ -1473,10 +1476,6 @@ pub fn supportsUnwinding(target: *const std.Target) bool {...@@ -1473,10 +1476,6 @@ pub fn supportsUnwinding(target: *const std.Target) bool {
1473 .spirv64,1476 .spirv64,
1474 => false,1477 => false,
14751478
1476 // Enabling this causes relocation errors such as:
1477 // error: invalid relocation type R_RISCV_SUB32 at offset 0x20
1478 .riscv64, .riscv64be, .riscv32, .riscv32be => false,
1479
1480 // Conservative guess. Feel free to update this logic with any targets1479 // Conservative guess. Feel free to update this logic with any targets
1481 // that are known to not support Dwarf unwinding.1480 // that are known to not support Dwarf unwinding.
1482 else => true,1481 else => true,
lib/std/debug/SelfInfo/Elf.zig+2
...@@ -88,6 +88,8 @@ pub const can_unwind: bool = s: {...@@ -88,6 +88,8 @@ pub const can_unwind: bool = s: {
88 .aarch64,88 .aarch64,
89 .aarch64_be,89 .aarch64_be,
90 .loongarch64,90 .loongarch64,
91 .riscv32,
92 .riscv64,
91 .x86,93 .x86,
92 .x86_64,94 .x86_64,
93 },95 },
lib/std/debug/cpu_context.zig+106
...@@ -7,6 +7,7 @@ else switch (native_arch) {...@@ -7,6 +7,7 @@ else switch (native_arch) {
7 .aarch64, .aarch64_be => Aarch64,7 .aarch64, .aarch64_be => Aarch64,
8 .arm, .armeb, .thumb, .thumbeb => Arm,8 .arm, .armeb, .thumb, .thumbeb => Arm,
9 .loongarch32, .loongarch64 => LoongArch,9 .loongarch32, .loongarch64 => LoongArch,
10 .riscv32, .riscv32be, .riscv64, .riscv64be => Riscv,
10 .x86 => X86,11 .x86 => X86,
11 .x86_64 => X86_64,12 .x86_64 => X86_64,
12 else => noreturn,13 else => noreturn,
...@@ -181,6 +182,13 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native {...@@ -181,6 +182,13 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native {
181 },182 },
182 else => null,183 else => null,
183 },184 },
185 .riscv32, .riscv64 => switch (builtin.os.tag) {
186 .linux => .{
187 .r = [1]usize{0} ++ uc.mcontext.gregs[1..].*, // r0 position is used for pc; replace with zero
188 .pc = uc.mcontext.gregs[0],
189 },
190 else => null,
191 },
184 else => null,192 else => null,
185 };193 };
186}194}
...@@ -571,6 +579,104 @@ pub const LoongArch = extern struct {...@@ -571,6 +579,104 @@ pub const LoongArch = extern struct {
571 }579 }
572};580};
573581
582/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
583pub const Riscv = extern struct {
584 /// The numbered general-purpose registers r0 - r31. r0 must be zero.
585 r: [32]usize,
586 pc: usize,
587
588 pub inline fn current() Riscv {
589 var ctx: Riscv = undefined;
590 asm volatile (if (@sizeOf(usize) == 8)
591 \\ sd zero, 0(t0)
592 \\ sd ra, 8(t0)
593 \\ sd sp, 16(t0)
594 \\ sd gp, 24(t0)
595 \\ sd tp, 32(t0)
596 \\ sd t0, 40(t0)
597 \\ sd t1, 48(t0)
598 \\ sd t2, 56(t0)
599 \\ sd s0, 64(t0)
600 \\ sd s1, 72(t0)
601 \\ sd a0, 80(t0)
602 \\ sd a1, 88(t0)
603 \\ sd a2, 96(t0)
604 \\ sd a3, 104(t0)
605 \\ sd a4, 112(t0)
606 \\ sd a5, 120(t0)
607 \\ sd a6, 128(t0)
608 \\ sd a7, 136(t0)
609 \\ sd s2, 144(t0)
610 \\ sd s3, 152(t0)
611 \\ sd s4, 160(t0)
612 \\ sd s5, 168(t0)
613 \\ sd s6, 176(t0)
614 \\ sd s7, 184(t0)
615 \\ sd s8, 192(t0)
616 \\ sd s9, 200(t0)
617 \\ sd s10, 208(t0)
618 \\ sd s11, 216(t0)
619 \\ sd t3, 224(t0)
620 \\ sd t4, 232(t0)
621 \\ sd t5, 240(t0)
622 \\ sd t6, 248(t0)
623 \\ jal ra, 1f
624 \\1:
625 \\ sd ra, 256(t0)
626 \\ ld ra, 8(t0)
627 else
628 \\ sw zero, 0(t0)
629 \\ sw ra, 4(t0)
630 \\ sw sp, 8(t0)
631 \\ sw gp, 12(t0)
632 \\ sw tp, 16(t0)
633 \\ sw t0, 20(t0)
634 \\ sw t1, 24(t0)
635 \\ sw t2, 28(t0)
636 \\ sw s0, 32(t0)
637 \\ sw s1, 36(t0)
638 \\ sw a0, 40(t0)
639 \\ sw a1, 44(t0)
640 \\ sw a2, 48(t0)
641 \\ sw a3, 52(t0)
642 \\ sw a4, 56(t0)
643 \\ sw a5, 60(t0)
644 \\ sw a6, 64(t0)
645 \\ sw a7, 68(t0)
646 \\ sw s2, 72(t0)
647 \\ sw s3, 76(t0)
648 \\ sw s4, 80(t0)
649 \\ sw s5, 84(t0)
650 \\ sw s6, 88(t0)
651 \\ sw s7, 92(t0)
652 \\ sw s8, 96(t0)
653 \\ sw s9, 100(t0)
654 \\ sw s10, 104(t0)
655 \\ sw s11, 108(t0)
656 \\ sw t3, 112(t0)
657 \\ sw t4, 116(t0)
658 \\ sw t5, 120(t0)
659 \\ sw t6, 124(t0)
660 \\ jal ra, 1f
661 \\1:
662 \\ sw ra, 128(t0)
663 \\ lw ra, 4(t0)
664 :
665 : [gprs] "{t0}" (&ctx),
666 : .{ .memory = true });
667 return ctx;
668 }
669
670 pub fn dwarfRegisterBytes(ctx: *Riscv, register_num: u16) DwarfRegisterError![]u8 {
671 switch (register_num) {
672 0...31 => return @ptrCast(&ctx.r[register_num]),
673 32 => return @ptrCast(&ctx.pc),
674
675 else => return error.InvalidRegister,
676 }
677 }
678};
679
574const signal_ucontext_t = switch (native_os) {680const signal_ucontext_t = switch (native_os) {
575 .linux => std.os.linux.ucontext_t,681 .linux => std.os.linux.ucontext_t,
576 .emscripten => std.os.emscripten.ucontext_t,682 .emscripten => std.os.emscripten.ucontext_t,