Skip to content

[DRAFT][memprof][darwin] Support memprof on Darwin platform and add binary access profile #142884

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/lib/Driver/ToolChains/Darwin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1619,6 +1619,8 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
AddLinkRuntimeLib(Args, CmdArgs, "stats_client", RLO_AlwaysLink);
AddLinkSanitizerLibArgs(Args, CmdArgs, "stats");
}
if (Sanitize.needsMemProfRt())
AddLinkSanitizerLibArgs(Args, CmdArgs, "memprof");
}

if (Sanitize.needsMemProfRt())
Expand Down
11 changes: 11 additions & 0 deletions clang/test/Driver/fmemprof-darwin.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

// Test sanitizer link flags on Darwin.

// RUN: %clang -### --target=x86_64-darwin \
// RUN: -stdlib=platform -fmemory-profile %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MEMPROF %s

// CHECK-MEMPROF: "{{.*}}ld{{(.exe)?}}"
// CHECK-MEMPROF-SAME: libclang_rt.memprof_osx_dynamic.dylib"
// CHECK-MEMPROF-SAME: "-rpath" "@executable_path"
// CHECK-MEMPROF-SAME: "-rpath" "{{[^"]*}}lib{{[^"]*}}darwin"
2 changes: 1 addition & 1 deletion compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ else()
endif()
set(ALL_NSAN_SUPPORTED_ARCH ${X86_64})
set(ALL_HWASAN_SUPPORTED_ARCH ${X86_64} ${ARM64} ${RISCV64})
set(ALL_MEMPROF_SUPPORTED_ARCH ${X86_64})
set(ALL_MEMPROF_SUPPORTED_ARCH ${X86_64} ${ARM64})
set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64}
${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}
${RISCV32} ${RISCV64} ${LOONGARCH64} ${WASM32})
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/cmake/config-ix.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,7 @@ else()
endif()

if (COMPILER_RT_HAS_SANITIZER_COMMON AND MEMPROF_SUPPORTED_ARCH AND
OS_NAME MATCHES "Linux")
OS_NAME MATCHES "Linux|Darwin")
set(COMPILER_RT_HAS_MEMPROF TRUE)
else()
set(COMPILER_RT_HAS_MEMPROF FALSE)
Expand Down
41 changes: 41 additions & 0 deletions compiler-rt/include/profile/MemProfBinaryAccessData.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*===-- MemProfBinaryAccessData.inc - MemProf profiling runtime macros -*- C++
-*-======== *\
|*
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|* See https://llvm.org/LICENSE.txt for license information.
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|*
\*===----------------------------------------------------------------------===*/
/*
* This file defines the macros for memprof profiling data structures
* for binary access.
*
* This file has two identical copies. The primary copy lives in LLVM and
* the other one sits in compiler-rt/include/profile directory. To make changes
* in this file, first modify the primary copy and copy it over to compiler-rt.
* Testing of any change in this file can start only after the two copies are
* synced up.
*
\*===----------------------------------------------------------------------===*/

// A 64-bit magic number to uniquely identify the raw binary memprof binary
// access profile file.
#define MEMPROF_BINARY_ACCESS_RAW_MAGIC_64 \
((uint64_t)255 << 56 | (uint64_t)'f' << 48 | (uint64_t)'b' << 40 | \
(uint64_t)'m' << 32 | (uint64_t)'b' << 24 | (uint64_t)'i' << 16 | \
(uint64_t)'n' << 8 | (uint64_t)129)

// The version number of the raw binary format.
#define MEMPROF_BINARY_ACCESS_RAW_VERSION 1ULL

// A struct describing the header used for the raw binary memprof profile
// format.
PACKED(struct BinaryAccessHeader {
uint64_t Magic;
uint64_t Version;
uint64_t TotalSize;
uint64_t SegmentOffset;
uint64_t NumSegments;
uint64_t MemAddressOffset;
uint64_t NumMemBlockAddresses;
});
2 changes: 2 additions & 0 deletions compiler-rt/include/profile/MemProfData.inc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@

namespace llvm {
namespace memprof {
#include "MemProfBinaryAccessData.inc"

// A struct describing the header used for the raw binary memprof profile format.
PACKED(struct Header {
uint64_t Magic;
Expand Down
237 changes: 130 additions & 107 deletions compiler-rt/lib/memprof/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ set(MEMPROF_SOURCES
memprof_interceptors.cpp
memprof_interceptors_memintrinsics.cpp
memprof_linux.cpp
memprof_mac.cpp
memprof_malloc_linux.cpp
memprof_malloc_mac.cpp
memprof_mibmap.cpp
memprof_posix.cpp
memprof_rawprofile.cpp
Expand Down Expand Up @@ -86,124 +88,145 @@ add_compiler_rt_object_libraries(RTMemprof_dynamic
DEFS ${MEMPROF_DYNAMIC_DEFINITIONS}
DEPS ${MEMPROF_DEPS})

add_compiler_rt_object_libraries(RTMemprof
ARCHS ${MEMPROF_SUPPORTED_ARCH}
SOURCES ${MEMPROF_SOURCES}
ADDITIONAL_HEADERS ${MEMPROF_HEADERS}
CFLAGS ${MEMPROF_CFLAGS}
DEFS ${MEMPROF_COMMON_DEFINITIONS}
DEPS ${MEMPROF_DEPS})
add_compiler_rt_object_libraries(RTMemprof_cxx
ARCHS ${MEMPROF_SUPPORTED_ARCH}
SOURCES ${MEMPROF_CXX_SOURCES}
ADDITIONAL_HEADERS ${MEMPROF_HEADERS}
CFLAGS ${MEMPROF_CFLAGS}
DEFS ${MEMPROF_COMMON_DEFINITIONS}
DEPS ${MEMPROF_DEPS})
add_compiler_rt_object_libraries(RTMemprof_preinit
ARCHS ${MEMPROF_SUPPORTED_ARCH}
SOURCES ${MEMPROF_PREINIT_SOURCES}
ADDITIONAL_HEADERS ${MEMPROF_HEADERS}
CFLAGS ${MEMPROF_CFLAGS}
DEFS ${MEMPROF_COMMON_DEFINITIONS}
DEPS ${MEMPROF_DEPS})

file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp "")
add_compiler_rt_object_libraries(RTMemprof_dynamic_version_script_dummy
ARCHS ${MEMPROF_SUPPORTED_ARCH}
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp
CFLAGS ${MEMPROF_DYNAMIC_CFLAGS}
DEFS ${MEMPROF_DYNAMIC_DEFINITIONS}
DEPS ${MEMPROF_DEPS})
if(NOT APPLE)
add_compiler_rt_object_libraries(RTMemprof
ARCHS ${MEMPROF_SUPPORTED_ARCH}
SOURCES ${MEMPROF_SOURCES}
ADDITIONAL_HEADERS ${MEMPROF_HEADERS}
CFLAGS ${MEMPROF_CFLAGS}
DEFS ${MEMPROF_COMMON_DEFINITIONS}
DEPS ${MEMPROF_DEPS})
add_compiler_rt_object_libraries(RTMemprof_cxx
ARCHS ${MEMPROF_SUPPORTED_ARCH}
SOURCES ${MEMPROF_CXX_SOURCES}
ADDITIONAL_HEADERS ${MEMPROF_HEADERS}
CFLAGS ${MEMPROF_CFLAGS}
DEFS ${MEMPROF_COMMON_DEFINITIONS}
DEPS ${MEMPROF_DEPS})
add_compiler_rt_object_libraries(RTMemprof_preinit
ARCHS ${MEMPROF_SUPPORTED_ARCH}
SOURCES ${MEMPROF_PREINIT_SOURCES}
ADDITIONAL_HEADERS ${MEMPROF_HEADERS}
CFLAGS ${MEMPROF_CFLAGS}
DEFS ${MEMPROF_COMMON_DEFINITIONS}
DEPS ${MEMPROF_DEPS})

file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp "")
add_compiler_rt_object_libraries(RTMemprof_dynamic_version_script_dummy
ARCHS ${MEMPROF_SUPPORTED_ARCH}
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp
CFLAGS ${MEMPROF_DYNAMIC_CFLAGS}
DEFS ${MEMPROF_DYNAMIC_DEFINITIONS}
DEPS ${MEMPROF_DEPS})
endif()

# Build MemProf runtimes shipped with Clang.
add_compiler_rt_component(memprof)

# Build separate libraries for each target.

set(MEMPROF_COMMON_RUNTIME_OBJECT_LIBS
RTInterception
RTSanitizerCommon
RTSanitizerCommonLibc
RTSanitizerCommonCoverage
RTSanitizerCommonSymbolizer
# FIXME: hangs.
# RTSanitizerCommonSymbolizerInternal
)

add_compiler_rt_runtime(clang_rt.memprof
STATIC
ARCHS ${MEMPROF_SUPPORTED_ARCH}
OBJECT_LIBS RTMemprof_preinit
RTMemprof
${MEMPROF_COMMON_RUNTIME_OBJECT_LIBS}
CFLAGS ${MEMPROF_CFLAGS}
DEFS ${MEMPROF_COMMON_DEFINITIONS}
PARENT_TARGET memprof)

add_compiler_rt_runtime(clang_rt.memprof_cxx
STATIC
ARCHS ${MEMPROF_SUPPORTED_ARCH}
OBJECT_LIBS RTMemprof_cxx
CFLAGS ${MEMPROF_CFLAGS}
DEFS ${MEMPROF_COMMON_DEFINITIONS}
PARENT_TARGET memprof)

add_compiler_rt_runtime(clang_rt.memprof-preinit
STATIC
ARCHS ${MEMPROF_SUPPORTED_ARCH}
OBJECT_LIBS RTMemprof_preinit
CFLAGS ${MEMPROF_CFLAGS}
DEFS ${MEMPROF_COMMON_DEFINITIONS}
PARENT_TARGET memprof)

foreach(arch ${MEMPROF_SUPPORTED_ARCH})
if (UNIX)
add_sanitizer_rt_version_list(clang_rt.memprof-dynamic-${arch}
LIBS clang_rt.memprof-${arch} clang_rt.memprof_cxx-${arch}
EXTRA memprof.syms.extra)
set(VERSION_SCRIPT_FLAG
-Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/clang_rt.memprof-dynamic-${arch}.vers)
set_property(SOURCE
${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp
APPEND PROPERTY
OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/clang_rt.memprof-dynamic-${arch}.vers)
else()
set(VERSION_SCRIPT_FLAG)
endif()

set(MEMPROF_DYNAMIC_WEAK_INTERCEPTION)

if(APPLE)
# following asan
add_weak_symbols("memprof" WEAK_SYMBOL_LINK_FLAGS)
add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINK_FLAGS)
add_compiler_rt_runtime(clang_rt.memprof
SHARED
ARCHS ${arch}
OBJECT_LIBS ${MEMPROF_COMMON_RUNTIME_OBJECT_LIBS}
RTMemprof_dynamic
# The only purpose of RTMemprof_dynamic_version_script_dummy is to
# carry a dependency of the shared runtime on the version script.
# Replacing it with a straightforward
# add_dependencies(clang_rt.memprof-dynamic-${arch} clang_rt.memprof-dynamic-${arch}-version-list)
# generates an order-only dependency in ninja.
RTMemprof_dynamic_version_script_dummy
${MEMPROF_DYNAMIC_WEAK_INTERCEPTION}
OS ${SANITIZER_COMMON_SUPPORTED_OS}
ARCHS ${MEMPROF_SUPPORTED_ARCH}
OBJECT_LIBS RTMemprof_dynamic
RTInterception
RTSanitizerCommon
RTSanitizerCommonLibc
RTSanitizerCommonCoverage
RTSanitizerCommonSymbolizer
CFLAGS ${MEMPROF_DYNAMIC_CFLAGS}
LINK_FLAGS ${MEMPROF_DYNAMIC_LINK_FLAGS}
${VERSION_SCRIPT_FLAG}
LINK_LIBS ${MEMPROF_DYNAMIC_LIBS}
LINK_FLAGS ${WEAK_SYMBOL_LINK_FLAGS}
DEFS ${MEMPROF_DYNAMIC_DEFINITIONS}
PARENT_TARGET memprof)
else()
# Build separate libraries for each target.

set(MEMPROF_COMMON_RUNTIME_OBJECT_LIBS
RTInterception
RTSanitizerCommon
RTSanitizerCommonLibc
RTSanitizerCommonCoverage
RTSanitizerCommonSymbolizer
# FIXME: hangs.
# RTSanitizerCommonSymbolizerInternal
)

if (SANITIZER_USE_SYMBOLS)
add_sanitizer_rt_symbols(clang_rt.memprof_cxx
ARCHS ${arch})
add_dependencies(memprof clang_rt.memprof_cxx-${arch}-symbols)
add_sanitizer_rt_symbols(clang_rt.memprof
ARCHS ${arch}
EXTRA memprof.syms.extra)
add_dependencies(memprof clang_rt.memprof-${arch}-symbols)
endif()
endforeach()
add_compiler_rt_runtime(clang_rt.memprof
STATIC
ARCHS ${MEMPROF_SUPPORTED_ARCH}
OBJECT_LIBS RTMemprof_preinit
RTMemprof
${MEMPROF_COMMON_RUNTIME_OBJECT_LIBS}
CFLAGS ${MEMPROF_CFLAGS}
DEFS ${MEMPROF_COMMON_DEFINITIONS}
PARENT_TARGET memprof)

add_compiler_rt_runtime(clang_rt.memprof_cxx
STATIC
ARCHS ${MEMPROF_SUPPORTED_ARCH}
OBJECT_LIBS RTMemprof_cxx
CFLAGS ${MEMPROF_CFLAGS}
DEFS ${MEMPROF_COMMON_DEFINITIONS}
PARENT_TARGET memprof)

add_compiler_rt_runtime(clang_rt.memprof-preinit
STATIC
ARCHS ${MEMPROF_SUPPORTED_ARCH}
OBJECT_LIBS RTMemprof_preinit
CFLAGS ${MEMPROF_CFLAGS}
DEFS ${MEMPROF_COMMON_DEFINITIONS}
PARENT_TARGET memprof)

foreach(arch ${MEMPROF_SUPPORTED_ARCH})
if (UNIX)
add_sanitizer_rt_version_list(clang_rt.memprof-dynamic-${arch}
LIBS clang_rt.memprof-${arch} clang_rt.memprof_cxx-${arch}
EXTRA memprof.syms.extra)
set(VERSION_SCRIPT_FLAG
-Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/clang_rt.memprof-dynamic-${arch}.vers)
set_property(SOURCE
${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp
APPEND PROPERTY
OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/clang_rt.memprof-dynamic-${arch}.vers)
else()
set(VERSION_SCRIPT_FLAG)
endif()

set(MEMPROF_DYNAMIC_WEAK_INTERCEPTION)

add_compiler_rt_runtime(clang_rt.memprof
SHARED
ARCHS ${arch}
OBJECT_LIBS ${MEMPROF_COMMON_RUNTIME_OBJECT_LIBS}
RTMemprof_dynamic
# The only purpose of RTMemprof_dynamic_version_script_dummy is to
# carry a dependency of the shared runtime on the version script.
# Replacing it with a straightforward
# add_dependencies(clang_rt.memprof-dynamic-${arch} clang_rt.memprof-dynamic-${arch}-version-list)
# generates an order-only dependency in ninja.
RTMemprof_dynamic_version_script_dummy
${MEMPROF_DYNAMIC_WEAK_INTERCEPTION}
CFLAGS ${MEMPROF_DYNAMIC_CFLAGS}
LINK_FLAGS ${MEMPROF_DYNAMIC_LINK_FLAGS}
${VERSION_SCRIPT_FLAG}
LINK_LIBS ${MEMPROF_DYNAMIC_LIBS}
DEFS ${MEMPROF_DYNAMIC_DEFINITIONS}
PARENT_TARGET memprof)

if (SANITIZER_USE_SYMBOLS)
add_sanitizer_rt_symbols(clang_rt.memprof_cxx
ARCHS ${arch})
add_dependencies(memprof clang_rt.memprof_cxx-${arch}-symbols)
add_sanitizer_rt_symbols(clang_rt.memprof
ARCHS ${arch}
EXTRA memprof.syms.extra)
add_dependencies(memprof clang_rt.memprof-${arch}-symbols)
endif()
endforeach()
endif()

if(COMPILER_RT_INCLUDE_TESTS)
add_subdirectory(tests)
Expand Down
Loading
Loading