llvm/lld/ELF/OutputSections.cpp

//===- 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 "InputFiles.h"
#include "LinkerScript.h"
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
#include "lld/Common/Arrays.h"
#include "lld/Common/Memory.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Config/llvm-config.h" // LLVM_ENABLE_ZLIB, LLVM_ENABLE_ZSTD
#include "llvm/Support/Compression.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TimeProfiler.h"
#undef in
#if LLVM_ENABLE_ZLIB
// Avoid introducing max as a macro from Windows headers.
#define NOMINMAX
#include <zlib.h>
#endif
#if LLVM_ENABLE_ZSTD
#include <zstd.h>
#endif

usingnamespacellvm;
usingnamespacellvm::dwarf;
usingnamespacellvm::object;
usingnamespacellvm::support::endian;
usingnamespacellvm::ELF;
usingnamespacelld;
usingnamespacelld::elf;

uint32_t OutputSection::getPhdrFlags() const {}

template <class ELFT>
void OutputSection::writeHeaderTo(typename ELFT::Shdr *shdr) {}

OutputSection::OutputSection(StringRef name, uint32_t type, uint64_t flags)
    :{}

// 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.
//
// NOTE: clang since rL252300 emits SHT_X86_64_UNWIND .eh_frame sections. Allow
// them to be merged into SHT_PROGBITS .eh_frame (GNU as .cfi_*).
static bool canMergeToProgbits(Ctx &ctx, unsigned type) {}

// Record that isec will be placed in the OutputSection. isec does not become
// permanent until finalizeInputSections() is called. The function should not be
// used after finalizeInputSections() is called. If you need to add an
// InputSection post finalizeInputSections(), then you must do the following:
//
// 1. Find or create an InputSectionDescription to hold InputSection.
// 2. Add the InputSection to the InputSectionDescription::sections.
// 3. Call commitSection(isec).
void OutputSection::recordSection(InputSectionBase *isec) {}

// Update fields (type, flags, alignment, etc) according to the InputSection
// isec. Also check whether the InputSection flags and type are consistent with
// other InputSections.
void OutputSection::commitSection(Ctx &ctx, InputSection *isec) {}

static MergeSyntheticSection *createMergeSynthetic(Ctx &ctx, StringRef name,
                                                   uint32_t type,
                                                   uint64_t flags,
                                                   uint32_t addralign) {}

// This function scans over the InputSectionBase list sectionBases to create
// InputSectionDescription::sections.
//
// It removes MergeInputSections from the input section array and adds
// new synthetic sections at the location of the first input section
// that it replaces. It then finalizes each synthetic section in order
// to compute an output offset for each piece of each input section.
void OutputSection::finalizeInputSections(Ctx &ctx) {}

static void sortByOrder(MutableArrayRef<InputSection *> in,
                        llvm::function_ref<int(InputSectionBase *s)> order) {}

uint64_t elf::getHeaderSize(Ctx &ctx) {}

void OutputSection::sort(llvm::function_ref<int(InputSectionBase *s)> order) {}

static void nopInstrFill(Ctx &ctx, uint8_t *buf, size_t size) {}

// 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) {}

#if LLVM_ENABLE_ZLIB
static SmallVector<uint8_t, 0> deflateShard(ArrayRef<uint8_t> in, int level,
                                            int flush) {}
#endif

// Compress certain non-SHF_ALLOC sections:
//
// * (if --compress-debug-sections is specified) non-empty .debug_* sections
// * (if --compress-sections is specified) matched sections
template <class ELFT> void OutputSection::maybeCompress(Ctx &ctx) {}

static void writeInt(uint8_t *buf, uint64_t data, uint64_t size) {}

template <class ELFT>
void OutputSection::writeTo(Ctx &ctx, uint8_t *buf, parallel::TaskGroup &tg) {}

static void finalizeShtGroup(Ctx &ctx, OutputSection *os,
                             InputSection *section) {}

template <class uint>
LLVM_ATTRIBUTE_ALWAYS_INLINE static void
encodeOneCrel(raw_svector_ostream &os, Elf_Crel<sizeof(uint) == 8> &out,
              uint offset, const Symbol &sym, uint32_t type, uint addend) {}

template <class ELFT>
static size_t relToCrel(raw_svector_ostream &os, Elf_Crel<ELFT::Is64Bits> &out,
                        InputSection *relSec, InputSectionBase *sec) {}

// Compute the content of a non-alloc CREL section due to -r or --emit-relocs.
// Input CREL sections are decoded while REL[A] need to be converted.
template <bool is64> void OutputSection::finalizeNonAllocCrel(Ctx &ctx) {}

void OutputSection::finalize(Ctx &ctx) {}

// Returns true if S is in one of the many forms the compiler driver may pass
// crtbegin files.
//
// Gcc uses any of crtbegin[<empty>|S|T].o.
// Clang uses Gcc's plus clang_rt.crtbegin[-<arch>|<empty>].o.

static bool isCrt(StringRef s, StringRef beginEnd) {}

// .ctors and .dtors are sorted by this order:
//
// 1. .ctors/.dtors in crtbegin (which contains a sentinel value -1).
// 2. The section is named ".ctors" or ".dtors" (priority: 65536).
// 3. The section has an optional priority value in the form of ".ctors.N" or
//    ".dtors.N" where N is a number in the form of %05u (priority: 65535-N).
// 4. .ctors/.dtors in crtend (which contains a sentinel value 0).
//
// For 2 and 3, the sections are sorted by priority from high to low, e.g.
// .ctors (65536), .ctors.00100 (65436), .ctors.00200 (65336).  In GNU ld's
// internal linker scripts, the sorting is by string comparison which can
// achieve the same goal given the optional priority values are of the same
// length.
//
// 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) {}

// 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() {}

// If an input string is in the form of "foo.N" where N is a number, return N
// (65535-N if .ctors.N or .dtors.N). Otherwise, returns 65536, which is one
// greater than the lowest priority.
int elf::getPriority(StringRef s) {}

InputSection *elf::getFirstInputSection(const OutputSection *os) {}

ArrayRef<InputSection *>
elf::getInputSections(const OutputSection &os,
                      SmallVector<InputSection *, 0> &storage) {}

// 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() {}

std::array<uint8_t, 4> OutputSection::getFiller(Ctx &ctx) {}

void OutputSection::checkDynRelAddends(Ctx &ctx) {}

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>(Ctx &, uint8_t *,
                                              llvm::parallel::TaskGroup &);
template void OutputSection::writeTo<ELF32BE>(Ctx &, uint8_t *,
                                              llvm::parallel::TaskGroup &);
template void OutputSection::writeTo<ELF64LE>(Ctx &, uint8_t *,
                                              llvm::parallel::TaskGroup &);
template void OutputSection::writeTo<ELF64BE>(Ctx &, uint8_t *,
                                              llvm::parallel::TaskGroup &);

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