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; 405ffd83dbSDimitry Andric 41e8d8bef9SDimitry Andric uint64_t InputSection::getFileSize() const { 42fe6060f1SDimitry Andric return isZeroFill(getFlags()) ? 0 : getSize(); 43e8d8bef9SDimitry Andric } 44e8d8bef9SDimitry Andric 45fe6060f1SDimitry Andric uint64_t InputSection::getVA(uint64_t off) const { 46fe6060f1SDimitry Andric return parent->addr + getOffset(off); 47fe6060f1SDimitry Andric } 485ffd83dbSDimitry Andric 49fe6060f1SDimitry Andric static uint64_t resolveSymbolVA(const Symbol *sym, uint8_t type) { 50fe6060f1SDimitry Andric const RelocAttrs &relocAttrs = target->getRelocAttrs(type); 51fe6060f1SDimitry Andric if (relocAttrs.hasAttr(RelocAttrBits::BRANCH)) 52fe6060f1SDimitry Andric return sym->resolveBranchVA(); 53fe6060f1SDimitry Andric if (relocAttrs.hasAttr(RelocAttrBits::GOT)) 54fe6060f1SDimitry Andric return sym->resolveGotVA(); 55fe6060f1SDimitry Andric if (relocAttrs.hasAttr(RelocAttrBits::TLV)) 56fe6060f1SDimitry Andric return sym->resolveTlvVA(); 57fe6060f1SDimitry Andric return sym->getVA(); 58fe6060f1SDimitry Andric } 59fe6060f1SDimitry Andric 6081ad6265SDimitry Andric const Defined *InputSection::getContainingSymbol(uint64_t off) const { 6181ad6265SDimitry Andric auto *nextSym = llvm::upper_bound( 6281ad6265SDimitry Andric symbols, off, [](uint64_t a, const Defined *b) { return a < b->value; }); 6381ad6265SDimitry Andric if (nextSym == symbols.begin()) 6481ad6265SDimitry Andric return nullptr; 6581ad6265SDimitry Andric return *std::prev(nextSym); 6681ad6265SDimitry Andric } 6781ad6265SDimitry Andric 6881ad6265SDimitry Andric std::string InputSection::getLocation(uint64_t off) const { 6981ad6265SDimitry Andric // First, try to find a symbol that's near the offset. Use it as a reference 7081ad6265SDimitry Andric // point. 7181ad6265SDimitry Andric if (auto *sym = getContainingSymbol(off)) 72972a253aSDimitry Andric return (toString(getFile()) + ":(symbol " + toString(*sym) + "+0x" + 7381ad6265SDimitry Andric Twine::utohexstr(off - sym->value) + ")") 7481ad6265SDimitry Andric .str(); 7581ad6265SDimitry Andric 7681ad6265SDimitry Andric // If that fails, use the section itself as a reference point. 7781ad6265SDimitry Andric for (const Subsection &subsec : section.subsections) { 7881ad6265SDimitry Andric if (subsec.isec == this) { 7981ad6265SDimitry Andric off += subsec.offset; 8081ad6265SDimitry Andric break; 81fe6060f1SDimitry Andric } 82fe6060f1SDimitry Andric } 83fe6060f1SDimitry Andric 8481ad6265SDimitry Andric return (toString(getFile()) + ":(" + getName() + "+0x" + 8581ad6265SDimitry Andric Twine::utohexstr(off) + ")") 8681ad6265SDimitry Andric .str(); 8781ad6265SDimitry Andric } 8881ad6265SDimitry Andric 8981ad6265SDimitry Andric std::string InputSection::getSourceLocation(uint64_t off) const { 9081ad6265SDimitry Andric auto *obj = dyn_cast_or_null<ObjFile>(getFile()); 9181ad6265SDimitry Andric if (!obj) 9281ad6265SDimitry Andric return {}; 9381ad6265SDimitry Andric 9481ad6265SDimitry Andric DWARFCache *dwarf = obj->getDwarf(); 9581ad6265SDimitry Andric if (!dwarf) 9681ad6265SDimitry Andric return std::string(); 9781ad6265SDimitry Andric 9881ad6265SDimitry Andric for (const Subsection &subsec : section.subsections) { 9981ad6265SDimitry Andric if (subsec.isec == this) { 10081ad6265SDimitry Andric off += subsec.offset; 10181ad6265SDimitry Andric break; 10281ad6265SDimitry Andric } 10381ad6265SDimitry Andric } 10481ad6265SDimitry Andric 10581ad6265SDimitry Andric auto createMsg = [&](StringRef path, unsigned line) { 10681ad6265SDimitry Andric std::string filename = sys::path::filename(path).str(); 10781ad6265SDimitry Andric std::string lineStr = (":" + Twine(line)).str(); 10881ad6265SDimitry Andric if (filename == path) 10981ad6265SDimitry Andric return filename + lineStr; 11081ad6265SDimitry Andric return (filename + lineStr + " (" + path + lineStr + ")").str(); 11181ad6265SDimitry Andric }; 11281ad6265SDimitry Andric 11381ad6265SDimitry Andric // First, look up a function for a given offset. 114bdd1243dSDimitry Andric if (std::optional<DILineInfo> li = dwarf->getDILineInfo( 11581ad6265SDimitry Andric section.addr + off, object::SectionedAddress::UndefSection)) 11681ad6265SDimitry Andric return createMsg(li->FileName, li->Line); 11781ad6265SDimitry Andric 11881ad6265SDimitry Andric // If it failed, look up again as a variable. 11981ad6265SDimitry Andric if (const Defined *sym = getContainingSymbol(off)) { 12081ad6265SDimitry Andric // Symbols are generally prefixed with an underscore, which is not included 12181ad6265SDimitry Andric // in the debug information. 12281ad6265SDimitry Andric StringRef symName = sym->getName(); 12381ad6265SDimitry Andric if (!symName.empty() && symName[0] == '_') 12481ad6265SDimitry Andric symName = symName.substr(1); 12581ad6265SDimitry Andric 126bdd1243dSDimitry Andric if (std::optional<std::pair<std::string, unsigned>> fileLine = 12781ad6265SDimitry Andric dwarf->getVariableLoc(symName)) 12881ad6265SDimitry Andric return createMsg(fileLine->first, fileLine->second); 12981ad6265SDimitry Andric } 13081ad6265SDimitry Andric 13181ad6265SDimitry Andric // Try to get the source file's name from the DWARF information. 13281ad6265SDimitry Andric if (obj->compileUnit) 13381ad6265SDimitry Andric return obj->sourceFile(); 13481ad6265SDimitry Andric 13581ad6265SDimitry Andric return {}; 136fe6060f1SDimitry Andric } 137fe6060f1SDimitry Andric 138*06c3fb27SDimitry Andric const Reloc *InputSection::getRelocAt(uint32_t off) const { 139*06c3fb27SDimitry Andric auto it = llvm::find_if( 140*06c3fb27SDimitry Andric relocs, [=](const macho::Reloc &r) { return r.offset == off; }); 141*06c3fb27SDimitry Andric if (it == relocs.end()) 142*06c3fb27SDimitry Andric return nullptr; 143*06c3fb27SDimitry Andric return &*it; 144*06c3fb27SDimitry Andric } 145*06c3fb27SDimitry Andric 146fe6060f1SDimitry Andric void ConcatInputSection::foldIdentical(ConcatInputSection *copy) { 147fe6060f1SDimitry Andric align = std::max(align, copy->align); 148fe6060f1SDimitry Andric copy->live = false; 149fe6060f1SDimitry Andric copy->wasCoalesced = true; 150fe6060f1SDimitry Andric copy->replacement = this; 151bdd1243dSDimitry Andric for (auto ©Sym : copy->symbols) { 15281ad6265SDimitry Andric copySym->wasIdenticalCodeFolded = true; 153bdd1243dSDimitry Andric copySym->size = 0; 154bdd1243dSDimitry Andric } 155349cc55cSDimitry Andric 156bdd1243dSDimitry Andric symbols.insert(symbols.end(), copy->symbols.begin(), copy->symbols.end()); 157349cc55cSDimitry Andric copy->symbols.clear(); 158349cc55cSDimitry Andric 159349cc55cSDimitry Andric // Remove duplicate compact unwind info for symbols at the same address. 160349cc55cSDimitry Andric if (symbols.empty()) 161349cc55cSDimitry Andric return; 162bdd1243dSDimitry Andric for (auto it = symbols.begin() + 1; it != symbols.end(); ++it) { 163bdd1243dSDimitry Andric assert((*it)->value == 0); 164bdd1243dSDimitry Andric (*it)->unwindEntry = nullptr; 165349cc55cSDimitry Andric } 166fe6060f1SDimitry Andric } 167fe6060f1SDimitry Andric 168fe6060f1SDimitry Andric void ConcatInputSection::writeTo(uint8_t *buf) { 169fe6060f1SDimitry Andric assert(!shouldOmitFromOutput()); 170fe6060f1SDimitry Andric 1715ffd83dbSDimitry Andric if (getFileSize() == 0) 1725ffd83dbSDimitry Andric return; 1735ffd83dbSDimitry Andric 1745ffd83dbSDimitry Andric memcpy(buf, data.data(), data.size()); 1755ffd83dbSDimitry Andric 176fe6060f1SDimitry Andric for (size_t i = 0; i < relocs.size(); i++) { 177fe6060f1SDimitry Andric const Reloc &r = relocs[i]; 178fe6060f1SDimitry Andric uint8_t *loc = buf + r.offset; 179e8d8bef9SDimitry Andric uint64_t referentVA = 0; 180bdd1243dSDimitry Andric 181bdd1243dSDimitry Andric const bool needsFixup = config->emitChainedFixups && 182bdd1243dSDimitry Andric target->hasAttr(r.type, RelocAttrBits::UNSIGNED); 183fe6060f1SDimitry Andric if (target->hasAttr(r.type, RelocAttrBits::SUBTRAHEND)) { 184fe6060f1SDimitry Andric const Symbol *fromSym = r.referent.get<Symbol *>(); 185fe6060f1SDimitry Andric const Reloc &minuend = relocs[++i]; 186fe6060f1SDimitry Andric uint64_t minuendVA; 187fe6060f1SDimitry Andric if (const Symbol *toSym = minuend.referent.dyn_cast<Symbol *>()) 188fe6060f1SDimitry Andric minuendVA = toSym->getVA() + minuend.addend; 189fe6060f1SDimitry Andric else { 190fe6060f1SDimitry Andric auto *referentIsec = minuend.referent.get<InputSection *>(); 191fe6060f1SDimitry Andric assert(!::shouldOmitFromOutput(referentIsec)); 192fe6060f1SDimitry Andric minuendVA = referentIsec->getVA(minuend.addend); 193fe6060f1SDimitry Andric } 194fe6060f1SDimitry Andric referentVA = minuendVA - fromSym->getVA(); 195fe6060f1SDimitry Andric } else if (auto *referentSym = r.referent.dyn_cast<Symbol *>()) { 196fe6060f1SDimitry Andric if (target->hasAttr(r.type, RelocAttrBits::LOAD) && 197fe6060f1SDimitry Andric !referentSym->isInGot()) 198fe6060f1SDimitry Andric target->relaxGotLoad(loc, r.type); 199753f127fSDimitry Andric // For dtrace symbols, do not handle them as normal undefined symbols 200*06c3fb27SDimitry Andric if (referentSym->getName().starts_with("___dtrace_")) { 201753f127fSDimitry Andric // Change dtrace call site to pre-defined instructions 202753f127fSDimitry Andric target->handleDtraceReloc(referentSym, r, loc); 203753f127fSDimitry Andric continue; 204753f127fSDimitry Andric } 205fe6060f1SDimitry Andric referentVA = resolveSymbolVA(referentSym, r.type) + r.addend; 2065ffd83dbSDimitry Andric 207bdd1243dSDimitry Andric if (isThreadLocalVariables(getFlags()) && isa<Defined>(referentSym)) { 208e8d8bef9SDimitry Andric // References from thread-local variable sections are treated as offsets 209e8d8bef9SDimitry Andric // relative to the start of the thread-local data memory area, which 210e8d8bef9SDimitry Andric // is initialized via copying all the TLV data sections (which are all 211e8d8bef9SDimitry Andric // contiguous). 212e8d8bef9SDimitry Andric referentVA -= firstTLVDataSection->addr; 213bdd1243dSDimitry Andric } else if (needsFixup) { 214bdd1243dSDimitry Andric writeChainedFixup(loc, referentSym, r.addend); 215bdd1243dSDimitry Andric continue; 2165ffd83dbSDimitry Andric } 217e8d8bef9SDimitry Andric } else if (auto *referentIsec = r.referent.dyn_cast<InputSection *>()) { 218fe6060f1SDimitry Andric assert(!::shouldOmitFromOutput(referentIsec)); 219fe6060f1SDimitry Andric referentVA = referentIsec->getVA(r.addend); 220bdd1243dSDimitry Andric 221bdd1243dSDimitry Andric if (needsFixup) { 222bdd1243dSDimitry Andric writeChainedRebase(loc, referentVA); 223bdd1243dSDimitry Andric continue; 224bdd1243dSDimitry Andric } 225e8d8bef9SDimitry Andric } 226fe6060f1SDimitry Andric target->relocateOne(loc, r, referentVA, getVA() + r.offset); 227e8d8bef9SDimitry Andric } 22881ad6265SDimitry Andric } 22981ad6265SDimitry Andric 23081ad6265SDimitry Andric ConcatInputSection *macho::makeSyntheticInputSection(StringRef segName, 23181ad6265SDimitry Andric StringRef sectName, 23281ad6265SDimitry Andric uint32_t flags, 23381ad6265SDimitry Andric ArrayRef<uint8_t> data, 23481ad6265SDimitry Andric uint32_t align) { 23581ad6265SDimitry Andric Section §ion = 23681ad6265SDimitry Andric *make<Section>(/*file=*/nullptr, segName, sectName, flags, /*addr=*/0); 23781ad6265SDimitry Andric auto isec = make<ConcatInputSection>(section, data, align); 23881ad6265SDimitry Andric section.subsections.push_back({0, isec}); 23981ad6265SDimitry Andric return isec; 240e8d8bef9SDimitry Andric } 241e8d8bef9SDimitry Andric 242fe6060f1SDimitry Andric void CStringInputSection::splitIntoPieces() { 243fe6060f1SDimitry Andric size_t off = 0; 244fe6060f1SDimitry Andric StringRef s = toStringRef(data); 245fe6060f1SDimitry Andric while (!s.empty()) { 246fe6060f1SDimitry Andric size_t end = s.find(0); 247fe6060f1SDimitry Andric if (end == StringRef::npos) 24881ad6265SDimitry Andric fatal(getLocation(off) + ": string is not null terminated"); 249*06c3fb27SDimitry Andric uint32_t hash = deduplicateLiterals ? xxh3_64bits(s.take_front(end)) : 0; 250fe6060f1SDimitry Andric pieces.emplace_back(off, hash); 251bdd1243dSDimitry Andric size_t size = end + 1; // include null terminator 252fe6060f1SDimitry Andric s = s.substr(size); 253fe6060f1SDimitry Andric off += size; 254fe6060f1SDimitry Andric } 255fe6060f1SDimitry Andric } 256fe6060f1SDimitry Andric 257fe6060f1SDimitry Andric StringPiece &CStringInputSection::getStringPiece(uint64_t off) { 258fe6060f1SDimitry Andric if (off >= data.size()) 259fe6060f1SDimitry Andric fatal(toString(this) + ": offset is outside the section"); 260fe6060f1SDimitry Andric 261fe6060f1SDimitry Andric auto it = 262fe6060f1SDimitry Andric partition_point(pieces, [=](StringPiece p) { return p.inSecOff <= off; }); 263fe6060f1SDimitry Andric return it[-1]; 264fe6060f1SDimitry Andric } 265fe6060f1SDimitry Andric 266fe6060f1SDimitry Andric const StringPiece &CStringInputSection::getStringPiece(uint64_t off) const { 267fe6060f1SDimitry Andric return const_cast<CStringInputSection *>(this)->getStringPiece(off); 268fe6060f1SDimitry Andric } 269fe6060f1SDimitry Andric 270*06c3fb27SDimitry Andric size_t CStringInputSection::getStringPieceIndex(uint64_t off) const { 271*06c3fb27SDimitry Andric if (off >= data.size()) 272*06c3fb27SDimitry Andric fatal(toString(this) + ": offset is outside the section"); 273*06c3fb27SDimitry Andric 274*06c3fb27SDimitry Andric auto it = 275*06c3fb27SDimitry Andric partition_point(pieces, [=](StringPiece p) { return p.inSecOff <= off; }); 276*06c3fb27SDimitry Andric return std::distance(pieces.begin(), it) - 1; 277*06c3fb27SDimitry Andric } 278*06c3fb27SDimitry Andric 279fe6060f1SDimitry Andric uint64_t CStringInputSection::getOffset(uint64_t off) const { 280fe6060f1SDimitry Andric const StringPiece &piece = getStringPiece(off); 281fe6060f1SDimitry Andric uint64_t addend = off - piece.inSecOff; 282fe6060f1SDimitry Andric return piece.outSecOff + addend; 283fe6060f1SDimitry Andric } 284fe6060f1SDimitry Andric 28581ad6265SDimitry Andric WordLiteralInputSection::WordLiteralInputSection(const Section §ion, 286fe6060f1SDimitry Andric ArrayRef<uint8_t> data, 28781ad6265SDimitry Andric uint32_t align) 28881ad6265SDimitry Andric : InputSection(WordLiteralKind, section, data, align) { 28981ad6265SDimitry Andric switch (sectionType(getFlags())) { 290fe6060f1SDimitry Andric case S_4BYTE_LITERALS: 291fe6060f1SDimitry Andric power2LiteralSize = 2; 292fe6060f1SDimitry Andric break; 293fe6060f1SDimitry Andric case S_8BYTE_LITERALS: 294fe6060f1SDimitry Andric power2LiteralSize = 3; 295fe6060f1SDimitry Andric break; 296fe6060f1SDimitry Andric case S_16BYTE_LITERALS: 297fe6060f1SDimitry Andric power2LiteralSize = 4; 298fe6060f1SDimitry Andric break; 299fe6060f1SDimitry Andric default: 300fe6060f1SDimitry Andric llvm_unreachable("invalid literal section type"); 301fe6060f1SDimitry Andric } 302fe6060f1SDimitry Andric 303fe6060f1SDimitry Andric live.resize(data.size() >> power2LiteralSize, !config->deadStrip); 304fe6060f1SDimitry Andric } 305fe6060f1SDimitry Andric 306fe6060f1SDimitry Andric uint64_t WordLiteralInputSection::getOffset(uint64_t off) const { 307fe6060f1SDimitry Andric auto *osec = cast<WordLiteralSection>(parent); 308349cc55cSDimitry Andric const uintptr_t buf = reinterpret_cast<uintptr_t>(data.data()); 309fe6060f1SDimitry Andric switch (sectionType(getFlags())) { 310fe6060f1SDimitry Andric case S_4BYTE_LITERALS: 311349cc55cSDimitry Andric return osec->getLiteral4Offset(buf + (off & ~3LLU)) | (off & 3); 312fe6060f1SDimitry Andric case S_8BYTE_LITERALS: 313349cc55cSDimitry Andric return osec->getLiteral8Offset(buf + (off & ~7LLU)) | (off & 7); 314fe6060f1SDimitry Andric case S_16BYTE_LITERALS: 315349cc55cSDimitry Andric return osec->getLiteral16Offset(buf + (off & ~15LLU)) | (off & 15); 316fe6060f1SDimitry Andric default: 317fe6060f1SDimitry Andric llvm_unreachable("invalid literal section type"); 318fe6060f1SDimitry Andric } 319fe6060f1SDimitry Andric } 320fe6060f1SDimitry Andric 321fe6060f1SDimitry Andric bool macho::isCodeSection(const InputSection *isec) { 322fe6060f1SDimitry Andric uint32_t type = sectionType(isec->getFlags()); 323e8d8bef9SDimitry Andric if (type != S_REGULAR && type != S_COALESCED) 324e8d8bef9SDimitry Andric return false; 325e8d8bef9SDimitry Andric 326fe6060f1SDimitry Andric uint32_t attr = isec->getFlags() & SECTION_ATTRIBUTES_USR; 327e8d8bef9SDimitry Andric if (attr == S_ATTR_PURE_INSTRUCTIONS) 328e8d8bef9SDimitry Andric return true; 329e8d8bef9SDimitry Andric 330fe6060f1SDimitry Andric if (isec->getSegName() == segment_names::text) 331fe6060f1SDimitry Andric return StringSwitch<bool>(isec->getName()) 332fe6060f1SDimitry Andric .Cases(section_names::textCoalNt, section_names::staticInit, true) 333e8d8bef9SDimitry Andric .Default(false); 334e8d8bef9SDimitry Andric 335e8d8bef9SDimitry Andric return false; 336e8d8bef9SDimitry Andric } 337e8d8bef9SDimitry Andric 338fe6060f1SDimitry Andric bool macho::isCfStringSection(const InputSection *isec) { 339fe6060f1SDimitry Andric return isec->getName() == section_names::cfString && 340fe6060f1SDimitry Andric isec->getSegName() == segment_names::data; 341fe6060f1SDimitry Andric } 342fe6060f1SDimitry Andric 34381ad6265SDimitry Andric bool macho::isClassRefsSection(const InputSection *isec) { 34481ad6265SDimitry Andric return isec->getName() == section_names::objcClassRefs && 34581ad6265SDimitry Andric isec->getSegName() == segment_names::data; 34681ad6265SDimitry Andric } 34781ad6265SDimitry Andric 348bdd1243dSDimitry Andric bool macho::isSelRefsSection(const InputSection *isec) { 349bdd1243dSDimitry Andric return isec->getName() == section_names::objcSelrefs && 350bdd1243dSDimitry Andric isec->getSegName() == segment_names::data; 351bdd1243dSDimitry Andric } 352bdd1243dSDimitry Andric 35381ad6265SDimitry Andric bool macho::isEhFrameSection(const InputSection *isec) { 35481ad6265SDimitry Andric return isec->getName() == section_names::ehFrame && 35581ad6265SDimitry Andric isec->getSegName() == segment_names::text; 35681ad6265SDimitry Andric } 35781ad6265SDimitry Andric 358fcaf7f86SDimitry Andric bool macho::isGccExceptTabSection(const InputSection *isec) { 359fcaf7f86SDimitry Andric return isec->getName() == section_names::gccExceptTab && 360fcaf7f86SDimitry Andric isec->getSegName() == segment_names::text; 361fcaf7f86SDimitry Andric } 362fcaf7f86SDimitry Andric 363e8d8bef9SDimitry Andric std::string lld::toString(const InputSection *isec) { 364fe6060f1SDimitry Andric return (toString(isec->getFile()) + ":(" + isec->getName() + ")").str(); 3655ffd83dbSDimitry Andric } 366