Function regBytes [src]

Returns a slice containing the backing storage for reg_number. This function assumes the Dwarf information corresponds not necessarily to the current executable, but at least with a matching CPU architecture and OS. It is planned to lift this limitation with a future enhancement. reg_context describes in what context the register number is used, as it can have different meanings depending on the DWARF container. It is only required when getting the stack or frame pointer register on some architectures.

Prototype

pub fn regBytes( thread_context_ptr: *std.debug.ThreadContext, reg_number: u8, reg_context: ?RegisterContext, ) RegBytesError![]u8

Parameters

thread_context_ptr: *std.debug.ThreadContextreg_number: u8reg_context: ?RegisterContext

Possible Errors

InvalidRegister
RegisterContextRequired
ThreadContextNotSupported
UnimplementedArch
UnimplementedOs

Source

pub fn regBytes( thread_context_ptr: *std.debug.ThreadContext, reg_number: u8, reg_context: ?RegisterContext, ) RegBytesError![]u8 { if (builtin.os.tag == .windows) { return switch (builtin.cpu.arch) { .x86 => switch (reg_number) { 0 => mem.asBytes(&thread_context_ptr.Eax), 1 => mem.asBytes(&thread_context_ptr.Ecx), 2 => mem.asBytes(&thread_context_ptr.Edx), 3 => mem.asBytes(&thread_context_ptr.Ebx), 4 => mem.asBytes(&thread_context_ptr.Esp), 5 => mem.asBytes(&thread_context_ptr.Ebp), 6 => mem.asBytes(&thread_context_ptr.Esi), 7 => mem.asBytes(&thread_context_ptr.Edi), 8 => mem.asBytes(&thread_context_ptr.Eip), 9 => mem.asBytes(&thread_context_ptr.EFlags), 10 => mem.asBytes(&thread_context_ptr.SegCs), 11 => mem.asBytes(&thread_context_ptr.SegSs), 12 => mem.asBytes(&thread_context_ptr.SegDs), 13 => mem.asBytes(&thread_context_ptr.SegEs), 14 => mem.asBytes(&thread_context_ptr.SegFs), 15 => mem.asBytes(&thread_context_ptr.SegGs), else => error.InvalidRegister, }, .x86_64 => switch (reg_number) { 0 => mem.asBytes(&thread_context_ptr.Rax), 1 => mem.asBytes(&thread_context_ptr.Rdx), 2 => mem.asBytes(&thread_context_ptr.Rcx), 3 => mem.asBytes(&thread_context_ptr.Rbx), 4 => mem.asBytes(&thread_context_ptr.Rsi), 5 => mem.asBytes(&thread_context_ptr.Rdi), 6 => mem.asBytes(&thread_context_ptr.Rbp), 7 => mem.asBytes(&thread_context_ptr.Rsp), 8 => mem.asBytes(&thread_context_ptr.R8), 9 => mem.asBytes(&thread_context_ptr.R9), 10 => mem.asBytes(&thread_context_ptr.R10), 11 => mem.asBytes(&thread_context_ptr.R11), 12 => mem.asBytes(&thread_context_ptr.R12), 13 => mem.asBytes(&thread_context_ptr.R13), 14 => mem.asBytes(&thread_context_ptr.R14), 15 => mem.asBytes(&thread_context_ptr.R15), 16 => mem.asBytes(&thread_context_ptr.Rip), else => error.InvalidRegister, }, .aarch64, .aarch64_be => switch (reg_number) { 0...30 => mem.asBytes(&thread_context_ptr.DUMMYUNIONNAME.X[reg_number]), 31 => mem.asBytes(&thread_context_ptr.Sp), 32 => mem.asBytes(&thread_context_ptr.Pc), else => error.InvalidRegister, }, else => error.UnimplementedArch, }; } if (!std.debug.have_ucontext) return error.ThreadContextNotSupported; const ucontext_ptr = thread_context_ptr; return switch (builtin.cpu.arch) { .x86 => switch (builtin.os.tag) { .linux, .netbsd, .solaris, .illumos => switch (reg_number) { 0 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.EAX]), 1 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.ECX]), 2 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.EDX]), 3 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.EBX]), 4...5 => if (reg_context) |r| bytes: { if (reg_number == 4) { break :bytes if (r.eh_frame and r.is_macho) mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.EBP]) else mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.ESP]); } else { break :bytes if (r.eh_frame and r.is_macho) mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.ESP]) else mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.EBP]); } } else error.RegisterContextRequired, 6 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.ESI]), 7 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.EDI]), 8 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.EIP]), 9 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.EFL]), 10 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.CS]), 11 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.SS]), 12 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.DS]), 13 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.ES]), 14 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.FS]), 15 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.GS]), 16...23 => error.InvalidRegister, // TODO: Support loading ST0-ST7 from mcontext.fpregs 32...39 => error.InvalidRegister, // TODO: Support loading XMM0-XMM7 from mcontext.fpregs else => error.InvalidRegister, }, else => error.UnimplementedOs, }, .x86_64 => switch (builtin.os.tag) { .linux, .solaris, .illumos => switch (reg_number) { 0 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.RAX]), 1 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.RDX]), 2 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.RCX]), 3 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.RBX]), 4 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.RSI]), 5 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.RDI]), 6 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.RBP]), 7 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.RSP]), 8 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.R8]), 9 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.R9]), 10 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.R10]), 11 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.R11]), 12 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.R12]), 13 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.R13]), 14 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.R14]), 15 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.R15]), 16 => mem.asBytes(&ucontext_ptr.mcontext.gregs[posix.REG.RIP]), 17...32 => |i| if (builtin.os.tag.isSolarish()) mem.asBytes(&ucontext_ptr.mcontext.fpregs.chip_state.xmm[i - 17]) else mem.asBytes(&ucontext_ptr.mcontext.fpregs.xmm[i - 17]), else => error.InvalidRegister, }, .freebsd => switch (reg_number) { 0 => mem.asBytes(&ucontext_ptr.mcontext.rax), 1 => mem.asBytes(&ucontext_ptr.mcontext.rdx), 2 => mem.asBytes(&ucontext_ptr.mcontext.rcx), 3 => mem.asBytes(&ucontext_ptr.mcontext.rbx), 4 => mem.asBytes(&ucontext_ptr.mcontext.rsi), 5 => mem.asBytes(&ucontext_ptr.mcontext.rdi), 6 => mem.asBytes(&ucontext_ptr.mcontext.rbp), 7 => mem.asBytes(&ucontext_ptr.mcontext.rsp), 8 => mem.asBytes(&ucontext_ptr.mcontext.r8), 9 => mem.asBytes(&ucontext_ptr.mcontext.r9), 10 => mem.asBytes(&ucontext_ptr.mcontext.r10), 11 => mem.asBytes(&ucontext_ptr.mcontext.r11), 12 => mem.asBytes(&ucontext_ptr.mcontext.r12), 13 => mem.asBytes(&ucontext_ptr.mcontext.r13), 14 => mem.asBytes(&ucontext_ptr.mcontext.r14), 15 => mem.asBytes(&ucontext_ptr.mcontext.r15), 16 => mem.asBytes(&ucontext_ptr.mcontext.rip), // TODO: Extract xmm state from mcontext.fpstate? else => error.InvalidRegister, }, .openbsd => switch (reg_number) { 0 => mem.asBytes(&ucontext_ptr.sc_rax), 1 => mem.asBytes(&ucontext_ptr.sc_rdx), 2 => mem.asBytes(&ucontext_ptr.sc_rcx), 3 => mem.asBytes(&ucontext_ptr.sc_rbx), 4 => mem.asBytes(&ucontext_ptr.sc_rsi), 5 => mem.asBytes(&ucontext_ptr.sc_rdi), 6 => mem.asBytes(&ucontext_ptr.sc_rbp), 7 => mem.asBytes(&ucontext_ptr.sc_rsp), 8 => mem.asBytes(&ucontext_ptr.sc_r8), 9 => mem.asBytes(&ucontext_ptr.sc_r9), 10 => mem.asBytes(&ucontext_ptr.sc_r10), 11 => mem.asBytes(&ucontext_ptr.sc_r11), 12 => mem.asBytes(&ucontext_ptr.sc_r12), 13 => mem.asBytes(&ucontext_ptr.sc_r13), 14 => mem.asBytes(&ucontext_ptr.sc_r14), 15 => mem.asBytes(&ucontext_ptr.sc_r15), 16 => mem.asBytes(&ucontext_ptr.sc_rip), // TODO: Extract xmm state from sc_fpstate? else => error.InvalidRegister, }, .macos, .ios => switch (reg_number) { 0 => mem.asBytes(&ucontext_ptr.mcontext.ss.rax), 1 => mem.asBytes(&ucontext_ptr.mcontext.ss.rdx), 2 => mem.asBytes(&ucontext_ptr.mcontext.ss.rcx), 3 => mem.asBytes(&ucontext_ptr.mcontext.ss.rbx), 4 => mem.asBytes(&ucontext_ptr.mcontext.ss.rsi), 5 => mem.asBytes(&ucontext_ptr.mcontext.ss.rdi), 6 => mem.asBytes(&ucontext_ptr.mcontext.ss.rbp), 7 => mem.asBytes(&ucontext_ptr.mcontext.ss.rsp), 8 => mem.asBytes(&ucontext_ptr.mcontext.ss.r8), 9 => mem.asBytes(&ucontext_ptr.mcontext.ss.r9), 10 => mem.asBytes(&ucontext_ptr.mcontext.ss.r10), 11 => mem.asBytes(&ucontext_ptr.mcontext.ss.r11), 12 => mem.asBytes(&ucontext_ptr.mcontext.ss.r12), 13 => mem.asBytes(&ucontext_ptr.mcontext.ss.r13), 14 => mem.asBytes(&ucontext_ptr.mcontext.ss.r14), 15 => mem.asBytes(&ucontext_ptr.mcontext.ss.r15), 16 => mem.asBytes(&ucontext_ptr.mcontext.ss.rip), else => error.InvalidRegister, }, else => error.UnimplementedOs, }, .arm, .armeb, .thumb, .thumbeb => switch (builtin.os.tag) { .linux => switch (reg_number) { 0 => mem.asBytes(&ucontext_ptr.mcontext.arm_r0), 1 => mem.asBytes(&ucontext_ptr.mcontext.arm_r1), 2 => mem.asBytes(&ucontext_ptr.mcontext.arm_r2), 3 => mem.asBytes(&ucontext_ptr.mcontext.arm_r3), 4 => mem.asBytes(&ucontext_ptr.mcontext.arm_r4), 5 => mem.asBytes(&ucontext_ptr.mcontext.arm_r5), 6 => mem.asBytes(&ucontext_ptr.mcontext.arm_r6), 7 => mem.asBytes(&ucontext_ptr.mcontext.arm_r7), 8 => mem.asBytes(&ucontext_ptr.mcontext.arm_r8), 9 => mem.asBytes(&ucontext_ptr.mcontext.arm_r9), 10 => mem.asBytes(&ucontext_ptr.mcontext.arm_r10), 11 => mem.asBytes(&ucontext_ptr.mcontext.arm_fp), 12 => mem.asBytes(&ucontext_ptr.mcontext.arm_ip), 13 => mem.asBytes(&ucontext_ptr.mcontext.arm_sp), 14 => mem.asBytes(&ucontext_ptr.mcontext.arm_lr), 15 => mem.asBytes(&ucontext_ptr.mcontext.arm_pc), // CPSR is not allocated a register number (See: https://github.com/ARM-software/abi-aa/blob/main/aadwarf32/aadwarf32.rst, Section 4.1) else => error.InvalidRegister, }, else => error.UnimplementedOs, }, .aarch64, .aarch64_be => switch (builtin.os.tag) { .macos, .ios, .watchos => switch (reg_number) { 0...28 => mem.asBytes(&ucontext_ptr.mcontext.ss.regs[reg_number]), 29 => mem.asBytes(&ucontext_ptr.mcontext.ss.fp), 30 => mem.asBytes(&ucontext_ptr.mcontext.ss.lr), 31 => mem.asBytes(&ucontext_ptr.mcontext.ss.sp), 32 => mem.asBytes(&ucontext_ptr.mcontext.ss.pc), // TODO: Find storage for this state //34 => mem.asBytes(&ucontext_ptr.ra_sign_state), // V0-V31 64...95 => mem.asBytes(&ucontext_ptr.mcontext.ns.q[reg_number - 64]), else => error.InvalidRegister, }, .netbsd => switch (reg_number) { 0...34 => mem.asBytes(&ucontext_ptr.mcontext.gregs[reg_number]), else => error.InvalidRegister, }, .freebsd => switch (reg_number) { 0...29 => mem.asBytes(&ucontext_ptr.mcontext.gpregs.x[reg_number]), 30 => mem.asBytes(&ucontext_ptr.mcontext.gpregs.lr), 31 => mem.asBytes(&ucontext_ptr.mcontext.gpregs.sp), // TODO: This seems wrong, but it was in the previous debug.zig code for mapping PC, check this 32 => mem.asBytes(&ucontext_ptr.mcontext.gpregs.elr), else => error.InvalidRegister, }, .openbsd => switch (reg_number) { 0...30 => mem.asBytes(&ucontext_ptr.sc_x[reg_number]), 31 => mem.asBytes(&ucontext_ptr.sc_sp), 32 => mem.asBytes(&ucontext_ptr.sc_lr), 33 => mem.asBytes(&ucontext_ptr.sc_elr), 34 => mem.asBytes(&ucontext_ptr.sc_spsr), else => error.InvalidRegister, }, else => switch (reg_number) { 0...30 => mem.asBytes(&ucontext_ptr.mcontext.regs[reg_number]), 31 => mem.asBytes(&ucontext_ptr.mcontext.sp), 32 => mem.asBytes(&ucontext_ptr.mcontext.pc), else => error.InvalidRegister, }, }, else => error.UnimplementedArch, }; }