To use gcov on a bare-metal target, instrument selected code with GCC and compile it with -fprofile-info-section. Retain the resulting .gcov_info pointers in the linker script, serialize coverage data through libgcov callbacks, and send the bytes to a host. There, gcov-tool merge-stream reconstructs the .gcda data that a matching version of gcov can use to generate reports. The target does not need a filesystem or a normal process-exit path, but your firmware must provide a reliable transport and a deliberate point at which to export the data.
How freestanding gcov collection works
GCC instruments the selected target code and updates its coverage counters as that code runs. With -fprofile-info-section, GCC places pointers to gcov information in a .gcov_info section instead of relying on constructors to register the information at startup or destructors to write it at shutdown. That makes the workflow suitable for firmware without the usual hosted C-library file I/O or process lifecycle.
The target is responsible for serializing and transporting the information; the host is responsible for rebuilding the data files and producing reports. The firmware can use the libgcov callbacks __gcov_filename_to_gcfn() and __gcov_info_to_gcda() to serialize file names and coverage data. GNU describes gcov as a tool used with GCC to test program code coverage.
What the target build and linker need
Compile the code you want to measure
Enable GCC coverage instrumentation for the translation units of interest and add -fprofile-info-section to their compile options. Apply instrumentation deliberately: the useful scope depends on the questions your tests need to answer, while instrumenting more code can increase target resource and export costs. Keep the exact compiler version and flags with the build artifacts so the host-side results can be reproduced.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →#1 Best Overall
- ✅【High-Performance ESP32-S3 Processor】Powered by the ESP32-S3 dual-core Xtensa LX7 processor with up to 240MHz clock speed, this development board features 16MB Flash and 8MB PSRAM. It provides powerful performance for IoT devices, embedded systems, AI applications and advanced DIY projects.
- ✅【Pre-Soldered GPIO Headers for Easy Use】The board comes with pre-soldered GPIO headers, eliminating the need for manual soldering. It can be directly connected to breadboards, sensors and expansion modules, making project setup faster and more convenient for makers and developers.
- ✅【WiFi & Bluetooth 5.0 Wireless Connectivity】Built-in 2.4GHz WiFi and Bluetooth 5.0 enable stable wireless communication for smart home, automation and IoT applications. The reserved IPEX antenna connector allows optional external antenna installation for different project requirements.
- ✅【Large Memory & Flexible Development】With 16MB Flash and 8MB PSRAM, this ESP32-S3 board provides more storage and memory resources for complex firmware, graphical interfaces, OTA updates and data-intensive applications.
- ✅【Arduino IDE, ESP-IDF & MicroPython Support】Compatible with Arduino IDE, ESP-IDF and MicroPython development environments. With dual USB-C interfaces and rich expansion options, it is suitable for robotics, sensors, automation and embedded system development.
Retain gcov pointers in the linker script
Collect the input .gcov_info sections into an output section and define symbols at its boundaries. The KEEP directive matters when the linker performs section garbage collection: without it, the linker can discard pointers that appear unused.
.gcov_info :
{
PROVIDE (__gcov_info_start = .);
KEEP (*(.gcov_info))
PROVIDE (__gcov_info_end = .);
}
Use the resulting __gcov_info_start and __gcov_info_end boundaries when walking the collected information in firmware. Adapt the fragment to the project’s linker script and memory layout; it shows the required section collection and symbols, not a complete board-specific script.
Rank #2
Link the toolchain runtime
Link with the libgcov runtime appropriate to the GCC toolchain used for the target. This is separate from transport: libgcov provides serialization callbacks, while the application must decide how serialized bytes leave the device.
How to export coverage without a target filesystem
Choose when to take a capture
Call the serialization path at a controlled point, such as a test-case boundary, periodic flush, or shutdown hook. A bare-metal system may not have a meaningful process exit, so waiting for normal termination is not a general solution. The chosen point affects what the capture represents: for example, a test-boundary export can associate a capture with an individual test, while a later export can include activity accumulated since the preceding capture or reset.
Rank #3
- Powerful Processor for Embedded Systems: The Luckfox Lyra Zero W is powered by the Rockchip RK3506B SoC, featuring a 1.2GHz ARM Cortex-A7 processor, delivering smooth performance for running Linux-based applications and making it suitable for embedded and IoT projects.
- High-Quality Display Interface: The board supports MIPI DSI 2-lane, allowing easy connection to high-resolution displays, ideal for applications like digital signage, HMI systems, and embedded interfaces.
- Extensive Connectivity Options: With USB 2.0 OTG, USB Host 2.0, and GPIO pins, the Lyra Zero W allows connectivity to various peripherals, making it versatile for sensors, devices, and other embedded systems.
- Onboard Wireless Capabilities: Equipped with Wi-Fi 6 and Bluetooth 5.2, the board supports seamless wireless communication, perfect for IoT, networking, and remote control applications.
- Cost-Effective Solution for Development: Offering a budget-friendly price, the Lyra Zero W provides a feature-rich platform for developers to prototype and create advanced embedded systems without exceeding their budget.
Provide an ordered, reliable byte stream
Walk the gcov information range and use the libgcov callbacks to serialize the associated file names and coverage data. Send the resulting bytes through a project-defined channel, such as a serial or debug transport, and capture the stream on the host. The format and transport are application responsibilities; plan for ordering, complete capture, and error detection or recovery appropriate to the channel. A truncated or corrupted stream cannot be treated as a trustworthy complete capture.
There is no universal transport choice. The appropriate channel depends on the board, available interfaces, bandwidth, and how the host records data. Coverage export also consumes resources on the target, so measure code size, RAM use, runtime impact, and transport cost on the actual device and build configuration rather than assuming a fixed overhead.
Rank #4
- CH32V003 Development Minimum System Board for Nano RISC-V CH32V003F4U6 Chip TYPE-C USB 22Pin
- on-board 24MHz Crystal oscillator
- Power by TYPE-C USB
How to merge target data and generate reports on the host
- Save the complete target byte stream as a capture file, and retain the corresponding target build and test-case identifier.
- Run
gcov-tool merge-streamwith that stream as input, for examplegcov-tool merge-stream < coverage.stream. This creates or updates the.gcdafiles from the serialized target data. - Run gcov matching the GCC version that produced the instrumented program against the reconstructed data. A reporting tool such as lcov or gcovr can then generate text or HTML output from the gcov data.
- Keep the compiler version, instrumentation flags, linker script, target build, test identifiers, and original capture together so later reports can be traced to the build and run that produced them.
Version compatibility is important: the Linux kernel’s gcov documentation likewise calls for a gcov tool compatible with the GCC version used to build the kernel. Treat the compiler and host tools as a matched set instead of assuming that a different installed gcov will interpret every capture correctly.
Quick Recap
Host-only testing or on-target collection?
| Consideration | Host-only tests | On-target collection |
|---|---|---|
| Target-specific execution | May miss startup, timing, interrupt-service-routine, and hardware paths. | Measures code as it runs on the target, including paths exercised by the device tests. |
| Collection complexity | Easier to automate without designing a target export path. | Requires linker/startup integration and an application-defined stream and capture process. |
| Target resources | Does not impose coverage instrumentation and export costs on the device under test. | Uses target resources; quantify the impact for the selected MCU, optimization level, and instrumentation scope. |
| Best fit | Fast feedback on code paths that can be exercised adequately in the host environment. | Coverage of behavior that depends on the actual target, its startup, timing, interrupts, or hardware. |
Common failure points to check
- No coverage information is exported: confirm that the relevant code was instrumented,
-fprofile-info-sectionwas used, and the linker script collects and retains.gcov_info. - Information is absent after linking: inspect section garbage-collection behavior and verify that the linker script uses
KEEPand defines the start and end symbols around the collected section. - The host cannot reconstruct data: check that the entire ordered stream was captured and that the host
gcov-toolis compatible with the GCC producer version. - The capture works but reports are incomplete: verify which code was instrumented and which paths the test actually exercised; a report cannot count execution that did not occur.
- The instrumented build disrupts target behavior: measure resource and timing effects on the real target. The GCC workflow does not establish a universal overhead figure or expected coverage percentage.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Free tools Windows power users keep installed
One-click scans. No signup required.

