// Copyright 2020 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 "tools/symbolizer/log_parser.h"

#include <charconv>
#include <cstdint>
#include <string>
#include <string_view>

#include "lib/fit/defer.h"
#include "lib/syslog/cpp/macros.h"
#include "src/lib/fxl/strings/split_string.h"
#include "src/lib/fxl/strings/trim.h"
#include "tools/symbolizer/symbolizer.h"

namespace symbolizer {

namespace {

// This need to match
// https://github.com/dart-lang/sdk/blob/f424f3a4cca306513e77c7747682f1c1c99e3307/runtime/vm/object.cc#L25501
constexpr std::string_view kDartStackTraceMagic =
    "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***";

// Converts the string in dec or hex into an integer. Returns whether the conversion is complete.
template <typename int_t>
bool ParseInt(std::string_view string, int_t &i, int base = 10) {
  if (string.empty())
    return false;

  const char *begin = string.data();
  const char *end = begin + string.size();
  if (string.size() > 2 && string[0] == '0' && string[1] == 'x') {
    base = 16;
    begin += 2;
  }
  return std::from_chars(begin, end, i, base).ptr == end;
}

}  // namespace

bool LogParser::ProcessNextLine() {
  std::string line;

  std::getline(input_, line);
  if (input_.eof() && line.empty()) {
    return false;
  }

  // Handle symbolizer markup.
  auto start = line.find("{{{");
  auto end = std::string::npos;

  if (start != std::string::npos) {
    end = line.find("}}}", start);
  }
  if (end != std::string::npos) {
    std::string_view line_view(line);
    auto output = CreateOutputFn(line_view.substr(0, start), line_view.substr(end + 3));
    if (ProcessMarkup(line_view.substr(start + 3, end - start - 3), std::move(output))) {
      // Skip outputting only if we have the starting and the ending braces and the markup is valid.
      return true;
    }
  }

  // Handle Dart symbolization.
  if (line == kDartStackTraceMagic) {
    symbolizing_dart_ = true;
  } else if (symbolizing_dart_) {
    if (ProcessDart(line, CreateOutputFn("", ""))) {
      return true;
    }
    symbolizing_dart_ = false;
  }

  OutputRaw(line);
  return true;
}

bool LogParser::ProcessMarkup(std::string_view markup, Symbolizer::OutputFn output) {
  auto splitted = fxl::SplitString(markup, ":", fxl::kKeepWhitespace, fxl::kSplitWantAll);
  if (splitted.empty()) {
    return false;
  }

  auto tag = splitted[0];

  if (tag == "reset") {
    auto type = Symbolizer::ResetType::kUnknown;
    if (splitted.size() >= 2) {
      if (splitted[1] == "begin") {
        type = Symbolizer::ResetType::kBegin;
      } else if (splitted[1] == "end") {
        type = Symbolizer::ResetType::kEnd;
      }
    }
    symbolizer_->Reset(false, type, std::move(output));
    return true;
  }

  if (tag == "module") {
    // module:0x{id}:{name}:elf:{build_id}
    if (splitted.size() < 5)
      return false;

    uint64_t id;
    if (!ParseInt(splitted[1], id) || splitted[3] != "elf")
      return false;

    symbolizer_->Module(id, splitted[2], splitted[4], std::move(output));
    return true;
  }

  if (tag == "mmap") {
    // mmap:0x{address}:0x{size}:load:0x{module_id}:r?w?x?:0x{module_offset}
    if (splitted.size() < 7)
      return false;

    uint64_t address;
    uint64_t size;
    uint64_t module_id;
    uint64_t module_offset;

    if (!ParseInt(splitted[1], address) || !ParseInt(splitted[2], size) ||
        !ParseInt(splitted[4], module_id) || !ParseInt(splitted[6], module_offset) ||
        splitted[3] != "load")
      return false;

    symbolizer_->MMap(address, size, module_id, splitted[5], module_offset, std::move(output));
    return true;
  }

  if (tag == "bt") {
    // bt:{frame_id}:{address}(:ra|:pc)?(:msg)?
    if (splitted.size() < 3)
      return false;

    int frame_id;
    uint64_t address;
    Symbolizer::AddressType type = Symbolizer::AddressType::kUnknown;
    std::string_view message;

    if (!ParseInt(splitted[1], frame_id) || !ParseInt(splitted[2], address))
      return false;

    // Optional suffix(es).
    if (splitted.size() >= 4) {
      if (splitted[3] == "ra") {
        type = Symbolizer::AddressType::kReturnAddress;
      } else if (splitted[3] == "pc") {
        type = Symbolizer::AddressType::kProgramCounter;
      } else {
        message = splitted[3];
      }
      if (splitted.size() >= 5) {
        message = splitted[4];
      }
    }
    symbolizer_->Backtrace(frame_id, address, type, message, std::move(output));
    return true;
  }

  if (tag == "dumpfile") {
    // dumpfile:{type}:{name}
    if (splitted.size() < 3)
      return false;

    symbolizer_->DumpFile(splitted[1], splitted[2], std::move(output));
    return true;
  }

  return false;
}

// If returning true, we're responsible to output the line.
bool LogParser::ProcessDart(std::string_view line, Symbolizer::OutputFn output) {
  constexpr uint64_t kModuleId = 0;
  constexpr uint64_t kModuleSize = 0x800000000;  // 32 GB should be big enough.

  auto splitted = fxl::SplitString(line, " ", fxl::kTrimWhitespace, fxl::kSplitWantNonEmpty);

  if (splitted.size() == 6 && splitted[0] == "pid:") {
    // pid: 12, tid: 30221, name some.ui
    dart_process_name_ = splitted[5];
    symbolizer_->Reset(true, Symbolizer::ResetType::kUnknown, std::move(output));
  } else if (splitted.size() == 2 && splitted[0] == "build_id:") {
    // build_id: '0123456789abcdef'
    symbolizer_->Module(kModuleId, dart_process_name_, fxl::TrimString(splitted[1], "'"),
                        std::move(output));
  } else if (splitted.size() == 4 && splitted[0] == "isolate_dso_base:") {
    // isolate_dso_base: f2e4c8000, vm_dso_base: f2e4c8000
    uint64_t address;
    if (!ParseInt(splitted[3], address, 16)) {
      return false;
    }
    symbolizer_->MMap(address, kModuleSize, kModuleId, "", 0, std::move(output));
  } else if (!splitted.empty() &&
             (splitted[0] == "os:" || splitted[0] == "isolate_instructions:")) {
    // os: fuchsia arch: arm64 comp: no sim: no
    // isolate_instructions: f2f9f8e60, vm_instructions: f2f9f4000
  } else if (splitted.size() >= 6 && splitted[0][0] == '#' && splitted[1] == "abs") {
    // #00 abs 0000000f2fbb51c7 virt 00000000016ed1c7 _kDartIsolateSnapshotInstructions+0x1bc367
    uint64_t frame_id;
    uint64_t address;
    if (!ParseInt(splitted[0].substr(1), frame_id)) {
      return false;
    }
    if (!ParseInt(splitted[2], address, 16)) {
      return false;
    }
    symbolizer_->Backtrace(frame_id, address, Symbolizer::AddressType::kUnknown, "",
                           std::move(output));
    return true;
  } else {
    return false;
  }

  // Don't forget to output the context as is.
  OutputRaw(line);
  return true;
}

Symbolizer::OutputFn LogParser::CreateOutputFn(std::string_view prefix, std::string_view suffix) {
  // Our design requires that the output must be in the same order of the input, which means the
  // the destruction of OutputFn must be in the same order of the construction.
  output_buffers_.emplace_back();
  // Use a pointer to the buffer as a guard to ensure such order, because std::deque won't
  // invalidate reference on resizing.
  std::string *buffer = &output_buffers_.back();
  auto on_drop = fit::defer([this, buffer]() {
    FX_CHECK(buffer == &output_buffers_.front());
    output_ << output_buffers_.front();
    output_buffers_.pop_front();
  });
  return [this, prefix = std::string(prefix), suffix = std::string(suffix),
          on_drop = std::move(on_drop)](std::string_view content) {
    output_ << prefix << content << suffix << '\n';
  };
}

void LogParser::OutputRaw(std::string_view message) {
  if (!output_buffers_.empty()) {
    output_buffers_.back() += message;
    output_buffers_.back() += '\n';
  } else {
    output_ << message << '\n';
  }
}

}  // namespace symbolizer
