DoxigAlpha

resolveValue

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

Function parameters

Parameters

#
context:*SelfInfo.UnwindContext
expression_context:std.debug.Dwarf.expression.Context
ma:*std.debug.MemoryAccessor
out:[]u8

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