22#include "gdbsupport/common-defs.h"
24#include "gdbsupport/common-regcache.h"
25#include "gdbsupport/gdb_wait.h"
27#include "gdbsupport/filestuff.h"
28#include "gdbsupport/scoped_fd.h"
29#include "gdbsupport/scoped_mmap.h"
33#include <sys/syscall.h>
35#if HAVE_LINUX_PERF_EVENT_H && defined(SYS_perf_event_open)
54struct perf_event_sample
57 struct perf_event_header header;
60 struct perf_event_bts bts;
64static struct btrace_cpu
67 struct btrace_cpu cpu;
68 unsigned int eax, ebx, ecx, edx;
71 memset (&cpu, 0,
sizeof (cpu));
73 ok =
x86_cpuid (0, &eax, &ebx, &ecx, &edx);
79 unsigned int cpuid, ignore;
81 ok =
x86_cpuid (1, &cpuid, &ignore, &ignore, &ignore);
84 cpu.vendor = CV_INTEL;
86 cpu.family = (cpuid >> 8) & 0xf;
87 if (cpu.family == 0xf)
88 cpu.family += (cpuid >> 20) & 0xff;
90 cpu.model = (cpuid >> 4) & 0xf;
91 if ((cpu.family == 0x6) || ((cpu.family & 0xf) == 0xf))
92 cpu.model += (cpuid >> 12) & 0xf0;
106perf_event_new_data (
const struct perf_event_buffer *pev)
108 return *pev->data_head != pev->last_head;
116perf_event_read (
const struct perf_event_buffer *pev, __u64 data_head,
119 const gdb_byte *begin, *end, *start, *stop;
128 buffer_size = pev->size;
129 gdb_assert (size <= buffer_size);
139 if (data_head < size)
140 data_head += buffer_size;
142 gdb_assert (size <= data_head);
143 data_tail = data_head - size;
146 start = begin + data_tail % buffer_size;
147 stop = begin + data_head % buffer_size;
149 buffer = (gdb_byte *) xmalloc (size);
152 memcpy (buffer, start, stop - start);
155 end = begin + buffer_size;
157 memcpy (buffer, start, end - start);
158 memcpy (buffer + (end - start), begin, stop - begin);
168perf_event_read_all (
struct perf_event_buffer *pev, gdb_byte **data,
174 data_head = *pev->data_head;
177 *data = perf_event_read (pev, data_head, size);
180 pev->last_head = data_head;
186linux_determine_kernel_start (
void)
188 static uint64_t kernel_start;
196 gdb_file_up file = gdb_fopen_cloexec (
"/proc/kallsyms",
"r");
200 while (!feof (file.get ()))
202 char buffer[1024], symbol[8], *line;
206 line = fgets (buffer,
sizeof (buffer), file.get ());
210 match = sscanf (line,
"%" SCNx64
" %*[tT] %7s", &addr, symbol);
214 if (strcmp (symbol,
"_text") == 0)
227perf_event_is_kernel_addr (uint64_t addr)
229 uint64_t kernel_start;
231 kernel_start = linux_determine_kernel_start ();
232 if (kernel_start != 0ull)
233 return (addr >= kernel_start);
237 return ((addr & (1ull << 63)) != 0);
243perf_event_skip_bts_record (
const struct perf_event_bts *bts)
248 return perf_event_is_kernel_addr (bts->from);
255perf_event_sample_ok (
const struct perf_event_sample *sample)
257 if (sample->header.type != PERF_RECORD_SAMPLE)
260 if (sample->header.size != sizeof (*sample))
279static std::vector<btrace_block> *
280perf_event_read_bts (btrace_target_info *tinfo,
const uint8_t *begin,
281 const uint8_t *end,
const uint8_t *start,
size_t size)
283 std::vector<btrace_block> *btrace =
new std::vector<btrace_block>;
284 struct perf_event_sample sample;
286 struct btrace_block block = { 0, 0 };
287 struct regcache *regcache;
289 gdb_assert (begin <= start);
290 gdb_assert (start <= end);
293 regcache = get_thread_regcache_for_ptid (tinfo->ptid);
294 block.end = regcache_read_pc (regcache);
298 read =
sizeof (sample) - 1;
300 for (; read < size; read +=
sizeof (sample))
302 const struct perf_event_sample *psample;
305 start -=
sizeof (sample);
309 psample = (
const struct perf_event_sample *) start;
317 missing = (begin - start);
318 start = (end - missing);
321 if (missing ==
sizeof (sample))
322 psample = (
const struct perf_event_sample *) start;
329 stack = (uint8_t *) &sample;
332 memcpy (stack, start, missing);
333 memcpy (stack + missing, begin,
sizeof (sample) - missing);
339 if (!perf_event_sample_ok (psample))
341 warning (_(
"Branch trace may be incomplete."));
345 if (perf_event_skip_bts_record (&psample->bts))
349 block.begin = psample->bts.to;
351 btrace->push_back (block);
354 block.end = psample->bts.from;
362 btrace->push_back (block);
370intel_supports_bts (
const struct btrace_cpu *cpu)
401cpu_supports_bts (
void)
403 struct btrace_cpu cpu;
405 cpu = btrace_this_cpu ();
413 return intel_supports_bts (&cpu);
424diagnose_perf_event_open_fail ()
431 static const char filename[] =
"/proc/sys/kernel/perf_event_paranoid";
433 gdb_file_up file = gdb_fopen_cloexec (filename,
"r");
434 if (file.get () ==
nullptr)
435 error (_(
"Failed to open %s (%s). Your system does not support "
436 "process recording."), filename, safe_strerror (errno));
438 int level, found = fscanf (file.get (),
"%d", &level);
439 if (found == 1 && level > 2)
440 error (_(
"You do not have permission to record the process. "
441 "Try setting %s to 2 or less."), filename);
447 error (_(
"Failed to start recording: %s"), safe_strerror (errno));
453get_linux_btrace_target_info (btrace_target_info *gtinfo)
455 return gdb::checked_static_cast<linux_btrace_target_info *> (gtinfo);
460static struct btrace_target_info *
461linux_enable_bts (ptid_t ptid,
const struct btrace_config_bts *conf)
467 if (!cpu_supports_bts ())
468 error (_(
"BTS support has been disabled for the target cpu."));
470 std::unique_ptr<linux_btrace_target_info> tinfo
471 { gdb::make_unique<linux_btrace_target_info> (ptid) };
473 tinfo->conf.format = BTRACE_FORMAT_BTS;
475 tinfo->attr.size =
sizeof (tinfo->attr);
476 tinfo->attr.type = PERF_TYPE_HARDWARE;
477 tinfo->attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
478 tinfo->attr.sample_period = 1;
481 tinfo->attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_ADDR;
483 tinfo->attr.exclude_kernel = 1;
484 tinfo->attr.exclude_hv = 1;
485 tinfo->attr.exclude_idle = 1;
492 scoped_fd fd (syscall (SYS_perf_event_open, &tinfo->attr, pid, -1, -1, 0));
494 diagnose_perf_event_open_fail ();
497 pages = ((size_t) conf->size / PAGE_SIZE
498 + ((conf->size % PAGE_SIZE) == 0 ? 0 : 1));
505 for (pg = 0; pages != ((size_t) 1 << pg); ++pg)
506 if ((pages & ((
size_t) 1 << pg)) != 0)
507 pages += ((
size_t) 1 << pg);
512 for (; pages > 0; pages >>= 1)
517 data_size = (__u64) pages * PAGE_SIZE;
520 if ((__u64) UINT_MAX < data_size)
523 size = (size_t) data_size;
524 length = size + PAGE_SIZE;
527 if ((__u64) length != data_size + PAGE_SIZE)
532 data.reset (
nullptr, length, PROT_READ, MAP_SHARED, fd.get (), 0);
533 if (data.get () != MAP_FAILED)
538 error (_(
"Failed to map trace buffer: %s."), safe_strerror (errno));
540 struct perf_event_mmap_page *header = (
struct perf_event_mmap_page *)
542 data_offset = PAGE_SIZE;
544#if defined (PERF_ATTR_SIZE_VER5)
545 if (offsetof (
struct perf_event_mmap_page, data_size) <= header->size)
549 data_offset = header->data_offset;
550 data_size = header->data_size;
552 size = (
unsigned int) data_size;
555 if ((__u64) size != data_size)
556 error (_(
"Failed to determine trace buffer size."));
560 tinfo->pev.size = size;
561 tinfo->pev.data_head = &header->data_head;
562 tinfo->pev.mem = (
const uint8_t *) data.release () + data_offset;
563 tinfo->pev.last_head = 0ull;
564 tinfo->header = header;
565 tinfo->file = fd.release ();
567 tinfo->conf.bts.size = (
unsigned int) size;
568 return tinfo.release ();
571#if defined (PERF_ATTR_SIZE_VER5)
576perf_event_pt_event_type ()
578 static const char filename[] =
"/sys/bus/event_source/devices/intel_pt/type";
581 gdb_file_up file = gdb_fopen_cloexec (filename,
"r");
582 if (file.get () ==
nullptr)
588 error (_(
"Failed to open %s (%s). You do not have permission "
589 "to use Intel PT."), filename, safe_strerror (errno));
593 error (_(
"Failed to open %s (%s). Your system does not support "
594 "Intel PT."), filename, safe_strerror (errno));
597 error (_(
"Failed to open %s: %s."), filename, safe_strerror (errno));
600 int type, found = fscanf (file.get (),
"%d", &type);
602 error (_(
"Failed to read the PT event type from %s."), filename);
609static struct btrace_target_info *
610linux_enable_pt (ptid_t ptid,
const struct btrace_config_pt *conf)
619 std::unique_ptr<linux_btrace_target_info> tinfo
620 { gdb::make_unique<linux_btrace_target_info> (ptid) };
622 tinfo->conf.format = BTRACE_FORMAT_PT;
624 tinfo->attr.size =
sizeof (tinfo->attr);
625 tinfo->attr.type = perf_event_pt_event_type ();
627 tinfo->attr.exclude_kernel = 1;
628 tinfo->attr.exclude_hv = 1;
629 tinfo->attr.exclude_idle = 1;
632 scoped_fd fd (syscall (SYS_perf_event_open, &tinfo->attr, pid, -1, -1, 0));
634 diagnose_perf_event_open_fail ();
637 scoped_mmap data (
nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
639 if (data.get () == MAP_FAILED)
640 error (_(
"Failed to map trace user page: %s."), safe_strerror (errno));
642 struct perf_event_mmap_page *header = (
struct perf_event_mmap_page *)
645 header->aux_offset = header->data_offset + header->data_size;
648 pages = ((size_t) conf->size / PAGE_SIZE
649 + ((conf->size % PAGE_SIZE) == 0 ? 0 : 1));
656 for (pg = 0; pages != ((size_t) 1 << pg); ++pg)
657 if ((pages & ((
size_t) 1 << pg)) != 0)
658 pages += ((
size_t) 1 << pg);
663 for (; pages > 0; pages >>= 1)
668 data_size = (__u64) pages * PAGE_SIZE;
671 if ((__u64) UINT_MAX < data_size)
674 length = (size_t) data_size;
677 if ((__u64) length != data_size)
680 header->aux_size = data_size;
683 aux.reset (
nullptr, length, PROT_READ, MAP_SHARED, fd.get (),
685 if (aux.get () != MAP_FAILED)
690 error (_(
"Failed to map trace buffer: %s."), safe_strerror (errno));
692 tinfo->pev.size = aux.size ();
693 tinfo->pev.mem = (
const uint8_t *) aux.release ();
694 tinfo->pev.data_head = &header->aux_head;
695 tinfo->header = (
struct perf_event_mmap_page *) data.release ();
696 gdb_assert (tinfo->header == header);
697 tinfo->file = fd.release ();
699 tinfo->conf.pt.size = (
unsigned int) tinfo->pev.size;
700 return tinfo.release ();
705static struct btrace_target_info *
706linux_enable_pt (ptid_t ptid,
const struct btrace_config_pt *conf)
708 error (_(
"Intel Processor Trace support was disabled at compile time."));
715struct btrace_target_info *
718 switch (conf->format)
720 case BTRACE_FORMAT_NONE:
721 error (_(
"Bad branch trace format."));
724 error (_(
"Unknown branch trace format."));
726 case BTRACE_FORMAT_BTS:
727 return linux_enable_bts (ptid, &conf->bts);
729 case BTRACE_FORMAT_PT:
730 return linux_enable_pt (ptid, &conf->pt);
739 munmap ((
void *) tinfo->header, tinfo->pev.size + PAGE_SIZE);
748 munmap ((
void *) tinfo->pev.mem, tinfo->pev.size);
749 munmap ((
void *) tinfo->header, PAGE_SIZE);
759 = get_linux_btrace_target_info (gtinfo);
761 switch (tinfo->conf.format)
763 case BTRACE_FORMAT_NONE:
764 return BTRACE_ERR_NOT_SUPPORTED;
766 case BTRACE_FORMAT_BTS:
767 linux_disable_bts (tinfo);
769 return BTRACE_ERR_NONE;
771 case BTRACE_FORMAT_PT:
772 linux_disable_pt (tinfo);
774 return BTRACE_ERR_NONE;
777 return BTRACE_ERR_NOT_SUPPORTED;
783static enum btrace_error
785 enum btrace_read_type type)
787 const uint8_t *begin, *end, *start;
788 size_t buffer_size, size;
789 __u64 data_head = 0, data_tail;
790 unsigned int retries = 5;
794 if (type == BTRACE_READ_NEW && !perf_event_new_data (&tinfo->pev))
795 return BTRACE_ERR_NONE;
797 buffer_size = tinfo->pev.size;
798 data_tail = tinfo->pev.last_head;
803 data_head = *tinfo->pev.data_head;
806 delete btrace->blocks;
807 btrace->blocks =
nullptr;
809 if (type == BTRACE_READ_DELTA)
819 if (data_head < data_tail)
820 return BTRACE_ERR_OVERFLOW;
823 data_size = data_head - data_tail;
824 if (buffer_size < data_size)
825 return BTRACE_ERR_OVERFLOW;
828 size = (size_t) data_size;
836 if (data_head < size)
837 size = (size_t) data_head;
841 begin = tinfo->pev.mem;
842 start = begin + data_head % buffer_size;
844 if (data_head <= buffer_size)
847 end = begin + tinfo->pev.size;
849 btrace->blocks = perf_event_read_bts (tinfo, begin, end, start, size);
856 if (data_head == *tinfo->pev.data_head)
860 tinfo->pev.last_head = data_head;
865 if (!btrace->blocks->empty () && type != BTRACE_READ_DELTA)
866 btrace->blocks->pop_back ();
868 return BTRACE_ERR_NONE;
874linux_fill_btrace_pt_config (
struct btrace_data_pt_config *conf)
876 conf->cpu = btrace_this_cpu ();
882static enum btrace_error
884 enum btrace_read_type type)
886 linux_fill_btrace_pt_config (&btrace->config);
890 case BTRACE_READ_DELTA:
893 return BTRACE_ERR_NOT_SUPPORTED;
895 case BTRACE_READ_NEW:
896 if (!perf_event_new_data (&tinfo->pev))
897 return BTRACE_ERR_NONE;
900 case BTRACE_READ_ALL:
901 perf_event_read_all (&tinfo->pev, &btrace->data, &btrace->size);
902 return BTRACE_ERR_NONE;
905 internal_error (_(
"Unknown btrace read type."));
912 struct btrace_target_info *gtinfo,
913 enum btrace_read_type type)
916 = get_linux_btrace_target_info (gtinfo);
918 switch (tinfo->conf.format)
920 case BTRACE_FORMAT_NONE:
921 return BTRACE_ERR_NOT_SUPPORTED;
923 case BTRACE_FORMAT_BTS:
925 btrace->format = BTRACE_FORMAT_BTS;
926 btrace->variant.bts.blocks = NULL;
928 return linux_read_bts (&btrace->variant.bts, tinfo, type);
930 case BTRACE_FORMAT_PT:
932 btrace->format = BTRACE_FORMAT_PT;
933 btrace->variant.pt.data = NULL;
934 btrace->variant.pt.size = 0;
936 return linux_read_pt (&btrace->variant.pt, tinfo, type);
939 internal_error (_(
"Unkown branch trace format."));
944const struct btrace_config *
954struct btrace_target_info *
965 return BTRACE_ERR_NOT_SUPPORTED;
972 struct btrace_target_info *tinfo,
973 enum btrace_read_type type)
975 return BTRACE_ERR_NOT_SUPPORTED;
980const struct btrace_config *
enum btrace_error linux_read_btrace(struct btrace_data *btrace, struct btrace_target_info *tinfo, enum btrace_read_type type)
const struct btrace_config * linux_btrace_conf(const struct btrace_target_info *tinfo)
struct btrace_target_info * linux_enable_btrace(ptid_t ptid, const struct btrace_config *conf)
enum btrace_error linux_disable_btrace(struct btrace_target_info *tinfo)
static __inline int x86_cpuid(unsigned int __level, unsigned int *__eax, unsigned int *__ebx, unsigned int *__ecx, unsigned int *__edx)
#define signature_INTEL_edx
#define signature_INTEL_ebx
#define signature_AMD_ecx
#define signature_AMD_edx
#define signature_INTEL_ecx
#define signature_AMD_ebx