This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] btrace: read entire aux buffer


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=db58b3735f45345c06cb9a14d0f83f5b26c1ebf3

commit db58b3735f45345c06cb9a14d0f83f5b26c1ebf3
Author: Markus Metzger <markus.t.metzger@intel.com>
Date:   Fri Oct 14 09:08:01 2016 +0200

    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

Diff:
---
 gdb/ChangeLog          |  5 +++++
 gdb/nat/linux-btrace.c | 19 +++++++++++++++----
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b4398f6..600925f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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.
diff --git a/gdb/nat/linux-btrace.c b/gdb/nat/linux-btrace.c
index 5ac5db2..e4144c6 100644
--- a/gdb/nat/linux-btrace.c
+++ b/gdb/nat/linux-btrace.c
@@ -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;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]