summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Lettner <jlettner@apple.com>2019-03-01 04:03:38 +0000
committerJulian Lettner <jlettner@apple.com>2019-03-01 04:03:38 +0000
commit27f8cfe7f25cdb667703d8c1f7e10473d167239e (patch)
tree6e9d31731b32b62f717f97218a8c86c06d336d41
parentf868cf800339c50fb704c76e1d1349bc4faf2871 (diff)
downloadcompiler-rt-27f8cfe7f25cdb667703d8c1f7e10473d167239e.tar.gz
[NFC][Sanitizer] Add new BufferedStackTrace::Unwind API
Retrying without replacing call sites in sanitizer_common (which might not have a symbol definition). Add new Unwind API. This is the final envisioned API with the correct abstraction level. It hides/slow fast unwinder selection from the caller and doesn't take any arguments that would leak that abstraction (i.e., arguments like stack_top/stack_bottom). GetStackTrace will become an implementation detail (private method) of the BufferedStackTrace class. Reviewers: vitalybuka Differential Revision: https://reviews.llvm.org/D58741 llvm-svn: 355168 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@355172 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/asan/asan_errors.cc2
-rw-r--r--lib/asan/asan_stack.h12
-rw-r--r--lib/hwasan/hwasan.h13
-rw-r--r--lib/hwasan/hwasan_linux.cpp7
-rw-r--r--lib/lsan/lsan.cc2
-rw-r--r--lib/lsan/lsan.h4
-rw-r--r--lib/msan/msan.cc2
-rw-r--r--lib/msan/msan.h25
-rw-r--r--lib/sanitizer_common/sanitizer_stacktrace.h45
-rw-r--r--lib/tsan/rtl/tsan_rtl.cc10
-rw-r--r--lib/tsan/rtl/tsan_rtl_report.cc12
-rw-r--r--lib/ubsan/ubsan_diag_standalone.cc24
12 files changed, 80 insertions, 78 deletions
diff --git a/lib/asan/asan_errors.cc b/lib/asan/asan_errors.cc
index 6fd465d61..16a300967 100644
--- a/lib/asan/asan_errors.cc
+++ b/lib/asan/asan_errors.cc
@@ -35,7 +35,7 @@ static void OnStackUnwind(const SignalContext &sig,
// corresponding code in the sanitizer_common and we use this callback to
// print it.
static_cast<const ScarinessScoreBase *>(callback_context)->Print();
- GetStackTrace(stack, kStackTraceMax, sig.pc, sig.bp, sig.context, fast);
+ stack->Unwind(sig.pc, sig.bp, sig.context, fast);
}
void ErrorDeadlySignal::Print() {
diff --git a/lib/asan/asan_stack.h b/lib/asan/asan_stack.h
index 3480d91c6..3a4b3cefc 100644
--- a/lib/asan/asan_stack.h
+++ b/lib/asan/asan_stack.h
@@ -42,19 +42,19 @@ u32 GetMallocContextSize();
if (max_size > 1) stack.trace_buffer[1] = GET_CALLER_PC(); \
} \
} else { \
- GetStackTrace(&stack, max_size, StackTrace::GetCurrentPc(), \
- GET_CURRENT_FRAME(), 0, fast); \
+ stack.Unwind(StackTrace::GetCurrentPc(), \
+ GET_CURRENT_FRAME(), nullptr, fast, max_size); \
}
#define GET_STACK_TRACE_FATAL(pc, bp) \
BufferedStackTrace stack; \
- GetStackTrace(&stack, kStackTraceMax, pc, bp, 0, \
- common_flags()->fast_unwind_on_fatal)
+ stack.Unwind(pc, bp, nullptr, \
+ common_flags()->fast_unwind_on_fatal)
#define GET_STACK_TRACE_SIGNAL(sig) \
BufferedStackTrace stack; \
- GetStackTrace(&stack, kStackTraceMax, (sig).pc, (sig).bp, (sig).context, \
- common_flags()->fast_unwind_on_fatal)
+ stack.Unwind((sig).pc, (sig).bp, (sig).context, \
+ common_flags()->fast_unwind_on_fatal)
#define GET_STACK_TRACE_FATAL_HERE \
GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_fatal)
diff --git a/lib/hwasan/hwasan.h b/lib/hwasan/hwasan.h
index b7357e915..74eaa0c7d 100644
--- a/lib/hwasan/hwasan.h
+++ b/lib/hwasan/hwasan.h
@@ -112,16 +112,15 @@ const int STACK_TRACE_TAG_POISON = StackTrace::TAG_CUSTOM + 1;
#define GET_MALLOC_STACK_TRACE \
BufferedStackTrace stack; \
- if (hwasan_inited) \
- GetStackTrace(&stack, common_flags()->malloc_context_size, \
- StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), nullptr, \
- common_flags()->fast_unwind_on_malloc)
+ if (hwasan_inited) \
+ stack.Unwind(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), \
+ nullptr, common_flags()->fast_unwind_on_malloc, \
+ common_flags()->malloc_context_size)
#define GET_FATAL_STACK_TRACE_PC_BP(pc, bp) \
BufferedStackTrace stack; \
- if (hwasan_inited) \
- GetStackTrace(&stack, kStackTraceMax, pc, bp, nullptr, \
- common_flags()->fast_unwind_on_fatal)
+ if (hwasan_inited) \
+ stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal)
#define GET_FATAL_STACK_TRACE_HERE \
GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME())
diff --git a/lib/hwasan/hwasan_linux.cpp b/lib/hwasan/hwasan_linux.cpp
index 4ab7c323d..ce0c55f06 100644
--- a/lib/hwasan/hwasan_linux.cpp
+++ b/lib/hwasan/hwasan_linux.cpp
@@ -378,8 +378,7 @@ static void HandleTagMismatch(AccessInfo ai, uptr pc, uptr frame,
InternalMmapVector<BufferedStackTrace> stack_buffer(1);
BufferedStackTrace *stack = stack_buffer.data();
stack->Reset();
- GetStackTrace(stack, kStackTraceMax, pc, frame, uc,
- common_flags()->fast_unwind_on_fatal);
+ stack->Unwind(pc, frame, uc, common_flags()->fast_unwind_on_fatal);
bool fatal = flags()->halt_on_error || !ai.recover;
ReportTagMismatch(stack, ai.addr, ai.size, ai.is_store, fatal);
@@ -417,8 +416,8 @@ extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __hwasan_tag_mismatch(
static void OnStackUnwind(const SignalContext &sig, const void *,
BufferedStackTrace *stack) {
- GetStackTrace(stack, kStackTraceMax, StackTrace::GetNextInstructionPc(sig.pc),
- sig.bp, sig.context, common_flags()->fast_unwind_on_fatal);
+ stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
+ common_flags()->fast_unwind_on_fatal);
}
void HwasanOnDeadlySignal(int signo, void *info, void *context) {
diff --git a/lib/lsan/lsan.cc b/lib/lsan/lsan.cc
index cf8d52661..5ff7347c2 100644
--- a/lib/lsan/lsan.cc
+++ b/lib/lsan/lsan.cc
@@ -89,7 +89,7 @@ static void InitializeFlags() {
static void OnStackUnwind(const SignalContext &sig, const void *,
BufferedStackTrace *stack) {
- GetStackTrace(stack, kStackTraceMax, sig.pc, sig.bp, sig.context,
+ stack->Unwind(sig.pc, sig.bp, sig.context,
common_flags()->fast_unwind_on_fatal);
}
diff --git a/lib/lsan/lsan.h b/lib/lsan/lsan.h
index 049fba2be..9904ada4b 100644
--- a/lib/lsan/lsan.h
+++ b/lib/lsan/lsan.h
@@ -17,8 +17,8 @@
#define GET_STACK_TRACE(max_size, fast) \
__sanitizer::BufferedStackTrace stack; \
- GetStackTrace(&stack, max_size, StackTrace::GetCurrentPc(), \
- GET_CURRENT_FRAME(), nullptr, fast);
+ stack.Unwind(StackTrace::GetCurrentPc(), \
+ GET_CURRENT_FRAME(), nullptr, fast, max_size);
#define GET_STACK_TRACE_FATAL \
GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_fatal)
diff --git a/lib/msan/msan.cc b/lib/msan/msan.cc
index 29d58c0a2..1ecbcd44b 100644
--- a/lib/msan/msan.cc
+++ b/lib/msan/msan.cc
@@ -382,7 +382,7 @@ void __msan_warning_noreturn() {
static void OnStackUnwind(const SignalContext &sig, const void *,
BufferedStackTrace *stack) {
- GetStackTrace(stack, kStackTraceMax, sig.pc, sig.bp, sig.context,
+ stack->Unwind(sig.pc, sig.bp, sig.context,
common_flags()->fast_unwind_on_fatal);
}
diff --git a/lib/msan/msan.h b/lib/msan/msan.h
index 6d17f50db..211256833 100644
--- a/lib/msan/msan.h
+++ b/lib/msan/msan.h
@@ -325,23 +325,21 @@ const int STACK_TRACE_TAG_POISON = StackTrace::TAG_CUSTOM + 1;
#define GET_MALLOC_STACK_TRACE \
BufferedStackTrace stack; \
if (__msan_get_track_origins() && msan_inited) \
- GetStackTrace(&stack, common_flags()->malloc_context_size, \
- StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), nullptr, \
- common_flags()->fast_unwind_on_malloc)
+ stack.Unwind(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME(), \
+ nullptr, common_flags()->fast_unwind_on_malloc, \
+ common_flags()->malloc_context_size)
// For platforms which support slow unwinder only, we restrict the store context
// size to 1, basically only storing the current pc. We do this because the slow
// unwinder which is based on libunwind is not async signal safe and causes
// random freezes in forking applications as well as in signal handlers.
-#define GET_STORE_STACK_TRACE_PC_BP(pc, bp) \
- BufferedStackTrace stack; \
- if (__msan_get_track_origins() > 1 && msan_inited) { \
- if (!SANITIZER_CAN_FAST_UNWIND) \
- GetStackTrace(&stack, Min(1, flags()->store_context_size), pc, bp, \
- nullptr, false); \
- else \
- GetStackTrace(&stack, flags()->store_context_size, pc, bp, nullptr, \
- common_flags()->fast_unwind_on_malloc); \
+#define GET_STORE_STACK_TRACE_PC_BP(pc, bp) \
+ BufferedStackTrace stack; \
+ if (__msan_get_track_origins() > 1 && msan_inited) { \
+ int size = flags()->store_context_size; \
+ if (!SANITIZER_CAN_FAST_UNWIND) \
+ size = Min(size, 1); \
+ stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_malloc, size);\
}
#define GET_STORE_STACK_TRACE \
@@ -350,8 +348,7 @@ const int STACK_TRACE_TAG_POISON = StackTrace::TAG_CUSTOM + 1;
#define GET_FATAL_STACK_TRACE_PC_BP(pc, bp) \
BufferedStackTrace stack; \
if (msan_inited) \
- GetStackTrace(&stack, kStackTraceMax, pc, bp, nullptr, \
- common_flags()->fast_unwind_on_fatal)
+ stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal)
#define GET_FATAL_STACK_TRACE_HERE \
GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME())
diff --git a/lib/sanitizer_common/sanitizer_stacktrace.h b/lib/sanitizer_common/sanitizer_stacktrace.h
index eeed983f6..b62d21385 100644
--- a/lib/sanitizer_common/sanitizer_stacktrace.h
+++ b/lib/sanitizer_common/sanitizer_stacktrace.h
@@ -16,6 +16,13 @@
namespace __sanitizer {
+struct BufferedStackTrace;
+// Get the stack trace with the given pc and bp.
+// The pc will be in the position 0 of the resulting stack trace.
+// The bp may refer to the current frame or to the caller's frame.
+void GetStackTrace(BufferedStackTrace *stack, uptr max_depth, uptr pc, uptr bp,
+ void *context, bool request_fast_unwind);
+
static const u32 kStackTraceMax = 256;
#if defined(__sparc__) || (SANITIZER_LINUX && defined(__mips__))
@@ -96,6 +103,20 @@ struct BufferedStackTrace : public StackTrace {
BufferedStackTrace() : StackTrace(trace_buffer, 0), top_frame_bp(0) {}
void Init(const uptr *pcs, uptr cnt, uptr extra_top_pc = 0);
+
+ void Unwind(uptr pc, uptr bp, void *context, bool request_fast,
+ u32 max_depth = kStackTraceMax) {
+ top_frame_bp = (max_depth > 0) ? bp : 0;
+ // Small max_depth optimization
+ if (max_depth <= 1) {
+ if (max_depth == 1)
+ trace_buffer[0] = pc;
+ size = max_depth;
+ return;
+ }
+ GetStackTrace(this, max_depth, pc, bp, context, request_fast);
+ }
+
void Unwind(u32 max_depth, uptr pc, uptr bp, void *context, uptr stack_top,
uptr stack_bottom, bool request_fast_unwind);
@@ -121,31 +142,27 @@ static inline bool IsValidFrame(uptr frame, uptr stack_top, uptr stack_bottom) {
return frame > stack_bottom && frame < stack_top - 2 * sizeof (uhwptr);
}
-// Get the stack trace with the given pc and bp.
-// The pc will be in the position 0 of the resulting stack trace.
-// The bp may refer to the current frame or to the caller's frame.
-void GetStackTrace(BufferedStackTrace *stack, uptr max_depth, uptr pc, uptr bp,
- void *context, bool request_fast_unwind);
-
} // namespace __sanitizer
// Use this macro if you want to print stack trace with the caller
// of the current function in the top frame.
-#define GET_CALLER_PC_BP_SP \
- uptr bp = GET_CURRENT_FRAME(); \
- uptr pc = GET_CALLER_PC(); \
- uptr local_stack; \
- uptr sp = (uptr)&local_stack
-
#define GET_CALLER_PC_BP \
uptr bp = GET_CURRENT_FRAME(); \
uptr pc = GET_CALLER_PC();
+#define GET_CALLER_PC_BP_SP \
+ GET_CALLER_PC_BP; \
+ uptr local_stack; \
+ uptr sp = (uptr)&local_stack
+
// Use this macro if you want to print stack trace with the current
// function in the top frame.
-#define GET_CURRENT_PC_BP_SP \
+#define GET_CURRENT_PC_BP \
uptr bp = GET_CURRENT_FRAME(); \
- uptr pc = StackTrace::GetCurrentPc(); \
+ uptr pc = StackTrace::GetCurrentPc()
+
+#define GET_CURRENT_PC_BP_SP \
+ GET_CURRENT_PC_BP; \
uptr local_stack; \
uptr sp = (uptr)&local_stack
diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc
index 0b690b78a..3d23f5047 100644
--- a/lib/tsan/rtl/tsan_rtl.cc
+++ b/lib/tsan/rtl/tsan_rtl.cc
@@ -328,14 +328,8 @@ static void CheckShadowMapping() {
#if !SANITIZER_GO
static void OnStackUnwind(const SignalContext &sig, const void *,
BufferedStackTrace *stack) {
- uptr top = 0;
- uptr bottom = 0;
- bool fast = common_flags()->fast_unwind_on_fatal;
- if (StackTrace::WillUseFastUnwind(fast)) {
- GetThreadStackTopAndBottom(false, &top, &bottom);
- stack->Unwind(kStackTraceMax, sig.pc, sig.bp, nullptr, top, bottom, true);
- } else
- stack->Unwind(kStackTraceMax, sig.pc, 0, sig.context, 0, 0, false);
+ stack->Unwind(sig.pc, sig.bp, sig.context,
+ common_flags()->fast_unwind_on_fatal);
}
static void TsanOnDeadlySignal(int signo, void *siginfo, void *context) {
diff --git a/lib/tsan/rtl/tsan_rtl_report.cc b/lib/tsan/rtl/tsan_rtl_report.cc
index 77fbcb0fd..220a425a2 100644
--- a/lib/tsan/rtl/tsan_rtl_report.cc
+++ b/lib/tsan/rtl/tsan_rtl_report.cc
@@ -729,18 +729,12 @@ void PrintCurrentStack(ThreadState *thr, uptr pc) {
ALWAYS_INLINE
void PrintCurrentStackSlow(uptr pc) {
#if !SANITIZER_GO
- uptr bp = 0;
- uptr top = 0;
- uptr bottom = 0;
+ uptr bp = GET_CURRENT_FRAME();
BufferedStackTrace *ptrace =
new(internal_alloc(MBlockStackTrace, sizeof(BufferedStackTrace)))
BufferedStackTrace();
- if (__sanitizer::StackTrace::WillUseFastUnwind(false)) {
- bp = GET_CURRENT_FRAME();
- __sanitizer::GetThreadStackTopAndBottom(false, &top, &bottom);
- ptrace->Unwind(kStackTraceMax, pc, bp, nullptr, top, bottom, true);
- } else
- ptrace->Unwind(kStackTraceMax, pc, 0, nullptr, 0, 0, false);
+ ptrace->Unwind(pc, bp, nullptr, false);
+
for (uptr i = 0; i < ptrace->size / 2; i++) {
uptr tmp = ptrace->trace_buffer[i];
ptrace->trace_buffer[i] = ptrace->trace_buffer[ptrace->size - i - 1];
diff --git a/lib/ubsan/ubsan_diag_standalone.cc b/lib/ubsan/ubsan_diag_standalone.cc
index 1eff0908e..d2b7d6e69 100644
--- a/lib/ubsan/ubsan_diag_standalone.cc
+++ b/lib/ubsan/ubsan_diag_standalone.cc
@@ -16,21 +16,23 @@
using namespace __ubsan;
+void __sanitizer::GetStackTrace(BufferedStackTrace *stack, uptr max_depth,
+ uptr pc, uptr bp, void *context, bool fast) {
+ uptr top = 0;
+ uptr bottom = 0;
+ if (StackTrace::WillUseFastUnwind(fast)) {
+ GetThreadStackTopAndBottom(false, &top, &bottom);
+ stack->Unwind(max_depth, pc, bp, nullptr, top, bottom, true);
+ } else
+ stack->Unwind(max_depth, pc, bp, context, 0, 0, false);
+}
+
extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE
void __sanitizer_print_stack_trace() {
- uptr top = 0;
- uptr bottom = 0;
- bool request_fast_unwind = common_flags()->fast_unwind_on_fatal;
- GET_CURRENT_PC_BP_SP;
- (void)sp;
+ GET_CURRENT_PC_BP;
BufferedStackTrace stack;
- if (__sanitizer::StackTrace::WillUseFastUnwind(request_fast_unwind)) {
- __sanitizer::GetThreadStackTopAndBottom(false, &top, &bottom);
- stack.Unwind(kStackTraceMax, pc, bp, nullptr, top, bottom, true);
- } else {
- stack.Unwind(kStackTraceMax, pc, 0, nullptr, 0, 0, false);
- }
+ stack.Unwind(pc, bp, nullptr, common_flags()->fast_unwind_on_fatal);
stack.Print();
}
} // extern "C"