probe-rs: jlink: stack overflow on fault, endless calls to `DAPAccess:write_register`

DAPAccess::write_register calls itself on fault, which can in turn fault again, leading to infinite stack overflow.

https://github.com/probe-rs/probe-rs/blob/9a10a0c0c439b64a597c576209164f1f8ad4033b/probe-rs/src/probe/jlink/swd.rs#L737

logs: logs2.txt.gz backtrace:

(... many lines like this..)
#3439 0x0000555555ab3178 in probe_rs::probe::jlink::swd::{{impl}}::write_register<probe_rs::probe::jlink::JLink> (self=0x555555fec830, port=..., address=0, value=16) at /home/dirbaio/rp/probe-rs/probe-rs/src/probe/jlink/swd.rs:795
#3440 0x0000555555ab3178 in probe_rs::probe::jlink::swd::{{impl}}::write_register<probe_rs::probe::jlink::JLink> (self=0x555555fec830, port=..., address=0, value=16) at /home/dirbaio/rp/probe-rs/probe-rs/src/probe/jlink/swd.rs:795
#3441 0x0000555555ab3178 in probe_rs::probe::jlink::swd::{{impl}}::write_register<probe_rs::probe::jlink::JLink> (self=0x555555fec830, port=..., address=0, value=16) at /home/dirbaio/rp/probe-rs/probe-rs/src/probe/jlink/swd.rs:795
#3442 0x0000555555ab3178 in probe_rs::probe::jlink::swd::{{impl}}::write_register<probe_rs::probe::jlink::JLink> (self=0x555555fec830, port=..., address=0, value=16) at /home/dirbaio/rp/probe-rs/probe-rs/src/probe/jlink/swd.rs:795
#3443 0x0000555555ab3178 in probe_rs::probe::jlink::swd::{{impl}}::write_register<probe_rs::probe::jlink::JLink> (self=0x555555fec830, port=..., address=0, value=16) at /home/dirbaio/rp/probe-rs/probe-rs/src/probe/jlink/swd.rs:795
#3444 0x0000555555ab3178 in probe_rs::probe::jlink::swd::{{impl}}::write_register<probe_rs::probe::jlink::JLink> (self=0x555555fec830, port=..., address=0, value=16) at /home/dirbaio/rp/probe-rs/probe-rs/src/probe/jlink/swd.rs:795
#3445 0x0000555555ab3178 in probe_rs::probe::jlink::swd::{{impl}}::write_register<probe_rs::probe::jlink::JLink> (self=0x555555fec830, port=..., address=0, value=16) at /home/dirbaio/rp/probe-rs/probe-rs/src/probe/jlink/swd.rs:795
#3446 0x0000555555ab3178 in probe_rs::probe::jlink::swd::{{impl}}::write_register<probe_rs::probe::jlink::JLink> (self=0x555555fec830, port=..., address=0, value=16) at /home/dirbaio/rp/probe-rs/probe-rs/src/probe/jlink/swd.rs:795
#3447 0x0000555555ab3178 in probe_rs::probe::jlink::swd::{{impl}}::write_register<probe_rs::probe::jlink::JLink> (self=0x555555fec830, port=..., address=0, value=16) at /home/dirbaio/rp/probe-rs/probe-rs/src/probe/jlink/swd.rs:795
#3448 0x0000555555ab3178 in probe_rs::probe::jlink::swd::{{impl}}::write_register<probe_rs::probe::jlink::JLink> (self=0x555555fec830, port=..., address=0, value=16) at /home/dirbaio/rp/probe-rs/probe-rs/src/probe/jlink/swd.rs:795
#3449 0x0000555555ab3178 in probe_rs::probe::jlink::swd::{{impl}}::write_register<probe_rs::probe::jlink::JLink> (self=0x555555fec830, port=..., address=4, value=3758157296) at /home/dirbaio/rp/probe-rs/probe-rs/src/probe/jlink/swd.rs:795
#3450 0x0000555555a7154f in probe_rs::architecture::arm::communication_interface::ArmCommunicationInterface::write_ap_register<probe_rs::architecture::arm::ap::memory_ap::MemoryAP,probe_rs::architecture::arm::ap::memory_ap::TAR,probe_rs::architecture::arm::ap::memory_ap::MemoryAP> (self=0x555555fd74f0, port=..., register=...) at /home/dirbaio/rp/probe-rs/probe-rs/src/architecture/arm/communication_interface.rs:422
#3451 0x0000555555a789b1 in probe_rs::architecture::arm::communication_interface::{{impl}}::write_ap_register<probe_rs::architecture::arm::ap::memory_ap::TAR,probe_rs::architecture::arm::ap::memory_ap::MemoryAP> (self=0x555555fd74f0, port=..., register=...) at /home/dirbaio/rp/probe-rs/probe-rs/src/architecture/arm/communication_interface.rs:670
#3452 0x0000555555a68e82 in probe_rs::architecture::arm::memory::adi_v5_memory_interface::ADIMemoryInterface<probe_rs::architecture::arm::communication_interface::ArmCommunicationInterface>::write_ap_register<probe_rs::architecture::arm::communication_interface::ArmCommunicationInterface,probe_rs::architecture::arm::ap::memory_ap::TAR> (self=0x555555fd84f0, access_port=..., register=...) at /home/dirbaio/rp/probe-rs/probe-rs/src/architecture/arm/memory/adi_v5_memory_interface.rs:191
#3453 0x0000555555a6922a in probe_rs::architecture::arm::memory::adi_v5_memory_interface::ADIMemoryInterface<probe_rs::architecture::arm::communication_interface::ArmCommunicationInterface>::read_word_32<probe_rs::architecture::arm::communication_interface::ArmCommunicationInterface> (self=0x555555fd84f0, access_port=..., address=3758157296) at /home/dirbaio/rp/probe-rs/probe-rs/src/architecture/arm/memory/adi_v5_memory_interface.rs:231
#3454 0x0000555555a6eb5b in probe_rs::architecture::arm::memory::adi_v5_memory_interface::{{impl}}::read_32<probe_rs::architecture::arm::communication_interface::ArmCommunicationInterface> (self=0x555555fd84f0, ap=..., address=3758157296, data=...) at /home/dirbaio/rp/probe-rs/probe-rs/src/architecture/arm/memory/adi_v5_memory_interface.rs:651
#3455 0x0000555555a94e59 in probe_rs::memory::Memory::read_word_32 (self=0x7fffffff5ff8, address=3758157296) at /home/dirbaio/rp/probe-rs/probe-rs/src/memory/mod.rs:113
#3456 0x0000555555a548ab in probe_rs::architecture::arm::core::m0::M0::new (memory=..., state=0x555555fd8701) at /home/dirbaio/rp/probe-rs/probe-rs/src/architecture/arm/core/m0.rs:274
#3457 0x00005555559f05b7 in probe_rs::core::SpecificCoreState::attach_arm (self=0x555555fd8700, state=0x555555fd8708, memory=...) at /home/dirbaio/rp/probe-rs/probe-rs/src/core/mod.rs:307
#3458 0x0000555555a1bad4 in probe_rs::session::ArchitectureInterface::attach (self=0x7fffffff6c70, core=0x555555fd8700, core_state=0x555555fd8708) at /home/dirbaio/rp/probe-rs/probe-rs/src/session.rs:71
#3459 0x0000555555a1bd7f in probe_rs::session::Session::core (self=0x7fffffff6c20, n=0) at /home/dirbaio/rp/probe-rs/probe-rs/src/session.rs:190
#3460 0x00005555556ea10b in probe_rs::session::Session::new<probe_rs::config::target::Target> (probe=..., target=..., attach_method=probe_rs::probe::AttachMethod::Normal) at /home/dirbaio/rp/probe-rs/probe-rs/src/session.rs:112
#3461 0x00005555556aa90b in probe_rs::probe::Probe::attach<probe_rs::config::target::Target> (self=..., target=...) at /home/dirbaio/rp/probe-rs/probe-rs/src/probe/mod.rs:288
#3462 0x0000555555685873 in probe_run::notmain () at /home/dirbaio/rp/probe-run/src/main.rs:317
#3463 0x0000555555681dd9 in probe_run::main () at /home/dirbaio/rp/probe-run/src/main.rs:43

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Comments: 17 (16 by maintainers)

Commits related to this issue

Most upvoted comments

@noppej I’ve created a new issue for the endless loop in the StackFrameIterator, and I’m working on fixing that now. I’ve split it up, because it seems to be a different issue than the original issue here.

The original issue mentioned here is something in the J-Link implemenation, so I’d like to keep them separate.

This issue is unrelated to the vscode debugger pointer loop issues.

This one is something much lower-level, related to the SWD protocol: doing an SWD register write can fault, which sets a “fault” flag. To clear it you have to do another register write, so the “write_register” fn calls itself. Of course the “clear fault” register write isn’t supposed to fault itself, but if it does then it stack overflows 😄

I don’t even know how to reproduce this, it just happened to have.

The fix would be to not recurse infinitely: if fault clearing faults again, abort.

I think the problem could be that the StackFrameIterator never finishes, but gets caught trying to unwind the same frame in a loop. This then leads to a stack overflow in the end.

To solve this, we should fix the iterator itself, but it’s probably also a good idea to add a limit to the number of stack frames in the debugger itself. AFAIK VS Code only requests a limited amount anyway.

I will have a go at solving this later today, but if someone wants to, feel free to go ahead.

@Tiwalun Ubuntu 21.10 Linux j 5.13.0-21-generic #21-Ubuntu SMP Tue Oct 19 08:59:28 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux