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

#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <link.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <elf-search.h>
#include <zircon/assert.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include "inspector/inspector.h"
#include "dso-list-impl.h"
#include "utils-impl.h"

#define rdebug_off_lmap offsetof(struct r_debug, r_map)

#define lmap_off_next offsetof(struct link_map, l_next)
#define lmap_off_name offsetof(struct link_map, l_name)
#define lmap_off_addr offsetof(struct link_map, l_addr)

using inspector::fetch_build_id;
using inspector::fetch_string;
using inspector::read_mem;

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

static inspector_dsoinfo_t* dsolist_add(inspector_dsoinfo_t** list, const char* name,
                                        uintptr_t base) {
  if (!strncmp(name, "app:devhost:", 12)) {
    // devhost processes use their name field to describe
    // the root of their device sub-tree.
    name = "app:/boot/bin/devhost";
  }
  size_t len = strlen(name);
  auto dso =
      reinterpret_cast<inspector_dsoinfo_t*>(calloc(1, sizeof(inspector_dsoinfo_t) + len + 1));
  if (dso == nullptr) {
    return nullptr;
  }
  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;
}

__EXPORT inspector_dsoinfo_t* inspector_dso_fetch_list(zx_handle_t h) {
  // Prepend "app:" to the name we print for the process binary to tell the
  // reader (and the symbolize script!) that the name is the process's.
  // The name property is only 32 characters which may be insufficient.
  // N.B. The symbolize script looks for "app" and "app:".
#define PROCESS_NAME_PREFIX "app:"
#define PROCESS_NAME_PREFIX_LEN (sizeof(PROCESS_NAME_PREFIX) - 1)
  char name[ZX_MAX_NAME_LEN + PROCESS_NAME_PREFIX_LEN];
  strcpy(name, PROCESS_NAME_PREFIX);
  auto status = zx_object_get_property(h, ZX_PROP_NAME, name + PROCESS_NAME_PREFIX_LEN,
                                       sizeof(name) - PROCESS_NAME_PREFIX_LEN);
  if (status != ZX_OK) {
    print_zx_error("zx_object_get_property, falling back to \"app\" for program name", status);
    strlcpy(name, "app", sizeof(name));
  }

  uintptr_t lmap, debug_addr;
  status = zx_object_get_property(h, ZX_PROP_PROCESS_DEBUG_ADDR, &debug_addr, sizeof(debug_addr));
  if (status != ZX_OK) {
    print_zx_error("zx_object_get_property(ZX_PROP_PROCESS_DEBUG_ADDR), unable to fetch dso list",
                   status);
    return nullptr;
  }
  if (read_mem(h, debug_addr + rdebug_off_lmap, &lmap, sizeof(lmap))) {
    return nullptr;
  }
  inspector_dsoinfo_t* dsolist = nullptr;
  int iter = 0;
  while (lmap != 0) {
    if (iter++ > 500) {
      print_error("dso_fetch_list detected too many entries, possible infinite loop");
      return nullptr;
    }
    char dsoname[64];
    zx_vaddr_t base;
    uintptr_t next;
    uintptr_t str;
    if (read_mem(h, lmap + lmap_off_addr, &base, sizeof(base))) {
      break;
    }
    if (read_mem(h, lmap + lmap_off_next, &next, sizeof(next))) {
      break;
    }
    if (read_mem(h, lmap + lmap_off_name, &str, sizeof(str))) {
      break;
    }
    if (fetch_string(h, str, dsoname, sizeof(dsoname))) {
      break;
    }
    inspector_dsoinfo_t* dso = dsolist_add(&dsolist, dsoname[0] ? dsoname : name, base);
    if (dso != nullptr) {
      fetch_build_id(h, dso->base, dso->buildid, sizeof(dso->buildid));
    }
    lmap = next;
  }

  return dsolist;
}

__EXPORT void inspector_dso_free_list(inspector_dsoinfo_t* list) {
  while (list != NULL) {
    inspector_dsoinfo_t* next = list->next;
    free(list->debug_file);
    free(list);
    list = next;
  }
}

__EXPORT inspector_dsoinfo_t* inspector_dso_lookup(inspector_dsoinfo_t* dso_list, zx_vaddr_t pc) {
  for (inspector_dsoinfo_t* dso = dso_list; dso != NULL; dso = dso->next) {
    if (pc >= dso->base) {
      return dso;
    }
  }

  return nullptr;
}

__EXPORT void inspector_print_markup_context(FILE* f, zx_handle_t process) {
  fprintf(f, "{{{reset}}}\n");
  ForEachModule(*zx::unowned_process{process}, [f, count = 0u](const ModuleInfo& info) mutable {
    unsigned int module_id = count++;
    // Print out the module first.
    fprintf(f, "{{{module:%#x:%s:elf:", module_id, info.name.begin());
    for (uint8_t byte : info.build_id) {
      fprintf(f, "%02x", byte);
    }
    fprintf(f, "}}}\n");
    // Now print out the various segments.
    for (const auto& phdr : info.phdrs) {
      if (phdr.p_type != PT_LOAD) {
        continue;
      }
      uintptr_t start = phdr.p_vaddr & -PAGE_SIZE;
      uintptr_t end = (phdr.p_vaddr + phdr.p_memsz + PAGE_SIZE - 1) & -PAGE_SIZE;
      fprintf(f, "{{{mmap:%#" PRIxPTR ":%#" PRIxPTR ":load:%#x:", info.vaddr + start, end - start,
              module_id);
      if (phdr.p_flags & PF_R) {
        fprintf(f, "%c", 'r');
      }
      if (phdr.p_flags & PF_W) {
        fprintf(f, "%c", 'w');
      }
      if (phdr.p_flags & PF_X) {
        fprintf(f, "%c", 'x');
      }
      fprintf(f, ":%#" PRIxPTR "}}}\n", start);
    }
  });
}

__EXPORT void inspector_dso_print_list(FILE* f, inspector_dsoinfo_t* dso_list) {
  for (inspector_dsoinfo_t* dso = dso_list; dso != nullptr; dso = dso->next) {
    fprintf(f, "dso: id=%s base=%p name=%s\n", dso->buildid, (void*)dso->base, dso->name);
  }
}

__EXPORT zx_status_t inspector_dso_find_debug_file(inspector_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:
        ZX_DEBUG_ASSERT(dso->debug_file != nullptr);
        *out_debug_file = dso->debug_file;
        __FALLTHROUGH;
      default:
        debugf(2, "returning %d, already tried to find debug file for %s\n", dso->debug_file_status,
               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) {
    debugf(1, "OOM building debug file path for dso %s\n", dso->name);
    dso->debug_file_status = ZX_ERR_NO_MEMORY;
    return dso->debug_file_status;
  }

  debugf(1, "looking for debug file %s\n", path);

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

  return dso->debug_file_status;
}
