/*
 * 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 &&
            symbol.st_shndx < sections_.size() &&  // Ignore ABS section.
            &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(std::forward<VisitSym>(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(std::forward<VisitCIE>(visit_cie),
                                             std::forward<VisitFDE>(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_
