From: Wangnan (F) [mailto:wangnan0@xxxxxxxxxx]Ah, I see. Uprobes may not check the target binary is in 32bit mode.
On 2016/1/20 21:59, Arnaldo Carvalho de Melo wrote:
Em Tue, Jan 19, 2016 at 09:33:06PM +0000, Ben Hutchings escreveu:This patch lead me find a bug in original code.
gcc 5 doesn't seem to care about these, but gcc 6 does and thatBen, please CC the people on the CC list for the patch that introduces
results in a build failure.
the problem, Wang, He, can I have your Acked-by?
- Arnaldo
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>
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.
Right, but I guess this can fixed by switching %sp (for x86-64)
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.
and +0(%sp) (for x86-32) instead of $stack.