Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler-rt/lib/sanitizer_common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ set(SANITIZER_SYMBOLIZER_SOURCES
sanitizer_symbolizer_report_fuchsia.cpp
sanitizer_symbolizer_win.cpp
sanitizer_thread_history.cpp
sanitizer_unwind_aix.cpp
sanitizer_unwind_linux_libcdep.cpp
sanitizer_unwind_fuchsia.cpp
sanitizer_unwind_win.cpp
Expand Down
66 changes: 66 additions & 0 deletions compiler-rt/lib/sanitizer_common/sanitizer_unwind_aix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//===-- sanitizer_unwind_aix.cpp ------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains the unwind.h-based (aka "slow") stack unwinding routines
// available to the tools on AIX.
//===----------------------------------------------------------------------===//

#include "sanitizer_platform.h"

#if SANITIZER_AIX
# include <unwind.h>

# include "sanitizer_common.h"
# include "sanitizer_stacktrace.h"

namespace __sanitizer {

struct UnwindTraceArg {
BufferedStackTrace *stack;
u32 max_depth;
};

_Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
UnwindTraceArg *arg = (UnwindTraceArg *)param;
CHECK_LT(arg->stack->size, arg->max_depth);
uptr pc = _Unwind_GetIP(ctx);
// On AIX 32-bit and 64-bit, address smaller than 0x0fffffff is for kernel.
if (pc <= 0x0fffffff)
return _URC_NORMAL_STOP;
arg->stack->trace_buffer[arg->stack->size++] = pc;
if (arg->stack->size == arg->max_depth)
return _URC_NORMAL_STOP;
return _URC_NO_REASON;
}

void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) {
CHECK_GE(max_depth, 2);
size = 0;
UnwindTraceArg arg = {this, Min(max_depth + 1, kStackTraceMax)};
_Unwind_Backtrace(Unwind_Trace, &arg);
// We need to pop a few frames so that pc is on top.
uptr to_pop = LocatePcInTrace(pc);
// trace_buffer[0] belongs to the current function so we always pop it,
// unless there is only 1 frame in the stack trace (1 frame is always better
// than 0!).
// 1-frame stacks don't normally happen, but this depends on the actual
// unwinder implementation (libgcc, libunwind, etc) which is outside of our
// control.
if (to_pop == 0 && size > 1)
to_pop = 1;

PopStackFrames(to_pop);
trace_buffer[0] = pc;
}

void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) {
UnwindSlow(pc, max_depth);
}
} // namespace __sanitizer

#endif // SANITIZER_AIX
Loading