resolveValue
Resolves the register rule and places the result into out (see regBytes)
Function parameters
Parameters
How is this different than `Module` when the host is Windows?
Types
- WindowsModule
- How is this different than `Module` when the host is Windows?
- VirtualMachine
- This is a virtual machine that runs DWARF call frame instructions.
Functions in this namespace
Functions
- readElfDebugInfo
- Reads debug info from an ELF file, or the current binary if none in specified.
- unwindFrameMachO
- Unwind a frame using MachO compact unwind info (from __unwind_info).
- stripInstructionPtrAuthCode
- Some platforms use pointer authentication - the upper bits of instruction pointers contain a signature.
- unwindFrameDwarf
- Unwind a stack frame using DWARF unwinding info, updating the register context.
- supportsUnwinding
- Tells whether unwinding for this target is *implemented* here in the Zig
Error sets in this namespace
Error Sets
Tells whether unwinding for the host is implemented.
Values
- supports_unwinding
- Tells whether unwinding for the host is implemented.
Source
Implementation
pub fn resolveValue(
self: Column,
context: *SelfInfo.UnwindContext,
expression_context: std.debug.Dwarf.expression.Context,
ma: *std.debug.MemoryAccessor,
out: []u8,
) !void {
switch (self.rule) {
.default => {
const register = self.register orelse return error.InvalidRegister;
try getRegDefaultValue(register, context, out);
},
.undefined => {
@memset(out, undefined);
},
.same_value => {
// TODO: This copy could be eliminated if callers always copy the state then call this function to update it
const register = self.register orelse return error.InvalidRegister;
const src = try regBytes(context.thread_context, register, context.reg_context);
if (src.len != out.len) return error.RegisterSizeMismatch;
@memcpy(out, src);
},
.offset => |offset| {
if (context.cfa) |cfa| {
const addr = try applyOffset(cfa, offset);
if (ma.load(usize, addr) == null) return error.InvalidAddress;
const ptr: *const usize = @ptrFromInt(addr);
mem.writeInt(usize, out[0..@sizeOf(usize)], ptr.*, native_endian);
} else return error.InvalidCFA;
},
.val_offset => |offset| {
if (context.cfa) |cfa| {
mem.writeInt(usize, out[0..@sizeOf(usize)], try applyOffset(cfa, offset), native_endian);
} else return error.InvalidCFA;
},
.register => |register| {
const src = try regBytes(context.thread_context, register, context.reg_context);
if (src.len != out.len) return error.RegisterSizeMismatch;
@memcpy(out, try regBytes(context.thread_context, register, context.reg_context));
},
.expression => |expression| {
context.stack_machine.reset();
const value = try context.stack_machine.run(expression, context.allocator, expression_context, context.cfa.?);
const addr = if (value) |v| blk: {
if (v != .generic) return error.InvalidExpressionValue;
break :blk v.generic;
} else return error.NoExpressionValue;
if (ma.load(usize, addr) == null) return error.InvalidExpressionAddress;
const ptr: *usize = @ptrFromInt(addr);
mem.writeInt(usize, out[0..@sizeOf(usize)], ptr.*, native_endian);
},
.val_expression => |expression| {
context.stack_machine.reset();
const value = try context.stack_machine.run(expression, context.allocator, expression_context, context.cfa.?);
if (value) |v| {
if (v != .generic) return error.InvalidExpressionValue;
mem.writeInt(usize, out[0..@sizeOf(usize)], v.generic, native_endian);
} else return error.NoExpressionValue;
},
.architectural => return error.UnimplementedRegisterRule,
}
}