> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/man/man4/kcov.4.md).

# kcov.4

`kcov` — 收集内核代码覆盖信息的接口

## 名称

`kcov`

## 概要

`要将 KCOV 编译进内核，请在你的内核配置文件中加入以下行：`

> options COVERAGE options KCOV

`以下头文件定义了 KCOV 提供的应用程序接口：`

`#include <sys/kcov.h>`

## 描述

`kcov` 是一个用于从内核收集代码覆盖信息的模块。它依赖 `COVERAGE` 内核选项启用的代码插桩。当 `kcov` 由用户态线程启用时，它仅收集该线程的覆盖信息，不包括硬中断处理程序。因此，`kcov` 不适合收集整个内核的全面覆盖数据；其主要目的是为覆盖引导的系统调用模糊测试器提供输入。

在典型用法中，用户态线程首先分配一块与 `kcov` 共享的内存。然后该线程启用覆盖追踪，内核将覆盖数据写入共享内存区域。禁用追踪后，内核放弃对共享内存区域的访问，可以消费已写入的覆盖数据。

共享内存缓冲区可视为一个 64 位无符号整数后跟一个记录数组。该整数记录有效记录数，由内核在记录覆盖信息时更新。可通过向此字段写入值 0 来重置追踪缓冲区状态。记录布局取决于使用 `KIOENABLE` ioctl 设置的追踪模式。

实现了两种追踪模式：`KCOV_MODE_TRACE_PC` 和 `KCOV_MODE_TRACE_CMP`。PC 追踪为启用追踪时执行的每个基本块记录一个程序计数器值。在此模式下，每个记录是一个包含程序计数器值的 64 位无符号整数。比较追踪提供有关数据流的信息；记录有关动态变量比较的信息。此类记录提供有关 [c(7)](/man/man7/c.7.md) `if` 或 `switch` 语句结果的信息。在此模式下，每个记录由四个 64 位无符号整数组成。第一个整数是位掩码，定义参与比较的变量的属性。如果其中一个变量在编译时具有常量值，则设置 `KCOV_CMP_CONST`；`KCOV_CMP_SIZE(n)` 指定变量的宽度：

**`KCOV_CMP_SIZE(0)`** ：8 位整数比较

**`KCOV_CMP_SIZE(1)`** ：16 位整数比较

**`KCOV_CMP_SIZE(2)`** ：32 位整数比较

**`KCOV_CMP_SIZE(3)`** ：64 位整数比较

第二和第三个字段记录两个变量的值，第四个也是最后一个字段存储比较的程序计数器值。

## IOCTL 接口

应用程序使用 ioctl(2) 系统调用与 `kcov` 交互。每个使用 `kcov` 的线程必须为 `/dev/kcov` 使用单独的文件描述符。定义了以下 ioctl：

**`KIOSETBUFSIZE`** `size_t entries` 以 `KCOV_ENTRY_SIZE` 为单位设置追踪缓冲区大小。然后可通过在 `kcov` 设备文件上调用 mmap(2) 将缓冲区映射到调用线程的地址空间。

**`KIOENABLE`** `int mode` 为调用线程启用覆盖追踪。有效模式为 `KCOV_MODE_TRACE_PC` 和 `KCOV_MODE_TRACE_CMP`。

**`KIODISABLE`** 为调用线程禁用覆盖追踪。

## 文件

`kcov` 创建 `/dev/kcov` 设备文件。

## 实例

以下代码示例收集有关执行打印 `Hello, world` 时内核代码的基本块覆盖信息。

```sh
size_t sz;
uint64_t *buf;
int fd;
fd = open("/dev/kcov", O_RDWR);
if (fd == -1)
	err(1, "open(/dev/kcov)");
sz = 1ul << 20; /* 1MB */
if (ioctl(fd, KIOSETBUFSIZE, sz / KCOV_ENTRY_SIZE) != 0)
	err(1, "ioctl(KIOSETBUFSIZE)");
buf = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (buf == MAP_FAILED)
	err(1, "mmap");
/* 启用 PC 追踪。 */
if (ioctl(fd, KIOENABLE, KCOV_MODE_TRACE_PC) != 0)
	err(1, "ioctl(KIOENABLE)");
/* 清除前一次 ioctl() 调用的追踪记录。 */
buf[0] = 0;
printf("Hello, world!n");
/* 禁用 PC 追踪。 */
if (ioctl(fd, KIODISABLE, 0) != 0)
	err(1, "ioctl(KIODISABLE)");
for (uint64_t i = 1; i < buf[0]; i++)
	printf("%#jxn", (uintmax_t)buf[i]);
```

此程序的输出可大致映射到内核源代码中的行号：

```sh
# ./kcov-test | sed 1d | addr2line -e /usr/lib/debug/boot/kernel/kernel.debug
```

## 参见

ioctl(2), mmap(2)

## 历史

`kcov` 最早出现于 FreeBSD 13.0。

## 缺陷

FreeBSD 的 `kcov` 实现尚不支持远程追踪。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://book.bsdcn.org/man/man4/kcov.4.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
