1 /* Linux-dependent part of branch trace support for GDB, and GDBserver.
3 Copyright (C) 2013-2014 Free Software Foundation, Inc.
5 Contributed by Intel Corp. <markus.t.metzger@intel.com>
7 This file is part of GDB.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
28 #include "linux-btrace.h"
29 #include "common-utils.h"
30 #include "gdb_assert.h"
32 #include "gdbthread.h"
34 #include "i386-cpuid.h"
36 #ifdef HAVE_SYS_SYSCALL_H
37 #include <sys/syscall.h>
40 #if HAVE_LINUX_PERF_EVENT_H && defined(SYS_perf_event_open)
48 #include <sys/ptrace.h>
49 #include <sys/types.h>
52 /* A branch trace record in perf_event. */
55 /* The linear address of the branch source. */
58 /* The linear address of the branch destination. */
62 /* A perf_event branch trace sample. */
63 struct perf_event_sample
65 /* The perf_event sample header. */
66 struct perf_event_header header
;
68 /* The perf_event branch tracing payload. */
69 struct perf_event_bts bts
;
72 /* Get the perf_event header. */
74 static inline volatile struct perf_event_mmap_page
*
75 perf_event_header (struct btrace_target_info
* tinfo
)
80 /* Get the size of the perf_event mmap buffer. */
83 perf_event_mmap_size (const struct btrace_target_info
*tinfo
)
85 /* The branch trace buffer is preceded by a configuration page. */
86 return (tinfo
->size
+ 1) * PAGE_SIZE
;
89 /* Get the size of the perf_event buffer. */
92 perf_event_buffer_size (struct btrace_target_info
* tinfo
)
94 return tinfo
->size
* PAGE_SIZE
;
97 /* Get the start address of the perf_event buffer. */
99 static inline const uint8_t *
100 perf_event_buffer_begin (struct btrace_target_info
* tinfo
)
102 return ((const uint8_t *) tinfo
->buffer
) + PAGE_SIZE
;
105 /* Get the end address of the perf_event buffer. */
107 static inline const uint8_t *
108 perf_event_buffer_end (struct btrace_target_info
* tinfo
)
110 return perf_event_buffer_begin (tinfo
) + perf_event_buffer_size (tinfo
);
113 /* Check whether an address is in the kernel. */
116 perf_event_is_kernel_addr (const struct btrace_target_info
*tinfo
,
121 /* If we don't know the size of a pointer, we can't check. Let's assume it's
122 not a kernel address in this case. */
123 if (tinfo
->ptr_bits
== 0)
126 /* A bit mask for the most significant bit in an address. */
127 mask
= (uint64_t) 1 << (tinfo
->ptr_bits
- 1);
129 /* Check whether the most significant bit in the address is set. */
130 return (addr
& mask
) != 0;
133 /* Check whether a perf event record should be skipped. */
136 perf_event_skip_record (const struct btrace_target_info
*tinfo
,
137 const struct perf_event_bts
*bts
)
139 /* The hardware may report branches from kernel into user space. Branches
140 from user into kernel space will be suppressed. We filter the former to
141 provide a consistent branch trace excluding kernel. */
142 return perf_event_is_kernel_addr (tinfo
, bts
->from
);
145 /* Perform a few consistency checks on a perf event sample record. This is
146 meant to catch cases when we get out of sync with the perf event stream. */
149 perf_event_sample_ok (const struct perf_event_sample
*sample
)
151 if (sample
->header
.type
!= PERF_RECORD_SAMPLE
)
154 if (sample
->header
.size
!= sizeof (*sample
))
160 /* Branch trace is collected in a circular buffer [begin; end) as pairs of from
161 and to addresses (plus a header).
163 Start points into that buffer at the next sample position.
164 We read the collected samples backwards from start.
166 While reading the samples, we convert the information into a list of blocks.
167 For two adjacent samples s1 and s2, we form a block b such that b.begin =
168 s1.to and b.end = s2.from.
170 In case the buffer overflows during sampling, one sample may have its lower
171 part at the end and its upper part at the beginning of the buffer. */
173 static VEC (btrace_block_s
) *
174 perf_event_read_bts (struct btrace_target_info
* tinfo
, const uint8_t *begin
,
175 const uint8_t *end
, const uint8_t *start
)
177 VEC (btrace_block_s
) *btrace
= NULL
;
178 struct perf_event_sample sample
;
179 size_t read
= 0, size
= (end
- begin
);
180 struct btrace_block block
= { 0, 0 };
181 struct regcache
*regcache
;
183 gdb_assert (begin
<= start
);
184 gdb_assert (start
<= end
);
186 /* The first block ends at the current pc. */
188 regcache
= get_thread_regcache (find_thread_ptid (tinfo
->ptid
), 1);
190 regcache
= get_thread_regcache (tinfo
->ptid
);
192 block
.end
= regcache_read_pc (regcache
);
194 /* The buffer may contain a partial record as its last entry (i.e. when the
195 buffer size is not a multiple of the sample size). */
196 read
= sizeof (sample
) - 1;
198 for (; read
< size
; read
+= sizeof (sample
))
200 const struct perf_event_sample
*psample
;
202 /* Find the next perf_event sample in a backwards traversal. */
203 start
-= sizeof (sample
);
205 /* If we're still inside the buffer, we're done. */
207 psample
= (const struct perf_event_sample
*) start
;
212 /* We're to the left of the ring buffer, we will wrap around and
213 reappear at the very right of the ring buffer. */
215 missing
= (begin
- start
);
216 start
= (end
- missing
);
218 /* If the entire sample is missing, we're done. */
219 if (missing
== sizeof (sample
))
220 psample
= (const struct perf_event_sample
*) start
;
225 /* The sample wrapped around. The lower part is at the end and
226 the upper part is at the beginning of the buffer. */
227 stack
= (uint8_t *) &sample
;
229 /* Copy the two parts so we have a contiguous sample. */
230 memcpy (stack
, start
, missing
);
231 memcpy (stack
+ missing
, begin
, sizeof (sample
) - missing
);
237 if (!perf_event_sample_ok (psample
))
239 warning (_("Branch trace may be incomplete."));
243 if (perf_event_skip_record (tinfo
, &psample
->bts
))
246 /* We found a valid sample, so we can complete the current block. */
247 block
.begin
= psample
->bts
.to
;
249 VEC_safe_push (btrace_block_s
, btrace
, &block
);
251 /* Start the next block. */
252 block
.end
= psample
->bts
.from
;
258 /* Check whether the kernel supports branch tracing. */
261 kernel_supports_btrace (void)
263 struct perf_event_attr attr
;
272 warning (_("test branch tracing: cannot fork: %s."), strerror (errno
));
276 status
= ptrace (PTRACE_TRACEME
, 0, NULL
, NULL
);
279 warning (_("test branch tracing: cannot PTRACE_TRACEME: %s."),
284 status
= raise (SIGTRAP
);
287 warning (_("test branch tracing: cannot raise SIGTRAP: %s."),
295 pid
= waitpid (child
, &status
, 0);
298 warning (_("test branch tracing: bad pid %ld, error: %s."),
299 (long) pid
, strerror (errno
));
303 if (!WIFSTOPPED (status
))
305 warning (_("test branch tracing: expected stop. status: %d."),
310 memset (&attr
, 0, sizeof (attr
));
312 attr
.type
= PERF_TYPE_HARDWARE
;
313 attr
.config
= PERF_COUNT_HW_BRANCH_INSTRUCTIONS
;
314 attr
.sample_period
= 1;
315 attr
.sample_type
= PERF_SAMPLE_IP
| PERF_SAMPLE_ADDR
;
316 attr
.exclude_kernel
= 1;
318 attr
.exclude_idle
= 1;
320 file
= syscall (SYS_perf_event_open
, &attr
, child
, -1, -1, 0);
324 kill (child
, SIGKILL
);
325 ptrace (PTRACE_KILL
, child
, NULL
, NULL
);
327 pid
= waitpid (child
, &status
, 0);
330 warning (_("test branch tracing: bad pid %ld, error: %s."),
331 (long) pid
, strerror (errno
));
332 if (!WIFSIGNALED (status
))
333 warning (_("test branch tracing: expected killed. status: %d."),
341 /* Check whether an Intel cpu supports branch tracing. */
344 intel_supports_btrace (void)
346 unsigned int cpuid
, model
, family
;
348 if (!i386_cpuid (1, &cpuid
, NULL
, NULL
, NULL
))
351 family
= (cpuid
>> 8) & 0xf;
352 model
= (cpuid
>> 4) & 0xf;
357 model
+= (cpuid
>> 12) & 0xf0;
361 case 0x1a: /* Nehalem */
365 case 0x25: /* Westmere */
368 case 0x2a: /* Sandy Bridge */
370 case 0x3a: /* Ivy Bridge */
372 /* AAJ122: LBR, BTM, or BTS records may have incorrect branch
373 "from" information afer an EIST transition, T-states, C1E, or
374 Adaptive Thermal Throttling. */
382 /* Check whether the cpu supports branch tracing. */
385 cpu_supports_btrace (void)
387 unsigned int ebx
, ecx
, edx
;
389 if (!i386_cpuid (0, NULL
, &ebx
, &ecx
, &edx
))
392 if (ebx
== signature_INTEL_ebx
&& ecx
== signature_INTEL_ecx
393 && edx
== signature_INTEL_edx
)
394 return intel_supports_btrace ();
396 /* Don't know about others. Let's assume they do. */
400 /* See linux-btrace.h. */
403 linux_supports_btrace (void)
409 if (!kernel_supports_btrace ())
411 else if (!cpu_supports_btrace ())
420 /* See linux-btrace.h. */
422 struct btrace_target_info
*
423 linux_enable_btrace (ptid_t ptid
)
425 struct btrace_target_info
*tinfo
;
428 tinfo
= xzalloc (sizeof (*tinfo
));
431 tinfo
->attr
.size
= sizeof (tinfo
->attr
);
432 tinfo
->attr
.type
= PERF_TYPE_HARDWARE
;
433 tinfo
->attr
.config
= PERF_COUNT_HW_BRANCH_INSTRUCTIONS
;
434 tinfo
->attr
.sample_period
= 1;
436 /* We sample from and to address. */
437 tinfo
->attr
.sample_type
= PERF_SAMPLE_IP
| PERF_SAMPLE_ADDR
;
439 tinfo
->attr
.exclude_kernel
= 1;
440 tinfo
->attr
.exclude_hv
= 1;
441 tinfo
->attr
.exclude_idle
= 1;
445 pid
= ptid_get_lwp (ptid
);
447 pid
= ptid_get_pid (ptid
);
450 tinfo
->file
= syscall (SYS_perf_event_open
, &tinfo
->attr
, pid
, -1, -1, 0);
454 /* We hard-code the trace buffer size.
455 At some later time, we should make this configurable. */
457 tinfo
->buffer
= mmap (NULL
, perf_event_mmap_size (tinfo
),
458 PROT_READ
, MAP_SHARED
, tinfo
->file
, 0);
459 if (tinfo
->buffer
== MAP_FAILED
)
472 /* See linux-btrace.h. */
475 linux_disable_btrace (struct btrace_target_info
*tinfo
)
480 errcode
= munmap (tinfo
->buffer
, perf_event_mmap_size (tinfo
));
490 /* Check whether the branch trace has changed. */
493 linux_btrace_has_changed (struct btrace_target_info
*tinfo
)
495 volatile struct perf_event_mmap_page
*header
= perf_event_header (tinfo
);
497 return header
->data_head
!= tinfo
->data_head
;
500 /* See linux-btrace.h. */
502 VEC (btrace_block_s
) *
503 linux_read_btrace (struct btrace_target_info
*tinfo
,
504 enum btrace_read_type type
)
506 VEC (btrace_block_s
) *btrace
= NULL
;
507 volatile struct perf_event_mmap_page
*header
;
508 const uint8_t *begin
, *end
, *start
;
509 unsigned long data_head
, retries
= 5;
512 if (type
== btrace_read_new
&& !linux_btrace_has_changed (tinfo
))
515 header
= perf_event_header (tinfo
);
516 buffer_size
= perf_event_buffer_size (tinfo
);
518 /* We may need to retry reading the trace. See below. */
521 data_head
= header
->data_head
;
523 /* Delete any leftover trace from the previous iteration. */
524 VEC_free (btrace_block_s
, btrace
);
526 /* If there's new trace, let's read it. */
527 if (data_head
!= tinfo
->data_head
)
529 /* Data_head keeps growing; the buffer itself is circular. */
530 begin
= perf_event_buffer_begin (tinfo
);
531 start
= begin
+ data_head
% buffer_size
;
533 if (data_head
<= buffer_size
)
536 end
= perf_event_buffer_end (tinfo
);
538 btrace
= perf_event_read_bts (tinfo
, begin
, end
, start
);
541 /* The stopping thread notifies its ptracer before it is scheduled out.
542 On multi-core systems, the debugger might therefore run while the
543 kernel might be writing the last branch trace records.
545 Let's check whether the data head moved while we read the trace. */
546 if (data_head
== header
->data_head
)
550 tinfo
->data_head
= data_head
;
555 #else /* !HAVE_LINUX_PERF_EVENT_H */
557 /* See linux-btrace.h. */
560 linux_supports_btrace (void)
565 /* See linux-btrace.h. */
567 struct btrace_target_info
*
568 linux_enable_btrace (ptid_t ptid
)
573 /* See linux-btrace.h. */
576 linux_disable_btrace (struct btrace_target_info
*tinfo
)
581 /* See linux-btrace.h. */
583 VEC (btrace_block_s
) *
584 linux_read_btrace (struct btrace_target_info
*tinfo
,
585 enum btrace_read_type type
)
590 #endif /* !HAVE_LINUX_PERF_EVENT_H */