diff options
author | Pirama Arumuga Nainar <pirama@google.com> | 2015-05-06 11:49:53 -0700 |
---|---|---|
committer | Pirama Arumuga Nainar <pirama@google.com> | 2015-05-13 15:23:54 -0700 |
commit | 259f7063e3e4c4b94dded1e90ab0a943d0fa737b (patch) | |
tree | b205dd574776abc80476c5077fce8849087dd74d /lib/sanitizer_common | |
parent | 76b747196ee83659ec43d23ea01cbcf0fd776178 (diff) | |
download | compiler-rt-259f7063e3e4c4b94dded1e90ab0a943d0fa737b.tar.gz |
Update aosp/master compiler-rt for rebase to r235153
Change-Id: I7c900e78d263fe0f574369e8383ccac7e36f5c3b
Diffstat (limited to 'lib/sanitizer_common')
39 files changed, 753 insertions, 567 deletions
diff --git a/lib/sanitizer_common/Android.mk b/lib/sanitizer_common/Android.mk index 1af23245e..9436a435a 100644 --- a/lib/sanitizer_common/Android.mk +++ b/lib/sanitizer_common/Android.mk @@ -72,6 +72,9 @@ san_rtl_cppflags := \ san_rtl_c_includes := \ external/compiler-rt/lib \ +################################################################################ +# Host modules + ifneq ($(HOST_OS),darwin) include $(CLEAR_VARS) diff --git a/lib/sanitizer_common/CMakeLists.txt b/lib/sanitizer_common/CMakeLists.txt index 5b32b6ad9..d213953ed 100644 --- a/lib/sanitizer_common/CMakeLists.txt +++ b/lib/sanitizer_common/CMakeLists.txt @@ -83,6 +83,7 @@ set(SANITIZER_HEADERS sanitizer_platform.h sanitizer_platform_interceptors.h sanitizer_platform_limits_posix.h + sanitizer_posix.h sanitizer_procmaps.h sanitizer_quarantine.h sanitizer_report_decorator.h @@ -111,6 +112,10 @@ else() SANITIZER_NEEDS_SEGV=1) endif() +include(CheckIncludeFile) +append_have_file_definition(rpc/xdr.h HAVE_RPC_XDR_H SANITIZER_COMMON_DEFINITIONS) +append_have_file_definition(tirpc/rpc/xdr.h HAVE_TIRPC_RPC_XDR_H SANITIZER_COMMON_DEFINITIONS) + set(SANITIZER_CFLAGS ${SANITIZER_COMMON_CFLAGS}) append_no_rtti_flag(SANITIZER_CFLAGS) diff --git a/lib/sanitizer_common/sanitizer_allocator.h b/lib/sanitizer_common/sanitizer_allocator.h index b5105f8c2..deaffef71 100644 --- a/lib/sanitizer_common/sanitizer_allocator.h +++ b/lib/sanitizer_common/sanitizer_allocator.h @@ -323,7 +323,7 @@ class SizeClassAllocator64 { void Init() { CHECK_EQ(kSpaceBeg, - reinterpret_cast<uptr>(Mprotect(kSpaceBeg, kSpaceSize))); + reinterpret_cast<uptr>(MmapNoAccess(kSpaceBeg, kSpaceSize))); MapWithCallback(kSpaceEnd, AdditionalSize()); } diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc index 956fc9935..8185c81c2 100644 --- a/lib/sanitizer_common/sanitizer_common.cc +++ b/lib/sanitizer_common/sanitizer_common.cc @@ -54,18 +54,17 @@ void ReportFile::ReopenIfNecessary() { if (fd_pid == pid) return; else - internal_close(fd); + CloseFile(fd); } internal_snprintf(full_path, kMaxPathLength, "%s.%zu", path_prefix, pid); - uptr openrv = OpenFile(full_path, WrOnly); - if (internal_iserror(openrv)) { + fd = OpenFile(full_path, WrOnly); + if (fd == kInvalidFd) { const char *ErrorMsgPrefix = "ERROR: Can't open file: "; - internal_write(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix)); - internal_write(kStderrFd, full_path, internal_strlen(full_path)); + WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix)); + WriteToFile(kStderrFd, full_path, internal_strlen(full_path)); Die(); } - fd = openrv; fd_pid = pid; } @@ -82,7 +81,7 @@ void ReportFile::SetReportPath(const char *path) { SpinMutexLock l(mu); if (fd != kStdoutFd && fd != kStderrFd && fd != kInvalidFd) - internal_close(fd); + CloseFile(fd); fd = kInvalidFd; if (internal_strcmp(path, "stdout") == 0) { fd = kStdoutFd; @@ -136,7 +135,7 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond, } uptr ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size, - uptr max_len, int *errno_p) { + uptr max_len, error_t *errno_p) { uptr PageSize = GetPageSizeCached(); uptr kMinFileLen = PageSize; uptr read_len = 0; @@ -144,9 +143,8 @@ uptr ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size, *buff_size = 0; // The files we usually open are not seekable, so try different buffer sizes. for (uptr size = kMinFileLen; size <= max_len; size *= 2) { - uptr openrv = OpenFile(file_name, RdOnly); - if (internal_iserror(openrv, errno_p)) return 0; - fd_t fd = openrv; + fd_t fd = OpenFile(file_name, RdOnly, errno_p); + if (fd == kInvalidFd) return 0; UnmapOrDie(*buff, *buff_size); *buff = (char*)MmapOrDie(size, __func__); *buff_size = size; @@ -154,8 +152,8 @@ uptr ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size, read_len = 0; bool reached_eof = false; while (read_len + PageSize <= size) { - uptr just_read = internal_read(fd, *buff + read_len, PageSize); - if (internal_iserror(just_read, errno_p)) { + uptr just_read; + if (!ReadFromFile(fd, *buff + read_len, PageSize, &just_read, errno_p)) { UnmapOrDie(*buff, *buff_size); return 0; } @@ -165,7 +163,7 @@ uptr ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size, } read_len += just_read; } - internal_close(fd); + CloseFile(fd); if (reached_eof) // We've read the whole file. break; } @@ -219,8 +217,15 @@ const char *StripPathPrefix(const char *filepath, const char *StripModuleName(const char *module) { if (module == 0) return 0; - if (const char *slash_pos = internal_strrchr(module, '/')) + if (SANITIZER_WINDOWS) { + // On Windows, both slash and backslash are possible. + // Pick the one that goes last. + if (const char *bslash_pos = internal_strrchr(module, '\\')) + return StripModuleName(bslash_pos + 1); + } + if (const char *slash_pos = internal_strrchr(module, '/')) { return slash_pos + 1; + } return module; } @@ -243,14 +248,15 @@ void ReportErrorSummary(const char *error_type, const AddressInfo &info) { } #endif -LoadedModule::LoadedModule(const char *module_name, uptr base_address) { +void LoadedModule::set(const char *module_name, uptr base_address) { + clear(); full_name_ = internal_strdup(module_name); base_address_ = base_address; - ranges_.clear(); } void LoadedModule::clear() { InternalFree(full_name_); + full_name_ = nullptr; while (!ranges_.empty()) { AddressRange *r = ranges_.front(); ranges_.pop_front(); diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index 0dfa81593..2e920c85e 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -39,6 +39,9 @@ const uptr kWordSizeInBits = 8 * kWordSize; const uptr kMaxPathLength = 4096; +// 16K loaded modules should be enough for everyone. +static const uptr kMaxNumberOfModules = 1 << 14; + const uptr kMaxThreadStackSize = 1 << 30; // 1Gb extern const char *SanitizerToolName; // Can be changed by the tool. @@ -69,9 +72,13 @@ void UnmapOrDie(void *addr, uptr size); void *MmapFixedNoReserve(uptr fixed_addr, uptr size); void *MmapNoReserveOrDie(uptr size, const char *mem_type); void *MmapFixedOrDie(uptr fixed_addr, uptr size); -void *Mprotect(uptr fixed_addr, uptr size); +void *MmapNoAccess(uptr fixed_addr, uptr size); // Map aligned chunk of address space; size and alignment are powers of two. void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type); +// Disallow access to a memory range. Use MmapNoAccess to allocate an +// unaccessible memory. +bool MprotectNoAccess(uptr addr, uptr size); + // Used to check if we can map shadow memory to a fixed location. bool MemoryRangeIsAvailable(uptr range_start, uptr range_end); void FlushUnneededShadowMemory(uptr addr, uptr size); @@ -160,7 +167,7 @@ extern StaticSpinMutex CommonSanitizerReportMutex; struct ReportFile { void Write(const char *buffer, uptr length); - bool PrintsToTty(); + bool SupportsColors(); void SetReportPath(const char *path); // Don't use fields directly. They are only declared public to allow @@ -193,18 +200,33 @@ enum FileAccessMode { RdWr }; -uptr OpenFile(const char *filename, FileAccessMode mode); +// 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); + +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', // Returns the number of read bytes or 0 if file can not be opened. uptr ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size, - uptr max_len, int *errno_p = nullptr); + uptr max_len, error_t *errno_p = nullptr); // Maps given file to virtual memory, and returns pointer to it -// (or NULL if the mapping failes). Stores the size of mmaped region +// (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, uptr fd, uptr offset); +void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, uptr offset); bool IsAccessibleMemoryRange(uptr beg, uptr size); @@ -548,8 +570,8 @@ uptr InternalBinarySearch(const Container &v, uptr first, uptr last, // executable or a shared object). class LoadedModule { public: - LoadedModule() : full_name_(nullptr), base_address_(0) {} - LoadedModule(const char *module_name, uptr base_address); + LoadedModule() : full_name_(nullptr), base_address_(0) { ranges_.clear(); } + void set(const char *module_name, uptr base_address); void clear(); void addAddressRange(uptr beg, uptr end, bool executable); bool containsAddress(uptr address) const; diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc index f724115f7..69c1cf83b 100644 --- a/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -102,6 +102,13 @@ #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (0) #endif +#define COMMON_INTERCEPTOR_READ_STRING_OF_LEN(ctx, s, len, n) \ + COMMON_INTERCEPTOR_READ_RANGE((ctx), (s), \ + common_flags()->strict_string_checks ? (len) + 1 : (n) ) + +#define COMMON_INTERCEPTOR_READ_STRING(ctx, s, n) \ + COMMON_INTERCEPTOR_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n)) + #ifndef COMMON_INTERCEPTOR_ON_DLOPEN #define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) {} #endif @@ -159,7 +166,8 @@ UNUSED static void DeleteInterceptorMetadata(void *addr) { INTERCEPTOR(char*, textdomain, const char *domainname) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, textdomain, domainname); - char* domain = REAL(textdomain)(domainname); + COMMON_INTERCEPTOR_READ_STRING(ctx, domainname, 0); + char *domain = REAL(textdomain)(domainname); if (domain) { COMMON_INTERCEPTOR_INITIALIZE_RANGE(domain, REAL(strlen)(domain) + 1); } @@ -185,8 +193,8 @@ INTERCEPTOR(int, strcmp, const char *s1, const char *s2) { c2 = (unsigned char)s2[i]; if (c1 != c2 || c1 == '\0') break; } - COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, i + 1); - COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, i + 1); + COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1); + COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1); return CharCmpX(c1, c2); } @@ -231,8 +239,8 @@ INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) { c2 = (unsigned char)s2[i]; if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break; } - COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, i + 1); - COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, i + 1); + COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1); + COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1); return CharCaseCmp(c1, c2); } @@ -727,12 +735,12 @@ INTERCEPTOR(char *, strptime, char *s, char *format, __sanitizer_tm *tm) { // its metadata. See // https://code.google.com/p/address-sanitizer/issues/detail?id=321. char *res = REAL(strptime)(s, format, tm); - if (res) { - COMMON_INTERCEPTOR_READ_RANGE(ctx, s, res - s); + COMMON_INTERCEPTOR_READ_STRING(ctx, s, res ? res - s : 0); + if (res && tm) { // Do not call unpoison_tm here, because strptime does not, in fact, // initialize the entire struct tm. For example, tm_zone pointer is left // uninitialized. - if (tm) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm)); } return res; } @@ -1513,6 +1521,7 @@ INTERCEPTOR(int, glob, const char *pattern, int flags, __sanitizer_glob_t *pglob) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob); + COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0); __sanitizer_glob_t glob_copy = { 0, 0, 0, 0, wrapped_gl_closedir, wrapped_gl_readdir, @@ -1543,6 +1552,7 @@ INTERCEPTOR(int, glob64, const char *pattern, int flags, __sanitizer_glob_t *pglob) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob); + COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0); __sanitizer_glob_t glob_copy = { 0, 0, 0, 0, wrapped_gl_closedir, wrapped_gl_readdir, @@ -1689,6 +1699,7 @@ INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) { INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, inet_pton, af, src, dst); + COMMON_INTERCEPTOR_READ_STRING(ctx, src, 0); // FIXME: figure out read size based on the address family. // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See @@ -2359,6 +2370,37 @@ INTERCEPTOR(char *, get_current_dir_name, int fake) { #define INIT_GET_CURRENT_DIR_NAME #endif +UNUSED static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) { + CHECK(endptr); + if (nptr == *endptr) { + // No digits were found at strtol call, we need to find out the last + // symbol accessed by strtoll on our own. + // We get this symbol by skipping leading blanks and optional +/- sign. + while (IsSpace(*nptr)) nptr++; + if (*nptr == '+' || *nptr == '-') nptr++; + *endptr = const_cast<char *>(nptr); + } + CHECK(*endptr >= nptr); +} + +UNUSED static inline void StrtolFixAndCheck(void *ctx, const char *nptr, + char **endptr, char *real_endptr, int base) { + if (endptr != 0) { + *endptr = real_endptr; + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr)); + } + // If base has unsupported value, strtol can exit with EINVAL + // without reading any characters. So do additional checks only + // if base is valid. + bool is_valid_base = (base == 0) || (2 <= base && base <= 36); + if (is_valid_base) { + FixRealStrtolEndptr(nptr, &real_endptr); + } + COMMON_INTERCEPTOR_READ_STRING(ctx, nptr, is_valid_base ? + (real_endptr - nptr) + 1 : 0); +} + + #if SANITIZER_INTERCEPT_STRTOIMAX INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) { void *ctx; @@ -2366,8 +2408,9 @@ INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://code.google.com/p/address-sanitizer/issues/detail?id=321. - INTMAX_T res = REAL(strtoimax)(nptr, endptr, base); - if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr)); + char *real_endptr; + INTMAX_T res = REAL(strtoimax)(nptr, &real_endptr, base); + StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); return res; } @@ -2377,8 +2420,9 @@ INTERCEPTOR(INTMAX_T, strtoumax, const char *nptr, char **endptr, int base) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://code.google.com/p/address-sanitizer/issues/detail?id=321. - INTMAX_T res = REAL(strtoumax)(nptr, endptr, base); - if (endptr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr)); + char *real_endptr; + INTMAX_T res = REAL(strtoumax)(nptr, &real_endptr, base); + StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); return res; } @@ -3642,6 +3686,7 @@ INTERCEPTOR(char *, tempnam, char *dir, char *pfx) { INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name); + COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0); COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name); return REAL(pthread_setname_np)(thread, name); } @@ -4699,6 +4744,7 @@ INTERCEPTOR(int, fclose, __sanitizer_FILE *fp) { INTERCEPTOR(void*, dlopen, const char *filename, int flag) { void *ctx; COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlopen, filename, flag); + if (filename) COMMON_INTERCEPTOR_READ_STRING(ctx, filename, 0); COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag); void *res = REAL(dlopen)(filename, flag); COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res); diff --git a/lib/sanitizer_common/sanitizer_common_libcdep.cc b/lib/sanitizer_common/sanitizer_common_libcdep.cc index 9622e60c2..1b65bced7 100644 --- a/lib/sanitizer_common/sanitizer_common_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_common_libcdep.cc @@ -17,12 +17,16 @@ #include "sanitizer_stacktrace.h" #include "sanitizer_symbolizer.h" +#if SANITIZER_POSIX +#include "sanitizer_posix.h" +#endif + namespace __sanitizer { -bool ReportFile::PrintsToTty() { +bool ReportFile::SupportsColors() { SpinMutexLock l(mu); ReopenIfNecessary(); - return internal_isatty(fd) != 0; + return SupportsColoredOutput(fd); } bool ColorizeReports() { @@ -33,7 +37,7 @@ bool ColorizeReports() { const char *flag = common_flags()->color; return internal_strcmp(flag, "always") == 0 || - (internal_strcmp(flag, "auto") == 0 && report_file.PrintsToTty()); + (internal_strcmp(flag, "auto") == 0 && report_file.SupportsColors()); } static void (*sandboxing_callback)(); @@ -113,12 +117,13 @@ void BackgroundThread(void *arg) { } void MaybeStartBackgroudThread() { - if (!SANITIZER_LINUX) return; // Need to implement/test on other platforms. +#if SANITIZER_LINUX // Need to implement/test on other platforms. // Start the background thread if one of the rss limits is given. if (!common_flags()->hard_rss_limit_mb && !common_flags()->soft_rss_limit_mb) return; if (!&real_pthread_create) return; // Can't spawn the thread anyway. internal_start_thread(BackgroundThread, nullptr); +#endif } } // namespace __sanitizer diff --git a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc index 94863c6ef..2c7c7e090 100644 --- a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc @@ -63,7 +63,7 @@ static atomic_uintptr_t coverage_counter; // dump current memory layout to another file. static bool cov_sandboxed = false; -static int cov_fd = kInvalidFd; +static fd_t cov_fd = kInvalidFd; static unsigned int cov_max_block_size = 0; static bool coverage_enabled = false; static const char *coverage_dir; @@ -109,7 +109,8 @@ class CoverageData { // Maximal size pc array may ever grow. // We MmapNoReserve this space to ensure that the array is contiguous. - static const uptr kPcArrayMaxSize = FIRST_32_SECOND_64(1 << 26, 1 << 27); + static const uptr kPcArrayMaxSize = + FIRST_32_SECOND_64(1 << (SANITIZER_ANDROID ? 24 : 26), 1 << 27); // The amount file mapping for the pc array is grown by. static const uptr kPcArrayMmapSize = 64 * 1024; @@ -123,7 +124,7 @@ class CoverageData { // Current file mapped size of the pc array. uptr pc_array_mapped_size; // Descriptor of the file mapped pc array. - int pc_fd; + fd_t pc_fd; // Vector of coverage guard arrays, protected by mu. InternalMmapVectorNoCtor<s32*> guard_array_vec; @@ -176,8 +177,8 @@ void CoverageData::DirectOpen() { internal_snprintf((char *)path.data(), path.size(), "%s/%zd.sancov.raw", coverage_dir, internal_getpid()); pc_fd = OpenFile(path.data(), RdWr); - if (internal_iserror(pc_fd)) { - Report(" Coverage: failed to open %s for reading/writing\n", path.data()); + if (pc_fd == kInvalidFd) { + Report("Coverage: failed to open %s for reading/writing\n", path.data()); Die(); } @@ -210,8 +211,9 @@ void CoverageData::Enable() { tr_event_array = reinterpret_cast<u32 *>(MmapNoReserveOrDie( sizeof(tr_event_array[0]) * kTrEventArrayMaxSize + GetMmapGranularity(), "CovInit::tr_event_array")); - Mprotect(reinterpret_cast<uptr>(&tr_event_array[kTrEventArrayMaxSize]), - GetMmapGranularity()); + MprotectNoAccess( + reinterpret_cast<uptr>(&tr_event_array[kTrEventArrayMaxSize]), + GetMmapGranularity()); tr_event_array_size = kTrEventArrayMaxSize; tr_event_pointer = tr_event_array; @@ -229,22 +231,22 @@ void CoverageData::InitializeGuardArray(s32 *guards) { void CoverageData::Disable() { if (pc_array) { - internal_munmap(pc_array, sizeof(uptr) * kPcArrayMaxSize); + UnmapOrDie(pc_array, sizeof(uptr) * kPcArrayMaxSize); pc_array = nullptr; } if (cc_array) { - internal_munmap(cc_array, sizeof(uptr *) * kCcArrayMaxSize); + UnmapOrDie(cc_array, sizeof(uptr *) * kCcArrayMaxSize); cc_array = nullptr; } if (tr_event_array) { - internal_munmap(tr_event_array, - sizeof(tr_event_array[0]) * kTrEventArrayMaxSize + - GetMmapGranularity()); + UnmapOrDie(tr_event_array, + sizeof(tr_event_array[0]) * kTrEventArrayMaxSize + + GetMmapGranularity()); tr_event_array = nullptr; tr_event_pointer = nullptr; } if (pc_fd != kInvalidFd) { - internal_close(pc_fd); + CloseFile(pc_fd); pc_fd = kInvalidFd; } } @@ -338,9 +340,8 @@ void CoverageData::UpdateModuleNameVec(uptr caller_pc, uptr range_beg, const char *module_name = sym->GetModuleNameForPc(caller_pc); if (!module_name) return; if (module_name_vec.empty() || - internal_strcmp(module_name_vec.back().copied_module_name, module_name)) - module_name_vec.push_back( - {internal_strdup(module_name), range_beg, range_end}); + module_name_vec.back().copied_module_name != module_name) + module_name_vec.push_back({module_name, range_beg, range_end}); else module_name_vec.back().end = range_end; } @@ -516,15 +517,15 @@ struct CovHeader { static void CovWritePacked(int pid, const char *module, const void *blob, unsigned int blob_size) { - if (cov_fd < 0) return; + if (cov_fd == kInvalidFd) return; unsigned module_name_length = internal_strlen(module); CovHeader header = {pid, module_name_length, blob_size}; if (cov_max_block_size == 0) { // Writing to a file. Just go ahead. - internal_write(cov_fd, &header, sizeof(header)); - internal_write(cov_fd, module, module_name_length); - internal_write(cov_fd, blob, blob_size); + WriteToFile(cov_fd, &header, sizeof(header)); + WriteToFile(cov_fd, module, module_name_length); + WriteToFile(cov_fd, blob, blob_size); } else { // Writing to a socket. We want to split the data into appropriately sized // blocks. @@ -547,8 +548,7 @@ static void CovWritePacked(int pid, const char *module, const void *blob, internal_memcpy(block_data_begin, blob_pos, payload_size); blob_pos += payload_size; ((CovHeader *)block.data())->data_length = payload_size; - internal_write(cov_fd, block.data(), - header_size_with_module + payload_size); + WriteToFile(cov_fd, block.data(), header_size_with_module + payload_size); } } } @@ -557,7 +557,7 @@ static void CovWritePacked(int pid, const char *module, const void *blob, // If packed = true and name == 0: <pid>.<sancov>.<packed>. // If packed = true and name != 0: <name>.<sancov>.<packed> (name is // user-supplied). -static int CovOpenFile(InternalScopedString *path, bool packed, +static fd_t CovOpenFile(InternalScopedString *path, bool packed, const char *name, const char *extension = "sancov") { path->clear(); if (!packed) { @@ -571,11 +571,9 @@ static int CovOpenFile(InternalScopedString *path, bool packed, else path->append("%s/%s.%s.packed", coverage_dir, name, extension); } - uptr fd = OpenFile(path->data(), WrOnly); - if (internal_iserror(fd)) { - Report(" SanitizerCoverage: failed to open %s for writing\n", path->data()); - return -1; - } + fd_t fd = OpenFile(path->data(), WrOnly); + if (fd == kInvalidFd) + Report("SanitizerCoverage: failed to open %s for writing\n", path->data()); return fd; } @@ -595,34 +593,35 @@ void CoverageData::DumpTrace() { out.append("%s 0x%zx\n", module_name, module_address); } InternalScopedString path(kMaxPathLength); - int fd = CovOpenFile(&path, false, "trace-points"); - if (fd < 0) return; - internal_write(fd, out.data(), out.length()); - internal_close(fd); + fd_t fd = CovOpenFile(&path, false, "trace-points"); + if (fd == kInvalidFd) return; + WriteToFile(fd, out.data(), out.length()); + CloseFile(fd); fd = CovOpenFile(&path, false, "trace-compunits"); - if (fd < 0) return; + if (fd == kInvalidFd) return; out.clear(); for (uptr i = 0; i < comp_unit_name_vec.size(); i++) out.append("%s\n", comp_unit_name_vec[i].copied_module_name); - internal_write(fd, out.data(), out.length()); - internal_close(fd); + WriteToFile(fd, out.data(), out.length()); + CloseFile(fd); fd = CovOpenFile(&path, false, "trace-events"); - if (fd < 0) return; + if (fd == kInvalidFd) return; uptr bytes_to_write = max_idx * sizeof(tr_event_array[0]); u8 *event_bytes = reinterpret_cast<u8*>(tr_event_array); // The trace file could be huge, and may not be written with a single syscall. while (bytes_to_write) { - uptr actually_written = internal_write(fd, event_bytes, bytes_to_write); - if (actually_written <= bytes_to_write) { + uptr actually_written; + if (WriteToFile(fd, event_bytes, bytes_to_write, &actually_written) && + actually_written <= bytes_to_write) { bytes_to_write -= actually_written; event_bytes += actually_written; } else { break; } } - internal_close(fd); + CloseFile(fd); VReport(1, " CovDump: Trace: %zd PCs written\n", size()); VReport(1, " CovDump: Trace: %zd Events written\n", max_idx); } @@ -660,10 +659,10 @@ void CoverageData::DumpCallerCalleePairs() { } } InternalScopedString path(kMaxPathLength); - int fd = CovOpenFile(&path, false, "caller-callee"); - if (fd < 0) return; - internal_write(fd, out.data(), out.length()); - internal_close(fd); + fd_t fd = CovOpenFile(&path, false, "caller-callee"); + if (fd == kInvalidFd) return; + WriteToFile(fd, out.data(), out.length()); + CloseFile(fd); VReport(1, " CovDump: %zd caller-callee pairs written\n", total); } @@ -694,11 +693,11 @@ void CoverageData::DumpCounters() { CHECK_LE(r.beg, r.end); CHECK_LE(r.end, size()); const char *base_name = StripModuleName(r.copied_module_name); - int fd = + fd_t fd = CovOpenFile(&path, /* packed */ false, base_name, "counters-sancov"); - if (fd < 0) return; - internal_write(fd, bitset.data() + r.beg, r.end - r.beg); - internal_close(fd); + if (fd == kInvalidFd) return; + WriteToFile(fd, bitset.data() + r.beg, r.end - r.beg); + CloseFile(fd); VReport(1, " CovDump: %zd counters written for '%s'\n", r.end - r.beg, base_name); } @@ -722,10 +721,10 @@ void CoverageData::DumpAsBitSet() { n_set_bits++; } const char *base_name = StripModuleName(r.copied_module_name); - int fd = CovOpenFile(&path, /* packed */ false, base_name, "bitset-sancov"); - if (fd < 0) return; - internal_write(fd, out.data() + r.beg, r.end - r.beg); - internal_close(fd); + fd_t fd = CovOpenFile(&path, /* packed */false, base_name, "bitset-sancov"); + if (fd == kInvalidFd) return; + WriteToFile(fd, out.data() + r.beg, r.end - r.beg); + CloseFile(fd); VReport(1, " CovDump: bitset of %zd bits written for '%s', %zd bits are set\n", r.end - r.beg, base_name, n_set_bits); @@ -751,9 +750,8 @@ void CoverageData::DumpOffsets() { uptr pc = UnbundlePc(pc_array[i]); uptr counter = UnbundleCounter(pc_array[i]); if (!pc) continue; // Not visited. - const char *unused; uptr offset = 0; - sym->GetModuleNameAndOffsetForPC(pc, &unused, &offset); + sym->GetModuleNameAndOffsetForPC(pc, nullptr, &offset); offsets.push_back(BundlePcAndCounter(offset, counter)); } @@ -771,22 +769,22 @@ void CoverageData::DumpOffsets() { const char *module_name = StripModuleName(r.copied_module_name); if (cov_sandboxed) { - if (cov_fd >= 0) { + if (cov_fd != kInvalidFd) { CovWritePacked(internal_getpid(), module_name, offsets.data(), offsets.size() * sizeof(offsets[0])); VReport(1, " CovDump: %zd PCs written to packed file\n", num_offsets); } } else { // One file per module per process. - int fd = CovOpenFile(&path, false /* packed */, module_name); - if (fd < 0) continue; - internal_write(fd, offsets.data(), offsets.size() * sizeof(offsets[0])); - internal_close(fd); + fd_t fd = CovOpenFile(&path, false /* packed */, module_name); + if (fd == kInvalidFd) continue; + WriteToFile(fd, offsets.data(), offsets.size() * sizeof(offsets[0])); + CloseFile(fd); VReport(1, " CovDump: %s: %zd PCs written\n", path.data(), num_offsets); } } - if (cov_fd >= 0) - internal_close(cov_fd); + if (cov_fd != kInvalidFd) + CloseFile(cov_fd); } void CoverageData::DumpAll() { @@ -805,18 +803,19 @@ void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args) { if (!coverage_enabled) return; cov_sandboxed = args->coverage_sandboxed; if (!cov_sandboxed) return; - cov_fd = args->coverage_fd; cov_max_block_size = args->coverage_max_block_size; - if (cov_fd < 0) { + if (args->coverage_fd >= 0) { + cov_fd = (fd_t)args->coverage_fd; + } else { InternalScopedString path(kMaxPathLength); // Pre-open the file now. The sandbox won't allow us to do it later. cov_fd = CovOpenFile(&path, true /* packed */, 0); } } -int MaybeOpenCovFile(const char *name) { +fd_t MaybeOpenCovFile(const char *name) { CHECK(name); - if (!coverage_enabled) return -1; + if (!coverage_enabled) return kInvalidFd; InternalScopedString path(kMaxPathLength); return CovOpenFile(&path, true /* packed */, name); } @@ -836,9 +835,7 @@ void InitializeCoverage(bool enabled, const char *dir) { coverage_dir = dir; coverage_data.Init(); if (enabled) coverage_data.Enable(); -#if !SANITIZER_WINDOWS if (!common_flags()->coverage_direct) Atexit(__sanitizer_cov_dump); -#endif } void ReInitializeCoverage(bool enabled, const char *dir) { @@ -893,7 +890,7 @@ __sanitizer_cov_module_init(s32 *guards, uptr npcs, u8 *counters, } SANITIZER_INTERFACE_ATTRIBUTE sptr __sanitizer_maybe_open_cov_file(const char *name) { - return MaybeOpenCovFile(name); + return (sptr)MaybeOpenCovFile(name); } SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_total_unique_coverage() { diff --git a/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc b/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc index d3bde4b24..a3d75abc0 100644 --- a/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_coverage_mapping_libcdep.cc @@ -35,7 +35,6 @@ namespace __sanitizer { -static const uptr kMaxNumberOfModules = 1 << 14; static const uptr kMaxTextSize = 64 * 1024; struct CachedMapping { @@ -96,32 +95,30 @@ void CovUpdateMapping(const char *coverage_dir, uptr caller_pc) { } } - int err; + error_t err; InternalScopedString tmp_path(64 + internal_strlen(coverage_dir)); uptr res = internal_snprintf((char *)tmp_path.data(), tmp_path.size(), "%s/%zd.sancov.map.tmp", coverage_dir, internal_getpid()); CHECK_LE(res, tmp_path.size()); - uptr map_fd = OpenFile(tmp_path.data(), WrOnly); - if (internal_iserror(map_fd, &err)) { - Report(" Coverage: failed to open %s for writing: %d\n", tmp_path.data(), + fd_t map_fd = OpenFile(tmp_path.data(), WrOnly, &err); + if (map_fd == kInvalidFd) { + Report("Coverage: failed to open %s for writing: %d\n", tmp_path.data(), err); Die(); } - res = internal_write(map_fd, text.data(), text.length()); - if (internal_iserror(res, &err)) { + if (!WriteToFile(map_fd, text.data(), text.length(), nullptr, &err)) { Printf("sancov.map write failed: %d\n", err); Die(); } - internal_close(map_fd); + CloseFile(map_fd); InternalScopedString path(64 + internal_strlen(coverage_dir)); res = internal_snprintf((char *)path.data(), path.size(), "%s/%zd.sancov.map", coverage_dir, internal_getpid()); CHECK_LE(res, path.size()); - res = internal_rename(tmp_path.data(), path.data()); - if (internal_iserror(res, &err)) { + if (!RenameFile(tmp_path.data(), path.data(), &err)) { Printf("sancov.map rename failed: %d\n", err); Die(); } diff --git a/lib/sanitizer_common/sanitizer_deadlock_detector1.cc b/lib/sanitizer_common/sanitizer_deadlock_detector1.cc index b931edc7e..5890b54b9 100644 --- a/lib/sanitizer_common/sanitizer_deadlock_detector1.cc +++ b/lib/sanitizer_common/sanitizer_deadlock_detector1.cc @@ -40,19 +40,20 @@ struct DD : public DDetector { explicit DD(const DDFlags *flags); - DDPhysicalThread* CreatePhysicalThread(); - void DestroyPhysicalThread(DDPhysicalThread *pt); + DDPhysicalThread *CreatePhysicalThread() override; + void DestroyPhysicalThread(DDPhysicalThread *pt) override; - DDLogicalThread* CreateLogicalThread(u64 ctx); - void DestroyLogicalThread(DDLogicalThread *lt); + DDLogicalThread *CreateLogicalThread(u64 ctx) override; + void DestroyLogicalThread(DDLogicalThread *lt) override; - void MutexInit(DDCallback *cb, DDMutex *m); - void MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock); - void MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock, bool trylock); - void MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock); - void MutexDestroy(DDCallback *cb, DDMutex *m); + void MutexInit(DDCallback *cb, DDMutex *m) override; + void MutexBeforeLock(DDCallback *cb, DDMutex *m, bool wlock) override; + void MutexAfterLock(DDCallback *cb, DDMutex *m, bool wlock, + bool trylock) override; + void MutexBeforeUnlock(DDCallback *cb, DDMutex *m, bool wlock) override; + void MutexDestroy(DDCallback *cb, DDMutex *m) override; - DDReport *GetReport(DDCallback *cb); + DDReport *GetReport(DDCallback *cb) override; void MutexEnsureID(DDLogicalThread *lt, DDMutex *m); void ReportDeadlock(DDCallback *cb, DDMutex *m); diff --git a/lib/sanitizer_common/sanitizer_flags.cc b/lib/sanitizer_common/sanitizer_flags.cc index e835b46a2..01098a3d6 100644 --- a/lib/sanitizer_common/sanitizer_flags.cc +++ b/lib/sanitizer_common/sanitizer_flags.cc @@ -54,7 +54,7 @@ class FlagHandlerInclude : public FlagHandlerBase { bool Parse(const char *value) final { char *data; uptr data_mapped_size; - int err; + error_t err; uptr len = ReadFileToBuffer(value, &data, &data_mapped_size, Max(kMaxIncludeSize, GetPageSizeCached()), &err); diff --git a/lib/sanitizer_common/sanitizer_flags.inc b/lib/sanitizer_common/sanitizer_flags.inc index 884602f79..80c30acd6 100644 --- a/lib/sanitizer_common/sanitizer_flags.inc +++ b/lib/sanitizer_common/sanitizer_flags.inc @@ -151,3 +151,5 @@ COMMON_FLAG(const char *, stack_trace_format, "DEFAULT", "Use DEFAULT to get default format.") COMMON_FLAG(bool, no_huge_pages_for_shadow, true, "If true, the shadow is not allowed to use huge pages. ") +COMMON_FLAG(bool, strict_string_checks, false, + "If set check that string arguments are properly null-terminated") diff --git a/lib/sanitizer_common/sanitizer_internal_defs.h b/lib/sanitizer_common/sanitizer_internal_defs.h index e7737bd46..b76c6023a 100644 --- a/lib/sanitizer_common/sanitizer_internal_defs.h +++ b/lib/sanitizer_common/sanitizer_internal_defs.h @@ -80,7 +80,15 @@ typedef signed char s8; typedef signed short s16; // NOLINT typedef signed int s32; typedef signed long long s64; // NOLINT +#if SANITIZER_WINDOWS +// On Windows, files are HANDLE, which is a synonim of void*. +// Use void* to avoid including <windows.h> everywhere. +typedef void* fd_t; +typedef unsigned error_t; +#else typedef int fd_t; +typedef int error_t; +#endif // WARNING: OFF_T may be different from OS type off_t, depending on the value of // _FILE_OFFSET_BITS. This definition of OFF_T matches the ABI of system calls diff --git a/lib/sanitizer_common/sanitizer_libc.h b/lib/sanitizer_common/sanitizer_libc.h index c086b8a91..ae4e938f4 100644 --- a/lib/sanitizer_common/sanitizer_libc.h +++ b/lib/sanitizer_common/sanitizer_libc.h @@ -11,6 +11,7 @@ // run-time libraries. // These tools can not use some of the libc functions directly because those // functions are intercepted. Instead, we implement a tiny subset of libc here. +// FIXME: Some of functions declared in this file are in fact POSIX, not libc. //===----------------------------------------------------------------------===// #ifndef SANITIZER_LIBC_H #define SANITIZER_LIBC_H @@ -56,74 +57,26 @@ int internal_snprintf(char *buffer, uptr length, const char *format, ...); // Optimized for the case when the result is true. bool mem_is_zero(const char *mem, uptr size); - -// Memory -uptr internal_mmap(void *addr, uptr length, int prot, int flags, - int fd, u64 offset); -uptr internal_munmap(void *addr, uptr length); - // I/O -const fd_t kInvalidFd = -1; +const fd_t kInvalidFd = (fd_t)-1; const fd_t kStdinFd = 0; -const fd_t kStdoutFd = 1; -const fd_t kStderrFd = 2; -uptr internal_close(fd_t fd); -int internal_isatty(fd_t fd); +const fd_t kStdoutFd = (fd_t)1; +const fd_t kStderrFd = (fd_t)2; -// Use __sanitizer::OpenFile() instead. -uptr internal_open(const char *filename, int flags); -uptr internal_open(const char *filename, int flags, u32 mode); - -uptr internal_read(fd_t fd, void *buf, uptr count); -uptr internal_write(fd_t fd, const void *buf, uptr count); uptr internal_ftruncate(fd_t fd, uptr size); // OS -uptr internal_filesize(fd_t fd); // -1 on error. -uptr internal_stat(const char *path, void *buf); -uptr internal_lstat(const char *path, void *buf); -uptr internal_fstat(fd_t fd, void *buf); -uptr internal_dup2(int oldfd, int newfd); -uptr internal_readlink(const char *path, char *buf, uptr bufsize); -uptr internal_unlink(const char *path); -uptr internal_rename(const char *oldpath, const char *newpath); void NORETURN internal__exit(int exitcode); -uptr internal_lseek(fd_t fd, OFF_T offset, int whence); -uptr internal_ptrace(int request, int pid, void *addr, void *data); -uptr internal_waitpid(int pid, int *status, int options); uptr internal_getpid(); uptr internal_getppid(); -int internal_fork(); - // Threading uptr internal_sched_yield(); -// These functions call appropriate pthread_ functions directly, bypassing -// the interceptor. They are weak and may not be present in some tools. -SANITIZER_WEAK_ATTRIBUTE -int real_pthread_create(void *th, void *attr, void *(*callback)(void *), - void *param); -SANITIZER_WEAK_ATTRIBUTE -int real_pthread_join(void *th, void **ret); - -#define DEFINE_REAL_PTHREAD_FUNCTIONS \ - namespace __sanitizer { \ - int real_pthread_create(void *th, void *attr, void *(*callback)(void *), \ - void *param) { \ - return REAL(pthread_create)(th, attr, callback, param); \ - } \ - int real_pthread_join(void *th, void **ret) { \ - return REAL(pthread_join(th, ret)); \ - } \ - } // namespace __sanitizer - // Error handling bool internal_iserror(uptr retval, int *rverrno = 0); -int internal_sigaction(int signum, const void *act, void *oldact); - } // namespace __sanitizer #endif // SANITIZER_LIBC_H diff --git a/lib/sanitizer_common/sanitizer_libignore.cc b/lib/sanitizer_common/sanitizer_libignore.cc index cefb1dc97..8c4aeffda 100644 --- a/lib/sanitizer_common/sanitizer_libignore.cc +++ b/lib/sanitizer_common/sanitizer_libignore.cc @@ -12,6 +12,7 @@ #include "sanitizer_libignore.h" #include "sanitizer_flags.h" +#include "sanitizer_posix.h" #include "sanitizer_procmaps.h" namespace __sanitizer { diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc index 8d2ea4889..11a6fe6cf 100644 --- a/lib/sanitizer_common/sanitizer_linux.cc +++ b/lib/sanitizer_common/sanitizer_linux.cc @@ -127,6 +127,10 @@ uptr internal_munmap(void *addr, uptr length) { return internal_syscall(SYSCALL(munmap), (uptr)addr, length); } +int internal_mprotect(void *addr, uptr length, int prot) { + return internal_syscall(SYSCALL(mprotect), (uptr)addr, length, prot); +} + uptr internal_close(fd_t fd) { return internal_syscall(SYSCALL(close), fd); } diff --git a/lib/sanitizer_common/sanitizer_linux.h b/lib/sanitizer_common/sanitizer_linux.h index 2ce2025d2..fd3c1340b 100644 --- a/lib/sanitizer_common/sanitizer_linux.h +++ b/lib/sanitizer_common/sanitizer_linux.h @@ -17,6 +17,7 @@ #if SANITIZER_FREEBSD || SANITIZER_LINUX #include "sanitizer_common.h" #include "sanitizer_internal_defs.h" +#include "sanitizer_posix.h" #include "sanitizer_platform_limits_posix.h" struct link_map; // Opaque type returned by dlopen(). diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc index 1c099d862..ab9f0ab40 100644 --- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -15,6 +15,7 @@ #include "sanitizer_platform.h" #if SANITIZER_FREEBSD || SANITIZER_LINUX +#include "sanitizer_atomic.h" #include "sanitizer_common.h" #include "sanitizer_flags.h" #include "sanitizer_freebsd.h" @@ -22,8 +23,6 @@ #include "sanitizer_placement_new.h" #include "sanitizer_procmaps.h" #include "sanitizer_stacktrace.h" -#include "sanitizer_atomic.h" -#include "sanitizer_symbolizer.h" #if SANITIZER_ANDROID || SANITIZER_FREEBSD #include <dlfcn.h> // for dlsym() @@ -437,9 +436,8 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { return 0; if (data->filter && !data->filter(module_name.data())) return 0; - void *mem = &data->modules[data->current_n]; - LoadedModule *cur_module = new(mem) LoadedModule(module_name.data(), - info->dlpi_addr); + LoadedModule *cur_module = &data->modules[data->current_n]; + cur_module->set(module_name.data(), info->dlpi_addr); data->current_n++; for (int i = 0; i < info->dlpi_phnum; i++) { const Elf_Phdr *phdr = &info->dlpi_phdr[i]; @@ -462,19 +460,6 @@ uptr GetListOfModules(LoadedModule *modules, uptr max_modules, } #endif // SANITIZER_ANDROID -void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) { - // Some kinds of sandboxes may forbid filesystem access, so we won't be able - // to read the file mappings from /proc/self/maps. Luckily, neither the - // process will be able to load additional libraries, so it's fine to use the - // cached mappings. - MemoryMappingLayout::CacheMemoryMappings(); - // Same for /proc/self/exe in the symbolizer. -#if !SANITIZER_GO - Symbolizer::GetOrInit()->PrepareForSandboxing(); - CovPrepareForSandboxing(args); -#endif -} - // getrusage does not give us the current RSS, only the max RSS. // Still, this is better than nothing if /proc/self/statm is not available // for some reason, e.g. due to a sandbox. @@ -488,8 +473,8 @@ static uptr GetRSSFromGetrusage() { uptr GetRSS() { if (!common_flags()->can_use_proc_maps_statm) return GetRSSFromGetrusage(); - uptr fd = OpenFile("/proc/self/statm", RdOnly); - if ((sptr)fd < 0) + fd_t fd = OpenFile("/proc/self/statm", RdOnly); + if (fd == kInvalidFd) return GetRSSFromGetrusage(); char buf[64]; uptr len = internal_read(fd, buf, sizeof(buf) - 1); diff --git a/lib/sanitizer_common/sanitizer_mac.cc b/lib/sanitizer_common/sanitizer_mac.cc index 91a5b7d93..4c5b40935 100644 --- a/lib/sanitizer_common/sanitizer_mac.cc +++ b/lib/sanitizer_common/sanitizer_mac.cc @@ -59,6 +59,10 @@ uptr internal_munmap(void *addr, uptr length) { return munmap(addr, length); } +int internal_mprotect(void *addr, uptr length, int prot) { + return mprotect(addr, length, prot); +} + uptr internal_close(fd_t fd) { return close(fd); } @@ -220,11 +224,6 @@ void ReExec() { UNIMPLEMENTED(); } -void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) { - (void)args; - // Nothing here for now. -} - uptr GetPageSize() { return sysconf(_SC_PAGESIZE); } diff --git a/lib/sanitizer_common/sanitizer_mac.h b/lib/sanitizer_common/sanitizer_mac.h index 9eed90518..f5d3fe8c3 100644 --- a/lib/sanitizer_common/sanitizer_mac.h +++ b/lib/sanitizer_common/sanitizer_mac.h @@ -15,6 +15,7 @@ #include "sanitizer_platform.h" #if SANITIZER_MAC +#include "sanitizer_posix.h" namespace __sanitizer { diff --git a/lib/sanitizer_common/sanitizer_platform.h b/lib/sanitizer_common/sanitizer_platform.h index fef5a5bcd..92f78481f 100644 --- a/lib/sanitizer_common/sanitizer_platform.h +++ b/lib/sanitizer_common/sanitizer_platform.h @@ -130,4 +130,10 @@ # define SANITIZER_POINTER_FORMAT_LENGTH FIRST_32_SECOND_64(8, 12) #endif +// Assume obsolete RPC headers are available by default +#if !defined(HAVE_RPC_XDR_H) && !defined(HAVE_TIRPC_RPC_XDR_H) +# define HAVE_RPC_XDR_H (SANITIZER_LINUX && !SANITIZER_ANDROID) +# define HAVE_TIRPC_RPC_XDR_H 0 +#endif + #endif // SANITIZER_PLATFORM_H diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc index 2839e92a7..e8117f3df 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -135,7 +135,11 @@ #include <netax25/ax25.h> #include <netipx/ipx.h> #include <netrom/netrom.h> -#include <rpc/xdr.h> +#if HAVE_RPC_XDR_H +# include <rpc/xdr.h> +#elif HAVE_TIRPC_RPC_XDR_H +# include <tirpc/rpc/xdr.h> +#endif #include <scsi/scsi.h> #include <sys/mtio.h> #include <sys/kd.h> @@ -1159,7 +1163,7 @@ CHECK_SIZE_AND_OFFSET(group, gr_passwd); CHECK_SIZE_AND_OFFSET(group, gr_gid); CHECK_SIZE_AND_OFFSET(group, gr_mem); -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if HAVE_RPC_XDR_H || HAVE_TIRPC_RPC_XDR_H CHECK_TYPE_SIZE(XDR); CHECK_SIZE_AND_OFFSET(XDR, x_op); CHECK_SIZE_AND_OFFSET(XDR, x_ops); diff --git a/lib/sanitizer_common/sanitizer_posix.cc b/lib/sanitizer_common/sanitizer_posix.cc index 5e01212c2..0b6d35eb1 100644 --- a/lib/sanitizer_common/sanitizer_posix.cc +++ b/lib/sanitizer_common/sanitizer_posix.cc @@ -9,7 +9,7 @@ // // This file is shared between AddressSanitizer and ThreadSanitizer // run-time libraries and implements POSIX-specific functions from -// sanitizer_libc.h. +// sanitizer_posix.h. //===----------------------------------------------------------------------===// #include "sanitizer_platform.h" @@ -17,6 +17,7 @@ #include "sanitizer_common.h" #include "sanitizer_libc.h" +#include "sanitizer_posix.h" #include "sanitizer_procmaps.h" #include "sanitizer_stacktrace.h" @@ -198,27 +199,62 @@ void *MmapFixedOrDie(uptr fixed_addr, uptr size) { return (void *)p; } -void *Mprotect(uptr fixed_addr, uptr size) { +void *MmapNoAccess(uptr fixed_addr, uptr size) { return (void *)internal_mmap((void*)fixed_addr, size, PROT_NONE, MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, -1, 0); } -uptr OpenFile(const char *filename, FileAccessMode mode) { +bool MprotectNoAccess(uptr addr, uptr size) { + return 0 == internal_mprotect((void*)addr, size, PROT_NONE); +} + +fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *errno_p) { int flags; switch (mode) { case RdOnly: flags = O_RDONLY; break; case WrOnly: flags = O_WRONLY | O_CREAT; break; case RdWr: flags = O_RDWR | O_CREAT; break; } - return internal_open(filename, flags, 0660); + fd_t res = internal_open(filename, flags, 0660); + if (internal_iserror(res, errno_p)) + return kInvalidFd; + return res; +} + +void CloseFile(fd_t fd) { + internal_close(fd); +} + +bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read, + error_t *error_p) { + uptr res = internal_read(fd, buff, buff_size); + if (internal_iserror(res, error_p)) + return false; + if (bytes_read) + *bytes_read = res; + return true; +} + +bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written, + error_t *error_p) { + uptr res = internal_write(fd, buff, buff_size); + if (internal_iserror(res, error_p)) + return false; + if (bytes_written) + *bytes_written = res; + return true; +} + +bool RenameFile(const char *oldpath, const char *newpath, error_t *error_p) { + uptr res = internal_rename(oldpath, newpath); + return !internal_iserror(res, error_p); } void *MapFileToMemory(const char *file_name, uptr *buff_size) { - uptr openrv = OpenFile(file_name, RdOnly); - CHECK(!internal_iserror(openrv)); - fd_t fd = openrv; + fd_t fd = OpenFile(file_name, RdOnly); + CHECK(fd != kInvalidFd); uptr fsize = internal_filesize(fd); CHECK_NE(fsize, (uptr)-1); CHECK_GT(fsize, 0); @@ -227,13 +263,13 @@ void *MapFileToMemory(const char *file_name, uptr *buff_size) { return internal_iserror(map) ? 0 : (void *)map; } -void *MapWritableFileToMemory(void *addr, uptr size, uptr fd, uptr offset) { +void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, uptr offset) { uptr flags = MAP_SHARED; if (addr) flags |= MAP_FIXED; uptr p = internal_mmap(addr, size, PROT_READ | PROT_WRITE, flags, fd, offset); int mmap_errno = 0; if (internal_iserror(p, &mmap_errno)) { - Printf("could not map writable file (%zd, %zu, %zu): %zd, errno: %d\n", + Printf("could not map writable file (%d, %zu, %zu): %zd, errno: %d\n", fd, offset, size, p, mmap_errno); return 0; } diff --git a/lib/sanitizer_common/sanitizer_posix.h b/lib/sanitizer_common/sanitizer_posix.h new file mode 100644 index 000000000..a3377a851 --- /dev/null +++ b/lib/sanitizer_common/sanitizer_posix.h @@ -0,0 +1,81 @@ +//===-- sanitizer_posix.h -------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is shared between AddressSanitizer and ThreadSanitizer +// run-time libraries and declares some useful POSIX-specific functions. +//===----------------------------------------------------------------------===// +#ifndef SANITIZER_POSIX_H +#define SANITIZER_POSIX_H + +// ----------- ATTENTION ------------- +// This header should NOT include any other headers from sanitizer runtime. +#include "sanitizer_internal_defs.h" + +#if !SANITIZER_POSIX +// Make it hard to accidentally use any of functions declared in this file: +#error This file should only be included on POSIX +#endif + +namespace __sanitizer { + +// I/O +// Don't use directly, use __sanitizer::OpenFile() instead. +uptr internal_open(const char *filename, int flags); +uptr internal_open(const char *filename, int flags, u32 mode); +uptr internal_close(fd_t fd); + +uptr internal_read(fd_t fd, void *buf, uptr count); +uptr internal_write(fd_t fd, const void *buf, uptr count); + +// Memory +uptr internal_mmap(void *addr, uptr length, int prot, int flags, + int fd, u64 offset); +uptr internal_munmap(void *addr, uptr length); +int internal_mprotect(void *addr, uptr length, int prot); + +// OS +uptr internal_filesize(fd_t fd); // -1 on error. +uptr internal_stat(const char *path, void *buf); +uptr internal_lstat(const char *path, void *buf); +uptr internal_fstat(fd_t fd, void *buf); +uptr internal_dup2(int oldfd, int newfd); +uptr internal_readlink(const char *path, char *buf, uptr bufsize); +uptr internal_unlink(const char *path); +uptr internal_rename(const char *oldpath, const char *newpath); +uptr internal_lseek(fd_t fd, OFF_T offset, int whence); + +uptr internal_ptrace(int request, int pid, void *addr, void *data); +uptr internal_waitpid(int pid, int *status, int options); + +int internal_fork(); + +// These functions call appropriate pthread_ functions directly, bypassing +// the interceptor. They are weak and may not be present in some tools. +SANITIZER_WEAK_ATTRIBUTE +int real_pthread_create(void *th, void *attr, void *(*callback)(void *), + void *param); +SANITIZER_WEAK_ATTRIBUTE +int real_pthread_join(void *th, void **ret); + +#define DEFINE_REAL_PTHREAD_FUNCTIONS \ + namespace __sanitizer { \ + int real_pthread_create(void *th, void *attr, void *(*callback)(void *), \ + void *param) { \ + return REAL(pthread_create)(th, attr, callback, param); \ + } \ + int real_pthread_join(void *th, void **ret) { \ + return REAL(pthread_join(th, ret)); \ + } \ + } // namespace __sanitizer + +int internal_sigaction(int signum, const void *act, void *oldact); + +} // namespace __sanitizer + +#endif // SANITIZER_POSIX_H diff --git a/lib/sanitizer_common/sanitizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_posix_libcdep.cc index 11828e6cd..9eb28c612 100644 --- a/lib/sanitizer_common/sanitizer_posix_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_posix_libcdep.cc @@ -18,7 +18,10 @@ #include "sanitizer_common.h" #include "sanitizer_flags.h" #include "sanitizer_platform_limits_posix.h" +#include "sanitizer_posix.h" +#include "sanitizer_procmaps.h" #include "sanitizer_stacktrace.h" +#include "sanitizer_symbolizer.h" #include <errno.h> #include <pthread.h> @@ -119,8 +122,8 @@ int Atexit(void (*function)(void)) { #endif } -int internal_isatty(fd_t fd) { - return isatty(fd); +bool SupportsColoredOutput(fd_t fd) { + return isatty(fd) != 0; } #ifndef SANITIZER_GO @@ -200,6 +203,19 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) { return result; } +void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) { + // Some kinds of sandboxes may forbid filesystem access, so we won't be able + // to read the file mappings from /proc/self/maps. Luckily, neither the + // process will be able to load additional libraries, so it's fine to use the + // cached mappings. + MemoryMappingLayout::CacheMemoryMappings(); + // Same for /proc/self/exe in the symbolizer. +#if !SANITIZER_GO + Symbolizer::GetOrInit()->PrepareForSandboxing(); + CovPrepareForSandboxing(args); +#endif +} + } // namespace __sanitizer #endif // SANITIZER_POSIX diff --git a/lib/sanitizer_common/sanitizer_procmaps_common.cc b/lib/sanitizer_common/sanitizer_procmaps_common.cc index 2ec08d7f1..2c6ce8e2b 100644 --- a/lib/sanitizer_common/sanitizer_procmaps_common.cc +++ b/lib/sanitizer_common/sanitizer_procmaps_common.cc @@ -130,7 +130,6 @@ uptr MemoryMappingLayout::DumpListOfModules(LoadedModule *modules, continue; if (filter && !filter(cur_name)) continue; - void *mem = &modules[n_modules]; // Don't subtract 'cur_beg' from the first entry: // * If a binary is compiled w/o -pie, then the first entry in // process maps is likely the binary itself (all dynamic libs @@ -143,7 +142,8 @@ uptr MemoryMappingLayout::DumpListOfModules(LoadedModule *modules, // shadow memory of the tool), so the module can't be the // first entry. uptr base_address = (i ? cur_beg : 0) - cur_offset; - LoadedModule *cur_module = new(mem) LoadedModule(cur_name, base_address); + LoadedModule *cur_module = &modules[n_modules]; + cur_module->set(cur_name, base_address); cur_module->addAddressRange(cur_beg, cur_end, prot & kProtectionExecute); n_modules++; } diff --git a/lib/sanitizer_common/sanitizer_procmaps_mac.cc b/lib/sanitizer_common/sanitizer_procmaps_mac.cc index c0a861497..29d699609 100644 --- a/lib/sanitizer_common/sanitizer_procmaps_mac.cc +++ b/lib/sanitizer_common/sanitizer_procmaps_mac.cc @@ -171,13 +171,13 @@ uptr MemoryMappingLayout::DumpListOfModules(LoadedModule *modules, continue; if (filter && !filter(cur_name)) continue; - LoadedModule *cur_module = 0; + LoadedModule *cur_module = nullptr; if (n_modules > 0 && 0 == internal_strcmp(cur_name, modules[n_modules - 1].full_name())) { cur_module = &modules[n_modules - 1]; } else { - void *mem = &modules[n_modules]; - cur_module = new(mem) LoadedModule(cur_name, cur_beg); + cur_module = &modules[n_modules]; + cur_module->set(cur_name, cur_beg); n_modules++; } cur_module->addAddressRange(cur_beg, cur_end, prot & kProtectionExecute); diff --git a/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc index 64e1c7974..47b27e7e5 100644 --- a/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc @@ -310,7 +310,7 @@ class ScopedStackSpaceWithGuard { // in the future. guard_start_ = (uptr)MmapOrDie(stack_size_ + guard_size_, "ScopedStackWithGuard"); - CHECK_EQ(guard_start_, (uptr)Mprotect((uptr)guard_start_, guard_size_)); + CHECK(MprotectNoAccess((uptr)guard_start_, guard_size_)); } ~ScopedStackSpaceWithGuard() { UnmapOrDie((void *)guard_start_, stack_size_ + guard_size_); diff --git a/lib/sanitizer_common/sanitizer_symbolizer.cc b/lib/sanitizer_common/sanitizer_symbolizer.cc index df7661ab6..8b2496a6d 100644 --- a/lib/sanitizer_common/sanitizer_symbolizer.cc +++ b/lib/sanitizer_common/sanitizer_symbolizer.cc @@ -75,8 +75,29 @@ void Symbolizer::AddHooks(Symbolizer::StartSymbolizationHook start_hook, end_hook_ = end_hook; } +const char *Symbolizer::ModuleNameOwner::GetOwnedCopy(const char *str) { + mu_->CheckLocked(); + + // 'str' will be the same string multiple times in a row, optimize this case. + if (last_match_ && !internal_strcmp(last_match_, str)) + return last_match_; + + // FIXME: this is linear search. + // We should optimize this further if this turns out to be a bottleneck later. + for (uptr i = 0; i < storage_.size(); ++i) { + if (!internal_strcmp(storage_[i], str)) { + last_match_ = storage_[i]; + return last_match_; + } + } + last_match_ = internal_strdup(str); + storage_.push_back(last_match_); + return last_match_; +} + Symbolizer::Symbolizer(IntrusiveList<SymbolizerTool> tools) - : tools_(tools), start_hook_(0), end_hook_(0) {} + : module_names_(&mu_), n_modules_(0), modules_fresh_(false), tools_(tools), + start_hook_(0), end_hook_(0) {} Symbolizer::SymbolizerScope::SymbolizerScope(const Symbolizer *sym) : sym_(sym) { @@ -89,76 +110,4 @@ Symbolizer::SymbolizerScope::~SymbolizerScope() { sym_->end_hook_(); } -SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) { - BlockingMutexLock l(&mu_); - const char *module_name; - uptr module_offset; - SymbolizedStack *res = SymbolizedStack::New(addr); - if (!PlatformFindModuleNameAndOffsetForAddress(addr, &module_name, - &module_offset)) - return res; - // Always fill data about module name and offset. - res->info.FillModuleInfo(module_name, module_offset); - for (auto iter = Iterator(&tools_); iter.hasNext();) { - auto *tool = iter.next(); - SymbolizerScope sym_scope(this); - if (tool->SymbolizePC(addr, res)) { - return res; - } - } - return res; -} - -bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) { - BlockingMutexLock l(&mu_); - const char *module_name; - uptr module_offset; - if (!PlatformFindModuleNameAndOffsetForAddress(addr, &module_name, - &module_offset)) - return false; - info->Clear(); - info->module = internal_strdup(module_name); - info->module_offset = module_offset; - for (auto iter = Iterator(&tools_); iter.hasNext();) { - auto *tool = iter.next(); - SymbolizerScope sym_scope(this); - if (tool->SymbolizeData(addr, info)) { - return true; - } - } - return true; -} - -bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name, - uptr *module_address) { - BlockingMutexLock l(&mu_); - return PlatformFindModuleNameAndOffsetForAddress(pc, module_name, - module_address); -} - -void Symbolizer::Flush() { - BlockingMutexLock l(&mu_); - for (auto iter = Iterator(&tools_); iter.hasNext();) { - auto *tool = iter.next(); - SymbolizerScope sym_scope(this); - tool->Flush(); - } -} - -const char *Symbolizer::Demangle(const char *name) { - BlockingMutexLock l(&mu_); - for (auto iter = Iterator(&tools_); iter.hasNext();) { - auto *tool = iter.next(); - SymbolizerScope sym_scope(this); - if (const char *demangled = tool->Demangle(name)) - return demangled; - } - return PlatformDemangle(name); -} - -void Symbolizer::PrepareForSandboxing() { - BlockingMutexLock l(&mu_); - PlatformPrepareForSandboxing(); -} - } // namespace __sanitizer diff --git a/lib/sanitizer_common/sanitizer_symbolizer.h b/lib/sanitizer_common/sanitizer_symbolizer.h index 225da70de..92332230f 100644 --- a/lib/sanitizer_common/sanitizer_symbolizer.h +++ b/lib/sanitizer_common/sanitizer_symbolizer.h @@ -75,7 +75,7 @@ struct DataInfo { class SymbolizerTool; -class Symbolizer { +class Symbolizer final { public: /// Initialize and return platform-specific implementation of symbolizer /// (if it wasn't already initialized). @@ -84,15 +84,19 @@ class Symbolizer { // all inlined functions, if necessary). SymbolizedStack *SymbolizePC(uptr address); bool SymbolizeData(uptr address, DataInfo *info); + + // The module names Symbolizer returns are stable and unique for every given + // module. It is safe to store and compare them as pointers. bool GetModuleNameAndOffsetForPC(uptr pc, const char **module_name, uptr *module_address); const char *GetModuleNameForPc(uptr pc) { - const char *module_name = 0; + const char *module_name = nullptr; uptr unused; if (GetModuleNameAndOffsetForPC(pc, &module_name, &unused)) return module_name; return nullptr; } + // Release internal caches (if any). void Flush(); // Attempts to demangle the provided C++ mangled name. @@ -110,16 +114,40 @@ class Symbolizer { EndSymbolizationHook end_hook); private: + // GetModuleNameAndOffsetForPC has to return a string to the caller. + // Since the corresponding module might get unloaded later, we should create + // our owned copies of the strings that we can safely return. + // ModuleNameOwner does not provide any synchronization, thus calls to + // its method should be protected by |mu_|. + class ModuleNameOwner { + public: + explicit ModuleNameOwner(BlockingMutex *synchronized_by) + : storage_(kInitialCapacity), last_match_(nullptr), + mu_(synchronized_by) {} + const char *GetOwnedCopy(const char *str); + + private: + static const uptr kInitialCapacity = 1000; + InternalMmapVector<const char*> storage_; + const char *last_match_; + + BlockingMutex *mu_; + } module_names_; + /// Platform-specific function for creating a Symbolizer object. static Symbolizer *PlatformInit(); - virtual bool PlatformFindModuleNameAndOffsetForAddress( - uptr address, const char **module_name, uptr *module_offset) { - UNIMPLEMENTED(); - } + bool FindModuleNameAndOffsetForAddress(uptr address, const char **module_name, + uptr *module_offset); + LoadedModule *FindModuleForAddress(uptr address); + LoadedModule modules_[kMaxNumberOfModules]; + uptr n_modules_; + // If stale, need to reload the modules before looking up addresses. + bool modules_fresh_; + // Platform-specific default demangler, must not return nullptr. - virtual const char *PlatformDemangle(const char *name) { UNIMPLEMENTED(); } - virtual void PlatformPrepareForSandboxing() { UNIMPLEMENTED(); } + const char *PlatformDemangle(const char *name); + void PlatformPrepareForSandboxing(); static Symbolizer *symbolizer_; static StaticSpinMutex init_mu_; @@ -132,7 +160,6 @@ class Symbolizer { typedef IntrusiveList<SymbolizerTool>::Iterator Iterator; IntrusiveList<SymbolizerTool> tools_; - protected: explicit Symbolizer(IntrusiveList<SymbolizerTool> tools); static LowLevelAllocator symbolizer_allocator_; diff --git a/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc index f1e2289c8..160f55d42 100644 --- a/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cc @@ -60,6 +60,121 @@ const char *ExtractTokenUpToDelimiter(const char *str, const char *delimiter, return prefix_end; } +SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) { + BlockingMutexLock l(&mu_); + const char *module_name; + uptr module_offset; + SymbolizedStack *res = SymbolizedStack::New(addr); + if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset)) + return res; + // Always fill data about module name and offset. + res->info.FillModuleInfo(module_name, module_offset); + for (auto iter = Iterator(&tools_); iter.hasNext();) { + auto *tool = iter.next(); + SymbolizerScope sym_scope(this); + if (tool->SymbolizePC(addr, res)) { + return res; + } + } + return res; +} + +bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) { + BlockingMutexLock l(&mu_); + const char *module_name; + uptr module_offset; + if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset)) + return false; + info->Clear(); + info->module = internal_strdup(module_name); + info->module_offset = module_offset; + for (auto iter = Iterator(&tools_); iter.hasNext();) { + auto *tool = iter.next(); + SymbolizerScope sym_scope(this); + if (tool->SymbolizeData(addr, info)) { + return true; + } + } + return true; +} + +bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name, + uptr *module_address) { + BlockingMutexLock l(&mu_); + const char *internal_module_name = nullptr; + if (!FindModuleNameAndOffsetForAddress(pc, &internal_module_name, + module_address)) + return false; + + if (module_name) + *module_name = module_names_.GetOwnedCopy(internal_module_name); + return true; +} + +void Symbolizer::Flush() { + BlockingMutexLock l(&mu_); + for (auto iter = Iterator(&tools_); iter.hasNext();) { + auto *tool = iter.next(); + SymbolizerScope sym_scope(this); + tool->Flush(); + } +} + +const char *Symbolizer::Demangle(const char *name) { + BlockingMutexLock l(&mu_); + for (auto iter = Iterator(&tools_); iter.hasNext();) { + auto *tool = iter.next(); + SymbolizerScope sym_scope(this); + if (const char *demangled = tool->Demangle(name)) + return demangled; + } + return PlatformDemangle(name); +} + +void Symbolizer::PrepareForSandboxing() { + BlockingMutexLock l(&mu_); + PlatformPrepareForSandboxing(); +} + +bool Symbolizer::FindModuleNameAndOffsetForAddress(uptr address, + const char **module_name, + uptr *module_offset) { + LoadedModule *module = FindModuleForAddress(address); + if (module == 0) + return false; + *module_name = module->full_name(); + *module_offset = address - module->base_address(); + return true; +} + +LoadedModule *Symbolizer::FindModuleForAddress(uptr address) { + bool modules_were_reloaded = false; + if (!modules_fresh_) { + for (uptr i = 0; i < n_modules_; i++) + modules_[i].clear(); + n_modules_ = + GetListOfModules(modules_, kMaxNumberOfModules, /* filter */ nullptr); + CHECK_GT(n_modules_, 0); + CHECK_LT(n_modules_, kMaxNumberOfModules); + modules_fresh_ = true; + modules_were_reloaded = true; + } + for (uptr i = 0; i < n_modules_; i++) { + if (modules_[i].containsAddress(address)) { + return &modules_[i]; + } + } + // Reload the modules and look up again, if we haven't tried it yet. + if (!modules_were_reloaded) { + // FIXME: set modules_fresh_ from dlopen()/dlclose() interceptors. + // It's too aggressive to reload the list of modules each time we fail + // to find a module for a given address. + modules_fresh_ = false; + return FindModuleForAddress(address); + } + return 0; +} + Symbolizer *Symbolizer::GetOrInit() { SpinMutexLock l(&init_mu_); if (symbolizer_) diff --git a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc index 189b0abd8..6e714c7c6 100644 --- a/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc @@ -129,13 +129,13 @@ class LLVMSymbolizerProcess : public SymbolizerProcess { explicit LLVMSymbolizerProcess(const char *path) : SymbolizerProcess(path) {} private: - bool ReachedEndOfOutput(const char *buffer, uptr length) const { + bool ReachedEndOfOutput(const char *buffer, uptr length) const override { // Empty line marks the end of llvm-symbolizer output. return length >= 2 && buffer[length - 1] == '\n' && buffer[length - 2] == '\n'; } - void ExecuteWithDefaultArgs(const char *path_to_binary) const { + void ExecuteWithDefaultArgs(const char *path_to_binary) const override { #if defined(__x86_64__) const char* const kSymbolizerArch = "--default-arch=x86_64"; #elif defined(__i386__) @@ -202,7 +202,7 @@ class Addr2LineProcess : public SymbolizerProcess { const char *module_name() const { return module_name_; } private: - bool ReachedEndOfOutput(const char *buffer, uptr length) const { + bool ReachedEndOfOutput(const char *buffer, uptr length) const override { // Output should consist of two lines. int num_lines = 0; for (uptr i = 0; i < length; ++i) { @@ -214,7 +214,7 @@ class Addr2LineProcess : public SymbolizerProcess { return false; } - void ExecuteWithDefaultArgs(const char *path_to_binary) const { + void ExecuteWithDefaultArgs(const char *path_to_binary) const override { execl(path_to_binary, path_to_binary, "-Cfe", module_name_, (char *)0); } @@ -349,69 +349,16 @@ class InternalSymbolizer : public SymbolizerTool { #endif // SANITIZER_SUPPORTS_WEAK_HOOKS -class POSIXSymbolizer : public Symbolizer { - public: - explicit POSIXSymbolizer(IntrusiveList<SymbolizerTool> tools) - : Symbolizer(tools), n_modules_(0), modules_fresh_(false) {} - - private: - const char *PlatformDemangle(const char *name) override { - return DemangleCXXABI(name); - } +const char *Symbolizer::PlatformDemangle(const char *name) { + return DemangleCXXABI(name); +} - void PlatformPrepareForSandboxing() override { +void Symbolizer::PlatformPrepareForSandboxing() { #if SANITIZER_LINUX && !SANITIZER_ANDROID - // Cache /proc/self/exe on Linux. - CacheBinaryName(); + // Cache /proc/self/exe on Linux. + CacheBinaryName(); #endif - } - - LoadedModule *FindModuleForAddress(uptr address) { - bool modules_were_reloaded = false; - if (!modules_fresh_) { - for (uptr i = 0; i < n_modules_; i++) - modules_[i].clear(); - n_modules_ = GetListOfModules(modules_, kMaxNumberOfModuleContexts, - /* filter */ 0); - CHECK_GT(n_modules_, 0); - CHECK_LT(n_modules_, kMaxNumberOfModuleContexts); - modules_fresh_ = true; - modules_were_reloaded = true; - } - for (uptr i = 0; i < n_modules_; i++) { - if (modules_[i].containsAddress(address)) { - return &modules_[i]; - } - } - // Reload the modules and look up again, if we haven't tried it yet. - if (!modules_were_reloaded) { - // FIXME: set modules_fresh_ from dlopen()/dlclose() interceptors. - // It's too aggressive to reload the list of modules each time we fail - // to find a module for a given address. - modules_fresh_ = false; - return FindModuleForAddress(address); - } - return 0; - } - - bool PlatformFindModuleNameAndOffsetForAddress(uptr address, - const char **module_name, - uptr *module_offset) override { - LoadedModule *module = FindModuleForAddress(address); - if (module == 0) - return false; - *module_name = module->full_name(); - *module_offset = address - module->base_address(); - return true; - } - - // 16K loaded modules should be enough for everyone. - static const uptr kMaxNumberOfModuleContexts = 1 << 14; - LoadedModule modules_[kMaxNumberOfModuleContexts]; - uptr n_modules_; - // If stale, need to reload the modules before looking up addresses. - bool modules_fresh_; -}; +} static SymbolizerTool *ChooseExternalSymbolizer(LowLevelAllocator *allocator) { const char *path = common_flags()->external_symbolizer_path; @@ -494,7 +441,7 @@ Symbolizer *Symbolizer::PlatformInit() { IntrusiveList<SymbolizerTool> list; list.clear(); ChooseSymbolizerTools(&list, &symbolizer_allocator_); - return new(symbolizer_allocator_) POSIXSymbolizer(list); + return new(symbolizer_allocator_) Symbolizer(list); } } // namespace __sanitizer diff --git a/lib/sanitizer_common/sanitizer_symbolizer_process_libcdep.cc b/lib/sanitizer_common/sanitizer_symbolizer_process_libcdep.cc index 98d16e04e..f1c01a332 100644 --- a/lib/sanitizer_common/sanitizer_symbolizer_process_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_symbolizer_process_libcdep.cc @@ -13,6 +13,7 @@ #include "sanitizer_platform.h" #if SANITIZER_POSIX +#include "sanitizer_posix.h" #include "sanitizer_symbolizer_internal.h" #include <errno.h> diff --git a/lib/sanitizer_common/sanitizer_symbolizer_win.cc b/lib/sanitizer_common/sanitizer_symbolizer_win.cc index 67ed4b325..31f374687 100644 --- a/lib/sanitizer_common/sanitizer_symbolizer_win.cc +++ b/lib/sanitizer_common/sanitizer_symbolizer_win.cc @@ -129,42 +129,19 @@ const char *WinSymbolizerTool::Demangle(const char *name) { return name; } -bool FindModuleNameAndOffsetForAddress(uptr addr, const char **module_name, - uptr *module_offset) { - InitializeDbgHelpIfNeeded(); - - IMAGEHLP_MODULE64 mod_info; - internal_memset(&mod_info, 0, sizeof(mod_info)); - mod_info.SizeOfStruct = sizeof(mod_info); - if (SymGetModuleInfo64(GetCurrentProcess(), addr, &mod_info)) { - *module_name = mod_info.ImageName; - *module_offset = addr - (uptr)mod_info.BaseOfImage; - return true; - } - return false; +const char *Symbolizer::PlatformDemangle(const char *name) { + return name; } -// TODO(kuba.brecka): To be merged with POSIXSymbolizer. -class WinSymbolizer : public Symbolizer { - public: - explicit WinSymbolizer(IntrusiveList<SymbolizerTool> tools) - : Symbolizer(tools) {} - - private: - bool PlatformFindModuleNameAndOffsetForAddress( - uptr addr, const char **module_name, uptr *module_offset) override { - return ::FindModuleNameAndOffsetForAddress(addr, module_name, - module_offset); - } - const char *PlatformDemangle(const char *name) override { return name; } - void PlatformPrepareForSandboxing() override { } -}; +void Symbolizer::PlatformPrepareForSandboxing() { + // Do nothing. +} Symbolizer *Symbolizer::PlatformInit() { IntrusiveList<SymbolizerTool> list; list.clear(); list.push_back(new(symbolizer_allocator_) WinSymbolizerTool()); - return new(symbolizer_allocator_) WinSymbolizer(list); + return new(symbolizer_allocator_) Symbolizer(list); } } // namespace __sanitizer diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc index 3ec90842c..e5e2f643e 100644 --- a/lib/sanitizer_common/sanitizer_win.cc +++ b/lib/sanitizer_common/sanitizer_win.cc @@ -93,6 +93,9 @@ void *MmapOrDie(uptr size, const char *mem_type) { } void UnmapOrDie(void *addr, uptr size) { + if (!size || !addr) + return; + if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) { Report("ERROR: %s failed to " "deallocate 0x%zx (%zd) bytes at address %p (error code: %d)\n", @@ -122,7 +125,7 @@ void *MmapNoReserveOrDie(uptr size, const char *mem_type) { return MmapOrDie(size, mem_type); } -void *Mprotect(uptr fixed_addr, uptr size) { +void *MmapNoAccess(uptr fixed_addr, uptr size) { void *res = VirtualAlloc((LPVOID)fixed_addr, size, MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS); if (res == 0) @@ -132,6 +135,12 @@ void *Mprotect(uptr fixed_addr, uptr size) { return res; } +bool MprotectNoAccess(uptr addr, uptr size) { + DWORD old_protection; + return VirtualProtect((LPVOID)addr, size, PAGE_NOACCESS, &old_protection); +} + + void FlushUnneededShadowMemory(uptr addr, uptr size) { // This is almost useless on 32-bits. // FIXME: add madvise-analog when we move to 64-bits. @@ -157,7 +166,7 @@ void *MapFileToMemory(const char *file_name, uptr *buff_size) { UNIMPLEMENTED(); } -void *MapWritableFileToMemory(void *addr, uptr size, uptr fd, uptr offset) { +void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, uptr offset) { UNIMPLEMENTED(); } @@ -206,76 +215,46 @@ u32 GetUid() { namespace { struct ModuleInfo { - HMODULE handle; + const char *filepath; uptr base_address; uptr end_address; }; int CompareModulesBase(const void *pl, const void *pr) { - const ModuleInfo &l = *(ModuleInfo *)pl, &r = *(ModuleInfo *)pr; - if (l.base_address < r.base_address) + const ModuleInfo *l = (ModuleInfo *)pl, *r = (ModuleInfo *)pr; + if (l->base_address < r->base_address) return -1; - return l.base_address > r.base_address; + return l->base_address > r->base_address; } } // namespace #ifndef SANITIZER_GO void DumpProcessMap() { Report("Dumping process modules:\n"); - HANDLE cur_process = GetCurrentProcess(); - - // Query the list of modules. Start by assuming there are no more than 256 - // modules and retry if that's not sufficient. - ModuleInfo *modules; - size_t num_modules; - { - HMODULE *hmodules = 0; - uptr modules_buffer_size = sizeof(HMODULE) * 256; - DWORD bytes_required; - while (!hmodules) { - hmodules = (HMODULE *)MmapOrDie(modules_buffer_size, __FUNCTION__); - CHECK(EnumProcessModules(cur_process, hmodules, modules_buffer_size, - &bytes_required)); - if (bytes_required > modules_buffer_size) { - // Either there turned out to be more than 256 hmodules, or new hmodules - // could have loaded since the last try. Retry. - UnmapOrDie(hmodules, modules_buffer_size); - hmodules = 0; - modules_buffer_size = bytes_required; - } - } + InternalScopedBuffer<LoadedModule> modules(kMaxNumberOfModules); + uptr num_modules = + GetListOfModules(modules.data(), kMaxNumberOfModules, nullptr); - num_modules = bytes_required / sizeof(HMODULE); - modules = - (ModuleInfo *)MmapOrDie(num_modules * sizeof(ModuleInfo), __FUNCTION__); - for (size_t i = 0; i < num_modules; ++i) { - modules[i].handle = hmodules[i]; - MODULEINFO mi; - if (!GetModuleInformation(cur_process, hmodules[i], &mi, sizeof(mi))) - continue; - modules[i].base_address = (uptr)mi.lpBaseOfDll; - modules[i].end_address = (uptr)mi.lpBaseOfDll + mi.SizeOfImage; - } - UnmapOrDie(hmodules, modules_buffer_size); + InternalScopedBuffer<ModuleInfo> module_infos(num_modules); + for (size_t i = 0; i < num_modules; ++i) { + module_infos[i].filepath = modules[i].full_name(); + module_infos[i].base_address = modules[i].base_address(); + module_infos[i].end_address = modules[i].ranges().next()->end; } - - qsort(modules, num_modules, sizeof(ModuleInfo), CompareModulesBase); + qsort(module_infos.data(), num_modules, sizeof(ModuleInfo), + CompareModulesBase); for (size_t i = 0; i < num_modules; ++i) { - const ModuleInfo &mi = modules[i]; - char module_name[MAX_PATH]; - bool got_module_name = GetModuleFileNameA( - mi.handle, module_name, sizeof(module_name)); + const ModuleInfo &mi = module_infos[i]; if (mi.end_address != 0) { Printf("\t%p-%p %s\n", mi.base_address, mi.end_address, - got_module_name ? module_name : "[no name]"); - } else if (got_module_name) { - Printf("\t??\?-??? %s\n", module_name); + mi.filepath[0] ? mi.filepath : "[no name]"); + } else if (mi.filepath[0]) { + Printf("\t??\?-??? %s\n", mi.filepath); } else { Printf("\t???\n"); } } - UnmapOrDie(modules, num_modules * sizeof(ModuleInfo)); } #endif @@ -346,117 +325,130 @@ void Abort() { uptr GetListOfModules(LoadedModule *modules, uptr max_modules, string_predicate_t filter) { - UNIMPLEMENTED(); -}; - -#ifndef SANITIZER_GO -int Atexit(void (*function)(void)) { - return atexit(function); -} -#endif + HANDLE cur_process = GetCurrentProcess(); -// ------------------ sanitizer_libc.h -uptr internal_mmap(void *addr, uptr length, int prot, int flags, - int fd, u64 offset) { - UNIMPLEMENTED(); -} + // Query the list of modules. Start by assuming there are no more than 256 + // modules and retry if that's not sufficient. + HMODULE *hmodules = 0; + uptr modules_buffer_size = sizeof(HMODULE) * 256; + DWORD bytes_required; + while (!hmodules) { + hmodules = (HMODULE *)MmapOrDie(modules_buffer_size, __FUNCTION__); + CHECK(EnumProcessModules(cur_process, hmodules, modules_buffer_size, + &bytes_required)); + if (bytes_required > modules_buffer_size) { + // Either there turned out to be more than 256 hmodules, or new hmodules + // could have loaded since the last try. Retry. + UnmapOrDie(hmodules, modules_buffer_size); + hmodules = 0; + modules_buffer_size = bytes_required; + } + } -uptr internal_munmap(void *addr, uptr length) { - UNIMPLEMENTED(); -} + // |num_modules| is the number of modules actually present, + // |count| is the number of modules we return. + size_t nun_modules = bytes_required / sizeof(HMODULE), + count = 0; + for (size_t i = 0; i < nun_modules && count < max_modules; ++i) { + HMODULE handle = hmodules[i]; + MODULEINFO mi; + if (!GetModuleInformation(cur_process, handle, &mi, sizeof(mi))) + continue; -uptr internal_close(fd_t fd) { - UNIMPLEMENTED(); -} + char module_name[MAX_PATH]; + bool got_module_name = + GetModuleFileNameA(handle, module_name, sizeof(module_name)); + if (!got_module_name) + module_name[0] = '\0'; + + if (filter && !filter(module_name)) + continue; + + uptr base_address = (uptr)mi.lpBaseOfDll; + uptr end_address = (uptr)mi.lpBaseOfDll + mi.SizeOfImage; + LoadedModule *cur_module = &modules[count]; + cur_module->set(module_name, base_address); + // We add the whole module as one single address range. + cur_module->addAddressRange(base_address, end_address, /*executable*/ true); + count++; + } + UnmapOrDie(hmodules, modules_buffer_size); -int internal_isatty(fd_t fd) { - return _isatty(fd); -} + return count; +}; -uptr internal_open(const char *filename, int flags) { - UNIMPLEMENTED(); -} +#ifndef SANITIZER_GO +// We can't use atexit() directly at __asan_init time as the CRT is not fully +// initialized at this point. Place the functions into a vector and use +// atexit() as soon as it is ready for use (i.e. after .CRT$XIC initializers). +InternalMmapVectorNoCtor<void (*)(void)> atexit_functions; -uptr internal_open(const char *filename, int flags, u32 mode) { - UNIMPLEMENTED(); +int Atexit(void (*function)(void)) { + atexit_functions.push_back(function); + return 0; } -uptr OpenFile(const char *filename, FileAccessMode mode) { - UNIMPLEMENTED(); +static int RunAtexit() { + int ret = 0; + for (uptr i = 0; i < atexit_functions.size(); ++i) { + ret |= atexit(atexit_functions[i]); + } + return ret; } -uptr internal_read(fd_t fd, void *buf, uptr count) { - UNIMPLEMENTED(); -} +#pragma section(".CRT$XID", long, read) // NOLINT +static __declspec(allocate(".CRT$XID")) int (*__run_atexit)() = RunAtexit; +#endif -uptr internal_write(fd_t fd, const void *buf, uptr count) { - if (fd != kStderrFd) +// ------------------ sanitizer_libc.h +fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *last_error) { + if (mode != WrOnly) UNIMPLEMENTED(); - - static HANDLE output_stream = 0; - // Abort immediately if we know printing is not possible. - if (output_stream == INVALID_HANDLE_VALUE) - return 0; - - // If called for the first time, try to use stderr to output stuff, - // falling back to stdout if anything goes wrong. - bool fallback_to_stdout = false; - if (output_stream == 0) { - output_stream = GetStdHandle(STD_ERROR_HANDLE); - // We don't distinguish "no such handle" from error. - if (output_stream == 0) - output_stream = INVALID_HANDLE_VALUE; - - if (output_stream == INVALID_HANDLE_VALUE) { - // Retry with stdout? - output_stream = GetStdHandle(STD_OUTPUT_HANDLE); - if (output_stream == 0) - output_stream = INVALID_HANDLE_VALUE; - if (output_stream == INVALID_HANDLE_VALUE) - return 0; - } else { - // Successfully got an stderr handle. However, if WriteFile() fails, - // we can still try to fallback to stdout. - fallback_to_stdout = true; - } - } - - DWORD ret; - if (WriteFile(output_stream, buf, count, &ret, 0)) - return ret; - - // Re-try with stdout if using a valid stderr handle fails. - if (fallback_to_stdout) { - output_stream = GetStdHandle(STD_OUTPUT_HANDLE); - if (output_stream == 0) - output_stream = INVALID_HANDLE_VALUE; - if (output_stream != INVALID_HANDLE_VALUE) - return internal_write(fd, buf, count); - } - return 0; + fd_t res = CreateFile(filename, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, nullptr); + CHECK(res != kStdoutFd || kStdoutFd == kInvalidFd); + CHECK(res != kStderrFd || kStderrFd == kInvalidFd); + return res; } -uptr internal_stat(const char *path, void *buf) { - UNIMPLEMENTED(); +void CloseFile(fd_t fd) { + CloseHandle(fd); } -uptr internal_lstat(const char *path, void *buf) { +bool ReadFromFile(fd_t fd, void *buff, uptr buff_size, uptr *bytes_read, + error_t *error_p) { UNIMPLEMENTED(); } -uptr internal_fstat(fd_t fd, void *buf) { - UNIMPLEMENTED(); +bool SupportsColoredOutput(fd_t fd) { + // FIXME: support colored output. + return false; } -uptr internal_filesize(fd_t fd) { - UNIMPLEMENTED(); -} +bool WriteToFile(fd_t fd, const void *buff, uptr buff_size, uptr *bytes_written, + error_t *error_p) { + CHECK(fd != kInvalidFd); -uptr internal_dup2(int oldfd, int newfd) { - UNIMPLEMENTED(); + if (fd == kStdoutFd) { + fd = GetStdHandle(STD_OUTPUT_HANDLE); + if (fd == 0) fd = kInvalidFd; + } else if (fd == kStderrFd) { + fd = GetStdHandle(STD_ERROR_HANDLE); + if (fd == 0) fd = kInvalidFd; + } + + DWORD internal_bytes_written; + if (fd == kInvalidFd || + WriteFile(fd, buff, buff_size, &internal_bytes_written, 0)) { + if (error_p) *error_p = GetLastError(); + return false; + } else { + if (bytes_written) *bytes_written = internal_bytes_written; + return true; + } } -uptr internal_readlink(const char *path, char *buf, uptr bufsize) { +bool RenameFile(const char *oldpath, const char *newpath, error_t *error_p) { UNIMPLEMENTED(); } @@ -473,10 +465,6 @@ uptr internal_ftruncate(fd_t fd, uptr size) { UNIMPLEMENTED(); } -uptr internal_rename(const char *oldpath, const char *newpath) { - UNIMPLEMENTED(); -} - uptr GetRSS() { return 0; } @@ -600,7 +588,7 @@ void BufferedStackTrace::SlowUnwindStackWithContext(uptr pc, void *context, void ReportFile::Write(const char *buffer, uptr length) { SpinMutexLock l(mu); ReopenIfNecessary(); - if (length != internal_write(fd, buffer, length)) { + if (!WriteToFile(fd, buffer, length)) { // stderr may be closed, but we may be able to print to the debugger // instead. This is the case when launching a program from Visual Studio, // and the following routine should write to its console. diff --git a/lib/sanitizer_common/scripts/sancov.py b/lib/sanitizer_common/scripts/sancov.py index 53180d09b..776b8d966 100755 --- a/lib/sanitizer_common/scripts/sancov.py +++ b/lib/sanitizer_common/scripts/sancov.py @@ -4,10 +4,11 @@ # We need to merge these integers into a set and then # either print them (as hex) or dump them into another file. import array -import struct -import sys import bisect +import glob import os.path +import struct +import sys prog_name = "" @@ -181,13 +182,19 @@ if __name__ == '__main__': if len(sys.argv) <= 2: Usage(); + file_list = [] + for f in sys.argv[2:]: + file_list += glob.glob(f) + if not file_list: + Usage() + if sys.argv[1] == "print": - PrintFiles(sys.argv[2:]) + PrintFiles(file_list) elif sys.argv[1] == "merge": - MergeAndPrint(sys.argv[2:]) + MergeAndPrint(file_list) elif sys.argv[1] == "unpack": - Unpack(sys.argv[2:]) + Unpack(file_list) elif sys.argv[1] == "rawunpack": - RawUnpack(sys.argv[2:]) + RawUnpack(file_list) else: Usage() diff --git a/lib/sanitizer_common/tests/sanitizer_libc_test.cc b/lib/sanitizer_common/tests/sanitizer_libc_test.cc index 279f6fed9..3252db776 100644 --- a/lib/sanitizer_common/tests/sanitizer_libc_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_libc_test.cc @@ -17,6 +17,7 @@ #if SANITIZER_LINUX || SANITIZER_MAC # define SANITIZER_TEST_HAS_STAT_H 1 # include <sys/stat.h> +# include "sanitizer_common/sanitizer_posix.h" #else # define SANITIZER_TEST_HAS_STAT_H 0 #endif @@ -78,16 +79,14 @@ TEST(SanitizerCommon, FileOps) { char tmpfile[128]; temp_file_name(tmpfile, sizeof(tmpfile), "sanitizer_common.fileops.tmp."); - uptr openrv = OpenFile(tmpfile, WrOnly); - EXPECT_FALSE(internal_iserror(openrv)); - fd_t fd = openrv; + fd_t fd = OpenFile(tmpfile, WrOnly); + ASSERT_NE(fd, kInvalidFd); EXPECT_EQ(len1, internal_write(fd, str1, len1)); EXPECT_EQ(len2, internal_write(fd, str2, len2)); - internal_close(fd); + CloseFile(fd); - openrv = OpenFile(tmpfile, RdOnly); - EXPECT_FALSE(internal_iserror(openrv)); - fd = openrv; + fd = OpenFile(tmpfile, RdOnly); + ASSERT_NE(fd, kInvalidFd); uptr fsize = internal_filesize(fd); EXPECT_EQ(len1 + len2, fsize); @@ -115,7 +114,7 @@ TEST(SanitizerCommon, FileOps) { internal_memset(buf, 0, len1); EXPECT_EQ(len2, internal_read(fd, buf, len2)); EXPECT_EQ(0, internal_memcmp(buf, str2, len2)); - internal_close(fd); + CloseFile(fd); internal_unlink(tmpfile); } #endif @@ -134,12 +133,11 @@ TEST(SanitizerCommon, InternalMmapWithOffset) { char tmpfile[128]; temp_file_name(tmpfile, sizeof(tmpfile), "sanitizer_common.internalmmapwithoffset.tmp."); - uptr res = OpenFile(tmpfile, RdWr); - ASSERT_FALSE(internal_iserror(res)); - fd_t fd = res; + fd_t fd = OpenFile(tmpfile, RdWr); + ASSERT_NE(fd, kInvalidFd); uptr page_size = GetPageSizeCached(); - res = internal_ftruncate(fd, page_size * 2); + uptr res = internal_ftruncate(fd, page_size * 2); ASSERT_FALSE(internal_iserror(res)); res = internal_lseek(fd, page_size, SEEK_SET); @@ -154,8 +152,8 @@ TEST(SanitizerCommon, InternalMmapWithOffset) { ASSERT_EQ('A', p[0]); ASSERT_EQ('B', p[1]); - internal_close(fd); - internal_munmap(p, page_size); + CloseFile(fd); + UnmapOrDie(p, page_size); internal_unlink(tmpfile); } #endif diff --git a/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc b/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc index abe4ef430..12bc9e181 100644 --- a/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_procmaps_test.cc @@ -37,8 +37,7 @@ TEST(MemoryMappingLayout, DumpListOfModules) { const char *binary_name = last_slash ? last_slash + 1 : argv0; MemoryMappingLayout memory_mapping(false); const uptr kMaxModules = 100; - LoadedModule *modules = - (LoadedModule *)malloc(kMaxModules * sizeof(LoadedModule)); + LoadedModule modules[kMaxModules]; uptr n_modules = memory_mapping.DumpListOfModules(modules, kMaxModules, 0); EXPECT_GT(n_modules, 0U); bool found = false; @@ -51,7 +50,6 @@ TEST(MemoryMappingLayout, DumpListOfModules) { modules[i].clear(); } EXPECT_TRUE(found); - free(modules); } } // namespace __sanitizer diff --git a/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc b/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc index a8bd7261e..654ea1db8 100644 --- a/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc +++ b/lib/sanitizer_common/tests/sanitizer_stacktrace_test.cc @@ -45,7 +45,7 @@ static uptr PC(uptr idx) { void FastUnwindTest::SetUp() { size_t ps = GetPageSize(); mapping = MmapOrDie(2 * ps, "FastUnwindTest"); - Mprotect((uptr)mapping, ps); + MprotectNoAccess((uptr)mapping, ps); // Unwinder may peek 1 word down from the starting FP. fake_stack = (uhwptr *)((uptr)mapping + ps + sizeof(uhwptr)); |