// Copyright 2016 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.

// TODO: Taken from crashlogger. Revisit.

#include "dso_list.h"

#include <fcntl.h>
#include <link.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include "src/lib/fxl/logging.h"
#include "src/lib/fxl/strings/string_printf.h"
#include "util.h"

namespace debugger_utils {

const char kDebugDirectory[] = "/boot/debug";
const char kDebugSuffix[] = ".debug";

static dsoinfo_t* dsolist_add(dsoinfo_t** list, const char* name, uintptr_t base) {
  size_t len = strlen(name);
  size_t alloc_bytes = sizeof(dsoinfo_t) + len + 1;
  auto dso = reinterpret_cast<dsoinfo_t*>(calloc(1, alloc_bytes));
  if (dso == nullptr) {
    FX_LOGS(FATAL) << "OOM allocating " << alloc_bytes << " bytes";
    exit(1);
  }
  memcpy(dso->name, name, len + 1);
  memset(dso->buildid, 'x', sizeof(dso->buildid) - 1);
  dso->base = base;
  dso->debug_file_tried = false;
  dso->debug_file_status = ZX_ERR_BAD_STATE;
  while (*list != nullptr) {
    if ((*list)->base < dso->base) {
      dso->next = *list;
      *list = dso;
      return dso;
    }
    list = &((*list)->next);
  }
  *list = dso;
  dso->next = nullptr;
  return dso;
}

dsoinfo_t* dso_fetch_list(std::shared_ptr<ByteBlock> bb, zx_vaddr_t lmap_addr, const char* name) {
  dsoinfo_t* dsolist = nullptr;
  // The first dso we see is the main executable.
  bool is_main_exec = true;

  while (lmap_addr != 0) {
    char dsoname[64];
    struct link_map lmap;

    // If there's a failure here, say because the internal data structures got
    // corrupted, just bail and return what we've collected so far.

    if (!bb->Read(lmap_addr, &lmap, sizeof(lmap)))
      break;
    if (!ReadString(*bb, reinterpret_cast<zx_vaddr_t>(lmap.l_name), dsoname, sizeof(dsoname)))
      break;

    const char* file_name = dsoname[0] ? dsoname : name;
    dsoinfo_t* dso = dsolist_add(&dsolist, file_name, lmap.l_addr);

    std::unique_ptr<ElfReader> elf_reader;
    ElfError rc = ElfReader::Create(file_name, bb, 0, dso->base, &elf_reader);
    if (rc != ElfError::OK) {
      FX_LOGS(ERROR) << "Unable to read ELF file: " << file_name << ": " << ElfErrorName(rc);
      break;
    }

    auto hdr = elf_reader->header();
    rc = elf_reader->ReadSegmentHeaders();
    if (rc != ElfError::OK) {
      FX_LOGS(ERROR) << "Error reading ELF segment headers: " << ElfErrorName(rc);
    } else {
      size_t num_segments = elf_reader->GetNumSegments();
      uint32_t num_loadable_phdrs = 0;
      for (size_t i = 0; i < num_segments; ++i) {
        const ElfSegmentHeader& phdr = elf_reader->GetSegmentHeader(i);
        if (phdr.p_type == PT_LOAD)
          ++num_loadable_phdrs;
      }
      // malloc may, or may not, return NULL for a zero byte request.
      // Remove the ambiguity for consumers and always use NULL if there no
      // loadable phdrs.
      ElfSegmentHeader* loadable_phdrs = NULL;
      if (num_loadable_phdrs > 0) {
        loadable_phdrs =
            reinterpret_cast<ElfSegmentHeader*>(malloc(num_loadable_phdrs * hdr.e_phentsize));
      }
      if (loadable_phdrs || num_loadable_phdrs == 0) {
        size_t j = 0;
        for (size_t i = 0; i < num_segments; ++i) {
          const ElfSegmentHeader& phdr = elf_reader->GetSegmentHeader(i);
          if (phdr.p_type == PT_LOAD)
            loadable_phdrs[j++] = phdr;
        }
        FX_DCHECK(j == num_loadable_phdrs);
        dso->num_loadable_phdrs = num_loadable_phdrs;
        dso->loadable_phdrs = loadable_phdrs;
      } else {
        FX_LOGS(ERROR) << "OOM reading phdrs";
      }
    }

    rc = elf_reader->ReadBuildId(dso->buildid, sizeof(dso->buildid));
    if (rc != ElfError::OK) {
      // This isn't fatal so don't flag as an error.
      FX_VLOGS(1) << "Unable to read build id: " << ElfErrorName(rc);
    }

    dso->is_main_exec = is_main_exec;
    dso->entry = dso->base + hdr.e_entry;
    dso->phdr = dso->base + hdr.e_phoff;
    dso->phentsize = hdr.e_phentsize;
    dso->phnum = hdr.e_phnum;

    is_main_exec = false;
    lmap_addr = reinterpret_cast<zx_vaddr_t>(lmap.l_next);
  }

  return dsolist;
}

void dso_free_list(dsoinfo_t* list) {
  while (list != nullptr) {
    dsoinfo_t* next = list->next;
    free(list->loadable_phdrs);
    free(list->debug_file);
    free(list);
    list = next;
  }
}

dsoinfo_t* dso_lookup(dsoinfo_t* dso_list, zx_vaddr_t pc) {
  for (auto dso = dso_list; dso != nullptr; dso = dso->next) {
    if (pc >= dso->base)
      return dso;
  }

  return nullptr;
}

dsoinfo_t* dso_get_main_exec(dsoinfo_t* dso_list) {
  for (auto dso = dso_list; dso != nullptr; dso = dso->next) {
    if (dso->is_main_exec)
      return dso;
  }

  return nullptr;
}

void dso_print_list(FILE* out, const dsoinfo_t* dso_list) {
  for (auto dso = dso_list; dso != nullptr; dso = dso->next) {
    fprintf(out, "dso: id=%s base=%p name=%s\n", dso->buildid, (void*)dso->base, dso->name);
  }
}

void dso_vlog_list(const dsoinfo_t* dso_list) {
  for (auto dso = dso_list; dso != nullptr; dso = dso->next) {
    FX_VLOGS(2) << fxl::StringPrintf("dso: id=%s base=%p name=%s", dso->buildid, (void*)dso->base,
                                     dso->name);
  }
}

zx_status_t dso_find_debug_file(dsoinfo_t* dso, const char** out_debug_file) {
  // Have we already tried?
  // Yeah, if we OOM it's possible it'll succeed next time, but
  // it's not worth the extra complexity to avoid printing the debugging
  // messages twice.
  if (dso->debug_file_tried) {
    switch (dso->debug_file_status) {
      case ZX_OK:
        FX_DCHECK(dso->debug_file != nullptr);
        *out_debug_file = dso->debug_file;
      // fall through
      default:
        FX_VLOGS(2) << "returning " << dso->debug_file_status
                    << ", already tried to find debug file for " << dso->name;
        return dso->debug_file_status;
    }
  }

  dso->debug_file_tried = true;

  char* path;
  if (asprintf(&path, "%s/%s%s", kDebugDirectory, dso->buildid, kDebugSuffix) < 0) {
    FX_VLOGS(1) << "OOM building debug file path for dso " << dso->name;
    dso->debug_file_status = ZX_ERR_NO_MEMORY;
    return dso->debug_file_status;
  }

  FX_VLOGS(1) << "looking for debug file " << path;

  int fd = open(path, O_RDONLY);
  if (fd < 0) {
    FX_VLOGS(1) << "debug file for dso " << dso->name << " not found: " << path;
    free(path);
    dso->debug_file_status = ZX_ERR_NOT_FOUND;
  } else {
    FX_VLOGS(1) << "found debug file for dso " << dso->name << ": " << path;
    close(fd);
    dso->debug_file = path;
    *out_debug_file = path;
    dso->debug_file_status = ZX_OK;
  }

  return dso->debug_file_status;
}

}  // namespace debugger_utils
