// Copyright 2021 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/forensics/crash_reports/dart_module_parser.h"

#include <lib/syslog/cpp/macros.h>

#include <algorithm>
#include <cctype>
#include <sstream>
#include <string_view>

#include <re2/re2.h>

#include "src/lib/fxl/strings/split_string.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace forensics::crash_reports {
namespace {

// See
// https://github.com/dart-lang/sdk/blob/b44250c3f6fa607a52325dfdf753268fffe1dea6/runtime/vm/object.cc#L25661
// for the reference on how unsymbolicated Dart stack traces are constructed.

// The crash reporter doesn't have access at runtime to the module name of the Dart snapshot so it
// assumes the fallback we use on Fuchsia for non-shared libraries.
constexpr std::string_view kDartModulesName = "<_>";

// Unsymbolicated stack traces have 16 groups of "***" on the second line.
static const re2::RE2* const kUnsymbolicatedDartStackTraceRegex =
    new re2::RE2(R"((?:\*{3}\s{0,1}){16})");

bool MatchesUnsymbolicatedDartStackTrace(const std::vector<std::string>& lines) {
  return lines.size() >= 2 && re2::RE2::FullMatch(lines[1], *kUnsymbolicatedDartStackTraceRegex);
}

// Regexes and functions for extracting information from unsymbolicated Dart stack traces.
//
// Stack frame.
static const re2::RE2* const kStackFrameRegex =
    new re2::RE2(R"(\s*#\d{2} abs ([\da-f]+)(?: virt [\da-f]+)? .*$)");

std::optional<uint64_t> TryMatchStackAddress(const std::string& line) {
  std::string address;
  if (!re2::RE2::FullMatch(line, *kStackFrameRegex, &address)) {
    return std::nullopt;
  }

  // The first match is the whole line, the second is the absolute address, and the third is the
  // virtual address.
  return std::strtoull(address.c_str(), nullptr, 16);
}

// Build id.
static const re2::RE2* const kBuildIdRegex = new re2::RE2(R"(\s*build_id: '([a-f\d]+)')");

std::optional<std::string> TryMatchBuildId(const std::string& line) {
  std::string build_id;
  if (!re2::RE2::FullMatch(line, *kBuildIdRegex, &build_id)) {
    return std::nullopt;
  }

  return build_id;
}

// Isolate DSO base address.
static const re2::RE2* const kIsolateDsoBaseRegex =
    new re2::RE2(R"(\s*isolate_dso_base: ([\da-f]+), vm_dso_base: [\da-f]+)");

std::optional<uint64_t> TryMatchIsolateDsoBase(const std::string& line) {
  std::string dso_base;
  if (!re2::RE2::FullMatch(line, *kIsolateDsoBaseRegex, &dso_base)) {
    return std::nullopt;
  }

  return std::strtoull(dso_base.c_str(), nullptr, 16);
}

std::string ToHexString(const uint64_t value) {
  std::stringstream stream;
  stream << std::hex << value;
  return stream.str();
}

// Converts build id endianness to match Breakpad's FileID::ConvertIDentifierToUUIDString() because
// symbol lookup is dependent on this identifier.
//
// \build_id| is a 32-bytes hex UUID without hyphens, which is 32 bytes long. It is formatted in
// groups of 8-4-4-4-12 characters. The first three groups must be big endian.
//
// Also appends a '0' to match what breakpad generates.
// https://osscs.corp.google.com/chromium/chromium/src/+/main:third_party/crashpad/crashpad/snapshot/elf/module_snapshot_elf.cc;l=153;drc=81cc8267d3a069163708f3ac140d0d940487c137
std::optional<std::string> FormatBuildId(const std::string& build_id) {
  // Build id is always 32 bytes long.
  if (build_id.size() < 16) {
    return std::nullopt;
  }

  std::string formatted{
      build_id[6],  build_id[7],  build_id[4],  build_id[5],  build_id[2], build_id[3],
      build_id[0],  build_id[1],  build_id[10], build_id[11], build_id[8], build_id[9],
      build_id[14], build_id[15], build_id[12], build_id[13],
  };

  formatted += build_id.substr(16);
  formatted += "0";

  std::transform(formatted.begin(), formatted.end(), formatted.begin(),
                 [](const unsigned char c) { return std::toupper(c); });

  return formatted;
}

}  // namespace

std::pair<bool, std::optional<std::string>> ParseDartModulesFromStackTrace(
    const std::string_view stack_trace) {
  const std::vector<std::string> lines =
      fxl::SplitStringCopy(stack_trace, "\n", fxl::WhiteSpaceHandling::kTrimWhitespace,
                           fxl::SplitResult::kSplitWantNonEmpty);

  if (!MatchesUnsymbolicatedDartStackTrace(lines)) {
    return {false, std::nullopt};
  }

  std ::optional<std::string> build_id;
  std::optional<uint64_t> isolate_dso_base;
  std::optional<uint64_t> max_address;
  for (const auto& line : lines) {
    if (const auto build_id_match = TryMatchBuildId(line); build_id_match.has_value()) {
      build_id = build_id_match;
    }

    if (const auto isolate_dso_base_match = TryMatchIsolateDsoBase(line);
        isolate_dso_base_match.has_value()) {
      isolate_dso_base = isolate_dso_base_match;
    }

    if (const auto stack_address_match = TryMatchStackAddress(line);
        stack_address_match.has_value()) {
      if (!max_address.has_value() || *stack_address_match > *max_address) {
        max_address = stack_address_match;
      }
    }
  }

  if (!build_id.has_value() || !isolate_dso_base.has_value() || !max_address.has_value()) {
    return {true, std::nullopt};
  }

  const auto identifier = FormatBuildId(build_id.value());
  if (!identifier.has_value()) {
    return {true, std::nullopt};
  }

  const std::string start_address = ToHexString(isolate_dso_base.value());
  const std::string name = std::string(kDartModulesName);

  // Estimate the length to be enough to cover every address in the stack trace.
  const std::string length = ToHexString(max_address.value() - isolate_dso_base.value() + 1);

  // Dart module information is formatted like "<startAddress>,<length>,<name>,<identifier>"
  return {true, fxl::StringPrintf("%s,%s,%s,%s", start_address.c_str(), length.c_str(),
                                  name.c_str(), identifier->c_str())};
}

}  // namespace forensics::crash_reports
