//===- 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 #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" #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(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(InputSection *isec) { … } static MergeSyntheticSection *createMergeSynthetic(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(LinkerScript *script) { … } static void sortByOrder(MutableArrayRef<InputSection *> in, llvm::function_ref<int(InputSectionBase *s)> order) { … } uint64_t elf::getHeaderSize() { … } void OutputSection::sort(llvm::function_ref<int(InputSectionBase *s)> order) { … } static void nopInstrFill(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() { … } static void writeInt(uint8_t *buf, uint64_t data, uint64_t size) { … } template <class ELFT> void OutputSection::writeTo(uint8_t *buf, parallel::TaskGroup &tg) { … } static void finalizeShtGroup(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() { … } void OutputSection::finalize() { … } // 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() { … } void OutputSection::checkDynRelAddends(const uint8_t *bufStart) { … } 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 *, llvm::parallel::TaskGroup &); template void OutputSection::writeTo<ELF32BE>(uint8_t *, llvm::parallel::TaskGroup &); template void OutputSection::writeTo<ELF64LE>(uint8_t *, llvm::parallel::TaskGroup &); template void OutputSection::writeTo<ELF64BE>(uint8_t *, llvm::parallel::TaskGroup &); template void OutputSection::maybeCompress<ELF32LE>(); template void OutputSection::maybeCompress<ELF32BE>(); template void OutputSection::maybeCompress<ELF64LE>(); template void OutputSection::maybeCompress<ELF64BE>();