Skip to content

Commit

Permalink
[sanitizer_common] Move filesystem-related code out of sanitizer_comm…
Browse files Browse the repository at this point in the history
…on.cc

This is a pure refactoring change. It just moves code that is
related to filesystem operations from sanitizer_common.{cc,h} to
sanitizer_file.{cc,h}. This makes it cleaner to disable the
filesystem-related code for a new port that doesn't want it.

Commiting for mcgrathr.

Reviewers: alekseyshl

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D35591

llvm-svn: 308640
  • Loading branch information
alekseyshl committed Jul 20, 2017
1 parent c37fe66 commit 89e85d1
Show file tree
Hide file tree
Showing 22 changed files with 303 additions and 223 deletions.
6 changes: 3 additions & 3 deletions compiler-rt/lib/asan/asan_report.cc
Expand Up @@ -141,9 +141,9 @@ class ScopedInErrorReport {

// Can't use Report() here because of potential deadlocks
// in nested signal handlers.
const char msg[] = "AddressSanitizer: nested bug in the same thread, "
"aborting.\n";
WriteToFile(kStderrFd, msg, sizeof(msg));
static const char msg[] =
"AddressSanitizer: nested bug in the same thread, aborting.\n";
CatastrophicErrorWrite(msg, sizeof(msg) - 1);

internal__exit(common_flags()->exitcode);
}
Expand Down
1 change: 1 addition & 0 deletions compiler-rt/lib/dfsan/dfsan.cc
Expand Up @@ -21,6 +21,7 @@

#include "sanitizer_common/sanitizer_atomic.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_file.h"
#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_flag_parser.h"
#include "sanitizer_common/sanitizer_libc.h"
Expand Down
2 changes: 2 additions & 0 deletions compiler-rt/lib/sanitizer_common/CMakeLists.txt
Expand Up @@ -7,6 +7,7 @@ set(SANITIZER_SOURCES_NOTERMINATION
sanitizer_deadlock_detector1.cc
sanitizer_deadlock_detector2.cc
sanitizer_errno.cc
sanitizer_file.cc
sanitizer_flags.cc
sanitizer_flag_parser.cc
sanitizer_libc.cc
Expand Down Expand Up @@ -96,6 +97,7 @@ set(SANITIZER_HEADERS
sanitizer_deadlock_detector_interface.h
sanitizer_errno.h
sanitizer_errno_codes.h
sanitizer_file.h
sanitizer_flag_parser.h
sanitizer_flags.h
sanitizer_flags.inc
Expand Down
141 changes: 0 additions & 141 deletions compiler-rt/lib/sanitizer_common/sanitizer_common.cc
Expand Up @@ -27,72 +27,6 @@ const char *SanitizerToolName = "SanitizerTool";
atomic_uint32_t current_verbosity;
uptr PageSizeCached;

StaticSpinMutex report_file_mu;
ReportFile report_file = {&report_file_mu, kStderrFd, "", "", 0};

void RawWrite(const char *buffer) {
report_file.Write(buffer, internal_strlen(buffer));
}

void ReportFile::ReopenIfNecessary() {
mu->CheckLocked();
if (fd == kStdoutFd || fd == kStderrFd) return;

uptr pid = internal_getpid();
// If in tracer, use the parent's file.
if (pid == stoptheworld_tracer_pid)
pid = stoptheworld_tracer_ppid;
if (fd != kInvalidFd) {
// If the report file is already opened by the current process,
// do nothing. Otherwise the report file was opened by the parent
// process, close it now.
if (fd_pid == pid)
return;
else
CloseFile(fd);
}

const char *exe_name = GetProcessName();
if (common_flags()->log_exe_name && exe_name) {
internal_snprintf(full_path, kMaxPathLength, "%s.%s.%zu", path_prefix,
exe_name, pid);
} else {
internal_snprintf(full_path, kMaxPathLength, "%s.%zu", path_prefix, pid);
}
fd = OpenFile(full_path, WrOnly);
if (fd == kInvalidFd) {
const char *ErrorMsgPrefix = "ERROR: Can't open file: ";
WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));
WriteToFile(kStderrFd, full_path, internal_strlen(full_path));
Die();
}
fd_pid = pid;
}

void ReportFile::SetReportPath(const char *path) {
if (!path)
return;
uptr len = internal_strlen(path);
if (len > sizeof(path_prefix) - 100) {
Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n",
path[0], path[1], path[2], path[3],
path[4], path[5], path[6], path[7]);
Die();
}

SpinMutexLock l(mu);
if (fd != kStdoutFd && fd != kStderrFd && fd != kInvalidFd)
CloseFile(fd);
fd = kInvalidFd;
if (internal_strcmp(path, "stdout") == 0) {
fd = kStdoutFd;
} else if (internal_strcmp(path, "stderr") == 0) {
fd = kStderrFd;
} else {
internal_snprintf(path_prefix, kMaxPathLength, "%s", path);
}
}

// PID of the tracer task in StopTheWorld. It shares the address space with the
// main process, but has a different PID and thus requires special handling.
uptr stoptheworld_tracer_pid = 0;
Expand Down Expand Up @@ -120,42 +54,6 @@ void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type,
UNREACHABLE("unable to mmap");
}

bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
uptr *read_len, uptr max_len, error_t *errno_p) {
uptr PageSize = GetPageSizeCached();
uptr kMinFileLen = PageSize;
*buff = nullptr;
*buff_size = 0;
*read_len = 0;
// The files we usually open are not seekable, so try different buffer sizes.
for (uptr size = kMinFileLen; size <= max_len; size *= 2) {
fd_t fd = OpenFile(file_name, RdOnly, errno_p);
if (fd == kInvalidFd) return false;
UnmapOrDie(*buff, *buff_size);
*buff = (char*)MmapOrDie(size, __func__);
*buff_size = size;
*read_len = 0;
// Read up to one page at a time.
bool reached_eof = false;
while (*read_len + PageSize <= size) {
uptr just_read;
if (!ReadFromFile(fd, *buff + *read_len, PageSize, &just_read, errno_p)) {
UnmapOrDie(*buff, *buff_size);
return false;
}
if (just_read == 0) {
reached_eof = true;
break;
}
*read_len += just_read;
}
CloseFile(fd);
if (reached_eof) // We've read the whole file.
break;
}
return true;
}

typedef bool UptrComparisonFunction(const uptr &a, const uptr &b);
typedef bool U32ComparisonFunction(const u32 &a, const u32 &b);

Expand Down Expand Up @@ -359,36 +257,6 @@ bool TemplateMatch(const char *templ, const char *str) {
return true;
}

static const char kPathSeparator = SANITIZER_WINDOWS ? ';' : ':';

char *FindPathToBinary(const char *name) {
if (FileExists(name)) {
return internal_strdup(name);
}

const char *path = GetEnv("PATH");
if (!path)
return nullptr;
uptr name_len = internal_strlen(name);
InternalScopedBuffer<char> buffer(kMaxPathLength);
const char *beg = path;
while (true) {
const char *end = internal_strchrnul(beg, kPathSeparator);
uptr prefix_len = end - beg;
if (prefix_len + name_len + 2 <= kMaxPathLength) {
internal_memcpy(buffer.data(), beg, prefix_len);
buffer[prefix_len] = '/';
internal_memcpy(&buffer[prefix_len + 1], name, name_len);
buffer[prefix_len + 1 + name_len] = '\0';
if (FileExists(buffer.data()))
return internal_strdup(buffer.data());
}
if (*end == '\0') break;
beg = end + 1;
}
return nullptr;
}

static char binary_name_cache_str[kMaxPathLength];
static char process_name_cache_str[kMaxPathLength];

Expand Down Expand Up @@ -482,15 +350,6 @@ static int InstallMallocFreeHooks(void (*malloc_hook)(const void *, uptr),
using namespace __sanitizer; // NOLINT

extern "C" {
void __sanitizer_set_report_path(const char *path) {
report_file.SetReportPath(path);
}

void __sanitizer_set_report_fd(void *fd) {
report_file.fd = (fd_t)reinterpret_cast<uptr>(fd);
report_file.fd_pid = internal_getpid();
}

SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_report_error_summary,
const char *error_summary) {
Printf("%s\n", error_summary);
Expand Down
80 changes: 1 addition & 79 deletions compiler-rt/lib/sanitizer_common/sanitizer_common.h
Expand Up @@ -185,6 +185,7 @@ typedef void (*LowLevelAllocateCallback)(uptr ptr, uptr size);
void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback);

// IO
void CatastrophicErrorWrite(const char *buffer, uptr length);
void RawWrite(const char *buffer);
bool ColorizeReports();
void RemoveANSIEscapeSequencesFromString(char *buffer);
Expand All @@ -203,64 +204,9 @@ void SetPrintfAndReportCallback(void (*callback)(const char *));
// Can be used to prevent mixing error reports from different sanitizers.
extern StaticSpinMutex CommonSanitizerReportMutex;

struct ReportFile {
void Write(const char *buffer, uptr length);
bool SupportsColors();
void SetReportPath(const char *path);

// Don't use fields directly. They are only declared public to allow
// aggregate initialization.

// Protects fields below.
StaticSpinMutex *mu;
// Opened file descriptor. Defaults to stderr. It may be equal to
// kInvalidFd, in which case new file will be opened when necessary.
fd_t fd;
// Path prefix of report file, set via __sanitizer_set_report_path.
char path_prefix[kMaxPathLength];
// Full path to report, obtained as <path_prefix>.PID
char full_path[kMaxPathLength];
// PID of the process that opened fd. If a fork() occurs,
// the PID of child will be different from fd_pid.
uptr fd_pid;

private:
void ReopenIfNecessary();
};
extern ReportFile report_file;

extern uptr stoptheworld_tracer_pid;
extern uptr stoptheworld_tracer_ppid;

enum FileAccessMode {
RdOnly,
WrOnly,
RdWr
};

// Returns kInvalidFd on error.
fd_t OpenFile(const char *filename, FileAccessMode mode,
error_t *errno_p = nullptr);
void CloseFile(fd_t);

// Return true on success, false on error.
bool ReadFromFile(fd_t fd, void *buff, uptr buff_size,
uptr *bytes_read = nullptr, error_t *error_p = nullptr);
bool WriteToFile(fd_t fd, const void *buff, uptr buff_size,
uptr *bytes_written = nullptr, error_t *error_p = nullptr);

bool RenameFile(const char *oldpath, const char *newpath,
error_t *error_p = nullptr);

// Scoped file handle closer.
struct FileCloser {
explicit FileCloser(fd_t fd) : fd(fd) {}
~FileCloser() { CloseFile(fd); }
fd_t fd;
};

bool SupportsColoredOutput(fd_t fd);

// Opens the file 'file_name" and reads up to 'max_len' bytes.
// The resulting buffer is mmaped and stored in '*buff'.
// The size of the mmaped region is stored in '*buff_size'.
Expand All @@ -269,11 +215,6 @@ bool SupportsColoredOutput(fd_t fd);
bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
uptr *read_len, uptr max_len = 1 << 26,
error_t *errno_p = nullptr);
// Maps given file to virtual memory, and returns pointer to it
// (or NULL if mapping fails). Stores the size of mmaped region
// in '*buff_size'.
void *MapFileToMemory(const char *file_name, uptr *buff_size);
void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset);

bool IsAccessibleMemoryRange(uptr beg, uptr size);

Expand All @@ -293,27 +234,8 @@ void CacheBinaryName();
void DisableCoreDumperIfNecessary();
void DumpProcessMap();
void PrintModuleMap();
bool FileExists(const char *filename);
const char *GetEnv(const char *name);
bool SetEnv(const char *name, const char *value);
const char *GetPwd();
char *FindPathToBinary(const char *name);
bool IsPathSeparator(const char c);
bool IsAbsolutePath(const char *path);
// Starts a subprocess and returs its pid.
// If *_fd parameters are not kInvalidFd their corresponding input/output
// streams will be redirect to the file. The files will always be closed
// in parent process even in case of an error.
// The child process will close all fds after STDERR_FILENO
// before passing control to a program.
pid_t StartSubprocess(const char *filename, const char *const argv[],
fd_t stdin_fd = kInvalidFd, fd_t stdout_fd = kInvalidFd,
fd_t stderr_fd = kInvalidFd);
// Checks if specified process is still running
bool IsProcessRunning(pid_t pid);
// Waits for the process to finish and returns its exit code.
// Returns -1 in case of an error.
int WaitForProcess(pid_t pid);

u32 GetUid();
void ReExec();
Expand Down
Expand Up @@ -14,6 +14,7 @@
#include "sanitizer_common.h"

#include "sanitizer_allocator_interface.h"
#include "sanitizer_file.h"
#include "sanitizer_flags.h"
#include "sanitizer_stackdepot.h"
#include "sanitizer_stacktrace.h"
Expand Down
Expand Up @@ -12,6 +12,7 @@
#include "sanitizer_allocator_internal.h"
#include "sanitizer_atomic.h"
#include "sanitizer_common.h"
#include "sanitizer_file.h"
#include "sanitizer_symbolizer.h"

using namespace __sanitizer;
Expand Down

0 comments on commit 89e85d1

Please sign in to comment.