diff options
Diffstat (limited to 'libsanitizer/sanitizer_common')
20 files changed, 245 insertions, 100 deletions
diff --git a/libsanitizer/sanitizer_common/sanitizer_allocator64.h b/libsanitizer/sanitizer_common/sanitizer_allocator64.h index 247719876aa..7614aba52ac 100644 --- a/libsanitizer/sanitizer_common/sanitizer_allocator64.h +++ b/libsanitizer/sanitizer_common/sanitizer_allocator64.h @@ -16,7 +16,7 @@ #define SANITIZER_ALLOCATOR_H #include "sanitizer_internal_defs.h" -#if __WORDSIZE != 64 +#if SANITIZER_WORDSIZE != 64 # error "sanitizer_allocator64.h can only be used on 64-bit platforms" #endif @@ -275,7 +275,12 @@ class SizeClassAllocator64 { } while (idx < end_idx); region->allocated_user += idx - beg_idx; region->allocated_meta += i * kMetadataSize; - CHECK_LT(region->allocated_user + region->allocated_meta, kRegionSize); + if (region->allocated_user + region->allocated_meta > kRegionSize) { + Printf("Out of memory. Dying.\n"); + Printf("The process has exhausted %zuMB for size class %zu.\n", + kRegionSize / 1024 / 1024, size); + Die(); + } } void *AllocateBySizeClass(uptr class_id) { diff --git a/libsanitizer/sanitizer_common/sanitizer_common.cc b/libsanitizer/sanitizer_common/sanitizer_common.cc index 43ef980e846..fda67a542d5 100644 --- a/libsanitizer/sanitizer_common/sanitizer_common.cc +++ b/libsanitizer/sanitizer_common/sanitizer_common.cc @@ -14,7 +14,9 @@ namespace __sanitizer { -static fd_t report_fd = 2; // By default, dump to stderr. +// By default, dump to stderr. If report_fd is kInvalidFd, try to obtain file +// descriptor by opening file in report_path. +static fd_t report_fd = kStderrFd; static char report_path[4096]; // Set via __sanitizer_set_report_path. static void (*DieCallback)(void); @@ -44,18 +46,27 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond, Die(); } +static void MaybeOpenReportFile() { + if (report_fd != kInvalidFd) + return; + fd_t fd = internal_open(report_path, true); + if (fd == kInvalidFd) { + report_fd = kStderrFd; + Report("ERROR: Can't open file: %s\n", report_path); + Die(); + } + report_fd = fd; +} + +bool PrintsToTty() { + MaybeOpenReportFile(); + return internal_isatty(report_fd); +} + void RawWrite(const char *buffer) { static const char *kRawWriteError = "RawWrite can't output requested buffer!"; uptr length = (uptr)internal_strlen(buffer); - if (report_fd == kInvalidFd) { - fd_t fd = internal_open(report_path, true); - if (fd == kInvalidFd) { - report_fd = 2; - Report("ERROR: Can't open file: %s\n", report_path); - Die(); - } - report_fd = fd; - } + MaybeOpenReportFile(); if (length != internal_write(report_fd, buffer, length)) { internal_write(report_fd, kRawWriteError, internal_strlen(kRawWriteError)); Die(); @@ -136,16 +147,27 @@ void SortArray(uptr *array, uptr size) { } // namespace __sanitizer +using namespace __sanitizer; // NOLINT + +extern "C" { void __sanitizer_set_report_path(const char *path) { if (!path) return; uptr len = internal_strlen(path); - if (len > sizeof(__sanitizer::report_path) - 100) { + if (len > sizeof(report_path) - 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(); } - internal_snprintf(__sanitizer::report_path, - sizeof(__sanitizer::report_path), "%s.%d", path, GetPid()); - __sanitizer::report_fd = kInvalidFd; + internal_snprintf(report_path, sizeof(report_path), "%s.%d", path, GetPid()); + report_fd = kInvalidFd; +} + +void __sanitizer_set_report_fd(int fd) { + if (report_fd != kStdoutFd && + report_fd != kStderrFd && + report_fd != kInvalidFd) + internal_close(report_fd); + report_fd = fd; } +} // extern "C" diff --git a/libsanitizer/sanitizer_common/sanitizer_common.h b/libsanitizer/sanitizer_common/sanitizer_common.h index cddefd7ea09..e565b93af29 100644 --- a/libsanitizer/sanitizer_common/sanitizer_common.h +++ b/libsanitizer/sanitizer_common/sanitizer_common.h @@ -19,14 +19,24 @@ namespace __sanitizer { // Constants. -const uptr kWordSize = __WORDSIZE / 8; +const uptr kWordSize = SANITIZER_WORDSIZE / 8; const uptr kWordSizeInBits = 8 * kWordSize; -const uptr kPageSizeBits = 12; -const uptr kPageSize = 1UL << kPageSizeBits; +#if defined(__powerpc__) || defined(__powerpc64__) +// Current PPC64 kernels use 64K pages sizes, but they can be +// configured with 4K or even other sizes. +// We may want to use getpagesize() or sysconf(_SC_PAGESIZE) here rather than +// hardcoding the values, but today these values need to be compile-time +// constants. +const uptr kPageSize = 1UL << 16; +const uptr kCacheLineSize = 128; +const uptr kMmapGranularity = kPageSize; +#elif !defined(_WIN32) +const uptr kPageSize = 1UL << 12; const uptr kCacheLineSize = 64; -#ifndef _WIN32 const uptr kMmapGranularity = kPageSize; #else +const uptr kPageSize = 1UL << 12; +const uptr kCacheLineSize = 64; const uptr kMmapGranularity = 1UL << 16; #endif @@ -96,6 +106,7 @@ void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback); // IO void RawWrite(const char *buffer); +bool PrintsToTty(); void Printf(const char *format, ...); void Report(const char *format, ...); void SetPrintfAndReportCallback(void (*callback)(const char *)); @@ -114,6 +125,7 @@ void *MapFileToMemory(const char *file_name, uptr *buff_size); // OS void DisableCoreDumper(); void DumpProcessMap(); +bool FileExists(const char *filename); const char *GetEnv(const char *name); const char *GetPwd(); void ReExec(); @@ -170,7 +182,7 @@ INLINE int ToLower(int c) { return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c; } -#if __WORDSIZE == 64 +#if SANITIZER_WORDSIZE == 64 # define FIRST_32_SECOND_64(a, b) (b) #else # define FIRST_32_SECOND_64(a, b) (a) diff --git a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h index da4d049e2c6..a6795c6720b 100644 --- a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h +++ b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h @@ -22,8 +22,7 @@ using namespace __sanitizer; // NOLINT #define WEAK SANITIZER_WEAK_ATTRIBUTE // Platform-specific defs. -#if defined(_WIN32) -typedef unsigned long DWORD; // NOLINT +#if defined(_MSC_VER) # define ALWAYS_INLINE __declspec(forceinline) // FIXME(timurrrr): do we need this on Windows? # define ALIAS(x) @@ -33,7 +32,11 @@ typedef unsigned long DWORD; // NOLINT # define NORETURN __declspec(noreturn) # define THREADLOCAL __declspec(thread) # define NOTHROW -#else // _WIN32 +# define LIKELY(x) (x) +# define UNLIKELY(x) (x) +# define UNUSED +# define USED +#else // _MSC_VER # define ALWAYS_INLINE __attribute__((always_inline)) # define ALIAS(x) __attribute__((alias(x))) # define ALIGNED(x) __attribute__((aligned(x))) @@ -41,22 +44,15 @@ typedef unsigned long DWORD; // NOLINT # define NOINLINE __attribute__((noinline)) # define NORETURN __attribute__((noreturn)) # define THREADLOCAL __thread -# ifdef __cplusplus -# define NOTHROW throw() -# else -# define NOTHROW __attribute__((__nothrow__)) -#endif -#endif // _WIN32 - -// We have no equivalent of these on Windows. -#ifndef _WIN32 +# define NOTHROW throw() # define LIKELY(x) __builtin_expect(!!(x), 1) # define UNLIKELY(x) __builtin_expect(!!(x), 0) # define UNUSED __attribute__((unused)) # define USED __attribute__((used)) -#endif +#endif // _MSC_VER #if defined(_WIN32) +typedef unsigned long DWORD; // NOLINT typedef DWORD thread_return_t; # define THREAD_CALLING_CONV __stdcall #else // _WIN32 @@ -65,15 +61,11 @@ typedef void* thread_return_t; #endif // _WIN32 typedef thread_return_t (THREAD_CALLING_CONV *thread_callback_t)(void* arg); -// If __WORDSIZE was undefined by the platform, define it in terms of the -// compiler built-ins __LP64__ and _WIN64. -#ifndef __WORDSIZE -# if __LP64__ || defined(_WIN64) -# define __WORDSIZE 64 -# else -# define __WORDSIZE 32 -# endif -#endif // __WORDSIZE +#if __LP64__ || defined(_WIN64) +# define SANITIZER_WORDSIZE 64 +#else +# define SANITIZER_WORDSIZE 32 +#endif // NOTE: Functions below must be defined in each run-time. namespace __sanitizer { @@ -128,7 +120,12 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond, #define DCHECK_GE(a, b) #endif -#define UNIMPLEMENTED() CHECK("unimplemented" && 0) +#define UNREACHABLE(msg) do { \ + CHECK(0 && msg); \ + Die(); \ +} while (0) + +#define UNIMPLEMENTED() UNREACHABLE("unimplemented") #define COMPILER_CHECK(pred) IMPL_COMPILER_ASSERT(pred, __LINE__) @@ -142,13 +139,13 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond, // have stdint.h (like in Visual Studio 9). #undef __INT64_C #undef __UINT64_C -#if __WORDSIZE == 64 +#if SANITIZER_WORDSIZE == 64 # define __INT64_C(c) c ## L # define __UINT64_C(c) c ## UL #else # define __INT64_C(c) c ## LL # define __UINT64_C(c) c ## ULL -#endif // __WORDSIZE == 64 +#endif // SANITIZER_WORDSIZE == 64 #undef INT32_MIN #define INT32_MIN (-2147483647-1) #undef INT32_MAX diff --git a/libsanitizer/sanitizer_common/sanitizer_libc.cc b/libsanitizer/sanitizer_common/sanitizer_libc.cc index 21869bc4846..4d43cd7d013 100644 --- a/libsanitizer/sanitizer_common/sanitizer_libc.cc +++ b/libsanitizer/sanitizer_common/sanitizer_libc.cc @@ -42,6 +42,23 @@ void *internal_memcpy(void *dest, const void *src, uptr n) { return dest; } +void *internal_memmove(void *dest, const void *src, uptr n) { + char *d = (char*)dest; + char *s = (char*)src; + sptr i, signed_n = (sptr)n; + CHECK_GE(signed_n, 0); + if (d < s) { + for (i = 0; i < signed_n; ++i) + d[i] = s[i]; + } else { + if (d > s && signed_n > 0) + for (i = signed_n - 1; i >= 0 ; --i) { + d[i] = s[i]; + } + } + return dest; +} + void *internal_memset(void* s, int c, uptr n) { // The next line prevents Clang from making a call to memset() instead of the // loop below. diff --git a/libsanitizer/sanitizer_common/sanitizer_libc.h b/libsanitizer/sanitizer_common/sanitizer_libc.h index 13528511190..4aa4a279d40 100644 --- a/libsanitizer/sanitizer_common/sanitizer_libc.h +++ b/libsanitizer/sanitizer_common/sanitizer_libc.h @@ -27,6 +27,7 @@ s64 internal_atoll(const char *nptr); void *internal_memchr(const void *s, int c, uptr n); int internal_memcmp(const void* s1, const void* s2, uptr n); void *internal_memcpy(void *dest, const void *src, uptr n); +void *internal_memmove(void *dest, const void *src, uptr n); // Should not be used in performance-critical places. void *internal_memset(void *s, int c, uptr n); char* internal_strchr(const char *s, int c); @@ -52,7 +53,11 @@ int internal_munmap(void *addr, uptr length); // I/O typedef int fd_t; const fd_t kInvalidFd = -1; +const fd_t kStdinFd = 0; +const fd_t kStdoutFd = 1; +const fd_t kStderrFd = 2; int internal_close(fd_t fd); +int internal_isatty(fd_t fd); fd_t internal_open(const char *filename, bool write); uptr internal_read(fd_t fd, void *buf, uptr count); uptr internal_write(fd_t fd, const void *buf, uptr count); diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.cc b/libsanitizer/sanitizer_common/sanitizer_linux.cc index f2a0d39ca99..2145aa04113 100644 --- a/libsanitizer/sanitizer_common/sanitizer_linux.cc +++ b/libsanitizer/sanitizer_common/sanitizer_linux.cc @@ -30,9 +30,9 @@ #include <errno.h> // Are we using 32-bit or 64-bit syscalls? -// x32 (which defines __x86_64__) has __WORDSIZE == 32 +// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32 // but it still needs to use 64-bit syscalls. -#if defined(__x86_64__) || __WORDSIZE == 64 +#if defined(__x86_64__) || SANITIZER_WORDSIZE == 64 # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1 #else # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0 @@ -101,6 +101,20 @@ int internal_sched_yield() { } // ----------------- sanitizer_common.h +bool FileExists(const char *filename) { +#if SANITIZER_LINUX_USES_64BIT_SYSCALLS + struct stat st; + if (syscall(__NR_stat, filename, &st)) + return false; +#else + struct stat64 st; + if (syscall(__NR_stat64, filename, &st)) + return false; +#endif + // Sanity check: filename is a regular file. + return S_ISREG(st.st_mode); +} + uptr GetTid() { return syscall(__NR_gettid); } diff --git a/libsanitizer/sanitizer_common/sanitizer_mac.cc b/libsanitizer/sanitizer_common/sanitizer_mac.cc index 400cd21842b..aa313baff92 100644 --- a/libsanitizer/sanitizer_common/sanitizer_mac.cc +++ b/libsanitizer/sanitizer_common/sanitizer_mac.cc @@ -78,6 +78,14 @@ int internal_sched_yield() { } // ----------------- sanitizer_common.h +bool FileExists(const char *filename) { + struct stat st; + if (stat(filename, &st)) + return false; + // Sanity check: filename is a regular file. + return S_ISREG(st.st_mode); +} + uptr GetTid() { return reinterpret_cast<uptr>(pthread_self()); } diff --git a/libsanitizer/sanitizer_common/sanitizer_placement_new.h b/libsanitizer/sanitizer_common/sanitizer_placement_new.h index d149683b43d..e32d65702df 100644 --- a/libsanitizer/sanitizer_common/sanitizer_placement_new.h +++ b/libsanitizer/sanitizer_common/sanitizer_placement_new.h @@ -17,7 +17,7 @@ #include "sanitizer_internal_defs.h" namespace __sanitizer { -#if (__WORDSIZE == 64) || defined(__APPLE__) +#if (SANITIZER_WORDSIZE == 64) || defined(__APPLE__) typedef uptr operator_new_ptr_type; #else typedef u32 operator_new_ptr_type; diff --git a/libsanitizer/sanitizer_common/sanitizer_posix.cc b/libsanitizer/sanitizer_common/sanitizer_posix.cc index 8f71cfc049d..bd9270ecaa4 100644 --- a/libsanitizer/sanitizer_common/sanitizer_posix.cc +++ b/libsanitizer/sanitizer_common/sanitizer_posix.cc @@ -72,10 +72,15 @@ void UnmapOrDie(void *addr, uptr size) { } void *MmapFixedNoReserve(uptr fixed_addr, uptr size) { - return internal_mmap((void*)fixed_addr, size, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, - -1, 0); + void *p = internal_mmap((void*)(fixed_addr & ~(kPageSize - 1)), + RoundUpTo(size, kPageSize), + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, + -1, 0); + if (p == (void*)-1) + Report("ERROR: Failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n", + size, size, fixed_addr, errno); + return p; } void *Mprotect(uptr fixed_addr, uptr size) { @@ -182,6 +187,10 @@ int Atexit(void (*function)(void)) { #endif } +int internal_isatty(fd_t fd) { + return isatty(fd); +} + } // namespace __sanitizer #endif // __linux__ || __APPLE_ diff --git a/libsanitizer/sanitizer_common/sanitizer_printf.cc b/libsanitizer/sanitizer_common/sanitizer_printf.cc index da4dc7f53a1..5876fef04f3 100644 --- a/libsanitizer/sanitizer_common/sanitizer_printf.cc +++ b/libsanitizer/sanitizer_common/sanitizer_printf.cc @@ -43,7 +43,12 @@ static int AppendUnsigned(char **buff, const char *buff_end, u64 num, num_buffer[pos++] = num % base; num /= base; } while (num > 0); - while (pos < minimal_num_length) num_buffer[pos++] = 0; + if (pos < minimal_num_length) { + // Make sure compiler doesn't insert call to memset here. + internal_memset(&num_buffer[pos], 0, + sizeof(num_buffer[0]) * (minimal_num_length - pos)); + pos = minimal_num_length; + } int result = 0; while (pos-- > 0) { uptr digit = num_buffer[pos]; @@ -53,13 +58,16 @@ static int AppendUnsigned(char **buff, const char *buff_end, u64 num, return result; } -static int AppendSignedDecimal(char **buff, const char *buff_end, s64 num) { +static int AppendSignedDecimal(char **buff, const char *buff_end, s64 num, + u8 minimal_num_length) { int result = 0; if (num < 0) { result += AppendChar(buff, buff_end, '-'); num = -num; + if (minimal_num_length) + --minimal_num_length; } - result += AppendUnsigned(buff, buff_end, (u64)num, 10, 0); + result += AppendUnsigned(buff, buff_end, (u64)num, 10, minimal_num_length); return result; } @@ -77,14 +85,14 @@ static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) { int result = 0; result += AppendString(buff, buff_end, "0x"); result += AppendUnsigned(buff, buff_end, ptr_value, 16, - (__WORDSIZE == 64) ? 12 : 8); + (SANITIZER_WORDSIZE == 64) ? 12 : 8); return result; } int VSNPrintf(char *buff, int buff_length, const char *format, va_list args) { - static const char *kPrintfFormatsHelp = "Supported Printf formats: " - "%%[z]{d,u,x}; %%p; %%s; %%c\n"; + static const char *kPrintfFormatsHelp = + "Supported Printf formats: %%(0[0-9]*)?(z|ll)?{d,u,x}; %%p; %%s; %%c\n"; RAW_CHECK(format); RAW_CHECK(buff_length > 0); const char *buff_end = &buff[buff_length - 1]; @@ -96,42 +104,55 @@ int VSNPrintf(char *buff, int buff_length, continue; } cur++; + bool have_width = (*cur == '0'); + int width = 0; + if (have_width) { + while (*cur >= '0' && *cur <= '9') { + have_width = true; + width = width * 10 + *cur++ - '0'; + } + } bool have_z = (*cur == 'z'); cur += have_z; + bool have_ll = !have_z && (cur[0] == 'l' && cur[1] == 'l'); + cur += have_ll * 2; s64 dval; u64 uval; + bool have_flags = have_width | have_z | have_ll; switch (*cur) { case 'd': { - dval = have_z ? va_arg(args, sptr) - : va_arg(args, int); - result += AppendSignedDecimal(&buff, buff_end, dval); + dval = have_ll ? va_arg(args, s64) + : have_z ? va_arg(args, sptr) + : va_arg(args, int); + result += AppendSignedDecimal(&buff, buff_end, dval, width); break; } case 'u': case 'x': { - uval = have_z ? va_arg(args, uptr) - : va_arg(args, unsigned); + uval = have_ll ? va_arg(args, u64) + : have_z ? va_arg(args, uptr) + : va_arg(args, unsigned); result += AppendUnsigned(&buff, buff_end, uval, - (*cur == 'u') ? 10 : 16, 0); + (*cur == 'u') ? 10 : 16, width); break; } case 'p': { - RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp); + RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp); result += AppendPointer(&buff, buff_end, va_arg(args, uptr)); break; } case 's': { - RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp); + RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp); result += AppendString(&buff, buff_end, va_arg(args, char*)); break; } case 'c': { - RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp); + RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp); result += AppendChar(&buff, buff_end, va_arg(args, int)); break; } case '%' : { - RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp); + RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp); result += AppendChar(&buff, buff_end, '%'); break; } @@ -151,7 +172,7 @@ void SetPrintfAndReportCallback(void (*callback)(const char *)) { } void Printf(const char *format, ...) { - const int kLen = 1024 * 4; + const int kLen = 16 * 1024; InternalScopedBuffer<char> buffer(kLen); va_list args; va_start(args, format); @@ -177,7 +198,7 @@ int internal_snprintf(char *buffer, uptr length, const char *format, ...) { // Like Printf, but prints the current PID before the output string. void Report(const char *format, ...) { - const int kLen = 1024 * 4; + const int kLen = 16 * 1024; InternalScopedBuffer<char> buffer(kLen); int needed_length = internal_snprintf(buffer.data(), kLen, "==%d== ", GetPid()); diff --git a/libsanitizer/sanitizer_common/sanitizer_procmaps.h b/libsanitizer/sanitizer_common/sanitizer_procmaps.h index 5e5e5ce89be..5541cfc0c63 100644 --- a/libsanitizer/sanitizer_common/sanitizer_procmaps.h +++ b/libsanitizer/sanitizer_common/sanitizer_procmaps.h @@ -23,7 +23,6 @@ class MemoryMappingLayout { bool GetObjectNameAndOffset(uptr addr, uptr *offset, char filename[], uptr filename_size) { UNIMPLEMENTED(); - return false; } }; diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc index 915c4b8050a..037a7c3f9c0 100644 --- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc +++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc @@ -31,7 +31,12 @@ static uptr patch_pc(uptr pc) { // Cancel Thumb bit. pc = pc & (~1); #endif +#if defined(__powerpc__) || defined(__powerpc64__) + // PCs are always 4 byte aligned. + return pc - 4; +#else return pc - 1; +#endif } static void PrintStackFramePrefix(uptr frame_num, uptr pc) { @@ -75,7 +80,8 @@ void StackTrace::PrintStack(const uptr *addr, uptr size, Printf(" %s\n", StripPathPrefix(buff.data(), strip_file_prefix)); frame_num++; } - } else if (symbolize) { + } + if (symbolize && addr_frames_num == 0) { // Use our own (online) symbolizer, if necessary. addr_frames_num = SymbolizeCode(pc, addr_frames.data(), addr_frames.size()); @@ -135,12 +141,20 @@ void StackTrace::FastUnwindStack(uptr pc, uptr bp, } } +void StackTrace::PopStackFrames(uptr count) { + CHECK(size >= count); + size -= count; + for (uptr i = 0; i < size; i++) { + trace[i] = trace[i + count]; + } +} + // On 32-bits we don't compress stack traces. // On 64-bits we compress stack traces: if a given pc differes slightly from // the previous one, we record a 31-bit offset instead of the full pc. SANITIZER_INTERFACE_ATTRIBUTE uptr StackTrace::CompressStack(StackTrace *stack, u32 *compressed, uptr size) { -#if __WORDSIZE == 32 +#if SANITIZER_WORDSIZE == 32 // Don't compress, just copy. uptr res = 0; for (uptr i = 0; i < stack->size && i < size; i++) { @@ -181,7 +195,7 @@ uptr StackTrace::CompressStack(StackTrace *stack, u32 *compressed, uptr size) { compressed[c_index] = 0; if (c_index + 1 < size) compressed[c_index + 1] = 0; -#endif // __WORDSIZE +#endif // SANITIZER_WORDSIZE // debug-only code #if 0 @@ -204,7 +218,7 @@ uptr StackTrace::CompressStack(StackTrace *stack, u32 *compressed, uptr size) { SANITIZER_INTERFACE_ATTRIBUTE void StackTrace::UncompressStack(StackTrace *stack, u32 *compressed, uptr size) { -#if __WORDSIZE == 32 +#if SANITIZER_WORDSIZE == 32 // Don't uncompress, just copy. stack->size = 0; for (uptr i = 0; i < size && i < kStackTraceMax; i++) { @@ -239,7 +253,7 @@ void StackTrace::UncompressStack(StackTrace *stack, stack->trace[stack->size++] = pc; prev_pc = pc; } -#endif // __WORDSIZE +#endif // SANITIZER_WORDSIZE } } // namespace __sanitizer diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.h b/libsanitizer/sanitizer_common/sanitizer_stacktrace.h index a7934c65e1e..b36a1a082c5 100644 --- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.h +++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.h @@ -43,6 +43,8 @@ struct StackTrace { void FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom); + void PopStackFrames(uptr count); + static uptr GetCurrentPc(); static uptr CompressStack(StackTrace *stack, diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer.cc index 66ac3c8a246..efd1e816832 100644 --- a/libsanitizer/sanitizer_common/sanitizer_symbolizer.cc +++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer.cc @@ -291,7 +291,8 @@ class Symbolizer { } } - static const uptr kMaxNumberOfModuleContexts = 4096; + // 16K loaded modules should be enough for everyone. + static const uptr kMaxNumberOfModuleContexts = 1 << 14; LoadedModule *modules_; // Array of module descriptions is leaked. uptr n_modules_; diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer.h b/libsanitizer/sanitizer_common/sanitizer_symbolizer.h index 83adf025282..13ec83f2cbf 100644 --- a/libsanitizer/sanitizer_common/sanitizer_symbolizer.h +++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer.h @@ -77,7 +77,7 @@ class LoadedModule { }; char *full_name_; uptr base_address_; - static const uptr kMaxNumberOfAddressRanges = 8; + static const uptr kMaxNumberOfAddressRanges = 6; AddressRange ranges_[kMaxNumberOfAddressRanges]; uptr n_ranges_; }; diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc index 50e39a75c3a..bb1c40f9613 100644 --- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc +++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc @@ -21,6 +21,7 @@ #include <poll.h> #include <sys/socket.h> #include <sys/types.h> +#include <sys/wait.h> #include <unistd.h> #if !defined(__ANDROID__) && !defined(ANDROID) @@ -29,8 +30,15 @@ namespace __sanitizer { +static const int kSymbolizerStartupTimeMillis = 10; + bool StartSymbolizerSubprocess(const char *path_to_symbolizer, int *input_fd, int *output_fd) { + if (!FileExists(path_to_symbolizer)) { + Report("WARNING: invalid path to external symbolizer!\n"); + return false; + } + int *infd = NULL; int *outfd = NULL; // The client program may close its stdin and/or stdout and/or stderr @@ -97,13 +105,23 @@ bool StartSymbolizerSubprocess(const char *path_to_symbolizer, internal_close(infd[1]); *input_fd = infd[0]; *output_fd = outfd[1]; + + // Check that symbolizer subprocess started successfully. + int pid_status; + SleepForMillis(kSymbolizerStartupTimeMillis); + int exited_pid = waitpid(pid, &pid_status, WNOHANG); + if (exited_pid != 0) { + // Either waitpid failed, or child has already exited. + Report("WARNING: external symbolizer didn't start up correctly!\n"); + return false; + } + return true; } #if defined(__ANDROID__) || defined(ANDROID) uptr GetListOfModules(LoadedModule *modules, uptr max_modules) { UNIMPLEMENTED(); - return 0; } #else // ANDROID typedef ElfW(Phdr) Elf_Phdr; diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.cc index c5ca616d89d..a1b931b737e 100644 --- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.cc +++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_mac.cc @@ -18,12 +18,10 @@ namespace __sanitizer { bool StartSymbolizerSubprocess(const char *path_to_symbolizer, int *input_fd, int *output_fd) { UNIMPLEMENTED(); - return false; } uptr GetListOfModules(LoadedModule *modules, uptr max_modules) { UNIMPLEMENTED(); - return 0; } } // namespace __sanitizer diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc index 7e6ba53e128..3b81e794e59 100644 --- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc +++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_win.cc @@ -20,12 +20,10 @@ namespace __sanitizer { bool StartSymbolizerSubprocess(const char *path_to_symbolizer, int *input_fd, int *output_fd) { UNIMPLEMENTED(); - return false; } uptr GetListOfModules(LoadedModule *modules, uptr max_modules) { UNIMPLEMENTED(); - return 0; }; } // namespace __sanitizer diff --git a/libsanitizer/sanitizer_common/sanitizer_win.cc b/libsanitizer/sanitizer_common/sanitizer_win.cc index 314852304d8..03a5c204c66 100644 --- a/libsanitizer/sanitizer_common/sanitizer_win.cc +++ b/libsanitizer/sanitizer_common/sanitizer_win.cc @@ -10,6 +10,9 @@ // sanitizer_libc.h. //===----------------------------------------------------------------------===// #ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#define NOGDI +#include <stdlib.h> #include <windows.h> #include "sanitizer_common.h" @@ -18,6 +21,10 @@ namespace __sanitizer { // --------------------- sanitizer_common.h +bool FileExists(const char *filename) { + UNIMPLEMENTED(); +} + int GetPid() { return GetProcessId(GetCurrentProcess()); } @@ -39,7 +46,6 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, *stack_bottom = (uptr)mbi.AllocationBase; } - void *MmapOrDie(uptr size, const char *mem_type) { void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (rv == 0) { @@ -59,8 +65,12 @@ void UnmapOrDie(void *addr, uptr size) { } void *MmapFixedNoReserve(uptr fixed_addr, uptr size) { - return VirtualAlloc((LPVOID)fixed_addr, size, - MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + void *p = VirtualAlloc((LPVOID)fixed_addr, size, + MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + if (p == 0) + Report("ERROR: Failed to allocate 0x%zx (%zd) bytes at %p (%d)\n", + size, size, fixed_addr, GetLastError()); + return p; } void *Mprotect(uptr fixed_addr, uptr size) { @@ -75,7 +85,6 @@ bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) { void *MapFileToMemory(const char *file_name, uptr *buff_size) { UNIMPLEMENTED(); - return 0; } const char *GetEnv(const char *name) { @@ -96,7 +105,6 @@ const char *GetEnv(const char *name) { const char *GetPwd() { UNIMPLEMENTED(); - return 0; } void DumpProcessMap() { @@ -113,7 +121,6 @@ void ReExec() { bool StackSizeIsUnlimited() { UNIMPLEMENTED(); - return false; } void SetStackSizeLimitInBytes(uptr limit) { @@ -137,39 +144,40 @@ void Abort() { _exit(-1); // abort is not NORETURN on Windows. } +#ifndef SANITIZER_GO int Atexit(void (*function)(void)) { return atexit(function); } +#endif // ------------------ sanitizer_libc.h void *internal_mmap(void *addr, uptr length, int prot, int flags, int fd, u64 offset) { UNIMPLEMENTED(); - return 0; } int internal_munmap(void *addr, uptr length) { UNIMPLEMENTED(); - return 0; } int internal_close(fd_t fd) { UNIMPLEMENTED(); - return 0; +} + +int internal_isatty(fd_t fd) { + UNIMPLEMENTED(); } fd_t internal_open(const char *filename, bool write) { UNIMPLEMENTED(); - return 0; } uptr internal_read(fd_t fd, void *buf, uptr count) { UNIMPLEMENTED(); - return 0; } uptr internal_write(fd_t fd, const void *buf, uptr count) { - if (fd != 2) + if (fd != kStderrFd) UNIMPLEMENTED(); HANDLE err = GetStdHandle(STD_ERROR_HANDLE); if (err == 0) @@ -182,21 +190,18 @@ uptr internal_write(fd_t fd, const void *buf, uptr count) { uptr internal_filesize(fd_t fd) { UNIMPLEMENTED(); - return 0; } int internal_dup2(int oldfd, int newfd) { UNIMPLEMENTED(); - return 0; } uptr internal_readlink(const char *path, char *buf, uptr bufsize) { UNIMPLEMENTED(); - return 0; } int internal_sched_yield() { - UNIMPLEMENTED(); + Sleep(0); return 0; } |