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(); 230b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner 240b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner uptr fake_stack[10]; 250b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner uptr start_pc; 260b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner uptr fake_top; 270b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner uptr fake_bottom; 280b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner StackTrace trace; 290b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner}; 300b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner 31583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryanystatic uptr PC(uptr idx) { 32583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany return (1<<20) + idx; 33583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany} 34583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany 350b487c02ed906e555fa473cea5afcd6363549373Reid Klecknervoid FastUnwindTest::SetUp() { 360b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner // Fill an array of pointers with fake fp+retaddr pairs. Frame pointers have 370b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner // even indices. 387907f1d0bd86e83677f8ae3bea7dc484546042cdAlexey Samsonov for (uptr i = 0; i+1 < ARRAY_SIZE(fake_stack); i += 2) { 390b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner fake_stack[i] = (uptr)&fake_stack[i+2]; // fp 40583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany fake_stack[i+1] = PC(i + 1); // retaddr 410b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner } 420b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner // Mark the last fp as zero to terminate the stack trace. 430b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner fake_stack[RoundDownTo(ARRAY_SIZE(fake_stack) - 1, 2)] = 0; 440b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner 450b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner // Top is two slots past the end because FastUnwindStack subtracts two. 460b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner fake_top = (uptr)&fake_stack[ARRAY_SIZE(fake_stack) + 2]; 470b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner // Bottom is one slot before the start because FastUnwindStack uses >. 480b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner fake_bottom = (uptr)&fake_stack[-1]; 49583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany start_pc = PC(0); 500b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner 510b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner // This is common setup done by __asan::GetStackTrace(). 520b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner trace.size = 0; 530b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner trace.max_size = ARRAY_SIZE(fake_stack); 540b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner trace.trace[0] = start_pc; 550b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner} 560b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner 570b487c02ed906e555fa473cea5afcd6363549373Reid KlecknerTEST_F(FastUnwindTest, Basic) { 580b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0], 590b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner fake_top, fake_bottom); 600b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner // Should get all on-stack retaddrs and start_pc. 617907f1d0bd86e83677f8ae3bea7dc484546042cdAlexey Samsonov EXPECT_EQ(6U, trace.size); 620b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner EXPECT_EQ(start_pc, trace.trace[0]); 63040620c84740b602bed9d67afeab2772d90b1158Alexey Samsonov for (uptr i = 1; i <= 5; i++) { 64583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany EXPECT_EQ(PC(i*2 - 1), trace.trace[i]); 650b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner } 660b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner} 670b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner 680b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner// From: http://code.google.com/p/address-sanitizer/issues/detail?id=162 690b487c02ed906e555fa473cea5afcd6363549373Reid KlecknerTEST_F(FastUnwindTest, FramePointerLoop) { 700b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner // Make one fp point to itself. 710b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner fake_stack[4] = (uptr)&fake_stack[4]; 720b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0], 730b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner fake_top, fake_bottom); 740b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner // Should get all on-stack retaddrs up to the 4th slot and start_pc. 757907f1d0bd86e83677f8ae3bea7dc484546042cdAlexey Samsonov EXPECT_EQ(4U, trace.size); 760b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner EXPECT_EQ(start_pc, trace.trace[0]); 77040620c84740b602bed9d67afeab2772d90b1158Alexey Samsonov for (uptr i = 1; i <= 3; i++) { 78583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany EXPECT_EQ(PC(i*2 - 1), trace.trace[i]); 790b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner } 800b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner} 810b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner 82583025ddc52988cdcedb5dee57e0d66a0c586340Kostya SerebryanyTEST_F(FastUnwindTest, MisalignedFramePointer) { 83583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany // Make one fp misaligned. 84583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany fake_stack[4] += 3; 85583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0], 86583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany fake_top, fake_bottom); 87583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany // Should get all on-stack retaddrs up to the 4th slot and start_pc. 88583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany EXPECT_EQ(4U, trace.size); 89583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany EXPECT_EQ(start_pc, trace.trace[0]); 90583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany for (uptr i = 1; i < 4U; i++) { 91583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany EXPECT_EQ(PC(i*2 - 1), trace.trace[i]); 92583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany } 93583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany} 94583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany 95583025ddc52988cdcedb5dee57e0d66a0c586340Kostya Serebryany 960b487c02ed906e555fa473cea5afcd6363549373Reid Kleckner} // namespace __sanitizer 97