// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/profiler/win32_stack_frame_unwinder.h"

#include <utility>
#include <vector>

#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace base {

namespace {

class TestUnwindFunctions : public Win32StackFrameUnwinder::UnwindFunctions {
 public:
  TestUnwindFunctions();

  PRUNTIME_FUNCTION LookupFunctionEntry(DWORD64 program_counter,
                                        PDWORD64 image_base) override;
  void VirtualUnwind(DWORD64 image_base,
                     DWORD64 program_counter,
                     PRUNTIME_FUNCTION runtime_function,
                     CONTEXT* context) override;
  ScopedModuleHandle GetModuleForProgramCounter(
      DWORD64 program_counter) override;

  // Instructs GetModuleForProgramCounter to return null on the next call.
  void SetUnloadedModule();

  // These functions set whether the next frame will have a RUNTIME_FUNCTION,
  // and allow specification of a custom image_base.
  void SetHasRuntimeFunction(CONTEXT* context);
  void SetHasRuntimeFunction(DWORD64 image_base, CONTEXT* context);
  void SetHasRuntimeFunction(DWORD64 image_base,
                             const RUNTIME_FUNCTION& runtime_function,
                             DWORD program_counter_offset,
                             CONTEXT* context);
  void SetNoRuntimeFunction(CONTEXT* context);
  void SetNoRuntimeFunction(DWORD64 image_base, CONTEXT* context);

 private:
  enum RuntimeFunctionState { NO_RUNTIME_FUNCTION, HAS_RUNTIME_FUNCTION };

  enum { kImageBaseIncrement = 1 << 20 };

  // Sets whether the next frame should have a RUNTIME_FUNCTION, and allows
  // specification of a custom image_base.
  void SetNextFrameState(RuntimeFunctionState runtime_function_state,
                         DWORD64 image_base,
                         CONTEXT* context);

  static RUNTIME_FUNCTION* const kInvalidRuntimeFunction;

  bool module_is_loaded_;
  DWORD64 expected_program_counter_;
  DWORD64 custom_image_base_;
  DWORD64 next_image_base_;
  DWORD64 expected_image_base_;
  RUNTIME_FUNCTION* next_runtime_function_;
  std::vector<RUNTIME_FUNCTION> runtime_functions_;

  DISALLOW_COPY_AND_ASSIGN(TestUnwindFunctions);
};

RUNTIME_FUNCTION* const TestUnwindFunctions::kInvalidRuntimeFunction =
    reinterpret_cast<RUNTIME_FUNCTION*>(static_cast<uintptr_t>(-1));

TestUnwindFunctions::TestUnwindFunctions()
    : module_is_loaded_(true),
      expected_program_counter_(0),
      custom_image_base_(0),
      next_image_base_(kImageBaseIncrement),
      expected_image_base_(0),
      next_runtime_function_(kInvalidRuntimeFunction) {
}

PRUNTIME_FUNCTION TestUnwindFunctions::LookupFunctionEntry(
    DWORD64 program_counter,
    PDWORD64 image_base) {
  EXPECT_EQ(expected_program_counter_, program_counter);
  if (custom_image_base_) {
    *image_base = expected_image_base_ = custom_image_base_;
    custom_image_base_ = 0;
  } else {
    *image_base = expected_image_base_ = next_image_base_;
    next_image_base_ += kImageBaseIncrement;
  }
  RUNTIME_FUNCTION* return_value = next_runtime_function_;
  next_runtime_function_ = kInvalidRuntimeFunction;
  return return_value;
}

void TestUnwindFunctions::VirtualUnwind(DWORD64 image_base,
                                        DWORD64 program_counter,
                                        PRUNTIME_FUNCTION runtime_function,
                                        CONTEXT* context) {
  ASSERT_NE(kInvalidRuntimeFunction, runtime_function)
      << "expected call to SetHasRuntimeFunction() or SetNoRuntimeFunction() "
      << "before invoking TryUnwind()";
  EXPECT_EQ(expected_image_base_, image_base);
  expected_image_base_ = 0;
  EXPECT_EQ(expected_program_counter_, program_counter);
  expected_program_counter_ = 0;
  // This function should only be called when LookupFunctionEntry returns
  // a RUNTIME_FUNCTION.
  EXPECT_EQ(&runtime_functions_.back(), runtime_function);
}

ScopedModuleHandle TestUnwindFunctions::GetModuleForProgramCounter(
    DWORD64 program_counter) {
  bool return_non_null_value = module_is_loaded_;
  module_is_loaded_ = true;
  return ScopedModuleHandle(return_non_null_value ?
                            ModuleHandleTraits::kNonNullModuleForTesting :
                            nullptr);
}

void TestUnwindFunctions::SetUnloadedModule() {
  module_is_loaded_ = false;
}

void TestUnwindFunctions::SetHasRuntimeFunction(CONTEXT* context) {
  SetNextFrameState(HAS_RUNTIME_FUNCTION, 0, context);
}

void TestUnwindFunctions::SetHasRuntimeFunction(DWORD64 image_base,
                                                CONTEXT* context) {
  SetNextFrameState(HAS_RUNTIME_FUNCTION, image_base, context);
}

void TestUnwindFunctions::SetHasRuntimeFunction(
    DWORD64 image_base,
    const RUNTIME_FUNCTION& runtime_function,
    DWORD program_counter_offset,
    CONTEXT* context) {
  custom_image_base_ = image_base;
  runtime_functions_.push_back(runtime_function);
  next_runtime_function_ = &runtime_functions_.back();
  expected_program_counter_ = context->Rip =
      image_base + program_counter_offset;
}

void TestUnwindFunctions::SetNoRuntimeFunction(CONTEXT* context) {
  SetNextFrameState(NO_RUNTIME_FUNCTION, 0, context);
}

void TestUnwindFunctions::SetNoRuntimeFunction(DWORD64 image_base,
                                               CONTEXT* context) {
  SetNextFrameState(NO_RUNTIME_FUNCTION, image_base, context);
}


void TestUnwindFunctions::SetNextFrameState(
    RuntimeFunctionState runtime_function_state,
    DWORD64 image_base,
    CONTEXT* context) {
  if (image_base)
    custom_image_base_ = image_base;

  if (runtime_function_state == HAS_RUNTIME_FUNCTION) {
    RUNTIME_FUNCTION runtime_function = {};
    runtime_function.BeginAddress = 16;
    runtime_function.EndAddress = runtime_function.BeginAddress + 256;
    runtime_functions_.push_back(runtime_function);
    next_runtime_function_ = &runtime_functions_.back();

    DWORD64 image_base = custom_image_base_ ? custom_image_base_ :
        next_image_base_;
    expected_program_counter_ = context->Rip =
        image_base + runtime_function.BeginAddress + 8;
  } else {
    expected_program_counter_ = context->Rip = 100;
    next_runtime_function_ = nullptr;
  }
}

}  // namespace

class Win32StackFrameUnwinderTest : public testing::Test {
 protected:
  Win32StackFrameUnwinderTest() {}

  // This exists so that Win32StackFrameUnwinder's constructor can be private
  // with a single friend declaration of this test fixture.
  scoped_ptr<Win32StackFrameUnwinder> CreateUnwinder();

  // Weak pointer to the unwind functions used by last created unwinder.
  TestUnwindFunctions* unwind_functions_;

 private:
  DISALLOW_COPY_AND_ASSIGN(Win32StackFrameUnwinderTest);
};

scoped_ptr<Win32StackFrameUnwinder>
Win32StackFrameUnwinderTest::CreateUnwinder() {
  scoped_ptr<TestUnwindFunctions> unwind_functions(new TestUnwindFunctions);
  unwind_functions_ = unwind_functions.get();
  return make_scoped_ptr(
      new Win32StackFrameUnwinder(std::move(unwind_functions)));
}

// Checks the case where all frames have unwind information.
TEST_F(Win32StackFrameUnwinderTest, FramesWithUnwindInfo) {
  scoped_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
  CONTEXT context = {0};
  ScopedModuleHandle module;

  unwind_functions_->SetHasRuntimeFunction(&context);
  EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
  EXPECT_TRUE(module.IsValid());

  unwind_functions_->SetHasRuntimeFunction(&context);
  module.Set(nullptr);
  EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
  EXPECT_TRUE(module.IsValid());

  unwind_functions_->SetHasRuntimeFunction(&context);
  module.Set(nullptr);
  EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
  EXPECT_TRUE(module.IsValid());
}

// Checks that an instruction pointer in an unloaded module fails to unwind.
TEST_F(Win32StackFrameUnwinderTest, UnloadedModule) {
  scoped_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
  CONTEXT context = {0};
  ScopedModuleHandle module;

  unwind_functions_->SetUnloadedModule();
  EXPECT_FALSE(unwinder->TryUnwind(&context, &module));
}

// Checks that the CONTEXT's stack pointer gets popped when the top frame has no
// unwind information.
TEST_F(Win32StackFrameUnwinderTest, FrameAtTopWithoutUnwindInfo) {
  scoped_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
  CONTEXT context = {0};
  ScopedModuleHandle module;
  const DWORD64 original_rsp = 128;
  context.Rsp = original_rsp;

  unwind_functions_->SetNoRuntimeFunction(&context);
  EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
  EXPECT_EQ(original_rsp, context.Rip);
  EXPECT_EQ(original_rsp + 8, context.Rsp);
  EXPECT_TRUE(module.IsValid());

  unwind_functions_->SetHasRuntimeFunction(&context);
  module.Set(nullptr);
  EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
  EXPECT_TRUE(module.IsValid());

  unwind_functions_->SetHasRuntimeFunction(&context);
  module.Set(nullptr);
  EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
  EXPECT_TRUE(module.IsValid());
}

// Checks that a frame below the top of the stack with missing unwind info
// results in blacklisting the module.
TEST_F(Win32StackFrameUnwinderTest, BlacklistedModule) {
  const DWORD64 image_base_for_module_with_bad_function = 1024;
  {
    // First stack, with a bad function below the top of the stack.
    scoped_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
    CONTEXT context = {0};
    ScopedModuleHandle module;
    unwind_functions_->SetHasRuntimeFunction(&context);
    EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
    EXPECT_TRUE(module.IsValid());

    unwind_functions_->SetNoRuntimeFunction(
        image_base_for_module_with_bad_function,
        &context);
    EXPECT_FALSE(unwinder->TryUnwind(&context, &module));
  }

  {
    // Second stack; check that a function at the top of the stack without
    // unwind info from the previously-seen module is blacklisted.
    scoped_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
    CONTEXT context = {0};
    ScopedModuleHandle module;
    unwind_functions_->SetNoRuntimeFunction(
        image_base_for_module_with_bad_function,
        &context);
    EXPECT_FALSE(unwinder->TryUnwind(&context, &module));
  }

  {
    // Third stack; check that a function at the top of the stack *with* unwind
    // info from the previously-seen module is not blacklisted. Then check that
    // functions below the top of the stack with unwind info are not
    // blacklisted, regardless of whether they are in the previously-seen
    // module.
    scoped_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
    CONTEXT context = {0};
    ScopedModuleHandle module;
    unwind_functions_->SetHasRuntimeFunction(
        image_base_for_module_with_bad_function,
        &context);
    EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
    EXPECT_TRUE(module.IsValid());

    unwind_functions_->SetHasRuntimeFunction(&context);
    module.Set(nullptr);
    EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
    EXPECT_TRUE(module.IsValid());

    unwind_functions_->SetHasRuntimeFunction(
        image_base_for_module_with_bad_function,
        &context);
    module.Set(nullptr);
    EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
    EXPECT_TRUE(module.IsValid());
  }

  {
    // Fourth stack; check that a function at the top of the stack without
    // unwind info and not from the previously-seen module is not
    // blacklisted. Then check that functions below the top of the stack with
    // unwind info are not blacklisted, regardless of whether they are in the
    // previously-seen module.
    scoped_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
    CONTEXT context = {0};
    ScopedModuleHandle module;
    unwind_functions_->SetNoRuntimeFunction(&context);
    EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
    EXPECT_TRUE(module.IsValid());

    unwind_functions_->SetHasRuntimeFunction(&context);
    module.Set(nullptr);
    EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
    EXPECT_TRUE(module.IsValid());

    unwind_functions_->SetHasRuntimeFunction(
        image_base_for_module_with_bad_function,
        &context);
    module.Set(nullptr);
    EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
    EXPECT_TRUE(module.IsValid());
  }
}

// Checks that a frame below the top of the stack with missing unwind info does
// not result in blacklisting the module if the first frame also was missing
// unwind info. This ensures we don't blacklist an innocent module because the
// first frame was bad but we didn't know it at the time.
TEST_F(Win32StackFrameUnwinderTest, ModuleFromQuestionableFrameNotBlacklisted) {
  const DWORD64 image_base_for_questionable_module = 2048;
  {
    // First stack, with both the first and second frames missing unwind info.
    scoped_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
    CONTEXT context = {0};
    ScopedModuleHandle module;
    unwind_functions_->SetNoRuntimeFunction(&context);
    EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
    EXPECT_TRUE(module.IsValid());

    unwind_functions_->SetNoRuntimeFunction(image_base_for_questionable_module,
                                            &context);
    EXPECT_FALSE(unwinder->TryUnwind(&context, &module));
  }

  {
    // Second stack; check that the questionable module was not blacklisted.
    scoped_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
    CONTEXT context = {0};
    ScopedModuleHandle module;
    unwind_functions_->SetNoRuntimeFunction(image_base_for_questionable_module,
                                            &context);
    EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
    EXPECT_TRUE(module.IsValid());
  }
}

}  // namespace base
