Skip to content

Commit 2be97a7

Browse files
authored
Merge pull request #37 from tweedegolf/cfa-fixes
Cfa improvement + noreturn function fixes
2 parents b0dc786 + 69d68c2 commit 2be97a7

File tree

5 files changed

+36
-20
lines changed

5 files changed

+36
-20
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
## 0.10.4 (09-10-25)
6+
7+
- Made unwinding more robust, especially around `noreturn` functions
8+
59
## 0.10.3 (01-08-25)
610

711
- Fix panic where a data slice was indexed out of range

Cargo.lock

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[workspace]
22
resolver = "2"
3-
package.version = "0.10.3"
3+
package.version = "0.10.4"
44

55
members = [
66
"capture",

trace/src/platform/cortex_m/mod.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,23 @@ impl<'data> CortexMPlatform<'data> {
2828
device_memory: &mut DeviceMemory<<Self as Platform<'data>>::Word>,
2929
unwind_info: UnwindTableRow<usize>,
3030
) -> Result<bool, TraceError> {
31-
let updated = match unwind_info.cfa() {
31+
let cfa = match unwind_info.cfa() {
3232
CfaRule::RegisterAndOffset { register, offset } => {
33-
let new_cfa = (device_memory.register(*register)? as i64 + *offset) as u32;
34-
let old_cfa = device_memory.register(gimli::Arm::SP)?;
35-
let changed = new_cfa != old_cfa;
36-
*device_memory.register_mut(gimli::Arm::SP)? = new_cfa;
37-
changed
33+
(device_memory.register(*register)? as i64 + *offset) as u32
3834
}
3935
CfaRule::Expression(_) => todo!("CfaRule::Expression"),
4036
};
4137

38+
let mut sp_updated = false;
39+
4240
for (reg, rule) in unwind_info.registers() {
41+
if *reg == gimli::Arm::SP {
42+
sp_updated = true;
43+
}
44+
4345
match rule {
4446
RegisterRule::Undefined => unreachable!(),
4547
RegisterRule::Offset(offset) => {
46-
let cfa = device_memory.register(gimli::Arm::SP)?;
4748
let addr = (i64::from(cfa) + offset) as u64;
4849
let new_value = device_memory
4950
.read_u32(addr, RunTimeEndian::Little)?
@@ -54,7 +55,12 @@ impl<'data> CortexMPlatform<'data> {
5455
}
5556
}
5657

57-
Ok(updated)
58+
if !sp_updated && device_memory.register(gimli::Arm::SP)? != cfa {
59+
sp_updated = true;
60+
*device_memory.register_mut(gimli::Arm::SP)? = cfa;
61+
}
62+
63+
Ok(sp_updated)
5864
}
5965

6066
fn is_last_frame(
@@ -264,9 +270,10 @@ impl<'data> Platform<'data> for CortexMPlatform<'data> {
264270
line: None,
265271
column: None,
266272
},
267-
frame_type: FrameType::Corrupted(
268-
"CFA did not change and LR and PC are equal".into(),
269-
),
273+
frame_type: FrameType::Corrupted(format!(
274+
"CFA did not change and LR and PC are equal: {:#010X}",
275+
device_memory.register(gimli::Arm::PC)?
276+
)),
270277
variables: Vec::new(),
271278
}),
272279
});
@@ -305,8 +312,13 @@ impl<'data> Platform<'data> for CortexMPlatform<'data> {
305312
Err(e) => return Err(e),
306313
}
307314
} else {
308-
// No exception, so follow the LR back
309-
*device_memory.register_mut(gimli::Arm::PC)? = device_memory.register(gimli::Arm::LR)?
315+
// No exception, so follow the LR back, but one instruction back.
316+
// Sometimes a function will have a `bl` instruction at the end.
317+
// An example is noreturn functions.
318+
// LR always points to the next instruction, which means that it doesn't have to be in the same function as from where the branch originated.
319+
// https://lkml.kernel.org/lkml/20240305175846.qnyiru7uaa7itqba@treble/
320+
*device_memory.register_mut(gimli::Arm::PC)? =
321+
device_memory.register(gimli::Arm::LR)? - 2;
310322
}
311323

312324
// Have we reached the reset vector?

trace/src/variables/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1252,7 +1252,7 @@ where
12521252
}))
12531253
}
12541254
(Ok(variable_name), Err(type_error)) => {
1255-
log::info!(
1255+
log::debug!(
12561256
"Could not read the type of variable `{}` of entry {:X?}: {}",
12571257
variable_name,
12581258
entry.offset().to_debug_info_offset(&unit.header),

0 commit comments

Comments
 (0)