xref: /openbsd-src/gnu/llvm/lld/MachO/InputSection.cpp (revision dfe94b169149f14cc1aee2cf6dad58a8d9a1860c)
1bb684c34Spatrick //===- InputSection.cpp ---------------------------------------------------===//
2bb684c34Spatrick //
3bb684c34Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bb684c34Spatrick // See https://llvm.org/LICENSE.txt for license information.
5bb684c34Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bb684c34Spatrick //
7bb684c34Spatrick //===----------------------------------------------------------------------===//
8bb684c34Spatrick 
9bb684c34Spatrick #include "InputSection.h"
101cf9926bSpatrick #include "ConcatOutputSection.h"
111cf9926bSpatrick #include "Config.h"
121cf9926bSpatrick #include "InputFiles.h"
13bb684c34Spatrick #include "OutputSegment.h"
14bb684c34Spatrick #include "Symbols.h"
151cf9926bSpatrick #include "SyntheticSections.h"
16bb684c34Spatrick #include "Target.h"
171cf9926bSpatrick #include "UnwindInfoSection.h"
181cf9926bSpatrick #include "Writer.h"
19*dfe94b16Srobert 
20*dfe94b16Srobert #include "lld/Common/ErrorHandler.h"
21bb684c34Spatrick #include "lld/Common/Memory.h"
22bb684c34Spatrick #include "llvm/Support/Endian.h"
231cf9926bSpatrick #include "llvm/Support/xxhash.h"
24bb684c34Spatrick 
25bb684c34Spatrick using namespace llvm;
26bb684c34Spatrick using namespace llvm::MachO;
27bb684c34Spatrick using namespace llvm::support;
28bb684c34Spatrick using namespace lld;
29bb684c34Spatrick using namespace lld::macho;
30bb684c34Spatrick 
31*dfe94b16Srobert // Verify ConcatInputSection's size on 64-bit builds. The size of std::vector
32*dfe94b16Srobert // can differ based on STL debug levels (e.g. iterator debugging on MSVC's STL),
33*dfe94b16Srobert // so account for that.
34*dfe94b16Srobert static_assert(sizeof(void *) != 8 ||
35*dfe94b16Srobert                   sizeof(ConcatInputSection) == sizeof(std::vector<Reloc>) + 88,
36*dfe94b16Srobert               "Try to minimize ConcatInputSection's size, we create many "
37*dfe94b16Srobert               "instances of it");
38*dfe94b16Srobert 
391cf9926bSpatrick std::vector<ConcatInputSection *> macho::inputSections;
40bb684c34Spatrick 
getFileSize() const411cf9926bSpatrick uint64_t InputSection::getFileSize() const {
421cf9926bSpatrick   return isZeroFill(getFlags()) ? 0 : getSize();
43bb684c34Spatrick }
44bb684c34Spatrick 
getVA(uint64_t off) const451cf9926bSpatrick uint64_t InputSection::getVA(uint64_t off) const {
461cf9926bSpatrick   return parent->addr + getOffset(off);
471cf9926bSpatrick }
48bb684c34Spatrick 
resolveSymbolVA(const Symbol * sym,uint8_t type)491cf9926bSpatrick static uint64_t resolveSymbolVA(const Symbol *sym, uint8_t type) {
501cf9926bSpatrick   const RelocAttrs &relocAttrs = target->getRelocAttrs(type);
511cf9926bSpatrick   if (relocAttrs.hasAttr(RelocAttrBits::BRANCH))
521cf9926bSpatrick     return sym->resolveBranchVA();
531cf9926bSpatrick   if (relocAttrs.hasAttr(RelocAttrBits::GOT))
541cf9926bSpatrick     return sym->resolveGotVA();
551cf9926bSpatrick   if (relocAttrs.hasAttr(RelocAttrBits::TLV))
561cf9926bSpatrick     return sym->resolveTlvVA();
571cf9926bSpatrick   return sym->getVA();
581cf9926bSpatrick }
591cf9926bSpatrick 
getContainingSymbol(uint64_t off) const60*dfe94b16Srobert const Defined *InputSection::getContainingSymbol(uint64_t off) const {
61*dfe94b16Srobert   auto *nextSym = llvm::upper_bound(
62*dfe94b16Srobert       symbols, off, [](uint64_t a, const Defined *b) { return a < b->value; });
63*dfe94b16Srobert   if (nextSym == symbols.begin())
64*dfe94b16Srobert     return nullptr;
65*dfe94b16Srobert   return *std::prev(nextSym);
66*dfe94b16Srobert }
67*dfe94b16Srobert 
getLocation(uint64_t off) const68*dfe94b16Srobert std::string InputSection::getLocation(uint64_t off) const {
69*dfe94b16Srobert   // First, try to find a symbol that's near the offset. Use it as a reference
70*dfe94b16Srobert   // point.
71*dfe94b16Srobert   if (auto *sym = getContainingSymbol(off))
72*dfe94b16Srobert     return (toString(getFile()) + ":(symbol " + toString(*sym) + "+0x" +
73*dfe94b16Srobert             Twine::utohexstr(off - sym->value) + ")")
74*dfe94b16Srobert         .str();
75*dfe94b16Srobert 
76*dfe94b16Srobert   // If that fails, use the section itself as a reference point.
77*dfe94b16Srobert   for (const Subsection &subsec : section.subsections) {
78*dfe94b16Srobert     if (subsec.isec == this) {
79*dfe94b16Srobert       off += subsec.offset;
80*dfe94b16Srobert       break;
811cf9926bSpatrick     }
821cf9926bSpatrick   }
831cf9926bSpatrick 
84*dfe94b16Srobert   return (toString(getFile()) + ":(" + getName() + "+0x" +
85*dfe94b16Srobert           Twine::utohexstr(off) + ")")
86*dfe94b16Srobert       .str();
87*dfe94b16Srobert }
88*dfe94b16Srobert 
getSourceLocation(uint64_t off) const89*dfe94b16Srobert std::string InputSection::getSourceLocation(uint64_t off) const {
90*dfe94b16Srobert   auto *obj = dyn_cast_or_null<ObjFile>(getFile());
91*dfe94b16Srobert   if (!obj)
92*dfe94b16Srobert     return {};
93*dfe94b16Srobert 
94*dfe94b16Srobert   DWARFCache *dwarf = obj->getDwarf();
95*dfe94b16Srobert   if (!dwarf)
96*dfe94b16Srobert     return std::string();
97*dfe94b16Srobert 
98*dfe94b16Srobert   for (const Subsection &subsec : section.subsections) {
99*dfe94b16Srobert     if (subsec.isec == this) {
100*dfe94b16Srobert       off += subsec.offset;
101*dfe94b16Srobert       break;
102*dfe94b16Srobert     }
103*dfe94b16Srobert   }
104*dfe94b16Srobert 
105*dfe94b16Srobert   auto createMsg = [&](StringRef path, unsigned line) {
106*dfe94b16Srobert     std::string filename = sys::path::filename(path).str();
107*dfe94b16Srobert     std::string lineStr = (":" + Twine(line)).str();
108*dfe94b16Srobert     if (filename == path)
109*dfe94b16Srobert       return filename + lineStr;
110*dfe94b16Srobert     return (filename + lineStr + " (" + path + lineStr + ")").str();
111*dfe94b16Srobert   };
112*dfe94b16Srobert 
113*dfe94b16Srobert   // First, look up a function for a given offset.
114*dfe94b16Srobert   if (std::optional<DILineInfo> li = dwarf->getDILineInfo(
115*dfe94b16Srobert           section.addr + off, object::SectionedAddress::UndefSection))
116*dfe94b16Srobert     return createMsg(li->FileName, li->Line);
117*dfe94b16Srobert 
118*dfe94b16Srobert   // If it failed, look up again as a variable.
119*dfe94b16Srobert   if (const Defined *sym = getContainingSymbol(off)) {
120*dfe94b16Srobert     // Symbols are generally prefixed with an underscore, which is not included
121*dfe94b16Srobert     // in the debug information.
122*dfe94b16Srobert     StringRef symName = sym->getName();
123*dfe94b16Srobert     if (!symName.empty() && symName[0] == '_')
124*dfe94b16Srobert       symName = symName.substr(1);
125*dfe94b16Srobert 
126*dfe94b16Srobert     if (std::optional<std::pair<std::string, unsigned>> fileLine =
127*dfe94b16Srobert             dwarf->getVariableLoc(symName))
128*dfe94b16Srobert       return createMsg(fileLine->first, fileLine->second);
129*dfe94b16Srobert   }
130*dfe94b16Srobert 
131*dfe94b16Srobert   // Try to get the source file's name from the DWARF information.
132*dfe94b16Srobert   if (obj->compileUnit)
133*dfe94b16Srobert     return obj->sourceFile();
134*dfe94b16Srobert 
135*dfe94b16Srobert   return {};
1361cf9926bSpatrick }
1371cf9926bSpatrick 
foldIdentical(ConcatInputSection * copy)1381cf9926bSpatrick void ConcatInputSection::foldIdentical(ConcatInputSection *copy) {
1391cf9926bSpatrick   align = std::max(align, copy->align);
1401cf9926bSpatrick   copy->live = false;
1411cf9926bSpatrick   copy->wasCoalesced = true;
1421cf9926bSpatrick   copy->replacement = this;
143*dfe94b16Srobert   for (auto &copySym : copy->symbols) {
144*dfe94b16Srobert     copySym->wasIdenticalCodeFolded = true;
145*dfe94b16Srobert     copySym->size = 0;
146*dfe94b16Srobert   }
147*dfe94b16Srobert 
148*dfe94b16Srobert   symbols.insert(symbols.end(), copy->symbols.begin(), copy->symbols.end());
149*dfe94b16Srobert   copy->symbols.clear();
150*dfe94b16Srobert 
151*dfe94b16Srobert   // Remove duplicate compact unwind info for symbols at the same address.
152*dfe94b16Srobert   if (symbols.empty())
153*dfe94b16Srobert     return;
154*dfe94b16Srobert   for (auto it = symbols.begin() + 1; it != symbols.end(); ++it) {
155*dfe94b16Srobert     assert((*it)->value == 0);
156*dfe94b16Srobert     (*it)->unwindEntry = nullptr;
157*dfe94b16Srobert   }
1581cf9926bSpatrick }
1591cf9926bSpatrick 
writeTo(uint8_t * buf)1601cf9926bSpatrick void ConcatInputSection::writeTo(uint8_t *buf) {
1611cf9926bSpatrick   assert(!shouldOmitFromOutput());
1621cf9926bSpatrick 
163bb684c34Spatrick   if (getFileSize() == 0)
164bb684c34Spatrick     return;
165bb684c34Spatrick 
166bb684c34Spatrick   memcpy(buf, data.data(), data.size());
167bb684c34Spatrick 
1681cf9926bSpatrick   for (size_t i = 0; i < relocs.size(); i++) {
1691cf9926bSpatrick     const Reloc &r = relocs[i];
1701cf9926bSpatrick     uint8_t *loc = buf + r.offset;
1711cf9926bSpatrick     uint64_t referentVA = 0;
172*dfe94b16Srobert 
173*dfe94b16Srobert     const bool needsFixup = config->emitChainedFixups &&
174*dfe94b16Srobert                             target->hasAttr(r.type, RelocAttrBits::UNSIGNED);
1751cf9926bSpatrick     if (target->hasAttr(r.type, RelocAttrBits::SUBTRAHEND)) {
1761cf9926bSpatrick       const Symbol *fromSym = r.referent.get<Symbol *>();
1771cf9926bSpatrick       const Reloc &minuend = relocs[++i];
1781cf9926bSpatrick       uint64_t minuendVA;
1791cf9926bSpatrick       if (const Symbol *toSym = minuend.referent.dyn_cast<Symbol *>())
1801cf9926bSpatrick         minuendVA = toSym->getVA() + minuend.addend;
1811cf9926bSpatrick       else {
1821cf9926bSpatrick         auto *referentIsec = minuend.referent.get<InputSection *>();
1831cf9926bSpatrick         assert(!::shouldOmitFromOutput(referentIsec));
1841cf9926bSpatrick         minuendVA = referentIsec->getVA(minuend.addend);
185bb684c34Spatrick       }
1861cf9926bSpatrick       referentVA = minuendVA - fromSym->getVA();
1871cf9926bSpatrick     } else if (auto *referentSym = r.referent.dyn_cast<Symbol *>()) {
1881cf9926bSpatrick       if (target->hasAttr(r.type, RelocAttrBits::LOAD) &&
1891cf9926bSpatrick           !referentSym->isInGot())
1901cf9926bSpatrick         target->relaxGotLoad(loc, r.type);
191*dfe94b16Srobert       // For dtrace symbols, do not handle them as normal undefined symbols
192*dfe94b16Srobert       if (referentSym->getName().startswith("___dtrace_")) {
193*dfe94b16Srobert         // Change dtrace call site to pre-defined instructions
194*dfe94b16Srobert         target->handleDtraceReloc(referentSym, r, loc);
195*dfe94b16Srobert         continue;
196*dfe94b16Srobert       }
1971cf9926bSpatrick       referentVA = resolveSymbolVA(referentSym, r.type) + r.addend;
1981cf9926bSpatrick 
199*dfe94b16Srobert       if (isThreadLocalVariables(getFlags()) && isa<Defined>(referentSym)) {
2001cf9926bSpatrick         // References from thread-local variable sections are treated as offsets
2011cf9926bSpatrick         // relative to the start of the thread-local data memory area, which
2021cf9926bSpatrick         // is initialized via copying all the TLV data sections (which are all
2031cf9926bSpatrick         // contiguous).
2041cf9926bSpatrick         referentVA -= firstTLVDataSection->addr;
205*dfe94b16Srobert       } else if (needsFixup) {
206*dfe94b16Srobert         writeChainedFixup(loc, referentSym, r.addend);
207*dfe94b16Srobert         continue;
2081cf9926bSpatrick       }
2091cf9926bSpatrick     } else if (auto *referentIsec = r.referent.dyn_cast<InputSection *>()) {
2101cf9926bSpatrick       assert(!::shouldOmitFromOutput(referentIsec));
2111cf9926bSpatrick       referentVA = referentIsec->getVA(r.addend);
212*dfe94b16Srobert 
213*dfe94b16Srobert       if (needsFixup) {
214*dfe94b16Srobert         writeChainedRebase(loc, referentVA);
215*dfe94b16Srobert         continue;
216*dfe94b16Srobert       }
2171cf9926bSpatrick     }
2181cf9926bSpatrick     target->relocateOne(loc, r, referentVA, getVA() + r.offset);
2191cf9926bSpatrick   }
2201cf9926bSpatrick }
2211cf9926bSpatrick 
makeSyntheticInputSection(StringRef segName,StringRef sectName,uint32_t flags,ArrayRef<uint8_t> data,uint32_t align)222*dfe94b16Srobert ConcatInputSection *macho::makeSyntheticInputSection(StringRef segName,
223*dfe94b16Srobert                                                      StringRef sectName,
224*dfe94b16Srobert                                                      uint32_t flags,
225*dfe94b16Srobert                                                      ArrayRef<uint8_t> data,
226*dfe94b16Srobert                                                      uint32_t align) {
227*dfe94b16Srobert   Section &section =
228*dfe94b16Srobert       *make<Section>(/*file=*/nullptr, segName, sectName, flags, /*addr=*/0);
229*dfe94b16Srobert   auto isec = make<ConcatInputSection>(section, data, align);
230*dfe94b16Srobert   section.subsections.push_back({0, isec});
231*dfe94b16Srobert   return isec;
232*dfe94b16Srobert }
233*dfe94b16Srobert 
splitIntoPieces()2341cf9926bSpatrick void CStringInputSection::splitIntoPieces() {
2351cf9926bSpatrick   size_t off = 0;
2361cf9926bSpatrick   StringRef s = toStringRef(data);
2371cf9926bSpatrick   while (!s.empty()) {
2381cf9926bSpatrick     size_t end = s.find(0);
2391cf9926bSpatrick     if (end == StringRef::npos)
240*dfe94b16Srobert       fatal(getLocation(off) + ": string is not null terminated");
241*dfe94b16Srobert     uint32_t hash = deduplicateLiterals ? xxHash64(s.take_front(end)) : 0;
2421cf9926bSpatrick     pieces.emplace_back(off, hash);
243*dfe94b16Srobert     size_t size = end + 1; // include null terminator
2441cf9926bSpatrick     s = s.substr(size);
2451cf9926bSpatrick     off += size;
2461cf9926bSpatrick   }
2471cf9926bSpatrick }
2481cf9926bSpatrick 
getStringPiece(uint64_t off)2491cf9926bSpatrick StringPiece &CStringInputSection::getStringPiece(uint64_t off) {
2501cf9926bSpatrick   if (off >= data.size())
2511cf9926bSpatrick     fatal(toString(this) + ": offset is outside the section");
2521cf9926bSpatrick 
2531cf9926bSpatrick   auto it =
2541cf9926bSpatrick       partition_point(pieces, [=](StringPiece p) { return p.inSecOff <= off; });
2551cf9926bSpatrick   return it[-1];
2561cf9926bSpatrick }
2571cf9926bSpatrick 
getStringPiece(uint64_t off) const2581cf9926bSpatrick const StringPiece &CStringInputSection::getStringPiece(uint64_t off) const {
2591cf9926bSpatrick   return const_cast<CStringInputSection *>(this)->getStringPiece(off);
2601cf9926bSpatrick }
2611cf9926bSpatrick 
getOffset(uint64_t off) const2621cf9926bSpatrick uint64_t CStringInputSection::getOffset(uint64_t off) const {
2631cf9926bSpatrick   const StringPiece &piece = getStringPiece(off);
2641cf9926bSpatrick   uint64_t addend = off - piece.inSecOff;
2651cf9926bSpatrick   return piece.outSecOff + addend;
2661cf9926bSpatrick }
2671cf9926bSpatrick 
WordLiteralInputSection(const Section & section,ArrayRef<uint8_t> data,uint32_t align)268*dfe94b16Srobert WordLiteralInputSection::WordLiteralInputSection(const Section &section,
2691cf9926bSpatrick                                                  ArrayRef<uint8_t> data,
270*dfe94b16Srobert                                                  uint32_t align)
271*dfe94b16Srobert     : InputSection(WordLiteralKind, section, data, align) {
272*dfe94b16Srobert   switch (sectionType(getFlags())) {
2731cf9926bSpatrick   case S_4BYTE_LITERALS:
2741cf9926bSpatrick     power2LiteralSize = 2;
2751cf9926bSpatrick     break;
2761cf9926bSpatrick   case S_8BYTE_LITERALS:
2771cf9926bSpatrick     power2LiteralSize = 3;
2781cf9926bSpatrick     break;
2791cf9926bSpatrick   case S_16BYTE_LITERALS:
2801cf9926bSpatrick     power2LiteralSize = 4;
2811cf9926bSpatrick     break;
2821cf9926bSpatrick   default:
2831cf9926bSpatrick     llvm_unreachable("invalid literal section type");
2841cf9926bSpatrick   }
2851cf9926bSpatrick 
2861cf9926bSpatrick   live.resize(data.size() >> power2LiteralSize, !config->deadStrip);
2871cf9926bSpatrick }
2881cf9926bSpatrick 
getOffset(uint64_t off) const2891cf9926bSpatrick uint64_t WordLiteralInputSection::getOffset(uint64_t off) const {
2901cf9926bSpatrick   auto *osec = cast<WordLiteralSection>(parent);
291*dfe94b16Srobert   const uintptr_t buf = reinterpret_cast<uintptr_t>(data.data());
2921cf9926bSpatrick   switch (sectionType(getFlags())) {
2931cf9926bSpatrick   case S_4BYTE_LITERALS:
294*dfe94b16Srobert     return osec->getLiteral4Offset(buf + (off & ~3LLU)) | (off & 3);
2951cf9926bSpatrick   case S_8BYTE_LITERALS:
296*dfe94b16Srobert     return osec->getLiteral8Offset(buf + (off & ~7LLU)) | (off & 7);
2971cf9926bSpatrick   case S_16BYTE_LITERALS:
298*dfe94b16Srobert     return osec->getLiteral16Offset(buf + (off & ~15LLU)) | (off & 15);
2991cf9926bSpatrick   default:
3001cf9926bSpatrick     llvm_unreachable("invalid literal section type");
3011cf9926bSpatrick   }
3021cf9926bSpatrick }
3031cf9926bSpatrick 
isCodeSection(const InputSection * isec)3041cf9926bSpatrick bool macho::isCodeSection(const InputSection *isec) {
3051cf9926bSpatrick   uint32_t type = sectionType(isec->getFlags());
3061cf9926bSpatrick   if (type != S_REGULAR && type != S_COALESCED)
3071cf9926bSpatrick     return false;
3081cf9926bSpatrick 
3091cf9926bSpatrick   uint32_t attr = isec->getFlags() & SECTION_ATTRIBUTES_USR;
3101cf9926bSpatrick   if (attr == S_ATTR_PURE_INSTRUCTIONS)
3111cf9926bSpatrick     return true;
3121cf9926bSpatrick 
3131cf9926bSpatrick   if (isec->getSegName() == segment_names::text)
3141cf9926bSpatrick     return StringSwitch<bool>(isec->getName())
3151cf9926bSpatrick         .Cases(section_names::textCoalNt, section_names::staticInit, true)
3161cf9926bSpatrick         .Default(false);
3171cf9926bSpatrick 
3181cf9926bSpatrick   return false;
3191cf9926bSpatrick }
3201cf9926bSpatrick 
isCfStringSection(const InputSection * isec)3211cf9926bSpatrick bool macho::isCfStringSection(const InputSection *isec) {
3221cf9926bSpatrick   return isec->getName() == section_names::cfString &&
3231cf9926bSpatrick          isec->getSegName() == segment_names::data;
3241cf9926bSpatrick }
3251cf9926bSpatrick 
isClassRefsSection(const InputSection * isec)326*dfe94b16Srobert bool macho::isClassRefsSection(const InputSection *isec) {
327*dfe94b16Srobert   return isec->getName() == section_names::objcClassRefs &&
328*dfe94b16Srobert          isec->getSegName() == segment_names::data;
329*dfe94b16Srobert }
330*dfe94b16Srobert 
isSelRefsSection(const InputSection * isec)331*dfe94b16Srobert bool macho::isSelRefsSection(const InputSection *isec) {
332*dfe94b16Srobert   return isec->getName() == section_names::objcSelrefs &&
333*dfe94b16Srobert          isec->getSegName() == segment_names::data;
334*dfe94b16Srobert }
335*dfe94b16Srobert 
isEhFrameSection(const InputSection * isec)336*dfe94b16Srobert bool macho::isEhFrameSection(const InputSection *isec) {
337*dfe94b16Srobert   return isec->getName() == section_names::ehFrame &&
338*dfe94b16Srobert          isec->getSegName() == segment_names::text;
339*dfe94b16Srobert }
340*dfe94b16Srobert 
isGccExceptTabSection(const InputSection * isec)341*dfe94b16Srobert bool macho::isGccExceptTabSection(const InputSection *isec) {
342*dfe94b16Srobert   return isec->getName() == section_names::gccExceptTab &&
343*dfe94b16Srobert          isec->getSegName() == segment_names::text;
344*dfe94b16Srobert }
345*dfe94b16Srobert 
toString(const InputSection * isec)3461cf9926bSpatrick std::string lld::toString(const InputSection *isec) {
3471cf9926bSpatrick   return (toString(isec->getFile()) + ":(" + isec->getName() + ")").str();
348bb684c34Spatrick }
349