Index: lib/sanitizer_common/sanitizer_common.h =================================================================== --- lib/sanitizer_common/sanitizer_common.h +++ lib/sanitizer_common/sanitizer_common.h @@ -213,6 +213,8 @@ bool SetEnv(const char *name, const char *value); const char *GetPwd(); char *FindPathToBinary(const char *name); +// Returns the path to the main executable. +uptr ReadBinaryName(/*out*/char *buf, uptr buf_len); u32 GetUid(); void ReExec(); bool StackSizeIsUnlimited(); Index: lib/sanitizer_common/sanitizer_linux.h =================================================================== --- lib/sanitizer_common/sanitizer_linux.h +++ lib/sanitizer_common/sanitizer_linux.h @@ -80,8 +80,6 @@ // information). bool LibraryNameIs(const char *full_name, const char *base_name); -// Read the name of the current binary from /proc/self/exe. -uptr ReadBinaryName(/*out*/char *buf, uptr buf_len); // Cache the value of /proc/self/exe. void CacheBinaryName(); Index: lib/sanitizer_common/sanitizer_mac.cc =================================================================== --- lib/sanitizer_common/sanitizer_mac.cc +++ lib/sanitizer_common/sanitizer_mac.cc @@ -31,9 +31,11 @@ #include // for _NSGetEnviron #include +#include #include #include #include +#include #include #include #include @@ -204,6 +206,18 @@ return 0; } +uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { + // On OS X the executable path is saved to the stack by dyld. Reading it + // from there is much faster than calling dladdr, especially for large + // binaries with symbols. + InternalScopedString exe_path(kMaxPathLength); + uint32_t size = exe_path.size(); + if (_NSGetExecutablePath(exe_path.data(), &size) == 0) + if (realpath(exe_path.data(), buf) != 0) + return internal_strlen(buf); + return 0; +} + void ReExec() { UNIMPLEMENTED(); } Index: lib/sanitizer_common/sanitizer_suppressions.cc =================================================================== --- lib/sanitizer_common/sanitizer_suppressions.cc +++ lib/sanitizer_common/sanitizer_suppressions.cc @@ -80,17 +80,45 @@ return suppression_ctx; } +static bool GetPathRelativeToExec(/*out*/char *rel_file_path, + const char *file_path){ + InternalScopedString exec(kMaxPathLength); + if (ReadBinaryName(exec.data(), exec.size())) { + if (const char *slash_pos = internal_strrchr(exec.data(), '/')) { + uptr path_to_exec_len = slash_pos - exec.data() + 1; + internal_memcpy(rel_file_path, exec.data(), path_to_exec_len); + internal_memcpy(rel_file_path + path_to_exec_len, + file_path, + internal_strlen(file_path) + 1); + return true; + } + } + return false; +} + void SuppressionContext::InitIfNecessary() { if (suppression_ctx) return; suppression_ctx = new(placeholder) SuppressionContext; if (common_flags()->suppressions[0] == '\0') return; + + const char *file_path = common_flags()->suppressions; char *suppressions_from_file; uptr buffer_size; + uptr max_len = 1 << 26; + + // If we cannot find the file, check if its location is relative to + // the location of the executable. + InternalScopedString new_file_path(kMaxPathLength); + if (!FileExists(file_path) && file_path[0] != '/' && + GetPathRelativeToExec(new_file_path.data(), file_path)) { + file_path = new_file_path.data(); + } + uptr contents_size = - ReadFileToBuffer(common_flags()->suppressions, &suppressions_from_file, - &buffer_size, 1 << 26 /* max_len */); + ReadFileToBuffer(file_path, &suppressions_from_file, &buffer_size, max_len); + if (contents_size == 0) { Printf("%s: failed to read suppressions file '%s'\n", SanitizerToolName, common_flags()->suppressions); Index: lib/sanitizer_common/sanitizer_win.cc =================================================================== --- lib/sanitizer_common/sanitizer_win.cc +++ lib/sanitizer_common/sanitizer_win.cc @@ -301,6 +301,11 @@ return 0; } +uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { + // Nothing here for now. + return 0; +} + void SleepForSeconds(int seconds) { Sleep(seconds * 1000); }