LLVM "continuous" coverage profiling hack^Wpatch

From: Poul-Henning Kamp <phk_at_phk.freebsd.dk>
Date: Mon, 12 Oct 2026 19:16:14 UTC
INTRO:
======

   Coverage profiling is where the compiler adds counters in the code so
   one can tell which bits got executed how many times.

   People should use it much more than they do.

   Normally, the counters are written to a file by an atexit(3) handler
   but that goes haywire in pretty much any unplain program.

   The solution is to mmap(2) the memory for the counters, so that no
   matter how the process expires, the counts are recorded for later
   analysis.

   For this to work, the counters must be page aligned in the ELF file.

CURRENT STATE OF AFFAIRS:
=========================

Somebody has hacked support for mmap(2) counters into LLVM on Apple
platforms, and they use an Apple-only lld(1) argument ("-sectalign")
to tell the loader to align the relevant ELF-sections.

They also added a comment to the effect that

	"Support for Linux may be mostly complete but requires
	testing, and support for Windows may require more extensive
	changes: please get involved if you are interested in porting
	this feature."

And seem to have left it there.

THE PATCH:
==========

I dont know what the proper way to implement this in FreeBSD is,
but the attached hack^Wpatch makes it work for me.

It uses the same code-path as Apple platforms for the mmap(2)'ery
and hardcodes the ELF segment names into lld.

The patch should be a no-op unless profiling is enabled.

I dont know if this patch is suitable as a local patch for FreeBSD
or if there is any reason to attempt to upstream it, and I dont
have the time spend to find out.  If somebody wants to pick it
up, be my guest.

HOWTO:
======

Apply patch, recompile clang and lld. (or world).

Compile your code with

	-fprofile-instr-generate -fcoverage-mapping

Create a directory for the count files:

	rm -rf /tmp/GC
	mkdir -p /tmp/GC

Set the environment var to point to that directory:

	export LLVM_PROFILE_FILE=/tmp/GC/%p%c.profraw

The '%c' is the magic bit which enables "continous" aka mmap(2) mode.

Now run the program(s) you want tested.

	./a.out

Then merge all the count files:

	llvm-profdata merge -sparse /tmp/GC/* -o /tmp/gc.profdata

The data can be visualized with:

	llvm-cov show ./a.out -instr-profile=/tmp/gc.profdata

Enjoy,

Poul-Henning

-- 
Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
phk@FreeBSD.ORG         | TCP/IP since RFC 956
FreeBSD committer       | BSD since 4.3-tahoe
Never attribute to malice what can adequately be explained by incompetence.