// Copyright 2019 The Fuchsia 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 "src/developer/debug/zxdb/client/pretty_stack_manager.h"

#include <algorithm>

#include "src/developer/debug/zxdb/client/stack.h"

namespace zxdb {

void PrettyStackManager::SetMatchers(std::vector<StackGlob> matchers) {
  matchers_ = std::move(matchers);

  // The matchers must always go from the largest to the smallest.
  std::sort(matchers_.begin(), matchers_.end(), [](const auto& left, const auto& right) {
    return left.frames.size() > right.frames.size();
  });
}

// TODO(https://fxbug.dev/292124860) this should be loaded from a configuration file somehow
// associated with the user's build instead of being hardcoded.
void PrettyStackManager::LoadDefaultMatchers() {
  std::vector<StackGlob> matchers;

  // Turn off formatting. We want each frame matcher to appear on different lines and clang-format
  // likes to combine them which makes it more difficult to follow.
  // clang-format off

  // C async loop waiting.
  StackGlob c_async_loop(
      "Waiting for event in async_loop_run()",
      {PrettyFrameGlob::Wildcard(1, 1),  // syscalls-<platform>.S
       PrettyFrameGlob::Func("_zx_port_wait"),
       PrettyFrameGlob::Func("async_loop_run_once"),
       PrettyFrameGlob::Func("async_loop_run")});

  // C++ async loop waiting (just adds a call to the C version).
  StackGlob cpp_async_loop("Waiting for event in async::Loop::Run()", c_async_loop.frames);
  cpp_async_loop.frames.push_back(PrettyFrameGlob::Func("async::Loop::Run"));

  matchers.push_back(std::move(cpp_async_loop));
  matchers.push_back(std::move(c_async_loop));

  // Typical background thread startup.
  StackGlob pthread_startup("pthread startup", {PrettyFrameGlob::Func("start_pthread"),
                                                PrettyFrameGlob::Func("thread_trampoline")});

  // std::thread startup (wraps pthread startup). This has a crazy function name the matcher can't
  // support so accept anything from std::thread being called from pthread startup.
  StackGlob std_thread_startup("std::thread startup", {PrettyFrameGlob::File("thread")});
  std_thread_startup.frames.insert(std_thread_startup.frames.end(), pthread_startup.frames.begin(),
                                   pthread_startup.frames.end());

  matchers.push_back(std::move(pthread_startup));
  matchers.push_back(std::move(std_thread_startup));

  // Async loop thread startup. Don't count "async_loop_run" because we count that as part of runing
  // and task dispatch (dispatch will be the same with a loop and without).
  matchers.push_back(StackGlob("async_loop thread startup",
                               {PrettyFrameGlob::FuncFile("async_loop_run_thread", "loop.c"),
                                PrettyFrameGlob::FuncFile("start_c11", "pthread_create.c"),
                                PrettyFrameGlob::Func("thread_trampoline")}));

  // Async loop task dispatch.
  matchers.push_back(StackGlob("Dispatching task from async loop",
                               {PrettyFrameGlob::Func("async_loop_dispatch_task"),
                                PrettyFrameGlob::Func("async_loop_dispatch_tasks"),
                                PrettyFrameGlob::Func("async_loop_run")}));

  // fpromise::promise and fit::function occur a lot and generate extremely long and useless names.
  // Matching useful sequences is difficult. But just replacing individual stack entries with
  // a simple string eliminates ~3 lines of template goop and ~3 lines of unnecessary function
  // parameters. This makes backtraces much easier to read. Duplicate matches will be merged
  // automatically.
  matchers.push_back(
      StackGlob("fpromise::promise code", {PrettyFrameGlob::File("fit/promise_internal.h")}));
  matchers.push_back(StackGlob("fpromise::promise code", {PrettyFrameGlob::File("fit/promise.h")}));
  matchers.push_back(StackGlob("fit::function code", {PrettyFrameGlob::File("fit/function.h")}));
  matchers.push_back(
      StackGlob("fit::function code", {PrettyFrameGlob::File("fit/function_internal.h")}));

  // Rust async loop waiting.
  StackGlob rust_async_loop(
      "Waiting for event in Executor::run_singlethreaded()",
      {PrettyFrameGlob::Wildcard(1, 1),  // syscalls file (name depends on platform).
       PrettyFrameGlob::Func("_zx_port_wait"),
       PrettyFrameGlob::Func("zx::port::Port::wait"),
       PrettyFrameGlob::Wildcard(2, 2),  // Lambdas
       PrettyFrameGlob::Func("std::thread::local::LocalKey<*>::try_with<*>"),
       PrettyFrameGlob::Func("std::thread::local::LocalKey<*>::with<*>"),
       PrettyFrameGlob::Func("fuchsia_async::runtime::fuchsia::executor::with_local_timer_heap<*>"),
       PrettyFrameGlob::Func(
           "fuchsia_async::runtime::fuchsia::executor::Executor::run_singlethreaded<*>")});
  matchers.push_back(std::move(rust_async_loop));

  StackGlob rust_test_async_dispatch(
      "Polled event in fuchsia::test_singlethreaded",
      {PrettyFrameGlob::Func(
          "fuchsia_async::runtime::fuchsia::executor::atomic_future::AtomicFuture<*>::poll<*>"),
       PrettyFrameGlob::Wildcard(1, 25),
       PrettyFrameGlob::Func("fuchsia::test_singlethreaded<*>"),
      });
  matchers.push_back(std::move(rust_test_async_dispatch));

  StackGlob rust_multithreaded_test_async_dispatch(
      "Polled event in fuchsia::multithreaded_test_singlethreaded",
      {
       PrettyFrameGlob::Func(
        "fuchsia_async::runtime::fuchsia::executor::atomic_future::AtomicFuture<*>::poll<*>"),
       PrettyFrameGlob::Wildcard(1, 23),
       PrettyFrameGlob::Func("thread_trampoline"),
      });
  matchers.push_back(std::move(rust_multithreaded_test_async_dispatch));

  StackGlob rust_async_dispatch(
      "Polled event in Executor::run_singlethreaded",
      {PrettyFrameGlob::Func(
          "fuchsia_async::runtime::fuchsia::executor::atomic_future::AtomicFuture<*>::poll<*>"),
       PrettyFrameGlob::Wildcard(1,10),
       PrettyFrameGlob::Func(
           "fuchsia_async::runtime::fuchsia::executor::local::LocalExecutor::run_singlethreaded<*>"),
      });
  matchers.push_back(std::move(rust_async_dispatch));

  // C startup code. The functions depends on the platform, so just match the file name for most of
  // them. The number of functions in __libc_start_main has varied between 1 and 2 over time. Since
  // these aren't likely to be re-used in other places we can have very general matchers here. The
  // duplicate "libc startup" entries will be merged to produce just one entry.
  //
  // TODO(https://fxbug.dev/456895946): This has implementation knowledge of
  // both old and new libc implementations; see the bug for details on morphing
  // this into a more robust de facto protocol between debugger and libc.
  PrettyFrameGlob libc_start_main_c = PrettyFrameGlob::File("__libc_start_main.c");
  PrettyFrameGlob libc_start_main = PrettyFrameGlob::File("start-main.cc");
  PrettyFrameGlob libc_start = PrettyFrameGlob::Func("_start");
  matchers.push_back(StackGlob("libc startup", {libc_start_main}));
  matchers.push_back(StackGlob("libc startup", {libc_start_main_c}));
  matchers.push_back(StackGlob("libc startup", {libc_start}));

  // Rust has placeholder symbols in the stack "__rust_begin_short_backtrace" and
  // "__rust_end_short_backtrace" which are designed to help clean up backtraces. The production
  // versions of these live in std::sys::backtrace, and the test versions live in test::backtrace
  // which covers a bit more of test startup. Note that we ignore the ending marker for tests. This
  // is because the default "break-on-failure" behavior for Rust tests is to panic - which follows
  // the typical abort machinery.
  //
  // Rust uses the "begin" to indicate that the stack now contains "good" stack entries (the startup
  // code is complete) and then "end" before the internal crash code. But since we're walking the
  // stack in the opposite direction (most recent first), anything between "end" and "begin" should
  // be removed.
  //
  // This first one matches the "top of stack" crash handing code and later we've got specific
  // matches for the "bottom of stack" code. Each has an end-point to stop matching to avoid
  // overmatching. A more general entry would just list "*" followed by the "end" indicator, but
  // that will be much slower to match against. If we find a more general match is needed, it would
  // be best to hardcode this rust annotation scheme rather than try to express this with globs.
  matchers.push_back(StackGlob(
      "Rust library",
      {PrettyFrameGlob::Func("__fuchsia_libc::__abort_impl__"),
       PrettyFrameGlob::Wildcard(0, 16),
       PrettyFrameGlob::Func("std::sys::backtrace::__rust_end_short_backtrace<*>")}));

  // This is generic code that appears around the top of the stack when dumping a backtrace from a
  // failed assertion.
  matchers.push_back(StackGlob(
      "Rust backtrace library",
      {PrettyFrameGlob::Func("std::sys::backtrace::_print_fmt"),
       PrettyFrameGlob::Wildcard(0, 19),
       PrettyFrameGlob::Func("std::sys::backtrace::__rust_end_short_backtrace<*>")}));

  // Rust startup code. The "call_once()" in function.rs is present in debug mode but not release.
  matchers.push_back(StackGlob(
      "Rust startup",
      {PrettyFrameGlob::File("library/core/src/ops/function.rs"),
       PrettyFrameGlob::Func("std::sys::backtrace::__rust_begin_short_backtrace<*>"),
       PrettyFrameGlob::Wildcard(0, 16),
       libc_start}));

  // Rust test startup code, we want this one to match first since it could capture a few more
  // frames (hence the slightly larger wildcard glob) than the standard library marker.
  matchers.push_back(StackGlob(
      "Rust test startup",
      {PrettyFrameGlob::Func("test::__rust_begin_short_backtrace<*>"),
       PrettyFrameGlob::Wildcard(0, 20),
       libc_start}));
  matchers.push_back(StackGlob(
      "Rust startup",
      {PrettyFrameGlob::Func("std::sys::backtrace::__rust_begin_short_backtrace<*>"),
       PrettyFrameGlob::Wildcard(0, 16),
       libc_start}));

  // Rust new thread code. At least our Rust implementation often adds a bunch of stuff with
  // Executors and LocalKeys that aren't matched by this. It would be nice to elide those also but I
  // don't know how stable those symbols are.
  matchers.push_back(StackGlob(
      "Rust thread startup",
      {PrettyFrameGlob::Func("std::sys::backtrace::__rust_begin_short_backtrace<*>"),
       PrettyFrameGlob::Wildcard(0, 16),
       PrettyFrameGlob::Func("thread_trampoline")}));

  // clang-format on

  SetMatchers(std::move(matchers));
}

PrettyStackManager::Match PrettyStackManager::GetMatchAt(const Stack& stack,
                                                         size_t frame_index) const {
  for (const StackGlob& matcher : matchers_) {
    if (size_t match_count = StackGlobMatchesAt(matcher, stack, frame_index))
      return Match(match_count, matcher.description);
  }

  return Match();
}

std::vector<PrettyStackManager::FrameEntry> PrettyStackManager::ProcessStack(
    const Stack& stack) const {
  std::vector<FrameEntry> result;
  for (size_t stack_i = 0; stack_i < stack.size(); /* nothing */) {
    PrettyStackManager::Match match = GetMatchAt(stack, stack_i);

    if (match) {
      // Have a pretty stack entry, construct a FrameEntry for it.
      FrameEntry* entry = nullptr;
      if (!result.empty() && result.back().match &&
          result.back().match.description == match.description) {
        // This match is the same as the previous one, merge the two by appending our new frames to
        // the previous entry.
        entry = &result.back();
        entry->match.match_count += match.match_count;
      } else {
        // Got a new match, the frames go on a new entry.
        entry = &result.emplace_back();
        entry->begin_index = stack_i;
        entry->match = std::move(match);
      }
      for (size_t entry_i = 0; entry_i < match.match_count; entry_i++)
        entry->frames.push_back(stack[stack_i + entry_i]);
      stack_i += match.match_count;
    } else {
      // No match, append single stack entry.
      FrameEntry& entry = result.emplace_back();
      entry.begin_index = stack_i;
      entry.frames.push_back(stack[stack_i]);
      stack_i++;
    }
  }

  return result;
}

// static
size_t PrettyStackManager::StackGlobMatchesAt(const StackGlob& stack_glob, const Stack& stack,
                                              size_t frame_start_index) {
  if (frame_start_index + stack_glob.frames.size() > stack.size())
    return 0;  // Not enough room for all frame globs.

  size_t glob_index = 0;
  size_t stack_index = frame_start_index;

  // Number of wildcard positions left to possibly (but not necessarily) skip
  size_t wildcard_skip = 0;

  while (glob_index < stack_glob.frames.size() && stack_index < stack.size()) {
    const PrettyFrameGlob& frame_glob = stack_glob.frames[glob_index];
    const Frame* frame = stack[stack_index];

    if (frame_glob.is_wildcard()) {
      FX_DCHECK(!wildcard_skip);
      wildcard_skip = frame_glob.max_matches() - frame_glob.min_matches();
      // The min_matches will be eaten at the bottom of the loop.
    } else if (frame_glob.Matches(frame)) {
      wildcard_skip = 0;
    } else if (wildcard_skip == 0) {
      return 0;
    } else {
      wildcard_skip--;
      stack_index++;
      continue;
    }
    glob_index++;
    stack_index += frame_glob.min_matches();
  }

  if (stack_index > stack.size())
    return 0;  // Wildcard minimum is off the end of the stack.
  if (glob_index < stack_glob.frames.size())
    return 0;  // Not all frames required by the glob were matched.

  // Matched to the bottom of the stack.
  return stack_index - frame_start_index;
}

}  // namespace zxdb
