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" 10fe6060f1SDimitry Andric #include "ConcatOutputSection.h" 11fe6060f1SDimitry Andric #include "Config.h" 12e8d8bef9SDimitry Andric #include "InputFiles.h" 135ffd83dbSDimitry Andric #include "OutputSegment.h" 145ffd83dbSDimitry Andric #include "Symbols.h" 15fe6060f1SDimitry Andric #include "SyntheticSections.h" 165ffd83dbSDimitry Andric #include "Target.h" 17fe6060f1SDimitry Andric #include "UnwindInfoSection.h" 18e8d8bef9SDimitry Andric #include "Writer.h" 19bdd1243dSDimitry Andric 20bdd1243dSDimitry Andric #include "lld/Common/ErrorHandler.h" 215ffd83dbSDimitry Andric #include "lld/Common/Memory.h" 225ffd83dbSDimitry Andric #include "llvm/Support/Endian.h" 23fe6060f1SDimitry Andric #include "llvm/Support/xxhash.h" 245ffd83dbSDimitry Andric 255ffd83dbSDimitry Andric using namespace llvm; 265ffd83dbSDimitry Andric using namespace llvm::MachO; 275ffd83dbSDimitry Andric using namespace llvm::support; 285ffd83dbSDimitry Andric using namespace lld; 295ffd83dbSDimitry Andric using namespace lld::macho; 305ffd83dbSDimitry Andric 314824e7fdSDimitry Andric // Verify ConcatInputSection's size on 64-bit builds. The size of std::vector 324824e7fdSDimitry Andric // can differ based on STL debug levels (e.g. iterator debugging on MSVC's STL), 334824e7fdSDimitry Andric // so account for that. 34bdd1243dSDimitry Andric static_assert(sizeof(void *) != 8 || 35bdd1243dSDimitry Andric sizeof(ConcatInputSection) == sizeof(std::vector<Reloc>) + 88, 36349cc55cSDimitry Andric "Try to minimize ConcatInputSection's size, we create many " 37349cc55cSDimitry Andric "instances of it"); 38349cc55cSDimitry Andric 39fe6060f1SDimitry Andric std::vector<ConcatInputSection *> macho::inputSections; 40*0fca6ea1SDimitry Andric int macho::inputSectionsOrder = 0; 41*0fca6ea1SDimitry Andric 42*0fca6ea1SDimitry Andric // Call this function to add a new InputSection and have it routed to the 43*0fca6ea1SDimitry Andric // appropriate container. Depending on its type and current config, it will 44*0fca6ea1SDimitry Andric // either be added to 'inputSections' vector or to a synthetic section. 45*0fca6ea1SDimitry Andric void lld::macho::addInputSection(InputSection *inputSection) { 46*0fca6ea1SDimitry Andric if (auto *isec = dyn_cast<ConcatInputSection>(inputSection)) { 47*0fca6ea1SDimitry Andric if (isec->isCoalescedWeak()) 48*0fca6ea1SDimitry Andric return; 49*0fca6ea1SDimitry Andric if (config->emitRelativeMethodLists && 50*0fca6ea1SDimitry Andric ObjCMethListSection::isMethodList(isec)) { 51*0fca6ea1SDimitry Andric if (in.objcMethList->inputOrder == UnspecifiedInputOrder) 52*0fca6ea1SDimitry Andric in.objcMethList->inputOrder = inputSectionsOrder++; 53*0fca6ea1SDimitry Andric in.objcMethList->addInput(isec); 54*0fca6ea1SDimitry Andric isec->parent = in.objcMethList; 55*0fca6ea1SDimitry Andric return; 56*0fca6ea1SDimitry Andric } 57*0fca6ea1SDimitry Andric if (config->emitInitOffsets && 58*0fca6ea1SDimitry Andric sectionType(isec->getFlags()) == S_MOD_INIT_FUNC_POINTERS) { 59*0fca6ea1SDimitry Andric in.initOffsets->addInput(isec); 60*0fca6ea1SDimitry Andric return; 61*0fca6ea1SDimitry Andric } 62*0fca6ea1SDimitry Andric isec->outSecOff = inputSectionsOrder++; 63*0fca6ea1SDimitry Andric auto *osec = ConcatOutputSection::getOrCreateForInput(isec); 64*0fca6ea1SDimitry Andric isec->parent = osec; 65*0fca6ea1SDimitry Andric inputSections.push_back(isec); 66*0fca6ea1SDimitry Andric } else if (auto *isec = dyn_cast<CStringInputSection>(inputSection)) { 67*0fca6ea1SDimitry Andric if (isec->getName() == section_names::objcMethname) { 68*0fca6ea1SDimitry Andric if (in.objcMethnameSection->inputOrder == UnspecifiedInputOrder) 69*0fca6ea1SDimitry Andric in.objcMethnameSection->inputOrder = inputSectionsOrder++; 70*0fca6ea1SDimitry Andric in.objcMethnameSection->addInput(isec); 71*0fca6ea1SDimitry Andric } else { 72*0fca6ea1SDimitry Andric if (in.cStringSection->inputOrder == UnspecifiedInputOrder) 73*0fca6ea1SDimitry Andric in.cStringSection->inputOrder = inputSectionsOrder++; 74*0fca6ea1SDimitry Andric in.cStringSection->addInput(isec); 75*0fca6ea1SDimitry Andric } 76*0fca6ea1SDimitry Andric } else if (auto *isec = dyn_cast<WordLiteralInputSection>(inputSection)) { 77*0fca6ea1SDimitry Andric if (in.wordLiteralSection->inputOrder == UnspecifiedInputOrder) 78*0fca6ea1SDimitry Andric in.wordLiteralSection->inputOrder = inputSectionsOrder++; 79*0fca6ea1SDimitry Andric in.wordLiteralSection->addInput(isec); 80*0fca6ea1SDimitry Andric } else { 81*0fca6ea1SDimitry Andric llvm_unreachable("unexpected input section kind"); 82*0fca6ea1SDimitry Andric } 83*0fca6ea1SDimitry Andric 84*0fca6ea1SDimitry Andric assert(inputSectionsOrder <= UnspecifiedInputOrder); 85*0fca6ea1SDimitry Andric } 865ffd83dbSDimitry Andric 87e8d8bef9SDimitry Andric uint64_t InputSection::getFileSize() const { 88fe6060f1SDimitry Andric return isZeroFill(getFlags()) ? 0 : getSize(); 89e8d8bef9SDimitry Andric } 90e8d8bef9SDimitry Andric 91fe6060f1SDimitry Andric uint64_t InputSection::getVA(uint64_t off) const { 92fe6060f1SDimitry Andric return parent->addr + getOffset(off); 93fe6060f1SDimitry Andric } 945ffd83dbSDimitry Andric 95fe6060f1SDimitry Andric static uint64_t resolveSymbolVA(const Symbol *sym, uint8_t type) { 96fe6060f1SDimitry Andric const RelocAttrs &relocAttrs = target->getRelocAttrs(type); 97fe6060f1SDimitry Andric if (relocAttrs.hasAttr(RelocAttrBits::BRANCH)) 98fe6060f1SDimitry Andric return sym->resolveBranchVA(); 99fe6060f1SDimitry Andric if (relocAttrs.hasAttr(RelocAttrBits::GOT)) 100fe6060f1SDimitry Andric return sym->resolveGotVA(); 101fe6060f1SDimitry Andric if (relocAttrs.hasAttr(RelocAttrBits::TLV)) 102fe6060f1SDimitry Andric return sym->resolveTlvVA(); 103fe6060f1SDimitry Andric return sym->getVA(); 104fe6060f1SDimitry Andric } 105fe6060f1SDimitry Andric 10681ad6265SDimitry Andric const Defined *InputSection::getContainingSymbol(uint64_t off) const { 10781ad6265SDimitry Andric auto *nextSym = llvm::upper_bound( 10881ad6265SDimitry Andric symbols, off, [](uint64_t a, const Defined *b) { return a < b->value; }); 10981ad6265SDimitry Andric if (nextSym == symbols.begin()) 11081ad6265SDimitry Andric return nullptr; 11181ad6265SDimitry Andric return *std::prev(nextSym); 11281ad6265SDimitry Andric } 11381ad6265SDimitry Andric 11481ad6265SDimitry Andric std::string InputSection::getLocation(uint64_t off) const { 11581ad6265SDimitry Andric // First, try to find a symbol that's near the offset. Use it as a reference 11681ad6265SDimitry Andric // point. 11781ad6265SDimitry Andric if (auto *sym = getContainingSymbol(off)) 118972a253aSDimitry Andric return (toString(getFile()) + ":(symbol " + toString(*sym) + "+0x" + 11981ad6265SDimitry Andric Twine::utohexstr(off - sym->value) + ")") 12081ad6265SDimitry Andric .str(); 12181ad6265SDimitry Andric 12281ad6265SDimitry Andric // If that fails, use the section itself as a reference point. 12381ad6265SDimitry Andric for (const Subsection &subsec : section.subsections) { 12481ad6265SDimitry Andric if (subsec.isec == this) { 12581ad6265SDimitry Andric off += subsec.offset; 12681ad6265SDimitry Andric break; 127fe6060f1SDimitry Andric } 128fe6060f1SDimitry Andric } 129fe6060f1SDimitry Andric 13081ad6265SDimitry Andric return (toString(getFile()) + ":(" + getName() + "+0x" + 13181ad6265SDimitry Andric Twine::utohexstr(off) + ")") 13281ad6265SDimitry Andric .str(); 13381ad6265SDimitry Andric } 13481ad6265SDimitry Andric 13581ad6265SDimitry Andric std::string InputSection::getSourceLocation(uint64_t off) const { 13681ad6265SDimitry Andric auto *obj = dyn_cast_or_null<ObjFile>(getFile()); 13781ad6265SDimitry Andric if (!obj) 13881ad6265SDimitry Andric return {}; 13981ad6265SDimitry Andric 14081ad6265SDimitry Andric DWARFCache *dwarf = obj->getDwarf(); 14181ad6265SDimitry Andric if (!dwarf) 14281ad6265SDimitry Andric return std::string(); 14381ad6265SDimitry Andric 14481ad6265SDimitry Andric for (const Subsection &subsec : section.subsections) { 14581ad6265SDimitry Andric if (subsec.isec == this) { 14681ad6265SDimitry Andric off += subsec.offset; 14781ad6265SDimitry Andric break; 14881ad6265SDimitry Andric } 14981ad6265SDimitry Andric } 15081ad6265SDimitry Andric 15181ad6265SDimitry Andric auto createMsg = [&](StringRef path, unsigned line) { 15281ad6265SDimitry Andric std::string filename = sys::path::filename(path).str(); 15381ad6265SDimitry Andric std::string lineStr = (":" + Twine(line)).str(); 15481ad6265SDimitry Andric if (filename == path) 15581ad6265SDimitry Andric return filename + lineStr; 15681ad6265SDimitry Andric return (filename + lineStr + " (" + path + lineStr + ")").str(); 15781ad6265SDimitry Andric }; 15881ad6265SDimitry Andric 15981ad6265SDimitry Andric // First, look up a function for a given offset. 160bdd1243dSDimitry Andric if (std::optional<DILineInfo> li = dwarf->getDILineInfo( 16181ad6265SDimitry Andric section.addr + off, object::SectionedAddress::UndefSection)) 16281ad6265SDimitry Andric return createMsg(li->FileName, li->Line); 16381ad6265SDimitry Andric 16481ad6265SDimitry Andric // If it failed, look up again as a variable. 16581ad6265SDimitry Andric if (const Defined *sym = getContainingSymbol(off)) { 16681ad6265SDimitry Andric // Symbols are generally prefixed with an underscore, which is not included 16781ad6265SDimitry Andric // in the debug information. 16881ad6265SDimitry Andric StringRef symName = sym->getName(); 16981ad6265SDimitry Andric if (!symName.empty() && symName[0] == '_') 17081ad6265SDimitry Andric symName = symName.substr(1); 17181ad6265SDimitry Andric 172bdd1243dSDimitry Andric if (std::optional<std::pair<std::string, unsigned>> fileLine = 17381ad6265SDimitry Andric dwarf->getVariableLoc(symName)) 17481ad6265SDimitry Andric return createMsg(fileLine->first, fileLine->second); 17581ad6265SDimitry Andric } 17681ad6265SDimitry Andric 17781ad6265SDimitry Andric // Try to get the source file's name from the DWARF information. 17881ad6265SDimitry Andric if (obj->compileUnit) 17981ad6265SDimitry Andric return obj->sourceFile(); 18081ad6265SDimitry Andric 18181ad6265SDimitry Andric return {}; 182fe6060f1SDimitry Andric } 183fe6060f1SDimitry Andric 18406c3fb27SDimitry Andric const Reloc *InputSection::getRelocAt(uint32_t off) const { 18506c3fb27SDimitry Andric auto it = llvm::find_if( 18606c3fb27SDimitry Andric relocs, [=](const macho::Reloc &r) { return r.offset == off; }); 18706c3fb27SDimitry Andric if (it == relocs.end()) 18806c3fb27SDimitry Andric return nullptr; 18906c3fb27SDimitry Andric return &*it; 19006c3fb27SDimitry Andric } 19106c3fb27SDimitry Andric 192fe6060f1SDimitry Andric void ConcatInputSection::foldIdentical(ConcatInputSection *copy) { 193fe6060f1SDimitry Andric align = std::max(align, copy->align); 194fe6060f1SDimitry Andric copy->live = false; 195fe6060f1SDimitry Andric copy->wasCoalesced = true; 196fe6060f1SDimitry Andric copy->replacement = this; 197*0fca6ea1SDimitry Andric for (auto ©Sym : copy->symbols) 19881ad6265SDimitry Andric copySym->wasIdenticalCodeFolded = true; 199349cc55cSDimitry Andric 200bdd1243dSDimitry Andric symbols.insert(symbols.end(), copy->symbols.begin(), copy->symbols.end()); 201349cc55cSDimitry Andric copy->symbols.clear(); 202349cc55cSDimitry Andric 203349cc55cSDimitry Andric // Remove duplicate compact unwind info for symbols at the same address. 204349cc55cSDimitry Andric if (symbols.empty()) 205349cc55cSDimitry Andric return; 206bdd1243dSDimitry Andric for (auto it = symbols.begin() + 1; it != symbols.end(); ++it) { 207bdd1243dSDimitry Andric assert((*it)->value == 0); 208*0fca6ea1SDimitry Andric (*it)->originalUnwindEntry = nullptr; 209349cc55cSDimitry Andric } 210fe6060f1SDimitry Andric } 211fe6060f1SDimitry Andric 212fe6060f1SDimitry Andric void ConcatInputSection::writeTo(uint8_t *buf) { 213fe6060f1SDimitry Andric assert(!shouldOmitFromOutput()); 214fe6060f1SDimitry Andric 2155ffd83dbSDimitry Andric if (getFileSize() == 0) 2165ffd83dbSDimitry Andric return; 2175ffd83dbSDimitry Andric 2185ffd83dbSDimitry Andric memcpy(buf, data.data(), data.size()); 2195ffd83dbSDimitry Andric 220fe6060f1SDimitry Andric for (size_t i = 0; i < relocs.size(); i++) { 221fe6060f1SDimitry Andric const Reloc &r = relocs[i]; 222fe6060f1SDimitry Andric uint8_t *loc = buf + r.offset; 223e8d8bef9SDimitry Andric uint64_t referentVA = 0; 224bdd1243dSDimitry Andric 225bdd1243dSDimitry Andric const bool needsFixup = config->emitChainedFixups && 226bdd1243dSDimitry Andric target->hasAttr(r.type, RelocAttrBits::UNSIGNED); 227fe6060f1SDimitry Andric if (target->hasAttr(r.type, RelocAttrBits::SUBTRAHEND)) { 228fe6060f1SDimitry Andric const Symbol *fromSym = r.referent.get<Symbol *>(); 229fe6060f1SDimitry Andric const Reloc &minuend = relocs[++i]; 230fe6060f1SDimitry Andric uint64_t minuendVA; 231fe6060f1SDimitry Andric if (const Symbol *toSym = minuend.referent.dyn_cast<Symbol *>()) 232fe6060f1SDimitry Andric minuendVA = toSym->getVA() + minuend.addend; 233fe6060f1SDimitry Andric else { 234fe6060f1SDimitry Andric auto *referentIsec = minuend.referent.get<InputSection *>(); 235fe6060f1SDimitry Andric assert(!::shouldOmitFromOutput(referentIsec)); 236fe6060f1SDimitry Andric minuendVA = referentIsec->getVA(minuend.addend); 237fe6060f1SDimitry Andric } 238fe6060f1SDimitry Andric referentVA = minuendVA - fromSym->getVA(); 239fe6060f1SDimitry Andric } else if (auto *referentSym = r.referent.dyn_cast<Symbol *>()) { 240fe6060f1SDimitry Andric if (target->hasAttr(r.type, RelocAttrBits::LOAD) && 241fe6060f1SDimitry Andric !referentSym->isInGot()) 242fe6060f1SDimitry Andric target->relaxGotLoad(loc, r.type); 243753f127fSDimitry Andric // For dtrace symbols, do not handle them as normal undefined symbols 24406c3fb27SDimitry Andric if (referentSym->getName().starts_with("___dtrace_")) { 245753f127fSDimitry Andric // Change dtrace call site to pre-defined instructions 246753f127fSDimitry Andric target->handleDtraceReloc(referentSym, r, loc); 247753f127fSDimitry Andric continue; 248753f127fSDimitry Andric } 249fe6060f1SDimitry Andric referentVA = resolveSymbolVA(referentSym, r.type) + r.addend; 2505ffd83dbSDimitry Andric 251bdd1243dSDimitry Andric if (isThreadLocalVariables(getFlags()) && isa<Defined>(referentSym)) { 252e8d8bef9SDimitry Andric // References from thread-local variable sections are treated as offsets 253e8d8bef9SDimitry Andric // relative to the start of the thread-local data memory area, which 254e8d8bef9SDimitry Andric // is initialized via copying all the TLV data sections (which are all 255e8d8bef9SDimitry Andric // contiguous). 256e8d8bef9SDimitry Andric referentVA -= firstTLVDataSection->addr; 257bdd1243dSDimitry Andric } else if (needsFixup) { 258bdd1243dSDimitry Andric writeChainedFixup(loc, referentSym, r.addend); 259bdd1243dSDimitry Andric continue; 2605ffd83dbSDimitry Andric } 261e8d8bef9SDimitry Andric } else if (auto *referentIsec = r.referent.dyn_cast<InputSection *>()) { 262fe6060f1SDimitry Andric assert(!::shouldOmitFromOutput(referentIsec)); 263fe6060f1SDimitry Andric referentVA = referentIsec->getVA(r.addend); 264bdd1243dSDimitry Andric 265bdd1243dSDimitry Andric if (needsFixup) { 266bdd1243dSDimitry Andric writeChainedRebase(loc, referentVA); 267bdd1243dSDimitry Andric continue; 268bdd1243dSDimitry Andric } 269e8d8bef9SDimitry Andric } 270fe6060f1SDimitry Andric target->relocateOne(loc, r, referentVA, getVA() + r.offset); 271e8d8bef9SDimitry Andric } 27281ad6265SDimitry Andric } 27381ad6265SDimitry Andric 27481ad6265SDimitry Andric ConcatInputSection *macho::makeSyntheticInputSection(StringRef segName, 27581ad6265SDimitry Andric StringRef sectName, 27681ad6265SDimitry Andric uint32_t flags, 27781ad6265SDimitry Andric ArrayRef<uint8_t> data, 27881ad6265SDimitry Andric uint32_t align) { 27981ad6265SDimitry Andric Section §ion = 28081ad6265SDimitry Andric *make<Section>(/*file=*/nullptr, segName, sectName, flags, /*addr=*/0); 28181ad6265SDimitry Andric auto isec = make<ConcatInputSection>(section, data, align); 282*0fca6ea1SDimitry Andric // Since this is an explicitly created 'fake' input section, 283*0fca6ea1SDimitry Andric // it should not be dead stripped. 284*0fca6ea1SDimitry Andric isec->live = true; 28581ad6265SDimitry Andric section.subsections.push_back({0, isec}); 28681ad6265SDimitry Andric return isec; 287e8d8bef9SDimitry Andric } 288e8d8bef9SDimitry Andric 289fe6060f1SDimitry Andric void CStringInputSection::splitIntoPieces() { 290fe6060f1SDimitry Andric size_t off = 0; 291fe6060f1SDimitry Andric StringRef s = toStringRef(data); 292fe6060f1SDimitry Andric while (!s.empty()) { 293fe6060f1SDimitry Andric size_t end = s.find(0); 294fe6060f1SDimitry Andric if (end == StringRef::npos) 29581ad6265SDimitry Andric fatal(getLocation(off) + ": string is not null terminated"); 29606c3fb27SDimitry Andric uint32_t hash = deduplicateLiterals ? xxh3_64bits(s.take_front(end)) : 0; 297fe6060f1SDimitry Andric pieces.emplace_back(off, hash); 298bdd1243dSDimitry Andric size_t size = end + 1; // include null terminator 299fe6060f1SDimitry Andric s = s.substr(size); 300fe6060f1SDimitry Andric off += size; 301fe6060f1SDimitry Andric } 302fe6060f1SDimitry Andric } 303fe6060f1SDimitry Andric 304fe6060f1SDimitry Andric StringPiece &CStringInputSection::getStringPiece(uint64_t off) { 305fe6060f1SDimitry Andric if (off >= data.size()) 306fe6060f1SDimitry Andric fatal(toString(this) + ": offset is outside the section"); 307fe6060f1SDimitry Andric 308fe6060f1SDimitry Andric auto it = 309fe6060f1SDimitry Andric partition_point(pieces, [=](StringPiece p) { return p.inSecOff <= off; }); 310fe6060f1SDimitry Andric return it[-1]; 311fe6060f1SDimitry Andric } 312fe6060f1SDimitry Andric 313fe6060f1SDimitry Andric const StringPiece &CStringInputSection::getStringPiece(uint64_t off) const { 314fe6060f1SDimitry Andric return const_cast<CStringInputSection *>(this)->getStringPiece(off); 315fe6060f1SDimitry Andric } 316fe6060f1SDimitry Andric 31706c3fb27SDimitry Andric size_t CStringInputSection::getStringPieceIndex(uint64_t off) const { 31806c3fb27SDimitry Andric if (off >= data.size()) 31906c3fb27SDimitry Andric fatal(toString(this) + ": offset is outside the section"); 32006c3fb27SDimitry Andric 32106c3fb27SDimitry Andric auto it = 32206c3fb27SDimitry Andric partition_point(pieces, [=](StringPiece p) { return p.inSecOff <= off; }); 32306c3fb27SDimitry Andric return std::distance(pieces.begin(), it) - 1; 32406c3fb27SDimitry Andric } 32506c3fb27SDimitry Andric 326fe6060f1SDimitry Andric uint64_t CStringInputSection::getOffset(uint64_t off) const { 327fe6060f1SDimitry Andric const StringPiece &piece = getStringPiece(off); 328fe6060f1SDimitry Andric uint64_t addend = off - piece.inSecOff; 329fe6060f1SDimitry Andric return piece.outSecOff + addend; 330fe6060f1SDimitry Andric } 331fe6060f1SDimitry Andric 33281ad6265SDimitry Andric WordLiteralInputSection::WordLiteralInputSection(const Section §ion, 333fe6060f1SDimitry Andric ArrayRef<uint8_t> data, 33481ad6265SDimitry Andric uint32_t align) 33581ad6265SDimitry Andric : InputSection(WordLiteralKind, section, data, align) { 33681ad6265SDimitry Andric switch (sectionType(getFlags())) { 337fe6060f1SDimitry Andric case S_4BYTE_LITERALS: 338fe6060f1SDimitry Andric power2LiteralSize = 2; 339fe6060f1SDimitry Andric break; 340fe6060f1SDimitry Andric case S_8BYTE_LITERALS: 341fe6060f1SDimitry Andric power2LiteralSize = 3; 342fe6060f1SDimitry Andric break; 343fe6060f1SDimitry Andric case S_16BYTE_LITERALS: 344fe6060f1SDimitry Andric power2LiteralSize = 4; 345fe6060f1SDimitry Andric break; 346fe6060f1SDimitry Andric default: 347fe6060f1SDimitry Andric llvm_unreachable("invalid literal section type"); 348fe6060f1SDimitry Andric } 349fe6060f1SDimitry Andric 350fe6060f1SDimitry Andric live.resize(data.size() >> power2LiteralSize, !config->deadStrip); 351fe6060f1SDimitry Andric } 352fe6060f1SDimitry Andric 353fe6060f1SDimitry Andric uint64_t WordLiteralInputSection::getOffset(uint64_t off) const { 354fe6060f1SDimitry Andric auto *osec = cast<WordLiteralSection>(parent); 355349cc55cSDimitry Andric const uintptr_t buf = reinterpret_cast<uintptr_t>(data.data()); 356fe6060f1SDimitry Andric switch (sectionType(getFlags())) { 357fe6060f1SDimitry Andric case S_4BYTE_LITERALS: 358349cc55cSDimitry Andric return osec->getLiteral4Offset(buf + (off & ~3LLU)) | (off & 3); 359fe6060f1SDimitry Andric case S_8BYTE_LITERALS: 360349cc55cSDimitry Andric return osec->getLiteral8Offset(buf + (off & ~7LLU)) | (off & 7); 361fe6060f1SDimitry Andric case S_16BYTE_LITERALS: 362349cc55cSDimitry Andric return osec->getLiteral16Offset(buf + (off & ~15LLU)) | (off & 15); 363fe6060f1SDimitry Andric default: 364fe6060f1SDimitry Andric llvm_unreachable("invalid literal section type"); 365fe6060f1SDimitry Andric } 366fe6060f1SDimitry Andric } 367fe6060f1SDimitry Andric 368fe6060f1SDimitry Andric bool macho::isCodeSection(const InputSection *isec) { 369fe6060f1SDimitry Andric uint32_t type = sectionType(isec->getFlags()); 370e8d8bef9SDimitry Andric if (type != S_REGULAR && type != S_COALESCED) 371e8d8bef9SDimitry Andric return false; 372e8d8bef9SDimitry Andric 373fe6060f1SDimitry Andric uint32_t attr = isec->getFlags() & SECTION_ATTRIBUTES_USR; 374e8d8bef9SDimitry Andric if (attr == S_ATTR_PURE_INSTRUCTIONS) 375e8d8bef9SDimitry Andric return true; 376e8d8bef9SDimitry Andric 377fe6060f1SDimitry Andric if (isec->getSegName() == segment_names::text) 378fe6060f1SDimitry Andric return StringSwitch<bool>(isec->getName()) 379fe6060f1SDimitry Andric .Cases(section_names::textCoalNt, section_names::staticInit, true) 380e8d8bef9SDimitry Andric .Default(false); 381e8d8bef9SDimitry Andric 382e8d8bef9SDimitry Andric return false; 383e8d8bef9SDimitry Andric } 384e8d8bef9SDimitry Andric 385fe6060f1SDimitry Andric bool macho::isCfStringSection(const InputSection *isec) { 386fe6060f1SDimitry Andric return isec->getName() == section_names::cfString && 387fe6060f1SDimitry Andric isec->getSegName() == segment_names::data; 388fe6060f1SDimitry Andric } 389fe6060f1SDimitry Andric 39081ad6265SDimitry Andric bool macho::isClassRefsSection(const InputSection *isec) { 39181ad6265SDimitry Andric return isec->getName() == section_names::objcClassRefs && 39281ad6265SDimitry Andric isec->getSegName() == segment_names::data; 39381ad6265SDimitry Andric } 39481ad6265SDimitry Andric 395bdd1243dSDimitry Andric bool macho::isSelRefsSection(const InputSection *isec) { 396bdd1243dSDimitry Andric return isec->getName() == section_names::objcSelrefs && 397bdd1243dSDimitry Andric isec->getSegName() == segment_names::data; 398bdd1243dSDimitry Andric } 399bdd1243dSDimitry Andric 40081ad6265SDimitry Andric bool macho::isEhFrameSection(const InputSection *isec) { 40181ad6265SDimitry Andric return isec->getName() == section_names::ehFrame && 40281ad6265SDimitry Andric isec->getSegName() == segment_names::text; 40381ad6265SDimitry Andric } 40481ad6265SDimitry Andric 405fcaf7f86SDimitry Andric bool macho::isGccExceptTabSection(const InputSection *isec) { 406fcaf7f86SDimitry Andric return isec->getName() == section_names::gccExceptTab && 407fcaf7f86SDimitry Andric isec->getSegName() == segment_names::text; 408fcaf7f86SDimitry Andric } 409fcaf7f86SDimitry Andric 410e8d8bef9SDimitry Andric std::string lld::toString(const InputSection *isec) { 411fe6060f1SDimitry Andric return (toString(isec->getFile()) + ":(" + isec->getName() + ")").str(); 4125ffd83dbSDimitry Andric } 413