From 4c81a496e7c979755d9fc74734ab740a828c4491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Thu, 16 Oct 2025 17:31:55 +0200 Subject: [PATCH] std.debug: add CPU context and DWARF mappings for arc --- lib/std/debug/Dwarf.zig | 3 ++ lib/std/debug/SelfInfo/Elf.zig | 3 +- lib/std/debug/cpu_context.zig | 80 +++++++++++++++++++++++++++++++++- 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig index 8aaf85c66b..7229dcdf4c 100644 --- a/lib/std/debug/Dwarf.zig +++ b/lib/std/debug/Dwarf.zig @@ -1430,6 +1430,7 @@ pub fn compactUnwindToDwarfRegNumber(unwind_reg_number: u3) !u16 { pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 { return switch (arch) { .aarch64, .aarch64_be => 32, + .arc => 160, .arm, .armeb, .thumb, .thumbeb => 15, .csky => 64, .hexagon => 76, @@ -1452,6 +1453,7 @@ pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 { pub fn fpRegNum(arch: std.Target.Cpu.Arch) u16 { return switch (arch) { .aarch64, .aarch64_be => 29, + .arc => 27, .arm, .armeb, .thumb, .thumbeb => 11, .csky => 14, .hexagon => 30, @@ -1474,6 +1476,7 @@ pub fn fpRegNum(arch: std.Target.Cpu.Arch) u16 { pub fn spRegNum(arch: std.Target.Cpu.Arch) u16 { return switch (arch) { .aarch64, .aarch64_be => 31, + .arc => 28, .arm, .armeb, .thumb, .thumbeb => 13, .csky => 14, .hexagon => 29, diff --git a/lib/std/debug/SelfInfo/Elf.zig b/lib/std/debug/SelfInfo/Elf.zig index e25f357803..5713542510 100644 --- a/lib/std/debug/SelfInfo/Elf.zig +++ b/lib/std/debug/SelfInfo/Elf.zig @@ -102,10 +102,11 @@ pub const can_unwind: bool = s: { .x86, .x86_64, }, - // Not supported yet: arc, arm/armeb/thumb/thumbeb, xtensa + // Not supported yet: arm/armeb/thumb/thumbeb, xtensa .linux => &.{ .aarch64, .aarch64_be, + .arc, .csky, .loongarch64, .m68k, diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 1278e630ff..d46f9bd132 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -5,6 +5,7 @@ pub const Native = if (@hasDecl(root, "debug") and @hasDecl(root.debug, "CpuCont root.debug.CpuContext else switch (native_arch) { .aarch64, .aarch64_be => Aarch64, + .arc => Arc, .arm, .armeb, .thumb, .thumbeb => Arm, .csky => Csky, .hexagon => Hexagon, @@ -35,7 +36,20 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native { const uc: *const signal_ucontext_t = @ptrCast(@alignCast(ctx_ptr)); // Deal with some special cases first. - if (native_arch.isMIPS32() and native_os == .linux) { + if (native_arch == .arc and native_os == .linux) { + var native: Native = .{ + .r = [_]u32{ uc.mcontext.r31, uc.mcontext.r30, 0, uc.mcontext.r28 } ++ + uc.mcontext.r27_26 ++ + uc.mcontext.r25_13 ++ + uc.mcontext.r12_0, + .pcl = uc.mcontext.pcl, + }; + + // I have no idea why the kernel is storing these registers in such a bizarre order... + std.mem.reverse(native.r[0..]); + + return native; + } else if (native_arch.isMIPS32() and native_os == .linux) { // The O32 kABI uses 64-bit fields for some reason. return .{ .r = s: { @@ -327,6 +341,68 @@ const X86_64 = struct { } }; +/// This is an `extern struct` so that inline assembly in `current` can use field offsets. +const Arc = extern struct { + /// The numbered general-purpose registers r0 - r31. + r: [32]u32, + pcl: u32, + + pub inline fn current() Arc { + var ctx: Arc = undefined; + asm volatile ( + \\ st r0, [r8, 0] + \\ st r1, [r8, 4] + \\ st r2, [r8, 8] + \\ st r3, [r8, 12] + \\ st r4, [r8, 16] + \\ st r5, [r8, 20] + \\ st r6, [r8, 24] + \\ st r7, [r8, 28] + \\ st r8, [r8, 32] + \\ st r9, [r8, 36] + \\ st r10, [r8, 40] + \\ st r11, [r8, 44] + \\ st r12, [r8, 48] + \\ st r13, [r8, 52] + \\ st r14, [r8, 56] + \\ st r15, [r8, 60] + \\ st r16, [r8, 64] + \\ st r17, [r8, 68] + \\ st r18, [r8, 72] + \\ st r19, [r8, 76] + \\ st r20, [r8, 80] + \\ st r21, [r8, 84] + \\ st r22, [r8, 88] + \\ st r23, [r8, 92] + \\ st r24, [r8, 96] + \\ st r25, [r8, 100] + \\ st r26, [r8, 104] + \\ st r27, [r8, 108] + \\ st r28, [r8, 112] + \\ st r29, [r8, 116] + \\ st r30, [r8, 120] + \\ st r31, [r8, 124] + \\ st pcl, [r8, 128] + : + : [ctx] "{r8}" (&ctx), + : .{ .memory = true }); + return ctx; + } + + pub fn dwarfRegisterBytes(ctx: *Arc, register_num: u16) DwarfRegisterError![]u8 { + switch (register_num) { + 0...31 => return @ptrCast(&ctx.r[register_num]), + 160 => return @ptrCast(&ctx.pcl), + + 32...57 => return error.UnsupportedRegister, // Extension Core Registers + 58...127 => return error.UnsupportedRegister, // Reserved + 128...159 => return error.UnsupportedRegister, // f0 - f31 + + else => return error.InvalidRegister, + } + } +}; + const Arm = struct { /// The numbered general-purpose registers R0 - R15. r: [16]u32, @@ -1517,7 +1593,7 @@ const signal_ucontext_t = switch (native_os) { _count: u32, }, _status32: u32, - pc: u32, + pcl: u32, r31: u32, r27_26: [2]u32, r12_0: [13]u32,