xref: /freebsd-src/contrib/llvm-project/lld/MachO/InputSection.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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 &copySym : 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 &section =
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 &section,
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