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