Add support for trace type selection in kcov(4)
Allow to specify mode in KCOV_IOC_ENABLE synchronizing the functionality with Linux, FreeBSD and OpenBSD. As a NetBSD (and OpenBSD) specific of the ioctl(2) interface, the mode argument has to be specified as &value rather than value. There are 3 modes available: 1. KCOV_MODE_NONE -- no trace specified, useful for testing purposes 2. KCOV_MODE_TRACE_PC -- trace the kernel program counter 3. KCOV_MODE_TRACE_CMP -- trace comparison instructions and switch statements Adapt the ATF tests and documentation for new API. The KCOV_MODE_TRACE_CMP mode is implemented but still awaits for the GCC 8.x upgrade or selection of Clang/LLVM as the kernel compiler. Obtained from OpenBSD and adapted for NetBSD by myself.
This commit is contained in:
parent
ffd738cfac
commit
f43e07b7f7
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: kcov.4,v 1.3 2019/03/10 12:54:39 kamil Exp $
|
||||
.\" $NetBSD: kcov.4,v 1.4 2019/03/10 17:51:00 kamil Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2018 Anton Lindqvist <anton@openbsd.org>
|
||||
.\"
|
||||
@ -82,8 +82,46 @@ entries.
|
||||
Note that kcov_int_t is volatile.
|
||||
The first entry contains the number of entries in the array,
|
||||
excluding the first entry.
|
||||
.It Dv KCOV_IOC_ENABLE Fa void
|
||||
.It Dv KCOV_IOC_ENABLE Fa int *mode
|
||||
Enable code coverage tracing for the current thread.
|
||||
The
|
||||
.Fa mode
|
||||
must be one of the following:
|
||||
.Bl -ohang
|
||||
.It Dv KCOV_MODE_NONE
|
||||
No trace selected.
|
||||
This option is useful for testing the
|
||||
.Nm
|
||||
device.
|
||||
.It Dv KCOV_MODE_TRACE_PC
|
||||
Trace the kernel program counter.
|
||||
.It Dv KCOV_MODE_TRACE_CMP
|
||||
Trace comparison instructions and switch statements.
|
||||
For switch statements, the number of traced comparison instructions is equal to
|
||||
the number of switch cases.
|
||||
Each traced comparison instruction is represented by 4 entries in the coverage
|
||||
buffer:
|
||||
.Bl -enum
|
||||
.It
|
||||
A mask where the least significant bit is set if one of the comparison operands
|
||||
is a compile-time constant, which is always true for switch statements.
|
||||
The remaining bits represents the log2 size of the operands, ranging from 0 to
|
||||
3.
|
||||
.It
|
||||
First comparison operand.
|
||||
For switch statements, this operand corresponds to the case value.
|
||||
.It
|
||||
Second comparison operand.
|
||||
For switch statements, this operand corresponds to the value passed to switch.
|
||||
.It
|
||||
Kernel program counter where the comparison instruction took place.
|
||||
.El
|
||||
.Pp
|
||||
In this mode, the first entry in the coverage buffer reflects the number of
|
||||
traced comparison instructions.
|
||||
Thus, the effective number of entries in the coverage buffer is given by
|
||||
multiplying the first entry by 4.
|
||||
.El
|
||||
.It Dv KCOV_IOC_DISABLE Fa void
|
||||
Disable code coverage tracing for the current thread.
|
||||
.El
|
||||
@ -119,6 +157,7 @@ main(void)
|
||||
kcov_int_t *cover, i, n;
|
||||
uint64_t size = 1024 * 100;
|
||||
int fd;
|
||||
int mode;
|
||||
|
||||
fd = open("/dev/kcov", O_RDWR);
|
||||
if (fd == -1)
|
||||
@ -129,7 +168,8 @@ main(void)
|
||||
PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
|
||||
if (cover == MAP_FAILED)
|
||||
err(1, "mmap");
|
||||
if (ioctl(fd, KCOV_IOC_ENABLE) == -1)
|
||||
mode = KCOV_MODE_TRACE_PC;
|
||||
if (ioctl(fd, KCOV_IOC_ENABLE, &mode) == -1)
|
||||
err(1, "ioctl: KCOV_IOC_ENABLE");
|
||||
KCOV_STORE(cover[0], 0);
|
||||
read(-1, NULL, 0); /* syscall paths to be traced */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: subr_kcov.c,v 1.4 2019/03/10 12:54:39 kamil Exp $ */
|
||||
/* $NetBSD: subr_kcov.c,v 1.5 2019/03/10 17:51:00 kamil Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019 The NetBSD Foundation, Inc.
|
||||
@ -50,6 +50,9 @@
|
||||
|
||||
#define KCOV_BUF_MAX_ENTRIES (256 << 10)
|
||||
|
||||
#define KCOV_CMP_CONST 1
|
||||
#define KCOV_CMP_SIZE(x) ((x) << 1)
|
||||
|
||||
static dev_type_open(kcov_open);
|
||||
|
||||
const struct cdevsw kcov_cdevsw = {
|
||||
@ -107,6 +110,7 @@ typedef struct kcov_desc {
|
||||
struct uvm_object *uobj;
|
||||
size_t bufnent;
|
||||
size_t bufsize;
|
||||
int mode;
|
||||
bool enabled;
|
||||
bool lwpfree;
|
||||
} kcov_t;
|
||||
@ -231,6 +235,7 @@ static int
|
||||
kcov_fops_ioctl(file_t *fp, u_long cmd, void *addr)
|
||||
{
|
||||
int error = 0;
|
||||
int mode;
|
||||
kcov_t *kd;
|
||||
|
||||
kd = fp->f_data;
|
||||
@ -259,6 +264,20 @@ kcov_fops_ioctl(file_t *fp, u_long cmd, void *addr)
|
||||
error = ENOBUFS;
|
||||
break;
|
||||
}
|
||||
|
||||
mode = *((int *)addr);
|
||||
switch (mode) {
|
||||
case KCOV_MODE_NONE:
|
||||
case KCOV_MODE_TRACE_PC:
|
||||
case KCOV_MODE_TRACE_CMP:
|
||||
kd->mode = mode;
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
}
|
||||
if (error)
|
||||
break;
|
||||
|
||||
lwp_setspecific(kcov_lwp_key, kd);
|
||||
kd->enabled = true;
|
||||
break;
|
||||
@ -356,6 +375,11 @@ __sanitizer_cov_trace_pc(void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (kd->mode != KCOV_MODE_TRACE_PC) {
|
||||
/* PC tracing mode not enabled */
|
||||
return;
|
||||
}
|
||||
|
||||
idx = KCOV_LOAD(kd->buf[0]);
|
||||
if (idx < kd->bufnent) {
|
||||
KCOV_STORE(kd->buf[idx+1],
|
||||
@ -364,6 +388,163 @@ __sanitizer_cov_trace_pc(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
trace_cmp(uint64_t type, uint64_t arg1, uint64_t arg2, intptr_t pc)
|
||||
{
|
||||
extern int cold;
|
||||
uint64_t idx;
|
||||
kcov_t *kd;
|
||||
|
||||
if (__predict_false(cold)) {
|
||||
/* Do not trace during boot. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (in_interrupt()) {
|
||||
/* Do not trace in interrupts. */
|
||||
return;
|
||||
}
|
||||
|
||||
kd = lwp_getspecific(kcov_lwp_key);
|
||||
if (__predict_true(kd == NULL)) {
|
||||
/* Not traced. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (!kd->enabled) {
|
||||
/* Tracing not enabled */
|
||||
return;
|
||||
}
|
||||
|
||||
if (kd->mode != KCOV_MODE_TRACE_CMP) {
|
||||
/* PC tracing mode not enabled */
|
||||
return;
|
||||
}
|
||||
|
||||
idx = KCOV_LOAD(kd->buf[0]);
|
||||
if ((idx * 4 + 4) <= kd->bufnent) {
|
||||
KCOV_STORE(kd->buf[idx * 4 + 1], type);
|
||||
KCOV_STORE(kd->buf[idx * 4 + 2], arg1);
|
||||
KCOV_STORE(kd->buf[idx * 4 + 3], arg2);
|
||||
KCOV_STORE(kd->buf[idx * 4 + 4], pc);
|
||||
KCOV_STORE(kd->buf[0], idx + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void __sanitizer_cov_trace_cmp1(uint8_t arg1, uint8_t arg2);
|
||||
|
||||
void
|
||||
__sanitizer_cov_trace_cmp1(uint8_t arg1, uint8_t arg2)
|
||||
{
|
||||
|
||||
trace_cmp(KCOV_CMP_SIZE(0), arg1, arg2,
|
||||
(intptr_t)__builtin_return_address(0));
|
||||
}
|
||||
|
||||
void __sanitizer_cov_trace_cmp2(uint16_t arg1, uint16_t arg2);
|
||||
|
||||
void
|
||||
__sanitizer_cov_trace_cmp2(uint16_t arg1, uint16_t arg2)
|
||||
{
|
||||
|
||||
trace_cmp(KCOV_CMP_SIZE(1), arg1, arg2,
|
||||
(intptr_t)__builtin_return_address(0));
|
||||
}
|
||||
|
||||
void __sanitizer_cov_trace_cmp4(uint32_t arg1, uint32_t arg2);
|
||||
|
||||
void
|
||||
__sanitizer_cov_trace_cmp4(uint32_t arg1, uint32_t arg2)
|
||||
{
|
||||
|
||||
trace_cmp(KCOV_CMP_SIZE(2), arg1, arg2,
|
||||
(intptr_t)__builtin_return_address(0));
|
||||
}
|
||||
|
||||
void __sanitizer_cov_trace_cmp8(uint64_t arg1, uint64_t arg2);
|
||||
|
||||
void
|
||||
__sanitizer_cov_trace_cmp8(uint64_t arg1, uint64_t arg2)
|
||||
{
|
||||
|
||||
trace_cmp(KCOV_CMP_SIZE(3), arg1, arg2,
|
||||
(intptr_t)__builtin_return_address(0));
|
||||
}
|
||||
|
||||
void __sanitizer_cov_trace_const_cmp1(uint8_t arg1, uint8_t arg2);
|
||||
|
||||
void
|
||||
__sanitizer_cov_trace_const_cmp1(uint8_t arg1, uint8_t arg2)
|
||||
{
|
||||
|
||||
trace_cmp(KCOV_CMP_SIZE(0) | KCOV_CMP_CONST, arg1, arg2,
|
||||
(intptr_t)__builtin_return_address(0));
|
||||
}
|
||||
|
||||
void __sanitizer_cov_trace_const_cmp2(uint16_t arg1, uint16_t arg2);
|
||||
|
||||
void
|
||||
__sanitizer_cov_trace_const_cmp2(uint16_t arg1, uint16_t arg2)
|
||||
{
|
||||
|
||||
trace_cmp(KCOV_CMP_SIZE(1) | KCOV_CMP_CONST, arg1, arg2,
|
||||
(intptr_t)__builtin_return_address(0));
|
||||
}
|
||||
|
||||
void __sanitizer_cov_trace_const_cmp4(uint32_t arg1, uint32_t arg2);
|
||||
|
||||
void
|
||||
__sanitizer_cov_trace_const_cmp4(uint32_t arg1, uint32_t arg2)
|
||||
{
|
||||
|
||||
trace_cmp(KCOV_CMP_SIZE(2) | KCOV_CMP_CONST, arg1, arg2,
|
||||
(intptr_t)__builtin_return_address(0));
|
||||
}
|
||||
|
||||
void __sanitizer_cov_trace_const_cmp8(uint64_t arg1, uint64_t arg2);
|
||||
|
||||
void
|
||||
__sanitizer_cov_trace_const_cmp8(uint64_t arg1, uint64_t arg2)
|
||||
{
|
||||
|
||||
trace_cmp(KCOV_CMP_SIZE(3) | KCOV_CMP_CONST, arg1, arg2,
|
||||
(intptr_t)__builtin_return_address(0));
|
||||
}
|
||||
|
||||
void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases);
|
||||
|
||||
void
|
||||
__sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases)
|
||||
{
|
||||
uint64_t i, nbits, ncases, type;
|
||||
intptr_t pc;
|
||||
|
||||
pc = (intptr_t)__builtin_return_address(0);
|
||||
ncases = cases[0];
|
||||
nbits = cases[1];
|
||||
|
||||
switch (nbits) {
|
||||
case 8:
|
||||
type = KCOV_CMP_SIZE(0);
|
||||
break;
|
||||
case 16:
|
||||
type = KCOV_CMP_SIZE(1);
|
||||
break;
|
||||
case 32:
|
||||
type = KCOV_CMP_SIZE(2);
|
||||
break;
|
||||
case 64:
|
||||
type = KCOV_CMP_SIZE(3);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
type |= KCOV_CMP_CONST;
|
||||
|
||||
for (i = 0; i < ncases; i++)
|
||||
trace_cmp(type, cases[i + 2], val, pc);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
MODULE(MODULE_CLASS_ANY, kcov, NULL);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: kcov.h,v 1.3 2019/02/25 13:19:14 kamil Exp $ */
|
||||
/* $NetBSD: kcov.h,v 1.4 2019/03/10 17:51:00 kamil Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019 The NetBSD Foundation, Inc.
|
||||
@ -37,9 +37,13 @@
|
||||
#include <sys/atomic.h>
|
||||
|
||||
#define KCOV_IOC_SETBUFSIZE _IOW('K', 1, uint64_t)
|
||||
#define KCOV_IOC_ENABLE _IO('K', 2)
|
||||
#define KCOV_IOC_ENABLE _IOW('K', 2, int)
|
||||
#define KCOV_IOC_DISABLE _IO('K', 3)
|
||||
|
||||
#define KCOV_MODE_NONE 0
|
||||
#define KCOV_MODE_TRACE_PC 1
|
||||
#define KCOV_MODE_TRACE_CMP 2
|
||||
|
||||
typedef volatile uint64_t kcov_int_t;
|
||||
#define KCOV_ENTRY_SIZE sizeof(kcov_int_t)
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <atf-c.h>
|
||||
|
||||
@ -157,6 +158,7 @@ kcov_mmap_enable_thread(void *data)
|
||||
{
|
||||
int fd;
|
||||
uint64_t size = PAGE_SIZE / KCOV_ENTRY_SIZE;
|
||||
int mode;
|
||||
|
||||
fd = open_kcov();
|
||||
*(int *)data = fd;
|
||||
@ -164,7 +166,8 @@ kcov_mmap_enable_thread(void *data)
|
||||
ATF_REQUIRE(ioctl(fd, KCOV_IOC_SETBUFSIZE, &size) ==0);
|
||||
ATF_CHECK(mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
fd, 0) != MAP_FAILED);
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE) == 0);
|
||||
mode = KCOV_MODE_NONE;
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0);
|
||||
|
||||
sem_post(&sem1);
|
||||
sem_wait(&sem2);
|
||||
@ -193,10 +196,12 @@ ATF_TC_BODY(kcov_enable, tc)
|
||||
{
|
||||
int fd;
|
||||
uint64_t size = PAGE_SIZE / KCOV_ENTRY_SIZE;
|
||||
int mode;
|
||||
|
||||
fd = open_kcov();
|
||||
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE) == -1);
|
||||
mode = KCOV_MODE_NONE;
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == -1);
|
||||
|
||||
ATF_REQUIRE(ioctl(fd, KCOV_IOC_SETBUFSIZE, &size) ==0);
|
||||
|
||||
@ -204,15 +209,26 @@ ATF_TC_BODY(kcov_enable, tc)
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_DISABLE) == -1);
|
||||
|
||||
/* Check enabling works only with a valid trace method */
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE) == 0);
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE) == -1);
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0);
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == -1);
|
||||
|
||||
/* Disable should only be called once */
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_DISABLE) == 0);
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_DISABLE) == -1);
|
||||
|
||||
/* Re-enabling should also work */
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE) == 0);
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0);
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_DISABLE) == 0);
|
||||
|
||||
/* Re-enablibling and changing mode should also work */
|
||||
mode = KCOV_MODE_NONE;
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0);
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_DISABLE) == 0);
|
||||
mode = KCOV_MODE_TRACE_PC;
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0);
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_DISABLE) == 0);
|
||||
mode = KCOV_MODE_TRACE_CMP;
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0);
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_DISABLE) == 0);
|
||||
|
||||
close(fd);
|
||||
@ -223,10 +239,12 @@ ATF_TC_BODY(kcov_enable_no_disable, tc)
|
||||
{
|
||||
int fd;
|
||||
uint64_t size = PAGE_SIZE / KCOV_ENTRY_SIZE;
|
||||
int mode;
|
||||
|
||||
fd = open_kcov();
|
||||
ATF_REQUIRE(ioctl(fd, KCOV_IOC_SETBUFSIZE, &size) ==0);
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE) == 0);
|
||||
mode = KCOV_MODE_NONE;
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
@ -235,10 +253,12 @@ ATF_TC_BODY(kcov_enable_no_disable_no_close, tc)
|
||||
{
|
||||
int fd;
|
||||
uint64_t size = PAGE_SIZE / KCOV_ENTRY_SIZE;
|
||||
int mode;
|
||||
|
||||
fd = open_kcov();
|
||||
ATF_REQUIRE(ioctl(fd, KCOV_IOC_SETBUFSIZE, &size) ==0);
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE) == 0);
|
||||
mode = KCOV_MODE_NONE;
|
||||
ATF_CHECK(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0);
|
||||
}
|
||||
|
||||
static void *
|
||||
@ -270,19 +290,19 @@ common_tail(int fd, kcov_int_t *data)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(kcov_basic);
|
||||
ATF_TC_BODY(kcov_basic, tc)
|
||||
static void
|
||||
kcov_basic(int mode)
|
||||
{
|
||||
kcov_int_t *buf;
|
||||
int fd;
|
||||
|
||||
buf = common_head(&fd);
|
||||
ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_ENABLE) == 0,
|
||||
ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0,
|
||||
"Unable to enable kcov ");
|
||||
|
||||
KCOV_STORE(buf[0], 0);
|
||||
|
||||
sleep(0);
|
||||
sleep(0); /* XXX: Is it enough for all trace types? */
|
||||
ATF_REQUIRE_MSG(KCOV_LOAD(buf[0]) != 0, "No records found");
|
||||
|
||||
ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_DISABLE) == 0,
|
||||
@ -291,17 +311,35 @@ ATF_TC_BODY(kcov_basic, tc)
|
||||
common_tail(fd, buf);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(kcov_basic_pc);
|
||||
ATF_TC_BODY(kcov_basic_pc, tc)
|
||||
{
|
||||
|
||||
kcov_basic(KCOV_MODE_TRACE_PC);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(kcov_basic_cmp);
|
||||
ATF_TC_BODY(kcov_basic_cmp, tc)
|
||||
{
|
||||
|
||||
atf_tc_skip("XXX: GCC8 needed");
|
||||
|
||||
kcov_basic(KCOV_MODE_TRACE_CMP);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(kcov_multienable_on_the_same_thread);
|
||||
ATF_TC_BODY(kcov_multienable_on_the_same_thread, tc)
|
||||
{
|
||||
kcov_int_t *buf1, *buf2;
|
||||
int fd1, fd2;
|
||||
int mode;
|
||||
|
||||
buf1 = common_head(&fd1);
|
||||
buf2 = common_head(&fd2);
|
||||
ATF_REQUIRE_MSG(ioctl(fd1, KCOV_IOC_ENABLE) == 0,
|
||||
mode = KCOV_MODE_NONE;
|
||||
ATF_REQUIRE_MSG(ioctl(fd1, KCOV_IOC_ENABLE, &mode) == 0,
|
||||
"Unable to enable kcov");
|
||||
ATF_REQUIRE_ERRNO(EBUSY, ioctl(fd2, KCOV_IOC_ENABLE) != 0);
|
||||
ATF_REQUIRE_ERRNO(EBUSY, ioctl(fd2, KCOV_IOC_ENABLE, &mode) != 0);
|
||||
|
||||
ATF_REQUIRE_MSG(ioctl(fd1, KCOV_IOC_DISABLE) == 0,
|
||||
"Unable to disable kcov");
|
||||
@ -327,10 +365,12 @@ ATF_TC_BODY(kcov_buffer_access_from_custom_thread, tc)
|
||||
pthread_t thread;
|
||||
kcov_int_t *buf;
|
||||
int fd;
|
||||
int mode;
|
||||
|
||||
buf = common_head(&fd);
|
||||
|
||||
ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_ENABLE) == 0,
|
||||
mode = KCOV_MODE_TRACE_PC;
|
||||
ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0,
|
||||
"Unable to enable kcov ");
|
||||
|
||||
pthread_create(&thread, NULL, thread_buffer_access_test_helper,
|
||||
@ -363,11 +403,13 @@ ATF_TC_BODY(kcov_thread, tc)
|
||||
pthread_t thread;
|
||||
kcov_int_t *buf;
|
||||
int fd;
|
||||
int mode;
|
||||
volatile int i;
|
||||
|
||||
buf = common_head(&fd);
|
||||
|
||||
ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_ENABLE) == 0,
|
||||
mode = KCOV_MODE_TRACE_PC;
|
||||
ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0,
|
||||
"Unable to enable kcov ");
|
||||
|
||||
/* The thread does something, does not matter what exactly. */
|
||||
@ -392,9 +434,11 @@ multiple_threads_helper(void *ptr __unused)
|
||||
{
|
||||
kcov_int_t *buf;
|
||||
int fd;
|
||||
int mode;
|
||||
|
||||
buf = common_head(&fd);
|
||||
ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_ENABLE) == 0,
|
||||
mode = KCOV_MODE_TRACE_PC;
|
||||
ATF_REQUIRE_MSG(ioctl(fd, KCOV_IOC_ENABLE, &mode) == 0,
|
||||
"Unable to enable kcov ");
|
||||
|
||||
KCOV_STORE(buf[0], 0);
|
||||
@ -452,7 +496,8 @@ ATF_TP_ADD_TCS(tp)
|
||||
ATF_TP_ADD_TC(tp, kcov_enable_no_disable);
|
||||
ATF_TP_ADD_TC(tp, kcov_enable_no_disable_no_close);
|
||||
ATF_TP_ADD_TC(tp, kcov_mmap_enable_thread_close);
|
||||
ATF_TP_ADD_TC(tp, kcov_basic);
|
||||
ATF_TP_ADD_TC(tp, kcov_basic_pc);
|
||||
ATF_TP_ADD_TC(tp, kcov_basic_cmp);
|
||||
ATF_TP_ADD_TC(tp, kcov_multienable_on_the_same_thread);
|
||||
ATF_TP_ADD_TC(tp, kcov_buffer_access_from_custom_thread);
|
||||
ATF_TP_ADD_TC(tp, kcov_thread);
|
||||
|
Loading…
x
Reference in New Issue
Block a user