// 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 "elf_symtab.h"

#include "src/lib/fxl/logging.h"

namespace debugger_utils {

ElfSymbolTable::ElfSymbolTable(const std::string& file_name,
                               const std::string& contents)
    : file_name_(file_name), contents_(contents) {}

ElfSymbolTable::~ElfSymbolTable() {
  if (symbols_)
    delete[] symbols_;
}

bool ElfSymbolTable::Populate(ElfReader* elf, unsigned symtab_type) {
  FXL_DCHECK(symtab_type == SHT_SYMTAB || symtab_type == SHT_DYNSYM);

  // TODO(dje): Add support for loading both SHT_SYMTAB and SHT_DYNSYM.
  if (symbols_) {
    FXL_LOG(ERROR) << "Already populated";
    return false;
  }

  ElfError rc = elf->ReadSectionHeaders();
  if (rc != ElfError::OK) {
    FXL_LOG(ERROR) << "Error reading ELF section headers: " << ElfErrorName(rc);
    return false;
  }

  const ElfSectionHeader* shdr = elf->GetSectionHeaderByType(symtab_type);
  if (!shdr)
    return true;  // empty symbol table

  size_t num_sections = elf->GetNumSections();
  size_t string_section = shdr->sh_link;
  if (string_section >= num_sections) {
    FXL_LOG(ERROR) << "Bad string section: " << string_section;
    return false;
  }
  const ElfSectionHeader& str_shdr = elf->GetSectionHeader(string_section);

  std::unique_ptr<ElfSectionContents> contents;
  rc = elf->GetSectionContents(*shdr, &contents);
  if (rc != ElfError::OK) {
    FXL_LOG(ERROR) << "Error reading ELF section: " << ElfErrorName(rc);
    return false;
  }

  rc = elf->GetSectionContents(str_shdr, &string_section_);
  if (rc != ElfError::OK) {
    FXL_LOG(ERROR) << "Error reading ELF string section: " << ElfErrorName(rc);
    return false;
  }

  auto strings = reinterpret_cast<const char*>(string_section_->contents());
  size_t max_string_offset = string_section_->GetSize();

  size_t num_raw_symbols = contents->GetNumEntries();
  symbols_ = new ElfSymbol[num_raw_symbols];

  size_t num_symbols = 0;
  for (size_t i = 0; i < num_raw_symbols; ++i) {
    const ElfRawSymbol& sym = contents->GetSymbolEntry(i);
    if (sym.st_name >= max_string_offset) {
      FXL_LOG(ERROR) << "Bad symbol string name offset: " << sym.st_name;
      continue;
    }
    ElfSymbol* s = &symbols_[num_symbols++];
    // TODO(dje): IWBN to have a convenience function for getting symbol
    // names, not sure what it will look like yet.
    s->name = strings + sym.st_name;
    s->addr = sym.st_value;
    s->size = sym.st_size;
  }

  num_symbols_ = num_symbols;
  Finalize();
  return true;
}

static int CompareSymbol(const void* ap, const void* bp) {
  auto a = reinterpret_cast<const ElfSymbol*>(ap);
  auto b = reinterpret_cast<const ElfSymbol*>(bp);
  if (a->addr >= b->addr && a->addr < b->addr + b->size)
    return 0;
  if (b->addr >= a->addr && b->addr < a->addr + a->size)
    return 0;
  return a->addr - b->addr;
}

void ElfSymbolTable::Finalize() {
  qsort(symbols_, num_symbols_, sizeof(ElfSymbol), CompareSymbol);
}

const ElfSymbol* ElfSymbolTable::FindSymbol(uint64_t addr) const {
  ElfSymbol search = {.addr = addr};

  /* add last hit cache here */

  auto s = reinterpret_cast<const ElfSymbol*>(bsearch(
      &search, symbols_, num_symbols_, sizeof(ElfSymbol), CompareSymbol));
  return s;
}

void ElfSymbolTable::Dump(FILE* f) const {
  fprintf(f, "file: %s\n", file_name_.c_str());
  fprintf(f, "contents: %s\n", contents_.c_str());
  for (size_t i = 0; i < num_symbols_; i++) {
    ElfSymbol* s = &symbols_[i];
    if (s->addr && s->name[0])
      fprintf(f, "%p %s\n", (void*)s->addr, s->name);
  }
}

}  // namespace debugger_utils
