// 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) {
  FX_DCHECK(symtab_type == SHT_SYMTAB || symtab_type == SHT_DYNSYM);

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

  ElfError rc = elf->ReadSectionHeaders();
  if (rc != ElfError::OK) {
    FX_LOGS(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) {
    FX_LOGS(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) {
    FX_LOGS(ERROR) << "Error reading ELF section: " << ElfErrorName(rc);
    return false;
  }

  rc = elf->GetSectionContents(str_shdr, &string_section_);
  if (rc != ElfError::OK) {
    FX_LOGS(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) {
      FX_LOGS(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
