Skip to content

Commit 953e6e7

Browse files
committed
std.debug.Dwarf.SelfUnwinder: assume same-value rule by default for all columns
This fixes leaf function unwinding, presumably among other things.
1 parent 60a3324 commit 953e6e7

File tree

1 file changed

+11
-26
lines changed

1 file changed

+11
-26
lines changed

lib/std/debug/Dwarf/SelfUnwinder.zig

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,6 @@ pub fn next(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheEn
175175

176176
fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheEntry) !usize {
177177
const format = cache_entry.cie.format;
178-
const return_address_register = cache_entry.cie.return_address_register;
179178

180179
const cfa = switch (cache_entry.cfa_rule) {
181180
.none => return error.InvalidDebugInfo,
@@ -202,17 +201,6 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
202201
},
203202
};
204203

205-
// If unspecified, we'll use the default rule for the return address register, which is
206-
// typically equivalent to `.undefined` (meaning there is no return address), but may be
207-
// overriden by ABIs.
208-
var has_return_address: bool = switch (builtin.cpu.arch) {
209-
// DWARF for the Arm 64-bit Architecture (AArch64) §4.3, p1
210-
.aarch64, .aarch64_be => return_address_register >= 19 and return_address_register <= 28,
211-
// ELF ABI s390x Supplement §1.6.4
212-
.s390x => return_address_register >= 6 and return_address_register <= 15,
213-
else => false,
214-
};
215-
216204
// Create a copy of the CPU state, to which we will apply the new rules.
217205
var new_cpu_state = unwinder.cpu_state;
218206

@@ -228,13 +216,14 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
228216
bytes: []const u8,
229217
} = switch (rule) {
230218
.default => val: {
231-
// The default rule is typically equivalent to `.undefined`, but ABIs may override it.
232-
switch (builtin.target.cpu.arch) {
233-
.aarch64, .aarch64_be => if (register >= 19 and register <= 28) break :val .same,
234-
.s390x => if (register >= 6 and register <= 15) break :val .same,
235-
else => {},
236-
}
237-
break :val .undefined;
219+
// The way things are supposed to work is that `.undefined` is the default rule
220+
// unless an ABI says otherwise (e.g. aarch64, s390x).
221+
//
222+
// Unfortunately, at some point, a decision was made to have libgcc's unwinder
223+
// assume `.same` as the default for all registers. Compilers then started depending
224+
// on this, and the practice was carried forward to LLVM's libunwind and some of its
225+
// backends.
226+
break :val .same;
238227
},
239228
.undefined => .undefined,
240229
.same_value => .same,
@@ -286,15 +275,11 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
286275
@memcpy(dest, src);
287276
},
288277
}
289-
if (register == return_address_register) {
290-
has_return_address = new_val != .undefined;
291-
}
292278
}
293279

294-
const return_address: usize = if (has_return_address) pc: {
295-
const raw_ptr = try regNative(&new_cpu_state, return_address_register);
296-
break :pc stripInstructionPtrAuthCode(raw_ptr.*);
297-
} else 0;
280+
const return_address = stripInstructionPtrAuthCode(
281+
(try regNative(&new_cpu_state, cache_entry.cie.return_address_register)).*,
282+
);
298283

299284
(try regNative(&new_cpu_state, ip_reg_num)).* = return_address;
300285

0 commit comments

Comments
 (0)