MachO_x86_64.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. //===---- MachO_x86_64.cpp -JIT linker implementation for MachO/x86-64 ----===//
  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. // MachO/x86-64 jit-link implementation.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "llvm/ExecutionEngine/JITLink/MachO_x86_64.h"
  13. #include "BasicGOTAndStubsBuilder.h"
  14. #include "MachOLinkGraphBuilder.h"
  15. #define DEBUG_TYPE "jitlink"
  16. using namespace llvm;
  17. using namespace llvm::jitlink;
  18. using namespace llvm::jitlink::MachO_x86_64_Edges;
  19. namespace {
  20. class MachOLinkGraphBuilder_x86_64 : public MachOLinkGraphBuilder {
  21. public:
  22. MachOLinkGraphBuilder_x86_64(const object::MachOObjectFile &Obj)
  23. : MachOLinkGraphBuilder(Obj, Triple("x86_64-apple-darwin")) {}
  24. private:
  25. static Expected<MachOX86RelocationKind>
  26. getRelocationKind(const MachO::relocation_info &RI) {
  27. switch (RI.r_type) {
  28. case MachO::X86_64_RELOC_UNSIGNED:
  29. if (!RI.r_pcrel) {
  30. if (RI.r_length == 3)
  31. return RI.r_extern ? Pointer64 : Pointer64Anon;
  32. else if (RI.r_extern && RI.r_length == 2)
  33. return Pointer32;
  34. }
  35. break;
  36. case MachO::X86_64_RELOC_SIGNED:
  37. if (RI.r_pcrel && RI.r_length == 2)
  38. return RI.r_extern ? PCRel32 : PCRel32Anon;
  39. break;
  40. case MachO::X86_64_RELOC_BRANCH:
  41. if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
  42. return Branch32;
  43. break;
  44. case MachO::X86_64_RELOC_GOT_LOAD:
  45. if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
  46. return PCRel32GOTLoad;
  47. break;
  48. case MachO::X86_64_RELOC_GOT:
  49. if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
  50. return PCRel32GOT;
  51. break;
  52. case MachO::X86_64_RELOC_SUBTRACTOR:
  53. // SUBTRACTOR must be non-pc-rel, extern, with length 2 or 3.
  54. // Initially represent SUBTRACTOR relocations with 'Delta<W>'. They may
  55. // be turned into NegDelta<W> by parsePairRelocation.
  56. if (!RI.r_pcrel && RI.r_extern) {
  57. if (RI.r_length == 2)
  58. return Delta32;
  59. else if (RI.r_length == 3)
  60. return Delta64;
  61. }
  62. break;
  63. case MachO::X86_64_RELOC_SIGNED_1:
  64. if (RI.r_pcrel && RI.r_length == 2)
  65. return RI.r_extern ? PCRel32Minus1 : PCRel32Minus1Anon;
  66. break;
  67. case MachO::X86_64_RELOC_SIGNED_2:
  68. if (RI.r_pcrel && RI.r_length == 2)
  69. return RI.r_extern ? PCRel32Minus2 : PCRel32Minus2Anon;
  70. break;
  71. case MachO::X86_64_RELOC_SIGNED_4:
  72. if (RI.r_pcrel && RI.r_length == 2)
  73. return RI.r_extern ? PCRel32Minus4 : PCRel32Minus4Anon;
  74. break;
  75. case MachO::X86_64_RELOC_TLV:
  76. if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
  77. return PCRel32TLV;
  78. break;
  79. }
  80. return make_error<JITLinkError>(
  81. "Unsupported x86-64 relocation: address=" +
  82. formatv("{0:x8}", RI.r_address) +
  83. ", symbolnum=" + formatv("{0:x6}", RI.r_symbolnum) +
  84. ", kind=" + formatv("{0:x1}", RI.r_type) +
  85. ", pc_rel=" + (RI.r_pcrel ? "true" : "false") +
  86. ", extern=" + (RI.r_extern ? "true" : "false") +
  87. ", length=" + formatv("{0:d}", RI.r_length));
  88. }
  89. using PairRelocInfo = std::tuple<MachOX86RelocationKind, Symbol *, uint64_t>;
  90. // Parses paired SUBTRACTOR/UNSIGNED relocations and, on success,
  91. // returns the edge kind and addend to be used.
  92. Expected<PairRelocInfo>
  93. parsePairRelocation(Block &BlockToFix, Edge::Kind SubtractorKind,
  94. const MachO::relocation_info &SubRI,
  95. JITTargetAddress FixupAddress, const char *FixupContent,
  96. object::relocation_iterator &UnsignedRelItr,
  97. object::relocation_iterator &RelEnd) {
  98. using namespace support;
  99. assert(((SubtractorKind == Delta32 && SubRI.r_length == 2) ||
  100. (SubtractorKind == Delta64 && SubRI.r_length == 3)) &&
  101. "Subtractor kind should match length");
  102. assert(SubRI.r_extern && "SUBTRACTOR reloc symbol should be extern");
  103. assert(!SubRI.r_pcrel && "SUBTRACTOR reloc should not be PCRel");
  104. if (UnsignedRelItr == RelEnd)
  105. return make_error<JITLinkError>("x86_64 SUBTRACTOR without paired "
  106. "UNSIGNED relocation");
  107. auto UnsignedRI = getRelocationInfo(UnsignedRelItr);
  108. if (SubRI.r_address != UnsignedRI.r_address)
  109. return make_error<JITLinkError>("x86_64 SUBTRACTOR and paired UNSIGNED "
  110. "point to different addresses");
  111. if (SubRI.r_length != UnsignedRI.r_length)
  112. return make_error<JITLinkError>("length of x86_64 SUBTRACTOR and paired "
  113. "UNSIGNED reloc must match");
  114. Symbol *FromSymbol;
  115. if (auto FromSymbolOrErr = findSymbolByIndex(SubRI.r_symbolnum))
  116. FromSymbol = FromSymbolOrErr->GraphSymbol;
  117. else
  118. return FromSymbolOrErr.takeError();
  119. // Read the current fixup value.
  120. uint64_t FixupValue = 0;
  121. if (SubRI.r_length == 3)
  122. FixupValue = *(const little64_t *)FixupContent;
  123. else
  124. FixupValue = *(const little32_t *)FixupContent;
  125. // Find 'ToSymbol' using symbol number or address, depending on whether the
  126. // paired UNSIGNED relocation is extern.
  127. Symbol *ToSymbol = nullptr;
  128. if (UnsignedRI.r_extern) {
  129. // Find target symbol by symbol index.
  130. if (auto ToSymbolOrErr = findSymbolByIndex(UnsignedRI.r_symbolnum))
  131. ToSymbol = ToSymbolOrErr->GraphSymbol;
  132. else
  133. return ToSymbolOrErr.takeError();
  134. } else {
  135. auto ToSymbolSec = findSectionByIndex(UnsignedRI.r_symbolnum - 1);
  136. if (!ToSymbolSec)
  137. return ToSymbolSec.takeError();
  138. ToSymbol = getSymbolByAddress(ToSymbolSec->Address);
  139. assert(ToSymbol && "No symbol for section");
  140. FixupValue -= ToSymbol->getAddress();
  141. }
  142. MachOX86RelocationKind DeltaKind;
  143. Symbol *TargetSymbol;
  144. uint64_t Addend;
  145. if (&BlockToFix == &FromSymbol->getAddressable()) {
  146. TargetSymbol = ToSymbol;
  147. DeltaKind = (SubRI.r_length == 3) ? Delta64 : Delta32;
  148. Addend = FixupValue + (FixupAddress - FromSymbol->getAddress());
  149. // FIXME: handle extern 'from'.
  150. } else if (&BlockToFix == &ToSymbol->getAddressable()) {
  151. TargetSymbol = FromSymbol;
  152. DeltaKind = (SubRI.r_length == 3) ? NegDelta64 : NegDelta32;
  153. Addend = FixupValue - (FixupAddress - ToSymbol->getAddress());
  154. } else {
  155. // BlockToFix was neither FromSymbol nor ToSymbol.
  156. return make_error<JITLinkError>("SUBTRACTOR relocation must fix up "
  157. "either 'A' or 'B' (or a symbol in one "
  158. "of their alt-entry chains)");
  159. }
  160. return PairRelocInfo(DeltaKind, TargetSymbol, Addend);
  161. }
  162. Error addRelocations() override {
  163. using namespace support;
  164. auto &Obj = getObject();
  165. LLVM_DEBUG(dbgs() << "Processing relocations:\n");
  166. for (auto &S : Obj.sections()) {
  167. JITTargetAddress SectionAddress = S.getAddress();
  168. // Skip relocations virtual sections.
  169. if (S.isVirtual()) {
  170. if (S.relocation_begin() != S.relocation_end())
  171. return make_error<JITLinkError>("Virtual section contains "
  172. "relocations");
  173. continue;
  174. }
  175. // Skip relocations for debug symbols.
  176. {
  177. auto &NSec =
  178. getSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));
  179. if (!NSec.GraphSection) {
  180. LLVM_DEBUG({
  181. dbgs() << " Skipping relocations for MachO section "
  182. << NSec.SegName << "/" << NSec.SectName
  183. << " which has no associated graph section\n";
  184. });
  185. continue;
  186. }
  187. }
  188. // Add relocations for section.
  189. for (auto RelItr = S.relocation_begin(), RelEnd = S.relocation_end();
  190. RelItr != RelEnd; ++RelItr) {
  191. MachO::relocation_info RI = getRelocationInfo(RelItr);
  192. // Sanity check the relocation kind.
  193. auto Kind = getRelocationKind(RI);
  194. if (!Kind)
  195. return Kind.takeError();
  196. // Find the address of the value to fix up.
  197. JITTargetAddress FixupAddress = SectionAddress + (uint32_t)RI.r_address;
  198. LLVM_DEBUG({
  199. auto &NSec =
  200. getSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));
  201. dbgs() << " " << NSec.SectName << " + "
  202. << formatv("{0:x8}", RI.r_address) << ":\n";
  203. });
  204. // Find the block that the fixup points to.
  205. Block *BlockToFix = nullptr;
  206. {
  207. auto SymbolToFixOrErr = findSymbolByAddress(FixupAddress);
  208. if (!SymbolToFixOrErr)
  209. return SymbolToFixOrErr.takeError();
  210. BlockToFix = &SymbolToFixOrErr->getBlock();
  211. }
  212. if (FixupAddress + static_cast<JITTargetAddress>(1ULL << RI.r_length) >
  213. BlockToFix->getAddress() + BlockToFix->getContent().size())
  214. return make_error<JITLinkError>(
  215. "Relocation extends past end of fixup block");
  216. // Get a pointer to the fixup content.
  217. const char *FixupContent = BlockToFix->getContent().data() +
  218. (FixupAddress - BlockToFix->getAddress());
  219. // The target symbol and addend will be populated by the switch below.
  220. Symbol *TargetSymbol = nullptr;
  221. uint64_t Addend = 0;
  222. switch (*Kind) {
  223. case Branch32:
  224. case PCRel32:
  225. case PCRel32GOTLoad:
  226. case PCRel32GOT:
  227. if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
  228. TargetSymbol = TargetSymbolOrErr->GraphSymbol;
  229. else
  230. return TargetSymbolOrErr.takeError();
  231. Addend = *(const little32_t *)FixupContent;
  232. break;
  233. case Pointer32:
  234. if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
  235. TargetSymbol = TargetSymbolOrErr->GraphSymbol;
  236. else
  237. return TargetSymbolOrErr.takeError();
  238. Addend = *(const ulittle32_t *)FixupContent;
  239. break;
  240. case Pointer64:
  241. if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
  242. TargetSymbol = TargetSymbolOrErr->GraphSymbol;
  243. else
  244. return TargetSymbolOrErr.takeError();
  245. Addend = *(const ulittle64_t *)FixupContent;
  246. break;
  247. case Pointer64Anon: {
  248. JITTargetAddress TargetAddress = *(const ulittle64_t *)FixupContent;
  249. if (auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
  250. TargetSymbol = &*TargetSymbolOrErr;
  251. else
  252. return TargetSymbolOrErr.takeError();
  253. Addend = TargetAddress - TargetSymbol->getAddress();
  254. break;
  255. }
  256. case PCRel32Minus1:
  257. case PCRel32Minus2:
  258. case PCRel32Minus4:
  259. if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
  260. TargetSymbol = TargetSymbolOrErr->GraphSymbol;
  261. else
  262. return TargetSymbolOrErr.takeError();
  263. Addend = *(const little32_t *)FixupContent +
  264. (1 << (*Kind - PCRel32Minus1));
  265. break;
  266. case PCRel32Anon: {
  267. JITTargetAddress TargetAddress =
  268. FixupAddress + 4 + *(const little32_t *)FixupContent;
  269. if (auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
  270. TargetSymbol = &*TargetSymbolOrErr;
  271. else
  272. return TargetSymbolOrErr.takeError();
  273. Addend = TargetAddress - TargetSymbol->getAddress();
  274. break;
  275. }
  276. case PCRel32Minus1Anon:
  277. case PCRel32Minus2Anon:
  278. case PCRel32Minus4Anon: {
  279. JITTargetAddress Delta =
  280. static_cast<JITTargetAddress>(1ULL << (*Kind - PCRel32Minus1Anon));
  281. JITTargetAddress TargetAddress =
  282. FixupAddress + 4 + Delta + *(const little32_t *)FixupContent;
  283. if (auto TargetSymbolOrErr = findSymbolByAddress(TargetAddress))
  284. TargetSymbol = &*TargetSymbolOrErr;
  285. else
  286. return TargetSymbolOrErr.takeError();
  287. Addend = TargetAddress - TargetSymbol->getAddress();
  288. break;
  289. }
  290. case Delta32:
  291. case Delta64: {
  292. // We use Delta32/Delta64 to represent SUBTRACTOR relocations.
  293. // parsePairRelocation handles the paired reloc, and returns the
  294. // edge kind to be used (either Delta32/Delta64, or
  295. // NegDelta32/NegDelta64, depending on the direction of the
  296. // subtraction) along with the addend.
  297. auto PairInfo =
  298. parsePairRelocation(*BlockToFix, *Kind, RI, FixupAddress,
  299. FixupContent, ++RelItr, RelEnd);
  300. if (!PairInfo)
  301. return PairInfo.takeError();
  302. std::tie(*Kind, TargetSymbol, Addend) = *PairInfo;
  303. assert(TargetSymbol && "No target symbol from parsePairRelocation?");
  304. break;
  305. }
  306. case PCRel32TLV:
  307. return make_error<JITLinkError>(
  308. "MachO TLV relocations not yet supported");
  309. default:
  310. llvm_unreachable("Special relocation kind should not appear in "
  311. "mach-o file");
  312. }
  313. LLVM_DEBUG({
  314. dbgs() << " ";
  315. Edge GE(*Kind, FixupAddress - BlockToFix->getAddress(), *TargetSymbol,
  316. Addend);
  317. printEdge(dbgs(), *BlockToFix, GE,
  318. getMachOX86RelocationKindName(*Kind));
  319. dbgs() << "\n";
  320. });
  321. BlockToFix->addEdge(*Kind, FixupAddress - BlockToFix->getAddress(),
  322. *TargetSymbol, Addend);
  323. }
  324. }
  325. return Error::success();
  326. }
  327. };
  328. class MachO_x86_64_GOTAndStubsBuilder
  329. : public BasicGOTAndStubsBuilder<MachO_x86_64_GOTAndStubsBuilder> {
  330. public:
  331. static const uint8_t NullGOTEntryContent[8];
  332. static const uint8_t StubContent[6];
  333. MachO_x86_64_GOTAndStubsBuilder(LinkGraph &G)
  334. : BasicGOTAndStubsBuilder<MachO_x86_64_GOTAndStubsBuilder>(G) {}
  335. bool isGOTEdge(Edge &E) const {
  336. return E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad;
  337. }
  338. Symbol &createGOTEntry(Symbol &Target) {
  339. auto &GOTEntryBlock = G.createContentBlock(
  340. getGOTSection(), getGOTEntryBlockContent(), 0, 8, 0);
  341. GOTEntryBlock.addEdge(Pointer64, 0, Target, 0);
  342. return G.addAnonymousSymbol(GOTEntryBlock, 0, 8, false, false);
  343. }
  344. void fixGOTEdge(Edge &E, Symbol &GOTEntry) {
  345. assert((E.getKind() == PCRel32GOT || E.getKind() == PCRel32GOTLoad) &&
  346. "Not a GOT edge?");
  347. // If this is a PCRel32GOT then change it to an ordinary PCRel32. If it is
  348. // a PCRel32GOTLoad then leave it as-is for now. We will use the kind to
  349. // check for GOT optimization opportunities in the
  350. // optimizeMachO_x86_64_GOTAndStubs pass below.
  351. if (E.getKind() == PCRel32GOT)
  352. E.setKind(PCRel32);
  353. E.setTarget(GOTEntry);
  354. // Leave the edge addend as-is.
  355. }
  356. bool isExternalBranchEdge(Edge &E) {
  357. return E.getKind() == Branch32 && !E.getTarget().isDefined();
  358. }
  359. Symbol &createStub(Symbol &Target) {
  360. auto &StubContentBlock =
  361. G.createContentBlock(getStubsSection(), getStubBlockContent(), 0, 1, 0);
  362. // Re-use GOT entries for stub targets.
  363. auto &GOTEntrySymbol = getGOTEntrySymbol(Target);
  364. StubContentBlock.addEdge(PCRel32, 2, GOTEntrySymbol, 0);
  365. return G.addAnonymousSymbol(StubContentBlock, 0, 6, true, false);
  366. }
  367. void fixExternalBranchEdge(Edge &E, Symbol &Stub) {
  368. assert(E.getKind() == Branch32 && "Not a Branch32 edge?");
  369. assert(E.getAddend() == 0 && "Branch32 edge has non-zero addend?");
  370. // Set the edge kind to Branch32ToStub. We will use this to check for stub
  371. // optimization opportunities in the optimizeMachO_x86_64_GOTAndStubs pass
  372. // below.
  373. E.setKind(Branch32ToStub);
  374. E.setTarget(Stub);
  375. }
  376. private:
  377. Section &getGOTSection() {
  378. if (!GOTSection)
  379. GOTSection = &G.createSection("$__GOT", sys::Memory::MF_READ);
  380. return *GOTSection;
  381. }
  382. Section &getStubsSection() {
  383. if (!StubsSection) {
  384. auto StubsProt = static_cast<sys::Memory::ProtectionFlags>(
  385. sys::Memory::MF_READ | sys::Memory::MF_EXEC);
  386. StubsSection = &G.createSection("$__STUBS", StubsProt);
  387. }
  388. return *StubsSection;
  389. }
  390. StringRef getGOTEntryBlockContent() {
  391. return StringRef(reinterpret_cast<const char *>(NullGOTEntryContent),
  392. sizeof(NullGOTEntryContent));
  393. }
  394. StringRef getStubBlockContent() {
  395. return StringRef(reinterpret_cast<const char *>(StubContent),
  396. sizeof(StubContent));
  397. }
  398. Section *GOTSection = nullptr;
  399. Section *StubsSection = nullptr;
  400. };
  401. const uint8_t MachO_x86_64_GOTAndStubsBuilder::NullGOTEntryContent[8] = {
  402. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  403. const uint8_t MachO_x86_64_GOTAndStubsBuilder::StubContent[6] = {
  404. 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00};
  405. } // namespace
  406. static Error optimizeMachO_x86_64_GOTAndStubs(LinkGraph &G) {
  407. LLVM_DEBUG(dbgs() << "Optimizing GOT entries and stubs:\n");
  408. for (auto *B : G.blocks())
  409. for (auto &E : B->edges())
  410. if (E.getKind() == PCRel32GOTLoad) {
  411. assert(E.getOffset() >= 3 && "GOT edge occurs too early in block");
  412. // Switch the edge kind to PCRel32: Whether we change the edge target
  413. // or not this will be the desired kind.
  414. E.setKind(PCRel32);
  415. // Optimize GOT references.
  416. auto &GOTBlock = E.getTarget().getBlock();
  417. assert(GOTBlock.getSize() == G.getPointerSize() &&
  418. "GOT entry block should be pointer sized");
  419. assert(GOTBlock.edges_size() == 1 &&
  420. "GOT entry should only have one outgoing edge");
  421. auto &GOTTarget = GOTBlock.edges().begin()->getTarget();
  422. JITTargetAddress EdgeAddr = B->getAddress() + E.getOffset();
  423. JITTargetAddress TargetAddr = GOTTarget.getAddress();
  424. // Check that this is a recognized MOV instruction.
  425. // FIXME: Can we assume this?
  426. constexpr uint8_t MOVQRIPRel[] = {0x48, 0x8b};
  427. if (strncmp(B->getContent().data() + E.getOffset() - 3,
  428. reinterpret_cast<const char *>(MOVQRIPRel), 2) != 0)
  429. continue;
  430. int64_t Displacement = TargetAddr - EdgeAddr + 4;
  431. if (Displacement >= std::numeric_limits<int32_t>::min() &&
  432. Displacement <= std::numeric_limits<int32_t>::max()) {
  433. E.setTarget(GOTTarget);
  434. auto *BlockData = reinterpret_cast<uint8_t *>(
  435. const_cast<char *>(B->getContent().data()));
  436. BlockData[E.getOffset() - 2] = 0x8d;
  437. LLVM_DEBUG({
  438. dbgs() << " Replaced GOT load wih LEA:\n ";
  439. printEdge(dbgs(), *B, E,
  440. getMachOX86RelocationKindName(E.getKind()));
  441. dbgs() << "\n";
  442. });
  443. }
  444. } else if (E.getKind() == Branch32ToStub) {
  445. // Switch the edge kind to PCRel32: Whether we change the edge target
  446. // or not this will be the desired kind.
  447. E.setKind(Branch32);
  448. auto &StubBlock = E.getTarget().getBlock();
  449. assert(StubBlock.getSize() ==
  450. sizeof(MachO_x86_64_GOTAndStubsBuilder::StubContent) &&
  451. "Stub block should be stub sized");
  452. assert(StubBlock.edges_size() == 1 &&
  453. "Stub block should only have one outgoing edge");
  454. auto &GOTBlock = StubBlock.edges().begin()->getTarget().getBlock();
  455. assert(GOTBlock.getSize() == G.getPointerSize() &&
  456. "GOT block should be pointer sized");
  457. assert(GOTBlock.edges_size() == 1 &&
  458. "GOT block should only have one outgoing edge");
  459. auto &GOTTarget = GOTBlock.edges().begin()->getTarget();
  460. JITTargetAddress EdgeAddr = B->getAddress() + E.getOffset();
  461. JITTargetAddress TargetAddr = GOTTarget.getAddress();
  462. int64_t Displacement = TargetAddr - EdgeAddr + 4;
  463. if (Displacement >= std::numeric_limits<int32_t>::min() &&
  464. Displacement <= std::numeric_limits<int32_t>::max()) {
  465. E.setTarget(GOTTarget);
  466. LLVM_DEBUG({
  467. dbgs() << " Replaced stub branch with direct branch:\n ";
  468. printEdge(dbgs(), *B, E,
  469. getMachOX86RelocationKindName(E.getKind()));
  470. dbgs() << "\n";
  471. });
  472. }
  473. }
  474. return Error::success();
  475. }
  476. namespace llvm {
  477. namespace jitlink {
  478. class MachOJITLinker_x86_64 : public JITLinker<MachOJITLinker_x86_64> {
  479. friend class JITLinker<MachOJITLinker_x86_64>;
  480. public:
  481. MachOJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,
  482. std::unique_ptr<LinkGraph> G,
  483. PassConfiguration PassConfig)
  484. : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
  485. private:
  486. StringRef getEdgeKindName(Edge::Kind R) const override {
  487. return getMachOX86RelocationKindName(R);
  488. }
  489. static Error targetOutOfRangeError(const Block &B, const Edge &E) {
  490. std::string ErrMsg;
  491. {
  492. raw_string_ostream ErrStream(ErrMsg);
  493. ErrStream << "Relocation target out of range: ";
  494. printEdge(ErrStream, B, E, getMachOX86RelocationKindName(E.getKind()));
  495. ErrStream << "\n";
  496. }
  497. return make_error<JITLinkError>(std::move(ErrMsg));
  498. }
  499. Error applyFixup(Block &B, const Edge &E, char *BlockWorkingMem) const {
  500. using namespace support;
  501. char *FixupPtr = BlockWorkingMem + E.getOffset();
  502. JITTargetAddress FixupAddress = B.getAddress() + E.getOffset();
  503. switch (E.getKind()) {
  504. case Branch32:
  505. case PCRel32:
  506. case PCRel32Anon: {
  507. int64_t Value =
  508. E.getTarget().getAddress() - (FixupAddress + 4) + E.getAddend();
  509. if (Value < std::numeric_limits<int32_t>::min() ||
  510. Value > std::numeric_limits<int32_t>::max())
  511. return targetOutOfRangeError(B, E);
  512. *(little32_t *)FixupPtr = Value;
  513. break;
  514. }
  515. case Pointer64:
  516. case Pointer64Anon: {
  517. uint64_t Value = E.getTarget().getAddress() + E.getAddend();
  518. *(ulittle64_t *)FixupPtr = Value;
  519. break;
  520. }
  521. case PCRel32Minus1:
  522. case PCRel32Minus2:
  523. case PCRel32Minus4: {
  524. int Delta = 4 + (1 << (E.getKind() - PCRel32Minus1));
  525. int64_t Value =
  526. E.getTarget().getAddress() - (FixupAddress + Delta) + E.getAddend();
  527. if (Value < std::numeric_limits<int32_t>::min() ||
  528. Value > std::numeric_limits<int32_t>::max())
  529. return targetOutOfRangeError(B, E);
  530. *(little32_t *)FixupPtr = Value;
  531. break;
  532. }
  533. case PCRel32Minus1Anon:
  534. case PCRel32Minus2Anon:
  535. case PCRel32Minus4Anon: {
  536. int Delta = 4 + (1 << (E.getKind() - PCRel32Minus1Anon));
  537. int64_t Value =
  538. E.getTarget().getAddress() - (FixupAddress + Delta) + E.getAddend();
  539. if (Value < std::numeric_limits<int32_t>::min() ||
  540. Value > std::numeric_limits<int32_t>::max())
  541. return targetOutOfRangeError(B, E);
  542. *(little32_t *)FixupPtr = Value;
  543. break;
  544. }
  545. case Delta32:
  546. case Delta64:
  547. case NegDelta32:
  548. case NegDelta64: {
  549. int64_t Value;
  550. if (E.getKind() == Delta32 || E.getKind() == Delta64)
  551. Value = E.getTarget().getAddress() - FixupAddress + E.getAddend();
  552. else
  553. Value = FixupAddress - E.getTarget().getAddress() + E.getAddend();
  554. if (E.getKind() == Delta32 || E.getKind() == NegDelta32) {
  555. if (Value < std::numeric_limits<int32_t>::min() ||
  556. Value > std::numeric_limits<int32_t>::max())
  557. return targetOutOfRangeError(B, E);
  558. *(little32_t *)FixupPtr = Value;
  559. } else
  560. *(little64_t *)FixupPtr = Value;
  561. break;
  562. }
  563. case Pointer32: {
  564. uint64_t Value = E.getTarget().getAddress() + E.getAddend();
  565. if (Value > std::numeric_limits<uint32_t>::max())
  566. return targetOutOfRangeError(B, E);
  567. *(ulittle32_t *)FixupPtr = Value;
  568. break;
  569. }
  570. default:
  571. llvm_unreachable("Unrecognized edge kind");
  572. }
  573. return Error::success();
  574. }
  575. uint64_t NullValue = 0;
  576. };
  577. Expected<std::unique_ptr<LinkGraph>>
  578. createLinkGraphFromMachOObject_x86_64(MemoryBufferRef ObjectBuffer) {
  579. auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjectBuffer);
  580. if (!MachOObj)
  581. return MachOObj.takeError();
  582. return MachOLinkGraphBuilder_x86_64(**MachOObj).buildGraph();
  583. }
  584. void link_MachO_x86_64(std::unique_ptr<LinkGraph> G,
  585. std::unique_ptr<JITLinkContext> Ctx) {
  586. PassConfiguration Config;
  587. if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
  588. // Add eh-frame passses.
  589. Config.PrePrunePasses.push_back(EHFrameSplitter("__eh_frame"));
  590. Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
  591. "__eh_frame", G->getPointerSize(), Delta64, Delta32, NegDelta32));
  592. // Add a mark-live pass.
  593. if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
  594. Config.PrePrunePasses.push_back(std::move(MarkLive));
  595. else
  596. Config.PrePrunePasses.push_back(markAllSymbolsLive);
  597. // Add an in-place GOT/Stubs pass.
  598. Config.PostPrunePasses.push_back([](LinkGraph &G) -> Error {
  599. MachO_x86_64_GOTAndStubsBuilder(G).run();
  600. return Error::success();
  601. });
  602. // Add GOT/Stubs optimizer pass.
  603. Config.PreFixupPasses.push_back(optimizeMachO_x86_64_GOTAndStubs);
  604. }
  605. if (auto Err = Ctx->modifyPassConfig(G->getTargetTriple(), Config))
  606. return Ctx->notifyFailed(std::move(Err));
  607. // Construct a JITLinker and run the link function.
  608. MachOJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config));
  609. }
  610. StringRef getMachOX86RelocationKindName(Edge::Kind R) {
  611. switch (R) {
  612. case Branch32:
  613. return "Branch32";
  614. case Branch32ToStub:
  615. return "Branch32ToStub";
  616. case Pointer32:
  617. return "Pointer32";
  618. case Pointer64:
  619. return "Pointer64";
  620. case Pointer64Anon:
  621. return "Pointer64Anon";
  622. case PCRel32:
  623. return "PCRel32";
  624. case PCRel32Minus1:
  625. return "PCRel32Minus1";
  626. case PCRel32Minus2:
  627. return "PCRel32Minus2";
  628. case PCRel32Minus4:
  629. return "PCRel32Minus4";
  630. case PCRel32Anon:
  631. return "PCRel32Anon";
  632. case PCRel32Minus1Anon:
  633. return "PCRel32Minus1Anon";
  634. case PCRel32Minus2Anon:
  635. return "PCRel32Minus2Anon";
  636. case PCRel32Minus4Anon:
  637. return "PCRel32Minus4Anon";
  638. case PCRel32GOTLoad:
  639. return "PCRel32GOTLoad";
  640. case PCRel32GOT:
  641. return "PCRel32GOT";
  642. case PCRel32TLV:
  643. return "PCRel32TLV";
  644. case Delta32:
  645. return "Delta32";
  646. case Delta64:
  647. return "Delta64";
  648. case NegDelta32:
  649. return "NegDelta32";
  650. case NegDelta64:
  651. return "NegDelta64";
  652. default:
  653. return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
  654. }
  655. }
  656. } // end namespace jitlink
  657. } // end namespace llvm