Skip to content

Commit 6f86bdd

Browse files
committed
unwinding
1 parent c3715ec commit 6f86bdd

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

compiler-rt/lib/sanitizer_common/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ set(SANITIZER_SYMBOLIZER_SOURCES
9797
sanitizer_symbolizer_report_fuchsia.cpp
9898
sanitizer_symbolizer_win.cpp
9999
sanitizer_thread_history.cpp
100+
sanitizer_unwind_aix.cpp
100101
sanitizer_unwind_linux_libcdep.cpp
101102
sanitizer_unwind_fuchsia.cpp
102103
sanitizer_unwind_win.cpp
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//===-- sanitizer_unwind_aix.cpp ------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file contains the unwind.h-based (aka "slow") stack unwinding routines
10+
// available to the tools on AIX.
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "sanitizer_platform.h"
14+
15+
#if SANITIZER_AIX
16+
# include <unwind.h>
17+
18+
# include "sanitizer_common.h"
19+
# include "sanitizer_stacktrace.h"
20+
21+
namespace __sanitizer {
22+
23+
struct UnwindTraceArg {
24+
BufferedStackTrace *stack;
25+
u32 max_depth;
26+
};
27+
28+
_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
29+
UnwindTraceArg *arg = (UnwindTraceArg *)param;
30+
CHECK_LT(arg->stack->size, arg->max_depth);
31+
uptr pc = _Unwind_GetIP(ctx);
32+
// On AIX 32-bit and 64-bit, address smaller than 0x0fffffff is for kernel.
33+
if (pc <= 0x0fffffff)
34+
return _URC_NORMAL_STOP;
35+
arg->stack->trace_buffer[arg->stack->size++] = pc;
36+
if (arg->stack->size == arg->max_depth)
37+
return _URC_NORMAL_STOP;
38+
return _URC_NO_REASON;
39+
}
40+
41+
void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) {
42+
CHECK_GE(max_depth, 2);
43+
size = 0;
44+
UnwindTraceArg arg = {this, Min(max_depth + 1, kStackTraceMax)};
45+
_Unwind_Backtrace(Unwind_Trace, &arg);
46+
// We need to pop a few frames so that pc is on top.
47+
uptr to_pop = LocatePcInTrace(pc);
48+
// trace_buffer[0] belongs to the current function so we always pop it,
49+
// unless there is only 1 frame in the stack trace (1 frame is always better
50+
// than 0!).
51+
// 1-frame stacks don't normally happen, but this depends on the actual
52+
// unwinder implementation (libgcc, libunwind, etc) which is outside of our
53+
// control.
54+
if (to_pop == 0 && size > 1)
55+
to_pop = 1;
56+
57+
PopStackFrames(to_pop);
58+
trace_buffer[0] = pc;
59+
}
60+
61+
void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) {
62+
UnwindSlow(pc, max_depth);
63+
}
64+
} // namespace __sanitizer
65+
66+
#endif // SANITIZER_AIX

0 commit comments

Comments
 (0)