Skip to content

[profile] Add %t LLVM_PROFILE_FILE option to substitute $TMPDIR #1855

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 1 commit into from
Sep 25, 2020
Merged
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
3 changes: 3 additions & 0 deletions clang/docs/SourceBasedCodeCoverage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ directory structure will be created. Additionally, the following special

* "%h" expands out to the hostname of the machine running the program.

* "%t" expands out to the value of the ``TMPDIR`` environment variable. On
Darwin, this is typically set to a temporary scratch directory.

* "%Nm" expands out to the instrumented binary's signature. When this pattern
is specified, the runtime creates a pool of N raw profiles which are used for
on-line profile merging. The runtime takes care of selecting a raw profile
Expand Down
28 changes: 22 additions & 6 deletions compiler-rt/lib/profile/InstrProfilingFile.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ typedef struct lprofFilename {
unsigned OwnsFilenamePat;
const char *ProfilePathPrefix;
char PidChars[MAX_PID_SIZE];
char *TmpDir;
char Hostname[COMPILER_RT_MAX_HOSTLEN];
unsigned NumPids;
unsigned NumHosts;
Expand All @@ -90,8 +91,8 @@ typedef struct lprofFilename {
ProfileNameSpecifier PNS;
} lprofFilename;

static lprofFilename lprofCurFilename = {0, 0, 0, {0}, {0}, 0,
0, 0, {0}, 0, PNS_unknown};
static lprofFilename lprofCurFilename = {0, 0, 0, {0}, NULL, {0},
0, 0, 0, {0}, 0, PNS_unknown};

static int ProfileMergeRequested = 0;
static int isProfileMergeRequested() { return ProfileMergeRequested; }
Expand Down Expand Up @@ -773,6 +774,14 @@ static int parseFilenamePattern(const char *FilenamePat,
FilenamePat);
return -1;
}
} else if (FilenamePat[I] == 't') {
lprofCurFilename.TmpDir = getenv("TMPDIR");
if (!lprofCurFilename.TmpDir) {
PROF_WARN("Unable to get the TMPDIR environment variable, referenced "
"in %s. Using the default path.",
FilenamePat);
return -1;
}
} else if (FilenamePat[I] == 'c') {
if (__llvm_profile_is_continuous_mode_enabled()) {
PROF_WARN("%%c specifier can only be specified once in %s.\n",
Expand Down Expand Up @@ -874,12 +883,14 @@ static int getCurFilenameLength() {
return 0;

if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
lprofCurFilename.MergePoolSize || lprofCurFilename.NumExitSignals))
lprofCurFilename.TmpDir || lprofCurFilename.MergePoolSize ||
lprofCurFilename.NumExitSignals))
return strlen(lprofCurFilename.FilenamePat);

Len = strlen(lprofCurFilename.FilenamePat) +
lprofCurFilename.NumPids * (strlen(lprofCurFilename.PidChars) - 2) +
lprofCurFilename.NumHosts * (strlen(lprofCurFilename.Hostname) - 2);
lprofCurFilename.NumHosts * (strlen(lprofCurFilename.Hostname) - 2) +
(lprofCurFilename.TmpDir ? (strlen(lprofCurFilename.TmpDir) - 1) : 0);
if (lprofCurFilename.MergePoolSize)
Len += SIGLEN;
for (I = 0; I < lprofCurFilename.NumExitSignals; ++I) {
Expand All @@ -896,14 +907,14 @@ static int getCurFilenameLength() {
* current filename pattern string is directly returned, unless ForceUseBuf
* is enabled. */
static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {
int I, J, PidLength, HostNameLength, FilenamePatLength;
int I, J, PidLength, HostNameLength, TmpDirLength, FilenamePatLength;
const char *FilenamePat = lprofCurFilename.FilenamePat;

if (!lprofCurFilename.FilenamePat || !lprofCurFilename.FilenamePat[0])
return 0;

if (!(lprofCurFilename.NumPids || lprofCurFilename.NumHosts ||
lprofCurFilename.MergePoolSize ||
lprofCurFilename.TmpDir || lprofCurFilename.MergePoolSize ||
__llvm_profile_is_continuous_mode_enabled() ||
lprofCurFilename.NumExitSignals)) {
if (!ForceUseBuf)
Expand All @@ -917,6 +928,7 @@ static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {

PidLength = strlen(lprofCurFilename.PidChars);
HostNameLength = strlen(lprofCurFilename.Hostname);
TmpDirLength = lprofCurFilename.TmpDir ? strlen(lprofCurFilename.TmpDir) : 0;
/* Construct the new filename. */
for (I = 0, J = 0; FilenamePat[I]; ++I)
if (FilenamePat[I] == '%') {
Expand All @@ -929,6 +941,10 @@ static const char *getCurFilename(char *FilenameBuf, int ForceUseBuf) {
} else if (containsExitOnSignalSpecifier(FilenamePat, I)) {
while (FilenamePat[I] != 'x')
++I;
} else if (FilenamePat[I] == 't') {
memcpy(FilenameBuf + J, lprofCurFilename.TmpDir, TmpDirLength);
FilenameBuf[J + TmpDirLength] = DIR_SEPARATOR;
J += TmpDirLength + 1;
} else {
if (!getMergePoolSize(FilenamePat, &I))
continue;
Expand Down
22 changes: 22 additions & 0 deletions compiler-rt/test/profile/instrprof-tmpdir.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: cd %t
// RUN: %clang_profgen -o %t/binary %s
//
// Check that a dir separator is appended after %t is subsituted.
// RUN: env TMPDIR="%t" LLVM_PROFILE_FILE="%%traw1.profraw" %run ./binary
// RUN: llvm-profdata show ./raw1.profraw | FileCheck %s -check-prefix TMPDIR
//
// Check that substitution works even if a redundant dir separator is added.
// RUN: env TMPDIR="%t" LLVM_PROFILE_FILE="%%t/raw2.profraw" %run ./binary
// RUN: llvm-profdata show ./raw2.profraw | FileCheck %s -check-prefix TMPDIR
//
// Check that we fall back to the default path if TMPDIR is missing.
// RUN: env -u TMPDIR LLVM_PROFILE_FILE="%%t/raw3.profraw" %run ./binary 2>&1 | FileCheck %s -check-prefix MISSING
// RUN: llvm-profdata show ./default.profraw | FileCheck %s -check-prefix TMPDIR

// TMPDIR: Maximum function count: 1

// MISSING: Unable to get the TMPDIR environment variable, referenced in {{.*}}raw3.profraw. Using the default path.

int main() { return 0; }