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;
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> *
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 };
289 gdb_assert (begin <= start);
290 gdb_assert (start <= end);
298 read =
sizeof (sample) - 1;
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);
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));
453linux_enable_bts (ptid_t
ptid,
const struct btrace_config_bts *
conf)
455 struct btrace_tinfo_bts *bts;
460 if (!cpu_supports_bts ())
461 error (_(
"BTS support has been disabled for the target cpu."));
463 gdb::unique_xmalloc_ptr<btrace_target_info> tinfo
467 tinfo->
conf.format = BTRACE_FORMAT_BTS;
468 bts = &tinfo->variant.bts;
470 bts->attr.size =
sizeof (bts->attr);
471 bts->attr.type = PERF_TYPE_HARDWARE;
472 bts->attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
473 bts->attr.sample_period = 1;
476 bts->attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_ADDR;
478 bts->attr.exclude_kernel = 1;
479 bts->attr.exclude_hv = 1;
480 bts->attr.exclude_idle = 1;
487 scoped_fd fd (
syscall (SYS_perf_event_open, &bts->attr,
pid, -1, -1, 0));
489 diagnose_perf_event_open_fail ();
492 pages = ((size_t) conf->size / PAGE_SIZE
493 + ((conf->size % PAGE_SIZE) == 0 ? 0 : 1));
500 for (pg = 0; pages != ((size_t) 1 << pg); ++pg)
501 if ((pages & ((
size_t) 1 << pg)) != 0)
502 pages += ((
size_t) 1 << pg);
507 for (; pages > 0; pages >>= 1)
512 data_size = (__u64) pages * PAGE_SIZE;
518 size = (size_t) data_size;
519 length =
size + PAGE_SIZE;
522 if ((__u64) length != data_size + PAGE_SIZE)
527 data.reset (
nullptr, length, PROT_READ, MAP_SHARED, fd.get (), 0);
528 if (
data.get () != MAP_FAILED)
533 error (_(
"Failed to map trace buffer: %s."), safe_strerror (errno));
535 struct perf_event_mmap_page *header = (
struct perf_event_mmap_page *)
537 data_offset = PAGE_SIZE;
539#if defined (PERF_ATTR_SIZE_VER5)
540 if (offsetof (
struct perf_event_mmap_page, data_size) <= header->size)
544 data_offset = header->data_offset;
545 data_size = header->data_size;
547 size = (
unsigned int) data_size;
550 if ((__u64)
size != data_size)
551 error (_(
"Failed to determine trace buffer size."));
555 bts->bts.size =
size;
556 bts->bts.data_head = &header->data_head;
557 bts->bts.mem = (
const uint8_t *)
data.release () + data_offset;
558 bts->bts.last_head = 0ull;
559 bts->header = header;
560 bts->file = fd.release ();
562 tinfo->
conf.bts.size = (
unsigned int)
size;
563 return tinfo.release ();
566#if defined (PERF_ATTR_SIZE_VER5)
571perf_event_pt_event_type ()
573 static const char filename[] =
"/sys/bus/event_source/devices/intel_pt/type";
576 gdb_file_up
file = gdb_fopen_cloexec (filename,
"r");
577 if (
file.get () ==
nullptr)
583 error (_(
"Failed to open %s (%s). You do not have permission "
584 "to use Intel PT."), filename, safe_strerror (errno));
588 error (_(
"Failed to open %s (%s). Your system does not support "
589 "Intel PT."), filename, safe_strerror (errno));
592 error (_(
"Failed to open %s: %s."), filename, safe_strerror (errno));
597 error (_(
"Failed to read the PT event type from %s."), filename);
605linux_enable_pt (ptid_t
ptid,
const struct btrace_config_pt *
conf)
607 struct btrace_tinfo_pt *pt;
615 gdb::unique_xmalloc_ptr<btrace_target_info> tinfo
619 tinfo->
conf.format = BTRACE_FORMAT_PT;
620 pt = &tinfo->variant.pt;
622 pt->attr.size =
sizeof (pt->attr);
623 pt->attr.type = perf_event_pt_event_type ();
625 pt->attr.exclude_kernel = 1;
626 pt->attr.exclude_hv = 1;
627 pt->attr.exclude_idle = 1;
630 scoped_fd fd (
syscall (SYS_perf_event_open, &pt->attr,
pid, -1, -1, 0));
632 diagnose_perf_event_open_fail ();
635 scoped_mmap
data (
nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
637 if (
data.get () == MAP_FAILED)
638 error (_(
"Failed to map trace user page: %s."), safe_strerror (errno));
640 struct perf_event_mmap_page *header = (
struct perf_event_mmap_page *)
643 header->aux_offset = header->data_offset + header->data_size;
646 pages = ((size_t) conf->size / PAGE_SIZE
647 + ((conf->size % PAGE_SIZE) == 0 ? 0 : 1));
654 for (pg = 0; pages != ((size_t) 1 << pg); ++pg)
655 if ((pages & ((
size_t) 1 << pg)) != 0)
656 pages += ((
size_t) 1 << pg);
661 for (; pages > 0; pages >>= 1)
666 data_size = (__u64) pages * PAGE_SIZE;
672 length = (size_t) data_size;
675 if ((__u64) length != data_size)
678 header->aux_size = data_size;
681 aux.reset (
nullptr, length, PROT_READ, MAP_SHARED, fd.get (),
683 if (aux.get () != MAP_FAILED)
688 error (_(
"Failed to map trace buffer: %s."), safe_strerror (errno));
690 pt->pt.size = aux.size ();
691 pt->pt.mem = (
const uint8_t *) aux.release ();
692 pt->pt.data_head = &header->aux_head;
693 pt->header = (
struct perf_event_mmap_page *)
data.release ();
694 gdb_assert (pt->header == header);
695 pt->file = fd.release ();
697 tinfo->
conf.pt.size = (
unsigned int) pt->pt.size;
698 return tinfo.release ();
704linux_enable_pt (ptid_t
ptid,
const struct btrace_config_pt *
conf)
706 error (_(
"Intel Processor Trace support was disabled at compile time."));
716 switch (
conf->format)
718 case BTRACE_FORMAT_NONE:
719 error (_(
"Bad branch trace format."));
722 error (_(
"Unknown branch trace format."));
724 case BTRACE_FORMAT_BTS:
725 return linux_enable_bts (
ptid, &
conf->bts);
727 case BTRACE_FORMAT_PT:
728 return linux_enable_pt (
ptid, &
conf->pt);
734static enum btrace_error
735linux_disable_bts (
struct btrace_tinfo_bts *tinfo)
737 munmap((
void *) tinfo->header, tinfo->bts.size + PAGE_SIZE);
740 return BTRACE_ERR_NONE;
745static enum btrace_error
746linux_disable_pt (
struct btrace_tinfo_pt *tinfo)
748 munmap((
void *) tinfo->pt.mem, tinfo->pt.size);
749 munmap((
void *) tinfo->header, PAGE_SIZE);
752 return BTRACE_ERR_NONE;
760 enum btrace_error errcode;
762 errcode = BTRACE_ERR_NOT_SUPPORTED;
763 switch (tinfo->
conf.format)
765 case BTRACE_FORMAT_NONE:
768 case BTRACE_FORMAT_BTS:
769 errcode = linux_disable_bts (&tinfo->variant.bts);
772 case BTRACE_FORMAT_PT:
773 errcode = linux_disable_pt (&tinfo->variant.pt);
777 if (errcode == BTRACE_ERR_NONE)
786static enum btrace_error
787linux_read_bts (
struct btrace_data_bts *btrace,
789 enum btrace_read_type
type)
791 struct perf_event_buffer *pevent;
792 const uint8_t *begin, *end, *start;
793 size_t buffer_size,
size;
794 __u64 data_head = 0, data_tail;
795 unsigned int retries = 5;
797 pevent = &tinfo->variant.bts.bts;
801 if (
type == BTRACE_READ_NEW && !perf_event_new_data (pevent))
802 return BTRACE_ERR_NONE;
804 buffer_size = pevent->size;
805 data_tail = pevent->last_head;
810 data_head = *pevent->data_head;
813 delete btrace->blocks;
814 btrace->blocks =
nullptr;
816 if (
type == BTRACE_READ_DELTA)
826 if (data_head < data_tail)
827 return BTRACE_ERR_OVERFLOW;
830 data_size = data_head - data_tail;
831 if (buffer_size < data_size)
832 return BTRACE_ERR_OVERFLOW;
835 size = (size_t) data_size;
843 if (data_head <
size)
844 size = (size_t) data_head;
849 start = begin + data_head % buffer_size;
851 if (data_head <= buffer_size)
854 end = begin + pevent->size;
856 btrace->blocks = perf_event_read_bts (tinfo, begin, end, start,
size);
863 if (data_head == *pevent->data_head)
867 pevent->last_head = data_head;
872 if (!btrace->blocks->empty () &&
type != BTRACE_READ_DELTA)
873 btrace->blocks->pop_back ();
875 return BTRACE_ERR_NONE;
881linux_fill_btrace_pt_config (
struct btrace_data_pt_config *conf)
883 conf->cpu = btrace_this_cpu ();
889static enum btrace_error
890linux_read_pt (
struct btrace_data_pt *btrace,
892 enum btrace_read_type
type)
894 struct perf_event_buffer *pt;
896 pt = &tinfo->variant.pt.pt;
898 linux_fill_btrace_pt_config (&btrace->config);
902 case BTRACE_READ_DELTA:
905 return BTRACE_ERR_NOT_SUPPORTED;
907 case BTRACE_READ_NEW:
908 if (!perf_event_new_data (pt))
909 return BTRACE_ERR_NONE;
912 case BTRACE_READ_ALL:
913 perf_event_read_all (pt, &btrace->data, &btrace->size);
914 return BTRACE_ERR_NONE;
917 internal_error (_(
"Unknown btrace read type."));
925 enum btrace_read_type
type)
927 switch (tinfo->
conf.format)
929 case BTRACE_FORMAT_NONE:
930 return BTRACE_ERR_NOT_SUPPORTED;
932 case BTRACE_FORMAT_BTS:
934 btrace->format = BTRACE_FORMAT_BTS;
935 btrace->variant.bts.blocks = NULL;
937 return linux_read_bts (&btrace->variant.bts, tinfo,
type);
939 case BTRACE_FORMAT_PT:
941 btrace->format = BTRACE_FORMAT_PT;
942 btrace->variant.pt.data = NULL;
943 btrace->variant.pt.size = 0;
945 return linux_read_pt (&btrace->variant.pt, tinfo,
type);
948 internal_error (_(
"Unkown branch trace format."));
953const struct btrace_config *
974 return BTRACE_ERR_NOT_SUPPORTED;
982 enum btrace_read_type
type)
984 return BTRACE_ERR_NOT_SUPPORTED;
989const struct btrace_config *
ssize_t read(int fd, void *buf, size_t count)
mach_port_t mach_port_t name mach_port_t mach_port_t name kern_return_t int int rusage_t pid_t pid
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)
CORE_ADDR regcache_read_pc(struct regcache *regcache)
struct regcache * get_thread_regcache_for_ptid(ptid_t ptid)
struct btrace_config conf
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