Home | History | Annotate | Download | only in tests
      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 
     18 namespace __sanitizer {
     19 
     20 class 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 
     31 static uptr PC(uptr idx) {
     32   return (1<<20) + idx;
     33 }
     34 
     35 void 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   // This is common setup done by __asan::GetStackTrace().
     52   trace.size = 0;
     53   trace.max_size = ARRAY_SIZE(fake_stack);
     54   trace.trace[0] = start_pc;
     55 }
     56 
     57 TEST_F(FastUnwindTest, Basic) {
     58   trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0],
     59                         fake_top, fake_bottom);
     60   // Should get all on-stack retaddrs and start_pc.
     61   EXPECT_EQ(6U, trace.size);
     62   EXPECT_EQ(start_pc, trace.trace[0]);
     63   for (uptr i = 1; i <= 5; i++) {
     64     EXPECT_EQ(PC(i*2 - 1), trace.trace[i]);
     65   }
     66 }
     67 
     68 // From: http://code.google.com/p/address-sanitizer/issues/detail?id=162
     69 TEST_F(FastUnwindTest, FramePointerLoop) {
     70   // Make one fp point to itself.
     71   fake_stack[4] = (uptr)&fake_stack[4];
     72   trace.FastUnwindStack(start_pc, (uptr)&fake_stack[0],
     73                         fake_top, fake_bottom);
     74   // Should get all on-stack retaddrs up to the 4th slot and start_pc.
     75   EXPECT_EQ(4U, trace.size);
     76   EXPECT_EQ(start_pc, trace.trace[0]);
     77   for (uptr i = 1; i <= 3; i++) {
     78     EXPECT_EQ(PC(i*2 - 1), trace.trace[i]);
     79   }
     80 }
     81 
     82 TEST_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