-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Backtrace line numbers #3303
Backtrace line numbers #3303
Conversation
elf.read_section?(".debug_line") do |sh, io| | ||
Debug::DWARF::LineNumbers.new(io, sh.size) | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I chose to memoize the decompressed DWARF line numbers section in memory. This consumes some memory (around 8MB for the Crystal compiler) but this is only generated when printing the backtraces, and it will save time to avoid decompressing the whole section each time an exception is raised, for a service that rescues exceptions and logs them.
Here comes support for parsing Mach-O files... except that the DWARF sections aren't located in the executable Mach-O file itself (unlike ELF), but in its companion dSYM file (which is also a Mach-O file) which isn't even generated unless we ask for it using I'm not exactly sure what to do.
|
Note that Go actually generates its own sections ( |
Injecting segments and sections at link time is relatively easy. We just have to pass Calling |
@waj I investigated parsing the DWARF directly from the The The best information I could find (not actual documentation):
I propose to:
I'm too lazy to invest more time in redoing what the Line Numbers in optimized code As per the LLVM documentation, the DWARF information should be as proper in optimized builds as in non-optimized builds, so line number information (and everything else) should still be relevant when shipping software built with |
6603005
to
93d0bfb
Compare
Now with support for OSX... somewhat... that is only if there is an up-to-date dSYM bundle generated with Example:
Maybe Crystal could run |
It seems for 32 bits a type is wrong. After that I think this should be green :-) |
Hello @ysbaddaden, this is pure gold! 😄 I did a quick test and compared with lldb (how I use it right now) and your changes: def foo
bar
end
def bar
baz
end
def baz
raise "BOOM"
end
foo
Current: https://gist.github.com/luislavena/b323cbd50600171f355cad4c31e1e0f1#file-run-foo-log Noticed this misses some of the symbols from the callstack (foo & bar), but got the last one correctly. Wondering if there are chances we can learn something from Rust and backtraces-rs |
@luislavena I don't decode the function names from the DWARF sections (yet). It's still using |
I still have more work to achieve because of ASLR on some platforms. I already fixed it manually for OSX (using |
030c4f7
to
fb14b1c
Compare
d6e0161
to
e2442fd
Compare
Almost done: I fixed the ASLR issue on Linux with the PaX patch applied (e,g, Alpine Linux): just use I also found an issue in DWARF::LineNumbers which wrongly expected the matrix' sequences to have growing addresses —found on Alpine Linux. Symbols will come in another pull request. OSX prints all symbols, but linux is missing a lot, and on ARM, it doesn't print a single one :'( |
191de70
to
a3ce5b6
Compare
It looks like Travis eventually fails because |
@asterite done! |
Supports all currently supported platforms: Darwin, FreeBSD, Linux and OpenBSD. Takes care to offset the unwinded addresses to match the fixed addresses of the DWARF sections whtn the platform uses ASLR.
Skips any call in the callstack that relates to creating the exception, unwinding the stack or raising the exception, so the first backtrace entry is the call that did raise an exception. closes crystal-lang#3161
d8f696f
to
04a529c
Compare
Rebased on master with a clean commit history, and removed Debug::DWARF::Info and Debug::DWARF::Abbrev parsers, that will come in an upcoming pull request, where I'll replace the raw symbols for the nice function name stored in the |
require "tempfile" | ||
|
||
describe "Backtrace" do | ||
it "prints file line:colunm" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
line:column
😉
Backtrace lines for Instead of showing the
|
That is actually the name of the proc that is being generated, and not part of the backtrace that @ysbaddaden is generating |
@asterite Would it be possible to move it into the backtrace part of the line? |
@Sija But it's part of the function symbol name, and we should display the exact function symbol names to aid using C debuggers and the likes. |
@Sija I suspect the compiler doesn't set the location when generating the LLVM IR for procs, because since it's a symbol, it should have a location in DWARF. @RX14 actually we should display the function name from DWARF, instead of the mangled name. I don't know what name are given to procs, though. |
Some time ago the name given to procs like def foo
a = ->{
raise "OH NO!"
}
a.call
end
foo Running it we get:
Note how we can go back from the stack trace to every line in our program, except the line that effectively threw the exception. For methods, we'll, we just search We can change it back to |
@ysbaddaden I think we should have the option to display mangled names at least |
Alternative to #3170 which implements ELF, Mach-O and DWARF parsers (instead on relying on the external
addr2line
executable) to parse the running program, looking for the.debug_line
section to be decompressed to print a backtrace which includes the originating file line and columns for each line of the backtrace.For example:
As you may notice, the symbol names are sometimes not properly found. Work as begun to parse the DWARF address to symbol debug information. Since the binaries generated on Linux don't contain the
.debug_aranges
section (neither with gcc or clang), I begun to reconstruct it from the.debug_info
(which relies on the.debug_abbrev
and.debug_str
sections) instead of creating a parser for DWARF aranges.TODO:
read DWARF sections from(abandoned, see Backtrace line numbers #3303 (comment)).o
files (mapping offsets)Hopefully OSX now uses DWARF instead of STABS, so we won't have to add support for another debug format to support OSX.OSX keep the DWARF sections in the.o
files but will NEVER put them into the executable 😭POSTPONED (follow up pull request):
dladdr
)