Skip to content
This repository was archived by the owner on Nov 1, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -356,17 +356,18 @@ public void BuildCFIMap(NodeFactory factory, ObjectNode node)
ObjectNode.ObjectData ehInfo = nodeWithCodeInfo.EHInfo;
string mainEhInfoSymbolName = null;

int i = 0;
foreach (var frameInfo in frameInfos)
for (int i = 0; i < frameInfos.Length; i++)
{
FrameInfo frameInfo = frameInfos[i];

int start = frameInfo.StartOffset;
int end = frameInfo.EndOffset;
int len = frameInfo.BlobData.Length;
byte[] blob = frameInfo.BlobData;

if (_targetPlatform.OperatingSystem == TargetOS.Windows)
{
string blobSymbolName = "_unwind" + (i++).ToStringInvariant() + _currentNodeName;
string blobSymbolName = "_unwind" + i.ToStringInvariant() + _currentNodeName;

ObjectNodeSection section = ObjectNodeSection.XDataSection;
if (node.ShouldShareNodeAcrossModules(factory) && factory.Target.OperatingSystem == TargetOS.Windows)
Expand Down Expand Up @@ -421,37 +422,48 @@ public void BuildCFIMap(NodeFactory factory, ObjectNode node)
}
else
{
string blobSymbolName = "_lsda" + (i++).ToStringInvariant() + _currentNodeName;
string blobSymbolName = "_lsda" + i.ToStringInvariant() + _currentNodeName;

SwitchSection(_nativeObjectWriter, LsdaSection.Name);

EmitAlignment(4);
EmitSymbolDef(blobSymbolName);

// emit relative offset from the main function
EmitIntValue((ulong)(start - frameInfos[0].StartOffset), 4);

// emit last byte from the blob - the function kind
FrameInfoFlags flags = frameInfo.Flags;
if ((ehInfo != null) || (mainEhInfoSymbolName != null))
if (ehInfo != null)
{
flags |= FrameInfoFlags.HasEHInfo;
}
EmitIntValue((byte)flags, 1);

if (i != 0)
{
EmitSymbolRef("_lsda0" + _currentNodeName, RelocType.IMAGE_REL_BASED_REL32, 4);

// emit relative offset from the main function
EmitIntValue((ulong)(start - frameInfos[0].StartOffset), 4);
}

if (ehInfo != null)
{
mainEhInfoSymbolName = "_ehInfo" + _currentNodeName;
EmitSymbolRef(mainEhInfoSymbolName, RelocType.IMAGE_REL_BASED_REL32, 4);
}

if (gcInfo != null)
{
EmitBlob(gcInfo);
gcInfo = null;
}

if (ehInfo != null)
{
// TODO: Place EHInfo into different section for better locality
Debug.Assert(ehInfo.Alignment == 1);
Debug.Assert(ehInfo.DefinedSymbols.Length == 0);
mainEhInfoSymbolName = "_ehInfo" + _currentNodeName;
EmitSymbolDef(mainEhInfoSymbolName);
EmitBlobWithRelocs(ehInfo.Data, ehInfo.Relocs);
ehInfo = null;
}
else if (mainEhInfoSymbolName != null)
{
EmitSymbolRef(mainEhInfoSymbolName, RelocType.IMAGE_REL_BASED_REL32, 4);
}

// For Unix, we build CFI blob map for each offset.
Debug.Assert(len % CfiCodeSize == 0);
Expand Down
3 changes: 1 addition & 2 deletions src/Native/Bootstrap/platform.unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,11 @@ extern "C"

void OutputDebugStringW()
{
throw "OutputDebugStringW";
}

uint32_t GetCurrentThreadId()
{
throw "GetCurrentThreadId";
return 42;
}

uint32_t RhCompatibleReentrantWaitAny(uint32_t alertable, uint32_t timeout, uint32_t count, void* pHandles)
Expand Down
4 changes: 4 additions & 0 deletions src/Native/Runtime/unix/UnixContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,10 @@ void UnwindCursorToRegDisplay(unw_cursor_t *cursor, unw_context_t *unwContext, R
unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &regDisplay->IP);
unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &regDisplay->SP);

#if defined(_AMD64_)
regDisplay->pIP = PTR_PCODE(regDisplay->SP - sizeof(TADDR));
#endif

#if defined(_ARM_) || defined(_ARM64_)
regDisplay->IP |= 1;
#endif
Expand Down
85 changes: 57 additions & 28 deletions src/Native/Runtime/unix/UnixNativeCodeManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

#include "CommonMacros.inl"

#define GCINFODECODER_NO_EE
#include "coreclr/gcinfodecoder.cpp"

#include "UnixContext.h"

#define UBF_FUNC_KIND_MASK 0x03
Expand All @@ -23,11 +26,13 @@

#define UBF_FUNC_HAS_EHINFO 0x04

#define UBF_FUNC_REVERSE_PINVOKE 0x08

struct UnixNativeMethodInfo
{
PTR_VOID pMethodStartAddress;
PTR_UInt8 pEhInfo;
uint8_t funcFlags;
PTR_UInt8 pMainLSDA;
PTR_UInt8 pLSDA;
bool executionAborted;
};

Expand Down Expand Up @@ -57,30 +62,26 @@ bool UnixNativeCodeManager::FindMethodInfo(PTR_VOID ControlPC,
return false;
}

PTR_UInt8 lsdaPtr = dac_cast<PTR_UInt8>(lsda);
PTR_UInt8 p = dac_cast<PTR_UInt8>(lsda);

int offsetFromMainFunction = *dac_cast<PTR_Int32>(lsdaPtr);
lsdaPtr += sizeof(int);
pMethodInfo->funcFlags = *lsdaPtr;
++lsdaPtr;
pMethodInfo->pLSDA = p;

PTR_UInt8 ehInfoPtr = NULL;
if (pMethodInfo->funcFlags & UBF_FUNC_HAS_EHINFO)
uint8_t unwindBlockFlags = *p++;

if ((unwindBlockFlags & UBF_FUNC_KIND_MASK) != UBF_FUNC_KIND_ROOT)
{
// main function contains the EH info blob in its LSDA, funclets just refer
// to the main function's blob
if (offsetFromMainFunction == 0)
{
ehInfoPtr = lsdaPtr;
}
else
{
ehInfoPtr = lsdaPtr + *dac_cast<PTR_Int32>(lsdaPtr);
}
// Funclets just refer to the main function's blob
pMethodInfo->pMainLSDA = p + *dac_cast<PTR_Int32>(p);
p += sizeof(int32_t);

pMethodInfo->pMethodStartAddress = dac_cast<PTR_VOID>(startAddress - *dac_cast<PTR_Int32>(p));
}
else
{
pMethodInfo->pMainLSDA = dac_cast<PTR_UInt8>(lsda);
pMethodInfo->pMethodStartAddress = dac_cast<PTR_VOID>(startAddress);
}

pMethodInfo->pMethodStartAddress = (PTR_VOID)(startAddress - offsetFromMainFunction);
pMethodInfo->pEhInfo = ehInfoPtr;
pMethodInfo->executionAborted = false;

return true;
Expand All @@ -90,7 +91,8 @@ bool UnixNativeCodeManager::IsFunclet(MethodInfo * pMethodInfo)
{
UnixNativeMethodInfo * pNativeMethodInfo = (UnixNativeMethodInfo *)pMethodInfo;

return (pNativeMethodInfo->funcFlags & UBF_FUNC_KIND_MASK) != UBF_FUNC_KIND_ROOT;
uint8_t unwindBlockFlags = *(pNativeMethodInfo->pLSDA);
return (unwindBlockFlags & UBF_FUNC_KIND_MASK) != UBF_FUNC_KIND_ROOT;
}

PTR_VOID UnixNativeCodeManager::GetFramePointer(MethodInfo * pMethodInfo,
Expand All @@ -99,7 +101,7 @@ PTR_VOID UnixNativeCodeManager::GetFramePointer(MethodInfo * pMethodInfo,
UnixNativeMethodInfo * pNativeMethodInfo = (UnixNativeMethodInfo *)pMethodInfo;

// Return frame pointer for methods with EH and funclets
uint8_t unwindBlockFlags = pNativeMethodInfo->funcFlags;
uint8_t unwindBlockFlags = *(pNativeMethodInfo->pLSDA);
if ((unwindBlockFlags & UBF_FUNC_HAS_EHINFO) != 0 || (unwindBlockFlags & UBF_FUNC_KIND_MASK) != UBF_FUNC_KIND_ROOT)
{
return (PTR_VOID)pRegisterSet->GetFP();
Expand Down Expand Up @@ -127,14 +129,37 @@ bool UnixNativeCodeManager::UnwindStackFrame(MethodInfo * pMethodInfo,
REGDISPLAY * pRegisterSet, // in/out
PTR_VOID * ppPreviousTransitionFrame) // out
{
if (!VirtualUnwind(pRegisterSet))
UnixNativeMethodInfo * pNativeMethodInfo = (UnixNativeMethodInfo *)pMethodInfo;

PTR_UInt8 p = pNativeMethodInfo->pMainLSDA;

uint8_t unwindBlockFlags = *p++;

if ((unwindBlockFlags & UBF_FUNC_REVERSE_PINVOKE) != 0)
{
return false;
// Reverse PInvoke transition should on the main function body only
assert(pNativeMethodInfo->pMainLSDA == pNativeMethodInfo->pLSDA);

if ((unwindBlockFlags & UBF_FUNC_HAS_EHINFO) != 0)
p += sizeof(int32_t);

GcInfoDecoder decoder(GCInfoToken(p), DECODE_REVERSE_PINVOKE_VAR);

// @TODO: CORERT: Encode reverse PInvoke frame slot in GCInfo: https://github.com/dotnet/corert/issues/2115
// INT32 slot = decoder.GetReversePInvokeFrameStackSlot();
// assert(slot != NO_REVERSE_PINVOKE_FRAME);

*ppPreviousTransitionFrame = (PTR_VOID)-1;
return true;
}

// @TODO: CORERT: PInvoke transitions
*ppPreviousTransitionFrame = NULL;

if (!VirtualUnwind(pRegisterSet))
{
return false;
}

return true;
}

Expand Down Expand Up @@ -187,8 +212,12 @@ bool UnixNativeCodeManager::EHEnumInit(MethodInfo * pMethodInfo, PTR_VOID * pMet

UnixNativeMethodInfo * pNativeMethodInfo = (UnixNativeMethodInfo *)pMethodInfo;

PTR_UInt8 p = pNativeMethodInfo->pMainLSDA;

uint8_t unwindBlockFlags = *p++;

// return if there is no EH info associated with this method
if ((pNativeMethodInfo->funcFlags & UBF_FUNC_HAS_EHINFO) == 0)
if ((unwindBlockFlags & UBF_FUNC_HAS_EHINFO) == 0)
{
return false;
}
Expand All @@ -198,7 +227,7 @@ bool UnixNativeCodeManager::EHEnumInit(MethodInfo * pMethodInfo, PTR_VOID * pMet
*pMethodStartAddress = pNativeMethodInfo->pMethodStartAddress;

pEnumState->pMethodStartAddress = dac_cast<PTR_UInt8>(pNativeMethodInfo->pMethodStartAddress);
pEnumState->pEHInfo = pNativeMethodInfo->pEhInfo;
pEnumState->pEHInfo = dac_cast<PTR_UInt8>(p + *dac_cast<PTR_Int32>(p));
pEnumState->uClause = 0;
pEnumState->nClauses = VarInt::ReadUnsigned(pEnumState->pEHInfo);

Expand Down
18 changes: 12 additions & 6 deletions src/Native/Runtime/windows/CoffNativeCodeManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "CommonMacros.inl"

#define GCINFODECODER_NO_EE
#include "coreclr\gcinfodecoder.cpp"
#include "coreclr/gcinfodecoder.cpp"

#define UBF_FUNC_KIND_MASK 0x03
#define UBF_FUNC_KIND_ROOT 0x00
Expand Down Expand Up @@ -306,27 +306,32 @@ bool CoffNativeCodeManager::UnwindStackFrame(MethodInfo * pMethodInfo,
CoffNativeMethodInfo * pNativeMethodInfo = (CoffNativeMethodInfo *)pMethodInfo;

size_t unwindDataBlobSize;
PTR_VOID pUnwindDataBlob = GetUnwindDataBlob(m_moduleBase, pNativeMethodInfo->mainRuntimeFunction, &unwindDataBlobSize);
PTR_VOID pUnwindDataBlob = GetUnwindDataBlob(m_moduleBase, pNativeMethodInfo->runtimeFunction, &unwindDataBlobSize);

PTR_UInt8 p = dac_cast<PTR_UInt8>(pUnwindDataBlob) + unwindDataBlobSize;

uint8_t unwindBlockFlags = *p++;

if ((unwindBlockFlags & UBF_FUNC_REVERSE_PINVOKE) != 0)
{
// Reverse PInvoke transition should on the main function body only
assert(pNativeMethodInfo->mainRuntimeFunction == pNativeMethodInfo->runtimeFunction);

if ((unwindBlockFlags & UBF_FUNC_HAS_EHINFO) != 0)
p += sizeof(int32_t);

GcInfoDecoder decoder(GCInfoToken(p), DECODE_REVERSE_PINVOKE_VAR);

// @TODO: CORERT: Encode reverse PInvoke frame slot in GCInfo: https://github.com/dotnet/corert/issues/2115
// INT32 slot = decoder.GetReversePInvokeFrameStackSlot();
// assert(slot != NO_REVERSE_PINVOKE_FRAME);

*ppPreviousTransitionFrame = (PTR_VOID)-1;
}
else
{
*ppPreviousTransitionFrame = NULL;
return true;
}

*ppPreviousTransitionFrame = NULL;

CONTEXT context;
KNONVOLATILE_CONTEXT_POINTERS contextPointers;

Expand Down Expand Up @@ -444,6 +449,7 @@ bool CoffNativeCodeManager::EHEnumInit(MethodInfo * pMethodInfo, PTR_VOID * pMet
}

*pMethodStartAddress = dac_cast<PTR_VOID>(m_moduleBase + pNativeMethodInfo->mainRuntimeFunction->BeginAddress);

pEnumState->pMethodStartAddress = dac_cast<PTR_UInt8>(*pMethodStartAddress);
pEnumState->pEHInfo = dac_cast<PTR_UInt8>(m_moduleBase + *dac_cast<PTR_Int32>(p));
pEnumState->uClause = 0;
Expand Down