Bug 18955 - GDBserver does not compile fast tracepoint conditions correctly on x86/i386
Summary: GDBserver does not compile fast tracepoint conditions correctly on x86/i386
Status: NEW
Alias: None
Product: gdb
Classification: Unclassified
Component: remote (show other bugs)
Version: HEAD
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-09-11 17:05 IST by Pierre Langlois
Modified: 2015-09-11 17:05 IST (History)
0 users

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Pierre Langlois 2015-09-11 17:05:16 IST
I noticed some conditions on fast tracepoints do not work as expected, and
in some cases can cause GDBserver to segfault.  I investigated the issue
and found that reading registers was the cause of some of these issues, but
not all.

Here is a transcript of debugging gdb.trace/ftrace.c, testing the following
condition: `$rip == *set_point', which should always return true.
~~~
(gdb) b begin
Breakpoint 1 at 0x4006aa: file ../../../binutils-gdb/gdb/testsuite/gdb.trace/ftrace.c, line 28.
(gdb) b end
Breakpoint 2 at 0x4006c8: file ../../../binutils-gdb/gdb/testsuite/gdb.trace/ftrace.c, line 62.
(gdb) c
Continuing.
Reading /scratch/pierre/x86-gdb-build/gdb/testsuite/../gdbserver/libinproctrace.so from remote target...
Reading /lib/x86_64-linux-gnu/libm.so.6 from remote target...
Reading /lib/x86_64-linux-gnu/libc.so.6 from remote target...
Reading /lib/x86_64-linux-gnu/libpthread.so.0 from remote target...
Reading /lib/x86_64-linux-gnu/libm-2.19.so from remote target...
Reading /lib/x86_64-linux-gnu/.debug/libm-2.19.so from remote target...
Reading /lib/x86_64-linux-gnu/libc-2.19.so from remote target...
Reading /lib/x86_64-linux-gnu/.debug/libc-2.19.so from remote target...
Reading /lib/x86_64-linux-gnu/libpthread-2.19.so from remote target...
Reading /lib/x86_64-linux-gnu/.debug/libpthread-2.19.so from remote target...
[New Thread 25454]

Breakpoint 1, begin () at ../../../binutils-gdb/gdb/testsuite/gdb.trace/ftrace.c:28
28	{}
(gdb) ftrace set_point if $rip == *set_point
Fast tracepoint 3 at 0x4006b9: file ../../../binutils-gdb/gdb/testsuite/gdb.trace/ftrace.c, line 41.
(gdb) tstart
(gdb) c
Continuing.

Breakpoint 2, end () at ../../../binutils-gdb/gdb/testsuite/gdb.trace/ftrace.c:62
62	{}
(gdb) tstop
(gdb) tstatus
Trace stopped by a tstop command ().
Collected 0 trace frames.
^^^^^^^^^^^^^^^^^^^^^^^^^
Trace buffer has 5242880 bytes of 5242880 bytes free (0% full).
Trace will stop if GDB disconnects.
Not looking at any trace frame.
Trace started at 1441990470.739096 secs, stopped 3.453575 secs later.
(gdb) q
A debugging session is active.

	Inferior 1 [process 25170] will be killed.

Quit anyway? (y or n) y
~~~

We can see that reading the program counter gave us the wrong value.

Since reading registers does not work, it can cause GDBserver to crash, for
example, using the condition `anarg == 100' which looks up a variable on the stack:

~~~
(gdb) b begin
Breakpoint 1 at 0x4006aa: file ../../../binutils-gdb/gdb/testsuite/gdb.trace/ftrace.c, line 28.
(gdb) b end
Breakpoint 2 at 0x4006c8: file ../../../binutils-gdb/gdb/testsuite/gdb.trace/ftrace.c, line 62.
(gdb) c
Continuing.
Reading /scratch/pierre/x86-gdb-build/gdb/testsuite/../gdbserver/libinproctrace.so from remote target...
Reading /lib/x86_64-linux-gnu/libm.so.6 from remote target...
Reading /lib/x86_64-linux-gnu/libc.so.6 from remote target...
Reading /lib/x86_64-linux-gnu/libpthread.so.0 from remote target...
Reading /lib/x86_64-linux-gnu/libm-2.19.so from remote target...
Reading /lib/x86_64-linux-gnu/.debug/libm-2.19.so from remote target...
Reading /lib/x86_64-linux-gnu/libc-2.19.so from remote target...
Reading /lib/x86_64-linux-gnu/.debug/libc-2.19.so from remote target...
Reading /lib/x86_64-linux-gnu/libpthread-2.19.so from remote target...
Reading /lib/x86_64-linux-gnu/.debug/libpthread-2.19.so from remote target...
[New Thread 33718]

Breakpoint 1, begin () at ../../../binutils-gdb/gdb/testsuite/gdb.trace/ftrace.c:28
28	{}
(gdb) ftrace set_point if anarg == 100
Fast tracepoint 3 at 0x4006b9: file ../../../binutils-gdb/gdb/testsuite/gdb.trace/ftrace.c, line 41.
(gdb) tstart
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x000000000001004f in ?? ()
(gdb) q
A debugging session is active.

	Inferior 1 [process 33261] will be killed.

Quit anyway? (y or n) y
Trace is running but will stop on detach; detach anyway? (y or n) y
~~~

I have a patch fixing reading register which I'll post on gdb-patches along
with a test case.  However, their seem to be additional issues, with the
following conditions for example:

On x86_64 only:
* `anarg == 100 || anarg == 200'
* `anarg == 100 && globvar == 1'

On i386 only:
* `(21 < 42 ? 0 : 1) == 0'
* `(42 > 21 ? 0 : 1) == 0'