diff --git a/CHANGELOG.md b/CHANGELOG.md index 092a04df..5b968793 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p - [#317] Clarify "can't determine stack overflow" error message - [#314] Clarify documentation in README - [#293] Update snapshot tests to new TRACE output +- Update probe-rs to 0.13.0 (does not yet implement 64-bit support) [#328]: https://github.com/knurling-rs/probe-run/pull/328 [#326]: https://github.com/knurling-rs/probe-run/pull/326 diff --git a/Cargo.lock b/Cargo.lock index 81520cfc..2b2a4c7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,7 +11,7 @@ dependencies = [ "cpp_demangle", "fallible-iterator", "gimli", - "object", + "object 0.27.1", "rustc-demangle", ] @@ -79,9 +79,9 @@ dependencies = [ [[package]] name = "bitfield" -version = "0.13.2" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" +checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" [[package]] name = "bitflags" @@ -91,9 +91,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitvec" -version = "0.22.3" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5237f00a8c86130a0cc317830e558b966dd7850d48a953d998c813f01a41b527" +checksum = "1489fcb93a5bb47da0462ca93ad252ad6af2145cce58d10d46a83931ba9f016b" dependencies = [ "funty", "radium", @@ -213,7 +213,7 @@ dependencies = [ "difference", "gimli", "log", - "object", + "object 0.27.1", "ryu", "serde", "serde_json", @@ -310,9 +310,9 @@ dependencies = [ [[package]] name = "funty" -version = "1.2.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "getrandom" @@ -440,9 +440,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "jaylink" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f58b72b6aa9d25083b8c19d292fe015a936185fa200d15e225e1524a18222e9" +checksum = "2d891935e08397d85684c1d3c88b6a0a6941c6e15e9f04a1ae9e30079f0b0df0" dependencies = [ "bitflags", "byteorder", @@ -473,9 +473,9 @@ checksum = "fbe5e23404da5b4f555ef85ebed98fb4083e55a00c317800bc2a50ede9f3d219" [[package]] name = "libusb1-sys" -version = "0.5.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22e89d08bbe6816c6c5d446203b859eba35b8fa94bf1b7edb2f6d25d43f023f" +checksum = "6dfab089105aa85a3b492b421bd90d55e6257f00f8447cc3873c44f8206809ce" dependencies = [ "cc", "libc", @@ -575,6 +575,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "object" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.8.0" @@ -645,9 +654,9 @@ dependencies = [ [[package]] name = "probe-rs" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "232e7f2912aba17bef48f84f9d90bfc9e6c1d8c90959fcf1451ccb3a68819ee7" +checksum = "03a92904dbd29f6af1f7bd6d22dac82569aa4b03bcbfc54441b7c76f7114ea79" dependencies = [ "anyhow", "base64", @@ -662,36 +671,36 @@ dependencies = [ "jep106", "log", "num-traits", - "object", + "object 0.29.0", "once_cell", "probe-rs-target", "rusb", - "scroll", + "scroll 0.11.0", "serde", "serde_yaml", "static_assertions", "svg", "thiserror", - "thousands", ] [[package]] name = "probe-rs-rtt" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17a9f49ddd5fa2f079961debbea5f93e4fc168bf89223a0407aa9de60eed8d51" +checksum = "68a97f5a269ac492bc911663aab10817225792fa69c18a85e567c090e0308ed4" dependencies = [ "log", "probe-rs", - "scroll", + "scroll 0.10.2", + "serde", "thiserror", ] [[package]] name = "probe-rs-target" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f9610234697e695947df2f7b0cd71d4e4e2fe2fea13df90bdc44bb65e0ef16f" +checksum = "4a024d514369dbabfdb7f476a8a16376b3aabf139454fdba5df012686a68430b" dependencies = [ "base64", "jep106", @@ -712,7 +721,7 @@ dependencies = [ "insta", "log", "nix", - "object", + "object 0.27.1", "os_pipe", "pretty_assertions", "probe-rs", @@ -773,9 +782,9 @@ dependencies = [ [[package]] name = "radium" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "redox_syscall" @@ -811,9 +820,9 @@ dependencies = [ [[package]] name = "rusb" -version = "0.8.1" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9a5084628cc5be77b1c750b3e5ee0cc519d2f2491b3f06b78b3aac3328b00ad" +checksum = "703aa035c21c589b34fb5136b12e68fc8dcf7ea46486861381361dd8ebf5cee0" dependencies = [ "libc", "libusb1-sys", @@ -852,6 +861,12 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fda28d4b4830b807a8b43f7b0e6b5df875311b3e7621d84577188c175b6ec1ec" +[[package]] +name = "scroll" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" + [[package]] name = "semver" version = "1.0.4" @@ -1058,12 +1073,6 @@ dependencies = [ "syn", ] -[[package]] -name = "thousands" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820" - [[package]] name = "unicode-segmentation" version = "1.8.0" @@ -1136,9 +1145,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "wyz" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "129e027ad65ce1453680623c3fb5163cbf7107bfe1aa32257e7d0e63f9ced188" +checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e" dependencies = [ "tap", ] diff --git a/Cargo.toml b/Cargo.toml index 7d420ace..02907451 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,8 +24,8 @@ gimli = { version = "0.26", default-features = false } git-version = "0.3" log = "0.4" object = { version = "0.27", default-features = false } -probe-rs = "0.12" -probe-rs-rtt = "0.12" +probe-rs = "0.13" +probe-rs-rtt = "0.13" signal-hook = "0.3" structopt = "0.3" diff --git a/src/backtrace/unwind.rs b/src/backtrace/unwind.rs index 6a558aa6..a5227c60 100644 --- a/src/backtrace/unwind.rs +++ b/src/backtrace/unwind.rs @@ -57,7 +57,7 @@ pub(crate) fn target(core: &mut Core, elf: &Elf, active_ram_region: &Option) -> bool { // NOTE stack is full descending; meaning the stack pointer can be // `ORIGIN(RAM) + LENGTH(RAM)` let range = active_ram_region.range.start..=active_ram_region.range.end; - !range.contains(&sp) + !range.contains(&sp.into()) } else { log::warn!("no RAM region appears to contain the stack; probe-run can't determine if this was a stack overflow"); false diff --git a/src/canary.rs b/src/canary.rs index aeb1a505..7165e516 100644 --- a/src/canary.rs +++ b/src/canary.rs @@ -1,6 +1,6 @@ use std::time::Instant; -use probe_rs::{Core, MemoryInterface, Session}; +use probe_rs::{Core, MemoryInterface, Session, RegisterValue}; use crate::{registers::PC, Elf, TargetInfo, TIMEOUT}; @@ -116,7 +116,7 @@ impl Canary { } let mut canary = vec![0; self.size]; let start = Instant::now(); - core.read_8(self.address, &mut canary)?; + core.read_8(self.address.into(), &mut canary)?; let seconds = start.elapsed().as_secs_f64(); log::trace!( "reading canary took {seconds:.3}s ({:.2} KiB/s)", @@ -195,10 +195,10 @@ fn paint_stack(core: &mut Core, start: u32, end: u32) -> Result<(), probe_rs::Er // write subroutine to RAM // NOTE: add `SUBROUTINE_LENGTH` to `start`, to avoid the subroutine overwriting itself - core.write_8(start, &subroutine(start + SUBROUTINE_LENGTH as u32, end))?; + core.write_8(start.into(), &subroutine(start + SUBROUTINE_LENGTH as u32, end))?; // store current PC and set PC to beginning of subroutine - let previous_pc = core.read_core_reg(PC)?; + let previous_pc: RegisterValue = core.read_core_reg(PC)?; core.write_core_reg(PC, start)?; // execute the subroutine and wait for it to finish @@ -206,7 +206,7 @@ fn paint_stack(core: &mut Core, start: u32, end: u32) -> Result<(), probe_rs::Er core.wait_for_core_halted(TIMEOUT)?; // overwrite subroutine - core.write_8(start, &[CANARY_VALUE; SUBROUTINE_LENGTH])?; + core.write_8(start.into(), &[CANARY_VALUE; SUBROUTINE_LENGTH])?; // reset PC to where it was before core.write_core_reg(PC, previous_pc)?; diff --git a/src/elf.rs b/src/elf.rs index eb1d2637..64f0c05d 100644 --- a/src/elf.rs +++ b/src/elf.rs @@ -200,8 +200,8 @@ fn extract_symbols(elf: &ObjectFile) -> anyhow::Result { main_fn_address.ok_or_else(|| anyhow!("`main` symbol not found"))?; Ok(Symbols { - rtt_buffer_address, + rtt_buffer_address: rtt_buffer_address.map(|v| v.into()), program_uses_heap, - main_fn_address: main_function_address, + main_fn_address: main_function_address.into(), }) } diff --git a/src/main.rs b/src/main.rs index c92fc52f..5536a1ea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,6 +28,7 @@ use probe_rs::{ Core, DebugProbeError::ProbeSpecific, MemoryInterface as _, Session, + Permissions, }; use probe_rs_rtt::{Rtt, ScanRegion, UpChannel}; use signal_hook::consts::signal; @@ -63,9 +64,9 @@ fn run_target_program(elf_path: &Path, chip_name: &str, opts: &cli::Opts) -> any let probe_target = target_info.probe_target.clone(); let mut sess = if opts.connect_under_reset { - probe.attach_under_reset(probe_target)? + probe.attach_under_reset(probe_target, Permissions::default())? } else { - let probe_attach = probe.attach(probe_target); + let probe_attach = probe.attach(probe_target, Permissions::default()); if let Err(probe_rs::Error::Probe(ProbeSpecific(e))) = &probe_attach { // FIXME Using `to_string().contains(...)` is a workaround as the concrete type // of `e` is not public and therefore does not allow downcasting. @@ -187,7 +188,7 @@ fn start_program(sess: &mut Session, elf: &Elf) -> anyhow::Result<()> { let mut core = sess.core(0)?; log::debug!("starting device"); - if core.get_available_breakpoint_units()? == 0 { + if core.available_breakpoint_units()? == 0 { if elf.rtt_buffer_address().is_some() { bail!("RTT not supported on device without HW breakpoints"); } else { @@ -199,7 +200,7 @@ fn start_program(sess: &mut Session, elf: &Elf) -> anyhow::Result<()> { set_rtt_to_blocking(&mut core, elf.main_fn_address(), rtt_buffer_address)? } - core.set_hw_breakpoint(cortexm::clear_thumb_bit(elf.vector_table.hard_fault))?; + core.set_hw_breakpoint(cortexm::clear_thumb_bit(elf.vector_table.hard_fault).into())?; core.run()?; Ok(()) @@ -212,7 +213,7 @@ fn set_rtt_to_blocking( rtt_buffer_address: u32, ) -> anyhow::Result<()> { // set and wait for a hardware breakpoint at the beginning of `fn main()` - core.set_hw_breakpoint(main_fn_address)?; + core.set_hw_breakpoint(main_fn_address.into())?; core.run()?; core.wait_for_core_halted(Duration::from_secs(5))?; @@ -222,16 +223,16 @@ fn set_rtt_to_blocking( // read flags let channel_flags = &mut [0]; - core.read_32(rtt_buffer_address, channel_flags)?; + core.read_32(rtt_buffer_address.into(), channel_flags)?; // modify flags to blocking const MODE_MASK: u32 = 0b11; const MODE_BLOCK_IF_FULL: u32 = 0b10; let modified_channel_flags = (channel_flags[0] & !MODE_MASK) | MODE_BLOCK_IF_FULL; // write flags back - core.write_word_32(rtt_buffer_address, modified_channel_flags)?; + core.write_word_32(rtt_buffer_address.into(), modified_channel_flags)?; // clear the breakpoint we set before - core.clear_hw_breakpoint(main_fn_address)?; + core.clear_hw_breakpoint(main_fn_address.into())?; Ok(()) } diff --git a/src/registers.rs b/src/registers.rs index fe3b882e..fa3979dd 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -1,11 +1,11 @@ use std::collections::{btree_map, BTreeMap}; use gimli::{read::CfaRule, EndianSlice, LittleEndian, Register, RegisterRule}; -use probe_rs::{Core, CoreRegisterAddress, MemoryInterface}; +use probe_rs::{Core, RegisterId, MemoryInterface}; -pub const LR: CoreRegisterAddress = CoreRegisterAddress(14); -pub const PC: CoreRegisterAddress = CoreRegisterAddress(15); -pub const SP: CoreRegisterAddress = CoreRegisterAddress(13); +pub const LR: RegisterId = RegisterId(14); +pub const PC: RegisterId = RegisterId(15); +pub const SP: RegisterId = RegisterId(13); pub const LR_END: u32 = 0xFFFF_FFFF; @@ -23,14 +23,14 @@ impl<'c, 'probe> Registers<'c, 'probe> { Self { cache, core } } - pub fn get(&mut self, reg: CoreRegisterAddress) -> anyhow::Result { + pub fn get(&mut self, reg: RegisterId) -> anyhow::Result { Ok(match self.cache.entry(reg.0) { btree_map::Entry::Occupied(entry) => *entry.get(), btree_map::Entry::Vacant(entry) => *entry.insert(self.core.read_core_reg(reg)?), }) } - pub fn insert(&mut self, reg: CoreRegisterAddress, val: u32) { + pub fn insert(&mut self, reg: RegisterId, val: u32) { self.cache.insert(reg.0, val); } @@ -44,7 +44,7 @@ impl<'c, 'probe> Registers<'c, 'probe> { ) -> anyhow::Result { match rule { CfaRule::RegisterAndOffset { register, offset } => { - let cfa = (i64::from(self.get(gimli2probe(register))?) + offset) as u32; + let cfa = (i64::from(self.get(gimli2probe(register))?) + offset) as u32; // wrapping_add_signed let old_cfa = self.cache.get(&SP.0); let changed = old_cfa != Some(&cfa); if changed { @@ -67,7 +67,7 @@ impl<'c, 'probe> Registers<'c, 'probe> { RegisterRule::Offset(offset) => { let cfa = self.get(SP)?; let addr = (cfa as i64 + offset) as u32; - let value = self.core.read_word_32(addr)?; + let value = self.core.read_word_32(addr.into())?; log::trace!( "update reg={:?}, rule={:?}, abs={:#010x} -> value={:#010x}", reg, @@ -84,6 +84,6 @@ impl<'c, 'probe> Registers<'c, 'probe> { } } -fn gimli2probe(reg: &Register) -> CoreRegisterAddress { - CoreRegisterAddress(reg.0) +fn gimli2probe(reg: &Register) -> RegisterId { + RegisterId(reg.0) } diff --git a/src/stacked.rs b/src/stacked.rs index c612cf5f..4d0efce9 100644 --- a/src/stacked.rs +++ b/src/stacked.rs @@ -64,7 +64,7 @@ impl Stacked { return Ok(None); } - core.read_32(start, registers)?; + core.read_32(start.into(), registers)?; Ok(Some(Stacked { lr: registers[0], diff --git a/src/target_info.rs b/src/target_info.rs index 1a73a487..c0db142c 100644 --- a/src/target_info.rs +++ b/src/target_info.rs @@ -65,6 +65,7 @@ fn check_processor_target_compatability(cores: &[Core], elf_path: &Path) { let matches = match core_type { CoreType::Armv6m => target == "thumbv6m-none-eabi", CoreType::Armv7m => target == "thumbv7m-none-eabi", + CoreType::Armv7a => target == "thumbv7a-none-eabi", CoreType::Armv7em => target == "thumbv7em-none-eabi" || target == "thumbv7em-none-eabihf", CoreType::Armv8m => { target == "thumbv8m.base-none-eabi" @@ -74,6 +75,10 @@ fn check_processor_target_compatability(cores: &[Core], elf_path: &Path) { CoreType::Riscv => return, // NOTE(return) Since we do not get any info about instruction // set support from probe-rs we do not know which compilation // targets fit. + _ => { + log::warn!("Unsupported architecture ({core_type:?}"); + return; + }, }; if matches { @@ -88,7 +93,7 @@ fn check_processor_target_compatability(cores: &[Core], elf_path: &Path) { CoreType::Armv8m => { "should be 'thumbv8m.base-none-eabi' (M23), 'thumbv8m.main-none-eabi' (M33 no FPU), or 'thumbv8m.main-none-eabihf' (M33 with FPU)" } - CoreType::Riscv => unreachable!(), + _ => unreachable!(), }; log::warn!("Compilation target ({target}) and core type ({core_type:?}) do not match. Your compilation target {recommendation}."); } @@ -105,7 +110,7 @@ fn extract_active_ram_region( // NOTE stack is full descending; meaning the stack pointer can be // `ORIGIN(RAM) + LENGTH(RAM)` let inclusive_range = ram_region.range.start..=ram_region.range.end; - if inclusive_range.contains(&initial_stack_pointer) { + if inclusive_range.contains(&initial_stack_pointer.into()) { log::debug!( "RAM region: 0x{:08X}-0x{:08X}", ram_region.range.start, @@ -121,7 +126,7 @@ fn extract_active_ram_region( .cloned() } -fn extract_stack_info(elf: &Elf, ram_range: &Range) -> Option { +fn extract_stack_info(elf: &Elf, ram_range: &Range) -> Option { // How does it work? // - the upper end of the stack is the initial SP, minus one // - the lower end of the stack is the highest address any section in the elf file uses, plus one @@ -129,7 +134,7 @@ fn extract_stack_info(elf: &Elf, ram_range: &Range) -> Option { let initial_stack_pointer = elf.vector_table.initial_stack_pointer; // SP points one word (4-byte) past the end of the stack. - let mut stack_range = ram_range.start..=initial_stack_pointer - 4; + let mut stack_range = ram_range.start.try_into().unwrap_or(u32::MAX)..=initial_stack_pointer - 4; for section in elf.sections() { let size: u32 = section.size().try_into().expect("expected 32-bit ELF"); @@ -142,7 +147,7 @@ fn extract_stack_info(elf: &Elf, ram_range: &Range) -> Option { let section_range = lowest_address..=highest_address; let name = section.name().unwrap_or(""); - if ram_range.contains(section_range.end()) { + if ram_range.contains(&(*section_range.end() as u64)) { log::debug!("section `{}` is in RAM at {:#010X?}", name, section_range); if section_range.contains(stack_range.end()) { @@ -159,7 +164,7 @@ fn extract_stack_info(elf: &Elf, ram_range: &Range) -> Option { log::debug!("valid SP range: {:#010X?}", stack_range); Some(StackInfo { - data_below_stack: *stack_range.start() > ram_range.start, + data_below_stack: *stack_range.start() as u64 > ram_range.start, range: stack_range, }) }