From 395221551d512de1b42160643b779d2decc9e120 Mon Sep 17 00:00:00 2001 From: Mitchell Horne Date: Wed, 4 Apr 2018 17:13:36 -0400 Subject: executor: update to support FreeBSD kcov Make the required changes to the BSD executor file to interface with FreeBSD's kernel coverage implementation. This will allow coverage to be used when running syzkaller on this platform. --- executor/executor_bsd.cc | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'executor/executor_bsd.cc') 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 #include +#include #include #include #include #include +#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) -- cgit mrf-deployment