Skip to content

Commit c23a5cc

Browse files
committed
std.debug.Dwarf.SelfUnwinder: skip caching rules for unsupported registers
For unwinding purposes, we don't care about unsupported registers. Yet because we added these rules to the cache entry, we'd later try to evaluate them and thus fail the unwind attempt for no good reason. They'd also take up cache rule slots that would be better spent on actually relevant registers. Note that any attempt to read unsupported registers during unwinding will still fail the unwind attempt as expected.
1 parent 6893e7f commit c23a5cc

File tree

1 file changed

+16
-8
lines changed

1 file changed

+16
-8
lines changed

lib/std/debug/Dwarf/SelfUnwinder.zig

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ cfi_vm: Dwarf.Unwind.VirtualMachine,
1515
expr_vm: Dwarf.expression.StackMachine(.{ .call_frame_context = true }),
1616

1717
pub const CacheEntry = struct {
18-
const max_regs = 32;
18+
const max_rules = 32;
1919

2020
pc: usize,
2121
cie: *const Dwarf.Unwind.CommonInformationEntry,
2222
cfa_rule: Dwarf.Unwind.VirtualMachine.CfaRule,
2323
num_rules: u8,
24-
rules_regs: [max_regs]u16,
25-
rules: [max_regs]Dwarf.Unwind.VirtualMachine.RegisterRule,
24+
rules_regs: [max_rules]u16,
25+
rules: [max_rules]Dwarf.Unwind.VirtualMachine.RegisterRule,
2626

2727
pub fn find(entries: []const CacheEntry, pc: usize) ?*const CacheEntry {
2828
assert(pc != 0);
@@ -108,22 +108,30 @@ pub fn computeRules(
108108

109109
unwinder.cfi_vm.reset();
110110
const row = try unwinder.cfi_vm.runTo(gpa, pc_vaddr, cie, &fde, @sizeOf(usize), native_endian);
111-
const cols = unwinder.cfi_vm.rowColumns(&row);
112-
113-
if (cols.len > CacheEntry.max_regs) return error.UnsupportedDebugInfo;
114111

115112
var entry: CacheEntry = .{
116113
.pc = unwinder.pc,
117114
.cie = cie,
118115
.cfa_rule = row.cfa,
119-
.num_rules = @intCast(cols.len),
116+
.num_rules = undefined,
120117
.rules_regs = undefined,
121118
.rules = undefined,
122119
};
123-
for (cols, 0..) |col, i| {
120+
var i: usize = 0;
121+
for (unwinder.cfi_vm.rowColumns(&row)) |col| {
122+
if (i == CacheEntry.max_rules) return error.UnsupportedDebugInfo;
123+
124+
_ = unwinder.cpu_state.dwarfRegisterBytes(col.register) catch |err| switch (err) {
125+
// Reading an unsupported register during unwinding will result in an error, so there is
126+
// no point wasting a rule slot in the cache entry for it.
127+
error.UnsupportedRegister => continue,
128+
error.InvalidRegister => return error.InvalidDebugInfo,
129+
};
124130
entry.rules_regs[i] = col.register;
125131
entry.rules[i] = col.rule;
132+
i += 1;
126133
}
134+
entry.num_rules = @intCast(i);
127135
return entry;
128136
}
129137

0 commit comments

Comments
 (0)