covdbg 1.5.0: Windows on ARM, 32-bit programs, Cobertura and exact counts
covdbg 1.5.0 is available. It measures programs on more of the machines you build for: natively on Windows on ARM, and 32-bit programs with the x64 covdbg. It exports Cobertura XML, counts every run of a block exactly in PERSISTENT mode, and measures a public repository in GitHub Actions without a secret.
In this release: Windows on ARM and 32-bit programs · Cobertura XML · Exact counts · No secret for public repositories · More in 1.5.0 · Upgrading
Windows on ARM and 32-bit programs
covdbg now comes in a native ARM64 build, which measures ARM64 programs on Windows on ARM. Download the ARM64 installer or ZIP.
The x64 covdbg also measures 32-bit x86 programs, which Windows runs under WOW64. There is no separate 32-bit covdbg to install: you run the same covdbg.exe against a 32-bit test executable, and it uses libcovdbg32.dll, a 32-bit build of its agent, which ships in the x64 installer and ZIP. The ARM64 build measures ARM64 programs only, and refuses a 32-bit one before it starts.
| covdbg build | Measures |
|---|---|
| x64 | x64 and 32-bit x86 programs |
| ARM64 | ARM64 programs |
Coverage from different builds of a program combines too. covdbg merge keeps two different builds at one path, such as the x64 and ARM64 builds of your tests, side by side, and combines the lines of the sources they share. It also merges databases recorded in different checkouts, matching source files by their path relative to each run's source_root.
See Installation.
Cobertura XML
Codecov and most CI coverage dashboards read Cobertura, and it is what Windows C++ projects that measure coverage with OpenCppCoverage produce today. covdbg 1.5.0 writes it:
covdbg convert -i coverage.covdb -f COBERTURA -o coverage.xml
Each source file is a class and each module a package, the way OpenCppCoverage grouped them, so a dashboard and the coverage history behind it carry over. When you switch, the collector is the only step that changes:
- name: Convert to Cobertura
shell: pwsh
run: covdbg convert -i tests.covdb -f COBERTURA -o coverage.xml
- name: Upload to Codecov
uses: codecov/codecov-action@v5
with:
files: coverage.xml
See Cobertura Format.
Exact counts in PERSISTENT mode
--mode PERSISTENT counts how many times each block ran. Until now, covdbg took a block's probe out to run the instruction under it and put it back afterwards. While it was out, another thread could run the same block without being counted, so busy code shared by many threads was undercounted.
In 1.5.0 the probe stays in place. covdbg runs the instruction from a relocated copy and jumps back, so the counts are exact, even when many threads run the same code at once. A few blocks still take the probe out: those that start with an indirect call, a trap such as int3 or ud2, or an ARM64 exclusive load or store, and every block in a process that runs with hardware shadow stacks (CET). Their counts are a lower bound when several threads run them at the same time.
PERSISTENT mode also counts an instruction once when it faults and the program's exception handler runs it again, including when the handler itself faults first, up to four faults nested in one another's handlers on a thread.
See the CLI reference.
No secret for public repositories
Public repositories are free, but until now their CI still had to carry a project token. Every public project had to create one and store it as a secret before its coverage step could pass.
From 1.5.0, a job in GitHub Actions only needs permission to request GitHub's token for itself:
jobs:
coverage:
runs-on: windows-latest
permissions:
contents: read
id-token: write # lets covdbg prove which repository this run belongs to
Without COVDBG_PROJECT_TOKEN and without a stored sign-in, covdbg presents that token, which GitHub signs with the name of the repository the job runs in. For a public repository nothing else is needed. A private repository still needs a project token, and one that is set takes precedence.
GitHub issues no token to a pull request from a fork, for the same reason it withholds secrets there. Measure pushes and pull requests from your own repository, and skip fork pull requests. The GitHub Actions guide shows how.
More in 1.5.0
- CTest under covdbg. With
--follow-children, a launcher without debug information of its own, such asctest.exeorcmd.exe, runs unmeasured, and covdbg measures the processes it starts.covdbg --follow-children ctest.exe --test-dir buildmeasures the test binaries CTest runs. Every process of one binary now adds its hits to one coverage database, so runs that start many processes finish much sooner. - Programs that debug themselves. JITs, anti-debug checks and embedded debuggers get their own single steps and breakpoints passed on. Code after a resumable
__debugbreakis measured, andif (x) __debugbreak();no longer loops forever. - More precise analysis. covdbg follows switch jump tables to their cases, as MSVC and Clang lay them out, and keeps probes out of jump tables and ARM64 literal pools.
- Writable code is optional.
--optimization-mode FAVOR_STABILITYgives probed code pages their original protection back, for targets or security software that object to writable code.FAVOR_SPEED, the default, keeps them writable for the fastest run. - MCP queries have limits. The
covdbg mcpquerytool stops a statement at a time limit and bounds the size of its result, so a runaway query no longer blocks your agent's session.covdbg mcp --query-timeoutchanges the limit. - Upgrades without a reboot. Upgrading or uninstalling covdbg while
covdbg mcpruns no longer needs a reboot. The running server stays on the old version until the client reconnects.
Moving to 1.5.0
- Install covdbg 1.5.0. In GitHub Actions, set
version: '1.5.0'onliasoft/setup-covdbg. - Record your coverage again. Coverage databases are now schema 8, and 1.5.0 refuses
.covdbfiles written by earlier versions. - Check patterns with a
/in them. Afiles:ormodules:pattern with a/at the start or in the middle is now anchored to the directory of the.covdbg.yamlthat holds it.src/**/*.cppmatchessrc\app\main.cppnext to the config, but no longerlib\src\x.cpp. A pattern without a/, or one that starts with**/, matches at any depth as before. See Configuration. - Keep covdbg's files together. covdbg looks for its agent DLLs only beside
covdbg.exe. A run without them now stops with exit code 1, where it used to record nothing and exit 0. - Check your option values. An invalid
--mode,--symbol-engine,--formator--log-level, orlog_levelin.covdbg.yaml, is refused instead of falling back to the default.covdbg analyzefails with exit code 1 when it cannot load its config. - On a public repository in GitHub Actions, you can grant
id-token: writeand remove theCOVDBG_PROJECT_TOKENsecret.
The full list of changes is in the changelog.
Try it with your project
Download covdbg and follow the quick-start guide. If you have questions about moving to ARM64, 32-bit programs or Cobertura, email our support team.