1 //===-- sanitizer_stacktrace_test.cc --------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
12 //===----------------------------------------------------------------------===//
14 #include "sanitizer_common/sanitizer_common.h"
15 #include "sanitizer_common/sanitizer_stacktrace.h"
16 #include "gtest/gtest.h"
18 namespace __sanitizer
{
20 class FastUnwindTest
: public ::testing::Test
{
23 bool TryFastUnwind(uptr max_depth
) {
24 if (!StackTrace::WillUseFastUnwind(true))
26 trace
.Unwind(max_depth
, start_pc
, (uptr
)&fake_stack
[0], 0, fake_top
,
38 static uptr
PC(uptr idx
) {
42 void FastUnwindTest::SetUp() {
43 // Fill an array of pointers with fake fp+retaddr pairs. Frame pointers have
45 for (uptr i
= 0; i
+1 < ARRAY_SIZE(fake_stack
); i
+= 2) {
46 fake_stack
[i
] = (uptr
)&fake_stack
[i
+2]; // fp
47 fake_stack
[i
+1] = PC(i
+ 1); // retaddr
49 // Mark the last fp as zero to terminate the stack trace.
50 fake_stack
[RoundDownTo(ARRAY_SIZE(fake_stack
) - 1, 2)] = 0;
52 // Top is two slots past the end because FastUnwindStack subtracts two.
53 fake_top
= (uptr
)&fake_stack
[ARRAY_SIZE(fake_stack
) + 2];
54 // Bottom is one slot before the start because FastUnwindStack uses >.
55 fake_bottom
= (uptr
)&fake_stack
[-1];
59 TEST_F(FastUnwindTest
, Basic
) {
60 if (!TryFastUnwind(kStackTraceMax
))
62 // Should get all on-stack retaddrs and start_pc.
63 EXPECT_EQ(6U, trace
.size
);
64 EXPECT_EQ(start_pc
, trace
.trace
[0]);
65 for (uptr i
= 1; i
<= 5; i
++) {
66 EXPECT_EQ(PC(i
*2 - 1), trace
.trace
[i
]);
70 // From: http://code.google.com/p/address-sanitizer/issues/detail?id=162
71 TEST_F(FastUnwindTest
, FramePointerLoop
) {
72 // Make one fp point to itself.
73 fake_stack
[4] = (uptr
)&fake_stack
[4];
74 if (!TryFastUnwind(kStackTraceMax
))
76 // Should get all on-stack retaddrs up to the 4th slot and start_pc.
77 EXPECT_EQ(4U, trace
.size
);
78 EXPECT_EQ(start_pc
, trace
.trace
[0]);
79 for (uptr i
= 1; i
<= 3; i
++) {
80 EXPECT_EQ(PC(i
*2 - 1), trace
.trace
[i
]);
84 TEST_F(FastUnwindTest
, MisalignedFramePointer
) {
85 // Make one fp misaligned.
87 if (!TryFastUnwind(kStackTraceMax
))
89 // Should get all on-stack retaddrs up to the 4th slot and start_pc.
90 EXPECT_EQ(4U, trace
.size
);
91 EXPECT_EQ(start_pc
, trace
.trace
[0]);
92 for (uptr i
= 1; i
< 4U; i
++) {
93 EXPECT_EQ(PC(i
*2 - 1), trace
.trace
[i
]);
97 TEST_F(FastUnwindTest
, OneFrameStackTrace
) {
98 if (!TryFastUnwind(1))
100 EXPECT_EQ(1U, trace
.size
);
101 EXPECT_EQ(start_pc
, trace
.trace
[0]);
102 EXPECT_EQ((uptr
)&fake_stack
[0], trace
.top_frame_bp
);
105 TEST_F(FastUnwindTest
, ZeroFramesStackTrace
) {
106 if (!TryFastUnwind(0))
108 EXPECT_EQ(0U, trace
.size
);
109 EXPECT_EQ(0U, trace
.top_frame_bp
);
112 TEST(SlowUnwindTest
, ShortStackTrace
) {
113 if (StackTrace::WillUseFastUnwind(false))
116 uptr pc
= StackTrace::GetCurrentPc();
117 uptr bp
= GET_CURRENT_FRAME();
118 stack
.Unwind(0, pc
, bp
, 0, 0, 0, false);
119 EXPECT_EQ(0U, stack
.size
);
120 EXPECT_EQ(0U, stack
.top_frame_bp
);
121 stack
.Unwind(1, pc
, bp
, 0, 0, 0, false);
122 EXPECT_EQ(1U, stack
.size
);
123 EXPECT_EQ(pc
, stack
.trace
[0]);
124 EXPECT_EQ(bp
, stack
.top_frame_bp
);
127 } // namespace __sanitizer