summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sanitizer/asan_interface.h12
-rw-r--r--lib/asan/asan_internal.h4
-rw-r--r--lib/asan/asan_rtl.cc5
-rw-r--r--lib/asan/asan_stack.cc17
-rw-r--r--lib/asan/asan_win.cc87
-rw-r--r--lib/asan/lit_tests/symbolize_callback.cc8
-rw-r--r--lib/sanitizer_common/sanitizer_stacktrace.cc68
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++;
}
}