>From: Wangnan (F) [mailto:wangn...@huawei.com] > >On 2016/1/20 21:59, Arnaldo Carvalho de Melo wrote: >> Em Tue, Jan 19, 2016 at 09:33:06PM +0000, Ben Hutchings escreveu: >>> gcc 5 doesn't seem to care about these, but gcc 6 does and that >>> results in a build failure. >> Ben, please CC the people on the CC list for the patch that introduces >> the problem, Wang, He, can I have your Acked-by? >> >> - Arnaldo >> > >This patch lead me find a bug in original code. > >If both perf and target ELF binary is x86_64, following command works okay: > > # perf probe -v -n --exec /tmp/oxygen_root/lib64/libc.so.6 pselect >data exceptfds readfds writefds nfds sigmask tval timeout > <SNIP> > Opening /sys/kernel/debug/tracing//uprobe_events write=1 > Writing event: p:probe_libc/pselect >/home/w00229757/oxygen_root-w00229757/lib64/libc-2.18.so:0xdfef0 >data=-216(%sp):u64 exceptfds=%cx:u64 readfds=%si:u64 writefds=%dx:u64 >nfds=%di:s32 sigmask=%r9:u64 tval=-232(%sp):u64 timeout=%r8:u64 > <SNIP> > >But if the library is x86_32, result is incorrect: > > # perf probe -v -n --exec /tmp/oxygen_root/lib32/libc.so.6 pselect >data exceptfds readfds writefds nfds sigmask tval > <SNIP> > Writing event: p:probe_libc/pselect >/tmp/oxygen_root-w00229757/lib32/libc-2.18.so:0xd1330 data=-172(%si):u64 >exceptfds=+16(%si):u32 readfds=+8(%si):u32 writefds=+12(%si):u32 >nfds=+4(%si):s32 sigmask=+24(%si):u32 tval=-180(%si):u64 >timeout=+20(%si):u32 > <SNIP> > >We know that (%si) is used to passing arguments. Here we should see >'%sp' or '$stack'. > >Use a x86_32 perf we get currect result: > > # ~/perf probe -v -n --exec /tmp/oxygen_root/lib32/libc.so.6 pselect >data exceptfds readfds writefds nfds sigmask tval > <SNIP> > Writing event: p:probe_libc/pselect >/tmp/oxygen_root-w00229757/lib32/libc-2.18.so:0xd1330 >data=-172($stack):u64 exceptfds=+16($stack):u32 readfds=+8($stack):u32 >writefds=+12($stack):u32 nfds=+4($stack):s32 sigmask=+24($stack):u32 >tval=-180($stack):u64 > <SNIP>
Ah, I see. Uprobes may not check the target binary is in 32bit mode. Since the stack of x86-64 and x86-32 on pt_regs are different, (regs->sp points stack on x86-64, &(regs->pt) points stack on x86-32) uprobes would better checking and change the behavior. But anyway, it is also fixed by changing perf's register table. > > >Use a small test program to check the result: > > #include <sys/time.h> > #include <sys/types.h> > #include <unistd.h> > #include <memory.h> > > static struct { > fd_set r, w, e; > struct timespec ts; > sigset_t m; > } s; > > int main() > { > memset(&s, '\0', sizeof(s)); > > pselect(0, &s.r, &s.w, &s.e, &s.ts, &s.m); > return 0; > } > ># gcc -m32 -g ./test_pselect.c > >Use x86_32 perf: > ># ./perf probe -v --exec /tmp/oxygen_root/lib32/libc.so.6 pselect data >exceptfds readfds writefds nfds sigmask tval >Writing event: p:probe_libc/pselect >/tmp/oxygen_root-w00229757/lib32/libc-2.18.so:0xd1330 >data=-172($stack):u64 exceptfds=+16($stack):u32 readfds=+8($stack):u32 >writefds=+12($stack):u32 nfds=+4($stack):s32 sigmask=+24($stack):u32 >tval=-180($stack):u64 >Added new event: > probe_libc:pselect (on pselect in >/tmp/oxygen_root-w00229757/lib32/libc-2.18.so with data exceptfds >readfds writefds nfds sigmask tval) > >You can now use it in all perf tools, such as: > > perf record -e probe_libc:pselect -aR sleep 1 > ># ./perf record -e probe_libc:pselect ./a.out >[ perf record: Woken up 1 times to write data ] >[ perf record: Captured and wrote 0.011 MB perf.data (1 samples) ] ># ./perf script > a.out 25336 [006] 64588.457597: probe_libc:pselect: >(f7663330) data=0xf772e00000000000 exceptfds=0x8049880 readfds=0x8049780 >writefds=0x8049800 nfds=0 sigmask=0x8049908 tval=0x0 > >Switch to x86_64 perf: > > # ./perf probe -v --exec /tmp/oxygen_root/lib32/libc.so.6 pselect >data exceptfds readfds writefds nfds sigmask tval > <SNIP> > Opening /sys/kernel/debug/tracing//uprobe_events write=1 >Writing event: p:probe_libc/pselect >/tmp/oxygen_root-w00229757/lib32/libc-2.18.so:0xd1330 data=-172(%si):u64 >exceptfds=+16(%si):u32 readfds=+8(%si):u32 writefds=+12(%si):u32 >nfds=+4(%si):s32 sigmask=+24(%si):u32 tval=-180(%si):u64 >Added new event: > probe_libc:pselect (on pselect in >/tmp/oxygen_root-w00229757/lib32/libc-2.18.so with data exceptfds >readfds writefds nfds sigmask tval) > >You can now use it in all perf tools, such as: > > perf record -e probe_libc:pselect -aR sleep 1 > ># ./perf record -e probe_libc:pselect ./a.out >[ perf record: Woken up 1 times to write data ] >[ perf record: Captured and wrote 0.011 MB perf.data (1 samples) ] ># ./perf script > a.out 25599 [002] 64759.743554: probe_libc:pselect: >(f76e7330) data=0x0 exceptfds=0x0 readfds=0x0 writefds=0x0 nfds=0 >sigmask=0x0 tval=0x0 > >Sad... > >I think this problem is not introduced by my patch. In fact >there's a fundamental problem in get_arch_regstr() that it is >impossible to switch sub ISA. Right, but I guess this can fixed by switching %sp (for x86-64) and +0(%sp) (for x86-32) instead of $stack. Thanks! > >Not only x86_64 and x86_32, I think on arm64 we also have this >problem when we try to setup uprobes on arm32 code. For me the >later problem is more important because there are many legacy arm32 >applications on Android platform (and I have already seen the buggy >unwind result in this case. It is another problem though). > >So I suggest us to solve this problem first before considering >gcc 6 Werror. At least x86_32_regoffset_table and x86_64_regoffset_table >should both be compiled no matter which ISA we select for perf. > >Thank you.