On Sat, Aug 22, 2015 at 12:18:46PM +0200, Ben Gamari wrote: > Mark Wielaard <m...@redhat.com> writes: > > > On Fri, Aug 21, 2015 at 06:25:38PM +0200, Ben Gamari wrote: > >> Does elfutils need .debug_ranges as well? > > > > Only if the DWARF producer created DIEs with DW_AT_ranges attributes. > > You seem to never do that. If your range is just one simple one you can > > just use a DW_AT_low_pc/high_pc pair and .debug_ranges will never be > > used. > > > I actually ask because while we don't produce or use the .debug_ranges > section, they sneak into our executables from the C runtime system > objects. However, whatever is emitting it seems to be doing a > questionable job, > > $ objdump --dwarf-check -e inplace/lib/bin/ghc-stage2 -x > /dev/null > objdump: Warning: There is an overlap [0x780 - 0x750] in .debug_ranges > section.
I wonder why binutils objdump is really warning about that. In this case it looks like the pc ranges might indeed overlap, but that is somewhat expected. I don't think it is actually wrong. e.g. this one seems to be a two nested lexical blocks, the outer block [750] obviously will overlap with the pc ranges of the inner block [780]: [c1bdf9] lexical_block ranges (sec_offset) range list [ 750] [c1bdfe] variable abstract_origin (ref4) [c1bad1] location (sec_offset) location list [ 7269] [...] [c1be46] lexical_block ranges (sec_offset) range list [ 780] [c1be4b] variable abstract_origin (ref4) [c1bb2e] location (exprloc) [ 0] fbreg -68 > You'll be pleased to know that libdw has worked out quite well. For > instance, with my patch [1] GHC can produce a backtrace like, > > 0x6ff81f set_initial_registers (rts/Libdw.c:323.0) > 0x7fd852eaba68 dwfl_thread_getframes ((null):0.0) > 0x7fd852eab4bf (null) ((null):0.0) > 0x7fd852eab7f7 dwfl_getthreads ((null):0.0) > 0x7fd852eabde3 dwfl_getthread_frames ((null):0.0) > 0x6ffbfc libdw_get_backtrace (rts/Libdw.c:295.0) > 0x6f187e backtrace_handler (rts/posix/Signals.c:540.0) > 0x7fd852b0617f (null) ((null):0.0) > 0x407b58 s91t_info (nofib/shootout/n-body/Main.hs:66.27) > 0x407cf8 r8YB_info (nofib/shootout/n-body/Main.hs:83.5) > 0x408408 s99O_info (nofib/shootout/n-body/Main.hs:28.19) > 0x409e80 Main_main1_info (nofib/shootout/n-body/Main.hs:27.26) > 0x6f41c0 stg_catch_frame_info (rts/Exception.cmm:370.1) > 0x6f29a8 stg_stop_thread_info (rts/StgStartup.cmm:42.1) > > There's still a fair amount of work left to integrate this fully, but at > least the tricky DWARF work is done. Very nice! Any idea why the libdw.so/dwfl_ functions don't have any info? Where they simply build without debuginfo? > [1] https://phabricator.haskell.org/D1156 Some quick answers to some of the questions there (I didn't read the full bug report or the patch, so please let me know if you have any specific questions): - portability of elfutils. It is ported across a lot of arches on GNU/Linux. i386, x86_64, ppc, ppc64, ppc64le, s390x, arm and aarch64 are at least regularly tested (should be zero fail at release time) and there are other ports in the backends both in tree [alpha, ia64, sparc, tilegx] and some not yet merged out of tree [mips, m68k, hppa]. In theory it should also work on other ELF/DWARF bases systems like *BSD, Debian has some limited success with kfreebsd, and Solaris. But there are some tricky dependencies of some of the dwfl functions on the /proc file system and ptrace, not all of them have clean backend/ebl functions. Darwin/MacOS is a bit harder since it doesn't use ELF and libdw currently depends on the DWARF container being ELF (and I have no idea what the ptrace/proc story is on Darwin). Windows is probably pretty hard given that it doesn't natively support ELF, DWARF or ptrace/proc. - As I said before between libunwind/elfutils and libbacktrace I actually would have expected libbacktrace to be the easiest for you to use since it is actually designed for in-process unwinding. libunwind tries to do both in- and out-of-process unwinding, which I think is a little confusing, and has much less other functionality than elfutils with respect to model process memory, libraries, ELF, DWARF and symbol inspection. And elfutils really only tries to support out-of-process unwinding (but you happily managed to make it do in-process anyway, so maybe our design isn't so bad). Now that you got your DWARF/CFI correct I would give libbacktrace another go. - To mark an end of stack you should set the CFI rule for the return register to undefined. See 6.4.4 Call Frame Calling Address. On x86_64 the return register is often just equal to rip and so using .cfi_undefined rip (in gas assembler) would do the trick. In general you can find fun and wonderful CFI describing interesting register unwinding tricks in glibc internals (try start.S, clone.S and __longjmp.S). - Yes, perf can use elfutils to do unwinding. It does this "after the fact" It has a initial registers handler and memory read handler like you probably made for the in-process Dwfl_Thread_Callbacks. But they use the dumped register and partial stack dump they made during runtime to do the actual unwinding. So this only works if the CFI in your binary is complete and it is (mostly) expressed through the contents of the initial register dump and the stack values (which is almost always the case). - We could in theory try to cleanup my hack to not need .debug_aranges if we really want to. But I hope we don't now that you have it :) - Why both have pc ranges in the CU and in .debug_aranges (pointing to the CUs)? Because they technically describe different things. The ranges given in the CU are the covered program scope entries (code). While .debug_aranges give the ranges of code and data object addresses described by the CU (although I believe in practice it really is the same and even .debug_aranges only has the code ranges). Secondly it is really mildly more efficient since .debug_aranges is small and compact and doesn't refer to other data sections (the CUs are all spread out in the .debug_info section and can potentially point into the .debug_ranges section when the CU uses DW_AT_low_pc plus DW_AT_ranges to describe more complex pc ranges). Cheers, Mark