MachO_arm64.cpp 27 KB

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