//===- lib/ReaderWriter/ELF/OutputELFWriter.cpp --------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "OutputELFWriter.h"
#include "lld/Core/SharedLibraryFile.h"
#include "lld/Core/Simple.h"
#include "lld/ReaderWriter/ELFLinkingContext.h"
#include "llvm/Support/Path.h"

namespace lld {
namespace elf {

namespace {

template <class ELFT> class SymbolFile : public RuntimeFile<ELFT> {
public:
  SymbolFile(ELFLinkingContext &ctx)
      : RuntimeFile<ELFT>(ctx, "Dynamic absolute symbols") {}

  void addUndefinedAtom(StringRef) override {
    llvm_unreachable("Cannot add undefined atoms to resolve undefined symbols");
  }

  bool hasAtoms() const { return this->absolute().size(); }
};

template <class ELFT>
class DynamicSymbolFile : public SimpleArchiveLibraryFile {
  typedef std::function<void(StringRef, RuntimeFile<ELFT> &)> Resolver;

public:
  DynamicSymbolFile(ELFLinkingContext &ctx, Resolver resolver)
      : SimpleArchiveLibraryFile("Dynamically added runtime symbols"),
        _ctx(ctx), _resolver(resolver) {}

  File *find(StringRef sym, bool dataSymbolOnly) override {
    if (!_file)
      _file.reset(new (_alloc) SymbolFile<ELFT>(_ctx));

    assert(!_file->hasAtoms() && "The file shouldn't have atoms yet");
    _resolver(sym, *_file);

    if (!_file->hasAtoms())
      return nullptr;

    // If atoms were added - return the file but also store it for later
    // destruction.
    File *result = _file.get();
    _returnedFiles.push_back(std::move(_file));
    return result;
  }

private:
  ELFLinkingContext &_ctx;
  Resolver _resolver;

  // The allocator should go before bump pointers because of
  // reversed destruction order.
  llvm::BumpPtrAllocator _alloc;
  unique_bump_ptr<SymbolFile<ELFT>> _file;
  std::vector<unique_bump_ptr<SymbolFile<ELFT>>> _returnedFiles;
};

} // end anon namespace

template <class ELFT>
OutputELFWriter<ELFT>::OutputELFWriter(ELFLinkingContext &ctx,
                                       TargetLayout<ELFT> &layout)
    : _ctx(ctx), _targetHandler(ctx.getTargetHandler()), _layout(layout) {}

template <class ELFT>
void OutputELFWriter<ELFT>::buildChunks(const File &file) {
  ScopedTask task(getDefaultDomain(), "buildChunks");
  for (const DefinedAtom *definedAtom : file.defined()) {
    DefinedAtom::ContentType contentType = definedAtom->contentType();
    // Dont add COMDAT group atoms and GNU linkonce atoms, as they are used for
    // symbol resolution.
    // TODO: handle partial linking.
    if (contentType == DefinedAtom::typeGroupComdat ||
        contentType == DefinedAtom::typeGnuLinkOnce)
      continue;
    _layout.addAtom(definedAtom);
  }
  for (const AbsoluteAtom *absoluteAtom : file.absolute())
    _layout.addAtom(absoluteAtom);
}

template <class ELFT>
void OutputELFWriter<ELFT>::buildStaticSymbolTable(const File &file) {
  ScopedTask task(getDefaultDomain(), "buildStaticSymbolTable");
  for (auto sec : _layout.sections())
    if (auto section = dyn_cast<AtomSection<ELFT>>(sec))
      for (const auto &atom : section->atoms())
        _symtab->addSymbol(atom->_atom, section->ordinal(), atom->_virtualAddr);
  for (auto &atom : _layout.absoluteAtoms())
    _symtab->addSymbol(atom->_atom, ELF::SHN_ABS, atom->_virtualAddr);
  for (const UndefinedAtom *a : file.undefined())
    _symtab->addSymbol(a, ELF::SHN_UNDEF);
}

// Returns the DSO name for a given input file if it's a shared library
// file and not marked as --as-needed.
template <class ELFT>
StringRef OutputELFWriter<ELFT>::maybeGetSOName(Node *node) {
  if (auto *fnode = dyn_cast<FileNode>(node))
    if (!fnode->asNeeded())
      if (auto *file = dyn_cast<SharedLibraryFile>(fnode->getFile()))
        return file->getDSOName();
  return "";
}

template <class ELFT>
void OutputELFWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
  ScopedTask task(getDefaultDomain(), "buildDynamicSymbolTable");
  for (const auto &sla : file.sharedLibrary()) {
    if (isDynSymEntryRequired(sla)) {
      _dynamicSymbolTable->addSymbol(sla, ELF::SHN_UNDEF);
      _soNeeded.insert(sla->loadName());
      continue;
    }
    if (isNeededTagRequired(sla))
      _soNeeded.insert(sla->loadName());
  }
  for (const std::unique_ptr<Node> &node : _ctx.getNodes()) {
    StringRef soname = maybeGetSOName(node.get());
    if (!soname.empty())
      _soNeeded.insert(soname);
  }
  // Never mark the dynamic linker as DT_NEEDED
  _soNeeded.erase(sys::path::filename(_ctx.getInterpreter()));
  for (const auto &loadName : _soNeeded)
    _dynamicTable->addEntry(DT_NEEDED,
                            _dynamicStringTable->addString(loadName.getKey()));
  const auto &rpathList = _ctx.getRpathList();
  if (!rpathList.empty()) {
    auto rpath =
        new (_alloc) std::string(join(rpathList.begin(), rpathList.end(), ":"));
    _dynamicTable->addEntry(_ctx.getEnableNewDtags() ? DT_RUNPATH : DT_RPATH,
                            _dynamicStringTable->addString(*rpath));
  }
  StringRef soname = _ctx.sharedObjectName();
  if (!soname.empty() && _ctx.getOutputELFType() == llvm::ELF::ET_DYN)
    _dynamicTable->addEntry(DT_SONAME, _dynamicStringTable->addString(soname));

  // Add DT_FLAGS/DT_FLAGS_1 entries if necessary.
  uint32_t dtflags = 0, dt1flags = 0;
  if (_ctx.getDTFlag(ELFLinkingContext::DTFlag::DT_NOW)) {
    dtflags |= DF_BIND_NOW;
    dt1flags |= DF_1_NOW;
  }
  if (_ctx.getDTFlag(ELFLinkingContext::DTFlag::DT_ORIGIN)) {
    dtflags |= DF_ORIGIN;
    dt1flags |= DF_1_ORIGIN;
  }
  if (dtflags != 0)
    _dynamicTable->addEntry(DT_FLAGS, dtflags);
  if (dt1flags != 0)
    _dynamicTable->addEntry(DT_FLAGS_1, dt1flags);

  // The dynamic symbol table need to be sorted earlier because the hash
  // table needs to be built using the dynamic symbol table. It would be
  // late to sort the symbols due to that in finalize. In the dynamic symbol
  // table finalize, we call the symbol table finalize and we don't want to
  // sort again
  _dynamicSymbolTable->sortSymbols();

  // Add the dynamic symbols into the hash table
  _dynamicSymbolTable->addSymbolsToHashTable();
}

template <class ELFT>
void OutputELFWriter<ELFT>::buildAtomToAddressMap(const File &file) {
  ScopedTask task(getDefaultDomain(), "buildAtomToAddressMap");
  int64_t totalAbsAtoms = _layout.absoluteAtoms().size();
  int64_t totalUndefinedAtoms = file.undefined().size();
  int64_t totalDefinedAtoms = 0;
  for (auto sec : _layout.sections())
    if (auto section = dyn_cast<AtomSection<ELFT>>(sec)) {
      totalDefinedAtoms += section->atoms().size();
      for (const auto &atom : section->atoms())
        _atomToAddressMap[atom->_atom] = atom->_virtualAddr;
    }
  // build the atomToAddressMap that contains absolute symbols too
  for (auto &atom : _layout.absoluteAtoms())
    _atomToAddressMap[atom->_atom] = atom->_virtualAddr;

  // Set the total number of atoms in the symbol table, so that appropriate
  // resizing of the string table can be done.
  // There's no such thing as symbol table if we're stripping all the symbols
  if (!_ctx.stripSymbols())
    _symtab->setNumEntries(totalDefinedAtoms + totalAbsAtoms +
                           totalUndefinedAtoms);
}

template <class ELFT> void OutputELFWriter<ELFT>::buildSectionHeaderTable() {
  ScopedTask task(getDefaultDomain(), "buildSectionHeaderTable");
  for (auto outputSection : _layout.outputSections()) {
    if (outputSection->kind() != Chunk<ELFT>::Kind::ELFSection &&
        outputSection->kind() != Chunk<ELFT>::Kind::AtomSection)
      continue;
    if (outputSection->hasSegment())
      _shdrtab->appendSection(outputSection);
  }
}

template <class ELFT>
void OutputELFWriter<ELFT>::assignSectionsWithNoSegments() {
  ScopedTask task(getDefaultDomain(), "assignSectionsWithNoSegments");
  for (auto outputSection : _layout.outputSections()) {
    if (outputSection->kind() != Chunk<ELFT>::Kind::ELFSection &&
        outputSection->kind() != Chunk<ELFT>::Kind::AtomSection)
      continue;
    if (!outputSection->hasSegment())
      _shdrtab->appendSection(outputSection);
  }
  _layout.assignFileOffsetsForMiscSections();
  for (auto sec : _layout.sections())
    if (auto section = dyn_cast<Section<ELFT>>(sec))
      if (!TargetLayout<ELFT>::hasOutputSegment(section))
        _shdrtab->updateSection(section);
}

template <class ELFT>
void OutputELFWriter<ELFT>::createImplicitFiles(
    std::vector<std::unique_ptr<File>> &result) {
  // Add the virtual archive to resolve undefined symbols.
  // The file will be added later in the linking context.
  auto callback = [this](StringRef sym, RuntimeFile<ELFT> &file) {
    processUndefinedSymbol(sym, file);
  };
  _ctx.setUndefinesResolver(
      llvm::make_unique<DynamicSymbolFile<ELFT>>(_ctx, std::move(callback)));
  // Add script defined symbols
  auto file =
      llvm::make_unique<RuntimeFile<ELFT>>(_ctx, "Linker script runtime");
  for (auto &sym : this->_ctx.linkerScriptSema().getScriptDefinedSymbols())
    file->addAbsoluteAtom(sym.getKey());
  result.push_back(std::move(file));
}

template <class ELFT> void OutputELFWriter<ELFT>::finalizeDefaultAtomValues() {
  const llvm::StringSet<> &symbols =
      _ctx.linkerScriptSema().getScriptDefinedSymbols();
  for (auto &sym : symbols) {
    uint64_t res =
        _ctx.linkerScriptSema().getLinkerScriptExprValue(sym.getKey());
    AtomLayout *a = _layout.findAbsoluteAtom(sym.getKey());
    assert(a);
    a->_virtualAddr = res;
  }
  // If there is a section named XXX, and XXX is a valid C identifier,
  // and there are undefined or weak __start_XXX/__stop_XXX symbols,
  // set the symbols values to the begin/end of the XXX section
  // correspondingly.
  for (const auto &name : _ctx.cidentSectionNames())
    updateScopeAtomValues((Twine("__start_") + name.getKey()).str(),
                          (Twine("__stop_") + name.getKey()).str(),
                          name.getKey());
}

template <class ELFT> void OutputELFWriter<ELFT>::createDefaultSections() {
  _elfHeader.reset(new (_alloc) ELFHeader<ELFT>(_ctx));
  _programHeader.reset(new (_alloc) ProgramHeader<ELFT>(_ctx));
  _layout.setHeader(_elfHeader.get());
  _layout.setProgramHeader(_programHeader.get());

  // Don't create .symtab and .strtab sections if we're going to
  // strip all the symbols.
  if (!_ctx.stripSymbols()) {
    _symtab = this->createSymbolTable();
    _strtab.reset(new (_alloc) StringTable<ELFT>(
        _ctx, ".strtab", TargetLayout<ELFT>::ORDER_STRING_TABLE));
    _layout.addSection(_symtab.get());
    _layout.addSection(_strtab.get());
    _symtab->setStringSection(_strtab.get());
  }

  _shstrtab.reset(new (_alloc) StringTable<ELFT>(
      _ctx, ".shstrtab", TargetLayout<ELFT>::ORDER_SECTION_STRINGS));
  _shdrtab.reset(new (_alloc) SectionHeader<ELFT>(
      _ctx, TargetLayout<ELFT>::ORDER_SECTION_HEADERS));
  _layout.addSection(_shstrtab.get());
  _shdrtab->setStringSection(_shstrtab.get());
  _layout.addSection(_shdrtab.get());

  for (auto sec : _layout.sections()) {
    // TODO: use findOutputSection
    auto section = dyn_cast<Section<ELFT>>(sec);
    if (!section || section->outputSectionName() != ".eh_frame")
      continue;
    _ehFrameHeader.reset(new (_alloc) EHFrameHeader<ELFT>(
        _ctx, ".eh_frame_hdr", _layout, TargetLayout<ELFT>::ORDER_EH_FRAMEHDR));
    _layout.addSection(_ehFrameHeader.get());
    break;
  }

  if (_ctx.isDynamic()) {
    _dynamicTable = createDynamicTable();
    _dynamicStringTable.reset(new (_alloc) StringTable<ELFT>(
        _ctx, ".dynstr", TargetLayout<ELFT>::ORDER_DYNAMIC_STRINGS, true));
    _dynamicSymbolTable = createDynamicSymbolTable();
    _hashTable.reset(new (_alloc) HashSection<ELFT>(
        _ctx, ".hash", TargetLayout<ELFT>::ORDER_HASH));
    // Set the hash table in the dynamic symbol table so that the entries in the
    // hash table can be created
    _dynamicSymbolTable->setHashTable(_hashTable.get());
    _hashTable->setSymbolTable(_dynamicSymbolTable.get());
    _layout.addSection(_dynamicTable.get());
    _layout.addSection(_dynamicStringTable.get());
    _layout.addSection(_dynamicSymbolTable.get());
    _layout.addSection(_hashTable.get());
    _dynamicSymbolTable->setStringSection(_dynamicStringTable.get());
    _dynamicTable->setSymbolTable(_dynamicSymbolTable.get());
    _dynamicTable->setHashTable(_hashTable.get());
    if (_layout.hasDynamicRelocationTable())
      _layout.getDynamicRelocationTable()->setSymbolTable(
          _dynamicSymbolTable.get());
    if (_layout.hasPLTRelocationTable())
      _layout.getPLTRelocationTable()->setSymbolTable(
          _dynamicSymbolTable.get());
  }
}

template <class ELFT>
unique_bump_ptr<SymbolTable<ELFT>> OutputELFWriter<ELFT>::createSymbolTable() {
  return unique_bump_ptr<SymbolTable<ELFT>>(new (_alloc) SymbolTable<ELFT>(
      this->_ctx, ".symtab", TargetLayout<ELFT>::ORDER_SYMBOL_TABLE));
}

/// \brief create dynamic table
template <class ELFT>
unique_bump_ptr<DynamicTable<ELFT>>
OutputELFWriter<ELFT>::createDynamicTable() {
  return unique_bump_ptr<DynamicTable<ELFT>>(new (_alloc) DynamicTable<ELFT>(
      this->_ctx, _layout, ".dynamic", TargetLayout<ELFT>::ORDER_DYNAMIC));
}

/// \brief create dynamic symbol table
template <class ELFT>
unique_bump_ptr<DynamicSymbolTable<ELFT>>
OutputELFWriter<ELFT>::createDynamicSymbolTable() {
  return unique_bump_ptr<DynamicSymbolTable<ELFT>>(
      new (_alloc)
          DynamicSymbolTable<ELFT>(this->_ctx, _layout, ".dynsym",
                                   TargetLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS));
}

template <class ELFT>
std::error_code OutputELFWriter<ELFT>::buildOutput(const File &file) {
  ScopedTask buildTask(getDefaultDomain(), "ELF Writer buildOutput");
  buildChunks(file);

  // Create the default sections like the symbol table, string table, and the
  // section string table
  createDefaultSections();

  // Set the Layout
  _layout.assignSectionsToSegments();

  // Create the dynamic table entries
  if (_ctx.isDynamic()) {
    _dynamicTable->createDefaultEntries();
    buildDynamicSymbolTable(file);
  }

  // Call the preFlight callbacks to modify the sections and the atoms
  // contained in them, in anyway the targets may want
  _layout.doPreFlight();

  _layout.assignVirtualAddress();

  // Finalize the default value of symbols that the linker adds
  finalizeDefaultAtomValues();

  // Build the Atom To Address map for applying relocations
  buildAtomToAddressMap(file);

  // Create symbol table and section string table
  // Do it only if -s is not specified.
  if (!_ctx.stripSymbols())
    buildStaticSymbolTable(file);

  // Finalize the layout by calling the finalize() functions
  _layout.finalize();

  // build Section Header table
  buildSectionHeaderTable();

  // assign Offsets and virtual addresses
  // for sections with no segments
  assignSectionsWithNoSegments();

  if (_ctx.isDynamic())
    _dynamicTable->updateDynamicTable();

  return std::error_code();
}

template <class ELFT> std::error_code OutputELFWriter<ELFT>::setELFHeader() {
  _elfHeader->e_type(_ctx.getOutputELFType());
  _elfHeader->e_machine(_ctx.getOutputMachine());
  _elfHeader->e_ident(ELF::EI_VERSION, 1);
  _elfHeader->e_ident(ELF::EI_OSABI, 0);
  _elfHeader->e_version(1);
  _elfHeader->e_phoff(_programHeader->fileOffset());
  _elfHeader->e_shoff(_shdrtab->fileOffset());
  _elfHeader->e_phentsize(_programHeader->entsize());
  _elfHeader->e_phnum(_programHeader->numHeaders());
  _elfHeader->e_shentsize(_shdrtab->entsize());
  _elfHeader->e_shnum(_shdrtab->numHeaders());
  _elfHeader->e_shstrndx(_shstrtab->ordinal());
  if (const auto *al = _layout.findAtomLayoutByName(_ctx.entrySymbolName()))
    _elfHeader->e_entry(al->_virtualAddr);
  else
    _elfHeader->e_entry(0);

  return std::error_code();
}

template <class ELFT> uint64_t OutputELFWriter<ELFT>::outputFileSize() const {
  return _shdrtab->fileOffset() + _shdrtab->fileSize();
}

template <class ELFT>
std::error_code OutputELFWriter<ELFT>::writeOutput(const File &file,
                                                   StringRef path) {

  ScopedTask createOutputTask(getDefaultDomain(), "ELF Writer Create Output");
  ErrorOr<std::unique_ptr<FileOutputBuffer>> bufferOrErr =
      FileOutputBuffer::create(path, outputFileSize(),
                               FileOutputBuffer::F_executable);
  if (std::error_code ec = bufferOrErr.getError())
    return ec;
  std::unique_ptr<FileOutputBuffer> &buffer = *bufferOrErr;
  createOutputTask.end();

  ScopedTask writeTask(getDefaultDomain(), "ELF Writer write to memory");

  // HACK: We have to write out the header and program header here even though
  // they are a member of a segment because only sections are written in the
  // following loop.

  // Finalize ELF Header / Program Headers.
  _elfHeader->finalize();
  _programHeader->finalize();

  _elfHeader->write(this, _layout, *buffer);
  _programHeader->write(this, _layout, *buffer);

  auto sections = _layout.sections();
  parallel_for_each(
      sections.begin(), sections.end(),
      [&](Chunk<ELFT> *section) { section->write(this, _layout, *buffer); });
  writeTask.end();

  ScopedTask commitTask(getDefaultDomain(), "ELF Writer commit to disk");
  return buffer->commit();
}

template <class ELFT>
std::error_code OutputELFWriter<ELFT>::writeFile(const File &file,
                                                 StringRef path) {
  if (std::error_code ec = buildOutput(file))
    return ec;
  if (std::error_code ec = setELFHeader())
    return ec;
  return writeOutput(file, path);
}

template <class ELFT>
void OutputELFWriter<ELFT>::processUndefinedSymbol(
    StringRef symName, RuntimeFile<ELFT> &file) const {
  if (symName.startswith("__start_")) {
    if (_ctx.cidentSectionNames().count(symName.drop_front(8)))
      file.addAbsoluteAtom(symName);
  } else if (symName.startswith("__stop_")) {
    if (_ctx.cidentSectionNames().count(symName.drop_front(7)))
      file.addAbsoluteAtom(symName);
  }
}

template <class ELFT>
void OutputELFWriter<ELFT>::updateScopeAtomValues(StringRef sym,
                                                  StringRef sec) {
  updateScopeAtomValues(("__" + sym + "_start").str().c_str(),
                        ("__" + sym + "_end").str().c_str(), sec);
}

template <class ELFT>
void OutputELFWriter<ELFT>::updateScopeAtomValues(StringRef start,
                                                  StringRef end,
                                                  StringRef sec) {
  AtomLayout *s = _layout.findAbsoluteAtom(start);
  AtomLayout *e = _layout.findAbsoluteAtom(end);
  const OutputSection<ELFT> *section = _layout.findOutputSection(sec);
  if (s)
    s->_virtualAddr = section ? section->virtualAddr() : 0;
  if (e)
    e->_virtualAddr = section ? section->virtualAddr() + section->memSize() : 0;
}

template class OutputELFWriter<ELF32LE>;
template class OutputELFWriter<ELF32BE>;
template class OutputELFWriter<ELF64LE>;
template class OutputELFWriter<ELF64BE>;

} // namespace elf
} // namespace lld
