xref: /freebsd-src/contrib/llvm-project/lld/MachO/InputSection.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
15ffd83dbSDimitry Andric //===- InputSection.cpp ---------------------------------------------------===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric 
95ffd83dbSDimitry Andric #include "InputSection.h"
10*e8d8bef9SDimitry Andric #include "InputFiles.h"
115ffd83dbSDimitry Andric #include "OutputSegment.h"
125ffd83dbSDimitry Andric #include "Symbols.h"
135ffd83dbSDimitry Andric #include "Target.h"
14*e8d8bef9SDimitry Andric #include "Writer.h"
155ffd83dbSDimitry Andric #include "lld/Common/Memory.h"
165ffd83dbSDimitry Andric #include "llvm/Support/Endian.h"
175ffd83dbSDimitry Andric 
185ffd83dbSDimitry Andric using namespace llvm;
195ffd83dbSDimitry Andric using namespace llvm::MachO;
205ffd83dbSDimitry Andric using namespace llvm::support;
215ffd83dbSDimitry Andric using namespace lld;
225ffd83dbSDimitry Andric using namespace lld::macho;
235ffd83dbSDimitry Andric 
245ffd83dbSDimitry Andric std::vector<InputSection *> macho::inputSections;
255ffd83dbSDimitry Andric 
265ffd83dbSDimitry Andric uint64_t InputSection::getFileOffset() const {
275ffd83dbSDimitry Andric   return parent->fileOff + outSecFileOff;
285ffd83dbSDimitry Andric }
295ffd83dbSDimitry Andric 
30*e8d8bef9SDimitry Andric uint64_t InputSection::getFileSize() const {
31*e8d8bef9SDimitry Andric   return isZeroFill(flags) ? 0 : getSize();
32*e8d8bef9SDimitry Andric }
33*e8d8bef9SDimitry Andric 
345ffd83dbSDimitry Andric uint64_t InputSection::getVA() const { return parent->addr + outSecOff; }
355ffd83dbSDimitry Andric 
365ffd83dbSDimitry Andric void InputSection::writeTo(uint8_t *buf) {
375ffd83dbSDimitry Andric   if (getFileSize() == 0)
385ffd83dbSDimitry Andric     return;
395ffd83dbSDimitry Andric 
405ffd83dbSDimitry Andric   memcpy(buf, data.data(), data.size());
415ffd83dbSDimitry Andric 
425ffd83dbSDimitry Andric   for (Reloc &r : relocs) {
43*e8d8bef9SDimitry Andric     uint64_t referentVA = 0;
44*e8d8bef9SDimitry Andric     if (auto *referentSym = r.referent.dyn_cast<Symbol *>()) {
45*e8d8bef9SDimitry Andric       referentVA =
46*e8d8bef9SDimitry Andric           target->resolveSymbolVA(buf + r.offset, *referentSym, r.type);
475ffd83dbSDimitry Andric 
48*e8d8bef9SDimitry Andric       if (isThreadLocalVariables(flags)) {
49*e8d8bef9SDimitry Andric         // References from thread-local variable sections are treated as offsets
50*e8d8bef9SDimitry Andric         // relative to the start of the thread-local data memory area, which
51*e8d8bef9SDimitry Andric         // is initialized via copying all the TLV data sections (which are all
52*e8d8bef9SDimitry Andric         // contiguous).
53*e8d8bef9SDimitry Andric         if (isa<Defined>(referentSym))
54*e8d8bef9SDimitry Andric           referentVA -= firstTLVDataSection->addr;
555ffd83dbSDimitry Andric       }
56*e8d8bef9SDimitry Andric     } else if (auto *referentIsec = r.referent.dyn_cast<InputSection *>()) {
57*e8d8bef9SDimitry Andric       referentVA = referentIsec->getVA();
58*e8d8bef9SDimitry Andric     }
59*e8d8bef9SDimitry Andric 
60*e8d8bef9SDimitry Andric     uint64_t referentVal = referentVA + r.addend;
61*e8d8bef9SDimitry Andric     if (r.pcrel)
62*e8d8bef9SDimitry Andric       referentVal -= getVA() + r.offset;
63*e8d8bef9SDimitry Andric     target->relocateOne(buf + r.offset, r, referentVal);
64*e8d8bef9SDimitry Andric   }
65*e8d8bef9SDimitry Andric }
66*e8d8bef9SDimitry Andric 
67*e8d8bef9SDimitry Andric bool macho::isCodeSection(InputSection *isec) {
68*e8d8bef9SDimitry Andric   uint32_t type = isec->flags & MachO::SECTION_TYPE;
69*e8d8bef9SDimitry Andric   if (type != S_REGULAR && type != S_COALESCED)
70*e8d8bef9SDimitry Andric     return false;
71*e8d8bef9SDimitry Andric 
72*e8d8bef9SDimitry Andric   uint32_t attr = isec->flags & MachO::SECTION_ATTRIBUTES_USR;
73*e8d8bef9SDimitry Andric   if (attr == S_ATTR_PURE_INSTRUCTIONS)
74*e8d8bef9SDimitry Andric     return true;
75*e8d8bef9SDimitry Andric 
76*e8d8bef9SDimitry Andric   if (isec->segname == segment_names::text)
77*e8d8bef9SDimitry Andric     return StringSwitch<bool>(isec->name)
78*e8d8bef9SDimitry Andric         .Cases("__textcoal_nt", "__StaticInit", true)
79*e8d8bef9SDimitry Andric         .Default(false);
80*e8d8bef9SDimitry Andric 
81*e8d8bef9SDimitry Andric   return false;
82*e8d8bef9SDimitry Andric }
83*e8d8bef9SDimitry Andric 
84*e8d8bef9SDimitry Andric std::string lld::toString(const InputSection *isec) {
85*e8d8bef9SDimitry Andric   return (toString(isec->file) + ":(" + isec->name + ")").str();
865ffd83dbSDimitry Andric }
87