I'm working on tools to use the DWARF information to do several things, such as finding holes in structures, help in finding inline functions to uninline, etc, the tools are available at this git repository: http://www.kernel.org/git/?p=linux/kernel/git/acme/pahole.git;a=summary One of the tools is called pfunct and one of its outputs is: /* /pub/scm/linux/kernel/git/acme/net-2.6.20/kernel/sched.c:4107 */ int sched_setscheduler(struct task_struct * p, int policy, struct sched_param * param); /* inline expansions in sched_setscheduler: current_thread_info: 7 unlock_task_sighand: 5 get_current: 9 __raw_local_irq_save: 3 task_running: 6 resched_task: 11 raw_local_irq_restore: 2 raw_local_irq_restore: 8 resched_task: 13 */ [acme@newtoy net-2.6.20]$ I.e. it searches in DW_TAG_subprogram trees for DW_TAG_inlined_subroutine entries, and uses the DW_AT_high_pc, DW_AT_low_pc and DW_AT_ranges to print the size of each inline expansion. Another tool goes thru the functions return types, parameter list, variables in all lexical blocks, inline expansions and recursively counts the references to the various tags, in the end it looks for entries that aren't referenced to help in reorganizing includes definitions, etc. In doing this I noticed that not all concrete inline instances are being emitted, such as __task_rq_lock, a inline function, used in sched_setscheduler in the above example, several other cases aren't also emitted, and this is confirmed by using elfutils's readelf as well as binutils equivalent tools. Searching for similar problems I've found the 19191 ticket, where the problem was worse, no concrete inline were being emitted, now most are being emitted, but not all, is this a know issue? More information, dumps, whatever I can do to help in fixing this problem can be provided if requested. This is my first ticket ever for gcc bugzilla, so here are more info: [acme@newtoy net-2.6.20]$ gcc -v Using built-in specs. Target: i686-pc-linux-gnu Configured with: /home/acme/svn/gcc/configure --prefix=/home/acme/gcc-cvs --enable-languages=c --with-dwarf2 --enable-targets=i686-mandriva-linux-gnu --disable-nls --with-gmp=/home/acme/gcc-infrastructure --with-mpfr=/home/acme/gcc-infrastructure Thread model: posix gcc version 4.3.0 20061108 (experimental) [acme@newtoy net-2.6.20]$ But the same problem happens at least with: [acme@newtoy net-2.6.20]$ gcc -v Using built-in specs. Target: i586-mandriva-linux-gnu Configured with: ../configure --prefix=/usr --libexecdir=/usr/lib --with-slibdir=/lib --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --enable-languages=c,c++,ada,fortran,objc,obj-c++,java --host=i586-mandriva-linux-gnu --with-cpu=generic --with-system-zlib --enable-long-long --enable-__cxa_atexit --enable-clocale=gnu --disable-libunwind-exceptions --enable-java-awt=gtk --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --enable-gtk-cairo --enable-ssp --disable-libssp Thread model: posix gcc version 4.1.1 20060724 (prerelease) (4.1.1-3mdk) [acme@newtoy net-2.6.20]$ I've been using Ulrich Drepper's excellent libdw DWARF library, found in the elfutils package.
Can you supply a preprocessed source of sched.c and the options which you compiled it with?
(In reply to comment #1) > Can you supply a preprocessed source of sched.c and the options which you > compiled it with? > Find the kernel/sched.i file attached, the options were these ones: gcc -m32 -Wp,-MD,kernel/.sched.o.d -nostdinc -isystem /home/acme/gcc-cvs/lib/gcc/i686-pc-linux-gnu/4.3.0/include -D__KERNEL__ -Iinclude -Iinclude2 -I/pub/scm/linux/kernel/git/acme/net-2.6.20/include -include include/linux/autoconf.h -I/pub/scm/linux/kernel/git/acme/net-2.6.20/kernel -Ikernel -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O2 -pipe -msoft-float -mpreferred-stack-boundary=2 -march=i686 -ffreestanding -maccumulate-outgoing-args -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -I/pub/scm/linux/kernel/git/acme/net-2.6.20/include/asm-i386/mach-default -Iinclude/asm-i386/mach-default -fomit-frame-pointer -g -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -fno-omit-frame-pointer -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(sched)" -D"KBUILD_MODNAME=KBUILD_STR(sched)" -c -o kernel/sched.o /pub/scm/linux/kernel/git/acme/net-2.6.20/kernel/sched.c
Created attachment 12584 [details] Preprocessed sched.c
The only thing left from __task_rq_lock is a label. If we look at that inlined function, we see: static inline __attribute__((always_inline)) struct rq *__task_rq_lock(struct task_struct *p) { struct rq *rq; repeat_lock_task: rq = (&(*((void)((task_cpu(p))), &per_cpu__runqueues))); do { do { } while (0); (void)0; (void)(&rq->lock); } while (0); if (__builtin_expect(!!(rq != (&(*((void)((task_cpu(p))), &per_cpu__runqueues)))), 0)) { do { do { } while (0); (void)0; (void)(&rq->lock); } while (0); goto repeat_lock_task; } return rq; } the if is never true as rq is always equal to &per_cpu__runqueues. The calls to task_cpu were inlined and we constant proped the value of rq the first of the way through the function which we inlined this to.
(In reply to comment #4) > The only thing left from __task_rq_lock is a label. <SNIP> > task_cpu were inlined and we constant proped the value of rq the first of the > way through the function which we inlined this to. OK, I thought that this was due to something like what you described, even not knowing that much about gcc internals, but I thought that even in this case the DW_TAG_inlined_subroutine would be emitted, or hoped to as it would allow me to do what I want with my tools :-\
Has an interesting discussion about "Thin inlines": http://sourceware.org/ml/dwarf2/2001-q1/msg00124.html
Subject: Re: DWARF: Not all inline concrete instances are being generated On 12 Nov 2006 20:39:43 -0000, acme at mandriva dot com <gcc-bugzilla@gcc.gnu.org> wrote: > > > ------- Comment #5 from acme at mandriva dot com 2006-11-12 20:39 ------- > (In reply to comment #4) > > The only thing left from __task_rq_lock is a label. > > <SNIP> > > > task_cpu were inlined and we constant proped the value of rq the first of the > > way through the function which we inlined this to. > > OK, I thought that this was due to something like what you described, even not > knowing that much about gcc internals, but I thought that even in this case the > DW_TAG_inlined_subroutine would be emitted, or hoped to as it would allow me to > do what I want with my tools :-\ There is nothing to emit debug info about, so we don't.
> > OK, I thought that this was due to something like what you described, even not > > knowing that much about gcc internals, but I thought that even in this case the > > DW_TAG_inlined_subroutine would be emitted, or hoped to as it would allow me to > > do what I want with my tools :-\ > > There is nothing to emit debug info about, so we don't. > Well, at least gcc emits this: <1><a2f2>: Abbrev Number: 65 (DW_TAG_subprogram) DW_AT_sibling : <a324> DW_AT_name : (indirect string, offset: 0x4515): __task_rq_lock DW_AT_decl_file : 1 DW_AT_decl_line : 378 DW_AT_prototyped : 1 DW_AT_type : <9a2f> DW_AT_inline : 3 (declared as inline and inlined) But no DW_TAG_inlined_subroutine, as we've been discussing: [acme@newtoy net-2.6.20]$ readelf -wi ../OUTPUT/qemu/net-2.6.20/kernel/sched.o | grep a2f2 DW_AT_sibling : <a2f2> <1><a2f2>: Abbrev Number: 65 (DW_TAG_subprogram) [acme@newtoy net-2.6.20]$ :-\
Subject: Re: DWARF: Not all inline concrete instances are being generated On 13 Nov 2006 16:16:50 -0000, acme at mandriva dot com <gcc-bugzilla@gcc.gnu.org> wrote: > > > ------- Comment #8 from acme at mandriva dot com 2006-11-13 16:16 ------- > > > OK, I thought that this was due to something like what you described, even not > > > knowing that much about gcc internals, but I thought that even in this case the > > > DW_TAG_inlined_subroutine would be emitted, or hoped to as it would allow me to > > > do what I want with my tools :-\ > > > > There is nothing to emit debug info about, so we don't. > > > > Well, at least gcc emits this: > > <1><a2f2>: Abbrev Number: 65 (DW_TAG_subprogram) > DW_AT_sibling : <a324> > DW_AT_name : (indirect string, offset: 0x4515): __task_rq_lock > DW_AT_decl_file : 1 > DW_AT_decl_line : 378 > DW_AT_prototyped : 1 > DW_AT_type : <9a2f> > DW_AT_inline : 3 (declared as inline and inlined) > > But no DW_TAG_inlined_subroutine, as we've been discussing: > > [acme@newtoy net-2.6.20]$ readelf -wi ../OUTPUT/qemu/net-2.6.20/kernel/sched.o > | grep a2f2 > DW_AT_sibling : <a2f2> > <1><a2f2>: Abbrev Number: 65 (DW_TAG_subprogram) > [acme@newtoy net-2.6.20]$ I'm quite aware of what GCC outputs here :) However, past the initial declarations, we don't output debug information about what the state of the IR is at random points in the compilation, only about what the final output looks like. Since there is no inlined code left, we don't end up saying there is an inlined subroutine. Even if we could change this, i'm not sure we'd want to. It doesn't seem incorrect at all to do what we do. Otherwise, you'd end up with inlined subroutine dies with no low pc/high pc associated with them, which seems nonsensical.
(In reply to comment #9) > > I'm quite aware of what GCC outputs here :) > > However, past the initial declarations, we don't output debug > information about what the state of the IR is at random points in the > compilation, only about what the final output looks like. Since there > is no inlined code left, we don't end up saying there is an inlined > subroutine. > > Even if we could change this, i'm not sure we'd want to. It doesn't > seem incorrect at all to do what we do. > Otherwise, you'd end up with inlined subroutine dies with no low > pc/high pc associated with them, which seems nonsensical. OK, so I'll have to find another way of using the DWARF info to see if a inline routine, such as __task_rq_lock was used at all in the build or was just included in the DWARF info but not referenced anywhere, have to dig more into the available information... BTW, if, in these cases, DW_TAG_subroutine is not referenced, what is the purpose of it being included? Is there a reason my limited knowledge is not realising?
Subject: Re: DWARF: Not all inline concrete instances are being generated > OK, so I'll have to find another way of using the DWARF info to see if a inline > routine, such as __task_rq_lock was used at all in the build or was just > included in the DWARF info but not referenced anywhere, have to dig more into > the available information... > > BTW, if, in these cases, DW_TAG_subroutine is not referenced, what is the > purpose of it being included? Is there a reason my limited knowledge is not > realising? Well, it is referenced. It did exist in the source, and was inlined. That's what we output. DW_TAG_subprogram with no PC range is actually common. Because all the inlined instances were optimized away, there are no DW_TAG_inlined_* entries for them. > > > -- > > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29792 > >
(In reply to comment #11) > Subject: Re: DWARF: Not all inline concrete instances are being generated > > > OK, so I'll have to find another way of using the DWARF info to see if a inline > > routine, such as __task_rq_lock was used at all in the build or was just > > included in the DWARF info but not referenced anywhere, have to dig more into > > the available information... > > > > BTW, if, in these cases, DW_TAG_subroutine is not referenced, what is the > > purpose of it being included? Is there a reason my limited knowledge is not > > realising? > > Well, it is referenced. It did exist in the source, and was inlined. > That's what we output. DW_TAG_subprogram with no PC range is actually > common. > > Because all the inlined instances were optimized away, there are no > DW_TAG_inlined_* entries for them. /me slaps himself in the face Duh, should have checked this :-) [acme@newtoy examples]$ cat a.c static inline int foo(int i) { return i + 10; } int main(void) { } [acme@newtoy examples]$ readelf -wi a |grep foo [acme@newtoy examples]$ Excellent, only if its not static: [acme@newtoy examples]$ cat a.c inline int foo(int i) { return i + 10; } int main(void) { } [acme@newtoy examples]$ readelf -wi a |grep foo DW_AT_name : foo [acme@newtoy examples]$ And in this case my tool, prefcnt, should warn that this routine, inline or not, is not being used at all and is eligible to go to the dustbin. Thanks a lot for your patience and advise, closing the ticket as INVALID.