10b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner//===-- sanitizer_stacktrace_test.cc --------------------------------------===//
20b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner//
30b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner//                     The LLVM Compiler Infrastructure
40b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner//
50b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner// This file is distributed under the University of Illinois Open Source
60b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner// License. See LICENSE.TXT for details.
70b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner//
80b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner//===----------------------------------------------------------------------===//
90b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner//
100b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
110b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner//
120b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner//===----------------------------------------------------------------------===//
130b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner
140b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner#include "sanitizer_common/sanitizer_common.h"
150b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner#include "sanitizer_common/sanitizer_stacktrace.h"
160b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner#include "gtest/gtest.h"
170b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner
180b487c02ed906e555fa473cea5afcd6363549373Reid Klecknernamespace __sanitizer {
190b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner
200b487c02ed906e555fa473cea5afcd6363549373Reid Klecknerclass FastUnwindTest : public ::testing::Test {
210b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner protected:
220b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  virtual void SetUp();
23f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov  bool TryFastUnwind(uptr max_depth) {
24f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov    if (!StackTrace::WillUseFastUnwind(true))
25f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov      return false;
262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    trace.Unwind(max_depth, start_pc, (uptr)&fake_stack[0], 0, fake_top,
27f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov                 fake_bottom, true);
28f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov    return true;
29f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov  }
300b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner
310b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  uptr fake_stack[10];
320b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  uptr start_pc;
330b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  uptr fake_top;
340b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  uptr fake_bottom;
350b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  StackTrace trace;
360b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner};
370b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner
38583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryanystatic uptr PC(uptr idx) {
39583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany  return (1<<20) + idx;
40583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany}
41583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany
420b487c02ed906e555fa473cea5afcd6363549373Reid Klecknervoid FastUnwindTest::SetUp() {
430b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  // Fill an array of pointers with fake fp+retaddr pairs.  Frame pointers have
440b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  // even indices.
457907f1d0bd86e83677f8ae3bea7dc484546042cdAlexey Samsonov  for (uptr i = 0; i+1 < ARRAY_SIZE(fake_stack); i += 2) {
460b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner    fake_stack[i] = (uptr)&fake_stack[i+2];  // fp
47583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany    fake_stack[i+1] = PC(i + 1); // retaddr
480b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  }
490b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  // Mark the last fp as zero to terminate the stack trace.
500b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  fake_stack[RoundDownTo(ARRAY_SIZE(fake_stack) - 1, 2)] = 0;
510b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner
520b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  // Top is two slots past the end because FastUnwindStack subtracts two.
530b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  fake_top = (uptr)&fake_stack[ARRAY_SIZE(fake_stack) + 2];
540b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  // Bottom is one slot before the start because FastUnwindStack uses >.
550b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  fake_bottom = (uptr)&fake_stack[-1];
56583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany  start_pc = PC(0);
570b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner}
580b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner
590b487c02ed906e555fa473cea5afcd6363549373Reid KlecknerTEST_F(FastUnwindTest, Basic) {
60f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov  if (!TryFastUnwind(kStackTraceMax))
61f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov    return;
620b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  // Should get all on-stack retaddrs and start_pc.
637907f1d0bd86e83677f8ae3bea7dc484546042cdAlexey Samsonov  EXPECT_EQ(6U, trace.size);
640b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  EXPECT_EQ(start_pc, trace.trace[0]);
65040620c84740b602bed9d67afeab2772d90b1158Alexey Samsonov  for (uptr i = 1; i <= 5; i++) {
66583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany    EXPECT_EQ(PC(i*2 - 1), trace.trace[i]);
670b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  }
680b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner}
690b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner
700b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner// From: http://code.google.com/p/address-sanitizer/issues/detail?id=162
710b487c02ed906e555fa473cea5afcd6363549373Reid KlecknerTEST_F(FastUnwindTest, FramePointerLoop) {
720b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  // Make one fp point to itself.
730b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  fake_stack[4] = (uptr)&fake_stack[4];
74f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov  if (!TryFastUnwind(kStackTraceMax))
75f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov    return;
760b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  // Should get all on-stack retaddrs up to the 4th slot and start_pc.
777907f1d0bd86e83677f8ae3bea7dc484546042cdAlexey Samsonov  EXPECT_EQ(4U, trace.size);
780b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  EXPECT_EQ(start_pc, trace.trace[0]);
79040620c84740b602bed9d67afeab2772d90b1158Alexey Samsonov  for (uptr i = 1; i <= 3; i++) {
80583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany    EXPECT_EQ(PC(i*2 - 1), trace.trace[i]);
810b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner  }
820b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner}
830b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner
84583025ddc52988cdcedb5dee57e0d66a0c586340Kostya SerebryanyTEST_F(FastUnwindTest, MisalignedFramePointer) {
85583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany  // Make one fp misaligned.
86583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany  fake_stack[4] += 3;
87f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov  if (!TryFastUnwind(kStackTraceMax))
88f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov    return;
89583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany  // Should get all on-stack retaddrs up to the 4th slot and start_pc.
90583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany  EXPECT_EQ(4U, trace.size);
91583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany  EXPECT_EQ(start_pc, trace.trace[0]);
92583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany  for (uptr i = 1; i < 4U; i++) {
93583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany    EXPECT_EQ(PC(i*2 - 1), trace.trace[i]);
94583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany  }
95583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany}
96583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany
97064da32709c8bf81283062abc04cf6e88e6c075dAlexey SamsonovTEST_F(FastUnwindTest, OneFrameStackTrace) {
98f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov  if (!TryFastUnwind(1))
99f16dc4234098a22a9d0d56f0198d87905481e7fdAlexey Samsonov    return;
100064da32709c8bf81283062abc04cf6e88e6c075dAlexey Samsonov  EXPECT_EQ(1U, trace.size);
101064da32709c8bf81283062abc04cf6e88e6c075dAlexey Samsonov  EXPECT_EQ(start_pc, trace.trace[0]);
1021b17f5b79d58c5aff291dde05727ad0b215b81c6Alexey Samsonov  EXPECT_EQ((uptr)&fake_stack[0], trace.top_frame_bp);
103064da32709c8bf81283062abc04cf6e88e6c075dAlexey Samsonov}
104583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany
1052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesTEST_F(FastUnwindTest, ZeroFramesStackTrace) {
1062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (!TryFastUnwind(0))
1072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return;
1082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  EXPECT_EQ(0U, trace.size);
1092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  EXPECT_EQ(0U, trace.top_frame_bp);
1102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesTEST(SlowUnwindTest, ShortStackTrace) {
1132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (StackTrace::WillUseFastUnwind(false))
1142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return;
1152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  StackTrace stack;
1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr pc = StackTrace::GetCurrentPc();
1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr bp = GET_CURRENT_FRAME();
1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  stack.Unwind(0, pc, bp, 0, 0, 0, false);
1192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  EXPECT_EQ(0U, stack.size);
1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  EXPECT_EQ(0U, stack.top_frame_bp);
1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  stack.Unwind(1, pc, bp, 0, 0, 0, false);
1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  EXPECT_EQ(1U, stack.size);
1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  EXPECT_EQ(pc, stack.trace[0]);
1242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  EXPECT_EQ(bp, stack.top_frame_bp);
1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
1270b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner}  // namespace __sanitizer
128