Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include <stdint.h>
  2. #include <unistd.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <fcntl.h>
  8. #include <signal.h>
  9. #include "umka.h"
  10.  
  11. #define MSR_IA32_DEBUGCTLMSR        0x1d9
  12. #define MSR_IA32_LASTBRANCHFROMIP   0x1db
  13. #define MSR_IA32_LASTBRANCHTOIP     0x1dc
  14.  
  15. int covfd, msrfd;
  16.  
  17. uint64_t rdmsr(uint32_t reg)
  18. {
  19.     uint64_t data;
  20.  
  21.     if (pread(msrfd, &data, sizeof data, reg) != sizeof data) {
  22.         perror("rdmsr: pread");
  23.         exit(1);
  24.     }
  25.  
  26.     return data;
  27. }
  28.  
  29. void wrmsr(uint32_t reg, uint64_t data)
  30. {
  31.     int fd;
  32.     fd = open("/dev/cpu/0/msr", O_WRONLY);
  33.     if (fd < 0) {
  34.         perror("wrmsr: open");
  35.         exit(1);
  36.     }
  37.  
  38.     if (pwrite(fd, &data, sizeof data, reg) != sizeof data) {
  39.         perror("wrmsr: pwrite");
  40.         exit(1);
  41.     }
  42.  
  43.     close(fd);
  44.     return;
  45. }
  46.  
  47. void handle_sigtrap() {
  48.     uint64_t from = rdmsr(MSR_IA32_LASTBRANCHFROMIP);
  49.     uint64_t to = rdmsr(MSR_IA32_LASTBRANCHTOIP);
  50.  
  51.     if ((from >= (uintptr_t)coverage_begin && from < (uintptr_t)coverage_end) ||
  52.         (to >= (uintptr_t)coverage_begin && to < (uintptr_t)coverage_end)) {
  53.         write(covfd, &from, 4);
  54.         write(covfd, &to, 4);
  55.     }
  56.  
  57.     wrmsr(MSR_IA32_DEBUGCTLMSR, 3);
  58. }
  59.  
  60. uint32_t set_eflags_tf(uint32_t tf) {
  61.     uint32_t prev;
  62.     __asm__ __inline__ __volatile__ (
  63.         "pushfd;"
  64.         "pop    eax;"
  65.         "ror    eax, 8;"
  66.         "mov    edx, eax;"
  67.         "and    edx, 1;"
  68.         "and    eax, ~1;"
  69.         "or     eax, ecx;"
  70.         "rol    eax, 8;"
  71.         "push   eax;"
  72.         "popfd"
  73.         : "=d"(prev)
  74.         : "c"(tf)
  75.         : "eax", "memory");
  76.     return prev;
  77. }
  78.  
  79. void trace_lbr_begin() {
  80.     struct sigaction action;
  81.     action.sa_sigaction = &handle_sigtrap;
  82.     action.sa_flags = SA_SIGINFO;
  83.     sigaction(SIGTRAP, &action, NULL);
  84.  
  85.     wrmsr(MSR_IA32_DEBUGCTLMSR, 3);
  86.     msrfd = open("/dev/cpu/0/msr", O_RDONLY);
  87.     if (msrfd < 0) {
  88.         perror("rdmsr: open");
  89.         exit(1);
  90.     }
  91.     char coverage_filename[32];
  92.     sprintf(coverage_filename, "coverage.%i", getpid());
  93.     covfd = open(coverage_filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH | S_IWOTH);
  94.     void *coverage_begin_addr = coverage_begin;
  95.     void *coverage_end_addr = coverage_end;
  96.     write(covfd, &coverage_begin_addr, 4);
  97.     write(covfd, &coverage_end_addr, 4);
  98. }
  99.  
  100. void trace_lbr_end() {
  101.     wrmsr(MSR_IA32_DEBUGCTLMSR, 0);
  102.     close(msrfd);
  103.     close(covfd);
  104. }
  105.  
  106. uint32_t trace_lbr_pause(void) {
  107.     return set_eflags_tf(0u);
  108. }
  109.  
  110. void trace_lbr_resume(uint32_t value) {
  111.     set_eflags_tf(value);
  112. }
  113.