/*
 * Copyright (C) 2016 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.
 */

#include "elf_debug_writer.h"

#include <type_traits>
#include <unordered_map>
#include <vector>

#include "base/array_ref.h"
#include "base/stl_util.h"
#include "debug/elf_compilation_unit.h"
#include "debug/elf_debug_frame_writer.h"
#include "debug/elf_debug_info_writer.h"
#include "debug/elf_debug_line_writer.h"
#include "debug/elf_debug_loc_writer.h"
#include "debug/elf_symtab_writer.h"
#include "debug/method_debug_info.h"
#include "dwarf/dwarf_constants.h"
#include "elf/elf_builder.h"
#include "elf/elf_debug_reader.h"
#include "elf/elf_utils.h"
#include "elf/xz_utils.h"
#include "jit/debugger_interface.h"
#include "oat/oat.h"
#include "stream/vector_output_stream.h"

namespace art HIDDEN {
namespace debug {

using ElfRuntimeTypes = std::conditional<sizeof(void*) == 4, ElfTypes32, ElfTypes64>::type;

template <typename ElfTypes>
void WriteDebugInfo(ElfBuilder<ElfTypes>* builder,
                    const DebugInfo& debug_info) {
  // Write .strtab and .symtab.
  WriteDebugSymbols(builder, /* mini-debug-info= */ false, debug_info);

  // Write .debug_frame.
  WriteCFISection(builder, debug_info.compiled_methods);

  // Group the methods into compilation units based on class.
  std::unordered_map<const dex::ClassDef*, ElfCompilationUnit> class_to_compilation_unit;
  for (const MethodDebugInfo& mi : debug_info.compiled_methods) {
    if (mi.dex_file != nullptr) {
      auto& dex_class_def = mi.dex_file->GetClassDef(mi.class_def_index);
      ElfCompilationUnit& cu = class_to_compilation_unit[&dex_class_def];
      cu.methods.push_back(&mi);
      // All methods must have the same addressing mode otherwise the min/max below does not work.
      DCHECK_EQ(cu.methods.front()->is_code_address_text_relative, mi.is_code_address_text_relative);
      cu.is_code_address_text_relative = mi.is_code_address_text_relative;
      cu.code_address = std::min(cu.code_address, mi.code_address);
      cu.code_end = std::max(cu.code_end, mi.code_address + mi.code_size);
    }
  }

  // Sort compilation units to make the compiler output deterministic.
  std::vector<ElfCompilationUnit> compilation_units;
  compilation_units.reserve(class_to_compilation_unit.size());
  for (auto& it : class_to_compilation_unit) {
    // The .debug_line section requires the methods to be sorted by code address.
    std::stable_sort(it.second.methods.begin(),
                     it.second.methods.end(),
                     [](const MethodDebugInfo* a, const MethodDebugInfo* b) {
                         return a->code_address < b->code_address;
                     });
    compilation_units.push_back(std::move(it.second));
  }
  std::sort(compilation_units.begin(),
            compilation_units.end(),
            [](ElfCompilationUnit& a, ElfCompilationUnit& b) {
                // Sort by index of the first method within the method_infos array.
                // This assumes that the order of method_infos is deterministic.
                // Code address is not good for sorting due to possible duplicates.
                return a.methods.front() < b.methods.front();
            });

  // Write .debug_line section.
  if (!compilation_units.empty()) {
    ElfDebugLineWriter<ElfTypes> line_writer(builder);
    line_writer.Start();
    for (auto& compilation_unit : compilation_units) {
      line_writer.WriteCompilationUnit(compilation_unit);
    }
    line_writer.End();
  }

  // Write .debug_info section.
  if (!compilation_units.empty()) {
    ElfDebugInfoWriter<ElfTypes> info_writer(builder);
    info_writer.Start();
    for (const auto& compilation_unit : compilation_units) {
      ElfCompilationUnitWriter<ElfTypes> cu_writer(&info_writer);
      cu_writer.Write(compilation_unit);
    }
    info_writer.End();
  }
}

template <typename ElfTypes>
static std::vector<uint8_t> MakeMiniDebugInfoInternal(
    InstructionSet isa,
    [[maybe_unused]] const InstructionSetFeatures* features,
    typename ElfTypes::Addr text_section_address,
    size_t text_section_size,
    typename ElfTypes::Addr dex_section_address,
    size_t dex_section_size,
    const DebugInfo& debug_info) {
  std::vector<uint8_t> buffer;
  buffer.reserve(KB);
  VectorOutputStream out("Mini-debug-info ELF file", &buffer);
  std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out));
  builder->Start(/* write_program_headers= */ false);
  // Mirror ELF sections as NOBITS since the added symbols will reference them.
  if (text_section_size != 0) {
    builder->GetText()->AllocateVirtualMemory(text_section_address, text_section_size);
  }
  if (dex_section_size != 0) {
    builder->GetDex()->AllocateVirtualMemory(dex_section_address, dex_section_size);
  }
  if (!debug_info.Empty()) {
    WriteDebugSymbols(builder.get(), /* mini-debug-info= */ true, debug_info);
  }
  if (!debug_info.compiled_methods.empty()) {
    WriteCFISection(builder.get(), debug_info.compiled_methods);
  }
  builder->End();
  CHECK(builder->Good());
  std::vector<uint8_t> compressed_buffer;
  compressed_buffer.reserve(buffer.size() / 4);
  XzCompress(ArrayRef<const uint8_t>(buffer), &compressed_buffer);
  return compressed_buffer;
}

std::vector<uint8_t> MakeMiniDebugInfo(
    InstructionSet isa,
    const InstructionSetFeatures* features,
    uint64_t text_section_address,
    size_t text_section_size,
    uint64_t dex_section_address,
    size_t dex_section_size,
    const DebugInfo& debug_info) {
  if (Is64BitInstructionSet(isa)) {
    return MakeMiniDebugInfoInternal<ElfTypes64>(isa,
                                                 features,
                                                 text_section_address,
                                                 text_section_size,
                                                 dex_section_address,
                                                 dex_section_size,
                                                 debug_info);
  } else {
    return MakeMiniDebugInfoInternal<ElfTypes32>(isa,
                                                 features,
                                                 text_section_address,
                                                 text_section_size,
                                                 dex_section_address,
                                                 dex_section_size,
                                                 debug_info);
  }
}

std::vector<uint8_t> MakeElfFileForJIT(InstructionSet isa,
                                       [[maybe_unused]] const InstructionSetFeatures* features,
                                       bool mini_debug_info,
                                       const MethodDebugInfo& method_info) {
  using ElfTypes = ElfRuntimeTypes;
  CHECK_EQ(sizeof(ElfTypes::Addr), static_cast<size_t>(GetInstructionSetPointerSize(isa)));
  CHECK_EQ(method_info.is_code_address_text_relative, false);
  DebugInfo debug_info{};
  debug_info.compiled_methods = ArrayRef<const MethodDebugInfo>(&method_info, 1);
  std::vector<uint8_t> buffer;
  buffer.reserve(KB);
  VectorOutputStream out("Debug ELF file", &buffer);
  std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out));
  // No program headers since the ELF file is not linked and has no allocated sections.
  builder->Start(/* write_program_headers= */ false);
  builder->GetText()->AllocateVirtualMemory(method_info.code_address, method_info.code_size);
  if (mini_debug_info) {
    // The compression is great help for multiple methods but it is not worth it for a
    // single method due to the overheads so skip the compression here for performance.
    WriteDebugSymbols(builder.get(), /* mini-debug-info= */ true, debug_info);
    WriteCFISection(builder.get(), debug_info.compiled_methods);
  } else {
    WriteDebugInfo(builder.get(), debug_info);
  }
  builder->End();
  CHECK(builder->Good());
  // Verify the ELF file by reading it back using the trivial reader.
  if (kIsDebugBuild) {
    using Elf_Sym = typename ElfTypes::Sym;
    size_t num_syms = 0;
    size_t num_cies = 0;
    size_t num_fdes = 0;
    using Reader = ElfDebugReader<ElfTypes>;
    Reader reader(buffer);
    reader.VisitFunctionSymbols([&](Elf_Sym sym, const char*) {
      DCHECK_EQ(sym.st_value,
                method_info.code_address + GetInstructionSetEntryPointAdjustment(isa));
      DCHECK_EQ(sym.st_size, method_info.code_size);
      num_syms++;
    });
    reader.VisitDebugFrame([&]([[maybe_unused]] const Reader::CIE* cie) { num_cies++; },
                           [&](const Reader::FDE* fde, [[maybe_unused]] const Reader::CIE* cie) {
                             DCHECK_EQ(fde->sym_addr, method_info.code_address);
                             DCHECK_EQ(fde->sym_size, method_info.code_size);
                             num_fdes++;
                           });
    DCHECK_EQ(num_syms, 1u);
    DCHECK_LE(num_cies, 1u);
    DCHECK_LE(num_fdes, 1u);
  }
  return buffer;
}

// Combine several mini-debug-info ELF files into one, while filtering some symbols.
std::vector<uint8_t> PackElfFileForJIT(
    ArrayRef<const JITCodeEntry*> jit_entries,
    ArrayRef<const void*> removed_symbols,
    bool compress,
    /*out*/ size_t* num_symbols) {
  using ElfTypes = ElfRuntimeTypes;
  using Elf_Addr = typename ElfTypes::Addr;
  using Elf_Sym = typename ElfTypes::Sym;
  const InstructionSet isa = kRuntimeISA;
  CHECK_EQ(sizeof(Elf_Addr), static_cast<size_t>(GetInstructionSetPointerSize(isa)));
  const uint32_t kPcAlign = GetInstructionSetInstructionAlignment(isa);
  auto is_pc_aligned = [](const void* pc) { return IsAligned<kPcAlign>(pc); };
  DCHECK(std::all_of(removed_symbols.begin(), removed_symbols.end(), is_pc_aligned));
  auto is_removed_symbol = [&removed_symbols](Elf_Addr addr) {
    // Remove thumb-bit, if any (using the fact that address is instruction aligned).
    const void* code_ptr = AlignDown(reinterpret_cast<const void*>(addr), kPcAlign);
    return std::binary_search(removed_symbols.begin(), removed_symbols.end(), code_ptr);
  };
  uint64_t min_address = std::numeric_limits<uint64_t>::max();
  uint64_t max_address = 0;

  // Produce the inner ELF file.
  // It will contain the symbols (.symtab) and unwind information (.debug_frame).
  std::vector<uint8_t> inner_elf_file;
  {
    inner_elf_file.reserve(1 * KB);  // Approximate size of ELF file with a single symbol.
    VectorOutputStream out("Mini-debug-info ELF file for JIT", &inner_elf_file);
    std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out));
    builder->Start(/*write_program_headers=*/ false);
    auto* text = builder->GetText();
    auto* strtab = builder->GetStrTab();
    auto* symtab = builder->GetSymTab();
    auto* debug_frame = builder->GetDebugFrame();
    std::deque<Elf_Sym> symbols;

    using Reader = ElfDebugReader<ElfTypes>;
    std::deque<Reader> readers;
    for (const JITCodeEntry* it : jit_entries) {
      readers.emplace_back(GetJITCodeEntrySymFile(it));
    }

    // Write symbols names. All other data is buffered.
    strtab->Start();
    strtab->Write("");  // strtab should start with empty string.
    for (Reader& reader : readers) {
      reader.VisitFunctionSymbols([&](Elf_Sym sym, const char* name) {
          if (is_removed_symbol(sym.st_value)) {
            return;
          }
          sym.st_name = strtab->Write(name);
          symbols.push_back(sym);
          min_address = std::min<uint64_t>(min_address, sym.st_value);
          max_address = std::max<uint64_t>(max_address, sym.st_value + sym.st_size);
      });
    }
    strtab->End();

    // Create .text covering the code range. Needed for gdb to find the symbols.
    if (max_address > min_address) {
      text->AllocateVirtualMemory(min_address, max_address - min_address);
    }

    // Add the symbols.
    *num_symbols = symbols.size();
    for (; !symbols.empty(); symbols.pop_front()) {
      symtab->Add(symbols.front(), text);
    }
    symtab->WriteCachedSection();

    // Add the CFI/unwind section.
    debug_frame->Start();
    // ART always produces the same CIE, so we copy the first one and ignore the rest.
    bool copied_cie = false;
    for (Reader& reader : readers) {
      reader.VisitDebugFrame(
          [&](const Reader::CIE* cie) {
            if (!copied_cie) {
              debug_frame->WriteFully(cie->data(), cie->size());
              copied_cie = true;
            }
          },
          [&](const Reader::FDE* fde, [[maybe_unused]] const Reader::CIE* cie) {
            DCHECK(copied_cie);
            DCHECK_EQ(fde->cie_pointer, 0);
            if (!is_removed_symbol(fde->sym_addr)) {
              debug_frame->WriteFully(fde->data(), fde->size());
            }
          });
    }
    debug_frame->End();

    builder->End();
    CHECK(builder->Good());
  }

  // Produce the outer ELF file.
  // It contains only the inner ELF file compressed as .gnu_debugdata section.
  // This extra wrapping is not necessary but the compression saves space.
  if (compress) {
    std::vector<uint8_t> outer_elf_file;
    std::vector<uint8_t> gnu_debugdata;
    gnu_debugdata.reserve(inner_elf_file.size() / 4);
    XzCompress(ArrayRef<const uint8_t>(inner_elf_file), &gnu_debugdata);

    outer_elf_file.reserve(KB + gnu_debugdata.size());
    VectorOutputStream out("Mini-debug-info ELF file for JIT", &outer_elf_file);
    std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out));
    builder->Start(/*write_program_headers=*/ false);
    if (max_address > min_address) {
      builder->GetText()->AllocateVirtualMemory(min_address, max_address - min_address);
    }
    builder->WriteSection(".gnu_debugdata", &gnu_debugdata);
    builder->End();
    CHECK(builder->Good());
    return outer_elf_file;
  } else {
    return inner_elf_file;
  }
}

std::vector<uint8_t> WriteDebugElfFileForClasses(
    InstructionSet isa,
    [[maybe_unused]] const InstructionSetFeatures* features,
    const ArrayRef<mirror::Class*>& types) REQUIRES_SHARED(Locks::mutator_lock_) {
  using ElfTypes = ElfRuntimeTypes;
  CHECK_EQ(sizeof(ElfTypes::Addr), static_cast<size_t>(GetInstructionSetPointerSize(isa)));
  std::vector<uint8_t> buffer;
  buffer.reserve(KB);
  VectorOutputStream out("Debug ELF file", &buffer);
  std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out));
  // No program headers since the ELF file is not linked and has no allocated sections.
  builder->Start(/* write_program_headers= */ false);
  ElfDebugInfoWriter<ElfTypes> info_writer(builder.get());
  info_writer.Start();
  ElfCompilationUnitWriter<ElfTypes> cu_writer(&info_writer);
  cu_writer.Write(types);
  info_writer.End();

  builder->End();
  CHECK(builder->Good());
  return buffer;
}

// Explicit instantiations
template void WriteDebugInfo<ElfTypes32>(
    ElfBuilder<ElfTypes32>* builder,
    const DebugInfo& debug_info);
template void WriteDebugInfo<ElfTypes64>(
    ElfBuilder<ElfTypes64>* builder,
    const DebugInfo& debug_info);

}  // namespace debug
}  // namespace art
