Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic backtrace functionality #10128

Closed
alexcrichton opened this issue Oct 28, 2013 · 9 comments · Fixed by #12602
Closed

Add basic backtrace functionality #10128

alexcrichton opened this issue Oct 28, 2013 · 9 comments · Fixed by #12602
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.)

Comments

@alexcrichton
Copy link
Member

There are a number of locations where it would be really nice if we had some very simple support for backtraces. By simple I just mean the ability to know the name of the function and possibly the instruction pointer inside the function.

Some possible use case:

  • Traces for each gc allocation (the old C++ managed box allocator did this)
  • Stack trace printing on failure
  • Less codegen bloat from failure functions that pass around file/line number. (function name isn't equivalent, but maybe sufficient?)

This is obviously a tricky thing to do, and I don't think that we should bring in libunwind for just this (it's pretty simple), but it appears that each platform has their own solution for acquiring a simple backtrace, and we can take the least common denominator of all of them:

This would probably be a module in std::unstable like the way dynamic_lib is a module. This isn't really a high priority, but it would certainly be something nice to have!

@catamorphism
Copy link
Contributor

+1

@alexcrichton
Copy link
Member Author

I played around with this for a bit using the backtrace function on OSX and linux. OSX refused to give any symbols at all (the backtrace function returned 0), and linux gave awful symbols names because all of our symbols in executables are flagged as internal. When getting a backtrace from a library, the symbol names were all acquired, but they were also all mangled.

Not entirely sure how useful this would be in light of this, and it also turns out that -Z extra-debug-info doesn't improve symbols at all. Certainly worth the interesting project tag!

@jdm
Copy link
Contributor

jdm commented Oct 29, 2013

Firefox has stackwalking code that might be worth investigating: http://mxr.mozilla.org/mozilla-central/source/xpcom/base/nsStackWalk.cpp

@jdm
Copy link
Contributor

jdm commented Oct 29, 2013

However, it appears that the production stackwalker code for our in-app profiler that runs on release builds is built on top of Breakpad.

@pnkfelix
Copy link
Member

cc me

@pnkfelix
Copy link
Member

pnkfelix commented Nov 8, 2013

In a toy example in C on Mac OS X, it seems like the backtrace functionality works, sort of, for a compiled executable. (I say "sort of" because once I start marking functions in my toy example as static, gcc starts emitting tail calls, so of course that means those frames get left off the stack, so my toy example isn't as full an illustration as I'd like it to be.)

@flaper87
Copy link
Contributor

cc me

@alexcrichton
Copy link
Member Author

The ruby implementation looks like this:

https://github.com/ruby/ruby/blob/trunk/vm_dump.c#L679-L705

@jdm
Copy link
Contributor

jdm commented Feb 5, 2014

Most recent Gecko work for use by the built-in profiler: https://bugzilla.mozilla.org/show_bug.cgi?id=938157

alexcrichton added a commit to alexcrichton/rust that referenced this issue Feb 5, 2014
Whenever a failure happens, if a program is run with
`RUST_LOG=std::rt::backtrace` a backtrace will be printed to the task's stderr
handle.

Currently this is not an exported interface because it's only supported on
osx/linux. I found that windows/freebsd/android all required extra libraries
which are not necessarily present by default.

cc rust-lang#10128
alexcrichton added a commit to alexcrichton/rust that referenced this issue Feb 27, 2014
Whenever a failure happens, if a program is run with
`RUST_LOG=std::rt::backtrace` a backtrace will be printed to the task's stderr
handle. Stack traces are uncondtionally printed on double-failure and
rtabort!().

This ended up having a nontrivial implementation, and here's some highlights of
it:

* We're bundling libbacktrace for everything but OSX and Windows
* We use libgcc_s and its libunwind apis to get a backtrace of instruction
  pointers
* On OSX we use dladdr() to go from an instruction pointer to a symbol
* On unix that isn't OSX, we use libbacktrace to get symbols
* Windows, as usual, has an entirely separate implementation

Lots more fun details and comments can be found in the source itself.

Closes rust-lang#10128
alexcrichton added a commit to alexcrichton/rust that referenced this issue Mar 12, 2014
Whenever a failure happens, if a program is run with
`RUST_LOG=std::rt::backtrace` a backtrace will be printed to the task's stderr
handle. Stack traces are uncondtionally printed on double-failure and
rtabort!().

This ended up having a nontrivial implementation, and here's some highlights of
it:

* We're bundling libbacktrace for everything but OSX and Windows
* We use libgcc_s and its libunwind apis to get a backtrace of instruction
  pointers
* On OSX we use dladdr() to go from an instruction pointer to a symbol
* On unix that isn't OSX, we use libbacktrace to get symbols
* Windows, as usual, has an entirely separate implementation

Lots more fun details and comments can be found in the source itself.

Closes rust-lang#10128
alexcrichton added a commit that referenced this issue Mar 13, 2014
Whenever a failure happens, if a program is run with
`RUST_LOG=std::rt::backtrace` a backtrace will be printed to the task's stderr
handle. Stack traces are uncondtionally printed on double-failure and
rtabort!().

This ended up having a nontrivial implementation, and here's some highlights of
it:

* We're bundling libbacktrace for everything but OSX and Windows
* We use libgcc_s and its libunwind apis to get a backtrace of instruction
  pointers
* On OSX we use dladdr() to go from an instruction pointer to a symbol
* On unix that isn't OSX, we use libbacktrace to get symbols
* Windows, as usual, has an entirely separate implementation

Lots more fun details and comments can be found in the source itself.

Closes #10128
bors added a commit that referenced this issue Mar 13, 2014
Whenever a failure happens, if a program is run with
`RUST_LOG=std::rt::backtrace` a backtrace will be printed to the task's stderr
handle. Stack traces are uncondtionally printed on double-failure and
rtabort!().

This ended up having a nontrivial implementation, and here's some highlights of
it:

* We're bundling libbacktrace for everything but OSX and Windows
* We use libgcc_s and its libunwind apis to get a backtrace of instruction
  pointers
* On OSX we use dladdr() to go from an instruction pointer to a symbol
* On unix that isn't OSX, we use libbacktrace to get symbols
* Windows, as usual, has an entirely separate implementation

Lots more fun details and comments can be found in the source itself.

Closes #10128
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.)
Projects
None yet
6 participants