Index: compiler-rt/lib/sanitizer_common/CMakeLists.txt =================================================================== --- compiler-rt/lib/sanitizer_common/CMakeLists.txt +++ compiler-rt/lib/sanitizer_common/CMakeLists.txt @@ -73,6 +73,7 @@ sanitizer_stacktrace.cc sanitizer_stacktrace_libcdep.cc sanitizer_stacktrace_printer.cc + sanitizer_stacktrace_sparc.cc sanitizer_symbolizer.cc sanitizer_symbolizer_fuchsia.cc sanitizer_symbolizer_libbacktrace.cc Index: compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc +++ compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.cc @@ -20,7 +20,7 @@ uptr StackTrace::GetNextInstructionPc(uptr pc) { #if defined(__mips__) return pc + 8; -#elif defined(__powerpc__) +#elif defined(__powerpc__) || defined(__sparc__) return pc + 4; #else return pc + 1; @@ -40,6 +40,9 @@ top_frame_bp = 0; } +// Sparc implemention is in its own file. +#if !defined(__sparc__) + // In GCC on ARM bp points to saved lr, not fp, so we should check the next // cell in stack to be a saved frame pointer. GetCanonicFrame returns the // pointer to saved frame pointer in any case. @@ -106,6 +109,8 @@ } } +#endif // !defined(__sparc__) + void BufferedStackTrace::PopStackFrames(uptr count) { CHECK_LT(count, size); size -= count; Index: compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_sparc.cc =================================================================== --- /dev/null +++ compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_sparc.cc @@ -0,0 +1,58 @@ +//===-- sanitizer_stacktrace_sparc.cc -------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is shared between AddressSanitizer and ThreadSanitizer +// run-time libraries. +// +// Implemention of fast stack unwinding for Sparc. +//===----------------------------------------------------------------------===// + +// This file is ported to Sparc v8, but it should be easy to port to +// Sparc v9. +#if defined(__sparcv8__) + +#include "sanitizer_common.h" +#include "sanitizer_stacktrace.h" + +namespace __sanitizer { + +void BufferedStackTrace::FastUnwindStack(uptr pc, uptr bp, uptr stack_top, + uptr stack_bottom, u32 max_depth) { + const uptr kPageSize = GetPageSizeCached(); + CHECK_GE(max_depth, 2); + trace_buffer[0] = pc; + size = 1; + if (stack_top < 4096) return; // Sanity check for stack top. + // Flush register windows to memory + asm volatile("ta 3" ::: "memory"); + uhwptr *frame = (uhwptr*)bp; + // Lowest possible address that makes sense as the next frame pointer. + // Goes up as we walk the stack. + uptr bottom = stack_bottom; + // Avoid infinite loop when frame == frame[0] by using frame > prev_frame. + while (IsValidFrame((uptr)frame, stack_top, bottom) && + IsAligned((uptr)frame, sizeof(*frame)) && + size < max_depth) { + uhwptr pc1 = frame[15]; + // Let's assume that any pointer in the 0th page is invalid and + // stop unwinding here. If we're adding support for a platform + // where this isn't true, we need to reconsider this check. + if (pc1 < kPageSize) + break; + if (pc1 != pc) { + trace_buffer[size++] = (uptr) pc1; + } + bottom = (uptr)frame; + frame = (uhwptr*)frame[14]; + } +} + +} // namespace __sanitizer + +#endif // !defined(__sparcv8__)