MachOLinkGraphBuilder.cpp 30 KB

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