14 #define DEBUG_TYPE "orc"
18 template <
typename ORCABI>
22 constexpr
unsigned MaxDisp = ORCABI::StubToPointerMaxDisplacement;
27 FirstPointer + ((NumStubs - 1) * ORCABI::StubSize);
29 if (FirstStub < FirstPointer) {
30 if (LastStub >= FirstPointer)
32 return (FirstPointer - FirstStub <= MaxDisp) &&
33 (LastPointer - LastStub <= MaxDisp);
36 if (LastPointer >= FirstStub)
39 return (FirstStub - FirstPointer <= MaxDisp) &&
40 (LastStub - LastPointer <= MaxDisp);
127 const unsigned ReentryFnAddrOffset = 0x110;
128 const unsigned ReentryCtxAddrOffset = 0x118;
130 memcpy(ResolverWorkingMem, ResolverCode,
sizeof(ResolverCode));
131 memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnAddr,
133 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxAddr,
140 unsigned NumTrampolines) {
144 memcpy(TrampolineBlockWorkingMem + OffsetToPtr, &ResolverAddr,
152 reinterpret_cast<uint32_t *
>(TrampolineBlockWorkingMem);
155 Trampolines[3 *
I + 0] = 0xaa1e03f1;
156 Trampolines[3 *
I + 1] = 0x58000010 | (OffsetToPtr << 3);
157 Trampolines[3 *
I + 2] = 0xd63f0200;
185 "Pointer and stub size must match for algorithm below");
186 assert(stubAndPointerRangesOk<OrcAArch64>(
187 StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) &&
188 "PointersBlock is out of range");
190 PointersBlockTargetAddress - StubsBlockTargetAddress;
192 uint64_t PtrOffsetField = PtrDisplacement << 3;
194 for (
unsigned I = 0;
I < NumStubs; ++
I)
195 Stub[
I] = 0xd61f020058000010 | PtrOffsetField;
199 char *TrampolineBlockWorkingMem,
205 memcpy(TrampolineBlockWorkingMem + OffsetToPtr, &ResolverAddr,
209 reinterpret_cast<uint64_t *
>(TrampolineBlockWorkingMem);
210 uint64_t CallIndirPCRel = 0xf1c40000000015ff;
213 Trampolines[
I] = CallIndirPCRel | ((OffsetToPtr - 6) << 16);
241 "Pointer and stub size must match for algorithm below");
242 assert(stubAndPointerRangesOk<OrcX86_64_Base>(
243 StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) &&
244 "PointersBlock is out of range");
247 (PointersBlockTargetAddress - StubsBlockTargetAddress - 6) << 16;
248 for (
unsigned I = 0;
I < NumStubs; ++
I)
249 Stub[
I] = 0xF1C40000000025ff | PtrOffsetField;
258 dbgs() <<
"Writing resolver code to "
259 <<
formatv(
"{0:x16}", ResolverTargetAddress) <<
"\n";
262 const uint8_t ResolverCode[] = {
280 0x48, 0x81, 0xec, 0x08, 0x02, 0x00, 0x00,
281 0x48, 0x0f, 0xae, 0x04, 0x24,
285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287 0x48, 0x8b, 0x75, 0x08,
288 0x48, 0x83, 0xee, 0x06,
292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
295 0x48, 0x89, 0x45, 0x08,
296 0x48, 0x0f, 0xae, 0x0c, 0x24,
297 0x48, 0x81, 0xc4, 0x08, 0x02, 0x00, 0x00,
316 const unsigned ReentryFnAddrOffset = 0x3a;
317 const unsigned ReentryCtxAddrOffset = 0x28;
319 memcpy(ResolverWorkingMem, ResolverCode,
sizeof(ResolverCode));
320 memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnAddr,
322 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxAddr,
334 const uint8_t ResolverCode[] = {
352 0x48, 0x81, 0xec, 0x08, 0x02, 0x00, 0x00,
353 0x48, 0x0f, 0xae, 0x04, 0x24,
357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359 0x48, 0x8B, 0x55, 0x08,
360 0x48, 0x83, 0xea, 0x06,
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367 0x48, 0x83, 0xEC, 0x20,
371 0x48, 0x83, 0xC4, 0x20,
373 0x48, 0x89, 0x45, 0x08,
374 0x48, 0x0f, 0xae, 0x0c, 0x24,
375 0x48, 0x81, 0xc4, 0x08, 0x02, 0x00, 0x00,
394 const unsigned ReentryFnAddrOffset = 0x3a;
395 const unsigned ReentryCtxAddrOffset = 0x28;
397 memcpy(ResolverWorkingMem, ResolverCode,
sizeof(ResolverCode));
398 memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnAddr,
400 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxAddr,
409 assert((ReentryFnAddr >> 32) == 0 &&
"ReentryFnAddr out of range");
410 assert((ReentryCtxAddr >> 32) == 0 &&
"ReentryCtxAddr out of range");
412 const uint8_t ResolverCode[] = {
424 0x81, 0xec, 0x18, 0x02, 0x00, 0x00,
425 0x0f, 0xae, 0x44, 0x24, 0x10,
428 0x89, 0x74, 0x24, 0x04,
429 0xc7, 0x04, 0x24, 0x00, 0x00, 0x00,
431 0xb8, 0x00, 0x00, 0x00, 0x00,
434 0x0f, 0xae, 0x4c, 0x24, 0x10,
435 0x81, 0xc4, 0x18, 0x02, 0x00, 0x00,
447 const unsigned ReentryFnAddrOffset = 0x2a;
448 const unsigned ReentryCtxAddrOffset = 0x25;
450 memcpy(ResolverWorkingMem, ResolverCode,
sizeof(ResolverCode));
451 memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnAddr,
453 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxAddr,
460 unsigned NumTrampolines) {
461 assert((ResolverAddr >> 32) == 0 &&
"ResolverAddr out of range");
463 uint64_t CallRelImm = 0xF1C4C400000000e8;
464 uint64_t ResolverRel = ResolverAddr - TrampolineBlockTargetAddress - 5;
468 Trampolines[
I] = CallRelImm | (ResolverRel << 8);
474 assert((StubsBlockTargetAddress >> 32) == 0 &&
475 "StubsBlockTargetAddress is out of range");
476 assert((PointersBlockTargetAddress >> 32) == 0 &&
477 "PointersBlockTargetAddress is out of range");
499 assert(stubAndPointerRangesOk<OrcI386>(
500 StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) &&
501 "PointersBlock is out of range");
504 uint64_t PtrAddr = PointersBlockTargetAddress;
505 for (
unsigned I = 0;
I < NumStubs; ++
I, PtrAddr += 4)
506 Stub[
I] = 0xF1C40000000025ff | (PtrAddr << 16);
588 const unsigned ReentryFnAddrOffset = 0x7c;
589 const unsigned ReentryCtxAddrOffset = 0x6c;
590 const unsigned Offsett = 0xf8;
592 memcpy(ResolverWorkingMem, ResolverCode,
sizeof(ResolverCode));
596 memcpy(ResolverWorkingMem + Offsett, &MoveVxT9,
sizeof(MoveVxT9));
599 0x3c040000 | (((ReentryCtxAddr + 0x8000) >> 16) & 0xFFFF);
600 uint32_t ReentryCtxADDiu = 0x24840000 | ((ReentryCtxAddr)&0xFFFF);
601 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxLUi,
602 sizeof(ReentryCtxLUi));
603 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset + 4, &ReentryCtxADDiu,
604 sizeof(ReentryCtxADDiu));
607 0x3c190000 | (((ReentryFnAddr + 0x8000) >> 16) & 0xFFFF);
608 uint32_t ReentryFnADDiu = 0x27390000 | ((ReentryFnAddr)&0xFFFF);
609 memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnLUi,
610 sizeof(ReentryFnLUi));
611 memcpy(ResolverWorkingMem + ReentryFnAddrOffset + 4, &ReentryFnADDiu,
612 sizeof(ReentryFnADDiu));
616 char *TrampolineBlockWorkingMem,
620 assert((ResolverAddr >> 32) == 0 &&
"ResolverAddr out of range");
623 reinterpret_cast<uint32_t *
>(TrampolineBlockWorkingMem);
624 uint32_t RHiAddr = ((ResolverAddr + 0x8000) >> 16);
626 for (
unsigned I = 0;
I < NumTrampolines; ++
I) {
632 Trampolines[5 *
I + 0] = 0x03e0c025;
633 Trampolines[5 *
I + 1] = 0x3c190000 | (RHiAddr & 0xFFFF);
634 Trampolines[5 *
I + 2] = 0x27390000 | (ResolverAddr & 0xFFFF);
635 Trampolines[5 *
I + 3] = 0x0320f809;
636 Trampolines[5 *
I + 4] = 0x00000000;
643 assert((StubsBlockTargetAddress >> 32) == 0 &&
644 "InitialPtrVal is out of range");
668 assert(stubAndPointerRangesOk<OrcMips32_Base>(
669 StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) &&
670 "PointersBlock is out of range");
674 uint64_t PtrAddr = PointersBlockTargetAddress;
676 for (
unsigned I = 0;
I < NumStubs; ++
I) {
677 uint32_t HiAddr = ((PtrAddr + 0x8000) >> 16);
678 Stub[4 *
I + 0] = 0x3c190000 | (HiAddr & 0xFFFF);
679 Stub[4 *
I + 1] = 0x8f390000 | (PtrAddr & 0xFFFF);
680 Stub[4 *
I + 2] = 0x03200008;
681 Stub[4 *
I + 3] = 0x00000000;
772 const unsigned ReentryFnAddrOffset = 0x8c;
773 const unsigned ReentryCtxAddrOffset = 0x6c;
775 memcpy(ResolverWorkingMem, ResolverCode,
sizeof(ResolverCode));
778 0x3c040000 | (((ReentryCtxAddr + 0x800080008000) >> 48) & 0xFFFF);
780 0x64840000 | (((ReentryCtxAddr + 0x80008000) >> 32) & 0xFFFF);
781 uint32_t ReentryCtxDSLL = 0x00042438;
783 0x64840000 | ((((ReentryCtxAddr + 0x8000) >> 16) & 0xFFFF));
784 uint32_t ReentryCtxDSLL2 = 0x00042438;
785 uint32_t ReentryCtxDADDiu3 = 0x64840000 | ((ReentryCtxAddr)&0xFFFF);
787 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxLUi,
788 sizeof(ReentryCtxLUi));
789 memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 4), &ReentryCtxDADDiu,
790 sizeof(ReentryCtxDADDiu));
791 memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 8), &ReentryCtxDSLL,
792 sizeof(ReentryCtxDSLL));
793 memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 12), &ReentryCtxDADDiu2,
794 sizeof(ReentryCtxDADDiu2));
795 memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 16), &ReentryCtxDSLL2,
796 sizeof(ReentryCtxDSLL2));
797 memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 20), &ReentryCtxDADDiu3,
798 sizeof(ReentryCtxDADDiu3));
801 0x3c190000 | (((ReentryFnAddr + 0x800080008000) >> 48) & 0xFFFF);
804 0x67390000 | (((ReentryFnAddr + 0x80008000) >> 32) & 0xFFFF);
806 uint32_t ReentryFnDSLL = 0x0019cc38;
809 0x67390000 | (((ReentryFnAddr + 0x8000) >> 16) & 0xFFFF);
811 uint32_t ReentryFnDSLL2 = 0x0019cc38;
813 uint32_t ReentryFnDADDiu3 = 0x67390000 | ((ReentryFnAddr)&0xFFFF);
815 memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnLUi,
816 sizeof(ReentryFnLUi));
817 memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 4), &ReentryFnDADDiu,
818 sizeof(ReentryFnDADDiu));
819 memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 8), &ReentryFnDSLL,
820 sizeof(ReentryFnDSLL));
821 memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 12), &ReentryFnDADDiu2,
822 sizeof(ReentryFnDADDiu2));
823 memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 16), &ReentryFnDSLL2,
824 sizeof(ReentryFnDSLL2));
825 memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 20), &ReentryFnDADDiu3,
826 sizeof(ReentryFnDADDiu3));
832 unsigned NumTrampolines) {
835 reinterpret_cast<uint32_t *
>(TrampolineBlockWorkingMem);
837 uint64_t HeighestAddr = ((ResolverAddr + 0x800080008000) >> 48);
838 uint64_t HeigherAddr = ((ResolverAddr + 0x80008000) >> 32);
839 uint64_t HiAddr = ((ResolverAddr + 0x8000) >> 16);
841 for (
unsigned I = 0;
I < NumTrampolines; ++
I) {
842 Trampolines[10 *
I + 0] = 0x03e0c025;
843 Trampolines[10 *
I + 1] = 0x3c190000 | (HeighestAddr & 0xFFFF);
844 Trampolines[10 *
I + 2] = 0x67390000 | (HeigherAddr & 0xFFFF);
845 Trampolines[10 *
I + 3] = 0x0019cc38;
846 Trampolines[10 *
I + 4] = 0x67390000 | (HiAddr & 0xFFFF);
847 Trampolines[10 *
I + 5] = 0x0019cc38;
848 Trampolines[10 *
I + 6] =
849 0x67390000 | (ResolverAddr & 0xFFFF);
850 Trampolines[10 *
I + 7] = 0x0320f809;
851 Trampolines[10 *
I + 8] = 0x00000000;
852 Trampolines[10 *
I + 9] = 0x00000000;
887 assert(stubAndPointerRangesOk<OrcMips64>(
888 StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) &&
889 "PointersBlock is out of range");
893 uint64_t PtrAddr = PointersBlockTargetAddress;
895 for (
unsigned I = 0;
I < NumStubs; ++
I, PtrAddr += 8) {
896 uint64_t HeighestAddr = ((PtrAddr + 0x800080008000) >> 48);
897 uint64_t HeigherAddr = ((PtrAddr + 0x80008000) >> 32);
898 uint64_t HiAddr = ((PtrAddr + 0x8000) >> 16);
899 Stub[8 *
I + 0] = 0x3c190000 | (HeighestAddr & 0xFFFF);
900 Stub[8 *
I + 1] = 0x67390000 | (HeigherAddr & 0xFFFF);
901 Stub[8 *
I + 2] = 0x0019cc38;
902 Stub[8 *
I + 3] = 0x67390000 | (HiAddr & 0xFFFF);
903 Stub[8 *
I + 4] = 0x0019cc38;
904 Stub[8 *
I + 5] = 0xdf390000 | (PtrAddr & 0xFFFF);
905 Stub[8 *
I + 6] = 0x03200008;
906 Stub[8 *
I + 7] = 0x00000000;
1000 const unsigned ReentryCtxAddrOffset = 0x138;
1001 const unsigned ReentryFnAddrOffset = 0x140;
1003 memcpy(ResolverWorkingMem, ResolverCode,
sizeof(ResolverCode));
1004 memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnAddr,
1006 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxAddr,
1013 unsigned NumTrampolines) {
1017 memcpy(TrampolineBlockWorkingMem + OffsetToPtr, &ResolverAddr,
1021 reinterpret_cast<uint32_t *
>(TrampolineBlockWorkingMem);
1023 uint32_t Hi20 = (OffsetToPtr + 0x800) & 0xFFFFF000;
1024 uint32_t Lo12 = OffsetToPtr - Hi20;
1025 Trampolines[4 *
I + 0] = 0x00000297 | Hi20;
1026 Trampolines[4 *
I + 1] =
1027 0x0002b283 | ((Lo12 & 0xFFF) << 20);
1028 Trampolines[4 *
I + 2] = 0x00028367;
1029 Trampolines[4 *
I + 3] = 0xdeadface;
1060 assert(stubAndPointerRangesOk<OrcRiscv64>(
1061 StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) &&
1062 "PointersBlock is out of range");
1066 for (
unsigned I = 0;
I < NumStubs; ++
I) {
1068 PointersBlockTargetAddress - StubsBlockTargetAddress;
1069 uint32_t Hi20 = (PtrDisplacement + 0x800) & 0xFFFFF000;
1070 uint32_t Lo12 = PtrDisplacement - Hi20;
1071 Stub[4 *
I + 0] = 0x00000297 | Hi20;
1072 Stub[4 *
I + 1] = 0x0002b283 | ((Lo12 & 0xFFF) << 20);
1073 Stub[4 *
I + 2] = 0x00028067;
1074 Stub[4 *
I + 3] = 0xfeedbeef;
1076 StubsBlockTargetAddress +=
StubSize;
1086 dbgs() <<
"Writing resolver code to "
1087 <<
formatv(
"{0:x16}", ResolverTargetAddress) <<
"\n";
1143 const unsigned ReentryCtxAddrOffset = 0xb8;
1144 const unsigned ReentryFnAddrOffset = 0xc0;
1146 memcpy(ResolverWorkingMem, ResolverCode,
sizeof(ResolverCode));
1147 memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnAddr,
1149 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxAddr,
1154 char *TrampolineBlockWorkingMem,
1159 dbgs() <<
"Writing trampoline code to "
1160 <<
formatv(
"{0:x16}", TrampolineBlockTargetAddress) <<
"\n";
1165 memcpy(TrampolineBlockWorkingMem + OffsetToPtr, &ResolverAddr,
1169 reinterpret_cast<uint32_t *
>(TrampolineBlockWorkingMem);
1171 uint32_t Hi20 = (OffsetToPtr + 0x800) & 0xfffff000;
1172 uint32_t Lo12 = OffsetToPtr - Hi20;
1173 Trampolines[4 *
I + 0] =
1175 (((Hi20 >> 12) & 0xfffff) << 5);
1176 Trampolines[4 *
I + 1] =
1177 0x28c0018c | ((Lo12 & 0xfff) << 10);
1178 Trampolines[4 *
I + 2] = 0x4c00018d;
1179 Trampolines[4 *
I + 3] = 0x0;
1208 dbgs() <<
"Writing stubs code to "
1209 <<
formatv(
"{0:x16}", StubsBlockTargetAddress) <<
"\n";
1211 assert(stubAndPointerRangesOk<OrcLoongArch64>(
1212 StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) &&
1213 "PointersBlock is out of range");
1217 for (
unsigned I = 0;
I < NumStubs; ++
I) {
1219 PointersBlockTargetAddress - StubsBlockTargetAddress;
1220 uint32_t Hi20 = (PtrDisplacement + 0x800) & 0xfffff000;
1221 uint32_t Lo12 = PtrDisplacement - Hi20;
1222 Stub[4 *
I + 0] = 0x1c00000c | (((Hi20 >> 12) & 0xfffff)
1225 0x28c0018c | ((Lo12 & 0xfff) << 10);
1226 Stub[4 *
I + 2] = 0x4c000180;
1227 Stub[4 *
I + 3] = 0x0;
1229 StubsBlockTargetAddress +=
StubSize;