xref: /llvm-project/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp (revision 2ccf7ed277df28651b94bbee9fccefdf22fb074f)
1 //=--------- MachOLinkGraphBuilder.cpp - MachO LinkGraph builder ----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Generic MachO LinkGraph building code.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "MachOLinkGraphBuilder.h"
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/ADT/Sequence.h"
16 #include <optional>
17 
18 #define DEBUG_TYPE "jitlink"
19 
20 static const char *CommonSectionName = "__common";
21 
22 namespace llvm {
23 namespace jitlink {
24 
25 MachOLinkGraphBuilder::~MachOLinkGraphBuilder() = default;
26 
27 Expected<std::unique_ptr<LinkGraph>> MachOLinkGraphBuilder::buildGraph() {
28 
29   // We only operate on relocatable objects.
30   if (!Obj.isRelocatableObject())
31     return make_error<JITLinkError>("Object is not a relocatable MachO");
32 
33   if (auto Err = createNormalizedSections())
34     return std::move(Err);
35 
36   if (auto Err = createNormalizedSymbols())
37     return std::move(Err);
38 
39   if (auto Err = graphifyRegularSymbols())
40     return std::move(Err);
41 
42   if (auto Err = graphifySectionsWithCustomParsers())
43     return std::move(Err);
44 
45   if (auto Err = addRelocations())
46     return std::move(Err);
47 
48   return std::move(G);
49 }
50 
51 MachOLinkGraphBuilder::MachOLinkGraphBuilder(
52     const object::MachOObjectFile &Obj,
53     std::shared_ptr<orc::SymbolStringPool> SSP, Triple TT,
54     SubtargetFeatures Features,
55     LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
56     : Obj(Obj), G(std::make_unique<LinkGraph>(
57                     std::string(Obj.getFileName()), std::move(SSP),
58                     std::move(TT), std::move(Features), getPointerSize(Obj),
59                     getEndianness(Obj), std::move(GetEdgeKindName))) {
60   auto &MachHeader = Obj.getHeader64();
61   SubsectionsViaSymbols = MachHeader.flags & MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
62 }
63 
64 void MachOLinkGraphBuilder::addCustomSectionParser(
65     StringRef SectionName, SectionParserFunction Parser) {
66   assert(!CustomSectionParserFunctions.count(SectionName) &&
67          "Custom parser for this section already exists");
68   CustomSectionParserFunctions[SectionName] = std::move(Parser);
69 }
70 
71 Linkage MachOLinkGraphBuilder::getLinkage(uint16_t Desc) {
72   if ((Desc & MachO::N_WEAK_DEF) || (Desc & MachO::N_WEAK_REF))
73     return Linkage::Weak;
74   return Linkage::Strong;
75 }
76 
77 Scope MachOLinkGraphBuilder::getScope(StringRef Name, uint8_t Type) {
78   if (Type & MachO::N_EXT) {
79     if ((Type & MachO::N_PEXT) || Name.starts_with("l"))
80       return Scope::Hidden;
81     else
82       return Scope::Default;
83   }
84   return Scope::Local;
85 }
86 
87 bool MachOLinkGraphBuilder::isAltEntry(const NormalizedSymbol &NSym) {
88   return NSym.Desc & MachO::N_ALT_ENTRY;
89 }
90 
91 bool MachOLinkGraphBuilder::isDebugSection(const NormalizedSection &NSec) {
92   return (NSec.Flags & MachO::S_ATTR_DEBUG &&
93           strcmp(NSec.SegName, "__DWARF") == 0);
94 }
95 
96 bool MachOLinkGraphBuilder::isZeroFillSection(const NormalizedSection &NSec) {
97   switch (NSec.Flags & MachO::SECTION_TYPE) {
98   case MachO::S_ZEROFILL:
99   case MachO::S_GB_ZEROFILL:
100   case MachO::S_THREAD_LOCAL_ZEROFILL:
101     return true;
102   default:
103     return false;
104   }
105 }
106 
107 unsigned
108 MachOLinkGraphBuilder::getPointerSize(const object::MachOObjectFile &Obj) {
109   return Obj.is64Bit() ? 8 : 4;
110 }
111 
112 llvm::endianness
113 MachOLinkGraphBuilder::getEndianness(const object::MachOObjectFile &Obj) {
114   return Obj.isLittleEndian() ? llvm::endianness::little
115                               : llvm::endianness::big;
116 }
117 
118 Section &MachOLinkGraphBuilder::getCommonSection() {
119   if (!CommonSection)
120     CommonSection = &G->createSection(CommonSectionName,
121                                       orc::MemProt::Read | orc::MemProt::Write);
122   return *CommonSection;
123 }
124 
125 Error MachOLinkGraphBuilder::createNormalizedSections() {
126   // Build normalized sections. Verifies that section data is in-range (for
127   // sections with content) and that address ranges are non-overlapping.
128 
129   LLVM_DEBUG(dbgs() << "Creating normalized sections...\n");
130 
131   for (auto &SecRef : Obj.sections()) {
132     NormalizedSection NSec;
133     uint32_t DataOffset = 0;
134 
135     auto SecIndex = Obj.getSectionIndex(SecRef.getRawDataRefImpl());
136 
137     if (Obj.is64Bit()) {
138       const MachO::section_64 &Sec64 =
139           Obj.getSection64(SecRef.getRawDataRefImpl());
140 
141       memcpy(&NSec.SectName, &Sec64.sectname, 16);
142       NSec.SectName[16] = '\0';
143       memcpy(&NSec.SegName, Sec64.segname, 16);
144       NSec.SegName[16] = '\0';
145 
146       NSec.Address = orc::ExecutorAddr(Sec64.addr);
147       NSec.Size = Sec64.size;
148       NSec.Alignment = 1ULL << Sec64.align;
149       NSec.Flags = Sec64.flags;
150       DataOffset = Sec64.offset;
151     } else {
152       const MachO::section &Sec32 = Obj.getSection(SecRef.getRawDataRefImpl());
153 
154       memcpy(&NSec.SectName, &Sec32.sectname, 16);
155       NSec.SectName[16] = '\0';
156       memcpy(&NSec.SegName, Sec32.segname, 16);
157       NSec.SegName[16] = '\0';
158 
159       NSec.Address = orc::ExecutorAddr(Sec32.addr);
160       NSec.Size = Sec32.size;
161       NSec.Alignment = 1ULL << Sec32.align;
162       NSec.Flags = Sec32.flags;
163       DataOffset = Sec32.offset;
164     }
165 
166     LLVM_DEBUG({
167       dbgs() << "  " << NSec.SegName << "," << NSec.SectName << ": "
168              << formatv("{0:x16}", NSec.Address) << " -- "
169              << formatv("{0:x16}", NSec.Address + NSec.Size)
170              << ", align: " << NSec.Alignment << ", index: " << SecIndex
171              << "\n";
172     });
173 
174     // Get the section data if any.
175     if (!isZeroFillSection(NSec)) {
176       if (DataOffset + NSec.Size > Obj.getData().size())
177         return make_error<JITLinkError>(
178             "Section data extends past end of file");
179 
180       NSec.Data = Obj.getData().data() + DataOffset;
181     }
182 
183     // Get prot flags.
184     // FIXME: Make sure this test is correct (it's probably missing cases
185     // as-is).
186     orc::MemProt Prot;
187     if (NSec.Flags & MachO::S_ATTR_PURE_INSTRUCTIONS)
188       Prot = orc::MemProt::Read | orc::MemProt::Exec;
189     else
190       Prot = orc::MemProt::Read | orc::MemProt::Write;
191 
192     auto FullyQualifiedName =
193         G->allocateContent(StringRef(NSec.SegName) + "," + NSec.SectName);
194     NSec.GraphSection = &G->createSection(
195         StringRef(FullyQualifiedName.data(), FullyQualifiedName.size()), Prot);
196 
197     // TODO: Are there any other criteria for NoAlloc lifetime?
198     if (NSec.Flags & MachO::S_ATTR_DEBUG)
199       NSec.GraphSection->setMemLifetime(orc::MemLifetime::NoAlloc);
200 
201     IndexToSection.insert(std::make_pair(SecIndex, std::move(NSec)));
202   }
203 
204   std::vector<NormalizedSection *> Sections;
205   Sections.reserve(IndexToSection.size());
206   for (auto &KV : IndexToSection)
207     Sections.push_back(&KV.second);
208 
209   // If we didn't end up creating any sections then bail out. The code below
210   // assumes that we have at least one section.
211   if (Sections.empty())
212     return Error::success();
213 
214   llvm::sort(Sections,
215              [](const NormalizedSection *LHS, const NormalizedSection *RHS) {
216                assert(LHS && RHS && "Null section?");
217                if (LHS->Address != RHS->Address)
218                  return LHS->Address < RHS->Address;
219                return LHS->Size < RHS->Size;
220              });
221 
222   for (unsigned I = 0, E = Sections.size() - 1; I != E; ++I) {
223     auto &Cur = *Sections[I];
224     auto &Next = *Sections[I + 1];
225     if (Next.Address < Cur.Address + Cur.Size)
226       return make_error<JITLinkError>(
227           "Address range for section " +
228           formatv("\"{0}/{1}\" [ {2:x16} -- {3:x16} ] ", Cur.SegName,
229                   Cur.SectName, Cur.Address, Cur.Address + Cur.Size) +
230           "overlaps section \"" + Next.SegName + "/" + Next.SectName + "\"" +
231           formatv("\"{0}/{1}\" [ {2:x16} -- {3:x16} ] ", Next.SegName,
232                   Next.SectName, Next.Address, Next.Address + Next.Size));
233   }
234 
235   return Error::success();
236 }
237 
238 Error MachOLinkGraphBuilder::createNormalizedSymbols() {
239   LLVM_DEBUG(dbgs() << "Creating normalized symbols...\n");
240 
241   for (auto &SymRef : Obj.symbols()) {
242 
243     unsigned SymbolIndex = Obj.getSymbolIndex(SymRef.getRawDataRefImpl());
244     uint64_t Value;
245     uint32_t NStrX;
246     uint8_t Type;
247     uint8_t Sect;
248     uint16_t Desc;
249 
250     if (Obj.is64Bit()) {
251       const MachO::nlist_64 &NL64 =
252           Obj.getSymbol64TableEntry(SymRef.getRawDataRefImpl());
253       Value = NL64.n_value;
254       NStrX = NL64.n_strx;
255       Type = NL64.n_type;
256       Sect = NL64.n_sect;
257       Desc = NL64.n_desc;
258     } else {
259       const MachO::nlist &NL32 =
260           Obj.getSymbolTableEntry(SymRef.getRawDataRefImpl());
261       Value = NL32.n_value;
262       NStrX = NL32.n_strx;
263       Type = NL32.n_type;
264       Sect = NL32.n_sect;
265       Desc = NL32.n_desc;
266     }
267 
268     // Skip stabs.
269     // FIXME: Are there other symbols we should be skipping?
270     if (Type & MachO::N_STAB)
271       continue;
272 
273     std::optional<StringRef> Name;
274     if (NStrX) {
275       if (auto NameOrErr = SymRef.getName())
276         Name = *NameOrErr;
277       else
278         return NameOrErr.takeError();
279     } else if (Type & MachO::N_EXT)
280       return make_error<JITLinkError>("Symbol at index " +
281                                       formatv("{0}", SymbolIndex) +
282                                       " has no name (string table index 0), "
283                                       "but N_EXT bit is set");
284 
285     LLVM_DEBUG({
286       dbgs() << "  ";
287       if (!Name)
288         dbgs() << "<anonymous symbol>";
289       else
290         dbgs() << *Name;
291       dbgs() << ": value = " << formatv("{0:x16}", Value)
292              << ", type = " << formatv("{0:x2}", Type)
293              << ", desc = " << formatv("{0:x4}", Desc) << ", sect = ";
294       if (Sect)
295         dbgs() << static_cast<unsigned>(Sect - 1);
296       else
297         dbgs() << "none";
298       dbgs() << "\n";
299     });
300 
301     // If this symbol has a section, verify that the addresses line up.
302     if (Sect != 0) {
303       auto NSec = findSectionByIndex(Sect - 1);
304       if (!NSec)
305         return NSec.takeError();
306 
307       if (orc::ExecutorAddr(Value) < NSec->Address ||
308           orc::ExecutorAddr(Value) > NSec->Address + NSec->Size)
309         return make_error<JITLinkError>("Address " + formatv("{0:x}", Value) +
310                                         " for symbol " + *Name +
311                                         " does not fall within section");
312 
313       if (!NSec->GraphSection) {
314         LLVM_DEBUG({
315           dbgs() << "  Skipping: Symbol is in section " << NSec->SegName << "/"
316                  << NSec->SectName
317                  << " which has no associated graph section.\n";
318         });
319         continue;
320       }
321     }
322 
323     IndexToSymbol[SymbolIndex] = &createNormalizedSymbol(
324         Name, Value, Type, Sect, Desc, getLinkage(Desc), getScope(*Name, Type));
325   }
326 
327   return Error::success();
328 }
329 
330 void MachOLinkGraphBuilder::addSectionStartSymAndBlock(
331     unsigned SecIndex, Section &GraphSec, orc::ExecutorAddr Address,
332     const char *Data, orc::ExecutorAddrDiff Size, uint32_t Alignment,
333     bool IsLive) {
334   Block &B =
335       Data ? G->createContentBlock(GraphSec, ArrayRef<char>(Data, Size),
336                                    Address, Alignment, 0)
337            : G->createZeroFillBlock(GraphSec, Size, Address, Alignment, 0);
338   auto &Sym = G->addAnonymousSymbol(B, 0, Size, false, IsLive);
339   auto SecI = IndexToSection.find(SecIndex);
340   assert(SecI != IndexToSection.end() && "SecIndex invalid");
341   auto &NSec = SecI->second;
342   assert(!NSec.CanonicalSymbols.count(Sym.getAddress()) &&
343          "Anonymous block start symbol clashes with existing symbol address");
344   NSec.CanonicalSymbols[Sym.getAddress()] = &Sym;
345 }
346 
347 Error MachOLinkGraphBuilder::graphifyRegularSymbols() {
348 
349   LLVM_DEBUG(dbgs() << "Creating graph symbols...\n");
350 
351   /// We only have 256 section indexes: Use a vector rather than a map.
352   std::vector<std::vector<NormalizedSymbol *>> SecIndexToSymbols;
353   SecIndexToSymbols.resize(256);
354 
355   // Create commons, externs, and absolutes, and partition all other symbols by
356   // section.
357   for (auto &KV : IndexToSymbol) {
358     auto &NSym = *KV.second;
359 
360     switch (NSym.Type & MachO::N_TYPE) {
361     case MachO::N_UNDF:
362       if (NSym.Value) {
363         if (!NSym.Name)
364           return make_error<JITLinkError>("Anonymous common symbol at index " +
365                                           Twine(KV.first));
366         NSym.GraphSymbol = &G->addDefinedSymbol(
367             G->createZeroFillBlock(getCommonSection(),
368                                    orc::ExecutorAddrDiff(NSym.Value),
369                                    orc::ExecutorAddr(),
370                                    1ull << MachO::GET_COMM_ALIGN(NSym.Desc), 0),
371             0, *NSym.Name, orc::ExecutorAddrDiff(NSym.Value), Linkage::Weak,
372             NSym.S, false, NSym.Desc & MachO::N_NO_DEAD_STRIP);
373       } else {
374         if (!NSym.Name)
375           return make_error<JITLinkError>("Anonymous external symbol at "
376                                           "index " +
377                                           Twine(KV.first));
378         NSym.GraphSymbol = &G->addExternalSymbol(
379             *NSym.Name, 0, (NSym.Desc & MachO::N_WEAK_REF) != 0);
380       }
381       break;
382     case MachO::N_ABS:
383       if (!NSym.Name)
384         return make_error<JITLinkError>("Anonymous absolute symbol at index " +
385                                         Twine(KV.first));
386       NSym.GraphSymbol = &G->addAbsoluteSymbol(
387           *NSym.Name, orc::ExecutorAddr(NSym.Value), 0, Linkage::Strong,
388           getScope(*NSym.Name, NSym.Type), NSym.Desc & MachO::N_NO_DEAD_STRIP);
389       break;
390     case MachO::N_SECT:
391       SecIndexToSymbols[NSym.Sect - 1].push_back(&NSym);
392       break;
393     case MachO::N_PBUD:
394       return make_error<JITLinkError>(
395           "Unupported N_PBUD symbol " +
396           (NSym.Name ? ("\"" + *NSym.Name + "\"") : Twine("<anon>")) +
397           " at index " + Twine(KV.first));
398     case MachO::N_INDR:
399       return make_error<JITLinkError>(
400           "Unupported N_INDR symbol " +
401           (NSym.Name ? ("\"" + *NSym.Name + "\"") : Twine("<anon>")) +
402           " at index " + Twine(KV.first));
403     default:
404       return make_error<JITLinkError>(
405           "Unrecognized symbol type " + Twine(NSym.Type & MachO::N_TYPE) +
406           " for symbol " +
407           (NSym.Name ? ("\"" + *NSym.Name + "\"") : Twine("<anon>")) +
408           " at index " + Twine(KV.first));
409     }
410   }
411 
412   // Loop over sections performing regular graphification for those that
413   // don't have custom parsers.
414   for (auto &KV : IndexToSection) {
415     auto SecIndex = KV.first;
416     auto &NSec = KV.second;
417 
418     if (!NSec.GraphSection) {
419       LLVM_DEBUG({
420         dbgs() << "  " << NSec.SegName << "/" << NSec.SectName
421                << " has no graph section. Skipping.\n";
422       });
423       continue;
424     }
425 
426     // Skip sections with custom parsers.
427     if (CustomSectionParserFunctions.count(NSec.GraphSection->getName())) {
428       LLVM_DEBUG({
429         dbgs() << "  Skipping section " << NSec.GraphSection->getName()
430                << " as it has a custom parser.\n";
431       });
432       continue;
433     } else if ((NSec.Flags & MachO::SECTION_TYPE) ==
434                MachO::S_CSTRING_LITERALS) {
435       if (auto Err = graphifyCStringSection(
436               NSec, std::move(SecIndexToSymbols[SecIndex])))
437         return Err;
438       continue;
439     } else
440       LLVM_DEBUG({
441         dbgs() << "  Graphifying regular section "
442                << NSec.GraphSection->getName() << "...\n";
443       });
444 
445     bool SectionIsNoDeadStrip = NSec.Flags & MachO::S_ATTR_NO_DEAD_STRIP;
446     bool SectionIsText = NSec.Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
447 
448     auto &SecNSymStack = SecIndexToSymbols[SecIndex];
449 
450     // If this section is non-empty but there are no symbols covering it then
451     // create one block and anonymous symbol to cover the entire section.
452     if (SecNSymStack.empty()) {
453       if (NSec.Size > 0) {
454         LLVM_DEBUG({
455           dbgs() << "    Section non-empty, but contains no symbols. "
456                     "Creating anonymous block to cover "
457                  << formatv("{0:x16}", NSec.Address) << " -- "
458                  << formatv("{0:x16}", NSec.Address + NSec.Size) << "\n";
459         });
460         addSectionStartSymAndBlock(SecIndex, *NSec.GraphSection, NSec.Address,
461                                    NSec.Data, NSec.Size, NSec.Alignment,
462                                    SectionIsNoDeadStrip);
463       } else
464         LLVM_DEBUG({
465           dbgs() << "    Section empty and contains no symbols. Skipping.\n";
466         });
467       continue;
468     }
469 
470     // Sort the symbol stack in by address, alt-entry status, scope, and name.
471     // We sort in reverse order so that symbols will be visited in the right
472     // order when we pop off the stack below.
473     llvm::sort(SecNSymStack, [](const NormalizedSymbol *LHS,
474                                 const NormalizedSymbol *RHS) {
475       if (LHS->Value != RHS->Value)
476         return LHS->Value > RHS->Value;
477       if (isAltEntry(*LHS) != isAltEntry(*RHS))
478         return isAltEntry(*RHS);
479       if (LHS->S != RHS->S)
480         return static_cast<uint8_t>(LHS->S) < static_cast<uint8_t>(RHS->S);
481       return LHS->Name < RHS->Name;
482     });
483 
484     // The first symbol in a section can not be an alt-entry symbol.
485     if (!SecNSymStack.empty() && isAltEntry(*SecNSymStack.back()))
486       return make_error<JITLinkError>(
487           "First symbol in " + NSec.GraphSection->getName() + " is alt-entry");
488 
489     // If the section is non-empty but there is no symbol covering the start
490     // address then add an anonymous one.
491     if (orc::ExecutorAddr(SecNSymStack.back()->Value) != NSec.Address) {
492       auto AnonBlockSize =
493           orc::ExecutorAddr(SecNSymStack.back()->Value) - NSec.Address;
494       LLVM_DEBUG({
495         dbgs() << "    Section start not covered by symbol. "
496                << "Creating anonymous block to cover [ " << NSec.Address
497                << " -- " << (NSec.Address + AnonBlockSize) << " ]\n";
498       });
499       addSectionStartSymAndBlock(SecIndex, *NSec.GraphSection, NSec.Address,
500                                  NSec.Data, AnonBlockSize, NSec.Alignment,
501                                  SectionIsNoDeadStrip);
502     }
503 
504     // Visit section symbols in order by popping off the reverse-sorted stack,
505     // building graph symbols as we go.
506     //
507     // If MH_SUBSECTIONS_VIA_SYMBOLS is set we'll build a block for each
508     // alt-entry chain.
509     //
510     // If MH_SUBSECTIONS_VIA_SYMBOLS is not set then we'll just build one block
511     // for the whole section.
512     while (!SecNSymStack.empty()) {
513       SmallVector<NormalizedSymbol *, 8> BlockSyms;
514 
515       // Get the symbols in this alt-entry chain, or the whole section (if
516       // !SubsectionsViaSymbols).
517       BlockSyms.push_back(SecNSymStack.back());
518       SecNSymStack.pop_back();
519       while (!SecNSymStack.empty() &&
520              (isAltEntry(*SecNSymStack.back()) ||
521               SecNSymStack.back()->Value == BlockSyms.back()->Value ||
522              !SubsectionsViaSymbols)) {
523         BlockSyms.push_back(SecNSymStack.back());
524         SecNSymStack.pop_back();
525       }
526 
527       // BlockNSyms now contains the block symbols in reverse canonical order.
528       auto BlockStart = orc::ExecutorAddr(BlockSyms.front()->Value);
529       orc::ExecutorAddr BlockEnd =
530           SecNSymStack.empty() ? NSec.Address + NSec.Size
531                                : orc::ExecutorAddr(SecNSymStack.back()->Value);
532       orc::ExecutorAddrDiff BlockOffset = BlockStart - NSec.Address;
533       orc::ExecutorAddrDiff BlockSize = BlockEnd - BlockStart;
534 
535       LLVM_DEBUG({
536         dbgs() << "    Creating block for " << formatv("{0:x16}", BlockStart)
537                << " -- " << formatv("{0:x16}", BlockEnd) << ": "
538                << NSec.GraphSection->getName() << " + "
539                << formatv("{0:x16}", BlockOffset) << " with "
540                << BlockSyms.size() << " symbol(s)...\n";
541       });
542 
543       Block &B =
544           NSec.Data
545               ? G->createContentBlock(
546                     *NSec.GraphSection,
547                     ArrayRef<char>(NSec.Data + BlockOffset, BlockSize),
548                     BlockStart, NSec.Alignment, BlockStart % NSec.Alignment)
549               : G->createZeroFillBlock(*NSec.GraphSection, BlockSize,
550                                        BlockStart, NSec.Alignment,
551                                        BlockStart % NSec.Alignment);
552 
553       std::optional<orc::ExecutorAddr> LastCanonicalAddr;
554       auto SymEnd = BlockEnd;
555       while (!BlockSyms.empty()) {
556         auto &NSym = *BlockSyms.back();
557         BlockSyms.pop_back();
558 
559         bool SymLive =
560             (NSym.Desc & MachO::N_NO_DEAD_STRIP) || SectionIsNoDeadStrip;
561 
562         auto &Sym = createStandardGraphSymbol(
563             NSym, B, SymEnd - orc::ExecutorAddr(NSym.Value), SectionIsText,
564             SymLive, LastCanonicalAddr != orc::ExecutorAddr(NSym.Value));
565 
566         if (LastCanonicalAddr != Sym.getAddress()) {
567           if (LastCanonicalAddr)
568             SymEnd = *LastCanonicalAddr;
569           LastCanonicalAddr = Sym.getAddress();
570         }
571       }
572     }
573   }
574 
575   return Error::success();
576 }
577 
578 Symbol &MachOLinkGraphBuilder::createStandardGraphSymbol(NormalizedSymbol &NSym,
579                                                          Block &B, size_t Size,
580                                                          bool IsText,
581                                                          bool IsNoDeadStrip,
582                                                          bool IsCanonical) {
583 
584   LLVM_DEBUG({
585     dbgs() << "      " << formatv("{0:x16}", NSym.Value) << " -- "
586            << formatv("{0:x16}", NSym.Value + Size) << ": ";
587     if (!NSym.Name)
588       dbgs() << "<anonymous symbol>";
589     else
590       dbgs() << *NSym.Name;
591     if (IsText)
592       dbgs() << " [text]";
593     if (IsNoDeadStrip)
594       dbgs() << " [no-dead-strip]";
595     if (!IsCanonical)
596       dbgs() << " [non-canonical]";
597     dbgs() << "\n";
598   });
599 
600   auto SymOffset = orc::ExecutorAddr(NSym.Value) - B.getAddress();
601   auto &Sym =
602       NSym.Name
603           ? G->addDefinedSymbol(B, SymOffset, *NSym.Name, Size, NSym.L, NSym.S,
604                                 IsText, IsNoDeadStrip)
605           : G->addAnonymousSymbol(B, SymOffset, Size, IsText, IsNoDeadStrip);
606   NSym.GraphSymbol = &Sym;
607 
608   if (IsCanonical)
609     setCanonicalSymbol(getSectionByIndex(NSym.Sect - 1), Sym);
610 
611   return Sym;
612 }
613 
614 Error MachOLinkGraphBuilder::graphifySectionsWithCustomParsers() {
615   // Graphify special sections.
616   for (auto &KV : IndexToSection) {
617     auto &NSec = KV.second;
618 
619     // Skip non-graph sections.
620     if (!NSec.GraphSection)
621       continue;
622 
623     auto HI = CustomSectionParserFunctions.find(NSec.GraphSection->getName());
624     if (HI != CustomSectionParserFunctions.end()) {
625       auto &Parse = HI->second;
626       if (auto Err = Parse(NSec))
627         return Err;
628     }
629   }
630 
631   return Error::success();
632 }
633 
634 Error MachOLinkGraphBuilder::graphifyCStringSection(
635     NormalizedSection &NSec, std::vector<NormalizedSymbol *> NSyms) {
636   assert(NSec.GraphSection && "C string literal section missing graph section");
637   assert(NSec.Data && "C string literal section has no data");
638 
639   LLVM_DEBUG({
640     dbgs() << "  Graphifying C-string literal section "
641            << NSec.GraphSection->getName() << "\n";
642   });
643 
644   if (NSec.Data[NSec.Size - 1] != '\0')
645     return make_error<JITLinkError>("C string literal section " +
646                                     NSec.GraphSection->getName() +
647                                     " does not end with null terminator");
648 
649   /// Sort into reverse order to use as a stack.
650   llvm::sort(NSyms,
651              [](const NormalizedSymbol *LHS, const NormalizedSymbol *RHS) {
652                if (LHS->Value != RHS->Value)
653                  return LHS->Value > RHS->Value;
654                if (LHS->L != RHS->L)
655                  return LHS->L > RHS->L;
656                if (LHS->S != RHS->S)
657                  return LHS->S > RHS->S;
658                if (RHS->Name) {
659                  if (!LHS->Name)
660                    return true;
661                  return *LHS->Name > *RHS->Name;
662                }
663                return false;
664              });
665 
666   bool SectionIsNoDeadStrip = NSec.Flags & MachO::S_ATTR_NO_DEAD_STRIP;
667   bool SectionIsText = NSec.Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
668   orc::ExecutorAddrDiff BlockStart = 0;
669 
670   // Scan section for null characters.
671   for (size_t I = 0; I != NSec.Size; ++I) {
672     if (NSec.Data[I] == '\0') {
673       size_t BlockSize = I + 1 - BlockStart;
674       // Create a block for this null terminated string.
675       auto &B = G->createContentBlock(*NSec.GraphSection,
676                                       {NSec.Data + BlockStart, BlockSize},
677                                       NSec.Address + BlockStart, NSec.Alignment,
678                                       BlockStart % NSec.Alignment);
679 
680       LLVM_DEBUG({
681         dbgs() << "    Created block " << B.getRange()
682                << ", align = " << B.getAlignment()
683                << ", align-ofs = " << B.getAlignmentOffset() << " for \"";
684         for (size_t J = 0; J != std::min(B.getSize(), size_t(16)); ++J)
685           switch (B.getContent()[J]) {
686           case '\0': break;
687           case '\n': dbgs() << "\\n"; break;
688           case '\t': dbgs() << "\\t"; break;
689           default:   dbgs() << B.getContent()[J]; break;
690           }
691         if (B.getSize() > 16)
692           dbgs() << "...";
693         dbgs() << "\"\n";
694       });
695 
696       // If there's no symbol at the start of this block then create one.
697       if (NSyms.empty() ||
698           orc::ExecutorAddr(NSyms.back()->Value) != B.getAddress()) {
699         auto &S = G->addAnonymousSymbol(B, 0, BlockSize, false, false);
700         setCanonicalSymbol(NSec, S);
701         LLVM_DEBUG({
702           dbgs() << "      Adding symbol for c-string block " << B.getRange()
703                  << ": <anonymous symbol> at offset 0\n";
704         });
705       }
706 
707       // Process any remaining symbols that point into this block.
708       auto LastCanonicalAddr = B.getAddress() + BlockSize;
709       while (!NSyms.empty() && orc::ExecutorAddr(NSyms.back()->Value) <
710                                    B.getAddress() + BlockSize) {
711         auto &NSym = *NSyms.back();
712         size_t SymSize = (B.getAddress() + BlockSize) -
713                          orc::ExecutorAddr(NSyms.back()->Value);
714         bool SymLive =
715             (NSym.Desc & MachO::N_NO_DEAD_STRIP) || SectionIsNoDeadStrip;
716 
717         bool IsCanonical = false;
718         if (LastCanonicalAddr != orc::ExecutorAddr(NSym.Value)) {
719           IsCanonical = true;
720           LastCanonicalAddr = orc::ExecutorAddr(NSym.Value);
721         }
722 
723         auto &Sym = createStandardGraphSymbol(NSym, B, SymSize, SectionIsText,
724                                               SymLive, IsCanonical);
725         (void)Sym;
726         LLVM_DEBUG({
727           dbgs() << "      Adding symbol for c-string block " << B.getRange()
728                  << ": "
729                  << (Sym.hasName() ? *Sym.getName() : "<anonymous symbol>")
730                  << " at offset " << formatv("{0:x}", Sym.getOffset()) << "\n";
731         });
732 
733         NSyms.pop_back();
734       }
735 
736       BlockStart += BlockSize;
737     }
738   }
739 
740   assert(llvm::all_of(NSec.GraphSection->blocks(),
741                       [](Block *B) { return isCStringBlock(*B); }) &&
742          "All blocks in section should hold single c-strings");
743 
744   return Error::success();
745 }
746 
747 Error CompactUnwindSplitter::operator()(LinkGraph &G) {
748   auto *CUSec = G.findSectionByName(CompactUnwindSectionName);
749   if (!CUSec)
750     return Error::success();
751 
752   if (!G.getTargetTriple().isOSBinFormatMachO())
753     return make_error<JITLinkError>(
754         "Error linking " + G.getName() +
755         ": compact unwind splitting not supported on non-macho target " +
756         G.getTargetTriple().str());
757 
758   unsigned CURecordSize = 0;
759   unsigned PersonalityEdgeOffset = 0;
760   unsigned LSDAEdgeOffset = 0;
761   switch (G.getTargetTriple().getArch()) {
762   case Triple::aarch64:
763   case Triple::x86_64:
764     // 64-bit compact-unwind record format:
765     // Range start: 8 bytes.
766     // Range size:  4 bytes.
767     // CU encoding: 4 bytes.
768     // Personality: 8 bytes.
769     // LSDA:        8 bytes.
770     CURecordSize = 32;
771     PersonalityEdgeOffset = 16;
772     LSDAEdgeOffset = 24;
773     break;
774   default:
775     return make_error<JITLinkError>(
776         "Error linking " + G.getName() +
777         ": compact unwind splitting not supported on " +
778         G.getTargetTriple().getArchName());
779   }
780 
781   std::vector<Block *> OriginalBlocks(CUSec->blocks().begin(),
782                                       CUSec->blocks().end());
783   LLVM_DEBUG({
784     dbgs() << "In " << G.getName() << " splitting compact unwind section "
785            << CompactUnwindSectionName << " containing "
786            << OriginalBlocks.size() << " initial blocks...\n";
787   });
788 
789   while (!OriginalBlocks.empty()) {
790     auto *B = OriginalBlocks.back();
791     OriginalBlocks.pop_back();
792 
793     if (B->getSize() == 0) {
794       LLVM_DEBUG({
795         dbgs() << "  Skipping empty block at "
796                << formatv("{0:x16}", B->getAddress()) << "\n";
797       });
798       continue;
799     }
800 
801     unsigned NumBlocks = B->getSize() / CURecordSize;
802 
803     LLVM_DEBUG({
804       dbgs() << "  Splitting block at " << formatv("{0:x16}", B->getAddress())
805              << " into " << NumBlocks << " compact unwind record(s)\n";
806     });
807 
808     if (B->getSize() % CURecordSize)
809       return make_error<JITLinkError>(
810           "Error splitting compact unwind record in " + G.getName() +
811           ": block at " + formatv("{0:x}", B->getAddress()) + " has size " +
812           formatv("{0:x}", B->getSize()) +
813           " (not a multiple of CU record size of " +
814           formatv("{0:x}", CURecordSize) + ")");
815 
816     auto Blocks =
817         G.splitBlock(*B, map_range(seq(1U, NumBlocks), [=](Edge::OffsetT Idx) {
818           return Idx * CURecordSize;
819         }));
820 
821     for (auto *CURec : Blocks) {
822       bool AddedKeepAlive = false;
823 
824       for (auto &E : CURec->edges()) {
825         if (E.getOffset() == 0) {
826           LLVM_DEBUG({
827             dbgs() << "    Updating compact unwind record at "
828                    << CURec->getAddress() << " to point to "
829                    << (E.getTarget().hasName() ? *E.getTarget().getName()
830                                                : StringRef())
831                    << " (at " << E.getTarget().getAddress() << ")\n";
832           });
833 
834           if (E.getTarget().isExternal())
835             return make_error<JITLinkError>(
836                 "Error adding keep-alive edge for compact unwind record at " +
837                 formatv("{0:x}", CURec->getAddress()) + ": target " +
838                 *E.getTarget().getName() + " is an external symbol");
839           auto &TgtBlock = E.getTarget().getBlock();
840           auto &CURecSym =
841               G.addAnonymousSymbol(*CURec, 0, CURecordSize, false, false);
842           TgtBlock.addEdge(Edge::KeepAlive, 0, CURecSym, 0);
843           AddedKeepAlive = true;
844         } else if (E.getOffset() != PersonalityEdgeOffset &&
845                    E.getOffset() != LSDAEdgeOffset)
846           return make_error<JITLinkError>(
847               "Unexpected edge at offset " + formatv("{0:x}", E.getOffset()) +
848               " in compact unwind record at " +
849               formatv("{0:x}", CURec->getAddress()));
850       }
851 
852       if (!AddedKeepAlive)
853         return make_error<JITLinkError>(
854             "Error adding keep-alive edge for compact unwind record at " +
855             formatv("{0:x}", CURec->getAddress()) +
856             ": no outgoing target edge at offset 0");
857     }
858   }
859 
860   return Error::success();
861 }
862 
863 } // end namespace jitlink
864 } // end namespace llvm
865