// 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 <fcntl.h>
#include <link.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <zircon/syscalls.h>
#include <zircon/types.h>

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

#include "dso_list.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) {
  if (!strcmp(name, "libc.so")) {
    name = "libmusl.so";
  }
  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) {
    FXL_LOG(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) {
      FXL_LOG(ERROR) << "Unable to read ELF file: " << ElfErrorName(rc);
      break;
    }

    auto hdr = elf_reader->header();
    rc = elf_reader->ReadSegmentHeaders();
    if (rc != ElfError::OK) {
      FXL_LOG(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;
        }
        FXL_DCHECK(j == num_loadable_phdrs);
        dso->num_loadable_phdrs = num_loadable_phdrs;
        dso->loadable_phdrs = loadable_phdrs;
      } else {
        FXL_LOG(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.
      FXL_VLOG(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) {
    FXL_VLOG(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:
        FXL_DCHECK(dso->debug_file != nullptr);
        *out_debug_file = dso->debug_file;
      // fall through
      default:
        FXL_VLOG(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) {
    FXL_VLOG(1) << "OOM building debug file path for dso " << dso->name;
    dso->debug_file_status = ZX_ERR_NO_MEMORY;
    return dso->debug_file_status;
  }

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

  int fd = open(path, O_RDONLY);
  if (fd < 0) {
    FXL_VLOG(1) << "debug file for dso " << dso->name << " not found: " << path;
    free(path);
    dso->debug_file_status = ZX_ERR_NOT_FOUND;
  } else {
    FXL_VLOG(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
