@@ -175,7 +175,6 @@ pub fn next(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheEn
175
175
176
176
fn nextInner (unwinder : * SelfUnwinder , gpa : Allocator , cache_entry : * const CacheEntry ) ! usize {
177
177
const format = cache_entry .cie .format ;
178
- const return_address_register = cache_entry .cie .return_address_register ;
179
178
180
179
const cfa = switch (cache_entry .cfa_rule ) {
181
180
.none = > return error .InvalidDebugInfo ,
@@ -202,17 +201,6 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
202
201
},
203
202
};
204
203
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
-
216
204
// Create a copy of the CPU state, to which we will apply the new rules.
217
205
var new_cpu_state = unwinder .cpu_state ;
218
206
@@ -228,13 +216,14 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
228
216
bytes : []const u8 ,
229
217
} = switch (rule ) {
230
218
.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 ;
238
227
},
239
228
.undefined = > .undefined ,
240
229
.same_value = > .same ,
@@ -286,15 +275,11 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
286
275
@memcpy (dest , src );
287
276
},
288
277
}
289
- if (register == return_address_register ) {
290
- has_return_address = new_val != .undefined ;
291
- }
292
278
}
293
279
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
+ );
298
283
299
284
(try regNative (& new_cpu_state , ip_reg_num )).* = return_address ;
300
285
0 commit comments