Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_kcov.c
Show First 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | |||||
#include <vm/vm_extern.h> | #include <vm/vm_extern.h> | ||||
#include <vm/vm_object.h> | #include <vm/vm_object.h> | ||||
#include <vm/vm_page.h> | #include <vm/vm_page.h> | ||||
#include <vm/vm_pager.h> | #include <vm/vm_pager.h> | ||||
#include <vm/vm_param.h> | #include <vm/vm_param.h> | ||||
MALLOC_DEFINE(M_KCOV_INFO, "kcovinfo", "KCOV info type"); | MALLOC_DEFINE(M_KCOV_INFO, "kcovinfo", "KCOV info type"); | ||||
#define KCOV_ELEMENT_SIZE sizeof(uint64_t) | |||||
/* | /* | ||||
* To know what the code can safely perform at any point in time we use a | * To know what the code can safely perform at any point in time we use a | ||||
* state machine. In the normal case the state transitions are: | * state machine. In the normal case the state transitions are: | ||||
* | * | ||||
* OPEN -> READY -> RUNNING -> DYING | * OPEN -> READY -> RUNNING -> DYING | ||||
* | | ^ | ^ ^ | * | | ^ | ^ ^ | ||||
* | | +--------+ | | | * | | +--------+ | | | ||||
* | +-------------------+ | | * | +-------------------+ | | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | get_kinfo(struct thread *td) | ||||
return (info); | return (info); | ||||
} | } | ||||
static void | static void | ||||
trace_pc(uintptr_t ret) | trace_pc(uintptr_t ret) | ||||
{ | { | ||||
struct thread *td; | struct thread *td; | ||||
struct kcov_info *info; | struct kcov_info *info; | ||||
uint64_t *buf, index; | uintptr_t *buf, index; | ||||
td = curthread; | td = curthread; | ||||
info = get_kinfo(td); | info = get_kinfo(td); | ||||
if (info == NULL) | if (info == NULL) | ||||
return; | return; | ||||
/* | /* | ||||
* Check we are in the PC-trace mode. | * Check we are in the PC-trace mode. | ||||
*/ | */ | ||||
if (info->mode != KCOV_MODE_TRACE_PC) | if (info->mode != KCOV_MODE_TRACE_PC) | ||||
return; | return; | ||||
KASSERT(info->kvaddr != 0, | KASSERT(info->kvaddr != 0, | ||||
("__sanitizer_cov_trace_pc: NULL buf while running")); | ("__sanitizer_cov_trace_pc: NULL buf while running")); | ||||
buf = (uint64_t *)info->kvaddr; | buf = (uintptr_t *)info->kvaddr; | ||||
/* The first entry of the buffer holds the index */ | /* The first entry of the buffer holds the index */ | ||||
index = buf[0]; | index = buf[0]; | ||||
if (index + 2 > info->entries) | if (index + 2 > info->entries) | ||||
return; | return; | ||||
buf[index + 1] = ret; | buf[index + 1] = ret; | ||||
buf[0] = index + 1; | buf[0] = index + 1; | ||||
▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | kcov_mmap_single(struct cdev *dev, vm_ooffset_t *offset, vm_size_t size, | ||||
if ((nprot & (PROT_EXEC | PROT_READ | PROT_WRITE)) != | if ((nprot & (PROT_EXEC | PROT_READ | PROT_WRITE)) != | ||||
(PROT_READ | PROT_WRITE)) | (PROT_READ | PROT_WRITE)) | ||||
return (EINVAL); | return (EINVAL); | ||||
if ((error = devfs_get_cdevpriv((void **)&info)) != 0) | if ((error = devfs_get_cdevpriv((void **)&info)) != 0) | ||||
return (error); | return (error); | ||||
if (info->kvaddr == 0 || size / KCOV_ELEMENT_SIZE != info->entries) | if (info->kvaddr == 0 || size / KCOV_ENTRY_SIZE != info->entries) | ||||
return (EINVAL); | return (EINVAL); | ||||
vm_object_reference(info->bufobj); | vm_object_reference(info->bufobj); | ||||
*offset = 0; | *offset = 0; | ||||
*object = info->bufobj; | *object = info->bufobj; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
kcov_alloc(struct kcov_info *info, size_t entries) | kcov_alloc(struct kcov_info *info, size_t entries) | ||||
{ | { | ||||
size_t n, pages; | size_t n, pages; | ||||
vm_page_t m; | vm_page_t m; | ||||
KASSERT(info->kvaddr == 0, ("kcov_alloc: Already have a buffer")); | KASSERT(info->kvaddr == 0, ("kcov_alloc: Already have a buffer")); | ||||
KASSERT(info->state == KCOV_STATE_OPEN, | KASSERT(info->state == KCOV_STATE_OPEN, | ||||
("kcov_alloc: Not in open state (%x)", info->state)); | ("kcov_alloc: Not in open state (%x)", info->state)); | ||||
if (entries < 2 || entries > kcov_max_entries) | if (entries < 2 || entries > kcov_max_entries) | ||||
return (EINVAL); | return (EINVAL); | ||||
/* Align to page size so mmap can't access other kernel memory */ | /* Align to page size so mmap can't access other kernel memory */ | ||||
info->bufsize = roundup2(entries * KCOV_ELEMENT_SIZE, PAGE_SIZE); | info->bufsize = roundup2(entries * KCOV_ENTRY_SIZE, PAGE_SIZE); | ||||
pages = info->bufsize / PAGE_SIZE; | pages = info->bufsize / PAGE_SIZE; | ||||
if ((info->kvaddr = kva_alloc(info->bufsize)) == 0) | if ((info->kvaddr = kva_alloc(info->bufsize)) == 0) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
info->bufobj = vm_pager_allocate(OBJT_PHYS, 0, info->bufsize, | info->bufobj = vm_pager_allocate(OBJT_PHYS, 0, info->bufsize, | ||||
PROT_READ | PROT_WRITE, 0, curthread->td_ucred); | PROT_READ | PROT_WRITE, 0, curthread->td_ucred); | ||||
▲ Show 20 Lines • Show All 199 Lines • Show Last 20 Lines |