Skip to content

Commit bc0d0bb

Browse files
[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.
1 parent 04dcb1b commit bc0d0bb

File tree

10 files changed

+70
-24
lines changed

10 files changed

+70
-24
lines changed

compiler-rt/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,8 @@ option(COMPILER_RT_USE_BUILTINS_LIBRARY
312312

313313
option(COMPILER_RT_USE_ATOMIC_LIBRARY "Use compiler-rt atomic instead of libatomic" OFF)
314314

315+
option(COMPILER_RT_PROFILE_BAREMETAL "Build minimal baremetal profile library" OFF)
316+
315317
include(config-ix)
316318

317319
#================================

compiler-rt/cmake/config-ix.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ else()
842842
endif()
843843

844844
if (PROFILE_SUPPORTED_ARCH AND NOT LLVM_USE_SANITIZER AND
845-
OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS|NetBSD|AIX|WASI|Haiku")
845+
(OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS|NetBSD|AIX|WASI|Haiku" OR COMPILER_RT_PROFILE_BAREMETAL))
846846
set(COMPILER_RT_HAS_PROFILE TRUE)
847847
else()
848848
set(COMPILER_RT_HAS_PROFILE FALSE)

compiler-rt/lib/profile/CMakeLists.txt

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,9 @@ int main() {
6060
add_compiler_rt_component(profile)
6161

6262
set(PROFILE_SOURCES
63-
GCDAProfiling.c
6463
InstrProfiling.c
6564
InstrProfilingInternal.c
66-
InstrProfilingValue.c
6765
InstrProfilingBuffer.c
68-
InstrProfilingFile.c
6966
InstrProfilingMerge.c
7067
InstrProfilingMergeFile.c
7168
InstrProfilingNameVar.c
@@ -77,10 +74,26 @@ set(PROFILE_SOURCES
7774
InstrProfilingPlatformLinux.c
7875
InstrProfilingPlatformOther.c
7976
InstrProfilingPlatformWindows.c
80-
InstrProfilingRuntime.cpp
81-
InstrProfilingUtil.c
8277
)
8378

79+
if (NOT COMPILER_RT_PROFILE_BAREMETAL)
80+
# For baremetal, exclude the following:
81+
# - Anything that contains filesystem operations (InstrProfilingFile.c,
82+
# InstrProfilingUtils.c)
83+
# - Initialization, because it isn't necesary without the filesystem bits
84+
# on ELF targets (InstrProfilingRuntime.cpp).
85+
# - Value profiling, because it requires malloc (InstrProfilingValue.c).
86+
# This could be optional if someone needs it.
87+
# - GCDA profiling, which is unrelated (GCDAProfiling.c)
88+
list(APPEND PROFILE_SOURCES
89+
GCDAProfiling.c
90+
InstrProfilingFile.c
91+
InstrProfilingRuntime.cpp
92+
InstrProfilingUtil.c
93+
InstrProfilingValue.c
94+
)
95+
endif()
96+
8497
set(PROFILE_HEADERS
8598
InstrProfiling.h
8699
InstrProfilingInternal.h
@@ -135,6 +148,12 @@ if(COMPILER_RT_TARGET_HAS_UNAME)
135148
-DCOMPILER_RT_HAS_UNAME=1)
136149
endif()
137150

151+
if(COMPILER_RT_PROFILE_BAREMETAL)
152+
set(EXTRA_FLAGS
153+
${EXTRA_FLAGS}
154+
-DCOMPILER_RT_PROFILE_BAREMETAL=1)
155+
endif()
156+
138157
if(MSVC)
139158
# profile historically has only been supported with the static runtime
140159
# on windows

compiler-rt/lib/profile/InstrProfiling.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
// with freestanding compilation. See `darwin_add_builtin_libraries`.
1111

1212
#include <limits.h>
13-
#include <stdio.h>
14-
#include <stdlib.h>
1513
#include <string.h>
1614

1715
#include "InstrProfiling.h"

compiler-rt/lib/profile/InstrProfiling.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010
#define PROFILE_INSTRPROFILING_H_
1111

1212
#include "InstrProfilingPort.h"
13+
#include <stddef.h>
14+
#ifndef COMPILER_RT_PROFILE_BAREMETAL
1315
#include <stdio.h>
16+
#endif
1417

1518
// Make sure __LLVM_INSTR_PROFILE_GENERATE is always defined before
1619
// including instr_prof_interface.h so the interface functions are
@@ -200,7 +203,9 @@ int __llvm_profile_write_file(void);
200203
* copying the old profile file to new profile file and this function is usually
201204
* used when the proess doesn't have permission to open file.
202205
*/
206+
#ifndef COMPILER_RT_PROFILE_BAREMETAL
203207
int __llvm_profile_set_file_object(FILE *File, int EnableMerge);
208+
#endif
204209

205210
/*! \brief Register to write instrumentation data to file at exit. */
206211
int __llvm_profile_register_write_file_atexit(void);

compiler-rt/lib/profile/InstrProfilingMerge.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
#include "InstrProfiling.h"
1313
#include "InstrProfilingInternal.h"
14-
#include "InstrProfilingUtil.h"
1514

1615
#define INSTR_PROF_VALUE_PROF_DATA
1716
#include "profile/InstrProfData.inc"

compiler-rt/lib/profile/InstrProfilingMergeFile.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
#include "InstrProfiling.h"
1515
#include "InstrProfilingInternal.h"
16-
#include "InstrProfilingUtil.h"
1716

1817
#define INSTR_PROF_VALUE_PROF_DATA
1918
#include "profile/InstrProfData.inc"

compiler-rt/lib/profile/InstrProfilingPlatformLinux.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,33 @@
66
|*
77
\*===----------------------------------------------------------------------===*/
88

9+
// This file defines profile data symbols for ELF, wasm, XCOFF. It assumes
10+
// __start_ and __stop_ symbols for profile data point at the beginning and
11+
// end of the sections in question. (This is technically a linker feature,
12+
// not a file format feature, but linkers for these targets support it.)
13+
//
14+
// MachO (MacOS/iOS) and PE-COFF (Windows) have a similar support, but the
15+
// identifiers are different, so the support is in separate files.
16+
//
17+
// Support for targets which don't have linker support is in
18+
// InstrProfilingPlatformOther.c.
19+
//
20+
// This file also contains code to extract ELF build IDs from the ELF file,
21+
// to identify the build which generated the file.
22+
923
#if defined(__linux__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
1024
(defined(__sun__) && defined(__svr4__)) || defined(__NetBSD__) || \
11-
defined(_AIX) || defined(__wasm__) || defined(__HAIKU__)
25+
defined(_AIX) || defined(__wasm__) || defined(__HAIKU__) || \
26+
defined(COMPILER_RT_PROFILE_BAREMETAL)
1227

13-
#if !defined(_AIX) && !defined(__wasm__)
28+
#if !defined(_AIX) && !defined(__wasm__) && \
29+
!defined(COMPILER_RT_PROFILE_BAREMETAL)
30+
// Includes for non-baremetal ELF targets, used to output build IDs.
1431
#include <elf.h>
1532
#include <link.h>
16-
#endif
1733
#include <stdlib.h>
1834
#include <string.h>
35+
#endif
1936

2037
#include "InstrProfiling.h"
2138
#include "InstrProfilingInternal.h"

compiler-rt/lib/profile/InstrProfilingPlatformOther.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,18 @@
66
|*
77
\*===----------------------------------------------------------------------===*/
88

9+
// This file defines a fallback implementation to compute the locations of
10+
// profile data sections, for targets that don't have linker support. No
11+
// commonly used targets use this codepath.
12+
//
13+
// This implementation expects the compiler instrumentation pass to define a
14+
// constructor in each file which calls into this file.
15+
916
#if !defined(__APPLE__) && !defined(__linux__) && !defined(__FreeBSD__) && \
1017
!defined(__Fuchsia__) && !(defined(__sun__) && defined(__svr4__)) && \
1118
!defined(__NetBSD__) && !defined(_WIN32) && !defined(_AIX) && \
12-
!defined(__wasm__) && !defined(__HAIKU__)
19+
!defined(__wasm__) && !defined(__HAIKU__) && \
20+
!defined(COMPILER_RT_PROFILE_BAREMETAL)
1321

1422
#include <stdlib.h>
1523
#include <stdio.h>

compiler-rt/lib/profile/InstrProfilingPort.h

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,17 @@ static inline size_t getpagesize(void) {
117117
return S.dwPageSize;
118118
}
119119
#else /* defined(_WIN32) */
120+
#ifndef COMPILER_RT_PROFILE_BAREMETAL
120121
#include <unistd.h>
122+
#endif
121123
#endif /* defined(_WIN32) */
122124

125+
#ifdef COMPILER_RT_PROFILE_BAREMETAL
126+
// Baremetal doesn't support logging
127+
#define PROF_ERR(Format, ...)
128+
#define PROF_WARN(Format, ...)
129+
#define PROF_NOTE(Format, ...)
130+
#else
123131
#define PROF_ERR(Format, ...) \
124132
fprintf(stderr, "LLVM Profile Error: " Format, __VA_ARGS__);
125133

@@ -128,6 +136,7 @@ static inline size_t getpagesize(void) {
128136

129137
#define PROF_NOTE(Format, ...) \
130138
fprintf(stderr, "LLVM Profile Note: " Format, __VA_ARGS__);
139+
#endif /* COMPILER_RT_PROFILE_BAREMETAL */
131140

132141
#ifndef MAP_FILE
133142
#define MAP_FILE 0
@@ -137,16 +146,6 @@ static inline size_t getpagesize(void) {
137146
#define O_BINARY 0
138147
#endif
139148

140-
#if defined(__FreeBSD__)
141-
142-
#include <inttypes.h>
143-
#include <sys/types.h>
144-
145-
#else /* defined(__FreeBSD__) */
146-
147-
#include <inttypes.h>
148149
#include <stdint.h>
149150

150-
#endif /* defined(__FreeBSD__) && defined(__i386__) */
151-
152151
#endif /* PROFILE_INSTRPROFILING_PORT_H_ */

0 commit comments

Comments
 (0)