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