1414
1515#include " CommonMacros.inl"
1616
17+ #define GCINFODECODER_NO_EE
18+ #include " coreclr/gcinfodecoder.cpp"
19+
1720#include " UnixContext.h"
1821
1922#define UBF_FUNC_KIND_MASK 0x03
2326
2427#define UBF_FUNC_HAS_EHINFO 0x04
2528
29+ #define UBF_FUNC_REVERSE_PINVOKE 0x08
30+
2631struct UnixNativeMethodInfo
2732{
2833 PTR_VOID pMethodStartAddress;
29- PTR_UInt8 pEhInfo ;
30- uint8_t funcFlags ;
34+ PTR_UInt8 pMainLSDA ;
35+ PTR_UInt8 pLSDA ;
3136 bool executionAborted;
3237};
3338
@@ -57,30 +62,26 @@ bool UnixNativeCodeManager::FindMethodInfo(PTR_VOID ControlPC,
5762 return false ;
5863 }
5964
60- PTR_UInt8 lsdaPtr = dac_cast<PTR_UInt8>(lsda);
65+ PTR_UInt8 p = dac_cast<PTR_UInt8>(lsda);
6166
62- int offsetFromMainFunction = *dac_cast<PTR_Int32>(lsdaPtr);
63- lsdaPtr += sizeof (int );
64- pMethodInfo->funcFlags = *lsdaPtr;
65- ++lsdaPtr;
67+ pMethodInfo->pLSDA = p;
6668
67- PTR_UInt8 ehInfoPtr = NULL ;
68- if (pMethodInfo->funcFlags & UBF_FUNC_HAS_EHINFO)
69+ uint8_t unwindBlockFlags = *p++;
70+
71+ if ((unwindBlockFlags & UBF_FUNC_KIND_MASK) != UBF_FUNC_KIND_ROOT)
6972 {
70- // main function contains the EH info blob in its LSDA, funclets just refer
71- // to the main function's blob
72- if (offsetFromMainFunction == 0 )
73- {
74- ehInfoPtr = lsdaPtr ;
75- }
76- else
77- {
78- ehInfoPtr = lsdaPtr + * dac_cast<PTR_Int32>(lsdaPtr );
79- }
73+ // Funclets just refer to the main function's blob
74+ pMethodInfo-> pMainLSDA = p + *dac_cast<PTR_Int32>(p);
75+ p += sizeof ( int32_t );
76+
77+ pMethodInfo-> pMethodStartAddress = dac_cast<PTR_VOID>(startAddress - *dac_cast<PTR_Int32>(p)) ;
78+ }
79+ else
80+ {
81+ pMethodInfo-> pMainLSDA = dac_cast<PTR_UInt8>(lsda );
82+ pMethodInfo-> pMethodStartAddress = dac_cast<PTR_VOID>(startAddress);
8083 }
8184
82- pMethodInfo->pMethodStartAddress = (PTR_VOID)(startAddress - offsetFromMainFunction);
83- pMethodInfo->pEhInfo = ehInfoPtr;
8485 pMethodInfo->executionAborted = false ;
8586
8687 return true ;
@@ -90,7 +91,8 @@ bool UnixNativeCodeManager::IsFunclet(MethodInfo * pMethodInfo)
9091{
9192 UnixNativeMethodInfo * pNativeMethodInfo = (UnixNativeMethodInfo *)pMethodInfo;
9293
93- return (pNativeMethodInfo->funcFlags & UBF_FUNC_KIND_MASK) != UBF_FUNC_KIND_ROOT;
94+ uint8_t unwindBlockFlags = *(pNativeMethodInfo->pLSDA );
95+ return (unwindBlockFlags & UBF_FUNC_KIND_MASK) != UBF_FUNC_KIND_ROOT;
9496}
9597
9698PTR_VOID UnixNativeCodeManager::GetFramePointer (MethodInfo * pMethodInfo,
@@ -99,7 +101,7 @@ PTR_VOID UnixNativeCodeManager::GetFramePointer(MethodInfo * pMethodInfo,
99101 UnixNativeMethodInfo * pNativeMethodInfo = (UnixNativeMethodInfo *)pMethodInfo;
100102
101103 // Return frame pointer for methods with EH and funclets
102- uint8_t unwindBlockFlags = pNativeMethodInfo->funcFlags ;
104+ uint8_t unwindBlockFlags = *( pNativeMethodInfo->pLSDA ) ;
103105 if ((unwindBlockFlags & UBF_FUNC_HAS_EHINFO) != 0 || (unwindBlockFlags & UBF_FUNC_KIND_MASK) != UBF_FUNC_KIND_ROOT)
104106 {
105107 return (PTR_VOID)pRegisterSet->GetFP ();
@@ -127,14 +129,37 @@ bool UnixNativeCodeManager::UnwindStackFrame(MethodInfo * pMethodInfo,
127129 REGDISPLAY * pRegisterSet, // in/out
128130 PTR_VOID * ppPreviousTransitionFrame) // out
129131{
130- if (!VirtualUnwind (pRegisterSet))
132+ UnixNativeMethodInfo * pNativeMethodInfo = (UnixNativeMethodInfo *)pMethodInfo;
133+
134+ PTR_UInt8 p = pNativeMethodInfo->pMainLSDA ;
135+
136+ uint8_t unwindBlockFlags = *p++;
137+
138+ if ((unwindBlockFlags & UBF_FUNC_REVERSE_PINVOKE) != 0 )
131139 {
132- return false ;
140+ // Reverse PInvoke transition should on the main function body only
141+ assert (pNativeMethodInfo->pMainLSDA == pNativeMethodInfo->pLSDA );
142+
143+ if ((unwindBlockFlags & UBF_FUNC_HAS_EHINFO) != 0 )
144+ p += sizeof (int32_t );
145+
146+ GcInfoDecoder decoder (GCInfoToken (p), DECODE_REVERSE_PINVOKE_VAR);
147+
148+ // @TODO: CORERT: Encode reverse PInvoke frame slot in GCInfo: https://github.com/dotnet/corert/issues/2115
149+ // INT32 slot = decoder.GetReversePInvokeFrameStackSlot();
150+ // assert(slot != NO_REVERSE_PINVOKE_FRAME);
151+
152+ *ppPreviousTransitionFrame = (PTR_VOID)-1 ;
153+ return true ;
133154 }
134155
135- // @TODO: CORERT: PInvoke transitions
136156 *ppPreviousTransitionFrame = NULL ;
137157
158+ if (!VirtualUnwind (pRegisterSet))
159+ {
160+ return false ;
161+ }
162+
138163 return true ;
139164}
140165
@@ -187,8 +212,12 @@ bool UnixNativeCodeManager::EHEnumInit(MethodInfo * pMethodInfo, PTR_VOID * pMet
187212
188213 UnixNativeMethodInfo * pNativeMethodInfo = (UnixNativeMethodInfo *)pMethodInfo;
189214
215+ PTR_UInt8 p = pNativeMethodInfo->pMainLSDA ;
216+
217+ uint8_t unwindBlockFlags = *p++;
218+
190219 // return if there is no EH info associated with this method
191- if ((pNativeMethodInfo-> funcFlags & UBF_FUNC_HAS_EHINFO) == 0 )
220+ if ((unwindBlockFlags & UBF_FUNC_HAS_EHINFO) == 0 )
192221 {
193222 return false ;
194223 }
@@ -198,7 +227,7 @@ bool UnixNativeCodeManager::EHEnumInit(MethodInfo * pMethodInfo, PTR_VOID * pMet
198227 *pMethodStartAddress = pNativeMethodInfo->pMethodStartAddress ;
199228
200229 pEnumState->pMethodStartAddress = dac_cast<PTR_UInt8>(pNativeMethodInfo->pMethodStartAddress );
201- pEnumState->pEHInfo = pNativeMethodInfo-> pEhInfo ;
230+ pEnumState->pEHInfo = dac_cast<PTR_UInt8>(p + *dac_cast<PTR_Int32>(p)) ;
202231 pEnumState->uClause = 0 ;
203232 pEnumState->nClauses = VarInt::ReadUnsigned (pEnumState->pEHInfo );
204233
0 commit comments