diff options
Diffstat (limited to 'executor/executor_bsd.cc')
| -rw-r--r-- | executor/executor_bsd.cc | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/executor/executor_bsd.cc b/executor/executor_bsd.cc index ee14d84a6..10b189008 100644 --- a/executor/executor_bsd.cc +++ b/executor/executor_bsd.cc @@ -21,12 +21,24 @@ #define __syscall syscall #endif +#include <fcntl.h> #include <signal.h> +#include <sys/ioctl.h> #include <sys/mman.h> #include <sys/resource.h> #include <sys/time.h> #include <sys/types.h> +#if defined(__FreeBSD__) +#define KIOENABLE _IOW('c', 2, int) // Enable coverage recording +#define KIODISABLE _IO('c', 3) // Disable coverage recording +#define KIOSETBUFSIZE _IOW('c', 4, unsigned int) // Set the buffer size + +#define KCOV_MODE_NONE -1 +#define KCOV_MODE_TRACE_PC 0 +#define KCOV_MODE_TRACE_CMP 1 +#endif + const int kInFd = 3; const int kOutFd = 4; @@ -145,27 +157,66 @@ void cover_open() return; for (int i = 0; i < kMaxThreads; i++) { thread_t* th = &threads[i]; +#if defined(__FreeBSD__) + th->cover_fd = open("/dev/kcov", O_RDWR); + if (th->cover_fd == -1) + fail("open of /dev/kcov failed"); + if (ioctl(th->cover_fd, KIOSETBUFSIZE, &kCoverSize)) + fail("ioctl init trace write failed"); + size_t mmap_alloc_size = kCoverSize * sizeof(th->cover_data[0]); + uint64* mmap_ptr = (uint64*)mmap(NULL, mmap_alloc_size, + PROT_READ | PROT_WRITE, + MAP_SHARED, th->cover_fd, 0); + if (mmap_ptr == NULL) + fail("cover mmap failed"); + th->cover_size_ptr = mmap_ptr; + th->cover_data = &mmap_ptr[1]; +#else th->cover_data = &th->cover_buffer[0]; +#endif } } void cover_enable(thread_t* th) { +#if defined(__FreeBSD__) + if (!flag_cover) + return; + debug("#%d: enabling /dev/kcov\n", th->id); + int kcov_mode = flag_collect_comps ? KCOV_MODE_TRACE_CMP : KCOV_MODE_TRACE_PC; + if (ioctl(th->cover_fd, KIOENABLE, &kcov_mode)) + exitf("cover enable write trace failed, mode=%d", kcov_mode); + debug("#%d: enabled /dev/kcov\n", th->id); +#endif } void cover_reset(thread_t* th) { +#if defined(__FreeBSD__) + if (!flag_cover) + return; + + *th->cover_size_ptr = 0; +#endif } uint64 read_cover_size(thread_t* th) { if (!flag_cover) return 0; +#if defined(__FreeBSD__) + uint64 size = *th->cover_size_ptr; + debug("#%d: read cover size = %llu\n", th->id, size); + if (size > kCoverSize) + fail("#%d: too much cover %llu", th->id, size); + return size; +#else // Fallback coverage since we have no real coverage available. // We use syscall number or-ed with returned errno value as signal. // At least this gives us all combinations of syscall+errno. th->cover_data[0] = (th->call_num << 16) | ((th->res == -1 ? th->reserrno : 0) & 0x3ff); return 1; +#endif } uint32* write_output(uint32 v) |
