Skip to content

Commit ae9f5e4

Browse files
committed
Add compiler-rt MIP support
Add the compiler-rt library `libclang_rt.mip.a` that automatically dumps the contents of the `__llvm_mipraw` section when the program exits. Differential Revision: https://reviews.llvm.org/D104086
1 parent e4a0fc1 commit ae9f5e4

File tree

8 files changed

+250
-0
lines changed

8 files changed

+250
-0
lines changed

compiler-rt/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ option(COMPILER_RT_BUILD_PROFILE "Build profile runtime" ON)
4343
mark_as_advanced(COMPILER_RT_BUILD_PROFILE)
4444
option(COMPILER_RT_BUILD_MEMPROF "Build memory profiling runtime" ON)
4545
mark_as_advanced(COMPILER_RT_BUILD_MEMPROF)
46+
option(COMPILER_RT_BUILD_MIP "Build mip runtime" ON)
47+
mark_as_advanced(COMPILER_RT_BUILD_MIP)
4648
option(COMPILER_RT_BUILD_XRAY_NO_PREINIT "Build xray with no preinit patching" OFF)
4749
mark_as_advanced(COMPILER_RT_BUILD_XRAY_NO_PREINIT)
4850
option(COMPILER_RT_BUILD_ORC "Build ORC runtime" ON)

compiler-rt/cmake/config-ix.cmake

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ set(ALL_HWASAN_SUPPORTED_ARCH ${X86_64} ${ARM64})
329329
set(ALL_MEMPROF_SUPPORTED_ARCH ${X86_64})
330330
set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64}
331331
${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9})
332+
set(ALL_MIP_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64})
332333
set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64})
333334
set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64}
334335
${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9})
@@ -400,6 +401,7 @@ if(APPLE)
400401

401402
set(SANITIZER_COMMON_SUPPORTED_OS osx)
402403
set(PROFILE_SUPPORTED_OS osx)
404+
set(MIP_SUPPORTED_OS osx)
403405
set(TSAN_SUPPORTED_OS osx)
404406
set(XRAY_SUPPORTED_OS osx)
405407
set(FUZZER_SUPPORTED_OS osx)
@@ -487,6 +489,7 @@ if(APPLE)
487489
if(DARWIN_${platform}sim_ARCHS)
488490
list(APPEND SANITIZER_COMMON_SUPPORTED_OS ${platform}sim)
489491
list(APPEND PROFILE_SUPPORTED_OS ${platform}sim)
492+
list(APPEND MIP_SUPPORTED_OS ${platform}sim)
490493
list(APPEND TSAN_SUPPORTED_OS ${platform}sim)
491494
list(APPEND FUZZER_SUPPORTED_OS ${platform}sim)
492495
endif()
@@ -513,6 +516,7 @@ if(APPLE)
513516
if(DARWIN_${platform}_ARCHS)
514517
list(APPEND SANITIZER_COMMON_SUPPORTED_OS ${platform})
515518
list(APPEND PROFILE_SUPPORTED_OS ${platform})
519+
list(APPEND MIP_SUPPORTED_OS ${platform})
516520

517521
list_intersect(DARWIN_${platform}_TSAN_ARCHS DARWIN_${platform}_ARCHS ALL_TSAN_SUPPORTED_ARCH)
518522
if(DARWIN_${platform}_TSAN_ARCHS)
@@ -565,6 +569,9 @@ if(APPLE)
565569
list_intersect(PROFILE_SUPPORTED_ARCH
566570
ALL_PROFILE_SUPPORTED_ARCH
567571
SANITIZER_COMMON_SUPPORTED_ARCH)
572+
list_intersect(MIP_SUPPORTED_ARCH
573+
ALL_MIP_SUPPORTED_ARCH
574+
SANITIZER_COMMON_SUPPORTED_ARCH)
568575
list_intersect(TSAN_SUPPORTED_ARCH
569576
ALL_TSAN_SUPPORTED_ARCH
570577
SANITIZER_COMMON_SUPPORTED_ARCH)
@@ -615,6 +622,7 @@ else()
615622
filter_available_targets(HWASAN_SUPPORTED_ARCH ${ALL_HWASAN_SUPPORTED_ARCH})
616623
filter_available_targets(MEMPROF_SUPPORTED_ARCH ${ALL_MEMPROF_SUPPORTED_ARCH})
617624
filter_available_targets(PROFILE_SUPPORTED_ARCH ${ALL_PROFILE_SUPPORTED_ARCH})
625+
filter_available_targets(MIP_SUPPORTED_ARCH ${ALL_MIP_SUPPORTED_ARCH})
618626
filter_available_targets(TSAN_SUPPORTED_ARCH ${ALL_TSAN_SUPPORTED_ARCH})
619627
filter_available_targets(UBSAN_SUPPORTED_ARCH ${ALL_UBSAN_SUPPORTED_ARCH})
620628
filter_available_targets(SAFESTACK_SUPPORTED_ARCH
@@ -731,6 +739,12 @@ else()
731739
set(COMPILER_RT_HAS_PROFILE FALSE)
732740
endif()
733741

742+
if (MIP_SUPPORTED_ARCH AND OS_NAME MATCHES "Darwin|Linux|Android")
743+
set(COMPILER_RT_HAS_MIP TRUE)
744+
else()
745+
set(COMPILER_RT_HAS_MIP FALSE)
746+
endif()
747+
734748
if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH AND
735749
OS_NAME MATCHES "Darwin|Linux|FreeBSD|Android|NetBSD")
736750
set(COMPILER_RT_HAS_TSAN TRUE)

compiler-rt/include/mip/MIPData.inc

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//===-- MIPData.inc - machine ir profile runtime structures -------*- C -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file contains definitions and data structures that are shared between
10+
// the runtime and the compiler. It lives in two locations that need to stay in
11+
// sync.
12+
// + llvm/include/llvm/MIP/MIPData.inc
13+
// + compiler-rt/include/mip/MIPData.inc
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef MIP_DATA_DEFINED
18+
19+
#include <stdint.h>
20+
21+
#ifndef MIP_DATA_INC
22+
#define MIP_DATA_INC
23+
24+
#define MIP_SIMPLE_QUOTE(x) #x
25+
#define MIP_QUOTE(x) MIP_SIMPLE_QUOTE(x)
26+
#define MIP_SIMPLE_CONCAT(x,y) x ## y
27+
#define MIP_CONCAT(x,y) MIP_SIMPLE_CONCAT(x,y)
28+
29+
#define MIP_RAW_SECTION __llvm_mipraw
30+
#define MIP_MAP_SECTION __llvm_mipmap
31+
#define MIP_RUNTIME_SYMBOL __llvm_mip_runtime
32+
33+
#define MIP_RAW_SECTION_NAME MIP_QUOTE(MIP_RAW_SECTION)
34+
#define MIP_MAP_SECTION_NAME MIP_QUOTE(MIP_MAP_SECTION)
35+
#define MIP_RUNTIME_SYMBOL_NAME MIP_QUOTE(MIP_RUNTIME_SYMBOL)
36+
37+
// MIP magic value in little endian format.
38+
// \251 M I P
39+
// 0xFB 0x4D 0x49 0x50
40+
#define MIP_MAGIC_VALUE (0x50494DFB)
41+
#define MIP_VERSION (8)
42+
43+
typedef enum {
44+
MIP_FILE_TYPE_RAW = 0x0001, // .mipraw
45+
MIP_FILE_TYPE_MAP = 0x0002, // .mipmap
46+
MIP_FILE_TYPE_PROFILE = 0x0003, // .mip
47+
MIP_FILE_TYPE_CALL_EDGE_SAMPLES = 0x0004, // .mipret
48+
} MIPFileType;
49+
50+
typedef enum {
51+
MIP_PROFILE_TYPE_FUNCTION_COVERAGE = 1 << 0,
52+
MIP_PROFILE_TYPE_BLOCK_COVERAGE = 1 << 1,
53+
MIP_PROFILE_TYPE_FUNCTION_TIMESTAMP = 1 << 2,
54+
MIP_PROFILE_TYPE_FUNCTION_CALL_COUNT = 1 << 3,
55+
MIP_PROFILE_TYPE_RETURN_ADDRESS = 1 << 4,
56+
} MIPProfileType;
57+
58+
typedef struct {
59+
uint32_t Magic;
60+
uint16_t Version;
61+
uint16_t FileType;
62+
uint32_t ProfileType;
63+
uint32_t ModuleHash;
64+
uint32_t Reserved;
65+
uint32_t OffsetToData;
66+
} MIPHeader;
67+
68+
typedef struct {
69+
uint32_t CalleeProfileDataOffset;
70+
uint32_t SectionRelativeReturnAddress;
71+
} CallEdge_t;
72+
73+
#endif // MIP_DATA_INC
74+
75+
#else // MIP_DATA_INC
76+
#undef MIP_DATA_DEFINED
77+
#endif // MIP_DATA_DEFINED

compiler-rt/lib/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ if(COMPILER_RT_BUILD_PROFILE AND COMPILER_RT_HAS_PROFILE)
5454
compiler_rt_build_runtime(profile)
5555
endif()
5656

57+
if(COMPILER_RT_BUILD_MIP AND COMPILER_RT_HAS_MIP)
58+
compiler_rt_build_runtime(mip)
59+
endif()
60+
5761
if(COMPILER_RT_BUILD_XRAY)
5862
compiler_rt_build_runtime(xray)
5963
endif()

compiler-rt/lib/mip/CMakeLists.txt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
add_compiler_rt_component(mip)
2+
3+
set(MIP_SOURCES
4+
MIPHelper.c
5+
MIPRuntime.cpp
6+
)
7+
8+
set(MIP_HEADERS
9+
MIPHelper.h
10+
)
11+
12+
include_directories(../../include)
13+
14+
if(APPLE)
15+
add_compiler_rt_runtime(clang_rt.mip
16+
STATIC
17+
OS ${MIP_SUPPORTED_OS}
18+
ARCHS ${MIP_SUPPORTED_ARCH}
19+
CFLAGS ${EXTRA_FLAGS}
20+
SOURCES ${MIP_SOURCES}
21+
ADDITIONAL_HEADERS ${MIP_HEADERS}
22+
PARENT_TARGET mip)
23+
else()
24+
add_compiler_rt_runtime(clang_rt.mip
25+
STATIC
26+
ARCHS ${MIP_SUPPORTED_ARCH}
27+
CFLAGS ${EXTRA_FLAGS}
28+
SOURCES ${MIP_SOURCES}
29+
ADDITIONAL_HEADERS ${MIP_HEADERS}
30+
PARENT_TARGET mip)
31+
endif()

compiler-rt/lib/mip/MIPHelper.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*===- MIPHelper.c - Machine IR Profile Runtime Helper --------------------===*\
2+
|*
3+
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
|* See https://llvm.org/LICENSE.txt for license information.
5+
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
|*
7+
\*===----------------------------------------------------------------------===*/
8+
9+
#include "MIPHelper.h"
10+
#include <errno.h>
11+
#include <stdio.h>
12+
#include <stdlib.h>
13+
#include <string.h>
14+
15+
void __llvm_mip_runtime_initialize(void) { atexit(__llvm_dump_mip_profile); }
16+
17+
void __llvm_dump_mip_profile(void) {
18+
const char *Filename = getenv("LLVM_MIP_PROFILE_FILENAME");
19+
if (!Filename || !Filename[0])
20+
Filename = "default.mipraw";
21+
22+
char *FormatSpecifierPtr;
23+
char Buffer[strlen(Filename) + 3];
24+
if ((FormatSpecifierPtr = strstr(Filename, "%h"))) {
25+
const MIPHeader *Header = (MIPHeader *)__llvm_mip_profile_begin();
26+
const char *Prefix = Filename;
27+
int PrefixLength = FormatSpecifierPtr - Filename;
28+
const char *Suffix = FormatSpecifierPtr + strlen("%h");
29+
sprintf(Buffer, "%.*s%04x%s", PrefixLength, Prefix,
30+
Header->ModuleHash & 0xFFFF, Suffix);
31+
Filename = Buffer;
32+
}
33+
__llvm_dump_mip_profile_with_filename(Filename);
34+
}
35+
36+
int __llvm_dump_mip_profile_with_filename(const char *Filename) {
37+
FILE *filep = fopen(Filename, "wb");
38+
if (!filep) {
39+
fprintf(stderr, "[MIPRuntime]: Failed to open %s: %s\n", Filename,
40+
strerror(errno));
41+
return -1;
42+
}
43+
44+
const void *Data = __llvm_mip_profile_begin();
45+
size_t DataSize =
46+
(char *)__llvm_mip_profile_end() - (char *)__llvm_mip_profile_begin();
47+
size_t BytesWritten = fwrite(Data, 1, DataSize, filep);
48+
if (BytesWritten != DataSize) {
49+
fprintf(stderr, "[MIPRuntime]: Failed to write to %s: %s\n", Filename,
50+
strerror(errno));
51+
fclose(filep);
52+
return -1;
53+
}
54+
55+
fclose(filep);
56+
return 0;
57+
}
58+
59+
#ifdef __linux__
60+
#define MIP_RAW_SECTION_BEGIN_SYMBOL MIP_CONCAT(__start_, MIP_RAW_SECTION)
61+
#define MIP_RAW_SECTION_END_SYMBOL MIP_CONCAT(__stop_, MIP_RAW_SECTION)
62+
extern char MIP_RAW_SECTION_BEGIN_SYMBOL;
63+
extern char MIP_RAW_SECTION_END_SYMBOL;
64+
#endif // __linux__
65+
66+
#ifdef __APPLE__
67+
#define MIP_RAW_SECTION_BEGIN_SYMBOL __llvm_mip_raw_section_start
68+
#define MIP_RAW_SECTION_END_SYMBOL __llvm_mip_raw_section_end
69+
extern char MIP_RAW_SECTION_BEGIN_SYMBOL __asm(
70+
"section$start$__DATA$" MIP_RAW_SECTION_NAME);
71+
extern char MIP_RAW_SECTION_END_SYMBOL __asm(
72+
"section$end$__DATA$" MIP_RAW_SECTION_NAME);
73+
#endif // __APPLE__
74+
75+
void *__llvm_mip_profile_begin(void) { return &MIP_RAW_SECTION_BEGIN_SYMBOL; }
76+
77+
void *__llvm_mip_profile_end(void) { return &MIP_RAW_SECTION_END_SYMBOL; }

compiler-rt/lib/mip/MIPHelper.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*===- MIPHelper.h - Machine IR Profile Runtime Helper --------------------===*\
2+
|*
3+
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
|* See https://llvm.org/LICENSE.txt for license information.
5+
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
|*
7+
\*===----------------------------------------------------------------------===*/
8+
9+
#ifndef MIP_MIPHELPER_H
10+
#define MIP_MIPHELPER_H
11+
12+
#include "mip/MIPData.inc"
13+
14+
void __llvm_dump_mip_profile(void);
15+
int __llvm_dump_mip_profile_with_filename(const char *Filename);
16+
17+
void *__llvm_mip_profile_begin(void);
18+
void *__llvm_mip_profile_end(void);
19+
20+
void __llvm_mip_runtime_initialize(void);
21+
22+
#endif // MIP_MIPHELPER_H

compiler-rt/lib/mip/MIPRuntime.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*===- MIPRuntime.c - Machine IR Profile Runtime Helper -------------------===*\
2+
|*
3+
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
|* See https://llvm.org/LICENSE.txt for license information.
5+
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
|*
7+
\*===----------------------------------------------------------------------===*/
8+
9+
extern "C" {
10+
#include "MIPHelper.h"
11+
int MIP_RUNTIME_SYMBOL;
12+
}
13+
14+
namespace {
15+
16+
class RegisterMIPRuntime {
17+
public:
18+
RegisterMIPRuntime() { __llvm_mip_runtime_initialize(); }
19+
};
20+
21+
RegisterMIPRuntime Registration;
22+
23+
} // namespace

0 commit comments

Comments
 (0)