28 #ifdef HAVE_SYS_SYSCALL_H
29 #include <sys/syscall.h>
32 #if HAVE_LINUX_PERF_EVENT_H && defined(SYS_perf_event_open)
36 #include <sys/ptrace.h>
37 #include <sys/types.h>
39 #include <sys/utsname.h>
52 struct perf_event_sample
55 struct perf_event_header header;
58 struct perf_event_bts bts;
63 btrace_this_cpu (void)
66 unsigned int eax, ebx, ecx, edx;
69 memset (&cpu, 0,
sizeof (cpu));
71 ok =
x86_cpuid (0, &eax, &ebx, &ecx, &edx);
77 unsigned int cpuid,
ignore;
79 ok =
x86_cpuid (1, &cpuid, &ignore, &ignore, &ignore);
84 cpu.family = (cpuid >> 8) & 0xf;
85 cpu.model = (cpuid >> 4) & 0xf;
87 if (cpu.family == 0x6)
88 cpu.model += (cpuid >> 12) & 0xf0;
99 perf_event_new_data (
const struct perf_event_buffer *pev)
101 return *pev->data_head != pev->last_head;
114 perf_event_read (
const struct perf_event_buffer *pev,
unsigned long data_head,
117 const gdb_byte *begin, *end, *start, *stop;
119 unsigned long data_tail, buffer_size;
125 data_tail = data_head -
size;
127 buffer_size = pev->size;
129 start = begin + data_tail % buffer_size;
130 stop = begin + data_head % buffer_size;
135 memcpy (buffer, start, stop - start);
138 end = begin + buffer_size;
140 memcpy (buffer, start, end - start);
141 memcpy (buffer + (end - start), begin, stop - begin);
151 perf_event_read_all (
struct perf_event_buffer *pev,
gdb_byte **data,
152 unsigned long *psize)
154 unsigned long data_head,
size;
156 data_head = *pev->data_head;
159 if (data_head < size)
162 *data = perf_event_read (pev, data_head, size);
165 pev->last_head = data_head;
172 perf_event_pt_event_type (
int *type)
177 file = fopen (
"/sys/bus/event_source/devices/intel_pt/type",
"r");
181 found = fscanf (file,
"%d", type);
191 linux_determine_kernel_ptr_bits (
void)
196 memset (&utsn, 0,
sizeof (utsn));
198 errcode = uname (&utsn);
204 if (strcmp (utsn.machine,
"x86_64") == 0)
224 mask = (uint64_t) 1 << (tinfo->
ptr_bits - 1);
227 return (addr & mask) != 0;
234 const struct perf_event_bts *bts)
239 return perf_event_is_kernel_addr (tinfo, bts->from);
246 perf_event_sample_ok (
const struct perf_event_sample *sample)
248 if (sample->header.type != PERF_RECORD_SAMPLE)
251 if (sample->header.size != sizeof (*sample))
272 const uint8_t *end,
const uint8_t *start,
273 unsigned long long size)
276 struct perf_event_sample sample;
277 unsigned long long read = 0;
279 struct regcache *regcache;
290 read =
sizeof (sample) - 1;
292 for (; read <
size; read +=
sizeof (sample))
294 const struct perf_event_sample *psample;
297 start -=
sizeof (sample);
301 psample = (
const struct perf_event_sample *) start;
309 missing = (begin - start);
310 start = (end - missing);
313 if (missing ==
sizeof (sample))
314 psample = (
const struct perf_event_sample *) start;
321 stack = (uint8_t *) &sample;
324 memcpy (stack, start, missing);
325 memcpy (stack + missing, begin,
sizeof (sample) - missing);
331 if (!perf_event_sample_ok (psample))
333 warning (
_(
"Branch trace may be incomplete."));
337 if (perf_event_skip_bts_record (tinfo, &psample->bts))
341 block.
begin = psample->bts.to;
346 block.
end = psample->bts.from;
362 kernel_supports_bts (
void)
364 struct perf_event_attr attr;
373 warning (
_(
"test bts: cannot fork: %s."), strerror (errno));
377 status =
ptrace (PTRACE_TRACEME, 0, NULL, NULL);
380 warning (
_(
"test bts: cannot PTRACE_TRACEME: %s."),
385 status =
raise (SIGTRAP);
388 warning (
_(
"test bts: cannot raise SIGTRAP: %s."),
396 pid = waitpid (child, &status, 0);
399 warning (
_(
"test bts: bad pid %ld, error: %s."),
400 (
long) pid, strerror (errno));
406 warning (
_(
"test bts: expected stop. status: %d."),
411 memset (&attr, 0,
sizeof (attr));
413 attr.type = PERF_TYPE_HARDWARE;
414 attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
415 attr.sample_period = 1;
416 attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_ADDR;
417 attr.exclude_kernel = 1;
419 attr.exclude_idle = 1;
421 file =
syscall (SYS_perf_event_open, &attr, child, -1, -1, 0);
425 kill (child, SIGKILL);
426 ptrace (PTRACE_KILL, child, NULL, NULL);
428 pid = waitpid (child, &status, 0);
431 warning (
_(
"test bts: bad pid %ld, error: %s."),
432 (
long) pid, strerror (errno));
434 warning (
_(
"test bts: expected killed. status: %d."),
445 kernel_supports_pt (
void)
447 struct perf_event_attr attr;
456 warning (
_(
"test pt: cannot fork: %s."), strerror (errno));
460 status =
ptrace (PTRACE_TRACEME, 0, NULL, NULL);
463 warning (
_(
"test pt: cannot PTRACE_TRACEME: %s."),
468 status =
raise (SIGTRAP);
471 warning (
_(
"test pt: cannot raise SIGTRAP: %s."),
479 pid = waitpid (child, &status, 0);
482 warning (
_(
"test pt: bad pid %ld, error: %s."),
483 (
long) pid, strerror (errno));
489 warning (
_(
"test pt: expected stop. status: %d."),
494 status = perf_event_pt_event_type (&type);
499 memset (&attr, 0,
sizeof (attr));
501 attr.size =
sizeof (attr);
503 attr.exclude_kernel = 1;
505 attr.exclude_idle = 1;
507 file =
syscall (SYS_perf_event_open, &attr, child, -1, -1, 0);
512 kill (child, SIGKILL);
513 ptrace (PTRACE_KILL, child, NULL, NULL);
515 pid = waitpid (child, &status, 0);
518 warning (
_(
"test pt: bad pid %ld, error: %s."),
519 (
long) pid, strerror (errno));
521 warning (
_(
"test pt: expected killed. status: %d."),
532 intel_supports_bts (
const struct btrace_cpu *cpu)
563 cpu_supports_bts (
void)
567 cpu = btrace_this_cpu ();
575 return intel_supports_bts (&cpu);
582 linux_supports_bts (
void)
588 if (!kernel_supports_bts ())
590 else if (!cpu_supports_bts ())
602 linux_supports_pt (
void)
608 if (!kernel_supports_pt ())
628 return linux_supports_bts ();
631 return linux_supports_pt ();
642 struct perf_event_mmap_page *header;
644 struct btrace_tinfo_bts *bts;
645 unsigned long long size, pages, data_offset, data_size;
648 tinfo =
xzalloc (
sizeof (*tinfo));
650 tinfo->
ptr_bits = linux_determine_kernel_ptr_bits ();
653 bts = &tinfo->variant.bts;
655 bts->attr.size =
sizeof (bts->attr);
656 bts->attr.type = PERF_TYPE_HARDWARE;
657 bts->attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
658 bts->attr.sample_period = 1;
661 bts->attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_ADDR;
663 bts->attr.exclude_kernel = 1;
664 bts->attr.exclude_hv = 1;
665 bts->attr.exclude_idle = 1;
672 bts->file =
syscall (SYS_perf_event_open, &bts->attr, pid, -1, -1, 0);
677 pages = (((
unsigned long long) conf->
size) + PAGE_SIZE - 1) / PAGE_SIZE;
684 for (pg = 0; pages != (1u << pg); ++pg)
685 if ((pages & (1u << pg)) != 0)
690 for (; pages > 0; pages >>= 1)
694 size = pages * PAGE_SIZE;
695 length = size + PAGE_SIZE;
698 if ((
unsigned long long) length <
size)
702 header = mmap (NULL, length, PROT_READ, MAP_SHARED, bts->file, 0);
710 data_offset = PAGE_SIZE;
713 #if defined (PERF_ATTR_SIZE_VER5)
714 if (offsetof (
struct perf_event_mmap_page, data_size) <= header->size)
716 data_offset = header->data_offset;
717 data_size = header->data_size;
721 bts->header = header;
722 bts->bts.mem = ((
const uint8_t *) header) + data_offset;
723 bts->bts.size = data_size;
724 bts->bts.data_head = &header->data_head;
725 bts->bts.last_head = 0;
739 #if defined (PERF_ATTR_SIZE_VER5)
746 struct perf_event_mmap_page *header;
748 struct btrace_tinfo_pt *pt;
749 unsigned long long pages,
size;
755 errcode = perf_event_pt_event_type (&type);
763 tinfo =
xzalloc (
sizeof (*tinfo));
768 pt = &tinfo->variant.pt;
770 pt->attr.size =
sizeof (pt->attr);
771 pt->attr.type =
type;
773 pt->attr.exclude_kernel = 1;
774 pt->attr.exclude_hv = 1;
775 pt->attr.exclude_idle = 1;
778 pt->file =
syscall (SYS_perf_event_open, &pt->attr, pid, -1, -1, 0);
783 header = mmap (NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
788 header->aux_offset = header->data_offset + header->data_size;
791 pages = (((
unsigned long long) conf->
size) + PAGE_SIZE - 1) / PAGE_SIZE;
798 for (pg = 0; pages != (1u << pg); ++pg)
799 if ((pages & (1u << pg)) != 0)
804 for (; pages > 0; pages >>= 1)
808 size = pages * PAGE_SIZE;
812 if ((
unsigned long long) length <
size)
815 header->aux_size =
size;
817 pt->pt.mem = mmap (NULL, length, PROT_READ, MAP_SHARED, pt->file,
828 pt->pt.data_head = &header->aux_head;
834 munmap((
void *) header, PAGE_SIZE);
869 tinfo = linux_enable_bts (ptid, &conf->
bts);
873 tinfo = linux_enable_pt (ptid, &conf->
pt);
883 linux_disable_bts (
struct btrace_tinfo_bts *tinfo)
885 munmap((
void *) tinfo->header, tinfo->bts.size + PAGE_SIZE);
894 linux_disable_pt (
struct btrace_tinfo_pt *tinfo)
896 munmap((
void *) tinfo->pt.mem, tinfo->pt.size);
897 munmap((
void *) tinfo->header, PAGE_SIZE);
917 errcode = linux_disable_bts (&tinfo->variant.bts);
921 errcode = linux_disable_pt (&tinfo->variant.pt);
939 struct perf_event_buffer *pevent;
940 const uint8_t *begin, *end, *start;
941 unsigned long long data_head, data_tail, buffer_size,
size;
942 unsigned int retries = 5;
944 pevent = &tinfo->variant.bts.bts;
951 buffer_size = pevent->size;
952 data_tail = pevent->last_head;
957 data_head = *pevent->data_head;
970 if (data_head < data_tail)
974 size = data_head - data_tail;
975 if (buffer_size < size)
984 if (data_head < size)
990 start = begin + data_head % buffer_size;
992 if (data_head <= buffer_size)
995 end = begin + pevent->size;
997 btrace->blocks = perf_event_read_bts (tinfo, begin, end, start, size);
1004 if (data_head == *pevent->data_head)
1008 pevent->last_head = data_head;
1025 conf->
cpu = btrace_this_cpu ();
1036 struct perf_event_buffer *pt;
1038 pt = &tinfo->variant.pt.pt;
1040 linux_fill_btrace_pt_config (&btrace->
config);
1050 if (!perf_event_new_data (pt))
1055 perf_event_read_all (pt, &btrace->
data, &btrace->
size);
1079 return linux_read_bts (&btrace->
variant.
bts, tinfo, type);
1087 return linux_read_pt (&btrace->
variant.
pt, tinfo, type);
1090 internal_error (__FILE__, __LINE__,
_(
"Unkown branch trace format."));
1098 return &tinfo->
conf;
struct regcache * get_thread_regcache_for_ptid(ptid_t ptid)
struct btrace_config_bts bts
static __inline int x86_cpuid(unsigned int __level, unsigned int *__eax, unsigned int *__ebx, unsigned int *__ecx, unsigned int *__edx)
void warning(const char *fmt,...)
struct btrace_data_bts bts
#define signature_INTEL_ecx
void internal_error(const char *file, int line, const char *fmt,...)
#define VEC_safe_push(T, V, O)
enum btrace_error linux_read_btrace(struct btrace_data *btrace, struct btrace_target_info *tinfo, enum btrace_read_type type)
union btrace_data::@40 variant
int linux_supports_btrace(struct target_ops *ops, enum btrace_format format)
mach_port_t mach_port_t name mach_port_t mach_port_t name error_t err
void * xzalloc(size_t size)
mach_port_t mach_port_t name mach_port_t mach_port_t name error_t int status
enum btrace_format format
const struct btrace_config * linux_btrace_conf(const struct btrace_target_info *tinfo)
struct btrace_config conf
int ptid_get_pid(ptid_t ptid)
struct btrace_config_pt pt
enum btrace_error linux_disable_btrace(struct btrace_target_info *tinfo)
CORE_ADDR regcache_read_pc(struct regcache *regcache)
struct btrace_data_pt_config config
#define signature_INTEL_edx
static int ignore(struct target_ops *ops, struct gdbarch *gdbarch, struct bp_target_info *bp_tgt)
long ptid_get_lwp(ptid_t ptid)
struct btrace_target_info * linux_enable_btrace(ptid_t ptid, const struct btrace_config *conf)
enum btrace_format format
#define signature_INTEL_ebx
mach_port_t mach_port_t name mach_port_t mach_port_t name error_t int int rusage_t pid_t pid