4 if #[cfg(feature = "std")] {
6 use std
::prelude
::v1
::*;
10 use crate::backtrace
::Frame
;
11 use crate::types
::BytesOrWideString
;
12 use core
::ffi
::c_void
;
13 use rustc_demangle
::{try_demangle, Demangle}
;
15 /// Resolve an address to a symbol, passing the symbol to the specified
18 /// This function will look up the given address in areas such as the local
19 /// symbol table, dynamic symbol table, or DWARF debug info (depending on the
20 /// activated implementation) to find symbols to yield.
22 /// The closure may not be called if resolution could not be performed, and it
23 /// also may be called more than once in the case of inlined functions.
25 /// Symbols yielded represent the execution at the specified `addr`, returning
26 /// file/line pairs for that address (if available).
28 /// Note that if you have a `Frame` then it's recommended to use the
29 /// `resolve_frame` function instead of this one.
31 /// # Required features
33 /// This function requires the `std` feature of the `backtrace` crate to be
34 /// enabled, and the `std` feature is enabled by default.
38 /// This function strives to never panic, but if the `cb` provided panics then
39 /// some platforms will force a double panic to abort the process. Some
40 /// platforms use a C library which internally uses callbacks which cannot be
41 /// unwound through, so panicking from `cb` may trigger a process abort.
46 /// extern crate backtrace;
49 /// backtrace::trace(|frame| {
50 /// let ip = frame.ip();
52 /// backtrace::resolve(ip, |symbol| {
56 /// false // only look at the top frame
60 #[cfg(feature = "std")]
61 pub fn resolve
<F
: FnMut(&Symbol
)>(addr
: *mut c_void
, cb
: F
) {
62 let _guard
= crate::lock
::lock();
63 unsafe { resolve_unsynchronized(addr, cb) }
66 /// Resolve a previously capture frame to a symbol, passing the symbol to the
67 /// specified closure.
69 /// This functin performs the same function as `resolve` except that it takes a
70 /// `Frame` as an argument instead of an address. This can allow some platform
71 /// implementations of backtracing to provide more accurate symbol information
72 /// or information about inline frames for example. It's recommended to use this
75 /// # Required features
77 /// This function requires the `std` feature of the `backtrace` crate to be
78 /// enabled, and the `std` feature is enabled by default.
82 /// This function strives to never panic, but if the `cb` provided panics then
83 /// some platforms will force a double panic to abort the process. Some
84 /// platforms use a C library which internally uses callbacks which cannot be
85 /// unwound through, so panicking from `cb` may trigger a process abort.
90 /// extern crate backtrace;
93 /// backtrace::trace(|frame| {
94 /// backtrace::resolve_frame(frame, |symbol| {
98 /// false // only look at the top frame
102 #[cfg(feature = "std")]
103 pub fn resolve_frame
<F
: FnMut(&Symbol
)>(frame
: &Frame
, cb
: F
) {
104 let _guard
= crate::lock
::lock();
105 unsafe { resolve_frame_unsynchronized(frame, cb) }
108 pub enum ResolveWhat
<'a
> {
109 Address(*mut c_void
),
113 impl<'a
> ResolveWhat
<'a
> {
115 fn address_or_ip(&self) -> *mut c_void
{
117 ResolveWhat
::Address(a
) => adjust_ip(*a
),
118 ResolveWhat
::Frame(f
) => adjust_ip(f
.ip()),
123 // IP values from stack frames are typically (always?) the instruction
124 // *after* the call that's the actual stack trace. Symbolizing this on
125 // causes the filename/line number to be one ahead and perhaps into
126 // the void if it's near the end of the function.
128 // This appears to basically always be the case on all platforms, so we always
129 // subtract one from a resolved ip to resolve it to the previous call
130 // instruction instead of the instruction being returned to.
132 // Ideally we would not do this. Ideally we would require callers of the
133 // `resolve` APIs here to manually do the -1 and account that they want location
134 // information for the *previous* instruction, not the current. Ideally we'd
135 // also expose on `Frame` if we are indeed the address of the next instruction
138 // For now though this is a pretty niche concern so we just internally always
139 // subtract one. Consumers should keep working and getting pretty good results,
140 // so we should be good enough.
141 fn adjust_ip(a
: *mut c_void
) -> *mut c_void
{
145 (a
as usize - 1) as *mut c_void
149 /// Same as `resolve`, only unsafe as it's unsynchronized.
151 /// This function does not have synchronization guarentees but is available when
152 /// the `std` feature of this crate isn't compiled in. See the `resolve`
153 /// function for more documentation and examples.
157 /// See information on `resolve` for caveats on `cb` panicking.
158 pub unsafe fn resolve_unsynchronized
<F
>(addr
: *mut c_void
, mut cb
: F
)
162 resolve_imp(ResolveWhat
::Address(addr
), &mut cb
)
165 /// Same as `resolve_frame`, only unsafe as it's unsynchronized.
167 /// This function does not have synchronization guarentees but is available
168 /// when the `std` feature of this crate isn't compiled in. See the
169 /// `resolve_frame` function for more documentation and examples.
173 /// See information on `resolve_frame` for caveats on `cb` panicking.
174 pub unsafe fn resolve_frame_unsynchronized
<F
>(frame
: &Frame
, mut cb
: F
)
178 resolve_imp(ResolveWhat
::Frame(frame
), &mut cb
)
181 /// A trait representing the resolution of a symbol in a file.
183 /// This trait is yielded as a trait object to the closure given to the
184 /// `backtrace::resolve` function, and it is virtually dispatched as it's
185 /// unknown which implementation is behind it.
187 /// A symbol can give contextual information about a function, for example the
188 /// name, filename, line number, precise address, etc. Not all information is
189 /// always available in a symbol, however, so all methods return an `Option`.
191 // TODO: this lifetime bound needs to be persisted eventually to `Symbol`,
192 // but that's currently a breaking change. For now this is safe since
193 // `Symbol` is only ever handed out by reference and can't be cloned.
194 inner
: SymbolImp
<'
static>,
198 /// Returns the name of this function.
200 /// The returned structure can be used to query various properties about the
203 /// * The `Display` implementation will print out the demangled symbol.
204 /// * The raw `str` value of the symbol can be accessed (if it's valid
206 /// * The raw bytes for the symbol name can be accessed.
207 pub fn name(&self) -> Option
<SymbolName
<'_
>> {
211 /// Returns the starting address of this function.
212 pub fn addr(&self) -> Option
<*mut c_void
> {
213 self.inner
.addr().map(|p
| p
as *mut _
)
216 /// Returns the raw filename as a slice. This is mainly useful for `no_std`
218 pub fn filename_raw(&self) -> Option
<BytesOrWideString
<'_
>> {
219 self.inner
.filename_raw()
222 /// Returns the line number for where this symbol is currently executing.
224 /// This return value is typically `Some` if `filename` returns `Some`, and
225 /// is consequently subject to similar caveats.
226 pub fn lineno(&self) -> Option
<u32> {
230 /// Returns the file name where this function was defined.
232 /// This is currently only available when libbacktrace is being used (e.g.
233 /// unix platforms other than OSX) and when a binary is compiled with
234 /// debuginfo. If neither of these conditions is met then this will likely
237 /// # Required features
239 /// This function requires the `std` feature of the `backtrace` crate to be
240 /// enabled, and the `std` feature is enabled by default.
241 #[cfg(feature = "std")]
242 #[allow(unreachable_code)]
243 pub fn filename(&self) -> Option
<&Path
> {
244 self.inner
.filename()
248 impl fmt
::Debug
for Symbol
{
249 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
250 let mut d
= f
.debug_struct("Symbol");
251 if let Some(name
) = self.name() {
252 d
.field("name", &name
);
254 if let Some(addr
) = self.addr() {
255 d
.field("addr", &addr
);
258 #[cfg(feature = "std")]
260 if let Some(filename
) = self.filename() {
261 d
.field("filename", &filename
);
265 if let Some(lineno
) = self.lineno() {
266 d
.field("lineno", &lineno
);
273 if #[cfg(feature = "cpp_demangle")] {
274 // Maybe a parsed C++ symbol, if parsing the mangled symbol as Rust
276 struct OptionCppSymbol
<'a
>(Option
<::cpp_demangle
::BorrowedSymbol
<'a
>>);
278 impl<'a
> OptionCppSymbol
<'a
> {
279 fn parse(input
: &'a
[u8]) -> OptionCppSymbol
<'a
> {
280 OptionCppSymbol(::cpp_demangle
::BorrowedSymbol
::new(input
).ok())
283 fn none() -> OptionCppSymbol
<'a
> {
284 OptionCppSymbol(None
)
288 use core
::marker
::PhantomData
;
290 // Make sure to keep this zero-sized, so that the `cpp_demangle` feature
291 // has no cost when disabled.
292 struct OptionCppSymbol
<'a
>(PhantomData
<&'
a ()>);
294 impl<'a
> OptionCppSymbol
<'a
> {
295 fn parse(_
: &'a
[u8]) -> OptionCppSymbol
<'a
> {
296 OptionCppSymbol(PhantomData
)
299 fn none() -> OptionCppSymbol
<'a
> {
300 OptionCppSymbol(PhantomData
)
306 /// A wrapper around a symbol name to provide ergonomic accessors to the
307 /// demangled name, the raw bytes, the raw string, etc.
308 // Allow dead code for when the `cpp_demangle` feature is not enabled.
310 pub struct SymbolName
<'a
> {
312 demangled
: Option
<Demangle
<'a
>>,
313 cpp_demangled
: OptionCppSymbol
<'a
>,
316 impl<'a
> SymbolName
<'a
> {
317 /// Creates a new symbol name from the raw underlying bytes.
318 pub fn new(bytes
: &'a
[u8]) -> SymbolName
<'a
> {
319 let str_bytes
= str::from_utf8(bytes
).ok();
320 let demangled
= str_bytes
.and_then(|s
| try_demangle(s
).ok());
322 let cpp
= if demangled
.is_none() {
323 OptionCppSymbol
::parse(bytes
)
325 OptionCppSymbol
::none()
330 demangled
: demangled
,
335 /// Returns the raw (mangled) symbol name as a `str` if the symbol is valid utf-8.
337 /// Use the `Display` implementation if you want the demangled version.
338 pub fn as_str(&self) -> Option
<&'a
str> {
342 .or_else(|| str::from_utf8(self.bytes
).ok())
345 /// Returns the raw symbol name as a list of bytes
346 pub fn as_bytes(&self) -> &'a
[u8] {
351 fn format_symbol_name(
352 fmt
: fn(&str, &mut fmt
::Formatter
<'_
>) -> fmt
::Result
,
354 f
: &mut fmt
::Formatter
<'_
>,
356 while bytes
.len() > 0 {
357 match str::from_utf8(bytes
) {
365 match err
.error_len() {
366 Some(len
) => bytes
= &bytes
[err
.valid_up_to() + len
..],
376 if #[cfg(feature = "cpp_demangle")] {
377 impl<'a
> fmt
::Display
for SymbolName
<'a
> {
378 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
379 if let Some(ref s
) = self.demangled
{
381 } else if let Some(ref cpp
) = self.cpp_demangled
.0 {
384 format_symbol_name(fmt
::Display
::fmt
, self.bytes
, f
)
389 impl<'a
> fmt
::Display
for SymbolName
<'a
> {
390 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
391 if let Some(ref s
) = self.demangled
{
394 format_symbol_name(fmt
::Display
::fmt
, self.bytes
, f
)
402 if #[cfg(all(feature = "std", feature = "cpp_demangle"))] {
403 impl<'a
> fmt
::Debug
for SymbolName
<'a
> {
404 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
407 if let Some(ref s
) = self.demangled
{
411 // This may to print if the demangled symbol isn't actually
412 // valid, so handle the error here gracefully by not propagating
414 if let Some(ref cpp
) = self.cpp_demangled
.0 {
415 let mut s
= String
::new();
416 if write
!(s
, "{}", cpp
).is_ok() {
421 format_symbol_name(fmt
::Debug
::fmt
, self.bytes
, f
)
425 impl<'a
> fmt
::Debug
for SymbolName
<'a
> {
426 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
427 if let Some(ref s
) = self.demangled
{
430 format_symbol_name(fmt
::Debug
::fmt
, self.bytes
, f
)
437 /// Attempt to reclaim that cached memory used to symbolicate addresses.
439 /// This method will attempt to release any global data structures that have
440 /// otherwise been cached globally or in the thread which typically represent
441 /// parsed DWARF information or similar.
445 /// While this function is always available it doesn't actually do anything on
446 /// most implementations. Libraries like dbghelp or libbacktrace do not provide
447 /// facilities to deallocate state and manage the allocated memory. For now the
448 /// `gimli-symbolize` feature of this crate is the only feature where this
449 /// function has any effect.
450 #[cfg(feature = "std")]
451 pub fn clear_symbol_cache() {
452 let _guard
= crate::lock
::lock();
454 clear_symbol_cache_imp();
459 if #[cfg(all(windows, target_env = "msvc", not(target_vendor = "uwp")))] {
461 use self::dbghelp
::resolve
as resolve_imp
;
462 use self::dbghelp
::Symbol
as SymbolImp
;
463 unsafe fn clear_symbol_cache_imp() {}
465 feature
= "libbacktrace",
466 any(unix
, all(windows
, not(target_vendor
= "uwp"), target_env
= "gnu")),
467 not(target_os
= "fuchsia"),
468 not(target_os
= "emscripten"),
469 not(target_env
= "uclibc"),
472 use self::libbacktrace
::resolve
as resolve_imp
;
473 use self::libbacktrace
::Symbol
as SymbolImp
;
474 unsafe fn clear_symbol_cache_imp() {}
476 feature
= "gimli-symbolize",
478 not(target_os
= "emscripten"),
481 use self::gimli
::resolve
as resolve_imp
;
482 use self::gimli
::Symbol
as SymbolImp
;
483 use self::gimli
::clear_symbol_cache
as clear_symbol_cache_imp
;
486 use self::noop
::resolve
as resolve_imp
;
487 use self::noop
::Symbol
as SymbolImp
;
489 unsafe fn clear_symbol_cache_imp() {}