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 ©Sym : 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 §ion =
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 §ion,
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