sanitizer_stacktrace_test.cc revision 583025ddc52988cdcedb5dee57e0d66a0c586340
18dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor//===-- sanitizer_stacktrace_test.cc --------------------------------------===// 28dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor// 38dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor// The LLVM Compiler Infrastructure 48dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor// 58dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor// This file is distributed under the University of Illinois Open Source 68dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor// License. See LICENSE.TXT for details. 78dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor// 88dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor//===----------------------------------------------------------------------===// 98dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor// 108dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor// This file is a part of ThreadSanitizer/AddressSanitizer runtime. 118dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor// 128dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor//===----------------------------------------------------------------------===// 138dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor 148dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor#include "sanitizer_common/sanitizer_common.h" 158dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor#include "sanitizer_common/sanitizer_stacktrace.h" 16c2ee10d79f70036af652a395ac1f8273f3d04e12Douglas Gregor#include "gtest/gtest.h" 17c2ee10d79f70036af652a395ac1f8273f3d04e12Douglas Gregor 1892b7f70c924cbf4514e9e434cea7def51ab49860John McCallnamespace __sanitizer { 1930a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth 20c640058aa7f224a71ce3b1d2601d84e1b57f82d3Alexey Bataevclass FastUnwindTest : public ::testing::Test { 218211effbd3abc5948a5d6924c87e72323016a376Anders Carlsson protected: 228211effbd3abc5948a5d6924c87e72323016a376Anders Carlsson virtual void SetUp(); 238dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor 24ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko uptr fake_stack[10]; 258dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor uptr start_pc; 26ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko uptr fake_top; 27ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko uptr fake_bottom; 288dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor StackTrace trace; 298dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor}; 30ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko 31ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienkostatic uptr PC(uptr idx) { 328dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor return (1<<20) + idx; 33ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko} 34ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko 35ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienkovoid FastUnwindTest::SetUp() { 36ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko // Fill an array of pointers with fake fp+retaddr pairs. Frame pointers have 37ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko // even indices. 38ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko for (uptr i = 0; i+1 < ARRAY_SIZE(fake_stack); i += 2) { 398dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor fake_stack[i] = (uptr)&fake_stack[i+2]; // fp 409a55591af3e5506b95a9718e15380129fbfc5ebcSean Hunt fake_stack[i+1] = PC(i + 1); // retaddr 419a55591af3e5506b95a9718e15380129fbfc5ebcSean Hunt } 429a55591af3e5506b95a9718e15380129fbfc5ebcSean Hunt // Mark the last fp as zero to terminate the stack trace. 439a55591af3e5506b95a9718e15380129fbfc5ebcSean Hunt fake_stack[RoundDownTo(ARRAY_SIZE(fake_stack) - 1, 2)] = 0; 448dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor 45561d3abc881033776ece385a01a510e1cbc1fa92David Blaikie // Top is two slots past the end because FastUnwindStack subtracts two. 468dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor fake_top = (uptr)&fake_stack[ARRAY_SIZE(fake_stack) + 2]; 478dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor // Bottom is one slot before the start because FastUnwindStack uses >. 488dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor fake_bottom = (uptr)&fake_stack[-1]; 498dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor start_pc = PC(0); 509a55591af3e5506b95a9718e15380129fbfc5ebcSean Hunt 51ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko // This is common setup done by __asan::GetStackTrace(). 529a55591af3e5506b95a9718e15380129fbfc5ebcSean Hunt trace.size = 0; 538dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor trace.max_size = ARRAY_SIZE(fake_stack); 54ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko trace.trace[0] = start_pc; 558dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor} 56ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko 578dbc2694424b4e842b1d5ea39744a137b58600c3Douglas GregorTEST_F(FastUnwindTest, Basic) { 58ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0], 59ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko fake_top, fake_bottom); 60ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko // Should get all on-stack retaddrs and start_pc. 61ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko EXPECT_EQ(6U, trace.size); 62ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko EXPECT_EQ(start_pc, trace.trace[0]); 63ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko for (uptr i = 1; i <= 5; i++) { 64ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko EXPECT_EQ(PC(i*2 - 1), trace.trace[i]); 65ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko } 66ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko} 67ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko 68ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko// From: http://code.google.com/p/address-sanitizer/issues/detail?id=162 69ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander KornienkoTEST_F(FastUnwindTest, FramePointerLoop) { 70ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko // Make one fp point to itself. 71ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko fake_stack[4] = (uptr)&fake_stack[4]; 72ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0], 73ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko fake_top, fake_bottom); 74ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko // Should get all on-stack retaddrs up to the 4th slot and start_pc. 75ae54121c15cdd38f415f6fdda48215ab5e4dcee1Alexander Kornienko EXPECT_EQ(4U, trace.size); 768dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor EXPECT_EQ(start_pc, trace.trace[0]); 778dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor for (uptr i = 1; i <= 3; i++) { 788dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor EXPECT_EQ(PC(i*2 - 1), trace.trace[i]); 798dbc2694424b4e842b1d5ea39744a137b58600c3Douglas Gregor } 80} 81 82TEST_F(FastUnwindTest, MisalignedFramePointer) { 83 // Make one fp misaligned. 84 fake_stack[4] += 3; 85 trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0], 86 fake_top, fake_bottom); 87 // Should get all on-stack retaddrs up to the 4th slot and start_pc. 88 EXPECT_EQ(4U, trace.size); 89 EXPECT_EQ(start_pc, trace.trace[0]); 90 for (uptr i = 1; i < 4U; i++) { 91 EXPECT_EQ(PC(i*2 - 1), trace.trace[i]); 92 } 93} 94 95 96} // namespace __sanitizer 97