btrace: read entire aux buffer
The data_head of a perf event data buffer grows indefinitely. Users are expected to compute data_head % data_size to find the location inside the perf event data buffer. The aux_head of a perf event aux buffer wraps around and always stays within the perf event aux buffer. Well, at least that's the behaviour for BTS and PT - where BTS uses the data buffer and PT the aux buffer. GDB does not read beyond data_head or aux_head. This is OK for BTS but wrong for PT. It causes only a portion of the trace to be considered by GDB. In the extreme case, the buffer may appear (almost) empty. Thanks to Tim Wiederhake <tim.wiederhake@intel.com> for reporting the anomaly. Change it to read the entire aux buffer for PT. The buffer is initially zero so any extra zeroes we read before aux_head wraps around the first time will be ignored when searching for the first PSB packet in order to synchronize onto the trace stream. gdb/ * nat/linux-btrace.c (perf_event_read): Allow data_head < size. * nat/linux-btrace.c (perf_event_read_all): Do not adjust size. Change-Id: If4f8049a2080a5f16f336309450b32a3eb1e3ec9
This commit is contained in:
parent
80bb3407f6
commit
db58b3735f
@ -1,3 +1,8 @@
|
||||
2016-11-14 Markus Metzger <markus.t.metzger@intel.com>
|
||||
|
||||
* nat/linux-btrace.c (perf_event_read): Allow data_head < size.
|
||||
* nat/linux-btrace.c (perf_event_read_all): Do not adjust size.
|
||||
|
||||
2016-11-12 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* rust-exp.y (super_name): Use std::vector.
|
||||
|
@ -119,10 +119,24 @@ perf_event_read (const struct perf_event_buffer *pev, __u64 data_head,
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
|
||||
/* We should never ask for more data than the buffer can hold. */
|
||||
buffer_size = pev->size;
|
||||
gdb_assert (size <= buffer_size);
|
||||
|
||||
/* If we ask for more data than we seem to have, we wrap around and read
|
||||
data from the end of the buffer. This is already handled by the %
|
||||
BUFFER_SIZE operation, below. Here, we just need to make sure that we
|
||||
don't underflow.
|
||||
|
||||
Note that this is perfectly OK for perf event buffers where data_head
|
||||
doesn'grow indefinitely and instead wraps around to remain within the
|
||||
buffer's boundaries. */
|
||||
if (data_head < size)
|
||||
data_head += buffer_size;
|
||||
|
||||
gdb_assert (size <= data_head);
|
||||
data_tail = data_head - size;
|
||||
|
||||
buffer_size = pev->size;
|
||||
begin = pev->mem;
|
||||
start = begin + data_tail % buffer_size;
|
||||
stop = begin + data_head % buffer_size;
|
||||
@ -153,10 +167,7 @@ perf_event_read_all (struct perf_event_buffer *pev, gdb_byte **data,
|
||||
__u64 data_head;
|
||||
|
||||
data_head = *pev->data_head;
|
||||
|
||||
size = pev->size;
|
||||
if (data_head < size)
|
||||
size = (size_t) data_head;
|
||||
|
||||
*data = perf_event_read (pev, data_head, size);
|
||||
*psize = size;
|
||||
|
Loading…
Reference in New Issue
Block a user