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