95 const unsigned ReentryFnAddrOffset = 0x110;
96 const unsigned CallbackMgrAddrOffset = 0x118;
98 memcpy(ResolverMem, ResolverCode,
sizeof(ResolverCode));
99 memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn,
sizeof(ReentryFn));
100 memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr,
101 sizeof(CallbackMgr));
105 unsigned NumTrampolines) {
109 memcpy(TrampolineMem + OffsetToPtr, &ResolverAddr,
sizeof(
void *));
118 Trampolines[3 *
I + 0] = 0xaa1e03f1;
119 Trampolines[3 *
I + 1] = 0x58000010 | (OffsetToPtr << 3);
120 Trampolines[3 *
I + 2] = 0xd63f0200;
127 void *InitialPtrVal) {
152 unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize;
153 unsigned NumStubs = (NumPages *
PageSize) / StubSize;
158 2 * NumPages * PageSize,
nullptr,
168 NumPages * PageSize);
171 uint64_t *Stub =
reinterpret_cast<uint64_t *
>(StubsBlock.base());
172 uint64_t PtrOffsetField =
static_cast<uint64_t
>(NumPages *
PageSize)
175 for (
unsigned I = 0;
I < NumStubs; ++
I)
176 Stub[
I] = 0xd61f020058000010 | PtrOffsetField;
183 void **Ptr =
reinterpret_cast<void **
>(PtrsBlock.base());
184 for (
unsigned I = 0;
I < NumStubs; ++
I)
185 Ptr[
I] = InitialPtrVal;
194 unsigned NumTrampolines) {
198 memcpy(TrampolineMem + OffsetToPtr, &ResolverAddr,
sizeof(
void *));
200 uint64_t *Trampolines =
reinterpret_cast<uint64_t *
>(TrampolineMem);
201 uint64_t CallIndirPCRel = 0xf1c40000000015ff;
204 Trampolines[
I] = CallIndirPCRel | ((OffsetToPtr - 6) << 16);
209 void *InitialPtrVal) {
234 unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize;
235 unsigned NumStubs = (NumPages *
PageSize) / StubSize;
240 2 * NumPages * PageSize,
nullptr,
250 NumPages * PageSize);
253 uint64_t *Stub =
reinterpret_cast<uint64_t *
>(StubsBlock.base());
254 uint64_t PtrOffsetField =
static_cast<uint64_t
>(NumPages * PageSize - 6)
256 for (
unsigned I = 0;
I < NumStubs; ++
I)
257 Stub[
I] = 0xF1C40000000025ff | PtrOffsetField;
264 void **Ptr =
reinterpret_cast<void **
>(PtrsBlock.base());
265 for (
unsigned I = 0;
I < NumStubs; ++
I)
266 Ptr[
I] = InitialPtrVal;
277 const uint8_t ResolverCode[] = {
295 0x48, 0x81, 0xec, 0x08, 0x02, 0x00, 0x00,
296 0x48, 0x0f, 0xae, 0x04, 0x24,
300 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302 0x48, 0x8b, 0x75, 0x08,
303 0x48, 0x83, 0xee, 0x06,
307 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
310 0x48, 0x89, 0x45, 0x08,
311 0x48, 0x0f, 0xae, 0x0c, 0x24,
312 0x48, 0x81, 0xc4, 0x08, 0x02, 0x00, 0x00,
331 const unsigned ReentryFnAddrOffset = 0x3a;
332 const unsigned CallbackMgrAddrOffset = 0x28;
334 memcpy(ResolverMem, ResolverCode,
sizeof(ResolverCode));
335 memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn,
sizeof(ReentryFn));
336 memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr,
337 sizeof(CallbackMgr));
346 const uint8_t ResolverCode[] = {
364 0x48, 0x81, 0xec, 0x08, 0x02, 0x00, 0x00,
365 0x48, 0x0f, 0xae, 0x04, 0x24,
369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 0x48, 0x8B, 0x55, 0x08,
372 0x48, 0x83, 0xea, 0x06,
376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379 0x48, 0x83, 0xEC, 0x20,
383 0x48, 0x83, 0xC4, 0x20,
385 0x48, 0x89, 0x45, 0x08,
386 0x48, 0x0f, 0xae, 0x0c, 0x24,
387 0x48, 0x81, 0xc4, 0x08, 0x02, 0x00, 0x00,
407 const unsigned ReentryFnAddrOffset = 0x3a;
408 const unsigned CallbackMgrAddrOffset = 0x28;
410 memcpy(ResolverMem, ResolverCode,
sizeof(ResolverCode));
411 memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn,
sizeof(ReentryFn));
412 memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr,
413 sizeof(CallbackMgr));
419 const uint8_t ResolverCode[] = {
431 0x81, 0xec, 0x18, 0x02, 0x00, 0x00,
432 0x0f, 0xae, 0x44, 0x24, 0x10,
435 0x89, 0x74, 0x24, 0x04,
436 0xc7, 0x04, 0x24, 0x00, 0x00, 0x00,
438 0xb8, 0x00, 0x00, 0x00, 0x00,
441 0x0f, 0xae, 0x4c, 0x24, 0x10,
442 0x81, 0xc4, 0x18, 0x02, 0x00, 0x00,
454 const unsigned ReentryFnAddrOffset = 0x2a;
455 const unsigned CallbackMgrAddrOffset = 0x25;
457 memcpy(ResolverMem, ResolverCode,
sizeof(ResolverCode));
458 memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn,
sizeof(ReentryFn));
459 memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr,
460 sizeof(CallbackMgr));
464 unsigned NumTrampolines) {
466 uint64_t CallRelImm = 0xF1C4C400000000e8;
467 uint64_t
Resolver =
reinterpret_cast<uint64_t
>(ResolverAddr);
468 uint64_t ResolverRel =
469 Resolver -
reinterpret_cast<uint64_t
>(TrampolineMem) - 5;
471 uint64_t *Trampolines =
reinterpret_cast<uint64_t *
>(TrampolineMem);
473 Trampolines[
I] = CallRelImm | (ResolverRel << 8);
477 unsigned MinStubs,
void *InitialPtrVal) {
502 unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize;
503 unsigned NumStubs = (NumPages *
PageSize) / StubSize;
508 2 * NumPages * PageSize,
nullptr,
518 NumPages * PageSize);
521 uint64_t *Stub =
reinterpret_cast<uint64_t *
>(StubsBlock.base());
522 uint64_t PtrAddr =
reinterpret_cast<uint64_t
>(PtrsBlock.base());
523 for (
unsigned I = 0;
I < NumStubs; ++
I, PtrAddr += 4)
524 Stub[
I] = 0xF1C40000000025ff | (PtrAddr << 16);
531 void **Ptr =
reinterpret_cast<void **
>(PtrsBlock.base());
532 for (
unsigned I = 0;
I < NumStubs; ++
I)
533 Ptr[
I] = InitialPtrVal;
542 void *CallbackMgr,
bool isBigEndian) {
617 const unsigned ReentryFnAddrOffset = 0x7c;
618 const unsigned CallbackMgrAddrOffset = 0x6c;
619 const unsigned Offsett = 0xf8;
621 memcpy(ResolverMem, ResolverCode,
sizeof(ResolverCode));
624 uint32_t MoveVxT9 = isBigEndian ? 0x0060c825 : 0x0040c825;
625 memcpy(ResolverMem + Offsett, &MoveVxT9,
sizeof(MoveVxT9));
627 uint64_t CallMgrAddr =
reinterpret_cast<uint64_t
>(CallbackMgr);
628 uint32_t CallMgrLUi = 0x3c040000 | (((CallMgrAddr + 0x8000) >> 16) & 0xFFFF);
629 uint32_t CallMgrADDiu = 0x24840000 | ((CallMgrAddr) & 0xFFFF);
630 memcpy(ResolverMem + CallbackMgrAddrOffset, &CallMgrLUi,
sizeof(CallMgrLUi));
631 memcpy(ResolverMem + CallbackMgrAddrOffset + 4, &CallMgrADDiu,
632 sizeof(CallMgrADDiu));
634 uint64_t ReentryAddr =
reinterpret_cast<uint64_t
>(ReentryFn);
635 uint32_t ReentryLUi = 0x3c190000 | (((ReentryAddr + 0x8000) >> 16) & 0xFFFF);
636 uint32_t ReentryADDiu = 0x27390000 | ((ReentryAddr) & 0xFFFF);
637 memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryLUi,
sizeof(ReentryLUi));
638 memcpy(ResolverMem + ReentryFnAddrOffset + 4, &ReentryADDiu,
639 sizeof(ReentryADDiu));
644 unsigned NumTrampolines) {
647 uint64_t ResolveAddr =
reinterpret_cast<uint64_t
>(ResolverAddr);
648 uint32_t RHiAddr = ((ResolveAddr + 0x8000) >> 16);
650 for (
unsigned I = 0;
I < NumTrampolines; ++
I) {
651 Trampolines[5 *
I + 0] = 0x03e0c025;
652 Trampolines[5 *
I + 1] = 0x3c190000 | (RHiAddr & 0xFFFF);
653 Trampolines[5 *
I + 2] = 0x27390000 | (ResolveAddr & 0xFFFF);
654 Trampolines[5 *
I + 3] = 0x0320f809;
655 Trampolines[5 *
I + 4] = 0x00000000;
661 void *InitialPtrVal) {
688 unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize;
689 unsigned NumStubs = (NumPages *
PageSize) / StubSize;
694 2 * NumPages * PageSize,
nullptr,
704 NumPages * PageSize);
708 uint64_t PtrAddr =
reinterpret_cast<uint64_t
>(Stub) + NumPages * PageSize;
710 for (
unsigned I = 0;
I < NumStubs; ++
I) {
711 uint32_t HiAddr = ((PtrAddr + 0x8000) >> 16);
712 Stub[4 *
I + 0] = 0x3c190000 | (HiAddr & 0xFFFF);
713 Stub[4 *
I + 1] = 0x8f390000 | (PtrAddr & 0xFFFF);
714 Stub[4 *
I + 2] = 0x03200008;
715 Stub[4 *
I + 3] = 0x00000000;
724 void **Ptr =
reinterpret_cast<void **
>(PtrsBlock.base());
725 for (
unsigned I = 0;
I < NumStubs; ++
I)
726 Ptr[
I] = InitialPtrVal;
817 const unsigned ReentryFnAddrOffset = 0x8c;
818 const unsigned CallbackMgrAddrOffset = 0x6c;
820 memcpy(ResolverMem, ResolverCode,
sizeof(ResolverCode));
822 uint64_t CallMgrAddr =
reinterpret_cast<uint64_t
>(CallbackMgr);
825 0x3c040000 | (((CallMgrAddr + 0x800080008000) >> 48) & 0xFFFF);
827 0x64840000 | (((CallMgrAddr + 0x80008000) >> 32) & 0xFFFF);
830 0x64840000 | ((((CallMgrAddr + 0x8000) >> 16) & 0xFFFF));
832 uint32_t CallMgrDADDiu3 = 0x64840000 | ((CallMgrAddr)&0xFFFF);
834 memcpy(ResolverMem + CallbackMgrAddrOffset, &CallMgrLUi,
sizeof(CallMgrLUi));
835 memcpy(ResolverMem + (CallbackMgrAddrOffset + 4), &CallMgrDADDiu,
836 sizeof(CallMgrDADDiu));
837 memcpy(ResolverMem + (CallbackMgrAddrOffset + 8), &CallMgrDSLL,
838 sizeof(CallMgrDSLL));
839 memcpy(ResolverMem + (CallbackMgrAddrOffset + 12), &CallMgrDADDiu2,
840 sizeof(CallMgrDADDiu2));
841 memcpy(ResolverMem + (CallbackMgrAddrOffset + 16), &CallMgrDSLL2,
842 sizeof(CallMgrDSLL2));
843 memcpy(ResolverMem + (CallbackMgrAddrOffset + 20), &CallMgrDADDiu3,
844 sizeof(CallMgrDADDiu3));
846 uint64_t ReentryAddr =
reinterpret_cast<uint64_t
>(ReentryFn);
849 0x3c190000 | (((ReentryAddr + 0x800080008000) >> 48) & 0xFFFF);
852 0x67390000 | (((ReentryAddr + 0x80008000) >> 32) & 0xFFFF);
857 0x67390000 | (((ReentryAddr + 0x8000) >> 16) & 0xFFFF);
861 uint32_t ReentryDADDiu3 = 0x67390000 | ((ReentryAddr)&0xFFFF);
863 memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryLUi,
sizeof(ReentryLUi));
864 memcpy(ResolverMem + (ReentryFnAddrOffset + 4), &ReentryDADDiu,
865 sizeof(ReentryDADDiu));
866 memcpy(ResolverMem + (ReentryFnAddrOffset + 8), &ReentryDSLL,
867 sizeof(ReentryDSLL));
868 memcpy(ResolverMem + (ReentryFnAddrOffset + 12), &ReentryDADDiu2,
869 sizeof(ReentryDADDiu2));
870 memcpy(ResolverMem + (ReentryFnAddrOffset + 16), &ReentryDSLL2,
871 sizeof(ReentryDSLL2));
872 memcpy(ResolverMem + (ReentryFnAddrOffset + 20), &ReentryDADDiu3,
873 sizeof(ReentryDADDiu3));
877 unsigned NumTrampolines) {
880 uint64_t ResolveAddr =
reinterpret_cast<uint64_t
>(ResolverAddr);
882 uint64_t HeighestAddr = ((ResolveAddr + 0x800080008000) >> 48);
883 uint64_t HeigherAddr = ((ResolveAddr + 0x80008000) >> 32);
884 uint64_t HiAddr = ((ResolveAddr + 0x8000) >> 16);
886 for (
unsigned I = 0;
I < NumTrampolines; ++
I) {
887 Trampolines[10 *
I + 0] = 0x03e0c025;
888 Trampolines[10 *
I + 1] = 0x3c190000 | (HeighestAddr & 0xFFFF);
889 Trampolines[10 *
I + 2] = 0x67390000 | (HeigherAddr & 0xFFFF);
890 Trampolines[10 *
I + 3] = 0x0019cc38;
891 Trampolines[10 *
I + 4] = 0x67390000 | (HiAddr & 0xFFFF);
892 Trampolines[10 *
I + 5] = 0x0019cc38;
893 Trampolines[10 *
I + 6] = 0x67390000 | (ResolveAddr & 0xFFFF);
894 Trampolines[10 *
I + 7] = 0x0320f809;
895 Trampolines[10 *
I + 8] = 0x00000000;
896 Trampolines[10 *
I + 9] = 0x00000000;
902 void *InitialPtrVal) {
934 unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize;
935 unsigned NumStubs = (NumPages *
PageSize) / StubSize;
940 2 * NumPages * PageSize,
nullptr,
950 NumPages * PageSize);
954 uint64_t PtrAddr =
reinterpret_cast<uint64_t
>(PtrsBlock.base());
956 for (
unsigned I = 0;
I < NumStubs; ++
I, PtrAddr += 8) {
957 uint64_t HeighestAddr = ((PtrAddr + 0x800080008000) >> 48);
958 uint64_t HeigherAddr = ((PtrAddr + 0x80008000) >> 32);
959 uint64_t HiAddr = ((PtrAddr + 0x8000) >> 16);
960 Stub[8 *
I + 0] = 0x3c190000 | (HeighestAddr & 0xFFFF);
961 Stub[8 *
I + 1] = 0x67390000 | (HeigherAddr & 0xFFFF);
962 Stub[8 *
I + 2] = 0x0019cc38;
963 Stub[8 *
I + 3] = 0x67390000 | (HiAddr & 0xFFFF);
964 Stub[8 *
I + 4] = 0x0019cc38;
965 Stub[8 *
I + 5] = 0xdf390000 | (PtrAddr & 0xFFFF);
966 Stub[8 *
I + 6] = 0x03200008;
967 Stub[8 *
I + 7] = 0x00000000;
975 void **Ptr =
reinterpret_cast<void **
>(PtrsBlock.base());
976 for (
unsigned I = 0;
I < NumStubs; ++
I)
977 Ptr[
I] = InitialPtrVal;
This class represents lattice values for constants.
static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, unsigned NumTrampolines)
Write the requsted number of trampolines into the given memory, which must be big enough to hold 1 po...
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry, void *CallbackMgr)
Write the resolver code into the given memory.
static const unsigned StubSize
Provide information about stub blocks generated by the makeIndirectStubsBlock function.
JITTargetAddress(*)(void *CallbackMgr, void *TrampolineId) JITReentryFn
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry, void *CallbackMgr)
Write the resolver code into the given memory.
static MemoryBlock allocateMappedMemory(size_t NumBytes, const MemoryBlock *const NearBlock, unsigned Flags, std::error_code &EC)
This method allocates a block of memory that is suitable for loading dynamically generated code (e...
static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, unsigned MinStubs, void *InitialPtrVal)
Emit at least MinStubs worth of indirect call stubs, rounded out to the nearest page size...
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry, void *CallbackMgr)
Write the resolver code into the given memory.
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry, void *CallbackMgr)
Write the resolver code into the given memory.
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry, void *CallbackMgr, bool isBigEndian)
Write the resolver code into the given memory.
static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, unsigned NumTrampolines)
Write the requsted number of trampolines into the given memory, which must be big enough to hold 1 po...
JITTargetAddress(*)(void *CallbackMgr, void *TrampolineId) JITReentryFn
static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, unsigned MinStubs, void *InitialPtrVal)
Emit at least MinStubs worth of indirect call stubs, rounded out to the nearest page size...
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Interface for looking up the initializer for a variable name, used by Init::resolveReferences.
static const unsigned TrampolineSize
JITTargetAddress(*)(void *CallbackMgr, void *TrampolineId) JITReentryFn
JITTargetAddress(*)(void *CallbackMgr, void *TrampolineId) JITReentryFn
static unsigned getPageSize()
GenericIndirectStubsInfo< 8 > IndirectStubsInfo
static ErrorSuccess success()
Create a success value.
static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, unsigned NumTrampolines)
Write the requsted number of trampolines into the given memory, which must be big enough to hold 1 po...
This class encapsulates the notion of a memory block which has an address and a size.
JITTargetAddress(*)(void *CallbackMgr, void *TrampolineId) JITReentryFn
Owning version of MemoryBlock.
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry, void *CallbackMgr)
Write the resolver code into the given memory.
static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, unsigned MinStubs, void *InitialPtrVal)
Emit at least MinStubs worth of indirect call stubs, rounded out to the nearest page size...
static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, unsigned NumTrampolines)
Write the requsted number of trampolines into the given memory, which must be big enough to hold 1 po...
JITTargetAddress(*)(void *CallbackMgr, void *TrampolineId) JITReentryFn
Provides a library for accessing information about this process and other processes on the operating ...
static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, unsigned NumTrampolines)
Write the requsted number of trampolines into the given memory, which must be big enough to hold 1 po...
static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096), cl::Hidden)
Lightweight error class with error context and mandatory checking.
static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, unsigned MinStubs, void *InitialPtrVal)
Emit at least MinStubs worth of indirect call stubs, rounded out to the nearest page size...
static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, unsigned MinStubs, void *InitialPtrVal)
Emit at least MinStubs worth of indirect call stubs, rounded out to the nearest page size...
static std::error_code protectMappedMemory(const MemoryBlock &Block, unsigned Flags)
This method sets the protection flags for a block of memory to the state specified by /p Flags...