Product
Solutions
Resources
Company
Download Trial Book a Demo
RKTracer · Kernel code coverage

Code coverage for device drivers and kernel modules

User-space coverage tools stop at the syscall boundary. RKTracer follows your code into Linux kernel modules and device drivers, measuring every metric from statement and branch to MC/DC, without changing a line of your kernel source. Instrument the cross-compiled build, run on an ARM64 board or QEMU, and capture coverage from a kernel buffer.

No source changes · any cross-compiler · HTML and XML reports

arm64 · kernel-module coverage
# Coverage that follows your code into kernel space
$ make CC="rktracer -r aarch64-linux-gnu-gcc" \
       ARCH=arm64 LD=aarch64-linux-gnu-ld

  instrumenting kernel C sources…
   build complete, no source modified

# Run on the target, then read the kernel buffer
$ insmod knetstat.ko
$ cat /proc/RK_MEM.raw > RK_MEM.raw
$ rkresults
   statement 100% · decision 98% · MC/DC 96%
The kernel coverage problem

Why coverage inside the kernel and drivers is hard

Kernel and driver code is the hardest place in the system to instrument. There is no user-space runtime, so the usual coverage libraries and exit handlers never run. The code is cross-compiled for a foreign target, so coverage has to reflect the exact objects that ship, not a desktop rebuild. And the device often cannot simply write a coverage file to disk, because kernel code never returns to main() and may have no file system at all.

RKTracer is built for exactly this. It applies a small kernel patch so coverage counters live in a kernel memory buffer, hooks your cross-compiler so probes are injected during the real build, and reads the buffer out from the running target. The same statement, branch, condition and MC/DC rigor you apply to application code now reaches the modules that talk to hardware, with no source edits and no change to how you build the kernel.

This matters because drivers and kernel modules are exactly the code where structural coverage is hardest to fake and most worth having. Interrupt handlers, error paths, ioctl branches, lock contention and device fault handling are easy to skip in a test run and easy to miss in review. Device driver code coverage tells you which of those paths your tests actually exercised on the real target, so an untested error branch in a network or storage driver is caught before it ships rather than in the field. Because RKTracer reports per file and per function, you can see coverage of a single driver in isolation, even inside a kernel tree of millions of lines.

Instrumenting kernel modules and drivers

Instrument kernel C code by prefixing the compiler

RKTracer instruments Linux kernel modules and device drivers through your existing cross-compiled build. You do not edit a single line of kernel source. You apply the RKTracer kernel patch once, then point the build's compiler at the rktracer prefix so probes are injected as the kernel C code compiles.

  • Patch once. Apply 01-rktracer.patch so a coverage buffer lives in kernel memory and survives module load and unload.
  • Prefix the compiler. Set CC to the rktracer wrapper around your cross-compiler, for example aarch64-linux-gnu-gcc.
  • No source changes. Coverage maps to the very objects you ship, because instrumentation runs through the toolchain that builds your kernel image.

Step-by-step guides: kernel module coverage and Makefile builds.

patch-and-build.sh
# 1 · apply the RKTracer kernel coverage patch
$ patch -p1 < /home/rkvalidate/share/rktracer/01-rktracer.patch

# 2 · build a standalone module through the cross-compiler
$ make CC="rktracer -r aarch64-linux-gnu-gcc" \
       ARCH=arm64 LD=aarch64-linux-gnu-ld

# or instrument an in-tree subsystem via its Makefile
CC := rktracer -r ${CC}

   knetstat.ko instrumented · no source modified
Capturing coverage on the target

From kernel buffer to coverage report

A repeatable, scriptable loop. The same stages whether you cover a standalone driver, a file system under test, or a selectively instrumented subsystem, on real ARM64 silicon or a QEMU emulator.

1

Boot the target

Boot the instrumented kernel on a real ARM64 board or a QEMU 64-bit ARM emulator, then copy the instrumented .ko over with scp.

2

Load and exercise

Run insmod knetstat.ko, then drive the driver paths: I/O, /proc reads, fault handling and unload.

3

Read the buffer

Counts accumulate in kernel memory. Read them out, for example cat /proc/RK_MEM.raw > RK_MEM.raw, across multiple loads.

4

Generate the report

rkresults turns RK_MEM.raw into HTML and XML coverage, from statement through MC/DC, off-target.

Two common capture scenarios

Standalone driver module. Cover an out-of-tree kernel module such as knetstat: load it, drive its /proc and socket paths, unload, then read the buffer.

Kernel file system. Run the Linux Test Project file-system suite with runltp -s fs against an instrumented kernel, using the rkmem.ko interface module to read out coverage of VFS and driver paths.

on-target.sh
# standalone driver, on ARM64 or QEMU
$ insmod knetstat.ko
$ cat /proc/net/tcp_estats
$ rmmod knetstat
$ cat /proc/RK_MEM.raw > RK_MEM.raw

# kernel file system, via LTP
$ insmod /lib/modules/4.19.16/kernel/\
    drivers/char/rkmem.ko
$ ./runltp -s fs
$ rkresults
   RK_MEM.raw → rkresults/index.html
rktracer.config

Selective coverage by folder or function

Kernel trees are huge, and not every subsystem belongs in your coverage scope. The rktracer.config file gives you folder-level and function-level control, so probes stay off the paths you must not touch and measurement focuses on the driver under test.

instrument opts folders into probing and reporting, such as */power/* */core/* */keys/*. ignore drops files or folders from the report, for example ignore *.c to start clean. never guarantees no probes are emitted at all for sensitive paths such as */firmware_loader/* */lockdown/*, early boot, or timing-critical code.

Restrict probing to named functions, for example function-instrument fun_X() fun_Y() fun_Z(). Ideal for isolating the handful of driver entry points that carry your requirements.

Exclude individual functions such as debug helpers, logging, or vendor stubs with function-ignore * or a name list, so they neither carry overhead nor dilute your coverage percentages.

rktracer.config
# start by excluding everything, then opt in
ignore     *.c
instrument */power/* */core/* */keys/*

# never emit probes for sensitive paths
never      */firmware_loader/* */lockdown/*

# function-level control
function-instrument fun_X() fun_Y() fun_Z()
function-ignore     *

never excludes code from instrumentation entirely, giving build-time safety, while ignore can compile probes but omit a region from the report, giving report-time control.

Coverage metrics

Every metric for kernel code, through MC/DC

The same structural coverage you measure for application code now reaches kernel modules and device drivers.

Most coverage tools stop at statement or line coverage on a desktop build. RKTracer measures the full set of structural metrics for kernel space: function, file, statement, branch and decision, condition, MC/DC, multi-condition and delta (changed-code) coverage. MC/DC for C and C++ is the strongest structural metric and the one the highest assurance levels reference. Kernel and driver code is C, so MC/DC applies directly.

Statement coverage answers "did this line run?" Decision coverage adds "was each branch taken both ways?" Condition and MC/DC go further still: they ask whether every condition in a compound decision was independently shown to affect the outcome. In driver code, a single if that combines a device state flag, a buffer-length check and an error code is the kind of compound decision where statement coverage looks complete while a real bug hides in an untested combination. RKTracer measures all of these for the exact kernel objects you ship, and delta coverage lets you focus a review on only the lines that changed in the latest patch.

Coverage metricReferenced at
StatementDO-178C Level C · ISO 26262 ASIL A
Decision / BranchDO-178C Level B · ASIL B/C
MC/DCDO-178C Level A · ASIL D
Multi-ConditionDeep verification · IEC 61508 SIL 4

RKValidate is an ISO 9001 quality-certified vendor. RKTracer measures the coverage metrics these standards reference; it does not itself carry a functional-safety certification, and the standards are shown only as context.

rkresults · knetstat.koOn-target
Function100%
Statement100%
Decision98%
Condition97%
MC/DC96%
Multi-condition94%

QEMU
aarch64 target
RK_MEM.raw
capture source
0
source edits
CI and reports

Audit-ready reports, gateable in CI

Report output

  • HTML and XML from rkresults
  • Per-file and per-function detail
  • MC/DC pair tables per decision
  • Merge multiple RK_MEM.raw runs

Targets

  • Real ARM64 silicon
  • QEMU 64-bit ARM emulator
  • Targets with or without a file system
  • Any kernel cross-compiler

CI and dashboards

  • Jenkins, Azure DevOps, GitLab CI
  • Publishes coverage to SonarQube
  • Threshold gates per build
  • Delta coverage on changed code

Targets without a file system can stream coverage out without writing to disk: see coverage on targets without a file system.

From coverage to tests

Coverage finds the gaps. Two ways to close them.

RKTracer pinpoints the uncovered lines, decisions and MC/DC conditions in your kernel modules and drivers. Turning those gaps into tests is your choice, and both options are part of the RKTracer tool.

RKTracer itself measures coverage; it is not a test generator. The two tools below generate the tests.

See features and how RKTracer works

RKMCP · AI-assisted

An MCP server that streams the uncovered code to your AI agent over MCP. The AI writes the unit and functional tests plus the build, then runs and re-checks until the gaps close.

RKTracerGen · offline, C and C++ only

A deterministic, fully offline unit-test generator for C and C++ only. Since kernel and driver code is C, it applies here. No AI, no tokens, no network.

FAQ

Kernel code coverage questions, answered

Yes. RKTracer measures kernel code coverage and device driver code coverage from inside kernel space. It applies a small kernel patch so coverage counts live in a kernel buffer, instruments the cross-compiled build, and captures the data from the running target. The same metrics you get for application code, including MC/DC, reach kernel modules and drivers.
Apply the RKTracer kernel patch, then build by setting the compiler to the rktracer prefix, for example CC="rktracer -r aarch64-linux-gnu-gcc" ARCH=arm64. There are no source edits. RKTracer instruments the kernel C code at compile time through your existing cross-compiler and adds its runtime automatically.
Coverage counts accumulate in an in-kernel buffer. You load the module with insmod, exercise the driver paths, then read the buffer out, for example cat /proc/RK_MEM.raw > RK_MEM.raw, on real ARM64 silicon or a QEMU emulator. The raw data is turned into reports off-target with rkresults.
Function, file, statement, branch/decision, condition, MC/DC, multi-condition and delta coverage, all for kernel modules and device drivers. MC/DC for C and C++ is the strongest structural metric and the one the highest assurance levels reference.
Yes. The rktracer.config file gives folder and function control. Use instrument and ignore to scope folders, never to exclude code such as firmware loader or lockdown paths entirely, and function-instrument and function-ignore to probe or skip named functions. This keeps probes off paths you must not touch and focuses measurement on the driver under test.
RKTracer measures coverage and pinpoints the uncovered lines, decisions and MC/DC conditions. It does not itself generate tests. To close gaps you can use RKMCP, which serves the gaps to your AI agent over MCP, or RKTracerGen, a deterministic offline unit-test generator for C and C++ only. Since kernel and driver code is C, RKTracerGen applies.

Looking for the full product? Read the RKTracer code coverage tool overview, browse the documentation, or learn how RKTracer works.

Measure coverage inside your own kernel modules

Download the free 30-day trial and capture MC/DC on your own driver, ARM64 target or QEMU, this week, or book a demo with an engineer.