shepmaster / snafu

Easily assign underlying errors into domain-specific errors while adding context
https://docs.rs/snafu/
Apache License 2.0
1.45k stars 61 forks source link

Useless backtrace with missing pdb file on Windows #246

Closed dmitry-zakablukov closed 4 years ago

dmitry-zakablukov commented 4 years ago

Good day!

Let's consider the following code:

use snafu::{Backtrace, Snafu, ErrorCompat};

#[derive(Debug, Snafu)]
pub enum Error {
    #[snafu(display("Test error"))]
    TestError {
        backtrace: Backtrace,
    }
}

type Result<T> = std::result::Result<T, Error>;

fn func() -> Result<()> {
    Err(TestError.build())
}

fn main() {
    if let Err(error) = func() {
        if let Some(bt) = ErrorCompat::backtrace(&error) {
            println!("{:?}", bt);
        }
    }
}

This code prints a valid backtrace when a PDB file is not renamed/deleted from the file system:

Backtrace(   0: backtrace::backtrace::trace
   1: backtrace::capture::Backtrace::new
   2: <alloc::vec::Vec<T> as core::ops::drop::Drop>::drop
   3: <alloc::vec::Vec<T> as core::ops::drop::Drop>::drop
   4: std::rt::lang_start_internal::{{closure}}
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\rt.rs:52
   5: std::panicking::try::do_call
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panicking.rs:331
   6: std::panicking::try
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panicking.rs:274
   7: std::panic::catch_unwind
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panic.rs:394
   8: std::rt::lang_start_internal
             at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\rt.rs:51
   9: main
  10: invoke_main
             at d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
  11: __scrt_common_main_seh
             at d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
  12: BaseThreadInitThunk
  13: RtlUserThreadStart
)

But if the PDB file was deleted, or renamed, or .cargo/config is as follows:

[target.'cfg(windows)']
rustflags = ["-C", "link-args=/PDBALTPATH:missing.pdb"]

then the example will output the following:

Backtrace(   0: <unknown>
   1: <unknown>
   2: <unknown>
   3: <unknown>
   4: <unknown>
   5: <unknown>
   6: <unknown>
   7: BaseThreadInitThunk
   8: RtlUserThreadStart
)

Missing PDB file is a common use case in a production environment. So my question are:

  1. Can the ip address be added to the backtrace output? See ip() documentation here: https://docs.rs/backtrace/0.3.50/backtrace/struct.BacktraceFrame.html#method.ip
  2. (this is not SNAFU specific question) How to get a module base address? Ip address is a relative to the base address, as far as I know. So without a base address there is no much use from ip addresses.
shepmaster commented 4 years ago

You haven't included the information about which backtrace provider feature flag you are using. You link to the backtrace crate; does that mean that's what you are using?

  1. Can the ip address be added to the backtrace output

Can it be? Maybe. Depending on the backtrace provider you are using, it might not be under the control of this crate however. What benefit do you see it providing in this case?

  1. How to get a module base address?

I do not know. Perhaps that is an appropriate question for the backtrace crate maintainers.

dmitry-zakablukov commented 4 years ago

You haven't included the information about which backtrace provider feature flag you are using. You link to the backtrace crate; does that mean that's what you are using?

Sorry, I didn't know that any backtrace provider can be used. I simply used snafu crate with the feature backtraces. I suppose the snafu crate uses this crate: https://docs.rs/backtrace/0.3.50/backtrace/index.html

Can it be? Maybe. Depending on the backtrace provider you are using, it might not be under the control of this crate however. What benefit do you see it providing in this case?

Frame addresses and base address are sufficient to decode backtrace using a PDB file. If ip addresses are equal to the frame addresses, then a half of my problem can be solved.

shepmaster commented 4 years ago

I simply used snafu crate with the feature backtraces

Thank you, that's what I was looking for.

In that case, I think you can fork the crate, modify this line:

https://github.com/shepmaster/snafu/blob/7fba216782cd1a0466b077b2667c15bb5f397203/src/backtrace_shim.rs#L92

Test it locally to see that it helps you, then submit a PR.

dmitry-zakablukov commented 4 years ago

@shepmaster , I have opened a PR #256 to implement a custom backtrace formatting I need.