[libc-commits] [libc] [libc] Enabling code coverage via Linux syscalls (PR #213271)

Michael Jones via libc-commits libc-commits at lists.llvm.org
Tue Aug 18 10:56:31 PDT 2026


================
@@ -43,8 +43,155 @@ TestOptions parseOptions(int argc, char **argv) {
 
 } // anonymous namespace
 
-// The C++ standard forbids declaring the main function with a linkage specifier
-// outisde of 'freestanding' mode, only define the linkage for hermetic tests.
+#include "src/__support/macros/properties/os.h"
+#if defined(LIBC_TARGET_OS_IS_LINUX)
+#include "hdr/errno_macros.h"
+#include "hdr/fcntl_macros.h"
+#include "hdr/sys_mman_macros.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/close.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/mmap.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/munmap.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/open.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/write.h"
+#include "src/__support/OSUtil/syscall.h"
+#include "src/__support/CPP/optional.h"
+#include "src/__support/CPP/span.h"
+#include "src/__support/integer_to_string.h"
+#include "src/string/memory_utils/inline_memcpy.h"
+#include <sys/syscall.h>
+
+//===----------------------------------------------------------------------===//
+// Freestanding Linux Code Coverage Profile Writer
+//
+// Freestanding (-nostdlib) libc binaries cannot link standard compiler-rt
+// file I/O (fopen/fwrite). Here we override compiler-rt's default filename
+// to "/dev/null" and invoke write_raw_profile() directly before main()
+// returns (and within death test subprocesses in ExecuteFunctionUnix.cpp)
+// to dump raw coverage counters (libc_cov_<pid>.profraw) using direct Linux
+// system calls (SYS_mmap, SYS_openat, SYS_write, SYS_close, SYS_munmap).
+//===----------------------------------------------------------------------===//
+extern "C" {
+__attribute__((weak)) uint64_t __llvm_profile_get_size_for_buffer();
+__attribute__((weak)) int __llvm_profile_write_buffer(char *buffer);
+__attribute__((weak)) void
+__llvm_profile_set_filename(const char *filename_pat);
+
+// Override compiler-rt's weak filename symbol. This redirects the default
+// filename to /dev/null to silence the default dumper by default.
+__attribute__((weak)) char __llvm_profile_filename[] = "/dev/null";
+}
+
+namespace {
+struct FixedSizeBuffer {
+  char data[64];
+  size_t idx = 0;
+
+  FixedSizeBuffer() { data[0] = '\0'; }
+
+  bool append(string_view str) {
+    size_t len = str.size();
+    if (idx + len >= sizeof(data))
+      return false;
+    LIBC_NAMESPACE::inline_memcpy(data + idx, str.data(), len);
+    idx += len;
+    data[idx] = '\0';
+    return true;
+  }
+
+  template <size_t N> bool append(const char (&str)[N]) {
+    size_t len = N - 1;
+    if (idx + len >= sizeof(data))
+      return false;
+    LIBC_NAMESPACE::inline_memcpy(data + idx, str, len);
+    idx += len;
+    data[idx] = '\0';
+    return true;
+  }
+};
+
+LIBC_INLINE void report_error(string_view msg) {
+  LIBC_NAMESPACE::syscall_impl<long>(SYS_write, 2, msg.data(), msg.size());
----------------
michaelrj-google wrote:

there's a syscall wrapper for `write` that you should use instead of the direct call here.

https://github.com/llvm/llvm-project/pull/213271


More information about the libc-commits mailing list