[compiler-rt] bc0d0bb - [compiler-rt] Add baremetal version of profile library. (#167998)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 10 12:58:29 PST 2025
Author: Eli Friedman
Date: 2025-12-10T12:58:25-08:00
New Revision: bc0d0bbc6b36445730067b6e302f332fa1e3fa35
URL: https://github.com/llvm/llvm-project/commit/bc0d0bbc6b36445730067b6e302f332fa1e3fa35
DIFF: https://github.com/llvm/llvm-project/commit/bc0d0bbc6b36445730067b6e302f332fa1e3fa35.diff
LOG: [compiler-rt] Add baremetal version of profile library. (#167998)
Adds a flag COMPILER_RT_PROFILE_BAREMETAL, which disables the parts of
the profile runtime which require a filesystem or malloc. This minimal
library only requires string.h from the C library.
This is useful for profiling or code coverage of baremetal images, which
don't have filesystem APIs, and might not have malloc configured (or
have limited heap space).
Expected usage:
- Add code to your project to call
`__llvm_profile_get_size_for_buffer()` and
`__llvm_profile_write_buffer()` to write the profile data to a buffer in
memory, and then copy that data off the device using target-specific
tools.
- If you're using a linker script, set up your linker script to map the
profiling and coverage input sections to corresponding output sections
with the same name, and mark them KEEP. `__llvm_covfun` and
`__llvm_covmap` are non-allocatable, `__llvm_prf_names` is read-only
allocatable, and `__llvm_prf_cnts` and `__llvm_prf_data` are read-write
allocatable.
- The resulting data is in same format as the non-baremetal profiles.
There's some room for improvement here in the future for doing profiling
and code coverage for baremetal. If we revised the profiling format, and
introduced some additional host tooling, we could move some of the
metadata into non-allocated sections, and construct the profraw file on
the host. But this patch is sufficient for some use-cases.
Added:
Modified:
compiler-rt/CMakeLists.txt
compiler-rt/cmake/config-ix.cmake
compiler-rt/lib/profile/CMakeLists.txt
compiler-rt/lib/profile/InstrProfiling.c
compiler-rt/lib/profile/InstrProfiling.h
compiler-rt/lib/profile/InstrProfilingMerge.c
compiler-rt/lib/profile/InstrProfilingMergeFile.c
compiler-rt/lib/profile/InstrProfilingPlatformLinux.c
compiler-rt/lib/profile/InstrProfilingPlatformOther.c
compiler-rt/lib/profile/InstrProfilingPort.h
Removed:
################################################################################
diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt
index 58ea75c42d14e..a92258ae12446 100644
--- a/compiler-rt/CMakeLists.txt
+++ b/compiler-rt/CMakeLists.txt
@@ -312,6 +312,8 @@ option(COMPILER_RT_USE_BUILTINS_LIBRARY
option(COMPILER_RT_USE_ATOMIC_LIBRARY "Use compiler-rt atomic instead of libatomic" OFF)
+option(COMPILER_RT_PROFILE_BAREMETAL "Build minimal baremetal profile library" OFF)
+
include(config-ix)
#================================
diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake
index 084a7060e8d13..1f82ff3cf7531 100644
--- a/compiler-rt/cmake/config-ix.cmake
+++ b/compiler-rt/cmake/config-ix.cmake
@@ -842,7 +842,7 @@ else()
endif()
if (PROFILE_SUPPORTED_ARCH AND NOT LLVM_USE_SANITIZER AND
- OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS|NetBSD|AIX|WASI|Haiku")
+ (OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS|NetBSD|AIX|WASI|Haiku" OR COMPILER_RT_PROFILE_BAREMETAL))
set(COMPILER_RT_HAS_PROFILE TRUE)
else()
set(COMPILER_RT_HAS_PROFILE FALSE)
diff --git a/compiler-rt/lib/profile/CMakeLists.txt b/compiler-rt/lib/profile/CMakeLists.txt
index a6402f80b890a..7c8473cc5f200 100644
--- a/compiler-rt/lib/profile/CMakeLists.txt
+++ b/compiler-rt/lib/profile/CMakeLists.txt
@@ -60,12 +60,9 @@ int main() {
add_compiler_rt_component(profile)
set(PROFILE_SOURCES
- GCDAProfiling.c
InstrProfiling.c
InstrProfilingInternal.c
- InstrProfilingValue.c
InstrProfilingBuffer.c
- InstrProfilingFile.c
InstrProfilingMerge.c
InstrProfilingMergeFile.c
InstrProfilingNameVar.c
@@ -77,10 +74,26 @@ set(PROFILE_SOURCES
InstrProfilingPlatformLinux.c
InstrProfilingPlatformOther.c
InstrProfilingPlatformWindows.c
- InstrProfilingRuntime.cpp
- InstrProfilingUtil.c
)
+if (NOT COMPILER_RT_PROFILE_BAREMETAL)
+ # For baremetal, exclude the following:
+ # - Anything that contains filesystem operations (InstrProfilingFile.c,
+ # InstrProfilingUtils.c)
+ # - Initialization, because it isn't necesary without the filesystem bits
+ # on ELF targets (InstrProfilingRuntime.cpp).
+ # - Value profiling, because it requires malloc (InstrProfilingValue.c).
+ # This could be optional if someone needs it.
+ # - GCDA profiling, which is unrelated (GCDAProfiling.c)
+ list(APPEND PROFILE_SOURCES
+ GCDAProfiling.c
+ InstrProfilingFile.c
+ InstrProfilingRuntime.cpp
+ InstrProfilingUtil.c
+ InstrProfilingValue.c
+ )
+endif()
+
set(PROFILE_HEADERS
InstrProfiling.h
InstrProfilingInternal.h
@@ -135,6 +148,12 @@ if(COMPILER_RT_TARGET_HAS_UNAME)
-DCOMPILER_RT_HAS_UNAME=1)
endif()
+if(COMPILER_RT_PROFILE_BAREMETAL)
+ set(EXTRA_FLAGS
+ ${EXTRA_FLAGS}
+ -DCOMPILER_RT_PROFILE_BAREMETAL=1)
+endif()
+
if(MSVC)
# profile historically has only been supported with the static runtime
# on windows
diff --git a/compiler-rt/lib/profile/InstrProfiling.c b/compiler-rt/lib/profile/InstrProfiling.c
index da04d8ebdec95..d59ec78ad3296 100644
--- a/compiler-rt/lib/profile/InstrProfiling.c
+++ b/compiler-rt/lib/profile/InstrProfiling.c
@@ -10,8 +10,6 @@
// with freestanding compilation. See `darwin_add_builtin_libraries`.
#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
#include "InstrProfiling.h"
diff --git a/compiler-rt/lib/profile/InstrProfiling.h b/compiler-rt/lib/profile/InstrProfiling.h
index 8791d5aa5dd70..187ef55ef3784 100644
--- a/compiler-rt/lib/profile/InstrProfiling.h
+++ b/compiler-rt/lib/profile/InstrProfiling.h
@@ -10,7 +10,10 @@
#define PROFILE_INSTRPROFILING_H_
#include "InstrProfilingPort.h"
+#include <stddef.h>
+#ifndef COMPILER_RT_PROFILE_BAREMETAL
#include <stdio.h>
+#endif
// Make sure __LLVM_INSTR_PROFILE_GENERATE is always defined before
// including instr_prof_interface.h so the interface functions are
@@ -200,7 +203,9 @@ int __llvm_profile_write_file(void);
* copying the old profile file to new profile file and this function is usually
* used when the proess doesn't have permission to open file.
*/
+#ifndef COMPILER_RT_PROFILE_BAREMETAL
int __llvm_profile_set_file_object(FILE *File, int EnableMerge);
+#endif
/*! \brief Register to write instrumentation data to file at exit. */
int __llvm_profile_register_write_file_atexit(void);
diff --git a/compiler-rt/lib/profile/InstrProfilingMerge.c b/compiler-rt/lib/profile/InstrProfilingMerge.c
index 92721c4fd55ea..681abda0188ac 100644
--- a/compiler-rt/lib/profile/InstrProfilingMerge.c
+++ b/compiler-rt/lib/profile/InstrProfilingMerge.c
@@ -11,7 +11,6 @@
#include "InstrProfiling.h"
#include "InstrProfilingInternal.h"
-#include "InstrProfilingUtil.h"
#define INSTR_PROF_VALUE_PROF_DATA
#include "profile/InstrProfData.inc"
diff --git a/compiler-rt/lib/profile/InstrProfilingMergeFile.c b/compiler-rt/lib/profile/InstrProfilingMergeFile.c
index 8923ba21cc580..d8fe1f6677950 100644
--- a/compiler-rt/lib/profile/InstrProfilingMergeFile.c
+++ b/compiler-rt/lib/profile/InstrProfilingMergeFile.c
@@ -13,7 +13,6 @@
#include "InstrProfiling.h"
#include "InstrProfilingInternal.h"
-#include "InstrProfilingUtil.h"
#define INSTR_PROF_VALUE_PROF_DATA
#include "profile/InstrProfData.inc"
diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c
index 558b7fc8cad62..acdb222004fd4 100644
--- a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c
+++ b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c
@@ -6,16 +6,33 @@
|*
\*===----------------------------------------------------------------------===*/
+// This file defines profile data symbols for ELF, wasm, XCOFF. It assumes
+// __start_ and __stop_ symbols for profile data point at the beginning and
+// end of the sections in question. (This is technically a linker feature,
+// not a file format feature, but linkers for these targets support it.)
+//
+// MachO (MacOS/iOS) and PE-COFF (Windows) have a similar support, but the
+// identifiers are
diff erent, so the support is in separate files.
+//
+// Support for targets which don't have linker support is in
+// InstrProfilingPlatformOther.c.
+//
+// This file also contains code to extract ELF build IDs from the ELF file,
+// to identify the build which generated the file.
+
#if defined(__linux__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
(defined(__sun__) && defined(__svr4__)) || defined(__NetBSD__) || \
- defined(_AIX) || defined(__wasm__) || defined(__HAIKU__)
+ defined(_AIX) || defined(__wasm__) || defined(__HAIKU__) || \
+ defined(COMPILER_RT_PROFILE_BAREMETAL)
-#if !defined(_AIX) && !defined(__wasm__)
+#if !defined(_AIX) && !defined(__wasm__) && \
+ !defined(COMPILER_RT_PROFILE_BAREMETAL)
+// Includes for non-baremetal ELF targets, used to output build IDs.
#include <elf.h>
#include <link.h>
-#endif
#include <stdlib.h>
#include <string.h>
+#endif
#include "InstrProfiling.h"
#include "InstrProfilingInternal.h"
diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformOther.c b/compiler-rt/lib/profile/InstrProfilingPlatformOther.c
index 19414ab78b3be..f5d1c74f10115 100644
--- a/compiler-rt/lib/profile/InstrProfilingPlatformOther.c
+++ b/compiler-rt/lib/profile/InstrProfilingPlatformOther.c
@@ -6,10 +6,18 @@
|*
\*===----------------------------------------------------------------------===*/
+// This file defines a fallback implementation to compute the locations of
+// profile data sections, for targets that don't have linker support. No
+// commonly used targets use this codepath.
+//
+// This implementation expects the compiler instrumentation pass to define a
+// constructor in each file which calls into this file.
+
#if !defined(__APPLE__) && !defined(__linux__) && !defined(__FreeBSD__) && \
!defined(__Fuchsia__) && !(defined(__sun__) && defined(__svr4__)) && \
!defined(__NetBSD__) && !defined(_WIN32) && !defined(_AIX) && \
- !defined(__wasm__) && !defined(__HAIKU__)
+ !defined(__wasm__) && !defined(__HAIKU__) && \
+ !defined(COMPILER_RT_PROFILE_BAREMETAL)
#include <stdlib.h>
#include <stdio.h>
diff --git a/compiler-rt/lib/profile/InstrProfilingPort.h b/compiler-rt/lib/profile/InstrProfilingPort.h
index 66d697885eaee..0149c7aacb2da 100644
--- a/compiler-rt/lib/profile/InstrProfilingPort.h
+++ b/compiler-rt/lib/profile/InstrProfilingPort.h
@@ -117,9 +117,17 @@ static inline size_t getpagesize(void) {
return S.dwPageSize;
}
#else /* defined(_WIN32) */
+#ifndef COMPILER_RT_PROFILE_BAREMETAL
#include <unistd.h>
+#endif
#endif /* defined(_WIN32) */
+#ifdef COMPILER_RT_PROFILE_BAREMETAL
+// Baremetal doesn't support logging
+#define PROF_ERR(Format, ...)
+#define PROF_WARN(Format, ...)
+#define PROF_NOTE(Format, ...)
+#else
#define PROF_ERR(Format, ...) \
fprintf(stderr, "LLVM Profile Error: " Format, __VA_ARGS__);
@@ -128,6 +136,7 @@ static inline size_t getpagesize(void) {
#define PROF_NOTE(Format, ...) \
fprintf(stderr, "LLVM Profile Note: " Format, __VA_ARGS__);
+#endif /* COMPILER_RT_PROFILE_BAREMETAL */
#ifndef MAP_FILE
#define MAP_FILE 0
@@ -137,16 +146,6 @@ static inline size_t getpagesize(void) {
#define O_BINARY 0
#endif
-#if defined(__FreeBSD__)
-
-#include <inttypes.h>
-#include <sys/types.h>
-
-#else /* defined(__FreeBSD__) */
-
-#include <inttypes.h>
#include <stdint.h>
-#endif /* defined(__FreeBSD__) && defined(__i386__) */
-
#endif /* PROFILE_INSTRPROFILING_PORT_H_ */
More information about the llvm-commits
mailing list