Hi, The end goal here is teach kcov to support tracing of comparison instructions and switch statements in order to improve coverage during fuzzing. It's achieved by compiling the kernel with the ` -fsanitize-coverage=trace-cmp' option.
But first, some refactoring: the diff below separates the kcov descriptor state and trace mode as a first step. While here, try to improve the name of states. Comments? OK? Index: dev/kcov.c =================================================================== RCS file: /cvs/src/sys/dev/kcov.c,v retrieving revision 1.6 diff -u -p -r1.6 kcov.c --- dev/kcov.c 25 Dec 2018 21:56:53 -0000 1.6 +++ dev/kcov.c 26 Dec 2018 10:50:01 -0000 @@ -35,11 +35,12 @@ struct kcov_dev { enum { - KCOV_MODE_DISABLED, - KCOV_MODE_INIT, - KCOV_MODE_TRACE_PC, - KCOV_MODE_DYING, - } kd_mode; + KCOV_STATE_NONE, + KCOV_STATE_READY, + KCOV_STATE_TRACE, + KCOV_STATE_DYING, + } kd_state; + int kd_mode; int kd_unit; /* device minor */ uintptr_t *kd_buf; /* traced coverage */ size_t kd_nmemb; @@ -137,12 +138,15 @@ kcovclose(dev_t dev, int flag, int mode, if (kd == NULL) return (EINVAL); - DPRINTF("%s: unit=%d\n", __func__, minor(dev)); + DPRINTF("%s: unit=%d, state=%d, mode=%d\n", + __func__, kd->kd_unit, kd->kd_state, kd->kd_mode); - if (kd->kd_mode == KCOV_MODE_TRACE_PC) - kd->kd_mode = KCOV_MODE_DYING; - else + if (kd->kd_state == KCOV_STATE_TRACE) { + kd->kd_state = KCOV_STATE_DYING; + kd->kd_mode = KCOV_MODE_NONE; + } else { kd_free(kd); + } return (0); } @@ -163,20 +167,22 @@ kcovioctl(dev_t dev, u_long cmd, caddr_t break; case KIOENABLE: /* Only one kcov descriptor can be enabled per thread. */ - if (p->p_kd != NULL || kd->kd_mode != KCOV_MODE_INIT) { + if (p->p_kd != NULL || kd->kd_state != KCOV_STATE_READY) { error = EBUSY; break; } + kd->kd_state = KCOV_STATE_TRACE; kd->kd_mode = KCOV_MODE_TRACE_PC; p->p_kd = kd; break; case KIODISABLE: /* Only the enabled thread may disable itself. */ - if (p->p_kd != kd || kd->kd_mode != KCOV_MODE_TRACE_PC) { + if (p->p_kd != kd || kd->kd_state != KCOV_STATE_TRACE) { error = EBUSY; break; } - kd->kd_mode = KCOV_MODE_INIT; + kd->kd_state = KCOV_STATE_READY; + kd->kd_mode = KCOV_MODE_NONE; p->p_kd = NULL; break; default: @@ -184,8 +190,8 @@ kcovioctl(dev_t dev, u_long cmd, caddr_t DPRINTF("%s: %lu: unknown command\n", __func__, cmd); } - DPRINTF("%s: unit=%d, mode=%d, error=%d\n", - __func__, kd->kd_unit, kd->kd_mode, error); + DPRINTF("%s: unit=%d, state=%d, mode=%d, error=%d\n", + __func__, kd->kd_unit, kd->kd_state, kd->kd_mode, error); return (error); } @@ -219,12 +225,15 @@ kcov_exit(struct proc *p) if (kd == NULL) return; - DPRINTF("%s: unit=%d\n", __func__, kd->kd_unit); + DPRINTF("%s: unit=%d, state=%d, mode=%d\n", + __func__, kd->kd_unit, kd->kd_state, kd->kd_mode); - if (kd->kd_mode == KCOV_MODE_DYING) + if (kd->kd_state == KCOV_STATE_DYING) { kd_free(kd); - else - kd->kd_mode = KCOV_MODE_INIT; + } else { + kd->kd_state = KCOV_STATE_READY; + kd->kd_mode = KCOV_MODE_NONE; + } p->p_kd = NULL; } @@ -248,7 +257,7 @@ kd_init(struct kcov_dev *kd, unsigned lo KASSERT(kd->kd_buf == NULL); - if (kd->kd_mode != KCOV_MODE_DISABLED) + if (kd->kd_state != KCOV_STATE_NONE) return (EBUSY); if (nmemb == 0 || nmemb > KCOV_BUF_MAX_NMEMB) @@ -257,7 +266,7 @@ kd_init(struct kcov_dev *kd, unsigned lo size = roundup(nmemb * sizeof(uintptr_t), PAGE_SIZE); buf = malloc(size, M_SUBPROC, M_WAITOK | M_ZERO); /* malloc() can sleep, ensure the race was won. */ - if (kd->kd_mode != KCOV_MODE_DISABLED) { + if (kd->kd_state != KCOV_STATE_NONE) { free(buf, M_SUBPROC, size); return (EBUSY); } @@ -265,14 +274,15 @@ kd_init(struct kcov_dev *kd, unsigned lo /* The first element is reserved to hold the number of used elements. */ kd->kd_nmemb = nmemb - 1; kd->kd_size = size; - kd->kd_mode = KCOV_MODE_INIT; + kd->kd_state = KCOV_STATE_READY; return (0); } void kd_free(struct kcov_dev *kd) { - DPRINTF("%s: unit=%d mode=%d\n", __func__, kd->kd_unit, kd->kd_mode); + DPRINTF("%s: unit=%d, state=%d, mode=%d\n", + __func__, kd->kd_unit, kd->kd_state, kd->kd_mode); TAILQ_REMOVE(&kd_list, kd, kd_entry); free(kd->kd_buf, M_SUBPROC, kd->kd_size); Index: sys/kcov.h =================================================================== RCS file: /cvs/src/sys/sys/kcov.h,v retrieving revision 1.1 diff -u -p -r1.1 kcov.h --- sys/kcov.h 19 Aug 2018 11:42:33 -0000 1.1 +++ sys/kcov.h 26 Dec 2018 10:50:01 -0000 @@ -25,6 +25,9 @@ #define KIOENABLE _IO('K', 2) #define KIODISABLE _IO('K', 3) +#define KCOV_MODE_NONE 0 +#define KCOV_MODE_TRACE_PC 1 + #ifdef _KERNEL #define KCOV_BUF_MAX_NMEMB (256 << 10)