Function step [src]

Executes a single instruction. If this instruction is from the CIE, is_initial should be set. Returns the value of current_row before executing this instruction.

Prototype

pub fn step( self: *VirtualMachine, allocator: std.mem.Allocator, cie: std.debug.Dwarf.CommonInformationEntry, is_initial: bool, instruction: Dwarf.call_frame.Instruction, ) !Row

Parameters

self: *VirtualMachineallocator: std.mem.Allocatorcie: std.debug.Dwarf.CommonInformationEntryis_initial: boolinstruction: Dwarf.call_frame.Instruction

Source

pub fn step( self: *VirtualMachine, allocator: std.mem.Allocator, cie: std.debug.Dwarf.CommonInformationEntry, is_initial: bool, instruction: Dwarf.call_frame.Instruction, ) !Row { // CIE instructions must be run before FDE instructions assert(!is_initial or self.cie_row == null); if (!is_initial and self.cie_row == null) { self.cie_row = self.current_row; self.current_row.copy_on_write = true; } const prev_row = self.current_row; switch (instruction) { .set_loc => |i| { if (i.address <= self.current_row.offset) return error.InvalidOperation; // TODO: Check cie.segment_selector_size != 0 for DWARFV4 self.current_row.offset = i.address; }, inline .advance_loc, .advance_loc1, .advance_loc2, .advance_loc4, => |i| { self.current_row.offset += i.delta * cie.code_alignment_factor; self.current_row.copy_on_write = true; }, inline .offset, .offset_extended, .offset_extended_sf, => |i| { try self.resolveCopyOnWrite(allocator); const column = try self.getOrAddColumn(allocator, i.register); column.rule = .{ .offset = @as(i64, @intCast(i.offset)) * cie.data_alignment_factor }; }, inline .restore, .restore_extended, => |i| { try self.resolveCopyOnWrite(allocator); if (self.cie_row) |cie_row| { const column = try self.getOrAddColumn(allocator, i.register); column.rule = for (self.rowColumns(cie_row)) |cie_column| { if (cie_column.register == i.register) break cie_column.rule; } else .{ .default = {} }; } else return error.InvalidOperation; }, .nop => {}, .undefined => |i| { try self.resolveCopyOnWrite(allocator); const column = try self.getOrAddColumn(allocator, i.register); column.rule = .{ .undefined = {} }; }, .same_value => |i| { try self.resolveCopyOnWrite(allocator); const column = try self.getOrAddColumn(allocator, i.register); column.rule = .{ .same_value = {} }; }, .register => |i| { try self.resolveCopyOnWrite(allocator); const column = try self.getOrAddColumn(allocator, i.register); column.rule = .{ .register = i.target_register }; }, .remember_state => { try self.stack.append(allocator, self.current_row.columns); self.current_row.copy_on_write = true; }, .restore_state => { const restored_columns = self.stack.pop() orelse return error.InvalidOperation; self.columns.shrinkRetainingCapacity(self.columns.items.len - self.current_row.columns.len); try self.columns.ensureUnusedCapacity(allocator, restored_columns.len); self.current_row.columns.start = self.columns.items.len; self.current_row.columns.len = restored_columns.len; self.columns.appendSliceAssumeCapacity(self.columns.items[restored_columns.start..][0..restored_columns.len]); }, .def_cfa => |i| { try self.resolveCopyOnWrite(allocator); self.current_row.cfa = .{ .register = i.register, .rule = .{ .val_offset = @intCast(i.offset) }, }; }, .def_cfa_sf => |i| { try self.resolveCopyOnWrite(allocator); self.current_row.cfa = .{ .register = i.register, .rule = .{ .val_offset = i.offset * cie.data_alignment_factor }, }; }, .def_cfa_register => |i| { try self.resolveCopyOnWrite(allocator); if (self.current_row.cfa.register == null or self.current_row.cfa.rule != .val_offset) return error.InvalidOperation; self.current_row.cfa.register = i.register; }, .def_cfa_offset => |i| { try self.resolveCopyOnWrite(allocator); if (self.current_row.cfa.register == null or self.current_row.cfa.rule != .val_offset) return error.InvalidOperation; self.current_row.cfa.rule = .{ .val_offset = @intCast(i.offset), }; }, .def_cfa_offset_sf => |i| { try self.resolveCopyOnWrite(allocator); if (self.current_row.cfa.register == null or self.current_row.cfa.rule != .val_offset) return error.InvalidOperation; self.current_row.cfa.rule = .{ .val_offset = i.offset * cie.data_alignment_factor, }; }, .def_cfa_expression => |i| { try self.resolveCopyOnWrite(allocator); self.current_row.cfa.register = undefined; self.current_row.cfa.rule = .{ .expression = i.block, }; }, .expression => |i| { try self.resolveCopyOnWrite(allocator); const column = try self.getOrAddColumn(allocator, i.register); column.rule = .{ .expression = i.block, }; }, .val_offset => |i| { try self.resolveCopyOnWrite(allocator); const column = try self.getOrAddColumn(allocator, i.register); column.rule = .{ .val_offset = @as(i64, @intCast(i.offset)) * cie.data_alignment_factor, }; }, .val_offset_sf => |i| { try self.resolveCopyOnWrite(allocator); const column = try self.getOrAddColumn(allocator, i.register); column.rule = .{ .val_offset = i.offset * cie.data_alignment_factor, }; }, .val_expression => |i| { try self.resolveCopyOnWrite(allocator); const column = try self.getOrAddColumn(allocator, i.register); column.rule = .{ .val_expression = i.block, }; }, } return prev_row; }