     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91

    // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
    // file at the top-level directory of this distribution and at
    // http://rust-lang.org/COPYRIGHT.
    //
    // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
    // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
    // option. This file may not be copied, modified, or distributed
    // except according to those terms.

    /// Backtrace support built on libgcc with some extra OS-specific support
    ///
    /// Some methods of getting a backtrace:
    ///
    /// * The backtrace() functions on unix. It turns out this doesn't work very
    ///   well for green threads on OSX, and the address to symbol portion of it
    ///   suffers problems that are described below.
    ///
    /// * Using libunwind. This is more difficult than it sounds because libunwind
    ///   isn't installed everywhere by default. It's also a bit of a hefty library,
    ///   so possibly not the best option. When testing, libunwind was excellent at
    ///   getting both accurate backtraces and accurate symbols across platforms.
    ///   This route was not chosen in favor of the next option, however.
    ///
    /// * We're already using libgcc_s for exceptions in rust (triggering thread
    ///   unwinding and running destructors on the stack), and it turns out that it
    ///   conveniently comes with a function that also gives us a backtrace. All of
    ///   these functions look like _Unwind_*, but it's not quite the full
    ///   repertoire of the libunwind API. Due to it already being in use, this was
    ///   the chosen route of getting a backtrace.
    ///
    /// After choosing libgcc_s for backtraces, the sad part is that it will only
    /// give us a stack trace of instruction pointers. Thankfully these instruction
    /// pointers are accurate (they work for green and native threads), but it's
    /// then up to us again to figure out how to translate these addresses to
    /// symbols. As with before, we have a few options. Before, that, a little bit
    /// of an interlude about symbols. This is my very limited knowledge about
    /// symbol tables, and this information is likely slightly wrong, but the
    /// general idea should be correct.
    ///
    /// When talking about symbols, it's helpful to know a few things about where
    /// symbols are located. Some symbols are located in the dynamic symbol table
    /// of the executable which in theory means that they're available for dynamic
    /// linking and lookup. Other symbols end up only in the local symbol table of
    /// the file. This loosely corresponds to pub and priv functions in Rust.
    ///
    /// Armed with this knowledge, we know that our solution for address to symbol
    /// translation will need to consult both the local and dynamic symbol tables.
    /// With that in mind, here's our options of translating an address to
    /// a symbol.
    ///
    /// * Use dladdr(). The original backtrace()-based idea actually uses dladdr()
    ///   behind the scenes to translate, and this is why backtrace() was not used.
    ///   Conveniently, this method works fantastically on OSX. It appears dladdr()
    ///   uses magic to consult the local symbol table, or we're putting everything
    ///   in the dynamic symbol table anyway. Regardless, for OSX, this is the
    ///   method used for translation. It's provided by the system and easy to do.o
    ///
    ///   Sadly, all other systems have a dladdr() implementation that does not
    ///   consult the local symbol table. This means that most functions are blank
    ///   because they don't have symbols. This means that we need another solution.
    ///
    /// * Use unw_get_proc_name(). This is part of the libunwind api (not the
    ///   libgcc_s version of the libunwind api), but involves taking a dependency
    ///   to libunwind. We may pursue this route in the future if we bundle
    ///   libunwind, but libunwind was unwieldy enough that it was not chosen at
    ///   this time to provide this functionality.
    ///
    /// * Shell out to a utility like `readelf`. Crazy though it may sound, it's a
    ///   semi-reasonable solution. The stdlib already knows how to spawn processes,
    ///   so in theory it could invoke readelf, parse the output, and consult the
    ///   local/dynamic symbol tables from there. This ended up not getting chosen
    ///   due to the craziness of the idea plus the advent of the next option.
    ///
    /// * Use `libbacktrace`. It turns out that this is a small library bundled in
    ///   the gcc repository which provides backtrace and symbol translation
    ///   functionality. All we really need from it is the backtrace functionality,
    ///   and we only really need this on everything that's not OSX, so this is the
    ///   chosen route for now.
    ///
    /// In summary, the current situation uses libgcc_s to get a trace of stack
    /// pointers, and we use dladdr() or libbacktrace to translate these addresses
    /// to symbols. This is a bit of a hokey implementation as-is, but it works for
    /// all unix platforms we support right now, so it at least gets the job done.

    pub use self::tracing::write;

    // tracing impls:
    mod tracing;
    // symbol resolvers:
    mod printing;

# Help

## Keyboard Shortcuts

?
  Show this help dialog
S
  Focus the search field
⇤
  Move up in search results
⇥
  Move down in search results
⏎
  Go to active search result

## Search Tricks

Prefix searches with a type followed by a colon (e.g. `fn:`) to restrict the search to a given type.

Accepted types are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `const`.

Search functions by type signature (e.g. `vec -> usize`)