/*
 * Copyright (C) 2021 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 "android-base/logging.h"

#include "base/os.h"
#include "base/unix_file/fd_file.h"
#include "elf/elf_builder.h"
#include "elf/elf_debug_reader.h"
#include "elf/xz_utils.h"
#include "stream/file_output_stream.h"
#include "stream/vector_output_stream.h"

#include <algorithm>
#include <deque>
#include <map>
#include <memory>
#include <string>
#include <string_view>
#include <vector>

namespace art {

static constexpr size_t kBlockSize = 32 * KB;

constexpr const char kSortedSymbolName[] = "$android.symtab.sorted";

template<typename ElfTypes>
static void WriteMinidebugInfo(const std::vector<uint8_t>& input, std::vector<uint8_t>* output) {
  using Elf_Addr = typename ElfTypes::Addr;
  using Elf_Shdr = typename ElfTypes::Shdr;
  using Elf_Sym = typename ElfTypes::Sym;
  using Elf_Word = typename ElfTypes::Word;
  using CIE = typename ElfDebugReader<ElfTypes>::CIE;
  using FDE = typename ElfDebugReader<ElfTypes>::FDE;

  ElfDebugReader<ElfTypes> reader(input);

  std::vector<uint8_t> output_elf_data;
  VectorOutputStream output_stream("Output ELF", &output_elf_data);
  InstructionSet isa = ElfBuilder<ElfTypes>::GetIsaFromHeader(*reader.GetHeader());
  std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &output_stream));
  builder->Start(/*write_program_headers=*/ false);

  auto* text = builder->GetText();
  const Elf_Shdr* original_text = reader.GetSection(".text");
  CHECK(original_text != nullptr);
  text->AllocateVirtualMemory(original_text->sh_addr, original_text->sh_size);

  auto* strtab = builder->GetStrTab();
  auto* symtab = builder->GetSymTab();
  strtab->Start();
  {
    std::multimap<std::string_view, Elf_Sym> syms;
    reader.VisitFunctionSymbols([&](Elf_Sym sym, const char* name) {
      // Exclude non-function or empty symbols.
      if (ELF32_ST_TYPE(sym.st_info) == STT_FUNC && sym.st_size != 0) {
        syms.emplace(name, sym);
      }
    });
    reader.VisitDynamicSymbols([&](Elf_Sym sym, const char* name) {
      // Exclude symbols which will be preserved in the dynamic table anyway.
      auto it = syms.find(name);
      if (it != syms.end() && it->second.st_value == sym.st_value) {
        syms.erase(it);
      }
    });
    if (!syms.empty()) {
      symtab->Add(strtab->Write(kSortedSymbolName), nullptr, 0, 0, STB_GLOBAL, STT_NOTYPE);
    }
    for (auto& entry : syms) {
      std::string_view name = entry.first;
      const Elf_Sym& sym = entry.second;
      Elf_Word name_idx = strtab->Write(name);
      symtab->Add(name_idx, text, sym.st_value, sym.st_size, STB_GLOBAL, STT_FUNC);
    }
  }
  strtab->End();
  symtab->WriteCachedSection();

  auto* debug_frame = builder->GetDebugFrame();
  debug_frame->Start();
  {
    std::map<std::string_view, Elf_Addr> cie_dedup;
    std::unordered_map<const CIE*, Elf_Addr> new_cie_offset;
    std::deque<std::pair<const FDE*, const CIE*>> entries;
    // Read, de-duplicate and write CIE entries.  Read FDE entries.
    reader.VisitDebugFrame(
        [&](const CIE* cie) {
          std::string_view key(reinterpret_cast<const char*>(cie->data()), cie->size());
          auto it = cie_dedup.emplace(key, debug_frame->GetPosition());
          if (/* inserted */ it.second) {
            debug_frame->WriteFully(cie->data(), cie->size());
          }
          new_cie_offset[cie] = it.first->second;
        },
        [&](const FDE* fde, const CIE* cie) { entries.emplace_back(std::make_pair(fde, cie)); });
    // Sort FDE entries by opcodes to improve locality for compression (saves ~25%).
    std::stable_sort(entries.begin(), entries.end(), [](const auto& lhs, const auto& rhs) {
      constexpr size_t opcode_offset = sizeof(FDE);
      return std::lexicographical_compare(
          lhs.first->data() + opcode_offset, lhs.first->data() + lhs.first->size(),
          rhs.first->data() + opcode_offset, rhs.first->data() + rhs.first->size());
    });
    // Write all FDE entries while adjusting the CIE offsets to the new locations.
    for (const auto& entry : entries) {
      const FDE* fde = entry.first;
      const CIE* cie = entry.second;
      FDE new_header = *fde;
      new_header.cie_pointer = new_cie_offset[cie];
      debug_frame->WriteFully(&new_header, sizeof(FDE));
      debug_frame->WriteFully(fde->data() + sizeof(FDE), fde->size() - sizeof(FDE));
    }
  }
  debug_frame->End();

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

  XzCompress(ArrayRef<const uint8_t>(output_elf_data), output, 9 /*size*/, kBlockSize);
}

static int Main(int argc, char** argv) {
  // Check command like arguments.
  if (argc != 3) {
    printf("Usage: create_minidebuginfo ELF_FILE OUT_FILE\n");
    printf("  ELF_FILE: The path to an ELF file with full symbols (before being stripped).\n");
    printf("  OUT_FILE: The path for the generated mini-debug-info data (not an elf file).\n");
    return 1;
  }
  const char* input_filename = argv[1];
  const char* output_filename = argv[2];

  // Read input file.
  std::unique_ptr<File> input_file(OS::OpenFileForReading(input_filename));
  CHECK(input_file.get() != nullptr) << "Failed to open input file";
  std::vector<uint8_t> elf(input_file->GetLength());
  CHECK(input_file->ReadFully(elf.data(), elf.size())) << "Failed to read input file";

  // Write output file.
  std::vector<uint8_t> output;
  if (ElfDebugReader<ElfTypes32>::IsValidElfHeader(elf)) {
    WriteMinidebugInfo<ElfTypes32>(elf, &output);
  } else if (ElfDebugReader<ElfTypes64>::IsValidElfHeader(elf)) {
    WriteMinidebugInfo<ElfTypes64>(elf, &output);
  } else {
    LOG(FATAL) << "Invalid ELF file header " << input_filename;
  }
  std::unique_ptr<File> output_file(OS::CreateEmptyFile(output_filename));
  if (!output_file->WriteFully(output.data(), output.size()) || output_file->FlushClose() != 0) {
    LOG(FATAL) << "Failed to write " << output_filename;
  }
  return 0;
}

}  // namespace art

int main(int argc, char** argv) {
  return art::Main(argc, argv);
}
