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

#include <lib/syslog/cpp/macros.h>

#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>

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

namespace debugger_utils {

const char* ElfErrorName(ElfError err) {
  switch (err) {
    case ElfError::OK:
      return "OK";
    case ElfError::IO:
      return "IO";
    case ElfError::BADELF:
      return "BADELF";
    case ElfError::NOMEM:
      return "NOMEM";
    default:
      return "UNKNOWN";
  }
}

ElfError ElfReader::Create(const std::string& file_name, std::shared_ptr<ByteBlock> byte_block,
                           uint32_t options, uint64_t base, std::unique_ptr<ElfReader>* out) {
  FX_DCHECK(options == 0);
  FX_VLOGS(1) << "Creating ELF reader for: " << file_name << ": base 0x" << std::hex << base;
  ElfReader* er = new ElfReader(file_name, byte_block, base);
  if (!ReadHeader(*byte_block, base, &er->header_)) {
    delete er;
    return ElfError::IO;
  }
  if (!VerifyHeader(&er->header_)) {
    delete er;
    return ElfError::BADELF;
  }
  *out = std::unique_ptr<ElfReader>(er);
  return ElfError::OK;
}

ElfReader::ElfReader(const std::string& file_name, std::shared_ptr<ByteBlock> byte_block,
                     uint64_t base)
    : file_name_(file_name), byte_block_(byte_block), base_(base) {}

ElfReader::~ElfReader() {
  FreeSegmentHeaders();
  FreeSectionHeaders();
}

// static
bool ElfReader::ReadHeader(const ByteBlock& m, uint64_t base, ElfHeader* hdr) {
  return m.Read(base, hdr, sizeof(*hdr));
}

// static
bool ElfReader::VerifyHeader(const ElfHeader* hdr) {
  if (memcmp(hdr->e_ident, ELFMAG, SELFMAG)) {
    FX_VLOGS(2) << fxl::StringPrintf("Bad ELF magic: %02x %02x %02x %02x", hdr->e_ident[0],
                                     hdr->e_ident[1], hdr->e_ident[2], hdr->e_ident[3]);
    return false;
  }
  // TODO(dje): Support larger entries.
  if (hdr->e_ehsize != sizeof(ElfHeader)) {
    FX_VLOGS(2) << "Bad ELF header size";
    return false;
  }
  // It's possible the entry size is zero if there are no entries.
  if (hdr->e_phnum > 0 && hdr->e_phentsize != sizeof(ElfSegmentHeader)) {
    FX_VLOGS(2) << "Bad ELF segment size";
    return false;
  }
  if (hdr->e_shnum > 0 && hdr->e_shentsize != sizeof(ElfSectionHeader)) {
    FX_VLOGS(2) << "Bad ELF section size";
    return false;
  }

  // TODO(dje): Could add more checks.
  return true;
}

ElfError ElfReader::ReadSegmentHeaders() {
  if (segment_headers_)
    return ElfError::OK;
  size_t num_segments = GetNumSegments();
  auto seg_hdrs = new ElfSegmentHeader[num_segments];
  if (!byte_block_->Read(base_ + header_.e_phoff, seg_hdrs,
                         num_segments * sizeof(ElfSegmentHeader))) {
    delete[] seg_hdrs;
    return ElfError::IO;
  }
  segment_headers_ = seg_hdrs;
  return ElfError::OK;
}

void ElfReader::FreeSegmentHeaders() {
  if (segment_headers_)
    delete[] segment_headers_;
  segment_headers_ = nullptr;
}

const ElfSegmentHeader& ElfReader::GetSegmentHeader(size_t segment_number) {
  FX_DCHECK(segment_headers_);
  FX_DCHECK(segment_number < GetNumSegments());
  return segment_headers_[segment_number];
}

ElfError ElfReader::ReadSectionHeaders() {
  if (section_headers_)
    return ElfError::OK;
  size_t num_sections = GetNumSections();
  auto scn_hdrs = new ElfSectionHeader[num_sections];
  if (!byte_block_->Read(base_ + header_.e_shoff, scn_hdrs,
                         num_sections * sizeof(ElfSectionHeader))) {
    delete[] scn_hdrs;
    return ElfError::IO;
  }
  section_headers_ = scn_hdrs;
  return ElfError::OK;
}

void ElfReader::FreeSectionHeaders() {
  if (section_headers_)
    delete[] section_headers_;
  section_headers_ = nullptr;
}

const ElfSectionHeader& ElfReader::GetSectionHeader(size_t section_number) {
  FX_DCHECK(section_headers_);
  FX_DCHECK(section_number < GetNumSections());
  return section_headers_[section_number];
}

const ElfSectionHeader* ElfReader::GetSectionHeaderByType(unsigned type) {
  size_t num_sections = GetNumSections();
  for (size_t i = 0; i < num_sections; ++i) {
    const ElfSectionHeader& shdr = GetSectionHeader(i);
    if (shdr.sh_type == type)
      return &shdr;
  }
  return nullptr;
}

ElfError ElfReader::GetSectionContents(const ElfSectionHeader& sh,
                                       std::unique_ptr<ElfSectionContents>* out_contents) {
  void* buffer = malloc(sh.sh_size);
  if (!buffer) {
    FX_LOGS(ERROR) << "OOM getting space for section contents";
    return ElfError::NOMEM;
  }

  if (!byte_block_->Read(base_ + sh.sh_offset, buffer, sh.sh_size)) {
    FX_LOGS(ERROR) << "Error reading section contents";
    return ElfError::IO;
  }

  // TODO(dje): Handle malloc failures for new.
  auto contents = new ElfSectionContents(sh, buffer);
  *out_contents = std::unique_ptr<ElfSectionContents>(contents);
  return ElfError::OK;
}

ElfError ElfReader::ReadBuildId(char* buf, size_t buf_size) {
  uint64_t vaddr = base_;

  FX_DCHECK(buf_size >= kMaxBuildIdSize * 2 + 1);

  ElfError rc = ReadSegmentHeaders();
  if (rc != ElfError::OK)
    return rc;

  size_t num_segments = GetNumSegments();

  for (size_t i = 0; i < num_segments; ++i) {
    const auto& phdr = GetSegmentHeader(i);
    if (phdr.p_type != PT_NOTE)
      continue;

    struct {
      Elf32_Nhdr hdr;
      char name[sizeof("GNU")];
    } note;
    uint64_t size = phdr.p_filesz;
    uint64_t offset = phdr.p_offset;
    while (size > sizeof(note)) {
      if (!byte_block_->Read(vaddr + offset, &note, sizeof(note)))
        return ElfError::IO;
      size_t header_size = sizeof(Elf32_Nhdr) + ((note.hdr.n_namesz + 3) & -4);
      size_t payload_size = (note.hdr.n_descsz + 3) & -4;
      offset += header_size;
      size -= header_size;
      uint64_t payload_vaddr = vaddr + offset;
      offset += payload_size;
      size -= payload_size;
      if (note.hdr.n_type != NT_GNU_BUILD_ID || note.hdr.n_namesz != sizeof("GNU") ||
          memcmp(note.name, "GNU", sizeof("GNU")) != 0) {
        continue;
      }
      if (note.hdr.n_descsz > kMaxBuildIdSize) {
        // TODO(dje): Revisit.
        snprintf(buf, buf_size, "build_id_too_large_%u", note.hdr.n_descsz);
      } else {
        uint8_t buildid[kMaxBuildIdSize];
        if (!byte_block_->Read(payload_vaddr, buildid, note.hdr.n_descsz))
          return ElfError::IO;
        for (uint32_t i = 0; i < note.hdr.n_descsz; ++i) {
          snprintf(&buf[i * 2], 3, "%02x", buildid[i]);
        }
      }
      return ElfError::OK;
    }
  }

  *buf = '\0';
  return ElfError::OK;
}

ElfSectionContents::ElfSectionContents(const ElfSectionHeader& header, void* contents)
    : header_(header), contents_(contents) {
  FX_DCHECK(contents);
}

ElfSectionContents::~ElfSectionContents() { free(contents_); }

size_t ElfSectionContents::GetNumEntries() const {
  switch (header_.sh_type) {
    case SHT_SYMTAB:
    case SHT_DYNSYM:
      break;
    default:
      return 0;
  }

  FX_DCHECK(header_.sh_entsize != 0);
  return header_.sh_size / header_.sh_entsize;
}

const ElfRawSymbol& ElfSectionContents::GetSymbolEntry(size_t entry_number) {
  FX_DCHECK(header_.sh_type == SHT_SYMTAB || header_.sh_type == SHT_DYNSYM);
  FX_DCHECK(entry_number < GetNumEntries());
  auto buf = reinterpret_cast<const char*>(contents_);
  auto sym = buf + entry_number * header_.sh_entsize;
  return *reinterpret_cast<const ElfRawSymbol*>(sym);
}

}  // namespace debugger_utils
