GDB (API)
/home/stan/gdb/src/gdb/common/linux-btrace.c
Go to the documentation of this file.
00001 /* Linux-dependent part of branch trace support for GDB, and GDBserver.
00002 
00003    Copyright (C) 2013 Free Software Foundation, Inc.
00004 
00005    Contributed by Intel Corp. <markus.t.metzger@intel.com>
00006 
00007    This file is part of GDB.
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 3 of the License, or
00012    (at your option) any later version.
00013 
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018 
00019    You should have received a copy of the GNU General Public License
00020    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00021 
00022 #ifdef GDBSERVER
00023 #include "server.h"
00024 #else
00025 #include "defs.h"
00026 #endif
00027 
00028 #include "linux-btrace.h"
00029 #include "common-utils.h"
00030 #include "gdb_assert.h"
00031 #include "regcache.h"
00032 #include "gdbthread.h"
00033 #include "gdb_wait.h"
00034 #include "i386-cpuid.h"
00035 
00036 #ifdef HAVE_SYS_SYSCALL_H
00037 #include <sys/syscall.h>
00038 #endif
00039 
00040 #if HAVE_LINUX_PERF_EVENT_H && defined(SYS_perf_event_open)
00041 
00042 #include <errno.h>
00043 #include <string.h>
00044 #include <stdint.h>
00045 #include <unistd.h>
00046 #include <sys/mman.h>
00047 #include <sys/user.h>
00048 #include <sys/ptrace.h>
00049 #include <sys/types.h>
00050 #include <signal.h>
00051 
00052 /* A branch trace record in perf_event.  */
00053 struct perf_event_bts
00054 {
00055   /* The linear address of the branch source.  */
00056   uint64_t from;
00057 
00058   /* The linear address of the branch destination.  */
00059   uint64_t to;
00060 };
00061 
00062 /* A perf_event branch trace sample.  */
00063 struct perf_event_sample
00064 {
00065   /* The perf_event sample header.  */
00066   struct perf_event_header header;
00067 
00068   /* The perf_event branch tracing payload.  */
00069   struct perf_event_bts bts;
00070 };
00071 
00072 /* Get the perf_event header.  */
00073 
00074 static inline volatile struct perf_event_mmap_page *
00075 perf_event_header (struct btrace_target_info* tinfo)
00076 {
00077   return tinfo->buffer;
00078 }
00079 
00080 /* Get the size of the perf_event mmap buffer.  */
00081 
00082 static inline size_t
00083 perf_event_mmap_size (const struct btrace_target_info *tinfo)
00084 {
00085   /* The branch trace buffer is preceded by a configuration page.  */
00086   return (tinfo->size + 1) * PAGE_SIZE;
00087 }
00088 
00089 /* Get the size of the perf_event buffer.  */
00090 
00091 static inline size_t
00092 perf_event_buffer_size (struct btrace_target_info* tinfo)
00093 {
00094   return tinfo->size * PAGE_SIZE;
00095 }
00096 
00097 /* Get the start address of the perf_event buffer.  */
00098 
00099 static inline const uint8_t *
00100 perf_event_buffer_begin (struct btrace_target_info* tinfo)
00101 {
00102   return ((const uint8_t *) tinfo->buffer) + PAGE_SIZE;
00103 }
00104 
00105 /* Get the end address of the perf_event buffer.  */
00106 
00107 static inline const uint8_t *
00108 perf_event_buffer_end (struct btrace_target_info* tinfo)
00109 {
00110   return perf_event_buffer_begin (tinfo) + perf_event_buffer_size (tinfo);
00111 }
00112 
00113 /* Check whether an address is in the kernel.  */
00114 
00115 static inline int
00116 perf_event_is_kernel_addr (const struct btrace_target_info *tinfo,
00117                            uint64_t addr)
00118 {
00119   uint64_t mask;
00120 
00121   /* If we don't know the size of a pointer, we can't check.  Let's assume it's
00122      not a kernel address in this case.  */
00123   if (tinfo->ptr_bits == 0)
00124     return 0;
00125 
00126   /* A bit mask for the most significant bit in an address.  */
00127   mask = (uint64_t) 1 << (tinfo->ptr_bits - 1);
00128 
00129   /* Check whether the most significant bit in the address is set.  */
00130   return (addr & mask) != 0;
00131 }
00132 
00133 /* Check whether a perf event record should be skipped.  */
00134 
00135 static inline int
00136 perf_event_skip_record (const struct btrace_target_info *tinfo,
00137                         const struct perf_event_bts *bts)
00138 {
00139   /* The hardware may report branches from kernel into user space.  Branches
00140      from user into kernel space will be suppressed.  We filter the former to
00141      provide a consistent branch trace excluding kernel.  */
00142   return perf_event_is_kernel_addr (tinfo, bts->from);
00143 }
00144 
00145 /* Perform a few consistency checks on a perf event sample record.  This is
00146    meant to catch cases when we get out of sync with the perf event stream.  */
00147 
00148 static inline int
00149 perf_event_sample_ok (const struct perf_event_sample *sample)
00150 {
00151   if (sample->header.type != PERF_RECORD_SAMPLE)
00152     return 0;
00153 
00154   if (sample->header.size != sizeof (*sample))
00155     return 0;
00156 
00157   return 1;
00158 }
00159 
00160 /* Branch trace is collected in a circular buffer [begin; end) as pairs of from
00161    and to addresses (plus a header).
00162 
00163    Start points into that buffer at the next sample position.
00164    We read the collected samples backwards from start.
00165 
00166    While reading the samples, we convert the information into a list of blocks.
00167    For two adjacent samples s1 and s2, we form a block b such that b.begin =
00168    s1.to and b.end = s2.from.
00169 
00170    In case the buffer overflows during sampling, one sample may have its lower
00171    part at the end and its upper part at the beginning of the buffer.  */
00172 
00173 static VEC (btrace_block_s) *
00174 perf_event_read_bts (struct btrace_target_info* tinfo, const uint8_t *begin,
00175                      const uint8_t *end, const uint8_t *start)
00176 {
00177   VEC (btrace_block_s) *btrace = NULL;
00178   struct perf_event_sample sample;
00179   size_t read = 0, size = (end - begin);
00180   struct btrace_block block = { 0, 0 };
00181   struct regcache *regcache;
00182 
00183   gdb_assert (begin <= start);
00184   gdb_assert (start <= end);
00185 
00186   /* The first block ends at the current pc.  */
00187 #ifdef GDBSERVER
00188   regcache = get_thread_regcache (find_thread_ptid (tinfo->ptid), 1);
00189 #else
00190   regcache = get_thread_regcache (tinfo->ptid);
00191 #endif
00192   block.end = regcache_read_pc (regcache);
00193 
00194   /* The buffer may contain a partial record as its last entry (i.e. when the
00195      buffer size is not a multiple of the sample size).  */
00196   read = sizeof (sample) - 1;
00197 
00198   for (; read < size; read += sizeof (sample))
00199     {
00200       const struct perf_event_sample *psample;
00201 
00202       /* Find the next perf_event sample in a backwards traversal.  */
00203       start -= sizeof (sample);
00204 
00205       /* If we're still inside the buffer, we're done.  */
00206       if (begin <= start)
00207         psample = (const struct perf_event_sample *) start;
00208       else
00209         {
00210           int missing;
00211 
00212           /* We're to the left of the ring buffer, we will wrap around and
00213              reappear at the very right of the ring buffer.  */
00214 
00215           missing = (begin - start);
00216           start = (end - missing);
00217 
00218           /* If the entire sample is missing, we're done.  */
00219           if (missing == sizeof (sample))
00220             psample = (const struct perf_event_sample *) start;
00221           else
00222             {
00223               uint8_t *stack;
00224 
00225               /* The sample wrapped around.  The lower part is at the end and
00226                  the upper part is at the beginning of the buffer.  */
00227               stack = (uint8_t *) &sample;
00228 
00229               /* Copy the two parts so we have a contiguous sample.  */
00230               memcpy (stack, start, missing);
00231               memcpy (stack + missing, begin, sizeof (sample) - missing);
00232 
00233               psample = &sample;
00234             }
00235         }
00236 
00237       if (!perf_event_sample_ok (psample))
00238         {
00239           warning (_("Branch trace may be incomplete."));
00240           break;
00241         }
00242 
00243       if (perf_event_skip_record (tinfo, &psample->bts))
00244         continue;
00245 
00246       /* We found a valid sample, so we can complete the current block.  */
00247       block.begin = psample->bts.to;
00248 
00249       VEC_safe_push (btrace_block_s, btrace, &block);
00250 
00251       /* Start the next block.  */
00252       block.end = psample->bts.from;
00253     }
00254 
00255   return btrace;
00256 }
00257 
00258 /* Check whether the kernel supports branch tracing.  */
00259 
00260 static int
00261 kernel_supports_btrace (void)
00262 {
00263   struct perf_event_attr attr;
00264   pid_t child, pid;
00265   int status, file;
00266 
00267   errno = 0;
00268   child = fork ();
00269   switch (child)
00270     {
00271     case -1:
00272       warning (_("test branch tracing: cannot fork: %s."), strerror (errno));
00273       return 0;
00274 
00275     case 0:
00276       status = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
00277       if (status != 0)
00278         {
00279           warning (_("test branch tracing: cannot PTRACE_TRACEME: %s."),
00280                    strerror (errno));
00281           _exit (1);
00282         }
00283 
00284       status = raise (SIGTRAP);
00285       if (status != 0)
00286         {
00287           warning (_("test branch tracing: cannot raise SIGTRAP: %s."),
00288                    strerror (errno));
00289           _exit (1);
00290         }
00291 
00292       _exit (1);
00293 
00294     default:
00295       pid = waitpid (child, &status, 0);
00296       if (pid != child)
00297         {
00298           warning (_("test branch tracing: bad pid %ld, error: %s."),
00299                    (long) pid, strerror (errno));
00300           return 0;
00301         }
00302 
00303       if (!WIFSTOPPED (status))
00304         {
00305           warning (_("test branch tracing: expected stop. status: %d."),
00306                    status);
00307           return 0;
00308         }
00309 
00310       memset (&attr, 0, sizeof (attr));
00311 
00312       attr.type = PERF_TYPE_HARDWARE;
00313       attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
00314       attr.sample_period = 1;
00315       attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_ADDR;
00316       attr.exclude_kernel = 1;
00317       attr.exclude_hv = 1;
00318       attr.exclude_idle = 1;
00319 
00320       file = syscall (SYS_perf_event_open, &attr, child, -1, -1, 0);
00321       if (file >= 0)
00322         close (file);
00323 
00324       kill (child, SIGKILL);
00325       ptrace (PTRACE_KILL, child, NULL, NULL);
00326 
00327       pid = waitpid (child, &status, 0);
00328       if (pid != child)
00329         {
00330           warning (_("test branch tracing: bad pid %ld, error: %s."),
00331                    (long) pid, strerror (errno));
00332           if (!WIFSIGNALED (status))
00333             warning (_("test branch tracing: expected killed. status: %d."),
00334                      status);
00335         }
00336 
00337       return (file >= 0);
00338     }
00339 }
00340 
00341 /* Check whether an Intel cpu supports branch tracing.  */
00342 
00343 static int
00344 intel_supports_btrace (void)
00345 {
00346   unsigned int cpuid, model, family;
00347 
00348   if (!i386_cpuid (1, &cpuid, NULL, NULL, NULL))
00349     return 0;
00350 
00351   family = (cpuid >> 8) & 0xf;
00352   model = (cpuid >> 4) & 0xf;
00353 
00354   switch (family)
00355     {
00356     case 0x6:
00357       model += (cpuid >> 12) & 0xf0;
00358 
00359       switch (model)
00360         {
00361         case 0x1a: /* Nehalem */
00362         case 0x1f:
00363         case 0x1e:
00364         case 0x2e:
00365         case 0x25: /* Westmere */
00366         case 0x2c:
00367         case 0x2f:
00368         case 0x2a: /* Sandy Bridge */
00369         case 0x2d:
00370         case 0x3a: /* Ivy Bridge */
00371 
00372           /* AAJ122: LBR, BTM, or BTS records may have incorrect branch
00373              "from" information afer an EIST transition, T-states, C1E, or
00374              Adaptive Thermal Throttling.  */
00375           return 0;
00376         }
00377     }
00378 
00379   return 1;
00380 }
00381 
00382 /* Check whether the cpu supports branch tracing.  */
00383 
00384 static int
00385 cpu_supports_btrace (void)
00386 {
00387   unsigned int ebx, ecx, edx;
00388 
00389   if (!i386_cpuid (0, NULL, &ebx, &ecx, &edx))
00390     return 0;
00391 
00392   if (ebx == signature_INTEL_ebx && ecx == signature_INTEL_ecx
00393       && edx == signature_INTEL_edx)
00394     return intel_supports_btrace ();
00395 
00396   /* Don't know about others.  Let's assume they do.  */
00397   return 1;
00398 }
00399 
00400 /* See linux-btrace.h.  */
00401 
00402 int
00403 linux_supports_btrace (void)
00404 {
00405   static int cached;
00406 
00407   if (cached == 0)
00408     {
00409       if (!kernel_supports_btrace ())
00410         cached = -1;
00411       else if (!cpu_supports_btrace ())
00412         cached = -1;
00413       else
00414         cached = 1;
00415     }
00416 
00417   return cached > 0;
00418 }
00419 
00420 /* See linux-btrace.h.  */
00421 
00422 struct btrace_target_info *
00423 linux_enable_btrace (ptid_t ptid)
00424 {
00425   struct btrace_target_info *tinfo;
00426   int pid;
00427 
00428   tinfo = xzalloc (sizeof (*tinfo));
00429   tinfo->ptid = ptid;
00430 
00431   tinfo->attr.size = sizeof (tinfo->attr);
00432   tinfo->attr.type = PERF_TYPE_HARDWARE;
00433   tinfo->attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
00434   tinfo->attr.sample_period = 1;
00435 
00436   /* We sample from and to address.  */
00437   tinfo->attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_ADDR;
00438 
00439   tinfo->attr.exclude_kernel = 1;
00440   tinfo->attr.exclude_hv = 1;
00441   tinfo->attr.exclude_idle = 1;
00442 
00443   tinfo->ptr_bits = 0;
00444 
00445   pid = ptid_get_lwp (ptid);
00446   if (pid == 0)
00447     pid = ptid_get_pid (ptid);
00448 
00449   errno = 0;
00450   tinfo->file = syscall (SYS_perf_event_open, &tinfo->attr, pid, -1, -1, 0);
00451   if (tinfo->file < 0)
00452     goto err;
00453 
00454   /* We hard-code the trace buffer size.
00455      At some later time, we should make this configurable.  */
00456   tinfo->size = 1;
00457   tinfo->buffer = mmap (NULL, perf_event_mmap_size (tinfo),
00458                         PROT_READ, MAP_SHARED, tinfo->file, 0);
00459   if (tinfo->buffer == MAP_FAILED)
00460     goto err_file;
00461 
00462   return tinfo;
00463 
00464  err_file:
00465   close (tinfo->file);
00466 
00467  err:
00468   xfree (tinfo);
00469   return NULL;
00470 }
00471 
00472 /* See linux-btrace.h.  */
00473 
00474 int
00475 linux_disable_btrace (struct btrace_target_info *tinfo)
00476 {
00477   int errcode;
00478 
00479   errno = 0;
00480   errcode = munmap (tinfo->buffer, perf_event_mmap_size (tinfo));
00481   if (errcode != 0)
00482     return errno;
00483 
00484   close (tinfo->file);
00485   xfree (tinfo);
00486 
00487   return 0;
00488 }
00489 
00490 /* Check whether the branch trace has changed.  */
00491 
00492 static int
00493 linux_btrace_has_changed (struct btrace_target_info *tinfo)
00494 {
00495   volatile struct perf_event_mmap_page *header = perf_event_header (tinfo);
00496 
00497   return header->data_head != tinfo->data_head;
00498 }
00499 
00500 /* See linux-btrace.h.  */
00501 
00502 VEC (btrace_block_s) *
00503 linux_read_btrace (struct btrace_target_info *tinfo,
00504                    enum btrace_read_type type)
00505 {
00506   VEC (btrace_block_s) *btrace = NULL;
00507   volatile struct perf_event_mmap_page *header;
00508   const uint8_t *begin, *end, *start;
00509   unsigned long data_head, retries = 5;
00510   size_t buffer_size;
00511 
00512   if (type == btrace_read_new && !linux_btrace_has_changed (tinfo))
00513     return NULL;
00514 
00515   header = perf_event_header (tinfo);
00516   buffer_size = perf_event_buffer_size (tinfo);
00517 
00518   /* We may need to retry reading the trace.  See below.  */
00519   while (retries--)
00520     {
00521       data_head = header->data_head;
00522 
00523       /* If there's new trace, let's read it.  */
00524       if (data_head != tinfo->data_head)
00525         {
00526           /* Data_head keeps growing; the buffer itself is circular.  */
00527           begin = perf_event_buffer_begin (tinfo);
00528           start = begin + data_head % buffer_size;
00529 
00530           if (data_head <= buffer_size)
00531             end = start;
00532           else
00533             end = perf_event_buffer_end (tinfo);
00534 
00535           btrace = perf_event_read_bts (tinfo, begin, end, start);
00536         }
00537 
00538       /* The stopping thread notifies its ptracer before it is scheduled out.
00539          On multi-core systems, the debugger might therefore run while the
00540          kernel might be writing the last branch trace records.
00541 
00542          Let's check whether the data head moved while we read the trace.  */
00543       if (data_head == header->data_head)
00544         break;
00545     }
00546 
00547   tinfo->data_head = data_head;
00548 
00549   return btrace;
00550 }
00551 
00552 #else /* !HAVE_LINUX_PERF_EVENT_H */
00553 
00554 /* See linux-btrace.h.  */
00555 
00556 int
00557 linux_supports_btrace (void)
00558 {
00559   return 0;
00560 }
00561 
00562 /* See linux-btrace.h.  */
00563 
00564 struct btrace_target_info *
00565 linux_enable_btrace (ptid_t ptid)
00566 {
00567   return NULL;
00568 }
00569 
00570 /* See linux-btrace.h.  */
00571 
00572 int
00573 linux_disable_btrace (struct btrace_target_info *tinfo)
00574 {
00575   return ENOSYS;
00576 }
00577 
00578 /* See linux-btrace.h.  */
00579 
00580 VEC (btrace_block_s) *
00581 linux_read_btrace (struct btrace_target_info *tinfo,
00582                    enum btrace_read_type type)
00583 {
00584   return NULL;
00585 }
00586 
00587 #endif /* !HAVE_LINUX_PERF_EVENT_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines