Skip to content

Commit 5120b39

Browse files
ADKasterawesomekling
authored andcommittedMay 1, 2022
Meta+Userland: Add ENABLE_USERSPACE_COVERAGE_COLLECTION CMake option
This option sets -fprofile-instr-generate -fcoverage-mapping for Clang builds only on almost all of Userland. Loader and LibTimeZone are exempt. This can be used for generating code coverage reports, or even PGO in the future.
1 parent a6b2c34 commit 5120b39

File tree

9 files changed

+39
-2
lines changed

9 files changed

+39
-2
lines changed
 

‎Documentation/AdvancedBuildInstructions.md

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ directory to `Build/i686` and then running `ninja <target>`:
4343
There are some optional features that can be enabled during compilation that are intended to help with specific types of development work or introduce experimental features. Currently, the following build options are available:
4444
- `ENABLE_ADDRESS_SANITIZER` and `ENABLE_KERNEL_ADDRESS_SANITIZER`: builds in runtime checks for memory corruption bugs (like buffer overflows and memory leaks) in Lagom test cases and the kernel, respectively.
4545
- `ENABLE_KERNEL_COVERAGE_COLLECTION`: enables the KCOV API and kernel coverage collection instrumentation. Only useful for coverage guided kernel fuzzing.
46+
- `ENABLE_USERSPACE_COVERAGE_COLLECTION`: enables coverage collection instrumentation for userspace. Currently only works with a Clang build.
4647
- `ENABLE_MEMORY_SANITIZER`: enables runtime checks for uninitialized memory accesses in Lagom test cases.
4748
- `ENABLE_UNDEFINED_SANITIZER`: builds in runtime checks for [undefined behavior](https://en.wikipedia.org/wiki/Undefined_behavior) (like null pointer dereferences and signed integer overflows) in Lagom test cases.
4849
- `ENABLE_COMPILER_EXPLORER_BUILD`: Skip building non-library entities in Lagom (this only applies to Lagom).

‎Meta/CMake/serenity_options.cmake

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ serenity_option(ENABLE_KERNEL_COVERAGE_COLLECTION OFF CACHE BOOL "Enable KCOV a
1212
serenity_option(ENABLE_KERNEL_LTO OFF CACHE BOOL "Build the kernel with link-time optimization")
1313
serenity_option(ENABLE_EXTRA_KERNEL_DEBUG_SYMBOLS OFF CACHE BOOL "Enable -Og and -ggdb3 options for Kernel code for easier debugging")
1414
serenity_option(ENABLE_MOLD_LINKER OFF CACHE BOOL "Link the SerenityOS userland with the mold linker")
15+
serenity_option(ENABLE_USERSPACE_COVERAGE_COLLECTION OFF CACHE BOOL "Enable code coverage instrumentation for userspace binaries in clang")

‎Meta/CMake/utils.cmake

+3
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ function(serenity_libc target_name fs_name)
7373
if (NOT ENABLE_MOLD_LINKER)
7474
target_link_options(${target_name} PRIVATE -Wl,--no-dependent-libraries)
7575
endif()
76+
if (ENABLE_USERSPACE_COVERAGE_COLLECTION)
77+
target_link_libraries(${target_name} clang_rt.profile)
78+
endif()
7679
endif()
7780
target_link_directories(LibC PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
7881
serenity_generated_sources(${target_name})

‎Userland/CMakeLists.txt

+16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
add_compile_options(-O2)
22

3+
# Escape hatch target to prevent runtime startup libraries from having coverage enabled
4+
# at awkward points in program initialization
5+
add_library(NoCoverage INTERFACE)
6+
7+
if (ENABLE_USERSPACE_COVERAGE_COLLECTION)
8+
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang$")
9+
add_compile_options(-fprofile-instr-generate -fcoverage-mapping)
10+
add_link_options(-fprofile-instr-generate -fcoverage-mapping)
11+
12+
target_compile_options(NoCoverage INTERFACE -fno-profile-generate -fno-profile-instr-use -fno-profile-instr-generate -fno-coverage-mapping)
13+
target_link_options(NoCoverage INTERFACE -fno-profile-generate -fno-profile-instr-use -fno-profile-instr-generate -fno-coverage-mapping)
14+
else()
15+
message(FATAL_ERROR "ENABLE_USERSPACE_COVERAGE_COLLECTION not supported yet for ${CMAKE_CXX_COMPILER_ID}")
16+
endif()
17+
endif()
18+
319
add_subdirectory(Applications)
420
add_subdirectory(Demos)
521
add_subdirectory(DevTools)

‎Userland/DynamicLoader/CMakeLists.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang$")
4444
target_link_libraries(Loader.so PRIVATE clang_rt.builtins)
4545
endif ()
4646

47-
target_link_libraries(Loader.so PRIVATE LibTimeZone)
47+
# Note: Don't confuse the coverage results by instrumenting Loader
48+
target_link_libraries(Loader.so PRIVATE LibTimeZone NoCoverage)
4849
target_link_options(Loader.so PRIVATE LINKER:--no-dynamic-linker)
4950
install(TARGETS Loader.so RUNTIME DESTINATION usr/lib/)

‎Userland/Libraries/LibC/CMakeLists.txt

+10-1
Original file line numberDiff line numberDiff line change
@@ -93,24 +93,32 @@ endif()
9393

9494
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-warning-option")
9595

96+
# Note: We link all these against NoCoverage so that we don't break ports by requiring coverage symbols
97+
# in runtime/startup objects.
98+
# Since all native serenity applications use dynamic libraries, prevent coverage on libc.a as well
99+
96100
add_library(crt0 STATIC crt0.cpp)
101+
target_link_libraries(crt0 PRIVATE NoCoverage)
97102
add_custom_command(
98103
TARGET crt0
99104
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_OBJECTS:crt0> ${CMAKE_INSTALL_PREFIX}/usr/lib/crt0.o
100105
)
101106
add_library(crt0_shared STATIC crt0_shared.cpp)
107+
target_link_libraries(crt0_shared PRIVATE NoCoverage)
102108
add_custom_command(
103109
TARGET crt0_shared
104110
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_OBJECTS:crt0_shared> ${CMAKE_INSTALL_PREFIX}/usr/lib/crt0_shared.o
105111
)
106112

107113
add_library(crti STATIC ${CRTI_SOURCE})
114+
target_link_libraries(crti PRIVATE NoCoverage)
108115
add_custom_command(
109116
TARGET crti
110117
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_OBJECTS:crti> ${CMAKE_INSTALL_PREFIX}/usr/lib/crti.o
111118
)
112119

113120
add_library(crtn STATIC ${CRTN_SOURCE})
121+
target_link_libraries(crtn PRIVATE NoCoverage)
114122
add_custom_command(
115123
TARGET crtn
116124
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_OBJECTS:crtn> ${CMAKE_INSTALL_PREFIX}/usr/lib/crtn.o
@@ -119,6 +127,7 @@ add_custom_command(
119127
set_source_files_properties (ssp.cpp PROPERTIES COMPILE_FLAGS
120128
"-fno-stack-protector")
121129
add_library(ssp STATIC ssp.cpp)
130+
target_link_libraries(ssp PRIVATE NoCoverage)
122131
add_custom_command(
123132
TARGET ssp
124133
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_OBJECTS:ssp> ${CMAKE_INSTALL_PREFIX}/usr/lib/ssp.o
@@ -131,7 +140,7 @@ set(SOURCES ${LIBC_SOURCES} ${AK_SOURCES} ${ELF_SOURCES} ${ASM_SOURCES})
131140
set_source_files_properties(stdio.cpp PROPERTIES COMPILE_FLAGS "-fno-builtin-fputc -fno-builtin-fputs -fno-builtin-fwrite")
132141

133142
add_library(LibCStaticWithoutDeps STATIC ${SOURCES})
134-
target_link_libraries(LibCStaticWithoutDeps ssp LibTimeZone)
143+
target_link_libraries(LibCStaticWithoutDeps PUBLIC ssp LibTimeZone PRIVATE NoCoverage)
135144
add_dependencies(LibCStaticWithoutDeps LibM LibSystem LibUBSanitizer)
136145

137146
add_custom_target(LibCStatic

‎Userland/Libraries/LibSanitizer/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib")
1010
serenity_libc(LibUBSanitizer ubsan)
1111

1212
add_library(LibUBSanitizerStatic STATIC ${SOURCES})
13+
target_link_libraries(LibUBSanitizerStatic PRIVATE NoCoverage)

‎Userland/Libraries/LibSystem/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ target_include_directories(LibSystem PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
88

99
add_library(LibSystemStatic STATIC ${SOURCES})
1010
target_include_directories(LibSystemStatic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
11+
target_link_libraries(LibSystemStatic PRIVATE NoCoverage)

‎Userland/Libraries/LibTimeZone/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@ set(SOURCES
77

88
add_library(LibTimeZone OBJECT ${SOURCES})
99
target_compile_definitions(LibTimeZone PRIVATE ENABLE_TIME_ZONE_DATA=$<BOOL:${ENABLE_TIME_ZONE_DATABASE_DOWNLOAD}>)
10+
11+
# NOTE: These objects are used by the DynamicLoader, which is always built without coverage instrumentation.
12+
# We could allow them to be instrumented for coverage if DynamicLoader built its own copy
13+
target_link_libraries(LibTimeZone PRIVATE NoCoverage)

0 commit comments

Comments
 (0)
Please sign in to comment.