[Ltrace-devel] Getting prototypes from debug information

Petr Machata pmachata at redhat.com
Fri May 2 12:57:11 UTC 2014


Dima Kogan <lists at dima.secretsauce.net> writes:

> 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:

These are all declarations (DW_AT_declaration of 1), that's why they
don't have DW_AT_low_pc and DW_AT_high_pc (and/or DW_AT_entry_pc).
Unfortunately they are probably implemented in assembly, and debug info
is not emitted for them.  (I seem to recall people talking about
annotating the assembly in glibc by hand, but I think this was only for
stack unwinding, not for actual Dwarf reflection.)

>
> $ 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.

I guess.  You'll have to scan the symbol table by hand, as in internal
ltrace structures, only one of these symbols will have survived (the
shorter one).  We don't keep lists of alternative names.  In theory, we
could--ltrace would the look for a prototype based on each of these
alternative names.  This would allow you to just add prototypes based on
their natural debug info entry name (and DW_AT_{MIPS_,}linkage_name as
well), and have ltrace pick whichever of them.

> 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) +++

It does work for a conf-based prototype (if I add __nanosleep into
libc.so.6.conf).  Again, having this reduced to a trivial reproducer
(that can afterwards be included in the test suite) might be helpful.

Thanks,
PM



More information about the Ltrace-devel mailing list