// 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 <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include "src/lib/fxl/logging.h"
#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) {
  FXL_DCHECK(options == 0);
  FXL_VLOG(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)) {
    FXL_VLOG(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)) {
    FXL_VLOG(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)) {
    FXL_VLOG(2) << "Bad ELF segment size";
    return false;
  }
  if (hdr->e_shnum > 0 && hdr->e_shentsize != sizeof(ElfSectionHeader)) {
    FXL_VLOG(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) {
  FXL_DCHECK(segment_headers_);
  FXL_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) {
  FXL_DCHECK(section_headers_);
  FXL_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) {
    FXL_LOG(ERROR) << "OOM getting space for section contents";
    return ElfError::NOMEM;
  }

  if (!byte_block_->Read(base_ + sh.sh_offset, buffer, sh.sh_size)) {
    FXL_LOG(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_;

  FXL_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) {
  FXL_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;
  }

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

const ElfRawSymbol& ElfSectionContents::GetSymbolEntry(size_t entry_number) {
  FXL_DCHECK(header_.sh_type == SHT_SYMTAB || header_.sh_type == SHT_DYNSYM);
  FXL_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
