forked from OSchip/llvm-project
[ASan] Add process basename to log name and error message to simplify analysis of sanitized systems logs.
Reviewed at http://reviews.llvm.org/D5724 llvm-svn: 221896
This commit is contained in:
parent
6be0f55d44
commit
17072ef348
|
@ -53,7 +53,7 @@ void AppendToErrorMessageBuffer(const char *buffer) {
|
|||
buffer, remaining);
|
||||
error_message_buffer[error_message_buffer_size - 1] = '\0';
|
||||
// FIXME: reallocate the buffer instead of truncating the message.
|
||||
error_message_buffer_pos += remaining > length ? length : remaining;
|
||||
error_message_buffer_pos += Min(remaining, length);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -803,7 +803,7 @@ INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
|
|||
__msan_unpoison(buf, res);
|
||||
if (srcaddr) {
|
||||
SIZE_T sz = *addrlen;
|
||||
__msan_unpoison(srcaddr, (sz < srcaddr_sz) ? sz : srcaddr_sz);
|
||||
__msan_unpoison(srcaddr, Min(sz, srcaddr_sz));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
|
|
@ -160,6 +160,8 @@ const char *StripModuleName(const char *module) {
|
|||
return 0;
|
||||
if (const char *slash_pos = internal_strrchr(module, '/'))
|
||||
return slash_pos + 1;
|
||||
else if (const char *backslash_pos = internal_strrchr(module, '\\'))
|
||||
return backslash_pos + 1;
|
||||
return module;
|
||||
}
|
||||
|
||||
|
@ -225,6 +227,24 @@ void DecreaseTotalMmap(uptr size) {
|
|||
atomic_fetch_sub(&g_total_mmaped, size, memory_order_relaxed);
|
||||
}
|
||||
|
||||
static BlockingMutex binary_name_cache_lock(LINKER_INITIALIZED);
|
||||
static char binary_name_cache_str[kMaxPathLength];
|
||||
static bool binary_name_cache_initialized = false;
|
||||
|
||||
const char *GetBinaryName() {
|
||||
BlockingMutexLock l(&binary_name_cache_lock);
|
||||
if (!binary_name_cache_initialized) {
|
||||
ReadBinaryName(binary_name_cache_str, sizeof(binary_name_cache_str));
|
||||
binary_name_cache_initialized = true;
|
||||
}
|
||||
return binary_name_cache_str;
|
||||
}
|
||||
|
||||
void CacheBinaryName() {
|
||||
// Call once to make sure that binary_name_cache_str is initialized
|
||||
GetBinaryName();
|
||||
}
|
||||
|
||||
} // namespace __sanitizer
|
||||
|
||||
using namespace __sanitizer; // NOLINT
|
||||
|
|
|
@ -176,6 +176,9 @@ const char *StripPathPrefix(const char *filepath,
|
|||
const char *StripModuleName(const char *module);
|
||||
|
||||
// OS
|
||||
uptr ReadBinaryName(/*out*/char *buf, uptr buf_len);
|
||||
const char *GetBinaryName();
|
||||
void CacheBinaryName();
|
||||
void DisableCoreDumperIfNecessary();
|
||||
void DumpProcessMap();
|
||||
bool FileExists(const char *filename);
|
||||
|
|
|
@ -98,8 +98,8 @@ void ParseCommonFlagsFromString(CommonFlags *f, const char *str) {
|
|||
ParseFlag(str, &f->malloc_context_size, "malloc_context_size",
|
||||
"Max number of stack frames kept for each allocation/deallocation.");
|
||||
ParseFlag(str, &f->log_path, "log_path",
|
||||
"Write logs to \"log_path.pid\". The special values are \"stdout\" and "
|
||||
"\"stderr\". The default is \"stderr\".");
|
||||
"Write logs to \"log_path.pname.pid\". The special values are \"stdout\" "
|
||||
"and \"stderr\". The default is \"stderr\".");
|
||||
ParseFlag(str, &f->verbosity, "verbosity",
|
||||
"Verbosity level (0 - silent, 1 - a bit of output, 2+ - more output).");
|
||||
ParseFlag(str, &f->detect_leaks, "detect_leaks",
|
||||
|
|
|
@ -678,47 +678,31 @@ uptr GetPageSize() {
|
|||
#endif
|
||||
}
|
||||
|
||||
static char proc_self_exe_cache_str[kMaxPathLength];
|
||||
static uptr proc_self_exe_cache_len = 0;
|
||||
|
||||
uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
|
||||
if (proc_self_exe_cache_len > 0) {
|
||||
// If available, use the cached module name.
|
||||
uptr module_name_len =
|
||||
internal_snprintf(buf, buf_len, "%s", proc_self_exe_cache_str);
|
||||
CHECK_LT(module_name_len, buf_len);
|
||||
return module_name_len;
|
||||
}
|
||||
#if SANITIZER_FREEBSD
|
||||
const int Mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
|
||||
const int Mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
|
||||
const char *default_module_name = "kern.proc.pathname";
|
||||
size_t Size = buf_len;
|
||||
bool IsErr = (sysctl(Mib, 4, buf, &Size, NULL, 0) != 0);
|
||||
bool IsErr = (sysctl(Mib, ARRAY_SIZE(Mib), buf, &Size, NULL, 0) != 0);
|
||||
int readlink_error = IsErr ? errno : 0;
|
||||
uptr module_name_len = Size;
|
||||
#else
|
||||
const char *default_module_name = "/proc/self/exe";
|
||||
uptr module_name_len = internal_readlink(
|
||||
"/proc/self/exe", buf, buf_len);
|
||||
int readlink_error;
|
||||
bool IsErr = internal_iserror(module_name_len, &readlink_error);
|
||||
#endif
|
||||
if (IsErr) {
|
||||
// We can't read /proc/self/exe for some reason, assume the name of the
|
||||
// binary is unknown.
|
||||
Report("WARNING: readlink(\"/proc/self/exe\") failed with errno %d, "
|
||||
// We can't read binary name for some reason, assume it's unknown.
|
||||
Report("WARNING: reading executable name failed with errno %d, "
|
||||
"some stack frames may not be symbolized\n", readlink_error);
|
||||
module_name_len = internal_snprintf(buf, buf_len, "/proc/self/exe");
|
||||
module_name_len = internal_snprintf(buf, buf_len, default_module_name);
|
||||
CHECK_LT(module_name_len, buf_len);
|
||||
}
|
||||
return module_name_len;
|
||||
}
|
||||
|
||||
void CacheBinaryName() {
|
||||
if (!proc_self_exe_cache_len) {
|
||||
proc_self_exe_cache_len =
|
||||
ReadBinaryName(proc_self_exe_cache_str, kMaxPathLength);
|
||||
}
|
||||
}
|
||||
|
||||
// Match full names of the form /path/to/base_name{-,.}*
|
||||
bool LibraryNameIs(const char *full_name, const char *base_name) {
|
||||
const char *name = full_name;
|
||||
|
|
|
@ -80,11 +80,6 @@ uptr ThreadSelfOffset();
|
|||
// 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();
|
||||
|
||||
// Call cb for each region mapped by map.
|
||||
void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr));
|
||||
} // namespace __sanitizer
|
||||
|
|
|
@ -317,6 +317,13 @@ MacosVersion GetMacosVersion() {
|
|||
return result;
|
||||
}
|
||||
|
||||
uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
|
||||
// FIXME: Actually implement this function.
|
||||
CHECK_GT(buf_len, 0);
|
||||
buf[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace __sanitizer
|
||||
|
||||
#endif // SANITIZER_MAC
|
||||
|
|
|
@ -289,13 +289,14 @@ char *FindPathToBinary(const char *name) {
|
|||
void MaybeOpenReportFile() {
|
||||
if (!log_to_file) return;
|
||||
uptr pid = internal_getpid();
|
||||
const char *pname = StripModuleName(GetBinaryName());
|
||||
// If in tracer, use the parent's file.
|
||||
if (pid == stoptheworld_tracer_pid)
|
||||
pid = stoptheworld_tracer_ppid;
|
||||
if (report_fd_pid == pid) return;
|
||||
InternalScopedBuffer<char> report_path_full(4096);
|
||||
internal_snprintf(report_path_full.data(), report_path_full.size(),
|
||||
"%s.%zu", report_path_prefix, pid);
|
||||
"%s.%s.%zu", report_path_prefix, pname, pid);
|
||||
uptr openrv = OpenFile(report_path_full.data(), true);
|
||||
if (internal_iserror(openrv)) {
|
||||
report_fd = kStderrFd;
|
||||
|
|
|
@ -253,9 +253,11 @@ static void SharedPrintfCode(bool append_pid, const char *format,
|
|||
needed_length = 0;
|
||||
if (append_pid) {
|
||||
int pid = internal_getpid();
|
||||
needed_length += internal_snprintf(buffer, buffer_size, "==%d==", pid);
|
||||
const char *pname = StripModuleName(GetBinaryName());
|
||||
needed_length += internal_snprintf(buffer, buffer_size,
|
||||
"==%s %d==", pname, pid);
|
||||
if (needed_length >= buffer_size) {
|
||||
// The pid doesn't fit into the current buffer.
|
||||
// Process name + pid do not fit into the current buffer.
|
||||
if (!use_mmap)
|
||||
continue;
|
||||
RAW_CHECK_MSG(needed_length < kLen, "Buffer in Report is too short!\n");
|
||||
|
|
|
@ -643,11 +643,8 @@ class POSIXSymbolizer : public Symbolizer {
|
|||
}
|
||||
|
||||
void PrepareForSandboxing() {
|
||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||
BlockingMutexLock l(&mu_);
|
||||
// Cache /proc/self/exe on Linux.
|
||||
CacheBinaryName();
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -527,6 +527,13 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) {
|
|||
return true;
|
||||
}
|
||||
|
||||
uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
|
||||
// FIXME: Actually implement this function.
|
||||
CHECK_GT(buf_len, 0);
|
||||
buf[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace __sanitizer
|
||||
|
||||
#endif // _WIN32
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// Good log_path.
|
||||
// RUN: rm -f %t.log.*
|
||||
// RUN: env ASAN_OPTIONS=log_path=%t.log not %run %t 2> %t.out
|
||||
// RUN: FileCheck %s --check-prefix=CHECK-ERROR < %t.log.*
|
||||
// RUN: FileCheck %s --check-prefix=CHECK-ERROR < %t.log.log-path_test.cc*
|
||||
|
||||
// Invalid log_path.
|
||||
// RUN: env ASAN_OPTIONS=log_path=/INVALID not %run %t 2> %t.out
|
||||
|
@ -24,7 +24,7 @@
|
|||
// Run w/o errors should not produce any log.
|
||||
// RUN: rm -f %t.log.*
|
||||
// RUN: env ASAN_OPTIONS=log_path=%t.log %run %t ARG ARG ARG
|
||||
// RUN: not cat %t.log.*
|
||||
// RUN: not cat %t.log.log-path_test.cc*
|
||||
|
||||
// FIXME: log_path is not supported on Windows yet.
|
||||
// XFAIL: win32
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// RUN: rm -f %t.log.*
|
||||
// Set verbosity to 1 so that the log files are opened prior to fork().
|
||||
// RUN: env ASAN_OPTIONS="log_path=%t.log verbosity=1" not %run %t 2> %t.out
|
||||
// RUN: for f in %t.log.* ; do FileCheck %s < $f; done
|
||||
// RUN: for f in %t.log.log_path_fork_test.cc* ; do FileCheck %s < $f; done
|
||||
// RUN: [ `ls %t.log.* | wc -l` == 2 ]
|
||||
|
||||
#include <stdlib.h>
|
||||
|
|
Loading…
Reference in New Issue