From ca73d697b9b11b579b2fefb40e68ec637bea5050 Mon Sep 17 00:00:00 2001 From: Alex Rønne Petersen Date: Mon, 6 Oct 2025 17:45:31 +0200 Subject: std.debug: add unwind support for mips*-linux --- lib/std/debug/Dwarf.zig | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/std/debug/Dwarf.zig') diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig index 0134d10e6b..6efc925c69 100644 --- a/lib/std/debug/Dwarf.zig +++ b/lib/std/debug/Dwarf.zig @@ -1433,6 +1433,7 @@ pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 { .arm, .armeb, .thumb, .thumbeb => 15, .hexagon => 76, .loongarch32, .loongarch64 => 32, + .mips, .mipsel, .mips64, .mips64el => 37, .riscv32, .riscv32be, .riscv64, .riscv64be => 32, .s390x => 65, .x86 => 8, @@ -1447,6 +1448,7 @@ pub fn fpRegNum(arch: std.Target.Cpu.Arch) u16 { .arm, .armeb, .thumb, .thumbeb => 11, .hexagon => 30, .loongarch32, .loongarch64 => 22, + .mips, .mipsel, .mips64, .mips64el => 30, .riscv32, .riscv32be, .riscv64, .riscv64be => 8, .s390x => 11, .x86 => 5, @@ -1461,6 +1463,7 @@ pub fn spRegNum(arch: std.Target.Cpu.Arch) u16 { .arm, .armeb, .thumb, .thumbeb => 13, .hexagon => 29, .loongarch32, .loongarch64 => 3, + .mips, .mipsel, .mips64, .mips64el => 29, .riscv32, .riscv32be, .riscv64, .riscv64be => 2, .s390x => 15, .x86 => 4, -- cgit v1.2.3 From aa74eb505a9a831e4b40adabbb653fe33be284b1 Mon Sep 17 00:00:00 2001 From: Alex Rønne Petersen Date: Tue, 7 Oct 2025 00:05:39 +0200 Subject: std.debug: add unwind support for powerpc*-linux --- lib/std/debug/Dwarf.zig | 3 ++ lib/std/debug/SelfInfo/Elf.zig | 4 ++ lib/std/debug/cpu_context.zig | 117 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+) (limited to 'lib/std/debug/Dwarf.zig') diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig index 6efc925c69..3bc5fcf4f0 100644 --- a/lib/std/debug/Dwarf.zig +++ b/lib/std/debug/Dwarf.zig @@ -1434,6 +1434,7 @@ pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 { .hexagon => 76, .loongarch32, .loongarch64 => 32, .mips, .mipsel, .mips64, .mips64el => 37, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => 357, .riscv32, .riscv32be, .riscv64, .riscv64be => 32, .s390x => 65, .x86 => 8, @@ -1449,6 +1450,7 @@ pub fn fpRegNum(arch: std.Target.Cpu.Arch) u16 { .hexagon => 30, .loongarch32, .loongarch64 => 22, .mips, .mipsel, .mips64, .mips64el => 30, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => 1, .riscv32, .riscv32be, .riscv64, .riscv64be => 8, .s390x => 11, .x86 => 5, @@ -1464,6 +1466,7 @@ pub fn spRegNum(arch: std.Target.Cpu.Arch) u16 { .hexagon => 29, .loongarch32, .loongarch64 => 3, .mips, .mipsel, .mips64, .mips64el => 29, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => 1, .riscv32, .riscv32be, .riscv64, .riscv64be => 2, .s390x => 15, .x86 => 4, diff --git a/lib/std/debug/SelfInfo/Elf.zig b/lib/std/debug/SelfInfo/Elf.zig index 145fdfa59f..146f41278d 100644 --- a/lib/std/debug/SelfInfo/Elf.zig +++ b/lib/std/debug/SelfInfo/Elf.zig @@ -103,6 +103,10 @@ pub const can_unwind: bool = s: { .mipsel, .mips64, .mips64el, + .powerpc, + .powerpcle, + .powerpc64, + .powerpc64le, .riscv32, .riscv64, .s390x, diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 93cf96d242..bfc82f33ec 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -9,6 +9,7 @@ else switch (native_arch) { .hexagon => Hexagon, .loongarch32, .loongarch64 => LoongArch, .mips, .mipsel, .mips64, .mips64el => Mips, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => Powerpc, .riscv32, .riscv32be, .riscv64, .riscv64be => Riscv, .s390x => S390x, .x86 => X86, @@ -216,6 +217,14 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native { }, else => null, }, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => switch (builtin.os.tag) { + .linux => .{ + .r = uc.mcontext.gp_regs[0..32].*, + .pc = uc.mcontext.gp_regs[32], + .lr = uc.mcontext.gp_regs[36], + }, + 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 @@ -808,6 +817,114 @@ pub const Mips = extern struct { } }; +/// This is an `extern struct` so that inline assembly in `current` can use field offsets. +pub const Powerpc = extern struct { + /// The numbered general-purpose registers r0 - r31. + r: [32]Gpr, + pc: Gpr, + lr: Gpr, + + pub const Gpr = if (builtin.target.cpu.arch.isPowerPC64()) u64 else u32; + + pub inline fn current() Powerpc { + var ctx: Powerpc = undefined; + asm volatile (if (Gpr == u64) + \\ std 0, 0(10) + \\ std 1, 8(10) + \\ std 2, 16(10) + \\ std 3, 24(10) + \\ std 4, 32(10) + \\ std 5, 40(10) + \\ std 6, 48(10) + \\ std 7, 56(10) + \\ std 8, 64(10) + \\ std 9, 72(10) + \\ std 10, 80(10) + \\ std 11, 88(10) + \\ std 12, 96(10) + \\ std 13, 104(10) + \\ std 14, 112(10) + \\ std 15, 120(10) + \\ std 16, 128(10) + \\ std 17, 136(10) + \\ std 18, 144(10) + \\ std 19, 152(10) + \\ std 20, 160(10) + \\ std 21, 168(10) + \\ std 22, 176(10) + \\ std 23, 184(10) + \\ std 24, 192(10) + \\ std 25, 200(10) + \\ std 26, 208(10) + \\ std 27, 216(10) + \\ std 28, 224(10) + \\ std 29, 232(10) + \\ std 30, 240(10) + \\ std 31, 248(10) + \\ mflr 8 + \\ std 8, 264(10) + \\ bl 1f + \\1: + \\ mflr 8 + \\ std 8, 256(10) + \\ ld 8, 64(10) + else + \\ stw 0, 0(10) + \\ stw 1, 4(10) + \\ stw 2, 8(10) + \\ stw 3, 12(10) + \\ stw 4, 16(10) + \\ stw 5, 20(10) + \\ stw 6, 24(10) + \\ stw 7, 28(10) + \\ stw 8, 32(10) + \\ stw 9, 36(10) + \\ stw 10, 40(10) + \\ stw 11, 44(10) + \\ stw 12, 48(10) + \\ stw 13, 52(10) + \\ stw 14, 56(10) + \\ stw 15, 60(10) + \\ stw 16, 64(10) + \\ stw 17, 68(10) + \\ stw 18, 72(10) + \\ stw 19, 76(10) + \\ stw 20, 80(10) + \\ stw 21, 84(10) + \\ stw 22, 88(10) + \\ stw 23, 92(10) + \\ stw 24, 96(10) + \\ stw 25, 100(10) + \\ stw 26, 104(10) + \\ stw 27, 108(10) + \\ stw 28, 112(10) + \\ stw 29, 116(10) + \\ stw 30, 120(10) + \\ stw 31, 124(10) + \\ mflr 8 + \\ stw 8, 132(10) + \\ bl 1f + \\1: + \\ mflr 8 + \\ stw 8, 128(10) + \\ lwz 8, 32(10) + : + : [gprs] "{r10}" (&ctx), + : .{ .lr = true, .memory = true }); + return ctx; + } + + pub fn dwarfRegisterBytes(ctx: *Powerpc, register_num: u16) DwarfRegisterError![]u8 { + switch (register_num) { + 0...31 => return @ptrCast(&ctx.r[register_num]), + 65 => return @ptrCast(&ctx.lr), + 357 => return @ptrCast(&ctx.pc), + + else => return error.InvalidRegister, + } + } +}; + /// 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. -- cgit v1.2.3 From 9a6fad2706d05743a512c9ab5b54ba91cf5956fa Mon Sep 17 00:00:00 2001 From: Alex Rønne Petersen Date: Tue, 7 Oct 2025 00:39:56 +0200 Subject: std.debug.Dwarf: use 64 as the (fake) LoongArch PC register 32-63 conflict with the floating point registers. --- lib/std/debug/Dwarf.zig | 2 +- lib/std/debug/cpu_context.zig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/std/debug/Dwarf.zig') diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig index 3bc5fcf4f0..64731beac3 100644 --- a/lib/std/debug/Dwarf.zig +++ b/lib/std/debug/Dwarf.zig @@ -1432,7 +1432,7 @@ pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 { .aarch64, .aarch64_be => 32, .arm, .armeb, .thumb, .thumbeb => 15, .hexagon => 76, - .loongarch32, .loongarch64 => 32, + .loongarch32, .loongarch64 => 64, .mips, .mipsel, .mips64, .mips64el => 37, .powerpc, .powerpcle, .powerpc64, .powerpc64le => 357, .riscv32, .riscv32be, .riscv64, .riscv64be => 32, diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index bfc82f33ec..7760918389 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -700,7 +700,7 @@ pub const LoongArch = extern struct { pub fn dwarfRegisterBytes(ctx: *LoongArch, register_num: u16) DwarfRegisterError![]u8 { switch (register_num) { 0...31 => return @ptrCast(&ctx.r[register_num]), - 32 => return @ptrCast(&ctx.pc), + 64 => return @ptrCast(&ctx.pc), else => return error.InvalidRegister, } -- cgit v1.2.3 From feba8a83a7c4eda738ebcf619c33ade8d0dfbfa7 Mon Sep 17 00:00:00 2001 From: Alex Rønne Petersen Date: Tue, 7 Oct 2025 00:45:27 +0200 Subject: std.debug.Dwarf: use 65 as the (fake) RISC-V PC register 32-63 conflict with the floating point registers. 64 is the Alternate Frame Return Column. --- lib/std/debug/Dwarf.zig | 2 +- lib/std/debug/cpu_context.zig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/std/debug/Dwarf.zig') diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig index 64731beac3..4af4dd7f34 100644 --- a/lib/std/debug/Dwarf.zig +++ b/lib/std/debug/Dwarf.zig @@ -1435,7 +1435,7 @@ pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 { .loongarch32, .loongarch64 => 64, .mips, .mipsel, .mips64, .mips64el => 37, .powerpc, .powerpcle, .powerpc64, .powerpc64le => 357, - .riscv32, .riscv32be, .riscv64, .riscv64be => 32, + .riscv32, .riscv32be, .riscv64, .riscv64be => 65, .s390x => 65, .x86 => 8, .x86_64 => 16, diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 7760918389..5cd5360dc6 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -1018,7 +1018,7 @@ pub const Riscv = extern struct { 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), + 65 => return @ptrCast(&ctx.pc), else => return error.InvalidRegister, } -- cgit v1.2.3 From f6403ed5ea05bcdbb55da15ee65204b1c8cdf423 Mon Sep 17 00:00:00 2001 From: Alex Rønne Petersen Date: Tue, 7 Oct 2025 02:13:43 +0200 Subject: std.debug.Dwarf: use 67 as the (fake) PowerPC PC register It's free real estate, as it turns out. --- lib/std/debug/Dwarf.zig | 2 +- lib/std/debug/cpu_context.zig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/std/debug/Dwarf.zig') diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig index 4af4dd7f34..a6ecd07b23 100644 --- a/lib/std/debug/Dwarf.zig +++ b/lib/std/debug/Dwarf.zig @@ -1434,7 +1434,7 @@ pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 { .hexagon => 76, .loongarch32, .loongarch64 => 64, .mips, .mipsel, .mips64, .mips64el => 37, - .powerpc, .powerpcle, .powerpc64, .powerpc64le => 357, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => 67, .riscv32, .riscv32be, .riscv64, .riscv64be => 65, .s390x => 65, .x86 => 8, diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 5cd5360dc6..6243131d25 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -918,7 +918,7 @@ pub const Powerpc = extern struct { switch (register_num) { 0...31 => return @ptrCast(&ctx.r[register_num]), 65 => return @ptrCast(&ctx.lr), - 357 => return @ptrCast(&ctx.pc), + 67 => return @ptrCast(&ctx.pc), else => return error.InvalidRegister, } -- cgit v1.2.3 From 9cd37a06965f1993f6e70ca3f10008d02f77334b Mon Sep 17 00:00:00 2001 From: Alex Rønne Petersen Date: Tue, 7 Oct 2025 08:46:43 +0200 Subject: std.debug.Dwarf: use 66 as the (fake) MIPS PC register 32-63 conflict with the floating point registers. 64 and 65 are used for the ac0 hi/lo registers. --- lib/std/debug/Dwarf.zig | 2 +- lib/std/debug/cpu_context.zig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/std/debug/Dwarf.zig') diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig index a6ecd07b23..98d7addb32 100644 --- a/lib/std/debug/Dwarf.zig +++ b/lib/std/debug/Dwarf.zig @@ -1433,7 +1433,7 @@ pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 { .arm, .armeb, .thumb, .thumbeb => 15, .hexagon => 76, .loongarch32, .loongarch64 => 64, - .mips, .mipsel, .mips64, .mips64el => 37, + .mips, .mipsel, .mips64, .mips64el => 66, .powerpc, .powerpcle, .powerpc64, .powerpc64le => 67, .riscv32, .riscv32be, .riscv64, .riscv64be => 65, .s390x => 65, diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 6243131d25..b899d76f1b 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -810,7 +810,7 @@ pub const Mips = extern struct { pub fn dwarfRegisterBytes(ctx: *Mips, register_num: u16) DwarfRegisterError![]u8 { switch (register_num) { 0...31 => return @ptrCast(&ctx.r[register_num]), - 37 => return @ptrCast(&ctx.pc), + 66 => return @ptrCast(&ctx.pc), else => return error.InvalidRegister, } -- cgit v1.2.3