{"action":"created","issue":{"url":"https://api.github.com/repos/crystal-lang/crystal/issues/3303","repository_url":"https://api.github.com/repos/crystal-lang/crystal","labels_url":"https://api.github.com/repos/crystal-lang/crystal/issues/3303/labels{/name}","comments_url":"https://api.github.com/repos/crystal-lang/crystal/issues/3303/comments","events_url":"https://api.github.com/repos/crystal-lang/crystal/issues/3303/events","html_url":"https://github.com/crystal-lang/crystal/pull/3303","id":176853906,"number":3303,"title":"Backtrace line numbers","user":{"login":"ysbaddaden","id":47380,"avatar_url":"https://avatars.githubusercontent.com/u/47380?v=3","gravatar_id":"","url":"https://api.github.com/users/ysbaddaden","html_url":"https://github.com/ysbaddaden","followers_url":"https://api.github.com/users/ysbaddaden/followers","following_url":"https://api.github.com/users/ysbaddaden/following{/other_user}","gists_url":"https://api.github.com/users/ysbaddaden/gists{/gist_id}","starred_url":"https://api.github.com/users/ysbaddaden/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ysbaddaden/subscriptions","organizations_url":"https://api.github.com/users/ysbaddaden/orgs","repos_url":"https://api.github.com/users/ysbaddaden/repos","events_url":"https://api.github.com/users/ysbaddaden/events{/privacy}","received_events_url":"https://api.github.com/users/ysbaddaden/received_events","type":"User","site_admin":false},"labels":[{"id":389899022,"url":"https://api.github.com/repos/crystal-lang/crystal/labels/debugger","name":"debugger","color":"ebca04","default":false},{"id":20487869,"url":"https://api.github.com/repos/crystal-lang/crystal/labels/enhancement","name":"enhancement","color":"84b6eb","default":true}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":20,"created_at":"2016-09-14T09:07:10Z","updated_at":"2016-12-07T18:10:37Z","closed_at":"2016-11-18T16:13:22Z","pull_request":{"url":"https://api.github.com/repos/crystal-lang/crystal/pulls/3303","html_url":"https://github.com/crystal-lang/crystal/pull/3303","diff_url":"https://github.com/crystal-lang/crystal/pull/3303.diff","patch_url":"https://github.com/crystal-lang/crystal/pull/3303.patch"},"body":"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.\r\n\r\nFor example:\r\n\r\n```\r\n0x452124: ??? at /home/github/crystal/test_addr2line.cr 4:5\r\n0x42be4e: ??? at /home/github/crystal/test_addr2line.cr 13:13\r\n0x428043: ??? at /home/github/crystal/src/signal.cr 129:1\r\n0x42bd29: main at /home/julien/.cache/crystal/macro67505680.cr 12:15\r\n0x7fcffd0b9f45: __libc_start_main at ??\r\n0x4279f9: ??? at ??\r\n0x0: ??? at ??\r\n```\r\n\r\nAs 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.\r\n\r\nTODO:\r\n- [x] parse ELF files (Linux, FreeBSD)\r\n- [x] parse Mach-O files (OSX)\r\n  - [x] locate the \"companion dSYM file\" with the DWARF symbols (OSX)\r\n  - [x] determinate the \"image slide\" of the loaded program (ASLR) to offset the addresses\r\n  - [ ] ~~read DWARF sections from `.o` files (mapping offsets)~~ (abandoned, see https://github.com/crystal-lang/crystal/pull/3303#issuecomment-248095455)\r\n- [x] parse DWARF line number section\r\n- [x] parse DWARF info, abbrev and str sections\r\n- [x] print file line:column information when printing a backtrace (#1270)\r\n- [x] skip implementation details when raising an exception (#3161)\r\n\r\n~~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 :sob: \r\n\r\nPOSTPONED (follow up pull request):\r\n- [ ] print the function name from the DWARF info (then fallback on seeking the symbol with `dladdr`)\r\n- [ ] parse symtabs section of ELF files (when DWARF info is missing)\r\n- [ ] parse symtabs section of Mach-O files (when DWARF info is missing)\r\n"},"comment":{"url":"https://api.github.com/repos/crystal-lang/crystal/issues/comments/265525174","html_url":"https://github.com/crystal-lang/crystal/pull/3303#issuecomment-265525174","issue_url":"https://api.github.com/repos/crystal-lang/crystal/issues/3303","id":265525174,"user":{"login":"asterite","id":209371,"avatar_url":"https://avatars.githubusercontent.com/u/209371?v=3","gravatar_id":"","url":"https://api.github.com/users/asterite","html_url":"https://github.com/asterite","followers_url":"https://api.github.com/users/asterite/followers","following_url":"https://api.github.com/users/asterite/following{/other_user}","gists_url":"https://api.github.com/users/asterite/gists{/gist_id}","starred_url":"https://api.github.com/users/asterite/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/asterite/subscriptions","organizations_url":"https://api.github.com/users/asterite/orgs","repos_url":"https://api.github.com/users/asterite/repos","events_url":"https://api.github.com/users/asterite/events{/privacy}","received_events_url":"https://api.github.com/users/asterite/received_events","type":"User","site_admin":false},"created_at":"2016-12-07T18:10:37Z","updated_at":"2016-12-07T18:10:37Z","body":"Some time ago the name given to procs like `->{ ... }` or captured blocks was `~proc1`, `~proc2`, etc. Not very descriptive. Now, since that's not very helpful, I decided to add their full location to the name. That way when they are shown in the backtrace you can trace back their location, even without compiling with `-d`. For example:\r\n\r\n```cr\r\ndef foo\r\n  a = ->{\r\n    raise \"OH NO!\"\r\n  }\r\n  a.call\r\nend\r\n\r\nfoo\r\n```\r\n\r\nRunning it we get:\r\n\r\n```\r\nOH NO! (Exception)\r\n0x108bbe662: *CallStack::unwind:Array(Pointer(Void)) at ??\r\n0x108bbe601: *CallStack#initialize:Array(Pointer(Void)) at ??\r\n0x108bbe5d8: *CallStack::new:CallStack at ??\r\n0x108bba7a1: *raise<Exception>:NoReturn at ??\r\n0x108bba781: *raise<String>:NoReturn at ??\r\n0x108bbdcb3: ~procProc(NoReturn)@foo.cr:2 at ??\r\n0x108bbdc87: *foo:NoReturn at ??\r\n0x108bba348: __crystal_main at ??\r\n0x108bbdb28: main at ??\r\n```\r\n\r\nNote 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 `def foo` in our program in the corresponding type. For a proc, the info is right there.\r\n\r\nWe can change it back to `~procN`, but then this info will be lost even without compiling with `-d`, so I'm not sure. I don't think those names bother much (on the contrary, I think they are very useful)"}}
{"actor":{"display_login":"asterite"}}