Search code examples
gdbstack-unwindingaddress-sanitizer

How to get line number from libunwind and AddressSanitizer listed as <shared object>+offset?


I often get stack traces from libunwind or AddressSanitizer like this:

#12 0x7ffff4b47063 (/home/janw/src/pl-devel/lib/x86_64-linux/libswipl.so.7.1.13+0x1f5063)
#13 0x7ffff4b2c783 (/home/janw/src/pl-devel/lib/x86_64-linux/libswipl.so.7.1.13+0x1da783)
#14 0x7ffff4b2cca4 (/home/janw/src/pl-devel/lib/x86_64-linux/libswipl.so.7.1.13+0x1daca4)
#15 0x7ffff4b2cf42 (/home/janw/src/pl-devel/lib/x86_64-linux/libswipl.so.7.1.13+0x1daf42)

I know that if I have gdb attached to the still living process, I can use this to get details on the location:

(gdb) list *0x7ffff4b47063

But if the process has died, I can not just restart it under gdb and use the above because address randomization makes that I get the wrong result (at least, that is my assumption; I clearly do not get meaningful locations). So, I tried

% gdb program
% run
<get to the place everything is loaded and type Control-C>
(gdb) info shared
<Dumps mapping location of shared objects>
(gdb) list *(<base of libswipl.so.7.1.13>+0x1f5063)

But, this either lists nothing or clearly the wrong location. This sounds simple, but I failed to find the answer :-( Platform is 64-bit Linux, but I guess this applies to any platform.


Solution

  • (gdb) info shared
    <Dumps mapping location of shared objects>

    Unfortunately, above does not dump actual mapping location that is usable with this:

    libswipl.so.7.1.13+0x1f5063

    (as you've discovered). Rather, GDB output lists where the .text section was mapped, not where the ELF binary itself was mapped.

    You can adjust for .text offset by finding it in

    readelf -WS libswipl.so.7.1.13 | grep '\.text'
    

    It might be easier to use addr2line instead. Something like

    addr2line -fe libswipl.so.7.1.13 0x1f5063 0x1da783
    

    should work.