structstd.debug.SelfInfo.VirtualMachine.Column[src]

Fields

register: ?u8 = null
rule: RegisterRule = .{ .default = {} }

Functions

FunctionresolveValue[src]

pub fn resolveValue( self: Column, context: *SelfInfo.UnwindContext, expression_context: std.debug.Dwarf.expression.Context, ma: *std.debug.MemoryAccessor, out: []u8, ) !void

Resolves the register rule and places the result into out (see regBytes)

Parameters

self: Column
expression_context: std.debug.Dwarf.expression.Context
out: []u8

Source Code

Source code
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,
    }
}

Source Code

Source code
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,
        }
    }
}