struct Column [src]
Fields
register: ?u8 = null
rule: RegisterRule = .{ .default = {} }
Members
- resolveValue (Function)
Source
pub const Column = struct {
register: ?u8 = null,
rule: RegisterRule = .{ .default = {} },
/// Resolves the register rule and places the result into `out` (see regBytes)
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,
}
}
}