// Copyright 2017 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 "load_maps.h"

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

#include <cinttypes>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>

#include "src/lib/files/directory.h"
#include "src/lib/files/path.h"
#include "src/lib/fxl/strings/string_printf.h"
#include "util.h"

namespace debugger_utils {

bool LoadMapTable::ReadLogListenerOutput(const std::string& file) {
  FX_LOGS(INFO) << "Loading load maps from " << file;

  FILE* f = fopen(file.c_str(), "r");
  if (!f) {
    FX_LOGS(ERROR) << "error opening file, " << ErrnoString(errno);
    return false;
  }
  auto close_file = fit::defer([&]() { fclose(f); });

  constexpr size_t kMaxLineLen = 1024;
  char* line = nullptr;
  size_t line_capacity = 0;
  int lineno = 1;

  std::map<uint64_t, LoadMap> map_data;
  ssize_t line_len;

  // These buffers are needed to break out elements of the line. Rather than
  // allocate space for them during each iteration we allocate them here.
  // And rather than use up a fair bit of stack, we use the heap.
  char* prefix = reinterpret_cast<char*>(malloc(kMaxLineLen));
  char* build_id = reinterpret_cast<char*>(malloc(kMaxLineLen));
  char* name = reinterpret_cast<char*>(malloc(kMaxLineLen));
  char* so_name = reinterpret_cast<char*>(malloc(kMaxLineLen));

  auto free_mem = fit::defer([&]() {
    free(line);
    free(prefix);
    free(build_id);
    free(name);
    free(so_name);
  });

  if (!prefix || !build_id || !name || !so_name) {
    FX_LOGS(ERROR) << "Out of memory";
    return false;
  }

  for (; (line_len = getline(&line, &line_capacity, f)) > 0; ++lineno) {
    // For paranoia's sake, watch for embedded NULs.
    size_t n = strlen(line);
    if (static_cast<ssize_t>(n) != line_len) {
      FX_LOGS(WARNING) << "Line contains embedded NULs: " << std::string(line, line_len);
      continue;
    }
    if (n > 0 && line[n - 1] == '\n')
      line[n - 1] = '\0';
    FX_VLOGS(2) << fxl::StringPrintf("%d: %s", lineno, line);

    if (n > kMaxLineLen) {
      FX_VLOGS(2) << fxl::StringPrintf("%d: too long, ignoring", lineno);
    }

    if (!strcmp(line, "\n"))
      continue;
    if (line[0] == '#')
      continue;

    // If this is a new boot, start over.
    if (strstr(line, "welcome to Zircon")) {
      FX_VLOGS(1) << "Restarting reading of load maps, machine rebooted";
      map_data.clear();
      Clear();
      continue;
    }

    // The sequence number is used for grouping records, done beforehand, but
    // is no longer needed after that.
    unsigned seqno;
    uint64_t pid, base_addr, load_addr, end_addr;

    // ld.so dumps the data in three separate records to avoid line-wrapping:
    // a: base load end
    // b: build_id
    // c: name so_name
    // TODO(dje): See MG-519. This is a temp hack until ld.so logs this data
    // via something better.

#define GET_ENTRY_ID(pid, seqno) (((pid) << 8) + (seqno))

    if (sscanf(line,
               "%[^@]@trace_load: %" PRIu64 ":%ua"
               " 0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64,
               prefix, &pid, &seqno, &base_addr, &load_addr, &end_addr) == 6) {
      uint64_t id = GET_ENTRY_ID(pid, seqno);
      if (map_data.find(id) != map_data.end()) {
        FX_LOGS(ERROR) << "Already have map entry for: " << line;
        continue;
      }
      struct LoadMap entry;
      entry.pid = pid;
      entry.base_addr = base_addr;
      entry.load_addr = load_addr;
      entry.end_addr = end_addr;
      map_data[id] = entry;
    } else if (sscanf(line,
                      "%[^@]@trace_load: %" PRIu64 ":%ub"
                      " %s",
                      prefix, &pid, &seqno, build_id) == 4) {
      uint64_t id = GET_ENTRY_ID(pid, seqno);
      auto entry_iter = map_data.find(id);
      if (entry_iter == map_data.end()) {
        FX_LOGS(ERROR) << "Missing entry (A record) for: " << line;
        continue;
      }
      (*entry_iter).second.build_id = build_id;
    } else if (sscanf(line,
                      "%[^@]@trace_load: %" PRIu64 ":%uc"
                      " %s %s",
                      prefix, &pid, &seqno, name, so_name) == 5) {
      uint64_t id = GET_ENTRY_ID(pid, seqno);
      auto entry_iter = map_data.find(id);
      if (entry_iter == map_data.end()) {
        FX_LOGS(ERROR) << "Missing entry (A record) for: " << line;
        continue;
      }
      LoadMap& entry = (*entry_iter).second;
      entry.name = name;
      entry.so_name = so_name;
      // We should now have the full record.
      AddLoadMap(entry);
    } else {
      FX_VLOGS(2) << fxl::StringPrintf("%d: ignoring", lineno);
    }
  }

  if (!feof(f)) {
    FX_LOGS(ERROR) << "Error reading file";
    return false;
  }

  return true;
}

void LoadMapTable::AddLoadMap(const LoadMap& map) {
  FX_VLOGS(2) << fxl::StringPrintf("Adding map entry, pid %" PRIu64 " %s 0x%" PRIx64 "-0x%" PRIx64,
                                   map.pid, map.name.c_str(), map.load_addr, map.end_addr);
  maps_.push_back(map);
}

void LoadMapTable::Clear() { maps_.clear(); }

const LoadMap* LoadMapTable::LookupLoadMap(zx_koid_t pid, uint64_t addr) {
  for (auto& m : maps_) {
    if (pid == m.pid && addr >= m.load_addr && addr < m.end_addr)
      return &m;
  }

  return nullptr;
}

}  // namespace debugger_utils
