//===- InputSection.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 "InputSection.h"
#include "ConcatOutputSection.h"
#include "Config.h"
#include "InputFiles.h"
#include "OutputSegment.h"
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
#include "UnwindInfoSection.h"
#include "Writer.h"

#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Memory.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/xxhash.h"

using namespace llvm;
using namespace llvm::MachO;
using namespace llvm::support;
using namespace lld;
using namespace lld::macho;

// Verify ConcatInputSection's size on 64-bit builds. The size of std::vector
// can differ based on STL debug levels (e.g. iterator debugging on MSVC's STL),
// so account for that.
static_assert(sizeof(void *) != 8 ||
                  sizeof(ConcatInputSection) == sizeof(std::vector<Reloc>) + 88,
              "Try to minimize ConcatInputSection's size, we create many "
              "instances of it");

std::vector<ConcatInputSection *> macho::inputSections;

uint64_t InputSection::getFileSize() const {
  return isZeroFill(getFlags()) ? 0 : getSize();
}

uint64_t InputSection::getVA(uint64_t off) const {
  return parent->addr + getOffset(off);
}

static uint64_t resolveSymbolVA(const Symbol *sym, uint8_t type) {
  const RelocAttrs &relocAttrs = target->getRelocAttrs(type);
  if (relocAttrs.hasAttr(RelocAttrBits::BRANCH))
    return sym->resolveBranchVA();
  if (relocAttrs.hasAttr(RelocAttrBits::GOT))
    return sym->resolveGotVA();
  if (relocAttrs.hasAttr(RelocAttrBits::TLV))
    return sym->resolveTlvVA();
  return sym->getVA();
}

const Defined *InputSection::getContainingSymbol(uint64_t off) const {
  auto *nextSym = llvm::upper_bound(
      symbols, off, [](uint64_t a, const Defined *b) { return a < b->value; });
  if (nextSym == symbols.begin())
    return nullptr;
  return *std::prev(nextSym);
}

std::string InputSection::getLocation(uint64_t off) const {
  // First, try to find a symbol that's near the offset. Use it as a reference
  // point.
  if (auto *sym = getContainingSymbol(off))
    return (toString(getFile()) + ":(symbol " + toString(*sym) + "+0x" +
            Twine::utohexstr(off - sym->value) + ")")
        .str();

  // If that fails, use the section itself as a reference point.
  for (const Subsection &subsec : section.subsections) {
    if (subsec.isec == this) {
      off += subsec.offset;
      break;
    }
  }

  return (toString(getFile()) + ":(" + getName() + "+0x" +
          Twine::utohexstr(off) + ")")
      .str();
}

std::string InputSection::getSourceLocation(uint64_t off) const {
  auto *obj = dyn_cast_or_null<ObjFile>(getFile());
  if (!obj)
    return {};

  DWARFCache *dwarf = obj->getDwarf();
  if (!dwarf)
    return std::string();

  for (const Subsection &subsec : section.subsections) {
    if (subsec.isec == this) {
      off += subsec.offset;
      break;
    }
  }

  auto createMsg = [&](StringRef path, unsigned line) {
    std::string filename = sys::path::filename(path).str();
    std::string lineStr = (":" + Twine(line)).str();
    if (filename == path)
      return filename + lineStr;
    return (filename + lineStr + " (" + path + lineStr + ")").str();
  };

  // First, look up a function for a given offset.
  if (std::optional<DILineInfo> li = dwarf->getDILineInfo(
          section.addr + off, object::SectionedAddress::UndefSection))
    return createMsg(li->FileName, li->Line);

  // If it failed, look up again as a variable.
  if (const Defined *sym = getContainingSymbol(off)) {
    // Symbols are generally prefixed with an underscore, which is not included
    // in the debug information.
    StringRef symName = sym->getName();
    if (!symName.empty() && symName[0] == '_')
      symName = symName.substr(1);

    if (std::optional<std::pair<std::string, unsigned>> fileLine =
            dwarf->getVariableLoc(symName))
      return createMsg(fileLine->first, fileLine->second);
  }

  // Try to get the source file's name from the DWARF information.
  if (obj->compileUnit)
    return obj->sourceFile();

  return {};
}

const Reloc *InputSection::getRelocAt(uint32_t off) const {
  auto it = llvm::find_if(
      relocs, [=](const macho::Reloc &r) { return r.offset == off; });
  if (it == relocs.end())
    return nullptr;
  return &*it;
}

void ConcatInputSection::foldIdentical(ConcatInputSection *copy) {
  align = std::max(align, copy->align);
  copy->live = false;
  copy->wasCoalesced = true;
  copy->replacement = this;
  for (auto &copySym : copy->symbols) {
    copySym->wasIdenticalCodeFolded = true;
    copySym->size = 0;
  }

  symbols.insert(symbols.end(), copy->symbols.begin(), copy->symbols.end());
  copy->symbols.clear();

  // Remove duplicate compact unwind info for symbols at the same address.
  if (symbols.empty())
    return;
  for (auto it = symbols.begin() + 1; it != symbols.end(); ++it) {
    assert((*it)->value == 0);
    (*it)->unwindEntry = nullptr;
  }
}

void ConcatInputSection::writeTo(uint8_t *buf) {
  assert(!shouldOmitFromOutput());

  if (getFileSize() == 0)
    return;

  memcpy(buf, data.data(), data.size());

  for (size_t i = 0; i < relocs.size(); i++) {
    const Reloc &r = relocs[i];
    uint8_t *loc = buf + r.offset;
    uint64_t referentVA = 0;

    const bool needsFixup = config->emitChainedFixups &&
                            target->hasAttr(r.type, RelocAttrBits::UNSIGNED);
    if (target->hasAttr(r.type, RelocAttrBits::SUBTRAHEND)) {
      const Symbol *fromSym = r.referent.get<Symbol *>();
      const Reloc &minuend = relocs[++i];
      uint64_t minuendVA;
      if (const Symbol *toSym = minuend.referent.dyn_cast<Symbol *>())
        minuendVA = toSym->getVA() + minuend.addend;
      else {
        auto *referentIsec = minuend.referent.get<InputSection *>();
        assert(!::shouldOmitFromOutput(referentIsec));
        minuendVA = referentIsec->getVA(minuend.addend);
      }
      referentVA = minuendVA - fromSym->getVA();
    } else if (auto *referentSym = r.referent.dyn_cast<Symbol *>()) {
      if (target->hasAttr(r.type, RelocAttrBits::LOAD) &&
          !referentSym->isInGot())
        target->relaxGotLoad(loc, r.type);
      // For dtrace symbols, do not handle them as normal undefined symbols
      if (referentSym->getName().starts_with("___dtrace_")) {
        // Change dtrace call site to pre-defined instructions
        target->handleDtraceReloc(referentSym, r, loc);
        continue;
      }
      referentVA = resolveSymbolVA(referentSym, r.type) + r.addend;

      if (isThreadLocalVariables(getFlags()) && isa<Defined>(referentSym)) {
        // References from thread-local variable sections are treated as offsets
        // relative to the start of the thread-local data memory area, which
        // is initialized via copying all the TLV data sections (which are all
        // contiguous).
        referentVA -= firstTLVDataSection->addr;
      } else if (needsFixup) {
        writeChainedFixup(loc, referentSym, r.addend);
        continue;
      }
    } else if (auto *referentIsec = r.referent.dyn_cast<InputSection *>()) {
      assert(!::shouldOmitFromOutput(referentIsec));
      referentVA = referentIsec->getVA(r.addend);

      if (needsFixup) {
        writeChainedRebase(loc, referentVA);
        continue;
      }
    }
    target->relocateOne(loc, r, referentVA, getVA() + r.offset);
  }
}

ConcatInputSection *macho::makeSyntheticInputSection(StringRef segName,
                                                     StringRef sectName,
                                                     uint32_t flags,
                                                     ArrayRef<uint8_t> data,
                                                     uint32_t align) {
  Section &section =
      *make<Section>(/*file=*/nullptr, segName, sectName, flags, /*addr=*/0);
  auto isec = make<ConcatInputSection>(section, data, align);
  section.subsections.push_back({0, isec});
  return isec;
}

void CStringInputSection::splitIntoPieces() {
  size_t off = 0;
  StringRef s = toStringRef(data);
  while (!s.empty()) {
    size_t end = s.find(0);
    if (end == StringRef::npos)
      fatal(getLocation(off) + ": string is not null terminated");
    uint32_t hash = deduplicateLiterals ? xxh3_64bits(s.take_front(end)) : 0;
    pieces.emplace_back(off, hash);
    size_t size = end + 1; // include null terminator
    s = s.substr(size);
    off += size;
  }
}

StringPiece &CStringInputSection::getStringPiece(uint64_t off) {
  if (off >= data.size())
    fatal(toString(this) + ": offset is outside the section");

  auto it =
      partition_point(pieces, [=](StringPiece p) { return p.inSecOff <= off; });
  return it[-1];
}

const StringPiece &CStringInputSection::getStringPiece(uint64_t off) const {
  return const_cast<CStringInputSection *>(this)->getStringPiece(off);
}

size_t CStringInputSection::getStringPieceIndex(uint64_t off) const {
  if (off >= data.size())
    fatal(toString(this) + ": offset is outside the section");

  auto it =
      partition_point(pieces, [=](StringPiece p) { return p.inSecOff <= off; });
  return std::distance(pieces.begin(), it) - 1;
}

uint64_t CStringInputSection::getOffset(uint64_t off) const {
  const StringPiece &piece = getStringPiece(off);
  uint64_t addend = off - piece.inSecOff;
  return piece.outSecOff + addend;
}

WordLiteralInputSection::WordLiteralInputSection(const Section &section,
                                                 ArrayRef<uint8_t> data,
                                                 uint32_t align)
    : InputSection(WordLiteralKind, section, data, align) {
  switch (sectionType(getFlags())) {
  case S_4BYTE_LITERALS:
    power2LiteralSize = 2;
    break;
  case S_8BYTE_LITERALS:
    power2LiteralSize = 3;
    break;
  case S_16BYTE_LITERALS:
    power2LiteralSize = 4;
    break;
  default:
    llvm_unreachable("invalid literal section type");
  }

  live.resize(data.size() >> power2LiteralSize, !config->deadStrip);
}

uint64_t WordLiteralInputSection::getOffset(uint64_t off) const {
  auto *osec = cast<WordLiteralSection>(parent);
  const uintptr_t buf = reinterpret_cast<uintptr_t>(data.data());
  switch (sectionType(getFlags())) {
  case S_4BYTE_LITERALS:
    return osec->getLiteral4Offset(buf + (off & ~3LLU)) | (off & 3);
  case S_8BYTE_LITERALS:
    return osec->getLiteral8Offset(buf + (off & ~7LLU)) | (off & 7);
  case S_16BYTE_LITERALS:
    return osec->getLiteral16Offset(buf + (off & ~15LLU)) | (off & 15);
  default:
    llvm_unreachable("invalid literal section type");
  }
}

bool macho::isCodeSection(const InputSection *isec) {
  uint32_t type = sectionType(isec->getFlags());
  if (type != S_REGULAR && type != S_COALESCED)
    return false;

  uint32_t attr = isec->getFlags() & SECTION_ATTRIBUTES_USR;
  if (attr == S_ATTR_PURE_INSTRUCTIONS)
    return true;

  if (isec->getSegName() == segment_names::text)
    return StringSwitch<bool>(isec->getName())
        .Cases(section_names::textCoalNt, section_names::staticInit, true)
        .Default(false);

  return false;
}

bool macho::isCfStringSection(const InputSection *isec) {
  return isec->getName() == section_names::cfString &&
         isec->getSegName() == segment_names::data;
}

bool macho::isClassRefsSection(const InputSection *isec) {
  return isec->getName() == section_names::objcClassRefs &&
         isec->getSegName() == segment_names::data;
}

bool macho::isSelRefsSection(const InputSection *isec) {
  return isec->getName() == section_names::objcSelrefs &&
         isec->getSegName() == segment_names::data;
}

bool macho::isEhFrameSection(const InputSection *isec) {
  return isec->getName() == section_names::ehFrame &&
         isec->getSegName() == segment_names::text;
}

bool macho::isGccExceptTabSection(const InputSection *isec) {
  return isec->getName() == section_names::gccExceptTab &&
         isec->getSegName() == segment_names::text;
}

std::string lld::toString(const InputSection *isec) {
  return (toString(isec->getFile()) + ":(" + isec->getName() + ")").str();
}
