@@ -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?
0 commit comments