sanitizer_stacktrace_test.cc revision 064da32709c8bf81283062abc04cf6e88e6c075d
1//===-- sanitizer_stacktrace_test.cc --------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
11//
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_common/sanitizer_common.h"
15#include "sanitizer_common/sanitizer_stacktrace.h"
16#include "gtest/gtest.h"
17
18namespace __sanitizer {
19
20class FastUnwindTest : public ::testing::Test {
21 protected:
22  virtual void SetUp();
23
24  uptr fake_stack[10];
25  uptr start_pc;
26  uptr fake_top;
27  uptr fake_bottom;
28  StackTrace trace;
29};
30
31static uptr PC(uptr idx) {
32  return (1<<20) + idx;
33}
34
35void FastUnwindTest::SetUp() {
36  // Fill an array of pointers with fake fp+retaddr pairs.  Frame pointers have
37  // even indices.
38  for (uptr i = 0; i+1 < ARRAY_SIZE(fake_stack); i += 2) {
39    fake_stack[i] = (uptr)&fake_stack[i+2];  // fp
40    fake_stack[i+1] = PC(i + 1); // retaddr
41  }
42  // Mark the last fp as zero to terminate the stack trace.
43  fake_stack[RoundDownTo(ARRAY_SIZE(fake_stack) - 1, 2)] = 0;
44
45  // Top is two slots past the end because FastUnwindStack subtracts two.
46  fake_top = (uptr)&fake_stack[ARRAY_SIZE(fake_stack) + 2];
47  // Bottom is one slot before the start because FastUnwindStack uses >.
48  fake_bottom = (uptr)&fake_stack[-1];
49  start_pc = PC(0);
50}
51
52TEST_F(FastUnwindTest, Basic) {
53  trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0],
54                        fake_top, fake_bottom, kStackTraceMax);
55  // Should get all on-stack retaddrs and start_pc.
56  EXPECT_EQ(6U, trace.size);
57  EXPECT_EQ(start_pc, trace.trace[0]);
58  for (uptr i = 1; i <= 5; i++) {
59    EXPECT_EQ(PC(i*2 - 1), trace.trace[i]);
60  }
61}
62
63// From: http://code.google.com/p/address-sanitizer/issues/detail?id=162
64TEST_F(FastUnwindTest, FramePointerLoop) {
65  // Make one fp point to itself.
66  fake_stack[4] = (uptr)&fake_stack[4];
67  trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0],
68                        fake_top, fake_bottom, kStackTraceMax);
69  // Should get all on-stack retaddrs up to the 4th slot and start_pc.
70  EXPECT_EQ(4U, trace.size);
71  EXPECT_EQ(start_pc, trace.trace[0]);
72  for (uptr i = 1; i <= 3; i++) {
73    EXPECT_EQ(PC(i*2 - 1), trace.trace[i]);
74  }
75}
76
77TEST_F(FastUnwindTest, MisalignedFramePointer) {
78  // Make one fp misaligned.
79  fake_stack[4] += 3;
80  trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0],
81                        fake_top, fake_bottom, kStackTraceMax);
82  // Should get all on-stack retaddrs up to the 4th slot and start_pc.
83  EXPECT_EQ(4U, trace.size);
84  EXPECT_EQ(start_pc, trace.trace[0]);
85  for (uptr i = 1; i < 4U; i++) {
86    EXPECT_EQ(PC(i*2 - 1), trace.trace[i]);
87  }
88}
89
90TEST_F(FastUnwindTest, OneFrameStackTrace) {
91  trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0],
92                        fake_top, fake_bottom, 1);
93  EXPECT_EQ(1U, trace.size);
94  EXPECT_EQ(1U, trace.max_size);
95  EXPECT_EQ(start_pc, trace.trace[0]);
96}
97
98}  // namespace __sanitizer
99