Skip to content

Commit 56dec4b

Browse files
committed
[Sanitizer] Allow setting the report path to create directory
When setting the report path, recursively create the directory as needed. This brings the profile path support for memprof on par with normal PGO. The code was largely cloned from __llvm_profile_recursive_mkdir in compiler-rt/lib/profile/InstrProfilingUtil.c. Differential Revision: https://reviews.llvm.org/D109794
1 parent 22ea0ce commit 56dec4b

File tree

7 files changed

+38
-2
lines changed

7 files changed

+38
-2
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_common_nolibc.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ void LogMessageOnPrintf(const char *str) {}
2525
#endif
2626
void WriteToSyslog(const char *buffer) {}
2727
void Abort() { internal__exit(1); }
28+
bool CreateDir(const char *pathname) { return false; }
2829
#endif // !SANITIZER_WINDOWS
2930

3031
#if !SANITIZER_WINDOWS && !SANITIZER_MAC

compiler-rt/lib/sanitizer_common/sanitizer_file.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,20 @@ void ReportFile::ReopenIfNecessary() {
7575
fd_pid = pid;
7676
}
7777

78+
static void RecursiveCreateParentDirs(char *path) {
79+
if (path[0] == '\0')
80+
return;
81+
for (int i = 1; path[i] != '\0'; ++i) {
82+
char save = path[i];
83+
if (!IsPathSeparator(path[i]))
84+
continue;
85+
path[i] = '\0';
86+
/* Some of these will fail, because the directory exists, ignore it. */
87+
CreateDir(path);
88+
path[i] = save;
89+
}
90+
}
91+
7892
void ReportFile::SetReportPath(const char *path) {
7993
if (path) {
8094
uptr len = internal_strlen(path);
@@ -95,6 +109,7 @@ void ReportFile::SetReportPath(const char *path) {
95109
fd = kStdoutFd;
96110
} else {
97111
internal_snprintf(path_prefix, kMaxPathLength, "%s", path);
112+
RecursiveCreateParentDirs(path_prefix);
98113
}
99114
}
100115

compiler-rt/lib/sanitizer_common/sanitizer_file.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ bool FileExists(const char *filename);
8181
char *FindPathToBinary(const char *name);
8282
bool IsPathSeparator(const char c);
8383
bool IsAbsolutePath(const char *path);
84+
// Returns true on success, false on failure.
85+
bool CreateDir(const char *pathname);
8486
// Starts a subprocess and returs its pid.
8587
// If *_fd parameters are not kInvalidFd their corresponding input/output
8688
// streams will be redirect to the file. The files will always be closed

compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ int Atexit(void (*function)(void)) {
151151
#endif
152152
}
153153

154+
bool CreateDir(const char *pathname) { return mkdir(pathname, 0755) == 0; }
155+
154156
bool SupportsColoredOutput(fd_t fd) {
155157
return isatty(fd) != 0;
156158
}

compiler-rt/lib/sanitizer_common/sanitizer_win.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,8 @@ void Abort() {
565565
internal__exit(3);
566566
}
567567

568+
bool CreateDir(const char *pathname) { return _mkdir(pathname) == 0; }
569+
568570
#if !SANITIZER_GO
569571
// Read the file to extract the ImageBase field from the PE header. If ASLR is
570572
// disabled and this virtual address is available, the loader will typically

compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,3 +326,17 @@ TEST(SanitizerCommon, InternalMmapWithOffset) {
326326
internal_unlink(tmpfile);
327327
}
328328
#endif
329+
330+
TEST(SanitizerCommon, ReportFile) {
331+
StaticSpinMutex report_file_mu;
332+
ReportFile report_file = {&report_file_mu, kStderrFd, "", "", 0};
333+
char tmpfile[128];
334+
temp_file_name(tmpfile, sizeof(tmpfile),
335+
"dir/sanitizer_common.reportfile.tmp.");
336+
report_file.SetReportPath(tmpfile);
337+
const char *path = report_file.GetReportPath();
338+
EXPECT_EQ(internal_strncmp(tmpfile, path, strlen(tmpfile)), 0);
339+
// This will close tmpfile.
340+
report_file.SetReportPath("stderr");
341+
Unlink(tmpfile);
342+
}

compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ volatile int *null = 0;
1111

1212
int main(int argc, char **argv) {
1313
char buff[1000];
14-
sprintf(buff, "%s.report_path", argv[0]);
14+
sprintf(buff, "%s.report_path/report", argv[0]);
1515
__sanitizer_set_report_path(buff);
1616
assert(strncmp(buff, __sanitizer_get_report_path(), strlen(buff)) == 0);
1717
printf("Path %s\n", __sanitizer_get_report_path());
1818
}
1919

20-
// CHECK: Path {{.*}}Posix/Output/sanitizer_set_report_path_test.cpp.tmp.report_path.
20+
// CHECK: Path {{.*}}Posix/Output/sanitizer_set_report_path_test.cpp.tmp.report_path/report.

0 commit comments

Comments
 (0)