umka/trace_lbr.c

116 lines
2.5 KiB
C
Raw Normal View History

2019-10-09 01:35:47 +02:00
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
2021-12-12 11:35:35 +01:00
#ifndef _WIN32
#include <unistd.h>
2019-10-09 01:35:47 +02:00
#include <fcntl.h>
2021-12-12 11:35:35 +01:00
#endif
#include "umka.h"
2019-10-09 01:35:47 +02:00
#define MSR_IA32_DEBUGCTLMSR 0x1d9
#define MSR_IA32_LASTBRANCHFROMIP 0x1db
#define MSR_IA32_LASTBRANCHTOIP 0x1dc
2019-10-09 01:35:47 +02:00
int covfd, msrfd;
uint64_t rdmsr(uint32_t reg)
{
2021-12-12 11:35:35 +01:00
uint64_t data = 0;
2019-10-09 01:35:47 +02:00
2021-12-12 11:35:35 +01:00
#ifndef _WIN32
2019-10-09 01:35:47 +02:00
if (pread(msrfd, &data, sizeof data, reg) != sizeof data) {
perror("rdmsr: pread");
exit(1);
}
2021-12-12 11:35:35 +01:00
#else
printf("STUB: %s:%d", __FILE__, __LINE__);
#endif
2019-10-09 01:35:47 +02:00
return data;
}
void wrmsr(uint32_t reg, uint64_t data)
{
2021-12-12 11:35:35 +01:00
#ifndef _WIN32
2019-10-09 01:35:47 +02:00
int fd;
fd = open("/dev/cpu/0/msr", O_WRONLY);
if (fd < 0) {
perror("wrmsr: open");
exit(1);
}
if (pwrite(fd, &data, sizeof data, reg) != sizeof data) {
perror("wrmsr: pwrite");
exit(1);
}
close(fd);
2021-12-12 11:35:35 +01:00
#else
printf("STUB: %s:%d", __FILE__, __LINE__);
#endif
2019-10-09 01:35:47 +02:00
}
void handle_sigtrap() {
2021-12-12 11:35:35 +01:00
#ifndef _WIN32
uint64_t from = rdmsr(MSR_IA32_LASTBRANCHFROMIP);
uint64_t to = rdmsr(MSR_IA32_LASTBRANCHTOIP);
2019-10-09 01:35:47 +02:00
if ((from >= (uintptr_t)coverage_begin && from < (uintptr_t)coverage_end) ||
(to >= (uintptr_t)coverage_begin && to < (uintptr_t)coverage_end)) {
write(covfd, &from, 4);
write(covfd, &to, 4);
2019-10-09 01:35:47 +02:00
}
wrmsr(MSR_IA32_DEBUGCTLMSR, 3);
2021-12-12 11:35:35 +01:00
#else
printf("STUB: %s:%d", __FILE__, __LINE__);
#endif
}
2021-12-04 18:58:16 +01:00
uint32_t set_eflags_tf(uint32_t tf);
2019-10-09 01:35:47 +02:00
void trace_lbr_begin() {
2021-12-12 11:35:35 +01:00
#ifndef _WIN32
2019-10-09 01:35:47 +02:00
struct sigaction action;
action.sa_sigaction = &handle_sigtrap;
action.sa_flags = SA_SIGINFO;
sigaction(SIGTRAP, &action, NULL);
wrmsr(MSR_IA32_DEBUGCTLMSR, 3);
2019-10-09 01:35:47 +02:00
msrfd = open("/dev/cpu/0/msr", O_RDONLY);
if (msrfd < 0) {
perror("rdmsr: open");
exit(1);
}
char coverage_filename[32];
sprintf(coverage_filename, "coverage.%i", getpid());
covfd = open(coverage_filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH | S_IWOTH);
void *coverage_begin_addr = coverage_begin;
void *coverage_end_addr = coverage_end;
write(covfd, &coverage_begin_addr, 4);
write(covfd, &coverage_end_addr, 4);
2021-12-12 11:35:35 +01:00
#else
printf("STUB: %s:%d", __FILE__, __LINE__);
#endif
2019-10-09 01:35:47 +02:00
}
void trace_lbr_end() {
2021-12-12 11:35:35 +01:00
#ifndef _WIN32
wrmsr(MSR_IA32_DEBUGCTLMSR, 0);
2019-10-09 01:35:47 +02:00
close(msrfd);
close(covfd);
2021-12-12 11:35:35 +01:00
#else
printf("STUB: %s:%d", __FILE__, __LINE__);
#endif
2019-10-09 01:35:47 +02:00
}
uint32_t trace_lbr_pause(void) {
return set_eflags_tf(0u);
}
void trace_lbr_resume(uint32_t value) {
set_eflags_tf(value);
}