Skip to content

Commit 5ebaadf

Browse files
sdmacleajkotas
authored andcommitted
GenericPInvokeCalli shift left then or 1 (dotnet#17734)
When _WIN64 is defined vm relies on the secret arg being shifted left and orred with #1. Revert part of changes from dotnet#17659 to fix dotnet/corefx#29266 Fix arm64 to match amd64 Simplify dllimport.cpp
1 parent 8c4a471 commit 5ebaadf

File tree

7 files changed

+44
-2
lines changed

7 files changed

+44
-2
lines changed

src/vm/amd64/PInvokeStubs.asm

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ LEAF_ENTRY GenericPInvokeCalliHelper, _TEXT
3131
test rax, rax
3232
jz GenericPInvokeCalliGenILStub
3333

34+
;
35+
; We need to distinguish between a MethodDesc* and an unmanaged target.
36+
; The way we do this is to shift the managed target to the left by one bit and then set the
37+
; least significant bit to 1. This works because MethodDesc* are always 8-byte aligned.
38+
;
39+
shl PINVOKE_CALLI_TARGET_REGISTER, 1
40+
or PINVOKE_CALLI_TARGET_REGISTER, 1
41+
3442
;
3543
; jump to existing IL stub
3644
;

src/vm/amd64/pinvokestubs.S

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ LEAF_ENTRY GenericPInvokeCalliHelper, _TEXT
2424
test rax, rax
2525
jz C_FUNC(GenericPInvokeCalliGenILStub)
2626

27+
//
28+
// We need to distinguish between a MethodDesc* and an unmanaged target.
29+
// The way we do this is to shift the managed target to the left by one bit and then set the
30+
// least significant bit to 1. This works because MethodDesc* are always 8-byte aligned.
31+
//
32+
shl PINVOKE_CALLI_TARGET_REGISTER, 1
33+
or PINVOKE_CALLI_TARGET_REGISTER, 1
34+
2735
//
2836
// jump to existing IL stub
2937
//

src/vm/arm64/PInvokeStubs.asm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ __PInvokeGenStubFuncName SETS "$__PInvokeGenStubFuncName":CC:"_RetBuffArg"
5858
; if null goto stub generation
5959
cbz x9, %0
6060

61+
IF "$FuncPrefix" == "GenericPInvokeCalli"
62+
;
63+
; We need to distinguish between a MethodDesc* and an unmanaged target.
64+
; The way we do this is to shift the managed target to the left by one bit and then set the
65+
; least significant bit to 1. This works because MethodDesc* are always 8-byte aligned.
66+
;
67+
lsl x9, x9, #1
68+
orr x9, x9, #1
69+
ENDIF
6170

6271
EPILOG_BRANCH_REG x9
6372

src/vm/arm64/pinvokestubs.S

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
// $VASigCookieReg : register which contains the VASigCookie
2222
// $SaveFPArgs : "Yes" or "No" . For varidic functions FP Args are not present in FP regs
2323
// So need not save FP Args registers for vararg Pinvoke
24-
.macro PINVOKE_STUB __PInvokeStubFuncName,__PInvokeGenStubFuncName,__PInvokeStubWorkerName,VASigCookieReg,HiddenArg,SaveFPArgs
24+
.macro PINVOKE_STUB __PInvokeStubFuncName,__PInvokeGenStubFuncName,__PInvokeStubWorkerName,VASigCookieReg,HiddenArg,SaveFPArgs,ShiftLeftAndOrSecret=0
2525

2626

2727
NESTED_ENTRY \__PInvokeStubFuncName, _TEXT, NoHandler
@@ -32,6 +32,16 @@
3232
// if null goto stub generation
3333
cbz x9, LOCAL_LABEL(\__PInvokeStubFuncName\()_0)
3434

35+
.if (\ShiftLeftAndOrSecret == 1)
36+
//
37+
// We need to distinguish between a MethodDesc* and an unmanaged target.
38+
// The way we do this is to shift the managed target to the left by one bit and then set the
39+
// least significant bit to 1. This works because MethodDesc* are always 8-byte aligned.
40+
//
41+
lsl x9, x9, #1
42+
orr x9, x9, #1
43+
.endif
44+
3545
EPILOG_BRANCH_REG x9
3646

3747
LOCAL_LABEL(\__PInvokeStubFuncName\()_0):
@@ -97,7 +107,7 @@ PINVOKE_STUB VarargPInvokeStub, VarargPInvokeGenILStub, VarargPInvokeStubWorker,
97107
// x15 = VASigCookie*
98108
// x12 = Unmanaged target
99109
//
100-
PINVOKE_STUB GenericPInvokeCalliHelper, GenericPInvokeCalliGenILStub, GenericPInvokeCalliStubWorker, x15, x12, 1
110+
PINVOKE_STUB GenericPInvokeCalliHelper, GenericPInvokeCalliGenILStub, GenericPInvokeCalliStubWorker, x15, x12, 1, 1
101111

102112
// ------------------------------------------------------------------
103113
// VarargPInvokeStub_RetBuffArg & VarargPInvokeGenILStub_RetBuffArg

src/vm/dllimport.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2256,6 +2256,11 @@ void NDirectStubLinker::DoNDirect(ILCodeStream *pcsEmit, DWORD dwStubFlags, Meth
22562256
// for managed-to-unmanaged CALLI that requires marshaling, the target is passed
22572257
// as the secret argument to the stub by GenericPInvokeCalliHelper (asmhelpers.asm)
22582258
EmitLoadStubContext(pcsEmit, dwStubFlags);
2259+
#ifdef _WIN64
2260+
// the secret arg has been shifted to left and ORed with 1 (see code:GenericPInvokeCalliHelper)
2261+
pcsEmit->EmitLDC(1);
2262+
pcsEmit->EmitSHR_UN();
2263+
#endif
22592264
}
22602265
else
22612266
#ifdef FEATURE_COMINTEROP

src/vm/frames.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2957,6 +2957,7 @@ class InlinedCallFrame : public Frame
29572957
WRAPPER_NO_CONTRACT;
29582958

29592959
#ifdef _WIN64
2960+
// See code:GenericPInvokeCalliHelper
29602961
return ((m_Datum != NULL) && !(dac_cast<TADDR>(m_Datum) & 0x1));
29612962
#else // _WIN64
29622963
return ((dac_cast<TADDR>(m_Datum) & ~0xffff) != 0);

src/vm/stubhelpers.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,7 @@ FCIMPL2(void*, StubHelpers::GetDelegateTarget, DelegateObject *pThisUNSAFE, UINT
11661166
#if defined(_WIN64)
11671167
UINT_PTR target = (UINT_PTR)orefThis->GetMethodPtrAux();
11681168

1169+
// See code:GenericPInvokeCalliHelper
11691170
// The lowest bit is used to distinguish between MD and target on 64-bit.
11701171
target = (target << 1) | 1;
11711172

0 commit comments

Comments
 (0)