1353940Sdim//=--------- MachOLinkGraphBuilder.cpp - MachO LinkGraph builder ----------===//
2353940Sdim//
3353940Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353940Sdim// See https://llvm.org/LICENSE.txt for license information.
5353940Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6353940Sdim//
7353940Sdim//===----------------------------------------------------------------------===//
8353940Sdim//
9353940Sdim// Generic MachO LinkGraph buliding code.
10353940Sdim//
11353940Sdim//===----------------------------------------------------------------------===//
12353940Sdim
13353940Sdim#include "MachOLinkGraphBuilder.h"
14353940Sdim
15353940Sdim#define DEBUG_TYPE "jitlink"
16353940Sdim
17353940Sdimstatic const char *CommonSectionName = "__common";
18353940Sdim
19353940Sdimnamespace llvm {
20353940Sdimnamespace jitlink {
21353940Sdim
22353940SdimMachOLinkGraphBuilder::~MachOLinkGraphBuilder() {}
23353940Sdim
24353940SdimExpected<std::unique_ptr<LinkGraph>> MachOLinkGraphBuilder::buildGraph() {
25353940Sdim
26353940Sdim  // Sanity check: we only operate on relocatable objects.
27353940Sdim  if (!Obj.isRelocatableObject())
28353940Sdim    return make_error<JITLinkError>("Object is not a relocatable MachO");
29353940Sdim
30353940Sdim  if (auto Err = createNormalizedSections())
31353940Sdim    return std::move(Err);
32353940Sdim
33353940Sdim  if (auto Err = createNormalizedSymbols())
34353940Sdim    return std::move(Err);
35353940Sdim
36353940Sdim  if (auto Err = graphifyRegularSymbols())
37353940Sdim    return std::move(Err);
38353940Sdim
39353940Sdim  if (auto Err = graphifySectionsWithCustomParsers())
40353940Sdim    return std::move(Err);
41353940Sdim
42353940Sdim  if (auto Err = addRelocations())
43353940Sdim    return std::move(Err);
44353940Sdim
45353940Sdim  return std::move(G);
46353940Sdim}
47353940Sdim
48353940SdimMachOLinkGraphBuilder::MachOLinkGraphBuilder(const object::MachOObjectFile &Obj)
49353940Sdim    : Obj(Obj),
50353940Sdim      G(std::make_unique<LinkGraph>(Obj.getFileName(), getPointerSize(Obj),
51353940Sdim                                    getEndianness(Obj))) {}
52353940Sdim
53353940Sdimvoid MachOLinkGraphBuilder::addCustomSectionParser(
54353940Sdim    StringRef SectionName, SectionParserFunction Parser) {
55353940Sdim  assert(!CustomSectionParserFunctions.count(SectionName) &&
56353940Sdim         "Custom parser for this section already exists");
57353940Sdim  CustomSectionParserFunctions[SectionName] = std::move(Parser);
58353940Sdim}
59353940Sdim
60353940SdimLinkage MachOLinkGraphBuilder::getLinkage(uint16_t Desc) {
61353940Sdim  if ((Desc & MachO::N_WEAK_DEF) || (Desc & MachO::N_WEAK_REF))
62353940Sdim    return Linkage::Weak;
63353940Sdim  return Linkage::Strong;
64353940Sdim}
65353940Sdim
66353940SdimScope MachOLinkGraphBuilder::getScope(StringRef Name, uint8_t Type) {
67353940Sdim  if (Name.startswith("l"))
68353940Sdim    return Scope::Local;
69353940Sdim  if (Type & MachO::N_PEXT)
70353940Sdim    return Scope::Hidden;
71353940Sdim  if (Type & MachO::N_EXT)
72353940Sdim    return Scope::Default;
73353940Sdim  return Scope::Local;
74353940Sdim}
75353940Sdim
76353940Sdimbool MachOLinkGraphBuilder::isAltEntry(const NormalizedSymbol &NSym) {
77353940Sdim  return NSym.Desc & MachO::N_ALT_ENTRY;
78353940Sdim}
79353940Sdim
80353940Sdimunsigned
81353940SdimMachOLinkGraphBuilder::getPointerSize(const object::MachOObjectFile &Obj) {
82353940Sdim  return Obj.is64Bit() ? 8 : 4;
83353940Sdim}
84353940Sdim
85353940Sdimsupport::endianness
86353940SdimMachOLinkGraphBuilder::getEndianness(const object::MachOObjectFile &Obj) {
87353940Sdim  return Obj.isLittleEndian() ? support::little : support::big;
88353940Sdim}
89353940Sdim
90353940SdimSection &MachOLinkGraphBuilder::getCommonSection() {
91353940Sdim  if (!CommonSection) {
92353940Sdim    auto Prot = static_cast<sys::Memory::ProtectionFlags>(
93353940Sdim        sys::Memory::MF_READ | sys::Memory::MF_WRITE);
94353940Sdim    CommonSection = &G->createSection(CommonSectionName, Prot);
95353940Sdim  }
96353940Sdim  return *CommonSection;
97353940Sdim}
98353940Sdim
99353940SdimError MachOLinkGraphBuilder::createNormalizedSections() {
100353940Sdim  // Build normalized sections. Verifies that section data is in-range (for
101353940Sdim  // sections with content) and that address ranges are non-overlapping.
102353940Sdim
103353940Sdim  LLVM_DEBUG(dbgs() << "Creating normalized sections...\n");
104353940Sdim
105353940Sdim  for (auto &SecRef : Obj.sections()) {
106353940Sdim    NormalizedSection NSec;
107353940Sdim    uint32_t DataOffset = 0;
108353940Sdim
109353940Sdim    auto SecIndex = Obj.getSectionIndex(SecRef.getRawDataRefImpl());
110353940Sdim
111353940Sdim    auto Name = SecRef.getName();
112353940Sdim    if (!Name)
113353940Sdim      return Name.takeError();
114353940Sdim
115353940Sdim    if (Obj.is64Bit()) {
116353940Sdim      const MachO::section_64 &Sec64 =
117353940Sdim          Obj.getSection64(SecRef.getRawDataRefImpl());
118353940Sdim
119353940Sdim      NSec.Address = Sec64.addr;
120353940Sdim      NSec.Size = Sec64.size;
121353940Sdim      NSec.Alignment = 1ULL << Sec64.align;
122353940Sdim      NSec.Flags = Sec64.flags;
123353940Sdim      DataOffset = Sec64.offset;
124353940Sdim    } else {
125353940Sdim      const MachO::section &Sec32 = Obj.getSection(SecRef.getRawDataRefImpl());
126353940Sdim      NSec.Address = Sec32.addr;
127353940Sdim      NSec.Size = Sec32.size;
128353940Sdim      NSec.Alignment = 1ULL << Sec32.align;
129353940Sdim      NSec.Flags = Sec32.flags;
130353940Sdim      DataOffset = Sec32.offset;
131353940Sdim    }
132353940Sdim
133353940Sdim    LLVM_DEBUG({
134353940Sdim      dbgs() << "  " << *Name << ": " << formatv("{0:x16}", NSec.Address)
135353940Sdim             << " -- " << formatv("{0:x16}", NSec.Address + NSec.Size)
136353940Sdim             << ", align: " << NSec.Alignment << ", index: " << SecIndex
137353940Sdim             << "\n";
138353940Sdim    });
139353940Sdim
140353940Sdim    // Get the section data if any.
141353940Sdim    {
142353940Sdim      unsigned SectionType = NSec.Flags & MachO::SECTION_TYPE;
143353940Sdim      if (SectionType != MachO::S_ZEROFILL &&
144353940Sdim          SectionType != MachO::S_GB_ZEROFILL) {
145353940Sdim
146353940Sdim        if (DataOffset + NSec.Size > Obj.getData().size())
147353940Sdim          return make_error<JITLinkError>(
148353940Sdim              "Section data extends past end of file");
149353940Sdim
150353940Sdim        NSec.Data = Obj.getData().data() + DataOffset;
151353940Sdim      }
152353940Sdim    }
153353940Sdim
154353940Sdim    // Get prot flags.
155353940Sdim    // FIXME: Make sure this test is correct (it's probably missing cases
156353940Sdim    // as-is).
157353940Sdim    sys::Memory::ProtectionFlags Prot;
158353940Sdim    if (NSec.Flags & MachO::S_ATTR_PURE_INSTRUCTIONS)
159353940Sdim      Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
160353940Sdim                                                       sys::Memory::MF_EXEC);
161353940Sdim    else
162353940Sdim      Prot = static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
163353940Sdim                                                       sys::Memory::MF_WRITE);
164353940Sdim
165353940Sdim    NSec.GraphSection = &G->createSection(*Name, Prot);
166353940Sdim    IndexToSection.insert(std::make_pair(SecIndex, std::move(NSec)));
167353940Sdim  }
168353940Sdim
169353940Sdim  std::vector<NormalizedSection *> Sections;
170353940Sdim  Sections.reserve(IndexToSection.size());
171353940Sdim  for (auto &KV : IndexToSection)
172353940Sdim    Sections.push_back(&KV.second);
173353940Sdim
174353940Sdim  // If we didn't end up creating any sections then bail out. The code below
175353940Sdim  // assumes that we have at least one section.
176353940Sdim  if (Sections.empty())
177353940Sdim    return Error::success();
178353940Sdim
179353940Sdim  llvm::sort(Sections,
180353940Sdim             [](const NormalizedSection *LHS, const NormalizedSection *RHS) {
181353940Sdim               assert(LHS && RHS && "Null section?");
182357095Sdim               if (LHS->Address != RHS->Address)
183357095Sdim                 return LHS->Address < RHS->Address;
184357095Sdim               return LHS->Size < RHS->Size;
185353940Sdim             });
186353940Sdim
187353940Sdim  for (unsigned I = 0, E = Sections.size() - 1; I != E; ++I) {
188353940Sdim    auto &Cur = *Sections[I];
189353940Sdim    auto &Next = *Sections[I + 1];
190353940Sdim    if (Next.Address < Cur.Address + Cur.Size)
191353940Sdim      return make_error<JITLinkError>(
192353940Sdim          "Address range for section " + Cur.GraphSection->getName() +
193353940Sdim          formatv(" [ {0:x16} -- {1:x16} ] ", Cur.Address,
194353940Sdim                  Cur.Address + Cur.Size) +
195353940Sdim          "overlaps " +
196353940Sdim          formatv(" [ {0:x16} -- {1:x16} ] ", Next.Address,
197353940Sdim                  Next.Address + Next.Size));
198353940Sdim  }
199353940Sdim
200353940Sdim  return Error::success();
201353940Sdim}
202353940Sdim
203353940SdimError MachOLinkGraphBuilder::createNormalizedSymbols() {
204353940Sdim  LLVM_DEBUG(dbgs() << "Creating normalized symbols...\n");
205353940Sdim
206353940Sdim  for (auto &SymRef : Obj.symbols()) {
207353940Sdim
208353940Sdim    unsigned SymbolIndex = Obj.getSymbolIndex(SymRef.getRawDataRefImpl());
209353940Sdim    uint64_t Value;
210353940Sdim    uint32_t NStrX;
211353940Sdim    uint8_t Type;
212353940Sdim    uint8_t Sect;
213353940Sdim    uint16_t Desc;
214353940Sdim
215353940Sdim    if (Obj.is64Bit()) {
216353940Sdim      const MachO::nlist_64 &NL64 =
217353940Sdim          Obj.getSymbol64TableEntry(SymRef.getRawDataRefImpl());
218353940Sdim      Value = NL64.n_value;
219353940Sdim      NStrX = NL64.n_strx;
220353940Sdim      Type = NL64.n_type;
221353940Sdim      Sect = NL64.n_sect;
222353940Sdim      Desc = NL64.n_desc;
223353940Sdim    } else {
224353940Sdim      const MachO::nlist &NL32 =
225353940Sdim          Obj.getSymbolTableEntry(SymRef.getRawDataRefImpl());
226353940Sdim      Value = NL32.n_value;
227353940Sdim      NStrX = NL32.n_strx;
228353940Sdim      Type = NL32.n_type;
229353940Sdim      Sect = NL32.n_sect;
230353940Sdim      Desc = NL32.n_desc;
231353940Sdim    }
232353940Sdim
233353940Sdim    // Skip stabs.
234353940Sdim    // FIXME: Are there other symbols we should be skipping?
235353940Sdim    if (Type & MachO::N_STAB)
236353940Sdim      continue;
237353940Sdim
238353940Sdim    Optional<StringRef> Name;
239353940Sdim    if (NStrX) {
240353940Sdim      if (auto NameOrErr = SymRef.getName())
241353940Sdim        Name = *NameOrErr;
242353940Sdim      else
243353940Sdim        return NameOrErr.takeError();
244353940Sdim    }
245353940Sdim
246353940Sdim    LLVM_DEBUG({
247353940Sdim      dbgs() << "  ";
248353940Sdim      if (!Name)
249353940Sdim        dbgs() << "<anonymous symbol>";
250353940Sdim      else
251353940Sdim        dbgs() << *Name;
252353940Sdim      dbgs() << ": value = " << formatv("{0:x16}", Value)
253353940Sdim             << ", type = " << formatv("{0:x2}", Type)
254353940Sdim             << ", desc = " << formatv("{0:x4}", Desc) << ", sect = ";
255353940Sdim      if (Sect)
256353940Sdim        dbgs() << static_cast<unsigned>(Sect - 1);
257353940Sdim      else
258353940Sdim        dbgs() << "none";
259353940Sdim      dbgs() << "\n";
260353940Sdim    });
261353940Sdim
262353940Sdim    // If this symbol has a section, sanity check that the addresses line up.
263353940Sdim    NormalizedSection *NSec = nullptr;
264353940Sdim    if (Sect != 0) {
265353940Sdim      if (auto NSecOrErr = findSectionByIndex(Sect - 1))
266353940Sdim        NSec = &*NSecOrErr;
267353940Sdim      else
268353940Sdim        return NSecOrErr.takeError();
269353940Sdim
270353940Sdim      if (Value < NSec->Address || Value > NSec->Address + NSec->Size)
271353940Sdim        return make_error<JITLinkError>("Symbol address does not fall within "
272353940Sdim                                        "section");
273353940Sdim    }
274353940Sdim
275353940Sdim    IndexToSymbol[SymbolIndex] =
276353940Sdim        &createNormalizedSymbol(*Name, Value, Type, Sect, Desc,
277353940Sdim                                getLinkage(Type), getScope(*Name, Type));
278353940Sdim  }
279353940Sdim
280353940Sdim  return Error::success();
281353940Sdim}
282353940Sdim
283353940Sdimvoid MachOLinkGraphBuilder::addSectionStartSymAndBlock(
284353940Sdim    Section &GraphSec, uint64_t Address, const char *Data, uint64_t Size,
285353940Sdim    uint32_t Alignment, bool IsLive) {
286353940Sdim  Block &B =
287353940Sdim      Data ? G->createContentBlock(GraphSec, StringRef(Data, Size), Address,
288353940Sdim                                   Alignment, 0)
289353940Sdim           : G->createZeroFillBlock(GraphSec, Size, Address, Alignment, 0);
290353940Sdim  auto &Sym = G->addAnonymousSymbol(B, 0, Size, false, IsLive);
291353940Sdim  assert(!AddrToCanonicalSymbol.count(Sym.getAddress()) &&
292353940Sdim         "Anonymous block start symbol clashes with existing symbol address");
293353940Sdim  AddrToCanonicalSymbol[Sym.getAddress()] = &Sym;
294353940Sdim}
295353940Sdim
296353940SdimError MachOLinkGraphBuilder::graphifyRegularSymbols() {
297353940Sdim
298353940Sdim  LLVM_DEBUG(dbgs() << "Creating graph symbols...\n");
299353940Sdim
300353940Sdim  /// We only have 256 section indexes: Use a vector rather than a map.
301353940Sdim  std::vector<std::vector<NormalizedSymbol *>> SecIndexToSymbols;
302353940Sdim  SecIndexToSymbols.resize(256);
303353940Sdim
304353940Sdim  // Create commons, externs, and absolutes, and partition all other symbols by
305353940Sdim  // section.
306353940Sdim  for (auto &KV : IndexToSymbol) {
307353940Sdim    auto &NSym = *KV.second;
308353940Sdim
309353940Sdim    switch (NSym.Type & MachO::N_TYPE) {
310353940Sdim    case MachO::N_UNDF:
311353940Sdim      if (NSym.Value) {
312353940Sdim        if (!NSym.Name)
313353940Sdim          return make_error<JITLinkError>("Anonymous common symbol at index " +
314353940Sdim                                          Twine(KV.first));
315353940Sdim        NSym.GraphSymbol = &G->addCommonSymbol(
316357095Sdim            *NSym.Name, NSym.S, getCommonSection(), 0, NSym.Value,
317353940Sdim            1ull << MachO::GET_COMM_ALIGN(NSym.Desc),
318353940Sdim            NSym.Desc & MachO::N_NO_DEAD_STRIP);
319353940Sdim      } else {
320353940Sdim        if (!NSym.Name)
321353940Sdim          return make_error<JITLinkError>("Anonymous external symbol at "
322353940Sdim                                          "index " +
323353940Sdim                                          Twine(KV.first));
324357095Sdim        NSym.GraphSymbol = &G->addExternalSymbol(
325357095Sdim            *NSym.Name, 0,
326357095Sdim            NSym.Desc & MachO::N_WEAK_REF ? Linkage::Weak : Linkage::Strong);
327353940Sdim      }
328353940Sdim      break;
329353940Sdim    case MachO::N_ABS:
330353940Sdim      if (!NSym.Name)
331353940Sdim        return make_error<JITLinkError>("Anonymous absolute symbol at index " +
332353940Sdim                                        Twine(KV.first));
333353940Sdim      NSym.GraphSymbol = &G->addAbsoluteSymbol(
334353940Sdim          *NSym.Name, NSym.Value, 0, Linkage::Strong, Scope::Default,
335353940Sdim          NSym.Desc & MachO::N_NO_DEAD_STRIP);
336353940Sdim      break;
337353940Sdim    case MachO::N_SECT:
338353940Sdim      SecIndexToSymbols[NSym.Sect - 1].push_back(&NSym);
339353940Sdim      break;
340353940Sdim    case MachO::N_PBUD:
341353940Sdim      return make_error<JITLinkError>(
342353940Sdim          "Unupported N_PBUD symbol " +
343353940Sdim          (NSym.Name ? ("\"" + *NSym.Name + "\"") : Twine("<anon>")) +
344353940Sdim          " at index " + Twine(KV.first));
345353940Sdim    case MachO::N_INDR:
346353940Sdim      return make_error<JITLinkError>(
347353940Sdim          "Unupported N_INDR symbol " +
348353940Sdim          (NSym.Name ? ("\"" + *NSym.Name + "\"") : Twine("<anon>")) +
349353940Sdim          " at index " + Twine(KV.first));
350353940Sdim    default:
351353940Sdim      return make_error<JITLinkError>(
352353940Sdim          "Unrecognized symbol type " + Twine(NSym.Type & MachO::N_TYPE) +
353353940Sdim          " for symbol " +
354353940Sdim          (NSym.Name ? ("\"" + *NSym.Name + "\"") : Twine("<anon>")) +
355353940Sdim          " at index " + Twine(KV.first));
356353940Sdim    }
357353940Sdim  }
358353940Sdim
359353940Sdim  // Loop over sections performing regular graphification for those that
360353940Sdim  // don't have custom parsers.
361353940Sdim  for (auto &KV : IndexToSection) {
362353940Sdim    auto SecIndex = KV.first;
363353940Sdim    auto &NSec = KV.second;
364353940Sdim
365353940Sdim    // Skip sections with custom parsers.
366353940Sdim    if (CustomSectionParserFunctions.count(NSec.GraphSection->getName())) {
367353940Sdim      LLVM_DEBUG({
368353940Sdim        dbgs() << "  Skipping section " << NSec.GraphSection->getName()
369353940Sdim               << " as it has a custom parser.\n";
370353940Sdim      });
371353940Sdim      continue;
372353940Sdim    } else
373353940Sdim      LLVM_DEBUG({
374353940Sdim        dbgs() << "  Processing section " << NSec.GraphSection->getName()
375353940Sdim               << "...\n";
376353940Sdim      });
377353940Sdim
378353940Sdim    bool SectionIsNoDeadStrip = NSec.Flags & MachO::S_ATTR_NO_DEAD_STRIP;
379353940Sdim    bool SectionIsText = NSec.Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
380353940Sdim
381353940Sdim    auto &SecNSymStack = SecIndexToSymbols[SecIndex];
382353940Sdim
383353940Sdim    // If this section is non-empty but there are no symbols covering it then
384353940Sdim    // create one block and anonymous symbol to cover the entire section.
385353940Sdim    if (SecNSymStack.empty()) {
386353940Sdim      if (NSec.Size > 0) {
387353940Sdim        LLVM_DEBUG({
388353940Sdim          dbgs() << "    Section non-empty, but contains no symbols. "
389353940Sdim                    "Creating anonymous block to cover "
390353940Sdim                 << formatv("{0:x16}", NSec.Address) << " -- "
391353940Sdim                 << formatv("{0:x16}", NSec.Address + NSec.Size) << "\n";
392353940Sdim        });
393353940Sdim        addSectionStartSymAndBlock(*NSec.GraphSection, NSec.Address, NSec.Data,
394353940Sdim                                   NSec.Size, NSec.Alignment,
395353940Sdim                                   SectionIsNoDeadStrip);
396353940Sdim      } else
397353940Sdim        LLVM_DEBUG({
398353940Sdim          dbgs() << "    Section empty and contains no symbols. Skipping.\n";
399353940Sdim        });
400353940Sdim      continue;
401353940Sdim    }
402353940Sdim
403353940Sdim    // Sort the symbol stack in by address, alt-entry status, scope, and name.
404353940Sdim    // We sort in reverse order so that symbols will be visited in the right
405353940Sdim    // order when we pop off the stack below.
406353940Sdim    llvm::sort(SecNSymStack, [](const NormalizedSymbol *LHS,
407353940Sdim                                const NormalizedSymbol *RHS) {
408353940Sdim      if (LHS->Value != RHS->Value)
409353940Sdim        return LHS->Value > RHS->Value;
410353940Sdim      if (isAltEntry(*LHS) != isAltEntry(*RHS))
411353940Sdim        return isAltEntry(*RHS);
412353940Sdim      if (LHS->S != RHS->S)
413353940Sdim        return static_cast<uint8_t>(LHS->S) < static_cast<uint8_t>(RHS->S);
414353940Sdim      return LHS->Name < RHS->Name;
415353940Sdim    });
416353940Sdim
417353940Sdim    // The first symbol in a section can not be an alt-entry symbol.
418353940Sdim    if (!SecNSymStack.empty() && isAltEntry(*SecNSymStack.back()))
419353940Sdim      return make_error<JITLinkError>(
420353940Sdim          "First symbol in " + NSec.GraphSection->getName() + " is alt-entry");
421353940Sdim
422353940Sdim    // If the section is non-empty but there is no symbol covering the start
423353940Sdim    // address then add an anonymous one.
424353940Sdim    if (SecNSymStack.back()->Value != NSec.Address) {
425353940Sdim      auto AnonBlockSize = SecNSymStack.back()->Value - NSec.Address;
426353940Sdim      LLVM_DEBUG({
427353940Sdim        dbgs() << "    Section start not covered by symbol. "
428353940Sdim               << "Creating anonymous block to cover [ "
429353940Sdim               << formatv("{0:x16}", NSec.Address) << " -- "
430353940Sdim               << formatv("{0:x16}", NSec.Address + AnonBlockSize) << " ]\n";
431353940Sdim      });
432353940Sdim      addSectionStartSymAndBlock(*NSec.GraphSection, NSec.Address, NSec.Data,
433353940Sdim                                 AnonBlockSize, NSec.Alignment,
434353940Sdim                                 SectionIsNoDeadStrip);
435353940Sdim    }
436353940Sdim
437353940Sdim    // Visit section symbols in order by popping off the reverse-sorted stack,
438353940Sdim    // building blocks for each alt-entry chain and creating symbols as we go.
439353940Sdim    while (!SecNSymStack.empty()) {
440353940Sdim      SmallVector<NormalizedSymbol *, 8> BlockSyms;
441353940Sdim
442353940Sdim      BlockSyms.push_back(SecNSymStack.back());
443353940Sdim      SecNSymStack.pop_back();
444353940Sdim      while (!SecNSymStack.empty() &&
445353940Sdim             (isAltEntry(*SecNSymStack.back()) ||
446353940Sdim              SecNSymStack.back()->Value == BlockSyms.back()->Value)) {
447353940Sdim        BlockSyms.push_back(SecNSymStack.back());
448353940Sdim        SecNSymStack.pop_back();
449353940Sdim      }
450353940Sdim
451353940Sdim      // BlockNSyms now contains the block symbols in reverse canonical order.
452353940Sdim      JITTargetAddress BlockStart = BlockSyms.front()->Value;
453353940Sdim      JITTargetAddress BlockEnd = SecNSymStack.empty()
454353940Sdim                                      ? NSec.Address + NSec.Size
455353940Sdim                                      : SecNSymStack.back()->Value;
456353940Sdim      JITTargetAddress BlockOffset = BlockStart - NSec.Address;
457353940Sdim      JITTargetAddress BlockSize = BlockEnd - BlockStart;
458353940Sdim
459353940Sdim      LLVM_DEBUG({
460353940Sdim        dbgs() << "    Creating block for " << formatv("{0:x16}", BlockStart)
461353940Sdim               << " -- " << formatv("{0:x16}", BlockEnd) << ": "
462353940Sdim               << NSec.GraphSection->getName() << " + "
463353940Sdim               << formatv("{0:x16}", BlockOffset) << " with "
464353940Sdim               << BlockSyms.size() << " symbol(s)...\n";
465353940Sdim      });
466353940Sdim
467353940Sdim      Block &B =
468353940Sdim          NSec.Data
469353940Sdim              ? G->createContentBlock(
470353940Sdim                    *NSec.GraphSection,
471353940Sdim                    StringRef(NSec.Data + BlockOffset, BlockSize), BlockStart,
472353940Sdim                    NSec.Alignment, BlockStart % NSec.Alignment)
473353940Sdim              : G->createZeroFillBlock(*NSec.GraphSection, BlockSize,
474353940Sdim                                       BlockStart, NSec.Alignment,
475353940Sdim                                       BlockStart % NSec.Alignment);
476353940Sdim
477353940Sdim      Optional<JITTargetAddress> LastCanonicalAddr;
478353940Sdim      JITTargetAddress SymEnd = BlockEnd;
479353940Sdim      while (!BlockSyms.empty()) {
480353940Sdim        auto &NSym = *BlockSyms.back();
481353940Sdim        BlockSyms.pop_back();
482353940Sdim
483353940Sdim        bool SymLive =
484353940Sdim            (NSym.Desc & MachO::N_NO_DEAD_STRIP) || SectionIsNoDeadStrip;
485353940Sdim
486353940Sdim        LLVM_DEBUG({
487353940Sdim          dbgs() << "      " << formatv("{0:x16}", NSym.Value) << " -- "
488353940Sdim                 << formatv("{0:x16}", SymEnd) << ": ";
489353940Sdim          if (!NSym.Name)
490353940Sdim            dbgs() << "<anonymous symbol>";
491353940Sdim          else
492353940Sdim            dbgs() << NSym.Name;
493353940Sdim          if (SymLive)
494353940Sdim            dbgs() << " [no-dead-strip]";
495353940Sdim          if (LastCanonicalAddr == NSym.Value)
496353940Sdim            dbgs() << " [non-canonical]";
497353940Sdim          dbgs() << "\n";
498353940Sdim        });
499353940Sdim
500353940Sdim        auto &Sym =
501353940Sdim            NSym.Name
502353940Sdim                ? G->addDefinedSymbol(B, NSym.Value - BlockStart, *NSym.Name,
503353940Sdim                                      SymEnd - NSym.Value, NSym.L, NSym.S,
504353940Sdim                                      SectionIsText, SymLive)
505353940Sdim                : G->addAnonymousSymbol(B, NSym.Value - BlockStart,
506353940Sdim                                        SymEnd - NSym.Value, SectionIsText,
507353940Sdim                                        SymLive);
508353940Sdim        NSym.GraphSymbol = &Sym;
509353940Sdim        if (LastCanonicalAddr != Sym.getAddress()) {
510353940Sdim          if (LastCanonicalAddr)
511353940Sdim            SymEnd = *LastCanonicalAddr;
512353940Sdim          LastCanonicalAddr = Sym.getAddress();
513353940Sdim          setCanonicalSymbol(Sym);
514353940Sdim        }
515353940Sdim      }
516353940Sdim    }
517353940Sdim  }
518353940Sdim
519353940Sdim  return Error::success();
520353940Sdim}
521353940Sdim
522353940SdimError MachOLinkGraphBuilder::graphifySectionsWithCustomParsers() {
523353940Sdim  // Graphify special sections.
524353940Sdim  for (auto &KV : IndexToSection) {
525353940Sdim    auto &NSec = KV.second;
526353940Sdim
527353940Sdim    auto HI = CustomSectionParserFunctions.find(NSec.GraphSection->getName());
528353940Sdim    if (HI != CustomSectionParserFunctions.end()) {
529353940Sdim      auto &Parse = HI->second;
530353940Sdim      if (auto Err = Parse(NSec))
531353940Sdim        return Err;
532353940Sdim    }
533353940Sdim  }
534353940Sdim
535353940Sdim  return Error::success();
536353940Sdim}
537353940Sdim
538353940Sdim} // end namespace jitlink
539353940Sdim} // end namespace llvm
540