[Ltrace-devel] Getting prototypes from debug information
Dima Kogan
lists at dima.secretsauce.net
Fri May 2 06:45:19 UTC 2014
Petr Machata <pmachata at redhat.com> writes:
>> Note that nanosleep didn't get its prototype parsed even though the
>> DWARF is available. It turns out that the exported symbol is indeed
>> called "nanosleep", but the DWARF definitions have a DW_AT_name of
>> "__nanosleep" and a DW_AT_linkage_name "__GI___nanosleep". The DWARF has
>> no mention at all of "nanosleep", which is the main issue. How can we
>> infer a connection between those two?
>
> I think what should work here is to look at DW_AT_low_pc of the
> DW_TAG_subprogram (dwarf_lowpc in libdw seems to be handling this) and
> cross-match it with ELF symbol tables, where each address will have a
> number of alias symbols. I guess you could just walk through ltrace's
> own data structures, struct library and struct library_symbol, and look
> into ::enter_addr of the latter to figure out what symbol name ltrace
> assigned to this address.
Hmmm. I just looked into this a bit more, and there are more questions
than answers. First off, there are several "__nanosleep" dies in
libc6.so. Our code just uses the first one.
Compile-unit '../nptl/sysdeps/unix/sysv/linux/sleep.c' @ 0x20b13a
<1><20c7ce>: Abbrev Number: 72 (DW_TAG_subprogram)
<20c7cf> DW_AT_external : 1
<20c7cf> DW_AT_name : (indirect string, offset: 0x13a95): __nanosleep
<20c7d3> DW_AT_decl_file : 32
<20c7d4> DW_AT_decl_line : 92
<20c7d5> DW_AT_linkage_name: (indirect string, offset: 0x13a90): __GI___nanosleep
<20c7d9> DW_AT_prototyped : 1
<20c7d9> DW_AT_type : <0x20b1b2>
<20c7dd> DW_AT_declaration : 1
<20c7dd> DW_AT_sibling : <0x20c7ec>
Compile-unit '../sysdeps/unix/sysv/linux/usleep.c' @ 0x280c56
<1><280d66>: Abbrev Number: 12 (DW_TAG_subprogram)
<280d67> DW_AT_external : 1
<280d67> DW_AT_name : (indirect string, offset: 0x13a95): __nanosleep
<280d6b> DW_AT_decl_file : 5
<280d6c> DW_AT_decl_line : 92
<280d6d> DW_AT_linkage_name: (indirect string, offset: 0x13a90): __GI___nanosleep
<280d71> DW_AT_prototyped : 1
<280d71> DW_AT_type : <0x280ca2>
<280d75> DW_AT_declaration : 1
<280d75> DW_AT_sibling : <0x280d84>
Compile-unit 'svc.c' @ 0x3ae74c
<1><3b0b58>: Abbrev Number: 83 (DW_TAG_subprogram)
<3b0b59> DW_AT_external : 1
<3b0b59> DW_AT_name : (indirect string, offset: 0x13a95): __nanosleep
<3b0b5d> DW_AT_decl_file : 33
<3b0b5e> DW_AT_decl_line : 92
<3b0b5f> DW_AT_linkage_name: (indirect string, offset: 0x13a90): __GI___nanosleep
<3b0b63> DW_AT_prototyped : 1
<3b0b63> DW_AT_type : <0x3ae76e>
<3b0b67> DW_AT_declaration : 1
<3b0b67> DW_AT_sibling : <0x3b0b76>
Note that these all lack a DW_AT_low_pc. Yet this works in gdb as
"nanosleep". I have a theory. Look:
$ nm -D /lib/x86_64-linux-gnu/libc-2.18.so | grep -P ' _*(?:GI)?_*nanosleep'
00000000000b7070 W __nanosleep
00000000000b7070 W nanosleep
So both of these resolve to the same address, and gdb maybe matches them
up this way. We can too.
And another (related?) issue. I have tst.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
int main(void)
{
__nanosleep( &(struct timespec){.tv_sec=0,.tv_nsec=1000}, NULL);
return 0;
}
I build it with 'gcc -std=gnu99 -o /tmp/tst{,.c}'
Here I used "__nanosleep" instead of "nanosleep", so ltrace should pick
it up.... But it doesn't:
$ ./ltrace -x '*sleep at libc.so*' /tmp/tst
__libc_start_main(0x40051d, 1, 0x7fffe4516b68, 0x400560 <unfinished ...>
__nanosleep(0x7fffe4516a70, 0, 0x7fffe4516b78, 0 <unfinished ...>
nanosleep at libc.so.6(0x7fffe4516a70, 0, 0x7fffe4516b78, 0) = 0
<... __nanosleep resumed> ) = 0
+++ exited (status 0) +++
If you have any thoughts about these, I'd love to hear about it.
Otherwise, I'll look again in a few days. Sorry about asking lots of
questions, I'm just hoping that somebody has already seen these issues
before.
dima
More information about the Ltrace-devel
mailing list