diff options
-rw-r--r-- | include/sanitizer/asan_interface.h | 12 | ||||
-rw-r--r-- | lib/asan/asan_internal.h | 4 | ||||
-rw-r--r-- | lib/asan/asan_rtl.cc | 5 | ||||
-rw-r--r-- | lib/asan/asan_stack.cc | 17 | ||||
-rw-r--r-- | lib/asan/asan_win.cc | 87 | ||||
-rw-r--r-- | lib/asan/lit_tests/symbolize_callback.cc | 8 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_stacktrace.cc | 68 |
7 files changed, 109 insertions, 92 deletions
diff --git a/include/sanitizer/asan_interface.h b/include/sanitizer/asan_interface.h index 4d344f6a2..787e8116c 100644 --- a/include/sanitizer/asan_interface.h +++ b/include/sanitizer/asan_interface.h @@ -135,15 +135,13 @@ extern "C" { void __asan_set_on_error_callback(void (*callback)(void)) SANITIZER_INTERFACE_ATTRIBUTE; - // User may register its own symbolization function. It should print - // the description of instruction at address "pc" to "out_buffer". - // Description should be at most "out_size" bytes long. + // User may provide its own implementation for symbolization function. + // It should print the description of instruction at address "pc" to + // "out_buffer". Description should be at most "out_size" bytes long. // User-specified function should return true if symbolization was // successful. - typedef bool (*__asan_symbolize_callback)(const void *pc, char *out_buffer, - int out_size); - void __asan_set_symbolize_callback(__asan_symbolize_callback callback) - SANITIZER_INTERFACE_ATTRIBUTE; + bool __asan_symbolize(const void *pc, char *out_buffer, int out_size) + SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE; // Returns the estimated number of bytes that will be reserved by allocator // for request of "size" bytes. If ASan allocator can't allocate that much diff --git a/lib/asan/asan_internal.h b/lib/asan/asan_internal.h index 178a3b735..652ac21cf 100644 --- a/lib/asan/asan_internal.h +++ b/lib/asan/asan_internal.h @@ -149,10 +149,6 @@ extern int asan_inited; extern bool asan_init_is_running; extern void (*death_callback)(void); -#ifdef _WIN32 -bool WinSymbolize(const void *addr, char *out_buffer, int buffer_size); -#endif // _WIN32 - // These magic values are written to shadow for better error reporting. const int kAsanHeapLeftRedzoneMagic = 0xfa; const int kAsanHeapRightRedzoneMagic = 0xfb; diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc index 97cb061d8..c7aedb28b 100644 --- a/lib/asan/asan_rtl.cc +++ b/lib/asan/asan_rtl.cc @@ -247,7 +247,7 @@ static NOINLINE void force_interface_symbols() { case 33: __asan_after_dynamic_init(); break; case 34: __asan_malloc_hook(0, 0); break; case 35: __asan_free_hook(0); break; - case 36: __asan_set_symbolize_callback(0); break; + case 36: __asan_symbolize(0, 0, 0); break; } } @@ -376,9 +376,6 @@ void __asan_init() { InitializeExternalSymbolizer(external_symbolizer); } } -#ifdef _WIN32 - __asan_set_symbolize_callback(WinSymbolize); -#endif // _WIN32 // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited // should be set to 1 prior to initializing the threads. diff --git a/lib/asan/asan_stack.cc b/lib/asan/asan_stack.cc index f8ebc8234..53a46470a 100644 --- a/lib/asan/asan_stack.cc +++ b/lib/asan/asan_stack.cc @@ -17,20 +17,21 @@ namespace __asan { -static __asan_symbolize_callback symbolize_callback; - void PrintStack(StackTrace *stack) { stack->PrintStack(stack->trace, stack->size, flags()->symbolize, - flags()->strip_path_prefix, symbolize_callback); + flags()->strip_path_prefix, __asan_symbolize); } - } // namespace __asan // ------------------ Interface -------------- {{{1 -using namespace __asan; // NOLINT -void NOINLINE __asan_set_symbolize_callback( - __asan_symbolize_callback callback) { - symbolize_callback = callback; +// Provide default implementation of __asan_symbolize that does nothing +// and may be overriden by user if he wants to use his own symbolization. +// ASan on Windows has its own implementation of this. +#ifndef _WIN32 +SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE NOINLINE +bool __asan_symbolize(const void *pc, char *out_buffer, int out_size) { + return false; } +#endif diff --git a/lib/asan/asan_win.cc b/lib/asan/asan_win.cc index dc2654a3a..8bee62e6d 100644 --- a/lib/asan/asan_win.cc +++ b/lib/asan/asan_win.cc @@ -55,47 +55,6 @@ void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp) { stack->trace[i] = (uptr)tmp[i + offset]; } -bool WinSymbolize(const void *addr, char *out_buffer, int buffer_size) { - ScopedLock lock(&dbghelp_lock); - if (!dbghelp_initialized) { - SymSetOptions(SYMOPT_DEFERRED_LOADS | - SYMOPT_UNDNAME | - SYMOPT_LOAD_LINES); - CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE)); - // FIXME: We don't call SymCleanup() on exit yet - should we? - dbghelp_initialized = true; - } - - // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx - char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)]; - PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; - symbol->SizeOfStruct = sizeof(SYMBOL_INFO); - symbol->MaxNameLen = MAX_SYM_NAME; - DWORD64 offset = 0; - BOOL got_objname = SymFromAddr(GetCurrentProcess(), - (DWORD64)addr, &offset, symbol); - if (!got_objname) - return false; - - DWORD unused; - IMAGEHLP_LINE64 info; - info.SizeOfStruct = sizeof(IMAGEHLP_LINE64); - BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), - (DWORD64)addr, &unused, &info); - int written = 0; - out_buffer[0] = '\0'; - // FIXME: it might be useful to print out 'obj' or 'obj+offset' info too. - if (got_fileline) { - written += internal_snprintf(out_buffer + written, buffer_size - written, - " %s %s:%d", symbol->Name, - info.FileName, info.LineNumber); - } else { - written += internal_snprintf(out_buffer + written, buffer_size - written, - " %s+0x%p", symbol->Name, offset); - } - return true; -} - // ---------------------- AsanLock ---------------- {{{1 enum LockState { LOCK_UNINITIALIZED = 0, @@ -182,4 +141,50 @@ void AsanPlatformThreadInit() { } // namespace __asan +// ---------------------- Interface ---------------- {{{1 +using namespace __asan; // NOLINT + +bool __asan_symbolize(const void *addr, char *out_buffer, int buffer_size) { + ScopedLock lock(&dbghelp_lock); + if (!dbghelp_initialized) { + SymSetOptions(SYMOPT_DEFERRED_LOADS | + SYMOPT_UNDNAME | + SYMOPT_LOAD_LINES); + CHECK(SymInitialize(GetCurrentProcess(), 0, TRUE)); + // FIXME: We don't call SymCleanup() on exit yet - should we? + dbghelp_initialized = true; + } + + // See http://msdn.microsoft.com/en-us/library/ms680578(VS.85).aspx + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(CHAR)]; + PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + symbol->MaxNameLen = MAX_SYM_NAME; + DWORD64 offset = 0; + BOOL got_objname = SymFromAddr(GetCurrentProcess(), + (DWORD64)addr, &offset, symbol); + if (!got_objname) + return false; + + DWORD unused; + IMAGEHLP_LINE64 info; + info.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(), + (DWORD64)addr, &unused, &info); + int written = 0; + out_buffer[0] = '\0'; + // FIXME: it might be useful to print out 'obj' or 'obj+offset' info too. + if (got_fileline) { + written += internal_snprintf(out_buffer + written, buffer_size - written, + " %s %s:%d", symbol->Name, + info.FileName, info.LineNumber); + } else { + written += internal_snprintf(out_buffer + written, buffer_size - written, + " %s+0x%p", symbol->Name, offset); + } + return true; +} + + + #endif // _WIN32 diff --git a/lib/asan/lit_tests/symbolize_callback.cc b/lib/asan/lit_tests/symbolize_callback.cc index 08ed9644d..0691d501e 100644 --- a/lib/asan/lit_tests/symbolize_callback.cc +++ b/lib/asan/lit_tests/symbolize_callback.cc @@ -3,17 +3,13 @@ #include <stdio.h> #include <stdlib.h> -bool MySymbolizer(const void *pc, char *out_buffer, int out_size) { +extern "C" +bool __asan_symbolize(const void *pc, char *out_buffer, int out_size) { snprintf(out_buffer, out_size, "MySymbolizer"); return true; } -typedef bool (*asan_symbolize_callback)(const void*, char*, int); -extern "C" -void __asan_set_symbolize_callback(asan_symbolize_callback); - int main() { - __asan_set_symbolize_callback(MySymbolizer); char *x = (char*)malloc(10 * sizeof(char)); free(x); return x[5]; diff --git a/lib/sanitizer_common/sanitizer_stacktrace.cc b/lib/sanitizer_common/sanitizer_stacktrace.cc index 30a3ef3bd..30c9c85ae 100644 --- a/lib/sanitizer_common/sanitizer_stacktrace.cc +++ b/lib/sanitizer_common/sanitizer_stacktrace.cc @@ -36,6 +36,26 @@ static uptr patch_pc(uptr pc) { return pc - 1; } +static void PrintStackFramePrefix(uptr frame_num, uptr pc) { + Printf(" #%zu 0x%zx", frame_num, pc); +} + +static void PrintSourceLocation(const char *file, int line, int column, + const char *strip_file_prefix) { + CHECK(file); + Printf(" %s", StripPathPrefix(file, strip_file_prefix)); + if (line > 0) { + Printf(":%d", line); + if (column > 0) + Printf(":%d", column); + } +} + +static void PrintModuleAndOffset(const char *module, uptr offset, + const char *strip_file_prefix) { + Printf(" (%s+0x%zx)", StripPathPrefix(module, strip_file_prefix), offset); +} + void StackTrace::PrintStack(const uptr *addr, uptr size, bool symbolize, const char *strip_file_prefix, SymbolizeCallback symbolize_callback ) { @@ -45,45 +65,49 @@ void StackTrace::PrintStack(const uptr *addr, uptr size, uptr frame_num = 0; for (uptr i = 0; i < size && addr[i]; i++) { uptr pc = patch_pc(addr[i]); + uptr addr_frames_num = 0; // The number of stack frames for current + // instruction address. if (symbolize_callback) { - symbolize_callback((void*)pc, buff.data(), buff.size()); - // We can't know anything about the string returned by external - // symbolizer, but if it starts with filename, try to strip path prefix - // from it. - Printf(" #%zu 0x%zx %s\n", frame_num, pc, - StripPathPrefix(buff.data(), strip_file_prefix)); - frame_num++; - continue; - } - uptr addr_frames_num = - symbolize ? SymbolizeCode(pc, addr_frames.data(), addr_frames.size()) : 0; - if (addr_frames_num > 0) { + if (symbolize_callback((void*)pc, buff.data(), buff.size())) { + addr_frames_num = 1; + PrintStackFramePrefix(frame_num, pc); + // We can't know anything about the string returned by external + // symbolizer, but if it starts with filename, try to strip path prefix + // from it. + Printf(" %s\n", StripPathPrefix(buff.data(), strip_file_prefix)); + frame_num++; + } + } else if (symbolize) { + // Use our own (online) symbolizer, if necessary. + addr_frames_num = SymbolizeCode(pc, addr_frames.data(), addr_frames.size()); for (uptr j = 0; j < addr_frames_num; j++) { AddressInfo &info = addr_frames[j]; - Printf(" #%zu 0x%zx", frame_num, pc); + PrintStackFramePrefix(frame_num, pc); if (info.function) { Printf(" in %s", info.function); } if (info.file) { - Printf(" %s:%d:%d", StripPathPrefix(info.file, strip_file_prefix), - info.line, info.column); + PrintSourceLocation(info.file, info.line, info.column, + strip_file_prefix); } else if (info.module) { - Printf(" (%s+0x%zx)", StripPathPrefix(info.module, strip_file_prefix), - info.module_offset); + PrintModuleAndOffset(info.module, info.module_offset, + strip_file_prefix); } Printf("\n"); info.Clear(); frame_num++; } - } else { + } + if (addr_frames_num == 0) { + // If online symbolization failed, try to output at least module and + // offset for instruction. + PrintStackFramePrefix(frame_num, pc); uptr offset; if (proc_maps.GetObjectNameAndOffset(pc, &offset, buff.data(), buff.size())) { - Printf(" #%zu 0x%zx (%s+0x%zx)\n", frame_num, pc, - StripPathPrefix(buff.data(), strip_file_prefix), offset); - } else { - Printf(" #%zu 0x%zx\n", frame_num, pc); + PrintModuleAndOffset(buff.data(), offset, strip_file_prefix); } + Printf("\n"); frame_num++; } } |