LLVM  14.0.0git
MachOLinkGraphBuilder.cpp
Go to the documentation of this file.
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 buliding code.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "MachOLinkGraphBuilder.h"
14 
15 #define DEBUG_TYPE "jitlink"
16 
17 static const char *CommonSectionName = "__common";
18 
19 namespace llvm {
20 namespace jitlink {
21 
23 
25 
26  // Sanity check: we only operate on relocatable objects.
27  if (!Obj.isRelocatableObject())
28  return make_error<JITLinkError>("Object is not a relocatable MachO");
29 
30  if (auto Err = createNormalizedSections())
31  return std::move(Err);
32 
33  if (auto Err = createNormalizedSymbols())
34  return std::move(Err);
35 
36  if (auto Err = graphifyRegularSymbols())
37  return std::move(Err);
38 
39  if (auto Err = graphifySectionsWithCustomParsers())
40  return std::move(Err);
41 
42  if (auto Err = addRelocations())
43  return std::move(Err);
44 
45  return std::move(G);
46 }
47 
49  const object::MachOObjectFile &Obj, Triple TT,
50  LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
51  : Obj(Obj),
52  G(std::make_unique<LinkGraph>(
53  std::string(Obj.getFileName()), std::move(TT), getPointerSize(Obj),
54  getEndianness(Obj), std::move(GetEdgeKindName))) {}
55 
58  assert(!CustomSectionParserFunctions.count(SectionName) &&
59  "Custom parser for this section already exists");
60  CustomSectionParserFunctions[SectionName] = std::move(Parser);
61 }
62 
64  if ((Desc & MachO::N_WEAK_DEF) || (Desc & MachO::N_WEAK_REF))
65  return Linkage::Weak;
66  return Linkage::Strong;
67 }
68 
70  if (Type & MachO::N_EXT) {
71  if ((Type & MachO::N_PEXT) || Name.startswith("l"))
72  return Scope::Hidden;
73  else
74  return Scope::Default;
75  }
76  return Scope::Local;
77 }
78 
80  return NSym.Desc & MachO::N_ALT_ENTRY;
81 }
82 
84  return (NSec.Flags & MachO::S_ATTR_DEBUG &&
85  strcmp(NSec.SegName, "__DWARF") == 0);
86 }
87 
89  switch (NSec.Flags & MachO::SECTION_TYPE) {
90  case MachO::S_ZEROFILL:
93  return true;
94  default:
95  return false;
96  }
97 }
98 
99 unsigned
100 MachOLinkGraphBuilder::getPointerSize(const object::MachOObjectFile &Obj) {
101  return Obj.is64Bit() ? 8 : 4;
102 }
103 
105 MachOLinkGraphBuilder::getEndianness(const object::MachOObjectFile &Obj) {
107 }
108 
109 Section &MachOLinkGraphBuilder::getCommonSection() {
110  if (!CommonSection)
111  CommonSection =
112  &G->createSection(CommonSectionName, MemProt::Read | MemProt::Write);
113  return *CommonSection;
114 }
115 
116 Error MachOLinkGraphBuilder::createNormalizedSections() {
117  // Build normalized sections. Verifies that section data is in-range (for
118  // sections with content) and that address ranges are non-overlapping.
119 
120  LLVM_DEBUG(dbgs() << "Creating normalized sections...\n");
121 
122  for (auto &SecRef : Obj.sections()) {
123  NormalizedSection NSec;
124  uint32_t DataOffset = 0;
125 
126  auto SecIndex = Obj.getSectionIndex(SecRef.getRawDataRefImpl());
127 
128  if (Obj.is64Bit()) {
129  const MachO::section_64 &Sec64 =
130  Obj.getSection64(SecRef.getRawDataRefImpl());
131 
132  memcpy(&NSec.SectName, &Sec64.sectname, 16);
133  NSec.SectName[16] = '\0';
134  memcpy(&NSec.SegName, Sec64.segname, 16);
135  NSec.SegName[16] = '\0';
136 
137  NSec.Address = Sec64.addr;
138  NSec.Size = Sec64.size;
139  NSec.Alignment = 1ULL << Sec64.align;
140  NSec.Flags = Sec64.flags;
141  DataOffset = Sec64.offset;
142  } else {
143  const MachO::section &Sec32 = Obj.getSection(SecRef.getRawDataRefImpl());
144 
145  memcpy(&NSec.SectName, &Sec32.sectname, 16);
146  NSec.SectName[16] = '\0';
147  memcpy(&NSec.SegName, Sec32.segname, 16);
148  NSec.SegName[16] = '\0';
149 
150  NSec.Address = Sec32.addr;
151  NSec.Size = Sec32.size;
152  NSec.Alignment = 1ULL << Sec32.align;
153  NSec.Flags = Sec32.flags;
154  DataOffset = Sec32.offset;
155  }
156 
157  LLVM_DEBUG({
158  dbgs() << " " << NSec.SegName << "," << NSec.SectName << ": "
159  << formatv("{0:x16}", NSec.Address) << " -- "
160  << formatv("{0:x16}", NSec.Address + NSec.Size)
161  << ", align: " << NSec.Alignment << ", index: " << SecIndex
162  << "\n";
163  });
164 
165  // Get the section data if any.
166  if (!isZeroFillSection(NSec)) {
167  if (DataOffset + NSec.Size > Obj.getData().size())
168  return make_error<JITLinkError>(
169  "Section data extends past end of file");
170 
171  NSec.Data = Obj.getData().data() + DataOffset;
172  }
173 
174  // Get prot flags.
175  // FIXME: Make sure this test is correct (it's probably missing cases
176  // as-is).
177  MemProt Prot;
178  if (NSec.Flags & MachO::S_ATTR_PURE_INSTRUCTIONS)
179  Prot = MemProt::Read | MemProt::Exec;
180  else
181  Prot = MemProt::Read | MemProt::Write;
182 
183  if (!isDebugSection(NSec)) {
184  auto FullyQualifiedName =
185  G->allocateString(StringRef(NSec.SegName) + "," + NSec.SectName);
186  NSec.GraphSection = &G->createSection(
187  StringRef(FullyQualifiedName.data(), FullyQualifiedName.size()),
188  Prot);
189  } else
190  LLVM_DEBUG({
191  dbgs() << " " << NSec.SegName << "," << NSec.SectName
192  << " is a debug section: No graph section will be created.\n";
193  });
194 
195  IndexToSection.insert(std::make_pair(SecIndex, std::move(NSec)));
196  }
197 
198  std::vector<NormalizedSection *> Sections;
199  Sections.reserve(IndexToSection.size());
200  for (auto &KV : IndexToSection)
201  Sections.push_back(&KV.second);
202 
203  // If we didn't end up creating any sections then bail out. The code below
204  // assumes that we have at least one section.
205  if (Sections.empty())
206  return Error::success();
207 
208  llvm::sort(Sections,
209  [](const NormalizedSection *LHS, const NormalizedSection *RHS) {
210  assert(LHS && RHS && "Null section?");
211  if (LHS->Address != RHS->Address)
212  return LHS->Address < RHS->Address;
213  return LHS->Size < RHS->Size;
214  });
215 
216  for (unsigned I = 0, E = Sections.size() - 1; I != E; ++I) {
217  auto &Cur = *Sections[I];
218  auto &Next = *Sections[I + 1];
219  if (Next.Address < Cur.Address + Cur.Size)
220  return make_error<JITLinkError>(
221  "Address range for section " +
222  formatv("\"{0}/{1}\" [ {2:x16} -- {3:x16} ] ", Cur.SegName,
223  Cur.SectName, Cur.Address, Cur.Address + Cur.Size) +
224  "overlaps section \"" + Next.SegName + "/" + Next.SectName + "\"" +
225  formatv("\"{0}/{1}\" [ {2:x16} -- {3:x16} ] ", Next.SegName,
226  Next.SectName, Next.Address, Next.Address + Next.Size));
227  }
228 
229  return Error::success();
230 }
231 
232 Error MachOLinkGraphBuilder::createNormalizedSymbols() {
233  LLVM_DEBUG(dbgs() << "Creating normalized symbols...\n");
234 
235  for (auto &SymRef : Obj.symbols()) {
236 
237  unsigned SymbolIndex = Obj.getSymbolIndex(SymRef.getRawDataRefImpl());
238  uint64_t Value;
239  uint32_t NStrX;
240  uint8_t Type;
241  uint8_t Sect;
242  uint16_t Desc;
243 
244  if (Obj.is64Bit()) {
245  const MachO::nlist_64 &NL64 =
246  Obj.getSymbol64TableEntry(SymRef.getRawDataRefImpl());
247  Value = NL64.n_value;
248  NStrX = NL64.n_strx;
249  Type = NL64.n_type;
250  Sect = NL64.n_sect;
251  Desc = NL64.n_desc;
252  } else {
253  const MachO::nlist &NL32 =
254  Obj.getSymbolTableEntry(SymRef.getRawDataRefImpl());
255  Value = NL32.n_value;
256  NStrX = NL32.n_strx;
257  Type = NL32.n_type;
258  Sect = NL32.n_sect;
259  Desc = NL32.n_desc;
260  }
261 
262  // Skip stabs.
263  // FIXME: Are there other symbols we should be skipping?
264  if (Type & MachO::N_STAB)
265  continue;
266 
267  Optional<StringRef> Name;
268  if (NStrX) {
269  if (auto NameOrErr = SymRef.getName())
270  Name = *NameOrErr;
271  else
272  return NameOrErr.takeError();
273  }
274 
275  LLVM_DEBUG({
276  dbgs() << " ";
277  if (!Name)
278  dbgs() << "<anonymous symbol>";
279  else
280  dbgs() << *Name;
281  dbgs() << ": value = " << formatv("{0:x16}", Value)
282  << ", type = " << formatv("{0:x2}", Type)
283  << ", desc = " << formatv("{0:x4}", Desc) << ", sect = ";
284  if (Sect)
285  dbgs() << static_cast<unsigned>(Sect - 1);
286  else
287  dbgs() << "none";
288  dbgs() << "\n";
289  });
290 
291  // If this symbol has a section, sanity check that the addresses line up.
292  if (Sect != 0) {
293  auto NSec = findSectionByIndex(Sect - 1);
294  if (!NSec)
295  return NSec.takeError();
296 
297  if (Value < NSec->Address || Value > NSec->Address + NSec->Size)
298  return make_error<JITLinkError>("Address " + formatv("{0:x}", Value) +
299  " for symbol " + *Name +
300  " does not fall within section");
301 
302  if (!NSec->GraphSection) {
303  LLVM_DEBUG({
304  dbgs() << " Skipping: Symbol is in section " << NSec->SegName << "/"
305  << NSec->SectName
306  << " which has no associated graph section.\n";
307  });
308  continue;
309  }
310  }
311 
312  IndexToSymbol[SymbolIndex] =
313  &createNormalizedSymbol(*Name, Value, Type, Sect, Desc,
314  getLinkage(Desc), getScope(*Name, Type));
315  }
316 
317  return Error::success();
318 }
319 
320 void MachOLinkGraphBuilder::addSectionStartSymAndBlock(
321  Section &GraphSec, uint64_t Address, const char *Data, uint64_t Size,
322  uint32_t Alignment, bool IsLive) {
323  Block &B =
324  Data ? G->createContentBlock(GraphSec, ArrayRef<char>(Data, Size),
325  Address, Alignment, 0)
326  : G->createZeroFillBlock(GraphSec, Size, Address, Alignment, 0);
327  auto &Sym = G->addAnonymousSymbol(B, 0, Size, false, IsLive);
328  assert(!AddrToCanonicalSymbol.count(Sym.getAddress()) &&
329  "Anonymous block start symbol clashes with existing symbol address");
330  AddrToCanonicalSymbol[Sym.getAddress()] = &Sym;
331 }
332 
333 Error MachOLinkGraphBuilder::graphifyRegularSymbols() {
334 
335  LLVM_DEBUG(dbgs() << "Creating graph symbols...\n");
336 
337  /// We only have 256 section indexes: Use a vector rather than a map.
338  std::vector<std::vector<NormalizedSymbol *>> SecIndexToSymbols;
339  SecIndexToSymbols.resize(256);
340 
341  // Create commons, externs, and absolutes, and partition all other symbols by
342  // section.
343  for (auto &KV : IndexToSymbol) {
344  auto &NSym = *KV.second;
345 
346  switch (NSym.Type & MachO::N_TYPE) {
347  case MachO::N_UNDF:
348  if (NSym.Value) {
349  if (!NSym.Name)
350  return make_error<JITLinkError>("Anonymous common symbol at index " +
351  Twine(KV.first));
352  NSym.GraphSymbol = &G->addCommonSymbol(
353  *NSym.Name, NSym.S, getCommonSection(), 0, NSym.Value,
354  1ull << MachO::GET_COMM_ALIGN(NSym.Desc),
355  NSym.Desc & MachO::N_NO_DEAD_STRIP);
356  } else {
357  if (!NSym.Name)
358  return make_error<JITLinkError>("Anonymous external symbol at "
359  "index " +
360  Twine(KV.first));
361  NSym.GraphSymbol = &G->addExternalSymbol(
362  *NSym.Name, 0,
364  }
365  break;
366  case MachO::N_ABS:
367  if (!NSym.Name)
368  return make_error<JITLinkError>("Anonymous absolute symbol at index " +
369  Twine(KV.first));
370  NSym.GraphSymbol = &G->addAbsoluteSymbol(
371  *NSym.Name, NSym.Value, 0, Linkage::Strong, Scope::Default,
372  NSym.Desc & MachO::N_NO_DEAD_STRIP);
373  break;
374  case MachO::N_SECT:
375  SecIndexToSymbols[NSym.Sect - 1].push_back(&NSym);
376  break;
377  case MachO::N_PBUD:
378  return make_error<JITLinkError>(
379  "Unupported N_PBUD symbol " +
380  (NSym.Name ? ("\"" + *NSym.Name + "\"") : Twine("<anon>")) +
381  " at index " + Twine(KV.first));
382  case MachO::N_INDR:
383  return make_error<JITLinkError>(
384  "Unupported N_INDR symbol " +
385  (NSym.Name ? ("\"" + *NSym.Name + "\"") : Twine("<anon>")) +
386  " at index " + Twine(KV.first));
387  default:
388  return make_error<JITLinkError>(
389  "Unrecognized symbol type " + Twine(NSym.Type & MachO::N_TYPE) +
390  " for symbol " +
391  (NSym.Name ? ("\"" + *NSym.Name + "\"") : Twine("<anon>")) +
392  " at index " + Twine(KV.first));
393  }
394  }
395 
396  // Loop over sections performing regular graphification for those that
397  // don't have custom parsers.
398  for (auto &KV : IndexToSection) {
399  auto SecIndex = KV.first;
400  auto &NSec = KV.second;
401 
402  if (!NSec.GraphSection) {
403  LLVM_DEBUG({
404  dbgs() << " " << NSec.SegName << "/" << NSec.SectName
405  << " has no graph section. Skipping.\n";
406  });
407  continue;
408  }
409 
410  // Skip sections with custom parsers.
411  if (CustomSectionParserFunctions.count(NSec.GraphSection->getName())) {
412  LLVM_DEBUG({
413  dbgs() << " Skipping section " << NSec.GraphSection->getName()
414  << " as it has a custom parser.\n";
415  });
416  continue;
417  } else if ((NSec.Flags & MachO::SECTION_TYPE) ==
419  if (auto Err = graphifyCStringSection(
420  NSec, std::move(SecIndexToSymbols[SecIndex])))
421  return Err;
422  continue;
423  } else
424  LLVM_DEBUG({
425  dbgs() << " Graphifying regular section "
426  << NSec.GraphSection->getName() << "...\n";
427  });
428 
429  bool SectionIsNoDeadStrip = NSec.Flags & MachO::S_ATTR_NO_DEAD_STRIP;
430  bool SectionIsText = NSec.Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
431 
432  auto &SecNSymStack = SecIndexToSymbols[SecIndex];
433 
434  // If this section is non-empty but there are no symbols covering it then
435  // create one block and anonymous symbol to cover the entire section.
436  if (SecNSymStack.empty()) {
437  if (NSec.Size > 0) {
438  LLVM_DEBUG({
439  dbgs() << " Section non-empty, but contains no symbols. "
440  "Creating anonymous block to cover "
441  << formatv("{0:x16}", NSec.Address) << " -- "
442  << formatv("{0:x16}", NSec.Address + NSec.Size) << "\n";
443  });
444  addSectionStartSymAndBlock(*NSec.GraphSection, NSec.Address, NSec.Data,
445  NSec.Size, NSec.Alignment,
446  SectionIsNoDeadStrip);
447  } else
448  LLVM_DEBUG({
449  dbgs() << " Section empty and contains no symbols. Skipping.\n";
450  });
451  continue;
452  }
453 
454  // Sort the symbol stack in by address, alt-entry status, scope, and name.
455  // We sort in reverse order so that symbols will be visited in the right
456  // order when we pop off the stack below.
457  llvm::sort(SecNSymStack, [](const NormalizedSymbol *LHS,
458  const NormalizedSymbol *RHS) {
459  if (LHS->Value != RHS->Value)
460  return LHS->Value > RHS->Value;
461  if (isAltEntry(*LHS) != isAltEntry(*RHS))
462  return isAltEntry(*RHS);
463  if (LHS->S != RHS->S)
464  return static_cast<uint8_t>(LHS->S) < static_cast<uint8_t>(RHS->S);
465  return LHS->Name < RHS->Name;
466  });
467 
468  // The first symbol in a section can not be an alt-entry symbol.
469  if (!SecNSymStack.empty() && isAltEntry(*SecNSymStack.back()))
470  return make_error<JITLinkError>(
471  "First symbol in " + NSec.GraphSection->getName() + " is alt-entry");
472 
473  // If the section is non-empty but there is no symbol covering the start
474  // address then add an anonymous one.
475  if (SecNSymStack.back()->Value != NSec.Address) {
476  auto AnonBlockSize = SecNSymStack.back()->Value - NSec.Address;
477  LLVM_DEBUG({
478  dbgs() << " Section start not covered by symbol. "
479  << "Creating anonymous block to cover [ "
480  << formatv("{0:x16}", NSec.Address) << " -- "
481  << formatv("{0:x16}", NSec.Address + AnonBlockSize) << " ]\n";
482  });
483  addSectionStartSymAndBlock(*NSec.GraphSection, NSec.Address, NSec.Data,
484  AnonBlockSize, NSec.Alignment,
485  SectionIsNoDeadStrip);
486  }
487 
488  // Visit section symbols in order by popping off the reverse-sorted stack,
489  // building blocks for each alt-entry chain and creating symbols as we go.
490  while (!SecNSymStack.empty()) {
491  SmallVector<NormalizedSymbol *, 8> BlockSyms;
492 
493  BlockSyms.push_back(SecNSymStack.back());
494  SecNSymStack.pop_back();
495  while (!SecNSymStack.empty() &&
496  (isAltEntry(*SecNSymStack.back()) ||
497  SecNSymStack.back()->Value == BlockSyms.back()->Value)) {
498  BlockSyms.push_back(SecNSymStack.back());
499  SecNSymStack.pop_back();
500  }
501 
502  // BlockNSyms now contains the block symbols in reverse canonical order.
503  JITTargetAddress BlockStart = BlockSyms.front()->Value;
504  JITTargetAddress BlockEnd = SecNSymStack.empty()
505  ? NSec.Address + NSec.Size
506  : SecNSymStack.back()->Value;
507  JITTargetAddress BlockOffset = BlockStart - NSec.Address;
508  JITTargetAddress BlockSize = BlockEnd - BlockStart;
509 
510  LLVM_DEBUG({
511  dbgs() << " Creating block for " << formatv("{0:x16}", BlockStart)
512  << " -- " << formatv("{0:x16}", BlockEnd) << ": "
513  << NSec.GraphSection->getName() << " + "
514  << formatv("{0:x16}", BlockOffset) << " with "
515  << BlockSyms.size() << " symbol(s)...\n";
516  });
517 
518  Block &B =
519  NSec.Data
520  ? G->createContentBlock(
521  *NSec.GraphSection,
522  ArrayRef<char>(NSec.Data + BlockOffset, BlockSize),
523  BlockStart, NSec.Alignment, BlockStart % NSec.Alignment)
524  : G->createZeroFillBlock(*NSec.GraphSection, BlockSize,
525  BlockStart, NSec.Alignment,
526  BlockStart % NSec.Alignment);
527 
528  Optional<JITTargetAddress> LastCanonicalAddr;
529  JITTargetAddress SymEnd = BlockEnd;
530  while (!BlockSyms.empty()) {
531  auto &NSym = *BlockSyms.back();
532  BlockSyms.pop_back();
533 
534  bool SymLive =
535  (NSym.Desc & MachO::N_NO_DEAD_STRIP) || SectionIsNoDeadStrip;
536 
537  auto &Sym = createStandardGraphSymbol(NSym, B, SymEnd - NSym.Value,
538  SectionIsText, SymLive,
539  LastCanonicalAddr != NSym.Value);
540 
541  if (LastCanonicalAddr != Sym.getAddress()) {
542  if (LastCanonicalAddr)
543  SymEnd = *LastCanonicalAddr;
544  LastCanonicalAddr = Sym.getAddress();
545  }
546  }
547  }
548  }
549 
550  return Error::success();
551 }
552 
553 Symbol &MachOLinkGraphBuilder::createStandardGraphSymbol(NormalizedSymbol &NSym,
554  Block &B, size_t Size,
555  bool IsText,
556  bool IsNoDeadStrip,
557  bool IsCanonical) {
558 
559  LLVM_DEBUG({
560  dbgs() << " " << formatv("{0:x16}", NSym.Value) << " -- "
561  << formatv("{0:x16}", NSym.Value + Size) << ": ";
562  if (!NSym.Name)
563  dbgs() << "<anonymous symbol>";
564  else
565  dbgs() << NSym.Name;
566  if (IsText)
567  dbgs() << " [text]";
568  if (IsNoDeadStrip)
569  dbgs() << " [no-dead-strip]";
570  if (!IsCanonical)
571  dbgs() << " [non-canonical]";
572  dbgs() << "\n";
573  });
574 
575  auto &Sym = NSym.Name ? G->addDefinedSymbol(B, NSym.Value - B.getAddress(),
576  *NSym.Name, Size, NSym.L, NSym.S,
577  IsText, IsNoDeadStrip)
578  : G->addAnonymousSymbol(B, NSym.Value - B.getAddress(),
579  Size, IsText, IsNoDeadStrip);
580  NSym.GraphSymbol = &Sym;
581 
582  if (IsCanonical)
583  setCanonicalSymbol(Sym);
584 
585  return Sym;
586 }
587 
588 Error MachOLinkGraphBuilder::graphifySectionsWithCustomParsers() {
589  // Graphify special sections.
590  for (auto &KV : IndexToSection) {
591  auto &NSec = KV.second;
592 
593  // Skip non-graph sections.
594  if (!NSec.GraphSection)
595  continue;
596 
597  auto HI = CustomSectionParserFunctions.find(NSec.GraphSection->getName());
598  if (HI != CustomSectionParserFunctions.end()) {
599  auto &Parse = HI->second;
600  if (auto Err = Parse(NSec))
601  return Err;
602  }
603  }
604 
605  return Error::success();
606 }
607 
608 Error MachOLinkGraphBuilder::graphifyCStringSection(
609  NormalizedSection &NSec, std::vector<NormalizedSymbol *> NSyms) {
610 
611  assert(NSec.GraphSection && "C string literal section missing graph section");
612  assert(NSec.Data && "C string literal section has no data");
613 
614  LLVM_DEBUG({
615  dbgs() << " Graphifying C-string literal section "
616  << NSec.GraphSection->getName() << "\n";
617  });
618 
619  if (NSec.Data[NSec.Size - 1] != '\0')
620  return make_error<JITLinkError>("C string literal section " +
621  NSec.GraphSection->getName() +
622  " does not end with null terminator");
623 
624  /// Sort into reverse order to use as a stack.
625  llvm::sort(NSyms,
626  [](const NormalizedSymbol *LHS, const NormalizedSymbol *RHS) {
627  if (LHS->Value != RHS->Value)
628  return LHS->Value > RHS->Value;
629  if (LHS->L != RHS->L)
630  return LHS->L > RHS->L;
631  if (LHS->S != RHS->S)
632  return LHS->S > RHS->S;
633  if (RHS->Name) {
634  if (!LHS->Name)
635  return true;
636  return *LHS->Name > *RHS->Name;
637  }
638  return false;
639  });
640 
641  bool SectionIsNoDeadStrip = NSec.Flags & MachO::S_ATTR_NO_DEAD_STRIP;
642  bool SectionIsText = NSec.Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
643  JITTargetAddress BlockStart = 0;
644 
645  // Scan section for null characters.
646  for (size_t I = 0; I != NSec.Size; ++I)
647  if (NSec.Data[I] == '\0') {
648  JITTargetAddress BlockEnd = I + 1;
649  size_t BlockSize = BlockEnd - BlockStart;
650  // Create a block for this null terminated string.
651  auto &B = G->createContentBlock(*NSec.GraphSection,
652  {NSec.Data + BlockStart, BlockSize},
653  NSec.Address + BlockStart, 1, 0);
654 
655  LLVM_DEBUG({
656  dbgs() << " Created block " << formatv("{0:x}", B.getAddress())
657  << " -- " << formatv("{0:x}", B.getAddress() + B.getSize())
658  << " for \"" << StringRef(B.getContent().data()) << "\"\n";
659  });
660 
661  // If there's no symbol at the start of this block then create one.
662  if (NSyms.empty() || NSyms.back()->Value != B.getAddress()) {
663  auto &S = G->addAnonymousSymbol(B, 0, BlockSize, false, false);
664  setCanonicalSymbol(S);
665  LLVM_DEBUG({
666  dbgs() << " Adding anonymous symbol for c-string block "
667  << formatv("{0:x16} -- {1:x16}", S.getAddress(),
668  S.getAddress() + BlockSize)
669  << "\n";
670  });
671  }
672 
673  // Process any remaining symbols that point into this block.
674  JITTargetAddress LastCanonicalAddr = B.getAddress() + BlockEnd;
675  while (!NSyms.empty() &&
676  NSyms.back()->Value < (B.getAddress() + BlockSize)) {
677  auto &NSym = *NSyms.back();
678  size_t SymSize = (B.getAddress() + BlockSize) - NSyms.back()->Value;
679  bool SymLive =
680  (NSym.Desc & MachO::N_NO_DEAD_STRIP) || SectionIsNoDeadStrip;
681 
682  bool IsCanonical = false;
683  if (LastCanonicalAddr != NSym.Value) {
684  IsCanonical = true;
685  LastCanonicalAddr = NSym.Value;
686  }
687 
688  createStandardGraphSymbol(NSym, B, SymSize, SectionIsText, SymLive,
689  IsCanonical);
690 
691  NSyms.pop_back();
692  }
693 
694  BlockStart += BlockSize;
695  }
696 
697  return Error::success();
698 }
699 
701  auto *CUSec = G.findSectionByName(CompactUnwindSectionName);
702  if (!CUSec)
703  return Error::success();
704 
705  if (!G.getTargetTriple().isOSBinFormatMachO())
706  return make_error<JITLinkError>(
707  "Error linking " + G.getName() +
708  ": compact unwind splitting not supported on non-macho target " +
709  G.getTargetTriple().str());
710 
711  unsigned CURecordSize = 0;
712  unsigned PersonalityEdgeOffset = 0;
713  unsigned LSDAEdgeOffset = 0;
714  switch (G.getTargetTriple().getArch()) {
715  case Triple::aarch64:
716  case Triple::x86_64:
717  // 64-bit compact-unwind record format:
718  // Range start: 8 bytes.
719  // Range size: 4 bytes.
720  // CU encoding: 4 bytes.
721  // Personality: 8 bytes.
722  // LSDA: 8 bytes.
723  CURecordSize = 32;
724  PersonalityEdgeOffset = 16;
725  LSDAEdgeOffset = 24;
726  break;
727  default:
728  return make_error<JITLinkError>(
729  "Error linking " + G.getName() +
730  ": compact unwind splitting not supported on " +
731  G.getTargetTriple().getArchName());
732  }
733 
734  std::vector<Block *> OriginalBlocks(CUSec->blocks().begin(),
735  CUSec->blocks().end());
736  LLVM_DEBUG({
737  dbgs() << "In " << G.getName() << " splitting compact unwind section "
738  << CompactUnwindSectionName << " containing "
739  << OriginalBlocks.size() << " initial blocks...\n";
740  });
741 
742  while (!OriginalBlocks.empty()) {
743  auto *B = OriginalBlocks.back();
744  OriginalBlocks.pop_back();
745 
746  if (B->getSize() == 0) {
747  LLVM_DEBUG({
748  dbgs() << " Skipping empty block at "
749  << formatv("{0:x16}", B->getAddress()) << "\n";
750  });
751  continue;
752  }
753 
754  LLVM_DEBUG({
755  dbgs() << " Splitting block at " << formatv("{0:x16}", B->getAddress())
756  << " into " << (B->getSize() / CURecordSize)
757  << " compact unwind record(s)\n";
758  });
759 
760  if (B->getSize() % CURecordSize)
761  return make_error<JITLinkError>(
762  "Error splitting compact unwind record in " + G.getName() +
763  ": block at " + formatv("{0:x}", B->getAddress()) + " has size " +
764  formatv("{0:x}", B->getSize()) +
765  " (not a multiple of CU record size of " +
766  formatv("{0:x}", CURecordSize) + ")");
767 
768  unsigned NumBlocks = B->getSize() / CURecordSize;
770 
771  for (unsigned I = 0; I != NumBlocks; ++I) {
772  auto &CURec = G.splitBlock(*B, CURecordSize, &C);
773  bool AddedKeepAlive = false;
774 
775  for (auto &E : CURec.edges()) {
776  if (E.getOffset() == 0) {
777  LLVM_DEBUG({
778  dbgs() << " Updating compact unwind record at "
779  << formatv("{0:x16}", CURec.getAddress()) << " to point to "
780  << (E.getTarget().hasName() ? E.getTarget().getName()
781  : StringRef())
782  << " (at " << formatv("{0:x16}", E.getTarget().getAddress())
783  << ")\n";
784  });
785 
786  if (E.getTarget().isExternal())
787  return make_error<JITLinkError>(
788  "Error adding keep-alive edge for compact unwind record at " +
789  formatv("{0:x}", CURec.getAddress()) + ": target " +
790  E.getTarget().getName() + " is an external symbol");
791  auto &TgtBlock = E.getTarget().getBlock();
792  auto &CURecSym =
793  G.addAnonymousSymbol(CURec, 0, CURecordSize, 0, false);
794  TgtBlock.addEdge(Edge::KeepAlive, 0, CURecSym, 0);
795  AddedKeepAlive = true;
796  } else if (E.getOffset() != PersonalityEdgeOffset &&
797  E.getOffset() != LSDAEdgeOffset)
798  return make_error<JITLinkError>("Unexpected edge at offset " +
799  formatv("{0:x}", E.getOffset()) +
800  " in compact unwind record at " +
801  formatv("{0:x}", CURec.getAddress()));
802  }
803 
804  if (!AddedKeepAlive)
805  return make_error<JITLinkError>(
806  "Error adding keep-alive edge for compact unwind record at " +
807  formatv("{0:x}", CURec.getAddress()) +
808  ": no outgoing target edge at offset 0");
809  }
810  }
811  return Error::success();
812 }
813 
814 } // end namespace jitlink
815 } // end namespace llvm
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
llvm::MachO::S_CSTRING_LITERALS
@ S_CSTRING_LITERALS
S_CSTRING_LITERALS - Section with literal C strings.
Definition: MachO.h:129
getPointerSize
static uint64_t getPointerSize(const Value *V, const DataLayout &DL, const TargetLibraryInfo &TLI, const Function *F)
Definition: DeadStoreElimination.cpp:312
llvm::AArch64CC::HI
@ HI
Definition: AArch64BaseInfo.h:263
llvm::MachO::N_WEAK_REF
@ N_WEAK_REF
Definition: MachO.h:339
llvm::MachO::S_ATTR_DEBUG
@ S_ATTR_DEBUG
S_ATTR_DEBUG - A debug section.
Definition: MachO.h:202
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
BlockSize
static const int BlockSize
Definition: TarWriter.cpp:33
llvm::lltok::Error
@ Error
Definition: LLToken.h:21
llvm::object::MachOObjectFile::getSectionIndex
uint64_t getSectionIndex(DataRefImpl Sec) const override
Definition: MachOObjectFile.cpp:1923
llvm::object::Binary::isLittleEndian
bool isLittleEndian() const
Definition: Binary.h:148
llvm::MachO::N_WEAK_DEF
@ N_WEAK_DEF
Definition: MachO.h:340
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:331
llvm::Triple
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:45
llvm::MachO::S_GB_ZEROFILL
@ S_GB_ZEROFILL
S_GB_ZEROFILL - Zero fill on demand section (that can be larger than 4 gigabytes).
Definition: MachO.h:153
llvm::StringMap::end
iterator end()
Definition: StringMap.h:203
llvm::MachO::GET_COMM_ALIGN
uint8_t GET_COMM_ALIGN(uint16_t n_desc)
Definition: MachO.h:1401
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::Triple::x86_64
@ x86_64
Definition: Triple.h:84
llvm::Optional
Definition: APInt.h:33
llvm::MachO::S_ZEROFILL
@ S_ZEROFILL
S_ZEROFILL - Zero fill on demand section.
Definition: MachO.h:127
llvm::MachO::N_UNDF
@ N_UNDF
Definition: MachO.h:310
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
llvm::StringMap::find
iterator find(StringRef Key)
Definition: StringMap.h:216
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::object::MachOObjectFile::getSymbolIndex
uint64_t getSymbolIndex(DataRefImpl Symb) const
Definition: MachOObjectFile.cpp:2534
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::object::MachOObjectFile::getSection
Expected< SectionRef > getSection(unsigned SectionIndex) const
Definition: MachOObjectFile.cpp:1992
llvm::object::ObjectFile::symbols
symbol_iterator_range symbols() const
Definition: ObjectFile.h:314
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::MachO::S_ATTR_PURE_INSTRUCTIONS
@ S_ATTR_PURE_INSTRUCTIONS
S_ATTR_PURE_INSTRUCTIONS - Section contains only true machine instructions.
Definition: MachO.h:187
llvm::ARMBuildAttrs::Section
@ Section
Legacy Tags.
Definition: ARMBuildAttributes.h:78
llvm::MachO::N_TYPE
@ N_TYPE
Definition: MachO.h:303
llvm::formatv
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
Definition: FormatVariadic.h:250
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::support::little
@ little
Definition: Endian.h:27
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::MachO::N_PBUD
@ N_PBUD
Definition: MachO.h:313
getFileName
static Expected< StringRef > getFileName(const DebugStringTableSubsectionRef &Strings, const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID)
Definition: CodeViewYAMLDebugSections.cpp:555
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::AMDGPU::ElfNote::SectionName
const char SectionName[]
Definition: AMDGPUPTNote.h:24
llvm::MachO::SECTION_TYPE
@ SECTION_TYPE
Definition: MachO.h:112
llvm::object::MachOObjectFile::getSection64
MachO::section_64 getSection64(DataRefImpl DRI) const
Definition: MachOObjectFile.cpp:4274
llvm::object::MachOObjectFile
Definition: MachO.h:262
llvm::MachO::S_ATTR_NO_DEAD_STRIP
@ S_ATTR_NO_DEAD_STRIP
S_ATTR_NO_DEAD_STRIP - No dead stripping.
Definition: MachO.h:195
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:202
llvm::object::MachOObjectFile::is64Bit
bool is64Bit() const
Definition: MachOObjectFile.cpp:4635
llvm::object::MachOObjectFile::getSymbol64TableEntry
MachO::nlist_64 getSymbol64TableEntry(DataRefImpl DRI) const
Definition: MachOObjectFile.cpp:4298
uint64_t
llvm::MachO::N_ALT_ENTRY
@ N_ALT_ENTRY
Definition: MachO.h:342
llvm::MachO::N_INDR
@ N_INDR
Definition: MachO.h:314
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
I
#define I(x, y, z)
Definition: MD5.cpp:59
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1609
memcpy
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
CommonSectionName
static const char * CommonSectionName
Definition: MachOLinkGraphBuilder.cpp:17
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::MachO::N_PEXT
@ N_PEXT
Definition: MachO.h:302
llvm::MachO::N_SECT
@ N_SECT
Definition: MachO.h:312
if
if(llvm_vc STREQUAL "") set(fake_version_inc "$
Definition: CMakeLists.txt:14
uint32_t
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::MachO::N_ABS
@ N_ABS
Definition: MachO.h:311
llvm::MachO::N_NO_DEAD_STRIP
@ N_NO_DEAD_STRIP
Definition: MachO.h:338
llvm::object::MachOObjectFile::getSymbolTableEntry
MachO::nlist getSymbolTableEntry(DataRefImpl DRI) const
Definition: MachOObjectFile.cpp:4292
llvm::MachO::N_EXT
@ N_EXT
Definition: MachO.h:304
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
std
Definition: BitVector.h:838
llvm::MachO::N_STAB
@ N_STAB
Definition: MachO.h:301
uint16_t
llvm::SectionName
Definition: DWARFSection.h:21
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1492
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
llvm::StringMap::count
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
Definition: StringMap.h:244
llvm::JITTargetAddress
uint64_t JITTargetAddress
Represents an address in the target process's address space.
Definition: JITSymbol.h:42
llvm::MachO::S_THREAD_LOCAL_ZEROFILL
@ S_THREAD_LOCAL_ZEROFILL
S_THREAD_LOCAL_ZEROFILL - Thread local zerofill section.
Definition: MachO.h:167
llvm::ARMBuildAttrs::Symbol
@ Symbol
Definition: ARMBuildAttributes.h:79
llvm::object::ObjectFile::sections
section_iterator_range sections() const
Definition: ObjectFile.h:322
llvm::support::endianness
endianness
Definition: Endian.h:27
llvm::StringRef::data
const LLVM_NODISCARD char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:149
llvm::object::Binary::getData
StringRef getData() const
Definition: Binary.cpp:40
llvm::msgpack::Type
Type
MessagePack types as defined in the standard, with the exception of Integer being divided into a sign...
Definition: MsgPackReader.h:49
MachOLinkGraphBuilder.h
llvm::StringRef::size
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:157
llvm::pdb::PDB_SymType::Block
@ Block
llvm::Triple::aarch64
@ aarch64
Definition: Triple.h:52
llvm::support::big
@ big
Definition: Endian.h:27
SpecialSubKind::string
@ string
llvm::object::MachOObjectFile::isRelocatableObject
bool isRelocatableObject() const override
True if this is a relocatable object (.o/.obj).
Definition: MachOObjectFile.cpp:4652