/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_LIBELFFILE_ELF_ELF_DEBUG_READER_H_
#define ART_LIBELFFILE_ELF_ELF_DEBUG_READER_H_

#include "base/array_ref.h"
#include "dwarf/headers.h"
#include "elf/elf_utils.h"
#include "xz_utils.h"

#include <map>
#include <string_view>

namespace art {

// Trivial ELF file reader.
//
// It is the bare minimum needed to read mini-debug-info symbols for unwinding.
// We use it to merge JIT mini-debug-infos together or to prune them after GC.
template <typename ElfTypes>
class ElfDebugReader {
 public:
  // Note that the input buffer might be misaligned.
  using Elf_Ehdr ALIGNED(1) = typename ElfTypes::Ehdr;
  using Elf_Phdr ALIGNED(1) = typename ElfTypes::Phdr;
  using Elf_Shdr ALIGNED(1) = typename ElfTypes::Shdr;
  using Elf_Sym ALIGNED(1) = typename ElfTypes::Sym;
  using Elf_Addr ALIGNED(1) = typename ElfTypes::Addr;

  // Call Frame Information.
  struct CFI {
    uint32_t length;  // Length excluding the size of this field.
    int32_t cie_pointer;  // Offset in the section or -1 for CIE.

    const uint8_t* data() const { return reinterpret_cast<const uint8_t*>(this); }
    size_t size() const { return sizeof(uint32_t) + length; }
  } PACKED(1);

  // Common Information Entry.
  struct CIE : public CFI {
  } PACKED(1);

  // Frame Description Entry.
  struct FDE : public CFI {
    Elf_Addr sym_addr;
    Elf_Addr sym_size;
  } PACKED(1);

  explicit ElfDebugReader(ArrayRef<const uint8_t> file) : file_(file) {
    header_ = Read<Elf_Ehdr>(/*offset=*/ 0);
    CHECK_EQ(header_->e_ident[0], ELFMAG0);
    CHECK_EQ(header_->e_ident[1], ELFMAG1);
    CHECK_EQ(header_->e_ident[2], ELFMAG2);
    CHECK_EQ(header_->e_ident[3], ELFMAG3);
    CHECK_EQ(header_->e_ident[4], sizeof(Elf_Addr) / sizeof(uint32_t));
    CHECK_EQ(header_->e_ehsize, sizeof(Elf_Ehdr));

    // Find all ELF sections.
    CHECK_EQ(header_->e_shentsize, sizeof(Elf_Shdr));
    sections_ = Read<Elf_Shdr>(header_->e_shoff, header_->e_shnum);
    for (const Elf_Shdr& section : sections_) {
      const char* name = Read<char>(sections_[header_->e_shstrndx].sh_offset + section.sh_name);
      section_map_[std::string_view(name)] = &section;
    }

    // Decompressed embedded debug symbols, if any.
    const Elf_Shdr* gnu_debugdata = section_map_[".gnu_debugdata"];
    if (gnu_debugdata != nullptr) {
      auto compressed = Read<uint8_t>(gnu_debugdata->sh_offset, gnu_debugdata->sh_size);
      XzDecompress(compressed, &decompressed_gnu_debugdata_);
      gnu_debugdata_reader_.reset(new ElfDebugReader(decompressed_gnu_debugdata_));
    }
  }

  explicit ElfDebugReader(const std::vector<uint8_t>& file)
      : ElfDebugReader(ArrayRef<const uint8_t>(file)) {
  }

  // Check that ELF signature is present at the start of the files,
  // and that the ELF bitness matches the ElfTypes template arguments.
  static bool IsValidElfHeader(const std::vector<uint8_t>& data) {
    static constexpr bool kIs64Bit = sizeof(Elf_Addr) == sizeof(uint64_t);
    static constexpr char kMagic[] = { 0x7f, 'E', 'L', 'F', kIs64Bit ? 2 : 1 };
    return data.size() >= sizeof(kMagic) && memcmp(data.data(), kMagic, sizeof(kMagic)) == 0;
  }

  const Elf_Ehdr* GetHeader() { return header_; }

  ArrayRef<Elf_Shdr> GetSections() { return sections_; }

  const Elf_Shdr* GetSection(const char* name) { return section_map_[name]; }

  // Find the base address where the ELF file wants to be loaded.
  // This is generally zero (therefore always requiring relocation).
  Elf_Addr GetLoadAddress() {
    std::optional<Elf_Addr> addr;
    CHECK_EQ(header_->e_phentsize, sizeof(Elf_Phdr));
    for (const Elf_Phdr& phdr : Read<Elf_Phdr>(header_->e_phoff, header_->e_phnum)) {
      if (phdr.p_type == PT_LOAD) {
        addr = addr.has_value() ? std::min(addr.value(), phdr.p_vaddr) : phdr.p_vaddr;
      }
    }
    CHECK(addr.has_value());
    return addr.value();
  }

  template <typename VisitSym>
  void VisitFunctionSymbols(VisitSym visit_sym) {
    const Elf_Shdr* symtab = GetSection(".symtab");
    const Elf_Shdr* strtab = GetSection(".strtab");
    const Elf_Shdr* text = GetSection(".text");
    if (symtab != nullptr && strtab != nullptr) {
      CHECK_EQ(symtab->sh_entsize, sizeof(Elf_Sym));
      size_t count = symtab->sh_size / sizeof(Elf_Sym);
      for (const Elf_Sym& symbol : Read<Elf_Sym>(symtab->sh_offset, count)) {
        if (ELF_ST_TYPE(symbol.st_info) == STT_FUNC && &sections_[symbol.st_shndx] == text) {
          visit_sym(symbol, Read<char>(strtab->sh_offset + symbol.st_name));
        }
      }
    }
    if (gnu_debugdata_reader_ != nullptr) {
      gnu_debugdata_reader_->VisitFunctionSymbols(visit_sym);
    }
  }

  template <typename VisitSym>
  void VisitDynamicSymbols(VisitSym visit_sym) {
    const Elf_Shdr* dynsym = GetSection(".dynsym");
    const Elf_Shdr* dynstr = GetSection(".dynstr");
    if (dynsym != nullptr && dynstr != nullptr) {
      CHECK_EQ(dynsym->sh_entsize, sizeof(Elf_Sym));
      size_t count = dynsym->sh_size / sizeof(Elf_Sym);
      for (const Elf_Sym& symbol : Read<Elf_Sym>(dynsym->sh_offset, count)) {
        visit_sym(symbol, Read<char>(dynstr->sh_offset + symbol.st_name));
      }
    }
  }

  template <typename VisitCIE, typename VisitFDE>
  void VisitDebugFrame(VisitCIE visit_cie, VisitFDE visit_fde) {
    const Elf_Shdr* debug_frame = GetSection(".debug_frame");
    if (debug_frame != nullptr) {
      for (size_t offset = 0; offset < debug_frame->sh_size;) {
        const CFI* entry = Read<CFI>(debug_frame->sh_offset + offset);
        DCHECK_LE(entry->size(), debug_frame->sh_size - offset);
        if (entry->cie_pointer == -1) {
          visit_cie(Read<CIE>(debug_frame->sh_offset + offset));
        } else {
          const FDE* fde = Read<FDE>(debug_frame->sh_offset + offset);
          visit_fde(fde, Read<CIE>(debug_frame->sh_offset + fde->cie_pointer));
        }
        offset += entry->size();
      }
    }
    if (gnu_debugdata_reader_ != nullptr) {
      gnu_debugdata_reader_->VisitDebugFrame(visit_cie, visit_fde);
    }
  }

 private:
  template<typename T>
  const T* Read(size_t offset) {
    DCHECK_LE(offset + sizeof(T), file_.size());
    return reinterpret_cast<const T*>(file_.data() + offset);
  }

  template<typename T>
  ArrayRef<const T> Read(size_t offset, size_t count) {
    DCHECK_LE(offset + count * sizeof(T), file_.size());
    return ArrayRef<const T>(Read<T>(offset), count);
  }

  ArrayRef<const uint8_t> const file_;
  const Elf_Ehdr* header_;
  ArrayRef<const Elf_Shdr> sections_;
  std::unordered_map<std::string_view, const Elf_Shdr*> section_map_;
  std::vector<uint8_t> decompressed_gnu_debugdata_;
  std::unique_ptr<ElfDebugReader> gnu_debugdata_reader_;

  DISALLOW_COPY_AND_ASSIGN(ElfDebugReader);
};

}  // namespace art
#endif  // ART_LIBELFFILE_ELF_ELF_DEBUG_READER_H_
