| //===-- 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__) |