//===- OutputSections.cpp -------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "OutputSections.h"
#include "Config.h"
#include "LinkerScript.h"
#include "SymbolTable.h"
#include "SyntheticSections.h"
#include "Target.h"
#include "lld/Common/Memory.h"
#include "lld/Common/Strings.h"
#include "lld/Common/Threads.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/SHA1.h"

using namespace llvm;
using namespace llvm::dwarf;
using namespace llvm::object;
using namespace llvm::support::endian;
using namespace llvm::ELF;

using namespace lld;
using namespace lld::elf;

uint8_t *Out::BufferStart;
uint8_t Out::First;
PhdrEntry *Out::TlsPhdr;
OutputSection *Out::ElfHeader;
OutputSection *Out::ProgramHeaders;
OutputSection *Out::PreinitArray;
OutputSection *Out::InitArray;
OutputSection *Out::FiniArray;

std::vector<OutputSection *> elf::OutputSections;

uint32_t OutputSection::getPhdrFlags() const {
  uint32_t Ret = 0;
  if (Config->EMachine != EM_ARM || !(Flags & SHF_ARM_PURECODE))
    Ret |= PF_R;
  if (Flags & SHF_WRITE)
    Ret |= PF_W;
  if (Flags & SHF_EXECINSTR)
    Ret |= PF_X;
  return Ret;
}

template <class ELFT>
void OutputSection::writeHeaderTo(typename ELFT::Shdr *Shdr) {
  Shdr->sh_entsize = Entsize;
  Shdr->sh_addralign = Alignment;
  Shdr->sh_type = Type;
  Shdr->sh_offset = Offset;
  Shdr->sh_flags = Flags;
  Shdr->sh_info = Info;
  Shdr->sh_link = Link;
  Shdr->sh_addr = Addr;
  Shdr->sh_size = Size;
  Shdr->sh_name = ShName;
}

OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags)
    : BaseCommand(OutputSectionKind),
      SectionBase(Output, Name, Flags, /*Entsize*/ 0, /*Alignment*/ 1, Type,
                  /*Info*/ 0, /*Link*/ 0) {}

// We allow sections of types listed below to merged into a
// single progbits section. This is typically done by linker
// scripts. Merging nobits and progbits will force disk space
// to be allocated for nobits sections. Other ones don't require
// any special treatment on top of progbits, so there doesn't
// seem to be a harm in merging them.
static bool canMergeToProgbits(unsigned Type) {
  return Type == SHT_NOBITS || Type == SHT_PROGBITS || Type == SHT_INIT_ARRAY ||
         Type == SHT_PREINIT_ARRAY || Type == SHT_FINI_ARRAY ||
         Type == SHT_NOTE;
}

void OutputSection::addSection(InputSection *IS) {
  if (!HasInputSections) {
    // If IS is the first section to be added to this section,
    // initialize Partition, Type, Entsize and flags from IS.
    HasInputSections = true;
    Partition = IS->Partition;
    Type = IS->Type;
    Entsize = IS->Entsize;
    Flags = IS->Flags;
  } else {
    // Otherwise, check if new type or flags are compatible with existing ones.
    unsigned Mask = SHF_TLS | SHF_LINK_ORDER;
    if ((Flags & Mask) != (IS->Flags & Mask))
      error("incompatible section flags for " + Name + "\n>>> " + toString(IS) +
            ": 0x" + utohexstr(IS->Flags) + "\n>>> output section " + Name +
            ": 0x" + utohexstr(Flags));

    if (Type != IS->Type) {
      if (!canMergeToProgbits(Type) || !canMergeToProgbits(IS->Type))
        error("section type mismatch for " + IS->Name + "\n>>> " +
              toString(IS) + ": " +
              getELFSectionTypeName(Config->EMachine, IS->Type) +
              "\n>>> output section " + Name + ": " +
              getELFSectionTypeName(Config->EMachine, Type));
      Type = SHT_PROGBITS;
    }
  }

  IS->Parent = this;
  uint64_t AndMask =
      Config->EMachine == EM_ARM ? (uint64_t)SHF_ARM_PURECODE : 0;
  uint64_t OrMask = ~AndMask;
  uint64_t AndFlags = (Flags & IS->Flags) & AndMask;
  uint64_t OrFlags = (Flags | IS->Flags) & OrMask;
  Flags = AndFlags | OrFlags;

  Alignment = std::max(Alignment, IS->Alignment);

  // If this section contains a table of fixed-size entries, sh_entsize
  // holds the element size. If it contains elements of different size we
  // set sh_entsize to 0.
  if (Entsize != IS->Entsize)
    Entsize = 0;

  if (!IS->Assigned) {
    IS->Assigned = true;
    if (SectionCommands.empty() ||
        !isa<InputSectionDescription>(SectionCommands.back()))
      SectionCommands.push_back(make<InputSectionDescription>(""));
    auto *ISD = cast<InputSectionDescription>(SectionCommands.back());
    ISD->Sections.push_back(IS);
  }
}

static void sortByOrder(MutableArrayRef<InputSection *> In,
                        llvm::function_ref<int(InputSectionBase *S)> Order) {
  std::vector<std::pair<int, InputSection *>> V;
  for (InputSection *S : In)
    V.push_back({Order(S), S});
  llvm::stable_sort(V, less_first());

  for (size_t I = 0; I < V.size(); ++I)
    In[I] = V[I].second;
}

uint64_t elf::getHeaderSize() {
  if (Config->OFormatBinary)
    return 0;
  return Out::ElfHeader->Size + Out::ProgramHeaders->Size;
}

bool OutputSection::classof(const BaseCommand *C) {
  return C->Kind == OutputSectionKind;
}

void OutputSection::sort(llvm::function_ref<int(InputSectionBase *S)> Order) {
  assert(isLive());
  for (BaseCommand *B : SectionCommands)
    if (auto *ISD = dyn_cast<InputSectionDescription>(B))
      sortByOrder(ISD->Sections, Order);
}

// Fill [Buf, Buf + Size) with Filler.
// This is used for linker script "=fillexp" command.
static void fill(uint8_t *Buf, size_t Size,
                 const std::array<uint8_t, 4> &Filler) {
  size_t I = 0;
  for (; I + 4 < Size; I += 4)
    memcpy(Buf + I, Filler.data(), 4);
  memcpy(Buf + I, Filler.data(), Size - I);
}

// Compress section contents if this section contains debug info.
template <class ELFT> void OutputSection::maybeCompress() {
  using Elf_Chdr = typename ELFT::Chdr;

  // Compress only DWARF debug sections.
  if (!Config->CompressDebugSections || (Flags & SHF_ALLOC) ||
      !Name.startswith(".debug_"))
    return;

  // Create a section header.
  ZDebugHeader.resize(sizeof(Elf_Chdr));
  auto *Hdr = reinterpret_cast<Elf_Chdr *>(ZDebugHeader.data());
  Hdr->ch_type = ELFCOMPRESS_ZLIB;
  Hdr->ch_size = Size;
  Hdr->ch_addralign = Alignment;

  // Write section contents to a temporary buffer and compress it.
  std::vector<uint8_t> Buf(Size);
  writeTo<ELFT>(Buf.data());
  if (Error E = zlib::compress(toStringRef(Buf), CompressedData))
    fatal("compress failed: " + llvm::toString(std::move(E)));

  // Update section headers.
  Size = sizeof(Elf_Chdr) + CompressedData.size();
  Flags |= SHF_COMPRESSED;
}

static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) {
  if (Size == 1)
    *Buf = Data;
  else if (Size == 2)
    write16(Buf, Data);
  else if (Size == 4)
    write32(Buf, Data);
  else if (Size == 8)
    write64(Buf, Data);
  else
    llvm_unreachable("unsupported Size argument");
}

template <class ELFT> void OutputSection::writeTo(uint8_t *Buf) {
  if (Type == SHT_NOBITS)
    return;

  // If -compress-debug-section is specified and if this is a debug seciton,
  // we've already compressed section contents. If that's the case,
  // just write it down.
  if (!CompressedData.empty()) {
    memcpy(Buf, ZDebugHeader.data(), ZDebugHeader.size());
    memcpy(Buf + ZDebugHeader.size(), CompressedData.data(),
           CompressedData.size());
    return;
  }

  // Write leading padding.
  std::vector<InputSection *> Sections = getInputSections(this);
  std::array<uint8_t, 4> Filler = getFiller();
  bool NonZeroFiller = read32(Filler.data()) != 0;
  if (NonZeroFiller)
    fill(Buf, Sections.empty() ? Size : Sections[0]->OutSecOff, Filler);

  parallelForEachN(0, Sections.size(), [&](size_t I) {
    InputSection *IS = Sections[I];
    IS->writeTo<ELFT>(Buf);

    // Fill gaps between sections.
    if (NonZeroFiller) {
      uint8_t *Start = Buf + IS->OutSecOff + IS->getSize();
      uint8_t *End;
      if (I + 1 == Sections.size())
        End = Buf + Size;
      else
        End = Buf + Sections[I + 1]->OutSecOff;
      fill(Start, End - Start, Filler);
    }
  });

  // Linker scripts may have BYTE()-family commands with which you
  // can write arbitrary bytes to the output. Process them if any.
  for (BaseCommand *Base : SectionCommands)
    if (auto *Data = dyn_cast<ByteCommand>(Base))
      writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size);
}

static void finalizeShtGroup(OutputSection *OS,
                             InputSection *Section) {
  assert(Config->Relocatable);

  // sh_link field for SHT_GROUP sections should contain the section index of
  // the symbol table.
  OS->Link = In.SymTab->getParent()->SectionIndex;

  // sh_info then contain index of an entry in symbol table section which
  // provides signature of the section group.
  ArrayRef<Symbol *> Symbols = Section->File->getSymbols();
  OS->Info = In.SymTab->getSymbolIndex(Symbols[Section->Info]);
}

void OutputSection::finalize() {
  std::vector<InputSection *> V = getInputSections(this);
  InputSection *First = V.empty() ? nullptr : V[0];

  if (Flags & SHF_LINK_ORDER) {
    // We must preserve the link order dependency of sections with the
    // SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We
    // need to translate the InputSection sh_link to the OutputSection sh_link,
    // all InputSections in the OutputSection have the same dependency.
    if (auto *EX = dyn_cast<ARMExidxSyntheticSection>(First))
      Link = EX->getLinkOrderDep()->getParent()->SectionIndex;
    else if (auto *D = First->getLinkOrderDep())
      Link = D->getParent()->SectionIndex;
  }

  if (Type == SHT_GROUP) {
    finalizeShtGroup(this, First);
    return;
  }

  if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL))
    return;

  if (isa<SyntheticSection>(First))
    return;

  Link = In.SymTab->getParent()->SectionIndex;
  // sh_info for SHT_REL[A] sections should contain the section header index of
  // the section to which the relocation applies.
  InputSectionBase *S = First->getRelocatedSection();
  Info = S->getOutputSection()->SectionIndex;
  Flags |= SHF_INFO_LINK;
}

// Returns true if S matches /Filename.?\.o$/.
static bool isCrtBeginEnd(StringRef S, StringRef Filename) {
  if (!S.endswith(".o"))
    return false;
  S = S.drop_back(2);
  if (S.endswith(Filename))
    return true;
  return !S.empty() && S.drop_back().endswith(Filename);
}

static bool isCrtbegin(StringRef S) { return isCrtBeginEnd(S, "crtbegin"); }
static bool isCrtend(StringRef S) { return isCrtBeginEnd(S, "crtend"); }

// .ctors and .dtors are sorted by this priority from highest to lowest.
//
//  1. The section was contained in crtbegin (crtbegin contains
//     some sentinel value in its .ctors and .dtors so that the runtime
//     can find the beginning of the sections.)
//
//  2. The section has an optional priority value in the form of ".ctors.N"
//     or ".dtors.N" where N is a number. Unlike .{init,fini}_array,
//     they are compared as string rather than number.
//
//  3. The section is just ".ctors" or ".dtors".
//
//  4. The section was contained in crtend, which contains an end marker.
//
// In an ideal world, we don't need this function because .init_array and
// .ctors are duplicate features (and .init_array is newer.) However, there
// are too many real-world use cases of .ctors, so we had no choice to
// support that with this rather ad-hoc semantics.
static bool compCtors(const InputSection *A, const InputSection *B) {
  bool BeginA = isCrtbegin(A->File->getName());
  bool BeginB = isCrtbegin(B->File->getName());
  if (BeginA != BeginB)
    return BeginA;
  bool EndA = isCrtend(A->File->getName());
  bool EndB = isCrtend(B->File->getName());
  if (EndA != EndB)
    return EndB;
  StringRef X = A->Name;
  StringRef Y = B->Name;
  assert(X.startswith(".ctors") || X.startswith(".dtors"));
  assert(Y.startswith(".ctors") || Y.startswith(".dtors"));
  X = X.substr(6);
  Y = Y.substr(6);
  return X < Y;
}

// Sorts input sections by the special rules for .ctors and .dtors.
// Unfortunately, the rules are different from the one for .{init,fini}_array.
// Read the comment above.
void OutputSection::sortCtorsDtors() {
  assert(SectionCommands.size() == 1);
  auto *ISD = cast<InputSectionDescription>(SectionCommands[0]);
  llvm::stable_sort(ISD->Sections, compCtors);
}

// If an input string is in the form of "foo.N" where N is a number,
// return N. Otherwise, returns 65536, which is one greater than the
// lowest priority.
int elf::getPriority(StringRef S) {
  size_t Pos = S.rfind('.');
  if (Pos == StringRef::npos)
    return 65536;
  int V;
  if (!to_integer(S.substr(Pos + 1), V, 10))
    return 65536;
  return V;
}

std::vector<InputSection *> elf::getInputSections(OutputSection *OS) {
  std::vector<InputSection *> Ret;
  for (BaseCommand *Base : OS->SectionCommands)
    if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
      Ret.insert(Ret.end(), ISD->Sections.begin(), ISD->Sections.end());
  return Ret;
}

// Sorts input sections by section name suffixes, so that .foo.N comes
// before .foo.M if N < M. Used to sort .{init,fini}_array.N sections.
// We want to keep the original order if the priorities are the same
// because the compiler keeps the original initialization order in a
// translation unit and we need to respect that.
// For more detail, read the section of the GCC's manual about init_priority.
void OutputSection::sortInitFini() {
  // Sort sections by priority.
  sort([](InputSectionBase *S) { return getPriority(S->Name); });
}

std::array<uint8_t, 4> OutputSection::getFiller() {
  if (Filler)
    return *Filler;
  if (Flags & SHF_EXECINSTR)
    return Target->TrapInstr;
  return {0, 0, 0, 0};
}

template void OutputSection::writeHeaderTo<ELF32LE>(ELF32LE::Shdr *Shdr);
template void OutputSection::writeHeaderTo<ELF32BE>(ELF32BE::Shdr *Shdr);
template void OutputSection::writeHeaderTo<ELF64LE>(ELF64LE::Shdr *Shdr);
template void OutputSection::writeHeaderTo<ELF64BE>(ELF64BE::Shdr *Shdr);

template void OutputSection::writeTo<ELF32LE>(uint8_t *Buf);
template void OutputSection::writeTo<ELF32BE>(uint8_t *Buf);
template void OutputSection::writeTo<ELF64LE>(uint8_t *Buf);
template void OutputSection::writeTo<ELF64BE>(uint8_t *Buf);

template void OutputSection::maybeCompress<ELF32LE>();
template void OutputSection::maybeCompress<ELF32BE>();
template void OutputSection::maybeCompress<ELF64LE>();
template void OutputSection::maybeCompress<ELF64BE>();
