Repository: esp-rs/espflash (language: rust)

Issue:
Update `addr2line` and `crossterm` dependencies
We have held off on updating these due to A) API changes in `addr2line` and B) issues with updating `crossterm` on Windows, but we should make an effort to resolve these issues and get back to using the latest versions.


Discussion / hints:
Looks like newer versions of `addr2line` expect a DWARF file now, so it's not clear to me how to accomplish this given that we only have an ELF, or if this is even possible. Will need to do some more reading, there are like 3 different package in play here all of which I need to better understand.

Regarding `crossterm`, I don't have a Windows machine so somebody else will need to try and figure that one out I guess.
I tested crossterm 0.28.1 on Windows 11 and it looks good to me - just bumping the dependency and it seems to work
> I tested crossterm 0.28.1 on Windows 11 and it looks good to me - just bumping the dependency and it seems to work

Awesome, thanks! Will just update it then.
For addr2line I think we just need this: https://github.com/gimli-rs/addr2line/blob/28ba2d45f2d22134915f55b46ddd6a039559366b/tests/parse.rs#L29-L40

To get the DWARF section from the parsed ELF

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index e6b56db8..4ff8d992 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,26 +4,18 @@ version = 3
 
 [[package]]
 name = "addr2line"
-version = "0.22.0"
+version = "0.24.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
+checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
 dependencies = [
  "cpp_demangle",
  "fallible-iterator",
- "gimli 0.29.0",
+ "gimli 0.31.1",
  "memmap2",
- "object 0.35.0",
+ "object 0.36.7",
  "rustc-demangle",
  "smallvec",
-]
-
-[[package]]
-name = "addr2line"
-version = "0.24.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
-dependencies = [
- "gimli 0.31.1",
+ "typed-arena",
 ]
 
 [[package]]
@@ -165,7 +157,7 @@ version = "0.3.74"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
 dependencies = [
- "addr2line 0.24.2",
+ "addr2line",
  "cfg-if",
  "libc",
  "miniz_oxide",
@@ -652,7 +644,7 @@ version = "7.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "24f165e7b643266ea80cb858aed492ad9280e3e05ce24d4a99d7d7b889b6a4d9"
 dependencies = [
- "crossterm 0.28.1",
+ "crossterm",
  "strum",
  "strum_macros",
  "unicode-width 0.2.0",
@@ -774,22 +766,6 @@ version = "0.8.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
 
-[[package]]
-name = "crossterm"
-version = "0.25.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67"
-dependencies = [
- "bitflags 1.3.2",
- "crossterm_winapi",
- "libc",
- "mio 0.8.11",
- "parking_lot",
- "signal-hook",
- "signal-hook-mio",
- "winapi",
-]
-
 [[package]]
 name = "crossterm"
 version = "0.28.1"
@@ -798,8 +774,11 @@ checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
 dependencies = [
  "bitflags 2.7.0",
  "crossterm_winapi",
+ "mio",
  "parking_lot",
  "rustix",
+ "signal-hook",
+ "signal-hook-mio",
  "winapi",
 ]
 
@@ -1035,17 +1014,6 @@ dependencies = [
  "serde",
 ]
 
-[[package]]
-name = "derive_more"
-version = "0.99.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.96",
-]
-
 [[package]]
 name = "dialoguer"
 version = "0.11.0"
@@ -1251,13 +1219,13 @@ dependencies = [
 name = "espflash"
 version = "4.0.0-dev"
 dependencies = [
- "addr2line 0.22.0",
+ "addr2line",
  "base64",
  "bytemuck",
  "clap",
  "clap_complete",
  "comfy-table",
- "crossterm 0.25.0",
+ "crossterm",
  "ctrlc",
  "defmt-decoder",
  "defmt-parser",
@@ -1272,6 +1240,7 @@ dependencies = [
  "log",
  "md-5",
  "miette",
+ "object 0.36.7",
  "regex",
  "serde",
  "serde_json",
@@ -1487,6 +1456,10 @@ name = "gimli"
 version = "0.31.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
+dependencies = [
+ "fallible-iterator",
+ "stable_deref_trait",
+]
 
 [[package]]
 name = "git2"
@@ -3053,18 +3026,6 @@ dependencies = [
  "adler2",
 ]
 
-[[package]]
-name = "mio"
-version = "0.8.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
-dependencies = [
- "libc",
- "log",
- "wasi",
- "windows-sys 0.48.0",
-]
-
 [[package]]
 name = "mio"
 version = "1.0.3"
@@ -3072,6 +3033,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
 dependencies = [
  "libc",
+ "log",
  "wasi",
  "windows-sys 0.52.0",
 ]
@@ -3164,9 +3126,7 @@ version = "0.35.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e"
 dependencies = [
- "flate2",
  "memchr",
- "ruzstd",
 ]
 
 [[package]]
@@ -3175,7 +3135,9 @@ version = "0.36.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
 dependencies = [
+ "flate2",
  "memchr",
+ "ruzstd",
 ]
 
 [[package]]
@@ -3822,12 +3784,10 @@ checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
 
 [[package]]
 name = "ruzstd"
-version = "0.6.0"
+version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5174a470eeb535a721ae9fdd6e291c2411a906b96592182d05217591d5c5cf7b"
+checksum = "fad02996bfc73da3e301efe90b1837be9ed8f4a462b6ed410aa35d00381de89f"
 dependencies = [
- "byteorder",
- "derive_more",
  "twox-hash",
 ]
 
@@ -4089,7 +4049,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd"
 dependencies = [
  "libc",
- "mio 0.8.11",
+ "mio",
  "signal-hook",
 ]
 
@@ -4449,7 +4409,7 @@ dependencies = [
  "backtrace",
  "bytes",
  "libc",
- "mio 1.0.3",
+ "mio",
  "pin-project-lite",
  "socket2",
  "windows-sys 0.52.0",
@@ -4625,6 +4585,12 @@ dependencies = [
  "static_assertions",
 ]
 
+[[package]]
+name = "typed-arena"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a"
+
 [[package]]
 name = "typeid"
 version = "1.0.2"
diff --git a/espflash/Cargo.toml b/espflash/Cargo.toml
index 2f942aee..ddb66b01 100644
--- a/espflash/Cargo.toml
+++ b/espflash/Cargo.toml
@@ -25,13 +25,13 @@ path              = "./src/bin/espflash.rs"
 required-features = ["cli", "serialport"]
 
 [dependencies]
-addr2line       = { version = "0.22.0", optional = true }
+addr2line       = { version = "0.24.2", optional = true }
 base64          = "0.22.1"
 bytemuck        = { version = "1.21.0", features = ["derive"] }
 clap            = { version = "4.5.24", features = ["derive", "env", "wrap_help"], optional = true }
 clap_complete   = { version = "4.5.41", optional = true }
 comfy-table     = { version = "7.1.3", optional = true }
-crossterm       = { version = "0.25.0", optional = true }
+crossterm       = { version = "0.28.1", optional = true }
 ctrlc           = { version = "3.4.5", optional = true }
 defmt-decoder   = { version = "=0.4.0", features = ["unstable"], optional = true }
 defmt-parser    = { version = "=0.4.1", features = ["unstable"], optional = true }
@@ -45,6 +45,7 @@ indicatif       = { version = "0.17.9", optional = true }
 log             = "0.4.22"
 md-5            = "0.10.6"
 miette          = "7.4.0"
+object          = "0.36.7"
 regex           = { version = "1.11.1", optional = true }
 serde           = { version = "1.0.217", features = ["derive"] }
 serde_json      = "1.0.138"
diff --git a/espflash/src/cli/monitor/symbols.rs b/espflash/src/cli/monitor/symbols.rs
index f4f18090..4e9d9a1c 100644
--- a/espflash/src/cli/monitor/symbols.rs
+++ b/espflash/src/cli/monitor/symbols.rs
@@ -1,43 +1,53 @@
 use std::error::Error;
 
 use addr2line::{
-    gimli::{EndianRcSlice, RunTimeEndian},
-    object::{read::File, Object, ObjectSegment, ObjectSymbol},
+    gimli::{self, Dwarf, EndianSlice, LittleEndian, SectionId},
     Context,
     LookupResult,
 };
+use object::{read::File, Object, ObjectSection, ObjectSegment, ObjectSymbol};
 
 // Wrapper around addr2line that allows to look up function names and
 // locations from a given address.
 pub(crate) struct Symbols<'sym> {
-    file: File<'sym, &'sym [u8]>,
-    ctx: Context<EndianRcSlice<RunTimeEndian>>,
+    object: File<'sym, &'sym [u8]>,
+    ctx: Context<EndianSlice<'sym, LittleEndian>>,
 }
 
 impl<'sym> Symbols<'sym> {
     pub fn try_from(bytes: &'sym [u8]) -> Result<Self, Box<dyn Error>> {
-        let file = File::parse(bytes)?;
-        let ctx = Context::new(&file)?;
+        let object = File::parse(bytes)?;
+        let dwarf = Dwarf::load(
+            |id: SectionId| -> Result<EndianSlice<'sym, LittleEndian>, gimli::Error> {
+                let data = object
+                    .section_by_name(id.name())
+                    .and_then(|section| section.data().ok())
+                    .unwrap_or(&[][..]);
+                Ok(EndianSlice::new(data, LittleEndian))
+            },
+        )?;
 
-        Ok(Self { file, ctx })
+        let ctx = Context::from_dwarf(dwarf)?;
+
+        Ok(Self { object, ctx })
     }
 
     /// Returns the name of the function at the given address, if one can be
     /// found.
     pub fn get_name(&self, addr: u64) -> Option<String> {
-        // no need to try an address not contained in any segment
-        if !self.file.segments().any(|segment| {
+        // No need to try an address not contained in any segment:
+        if !self.object.segments().any(|segment| {
             (segment.address()..(segment.address() + segment.size())).contains(&addr)
         }) {
             return None;
         }
 
         // The basic steps here are:
-        //   1. find which frame `addr` is in
-        //   2. look up and demangle the function name
-        //   3. if no function name is found, try to look it up in the object file
+        //   1. Find which frame `addr` is in
+        //   2. Look up and demangle the function name
+        //   3. If no function name is found, try to look it up in the object file
         //      directly
-        //   4. return a demangled function name, if one was found
+        //   4. Return a demangled function name, if one was found
         let mut frames = match self.ctx.find_frames(addr) {
             LookupResult::Output(result) => result.unwrap(),
             LookupResult::Load { .. } => unimplemented!(),
@@ -55,7 +65,7 @@ impl<'sym> Symbols<'sym> {
             .or_else(|| {
                 // Don't use `symbol_map().get(addr)` - it's documentation says "Get the symbol
                 // before the given address." which might be totally wrong
-                let symbol = self.file.symbols().find(|symbol| {
+                let symbol = self.object.symbols().find(|symbol| {
                     (symbol.address()..=(symbol.address() + symbol.size())).contains(&addr)
                 });
 


Test patch: