Skip to content

Cherry-pick profile runtime & lldb build fixes #203

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

Merged
merged 24 commits into from
Nov 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
78831f4
[debugserver] Detect arch from LLVM_DEFAULT_TARGET_TRIPLE
vedantk Oct 28, 2019
eb497cb
build: workaround stale caches (NFC)
compnerd Oct 29, 2019
950b721
DebugServer: be more lenient about the target triple
compnerd Oct 30, 2019
e87d17b
[profile] Clean up stale raw profiles in instrprof-write-file.c
vedantk Oct 2, 2019
78d8648
[llvm-profdata] Make "malformed-ptr-to-counter-array.test" textual
vedantk Oct 12, 2019
448563b
[llvm-profdata] Weaken "malformed-ptr-to-counter-array.test" to appea…
vedantk Oct 14, 2019
a899875
[llvm-profdata] Remove tools/llvm-profdata/malformed-ptr-to-counter-a…
vedantk Oct 15, 2019
c94123f
[llvm-profdata] Reinstate tools/llvm-profdata/malformed-ptr-to-counte…
vedantk Oct 15, 2019
2ab58b1
(Reland with changes) Adding a function for setting coverage output f…
sajjadm-google Jun 24, 2019
e5c6f3b
[profile] Do not cache __llvm_profile_get_filename result
vedantk Oct 18, 2019
f0c6a1e
[profile] Disable instrprof-get-filename-merge-mode.c on Windows
vedantk Oct 19, 2019
8bc4f02
[profile] Use -fPIC -shared in a test instead of -dynamiclib
vedantk Oct 19, 2019
38f7fcd
[profile] Add a mode to continuously sync counter updates to a file
vedantk Sep 19, 2019
3ea52be
[profile] Speculative fix for Windows after D68351
vedantk Oct 31, 2019
99d852f
[profile] Second speculative fix for Windows
vedantk Oct 31, 2019
6e4528b
[profile] Third speculative fix for Windows after D68351
vedantk Oct 31, 2019
160b090
[profile] Fourth fix for toolchains without zlib after D68351
vedantk Oct 31, 2019
6c07cc4
[profile] Fifth speculative fix for Android after D68351
vedantk Nov 1, 2019
2079f4c
[Function] Factor out GetCallEdgeForReturnAddress, NFC
vedantk Sep 10, 2019
e028da8
[lldbtest] Add an "expected_cmd_failure" option to the filecheck helper
vedantk Sep 10, 2019
565eac5
[Status] Add a LLDB_ERRORF macro for error reporting (similar to LLDB…
vedantk Sep 11, 2019
6bb4911
[cmake] Add an option to skip stripping before install
vedantk Nov 5, 2019
fd56620
[clang][driver] Add ProfileData to LLVM_LINK_COMPONENTS
aheejin Nov 1, 2019
59c5392
[profile] Mark instrprof-gcov-fork.test UNSUPPORTED on Darwin as well
vedantk Sep 27, 2019
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
10 changes: 10 additions & 0 deletions clang/docs/SourceBasedCodeCoverage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,16 @@ directory structure will be created. Additionally, the following special
be between 1 and 9. The merge pool specifier can only occur once per filename
pattern.

* "%c" expands out to nothing, but enables a mode in which profile counter
updates are continuously synced to a file. This means that if the
instrumented program crashes, or is killed by a signal, perfect coverage
information can still be recovered. Continuous mode is not yet compatible with
the "%Nm" merging mode described above, does not support value profiling for
PGO, and is only supported on Darwin. Support for Linux may be mostly
complete but requires testing, and support for Fuchsia/Windows may require
more extensive changes: please get involved if you are interested in porting
this feature.

.. code-block:: console

# Step 2: Run the program.
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
set(LLVM_LINK_COMPONENTS
BinaryFormat
Option
ProfileData
Support
)

Expand Down
37 changes: 35 additions & 2 deletions clang/lib/Driver/ToolChains/Darwin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/ArgList.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/TargetParser.h"
Expand Down Expand Up @@ -1114,28 +1115,60 @@ static void addExportedSymbol(ArgStringList &CmdArgs, const char *Symbol) {
CmdArgs.push_back(Symbol);
}

/// Add a sectalign directive for \p Segment and \p Section to the maximum
/// expected page size for Darwin.
///
/// On iPhone 6+ the max supported page size is 16K. On macOS, the max is 4K.
/// Use a common alignment constant (16K) for now, and reduce the alignment on
/// macOS if it proves important.
static void addSectalignToPage(const ArgList &Args, ArgStringList &CmdArgs,
StringRef Segment, StringRef Section) {
for (const char *A : {"-sectalign", Args.MakeArgString(Segment),
Args.MakeArgString(Section), "0x4000"})
CmdArgs.push_back(A);
}

void Darwin::addProfileRTLibs(const ArgList &Args,
ArgStringList &CmdArgs) const {
if (!needsProfileRT(Args)) return;

AddLinkRuntimeLib(Args, CmdArgs, "profile",
RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink));

bool ForGCOV = needsGCovInstrumentation(Args);

// If we have a symbol export directive and we're linking in the profile
// runtime, automatically export symbols necessary to implement some of the
// runtime's functionality.
if (hasExportSymbolDirective(Args)) {
if (needsGCovInstrumentation(Args)) {
if (ForGCOV) {
addExportedSymbol(CmdArgs, "___gcov_flush");
addExportedSymbol(CmdArgs, "_flush_fn_list");
addExportedSymbol(CmdArgs, "_writeout_fn_list");
} else {
addExportedSymbol(CmdArgs, "___llvm_profile_filename");
addExportedSymbol(CmdArgs, "___llvm_profile_raw_version");
addExportedSymbol(CmdArgs, "_lprofCurFilename");
}
addExportedSymbol(CmdArgs, "_lprofDirMode");
}

// Align __llvm_prf_{cnts,data} sections to the maximum expected page
// alignment. This allows profile counters to be mmap()'d to disk. Note that
// it's not enough to just page-align __llvm_prf_cnts: the following section
// must also be page-aligned so that its data is not clobbered by mmap().
//
// The section alignment is only needed when continuous profile sync is
// enabled, but this is expected to be the default in Xcode. Specifying the
// extra alignment also allows the same binary to be used with/without sync
// enabled.
if (!ForGCOV) {
for (auto IPSK : {llvm::IPSK_cnts, llvm::IPSK_data}) {
addSectalignToPage(
Args, CmdArgs, "__DATA",
llvm::getInstrProfSectionName(IPSK, llvm::Triple::MachO,
/*AddSegmentInfo=*/false));
}
}
}

void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
Expand Down
8 changes: 7 additions & 1 deletion clang/test/Driver/darwin-ld.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,12 @@
// RUN: FileCheck -check-prefix=LINK_PROFILE_FIRST %s < %t.log
// LINK_PROFILE_FIRST: {{ld(.exe)?"}} "{{[^"]+}}libclang_rt.profile_{{[a-z]+}}.a"

// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -### %t.o 2> %t.log
// RUN: FileCheck -check-prefix=PROFILE_SECTALIGN %s < %t.log
// RUN: %clang -target arm64-apple-ios12 -fprofile-instr-generate -### %t.o 2> %t.log
// RUN: FileCheck -check-prefix=PROFILE_SECTALIGN %s < %t.log
// PROFILE_SECTALIGN: "-sectalign" "__DATA" "__llvm_prf_cnts" "0x4000" "-sectalign" "__DATA" "__llvm_prf_data" "0x4000"

// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -exported_symbols_list /dev/null -### %t.o 2> %t.log
// RUN: FileCheck -check-prefix=PROFILE_EXPORT %s < %t.log
// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -Wl,-exported_symbols_list,/dev/null -### %t.o 2> %t.log
Expand All @@ -355,7 +361,7 @@
// RUN: FileCheck -check-prefix=PROFILE_EXPORT %s < %t.log
// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -Xlinker -exported_symbols_list -Xlinker /dev/null -### %t.o 2> %t.log
// RUN: FileCheck -check-prefix=PROFILE_EXPORT %s < %t.log
// PROFILE_EXPORT: "-exported_symbol" "___llvm_profile_filename" "-exported_symbol" "___llvm_profile_raw_version" "-exported_symbol" "_lprofCurFilename"
// PROFILE_EXPORT: "-exported_symbol" "___llvm_profile_filename" "-exported_symbol" "___llvm_profile_raw_version"
//
// RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate --coverage -### %t.o 2> %t.log
// RUN: FileCheck -check-prefix=NO_PROFILE_EXPORT %s < %t.log
Expand Down
4 changes: 3 additions & 1 deletion compiler-rt/lib/profile/InstrProfData.inc
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,9 @@ INSTR_PROF_VALUE_NODE(PtrToNodeT, llvm::Type::getInt8PtrTy(Ctx), Next, \
INSTR_PROF_RAW_HEADER(uint64_t, Magic, __llvm_profile_get_magic())
INSTR_PROF_RAW_HEADER(uint64_t, Version, __llvm_profile_get_version())
INSTR_PROF_RAW_HEADER(uint64_t, DataSize, DataSize)
INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesBeforeCounters, PaddingBytesBeforeCounters)
INSTR_PROF_RAW_HEADER(uint64_t, CountersSize, CountersSize)
INSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesAfterCounters, PaddingBytesAfterCounters)
INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize)
INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin)
INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin)
Expand Down Expand Up @@ -628,7 +630,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
(uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129

/* Raw profile format version (start from 1). */
#define INSTR_PROF_RAW_VERSION 4
#define INSTR_PROF_RAW_VERSION 5
/* Indexed profile format version (start from 1). */
#define INSTR_PROF_INDEX_VERSION 5
/* Coverage mapping format vresion (start from 0). */
Expand Down
82 changes: 80 additions & 2 deletions compiler-rt/lib/profile/InstrProfiling.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define PROFILE_INSTRPROFILING_H_

#include "InstrProfilingPort.h"
#include <stdio.h>

#define INSTR_PROF_VISIBILITY COMPILER_RT_VISIBILITY
#include "InstrProfData.inc"
Expand Down Expand Up @@ -37,6 +38,22 @@ typedef struct ValueProfNode {
#include "InstrProfData.inc"
} ValueProfNode;

/*!
* \brief Return 1 if profile counters are continuously synced to the raw
* profile via an mmap(). This is in contrast to the default mode, in which
* the raw profile is written out at program exit time.
*/
int __llvm_profile_is_continuous_mode_enabled(void);

/*!
* \brief Enable continuous mode.
*
* See \ref __llvm_profile_is_continuous_mode_enabled. The behavior is undefined
* if continuous mode is already enabled, or if it cannot be enable due to
* conflicting options.
*/
void __llvm_profile_enable_continuous_mode(void);

/*!
* \brief Get number of bytes necessary to pad the argument to eight
* byte boundary.
Expand Down Expand Up @@ -125,7 +142,7 @@ int __llvm_orderfile_write_file(void);
/*!
* \brief this is a wrapper interface to \c __llvm_profile_write_file.
* After this interface is invoked, a arleady dumped flag will be set
* so that profile won't be dumped again during program exit.
* so that profile won't be dumped again during program exit.
* Invocation of interface __llvm_profile_reset_counters will clear
* the flag. This interface is designed to be used to collect profile
* data from user selected hot regions. The use model is
Expand Down Expand Up @@ -154,9 +171,47 @@ int __llvm_orderfile_dump(void);
*
* \c Name is not copied, so it must remain valid. Passing NULL resets the
* filename logic to the default behaviour.
*
* Note: There may be multiple copies of the profile runtime (one for each
* instrumented image/DSO). This API only modifies the filename within the
* copy of the runtime available to the calling image.
*
* Warning: This is a no-op if continuous mode (\ref
* __llvm_profile_is_continuous_mode_enabled) is on. The reason for this is
* that in continuous mode, profile counters are mmap()'d to the profile at
* program initialization time. Support for transferring the mmap'd profile
* counts to a new file has not been implemented.
*/
void __llvm_profile_set_filename(const char *Name);

/*!
* \brief Set the FILE object for writing instrumentation data.
*
* Sets the FILE object to be used for subsequent calls to
* \a __llvm_profile_write_file(). The profile file name set by environment
* variable, command-line option, or calls to \a __llvm_profile_set_filename
* will be ignored.
*
* \c File will not be closed after a call to \a __llvm_profile_write_file() but
* it may be flushed. Passing NULL restores default behavior.
*
* If \c EnableMerge is nonzero, the runtime will always merge profiling data
* with the contents of the profiling file. If EnableMerge is zero, the runtime
* may still merge the data if it would have merged for another reason (for
* example, because of a %m specifier in the file name).
*
* Note: There may be multiple copies of the profile runtime (one for each
* instrumented image/DSO). This API only modifies the file object within the
* copy of the runtime available to the calling image.
*
* Warning: This is a no-op if continuous mode (\ref
* __llvm_profile_is_continuous_mode_enabled) is on. The reason for this is
* that in continuous mode, profile counters are mmap()'d to the profile at
* program initialization time. Support for transferring the mmap'd profile
* counts to a new file has not been implemented.
*/
void __llvm_profile_set_file_object(FILE *File, int EnableMerge);

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

Expand All @@ -177,7 +232,12 @@ const char *__llvm_profile_get_path_prefix();
* \brief Return filename (including path) of the profile data. Note that if the
* user calls __llvm_profile_set_filename later after invoking this interface,
* the actual file name may differ from what is returned here.
* Side-effect: this API call will invoke malloc with dynamic memory allocation.
* Side-effect: this API call will invoke malloc with dynamic memory allocation
* (the returned pointer must be passed to `free` to avoid a leak).
*
* Note: There may be multiple copies of the profile runtime (one for each
* instrumented image/DSO). This API only retrieves the filename from the copy
* of the runtime available to the calling image.
*/
const char *__llvm_profile_get_filename();

Expand All @@ -191,6 +251,24 @@ uint64_t __llvm_profile_get_version(void);
uint64_t __llvm_profile_get_data_size(const __llvm_profile_data *Begin,
const __llvm_profile_data *End);

/* ! \brief Given the sizes of the data and counter information, return the
* number of padding bytes before and after the counters, and after the names,
* in the raw profile.
*
* Note: In this context, "size" means "number of entries", i.e. the first two
* arguments must be the result of __llvm_profile_get_data_size() and of
* (__llvm_profile_end_counters() - __llvm_profile_begin_counters()) resp.
*
* Note: When mmap() mode is disabled, no padding bytes before/after counters
* are needed. However, in mmap() mode, the counter section in the raw profile
* must be page-aligned: this API computes the number of padding bytes
* needed to achieve that.
*/
void __llvm_profile_get_padding_sizes_for_counters(
uint64_t DataSize, uint64_t CountersSize, uint64_t NamesSize,
uint64_t *PaddingBytesBeforeCounters, uint64_t *PaddingBytesAfterCounters,
uint64_t *PaddingBytesAfterNames);

/*!
* \brief Set the flag that profile data has been dumped to the file.
* This is useful for users to disable dumping profile data to the file for
Expand Down
74 changes: 70 additions & 4 deletions compiler-rt/lib/profile/InstrProfilingBuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,27 @@

#include "InstrProfiling.h"
#include "InstrProfilingInternal.h"
#include "InstrProfilingPort.h"

/* When continuous mode is enabled (%c), this parameter is set to 1. This is
* incompatible with the in-process merging mode. Lifting this restriction
* may be complicated, as merging mode requires a lock on the profile, and
* mmap() mode would require that lock to be held for the entire process
* lifetime.
*
* This parameter is defined here in InstrProfilingBuffer.o, instead of in
* InstrProfilingFile.o, to sequester all libc-dependent code in
* InstrProfilingFile.o. The test `instrprof-without-libc` will break if this
* layering is violated. */
static int ContinuouslySyncProfile = 0;

COMPILER_RT_VISIBILITY int __llvm_profile_is_continuous_mode_enabled(void) {
return ContinuouslySyncProfile;
}

COMPILER_RT_VISIBILITY void __llvm_profile_enable_continuous_mode(void) {
ContinuouslySyncProfile = 1;
}

COMPILER_RT_VISIBILITY
uint64_t __llvm_profile_get_size_for_buffer(void) {
Expand All @@ -30,18 +51,63 @@ uint64_t __llvm_profile_get_data_size(const __llvm_profile_data *Begin,
sizeof(__llvm_profile_data);
}

/// Calculate the number of padding bytes needed to add to \p Offset in order
/// for (\p Offset + Padding) to be page-aligned.
static uint64_t calculateBytesNeededToPageAlign(uint64_t Offset,
unsigned PageSize) {
uint64_t OffsetModPage = Offset % PageSize;
if (OffsetModPage > 0)
return PageSize - OffsetModPage;
return 0;
}

COMPILER_RT_VISIBILITY
void __llvm_profile_get_padding_sizes_for_counters(
uint64_t DataSize, uint64_t CountersSize, uint64_t NamesSize,
uint64_t *PaddingBytesBeforeCounters, uint64_t *PaddingBytesAfterCounters,
uint64_t *PaddingBytesAfterNames) {
if (!__llvm_profile_is_continuous_mode_enabled()) {
*PaddingBytesBeforeCounters = 0;
*PaddingBytesAfterCounters = 0;
*PaddingBytesAfterNames = __llvm_profile_get_num_padding_bytes(NamesSize);
return;
}

// In continuous mode, the file offsets for headers and for the start of
// counter sections need to be page-aligned.
unsigned PageSize = getpagesize();
uint64_t DataSizeInBytes = DataSize * sizeof(__llvm_profile_data);
uint64_t CountersSizeInBytes = CountersSize * sizeof(uint64_t);
*PaddingBytesBeforeCounters = calculateBytesNeededToPageAlign(
sizeof(__llvm_profile_header) + DataSizeInBytes, PageSize);
*PaddingBytesAfterCounters =
calculateBytesNeededToPageAlign(CountersSizeInBytes, PageSize);
*PaddingBytesAfterNames =
calculateBytesNeededToPageAlign(NamesSize, PageSize);
}

COMPILER_RT_VISIBILITY
uint64_t __llvm_profile_get_size_for_buffer_internal(
const __llvm_profile_data *DataBegin, const __llvm_profile_data *DataEnd,
const uint64_t *CountersBegin, const uint64_t *CountersEnd,
const char *NamesBegin, const char *NamesEnd) {
/* Match logic in __llvm_profile_write_buffer(). */
const uint64_t NamesSize = (NamesEnd - NamesBegin) * sizeof(char);
const uint8_t Padding = __llvm_profile_get_num_padding_bytes(NamesSize);
uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd);
uint64_t CountersSize = CountersEnd - CountersBegin;

/* Determine how much padding is needed before/after the counters and after
* the names. */
uint64_t PaddingBytesBeforeCounters, PaddingBytesAfterCounters,
PaddingBytesAfterNames;
__llvm_profile_get_padding_sizes_for_counters(
DataSize, CountersSize, NamesSize, &PaddingBytesBeforeCounters,
&PaddingBytesAfterCounters, &PaddingBytesAfterNames);

return sizeof(__llvm_profile_header) +
(__llvm_profile_get_data_size(DataBegin, DataEnd) *
sizeof(__llvm_profile_data)) +
(CountersEnd - CountersBegin) * sizeof(uint64_t) + NamesSize + Padding;
(DataSize * sizeof(__llvm_profile_data)) + PaddingBytesBeforeCounters +
(CountersSize * sizeof(uint64_t)) + PaddingBytesAfterCounters +
NamesSize + PaddingBytesAfterNames;
}

COMPILER_RT_VISIBILITY
Expand Down
Loading