You've already forked linux-packaging-mono
Imported Upstream version 5.2.0.175
Former-commit-id: bb0468d0f257ff100aa895eb5fe583fb5dfbf900
This commit is contained in:
parent
4bdbaf4a88
commit
966bba02bb
18
external/corert/src/Native/Bootstrap/main.cpp
vendored
18
external/corert/src/Native/Bootstrap/main.cpp
vendored
@@ -209,6 +209,10 @@ extern "C" void RhpUniversalTransition_DebugStepTailCall()
|
||||
{
|
||||
throw "RhpUniversalTransition_DebugStepTailCall";
|
||||
}
|
||||
extern "C" void CCWAddRef()
|
||||
{
|
||||
throw "CCWAddRef";
|
||||
}
|
||||
|
||||
void* RtRHeaderWrapper();
|
||||
|
||||
@@ -262,7 +266,7 @@ static const pfn c_classlibFunctions[] = {
|
||||
|
||||
#endif // !CPPCODEGEN
|
||||
|
||||
extern "C" void InitializeModules(void ** modules, int count);
|
||||
extern "C" void InitializeModules(void* osModule, void ** modules, int count);
|
||||
|
||||
#if defined(_WIN32)
|
||||
extern "C" int __managed__Main(int argc, wchar_t* argv[]);
|
||||
@@ -282,10 +286,14 @@ int main(int argc, char* argv[])
|
||||
return -1;
|
||||
|
||||
#ifndef CPPCODEGEN
|
||||
void *osModule;
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (!RhpRegisterCoffModule(GetModuleHandleW(NULL),
|
||||
osModule = GetModuleHandleW(NULL);
|
||||
if (!RhpRegisterCoffModule(osModule,
|
||||
#else // _WIN32
|
||||
if (!RhpRegisterUnixModule(PalGetModuleHandleFromPointer((void*)&main),
|
||||
osModule = PalGetModuleHandleFromPointer((void*)&main);
|
||||
if (!RhpRegisterUnixModule(osModule,
|
||||
#endif // _WIN32
|
||||
(void*)&__managedcode_a, (uint32_t)((char *)&__managedcode_z - (char*)&__managedcode_a),
|
||||
(void **)&c_classlibFunctions, _countof(c_classlibFunctions)))
|
||||
@@ -300,9 +308,9 @@ int main(int argc, char* argv[])
|
||||
#endif
|
||||
|
||||
#ifndef CPPCODEGEN
|
||||
InitializeModules(__modules_a, (int)((__modules_z - __modules_a)));
|
||||
InitializeModules(osModule, __modules_a, (int)((__modules_z - __modules_a)));
|
||||
#else // !CPPCODEGEN
|
||||
InitializeModules((void**)RtRHeaderWrapper(), 2);
|
||||
InitializeModules(nullptr, (void**)RtRHeaderWrapper(), 2);
|
||||
#endif // !CPPCODEGEN
|
||||
|
||||
int retval;
|
||||
|
||||
@@ -59,6 +59,21 @@ extern "C"
|
||||
throw "CoGetApartmentType";
|
||||
}
|
||||
|
||||
void CoUnmarshalInterface()
|
||||
{
|
||||
throw "CoUnmarshalInterface";
|
||||
}
|
||||
|
||||
void CoMarshalInterface()
|
||||
{
|
||||
throw "CoMarshalInterface";
|
||||
}
|
||||
|
||||
void CoGetMarshalSizeMax()
|
||||
{
|
||||
throw "CoGetMarshalSizeMax";
|
||||
}
|
||||
|
||||
void CreateEventExW()
|
||||
{
|
||||
throw "CreateEventExW";
|
||||
|
||||
9
external/corert/src/Native/CMakeLists.txt
vendored
9
external/corert/src/Native/CMakeLists.txt
vendored
@@ -22,7 +22,7 @@ function(clr_unknown_arch)
|
||||
if (WIN32)
|
||||
message(FATAL_ERROR "Only AMD64 and I386 are supported")
|
||||
else()
|
||||
message(FATAL_ERROR "Only AMD64, ARM64 and ARM are supported")
|
||||
message(FATAL_ERROR "Only AMD64, ARM64, ARM and ARMEL are supported")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
@@ -32,7 +32,12 @@ elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l)
|
||||
add_definitions(-DBIT32=1)
|
||||
# Because we don't use CMAKE_C_COMPILER/CMAKE_CXX_COMPILER to use clang
|
||||
# we have to set the triple by adding a compiler argument
|
||||
add_compile_options(-target armv7-linux-gnueabihf)
|
||||
if(TOOLCHAIN STREQUAL arm-linux-gnueabi)
|
||||
add_compile_options(-target armv7-linux-gnueabi)
|
||||
add_compile_options(-mfloat-abi=softfp)
|
||||
else ()
|
||||
add_compile_options(-target armv7-linux-gnueabihf)
|
||||
endif ()
|
||||
add_compile_options(-mthumb)
|
||||
add_compile_options(-mfpu=vfpv3)
|
||||
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64)
|
||||
|
||||
@@ -33,9 +33,7 @@ ASM_OFFSET( 4, 8, Array, m_Length)
|
||||
ASM_OFFSET( 0, 0, EEType, m_usComponentSize)
|
||||
ASM_OFFSET( 2, 2, EEType, m_usFlags)
|
||||
ASM_OFFSET( 4, 4, EEType, m_uBaseSize)
|
||||
#if defined(CORERT)
|
||||
// If this ever changes, you must update src\ILCompiler.Compiler\src\Compiler\DependencyAnalysis\EETypeNode.cs GetVTableOffset()
|
||||
// to reflect the updated VTable offset
|
||||
#if defined(EETYPE_TYPE_MANAGER)
|
||||
ASM_OFFSET( 18, 20, EEType, m_VTable)
|
||||
#else
|
||||
ASM_OFFSET( 14, 18, EEType, m_VTable)
|
||||
|
||||
@@ -4,6 +4,8 @@ set(COMMON_RUNTIME_SOURCES
|
||||
CachedInterfaceDispatch.cpp
|
||||
Crst.cpp
|
||||
DebugEventSource.cpp
|
||||
DebugFuncEval.cpp
|
||||
DebuggerHook.cpp
|
||||
dllmain.cpp
|
||||
eetype.cpp
|
||||
EHHelpers.cpp
|
||||
@@ -136,9 +138,12 @@ endif()
|
||||
|
||||
list(APPEND RUNTIME_SOURCES_ARCH_ASM
|
||||
${ARCH_SOURCES_DIR}/AllocFast.${ASM_SUFFIX}
|
||||
${ARCH_SOURCES_DIR}/CallDescrWorker.${ASM_SUFFIX}
|
||||
${ARCH_SOURCES_DIR}/CallingConventionConverterHelpers.${ASM_SUFFIX}
|
||||
${ARCH_SOURCES_DIR}/ExceptionHandling.${ASM_SUFFIX}
|
||||
${ARCH_SOURCES_DIR}/Interlocked.${ASM_SUFFIX}
|
||||
${ARCH_SOURCES_DIR}/PInvoke.${ASM_SUFFIX}
|
||||
${ARCH_SOURCES_DIR}/InteropThunksHelpers.${ASM_SUFFIX}
|
||||
${ARCH_SOURCES_DIR}/StubDispatch.${ASM_SUFFIX}
|
||||
${ARCH_SOURCES_DIR}/UniversalTransition.${ASM_SUFFIX}
|
||||
${ARCH_SOURCES_DIR}/WriteBarriers.${ASM_SUFFIX}
|
||||
@@ -159,6 +164,7 @@ add_definitions(-DVERIFY_HEAP)
|
||||
add_definitions(-DCORERT)
|
||||
add_definitions(-DFEATURE_CACHED_INTERFACE_DISPATCH)
|
||||
add_definitions(-D_LIB)
|
||||
add_definitions(-DEETYPE_TYPE_MANAGER)
|
||||
|
||||
if(WIN32)
|
||||
# There is a problem with undefined symbol g_pConfig, windows don't care since it is in template method, but clang does
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
#pragma optimize( "", off )
|
||||
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#ifndef __COMMONMACROS_H__
|
||||
#define __COMMONMACROS_H__
|
||||
|
||||
// Some of our header files are shared with the binder, which needs the _TARGET_* macros defined
|
||||
#if defined(_TARGET_AMD64_)
|
||||
#elif defined(_TARGET_X86_)
|
||||
@@ -229,3 +234,5 @@ typedef int32_t HRESULT;
|
||||
#define UNREFERENCED_PARAMETER(P) (void)(P)
|
||||
#endif // !defined(_INC_WINDOWS) && !defined(BINDER)
|
||||
#endif // GCENV_INCLUDED
|
||||
|
||||
#endif // __COMMONMACROS_H__
|
||||
@@ -97,6 +97,17 @@ void DebugEventSource::SendExceptionFirstPassFrameEnteredEvent(CORDB_ADDRESS ipI
|
||||
SendRawEvent(&payload);
|
||||
}
|
||||
|
||||
void DebugEventSource::SendCustomEvent(void* payload, int length)
|
||||
{
|
||||
if (!EventEnabled(DEBUG_EVENT_TYPE_CUSTOM))
|
||||
return;
|
||||
DebugEventPayload rawPayload;
|
||||
rawPayload.type = DEBUG_EVENT_TYPE_CUSTOM;
|
||||
rawPayload.Custom.payload = (CORDB_ADDRESS)payload;
|
||||
rawPayload.Custom.length = length;
|
||||
SendRawEvent(&rawPayload);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
//
|
||||
// Sends a raw managed debug event to the debugger.
|
||||
@@ -201,4 +212,10 @@ COOP_PINVOKE_HELPER(ExceptionEventKind, RhpGetRequestedExceptionEvents, ())
|
||||
return (ExceptionEventKind)mask;
|
||||
}
|
||||
|
||||
//Called by the C# func eval code to hand shake with the debugger
|
||||
COOP_PINVOKE_HELPER(void, RhpSendCustomEventToDebugger, (void* payload, int length))
|
||||
{
|
||||
DebugEventSource::SendCustomEvent(payload, length);
|
||||
}
|
||||
|
||||
#endif //!DACCESS_COMPILE
|
||||
|
||||
@@ -20,6 +20,7 @@ typedef UInt64 CORDB_ADDRESS;
|
||||
#ifndef DACCESS_COMPILE
|
||||
|
||||
struct DebugEventPayload;
|
||||
class Module;
|
||||
|
||||
class DebugEventSource
|
||||
{
|
||||
@@ -30,7 +31,7 @@ public:
|
||||
static void SendExceptionCatchHandlerFoundEvent(CORDB_ADDRESS handlerIP, CORDB_ADDRESS HandlerFrameSP);
|
||||
static void SendExceptionUnhandledEvent();
|
||||
static void SendExceptionFirstPassFrameEnteredEvent(CORDB_ADDRESS ipInFrame, CORDB_ADDRESS frameSP);
|
||||
|
||||
static void SendCustomEvent(void* payload, int length);
|
||||
private:
|
||||
static void SendRawEvent(DebugEventPayload* payload);
|
||||
};
|
||||
|
||||
54
external/corert/src/Native/Runtime/DebugFuncEval.cpp
vendored
Normal file
54
external/corert/src/Native/Runtime/DebugFuncEval.cpp
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#include "common.h"
|
||||
#include "CommonTypes.h"
|
||||
#include "DebugFuncEval.h"
|
||||
|
||||
GVAL_IMPL_INIT(UInt64, g_FuncEvalTarget, 0);
|
||||
GVAL_IMPL_INIT(UInt32, g_FuncEvalParameterBufferSize, 0);
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
|
||||
void* DebugFuncEval::GetFuncEvalTarget()
|
||||
{
|
||||
return (void*)g_FuncEvalTarget;
|
||||
}
|
||||
|
||||
UInt32 DebugFuncEval::GetFuncEvalParameterBufferSize()
|
||||
{
|
||||
return g_FuncEvalParameterBufferSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the global FuncEval target address.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// During debugging, if a FuncEval is requested,
|
||||
/// the func eval infrastructure needs to know which function to call, and
|
||||
/// the C# supporting code will call this API to obtain the FuncEval target address.
|
||||
/// By that time, the value should have been set through the UpdateFuncEvalTarget() method
|
||||
/// on the ISosRedhawk7 interface.
|
||||
/// </remarks>
|
||||
EXTERN_C REDHAWK_API void* __cdecl RhpGetFuncEvalTargetAddress()
|
||||
{
|
||||
return DebugFuncEval::GetFuncEvalTarget();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the global FuncEval parameter buffer size.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// During debugging, if a FuncEval is requested,
|
||||
/// the func eval infrastructure needs to know how much buffer to allocate for the debugger to
|
||||
/// write the parameter information in. The C# supporting code will call this API to obtain the
|
||||
/// buffer size. By that time, the value should have been set through the UpdateFuncEvalParameterSize()
|
||||
/// method on the ISosRedhawk7 interface.
|
||||
/// </remarks>
|
||||
EXTERN_C REDHAWK_API UInt32 __cdecl RhpGetFuncEvalParameterBufferSize()
|
||||
{
|
||||
return DebugFuncEval::GetFuncEvalParameterBufferSize();
|
||||
}
|
||||
|
||||
#endif //!DACCESS_COMPILE
|
||||
49
external/corert/src/Native/Runtime/DebugFuncEval.h
vendored
Normal file
49
external/corert/src/Native/Runtime/DebugFuncEval.h
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
// Support for evaluating expression in the debuggee during debugging
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
#ifndef __DEBUG_FUNC_EVAL_H__
|
||||
#define __DEBUG_FUNC_EVAL_H__
|
||||
|
||||
#include "common.h"
|
||||
#include "CommonTypes.h"
|
||||
#include "CommonMacros.h"
|
||||
#include "daccess.h"
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
|
||||
class DebugFuncEval
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Retrieve the global FuncEval target address
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// During debugging, if a FuncEval is requested,
|
||||
/// The func eval infrastructure needs to know which function to call, and
|
||||
/// It will call this API to obtain the target address.
|
||||
/// By the time, the value should have been set through the UpdateFuncEvalTarget() method
|
||||
/// on the ISosRedhawk7 interface.
|
||||
/// </remarks>
|
||||
static void* GetFuncEvalTarget();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the global FuncEval parameter buffer size.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// During debugging, if a FuncEval is requested,
|
||||
/// the func eval infrastructure needs to know how much buffer to allocate for the debugger to
|
||||
/// write the parameter information in. The C# supporting code will call this API to obtain the
|
||||
/// buffer size. By that time, the value should have been set through the UpdateFuncEvalParameterSize()
|
||||
/// method on the ISosRedhawk7 interface.
|
||||
/// </remarks>
|
||||
static UInt32 GetFuncEvalParameterBufferSize();
|
||||
};
|
||||
|
||||
#endif //!DACCESS_COMPILE
|
||||
|
||||
#endif // __DEBUG_FUNC_EVAL_H__
|
||||
77
external/corert/src/Native/Runtime/DebuggerHook.cpp
vendored
Normal file
77
external/corert/src/Native/Runtime/DebuggerHook.cpp
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#include "common.h"
|
||||
#include "CommonTypes.h"
|
||||
#include "DebuggerHook.h"
|
||||
#include "DebugEventSource.h"
|
||||
|
||||
GVAL_IMPL_INIT(UInt32, g_numGcProtectionRequests, 0);
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
|
||||
// TODO: Tab to space, overall, just to make sure I will actually do it :)
|
||||
// TODO: This structure needs to match with DBI
|
||||
struct FuncEvalParameterCommand
|
||||
{
|
||||
// TODO: Consider giving these command code a good enumeration to define what they really are
|
||||
UInt32 commandCode;
|
||||
UInt32 unused; /* To make the data structure 64 bit aligned */
|
||||
UInt64 bufferAddress;
|
||||
};
|
||||
|
||||
// TODO: This structure needs to match with DBI
|
||||
struct GcProtectionRequest
|
||||
{
|
||||
UInt16 type;
|
||||
UInt16 size;
|
||||
UInt64 address;
|
||||
};
|
||||
|
||||
/* static */ void DebuggerHook::OnBeforeGcCollection()
|
||||
{
|
||||
if (g_numGcProtectionRequests > 0)
|
||||
{
|
||||
// The debugger has some request with respect to GC protection.
|
||||
// Here we are allocating a buffer to store them
|
||||
GcProtectionRequest* requests = new (nothrow) GcProtectionRequest[g_numGcProtectionRequests];
|
||||
|
||||
// TODO: We need to figure out how to communicate this broken promise to the debugger
|
||||
|
||||
// Notifying the debugger the buffer is ready to use
|
||||
FuncEvalParameterCommand command;
|
||||
command.commandCode = 2;
|
||||
command.bufferAddress = (uint64_t)requests;
|
||||
DebugEventSource::SendCustomEvent((void*)&command, sizeof(command));
|
||||
|
||||
// ... debugger magic happen here ...
|
||||
|
||||
// The debugger has filled the requests array
|
||||
for (uint32_t i = 0; i < g_numGcProtectionRequests; i++)
|
||||
{
|
||||
if (requests[i].type == 1)
|
||||
{
|
||||
// If the request requires extra memory, allocate for it
|
||||
requests[i].address = (uint64_t)new (nothrow) uint8_t[requests[i].size];
|
||||
}
|
||||
}
|
||||
|
||||
command.commandCode = 3;
|
||||
DebugEventSource::SendCustomEvent((void*)&command, sizeof(command));
|
||||
|
||||
// ... debugger magic happen here again ...
|
||||
|
||||
for (uint32_t i = 0; i < g_numGcProtectionRequests; i++)
|
||||
{
|
||||
if (requests[i].type == 1)
|
||||
{
|
||||
// What shall I do?
|
||||
}
|
||||
}
|
||||
|
||||
g_numGcProtectionRequests = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !DACCESS_COMPILE
|
||||
28
external/corert/src/Native/Runtime/DebuggerHook.h
vendored
Normal file
28
external/corert/src/Native/Runtime/DebuggerHook.h
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
// Support for evaluating expression in the debuggee during debugging
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
#ifndef __DEBUGGER_HOOK_H__
|
||||
#define __DEBUGGER_HOOK_H__
|
||||
|
||||
#include "common.h"
|
||||
#include "CommonTypes.h"
|
||||
#ifdef DACCESS_COMPILE
|
||||
#include "CommonMacros.h"
|
||||
#endif
|
||||
#include "daccess.h"
|
||||
|
||||
#ifndef DACCESS_COMPILE
|
||||
|
||||
class DebuggerHook
|
||||
{
|
||||
public:
|
||||
static void OnBeforeGcCollection();
|
||||
};
|
||||
|
||||
#endif //!DACCESS_COMPILE
|
||||
|
||||
#endif // __DEBUGGER_HOOK_H__
|
||||
36
external/corert/src/Native/Runtime/EHHelpers.cpp
vendored
36
external/corert/src/Native/Runtime/EHHelpers.cpp
vendored
@@ -367,14 +367,11 @@ static UIntNative UnwindWriteBarrierToCaller(
|
||||
#endif
|
||||
#if defined(_AMD64_) || defined(_X86_)
|
||||
// simulate a ret instruction
|
||||
UIntNative sp = pContext->GetSp(); // get the stack pointer
|
||||
UIntNative adjustedFaultingIP = *(UIntNative *)sp - 5; // call instruction will be 6 bytes - act as if start of call instruction + 1 were the faulting IP
|
||||
UIntNative sp = pContext->GetSp();
|
||||
UIntNative adjustedFaultingIP = *(UIntNative *)sp;
|
||||
pContext->SetSp(sp+sizeof(UIntNative)); // pop the stack
|
||||
#elif defined(_ARM_)
|
||||
UIntNative adjustedFaultingIP = pContext->GetLr() - 2; // bl instruction will be 4 bytes - act as if start of call instruction + 2 were the faulting IP
|
||||
#elif defined(_ARM64_)
|
||||
PORTABILITY_ASSERT("@TODO: FIXME:ARM64");
|
||||
UIntNative adjustedFaultingIP = -1;
|
||||
#elif defined(_ARM_) || defined(_ARM64_)
|
||||
UIntNative adjustedFaultingIP = pContext->GetLr();
|
||||
#else
|
||||
#error "Unknown Architecture"
|
||||
#endif
|
||||
@@ -390,11 +387,14 @@ Int32 __stdcall RhpHardwareExceptionHandler(UIntNative faultCode, UIntNative fau
|
||||
ICodeManager * pCodeManager = GetRuntimeInstance()->FindCodeManagerByAddress((PTR_VOID)faultingIP);
|
||||
if ((pCodeManager != NULL) || (faultCode == STATUS_ACCESS_VIOLATION && InWriteBarrierHelper(faultingIP)))
|
||||
{
|
||||
// Make sure that the OS does not use our internal fault codes
|
||||
ASSERT(faultCode != STATUS_REDHAWK_NULL_REFERENCE && faultCode != STATUS_REDHAWK_WRITE_BARRIER_NULL_REFERENCE);
|
||||
|
||||
if (faultCode == STATUS_ACCESS_VIOLATION)
|
||||
{
|
||||
if (faultAddress < NULL_AREA_SIZE)
|
||||
{
|
||||
faultCode = STATUS_REDHAWK_NULL_REFERENCE;
|
||||
faultCode = pCodeManager ? STATUS_REDHAWK_NULL_REFERENCE : STATUS_REDHAWK_WRITE_BARRIER_NULL_REFERENCE;
|
||||
}
|
||||
|
||||
if (pCodeManager == NULL)
|
||||
@@ -405,7 +405,9 @@ Int32 __stdcall RhpHardwareExceptionHandler(UIntNative faultCode, UIntNative fau
|
||||
}
|
||||
else if (faultCode == STATUS_STACK_OVERFLOW)
|
||||
{
|
||||
ASSERT_UNCONDITIONALLY("managed stack overflow");
|
||||
// Do not use ASSERT_UNCONDITIONALLY here. It will crash because of it consumes too much stack.
|
||||
|
||||
PalPrintFatalError("\nProcess is terminating due to StackOverflowException.\n");
|
||||
RhFailFast();
|
||||
}
|
||||
|
||||
@@ -429,10 +431,16 @@ Int32 __stdcall RhpVectoredExceptionHandler(PEXCEPTION_POINTERS pExPtrs)
|
||||
UIntNative faultCode = pExPtrs->ExceptionRecord->ExceptionCode;
|
||||
if ((pCodeManager != NULL) || (faultCode == STATUS_ACCESS_VIOLATION && InWriteBarrierHelper(faultingIP)))
|
||||
{
|
||||
// Make sure that the OS does not use our internal fault codes
|
||||
ASSERT(faultCode != STATUS_REDHAWK_NULL_REFERENCE && faultCode != STATUS_REDHAWK_WRITE_BARRIER_NULL_REFERENCE);
|
||||
|
||||
if (faultCode == STATUS_ACCESS_VIOLATION)
|
||||
{
|
||||
if (pExPtrs->ExceptionRecord->ExceptionInformation[1] < NULL_AREA_SIZE)
|
||||
faultCode = STATUS_REDHAWK_NULL_REFERENCE;
|
||||
{
|
||||
faultCode = pCodeManager ? STATUS_REDHAWK_NULL_REFERENCE : STATUS_REDHAWK_WRITE_BARRIER_NULL_REFERENCE;
|
||||
}
|
||||
|
||||
if (pCodeManager == NULL)
|
||||
{
|
||||
// we were AV-ing in a write barrier helper - unwind our way to our caller
|
||||
@@ -441,8 +449,10 @@ Int32 __stdcall RhpVectoredExceptionHandler(PEXCEPTION_POINTERS pExPtrs)
|
||||
}
|
||||
else if (faultCode == STATUS_STACK_OVERFLOW)
|
||||
{
|
||||
ASSERT_UNCONDITIONALLY("managed stack overflow");
|
||||
RhFailFast2(pExPtrs->ExceptionRecord, pExPtrs->ContextRecord);
|
||||
// Do not use ASSERT_UNCONDITIONALLY here. It will crash because of it consumes too much stack.
|
||||
|
||||
PalPrintFatalError("\nProcess is terminating due to StackOverflowException.\n");
|
||||
PalRaiseFailFastException(pExPtrs->ExceptionRecord, pExPtrs->ContextRecord, 0);
|
||||
}
|
||||
|
||||
pExPtrs->ContextRecord->SetIp((UIntNative)&RhpThrowHwEx);
|
||||
@@ -478,7 +488,7 @@ Int32 __stdcall RhpVectoredExceptionHandler(PEXCEPTION_POINTERS pExPtrs)
|
||||
// Generally any form of hardware exception within the runtime itself is considered a fatal error.
|
||||
// Note this includes the managed code within the runtime.
|
||||
ASSERT_UNCONDITIONALLY("Hardware exception raised inside the runtime.");
|
||||
RhFailFast2(pExPtrs->ExceptionRecord, pExPtrs->ContextRecord);
|
||||
PalRaiseFailFastException(pExPtrs->ExceptionRecord, pExPtrs->ContextRecord, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,144 @@
|
||||
#include "shash.h"
|
||||
#include "module.h"
|
||||
|
||||
#include "regdisplay.h"
|
||||
#include "StackFrameIterator.h"
|
||||
|
||||
#include "thread.h"
|
||||
#include "threadstore.h"
|
||||
#include "threadstore.inl"
|
||||
#include "thread.inl"
|
||||
|
||||
GPTR_DECL(Thread, g_pFinalizerThread);
|
||||
|
||||
CLREventStatic g_FinalizerEvent;
|
||||
CLREventStatic g_FinalizerDoneEvent;
|
||||
|
||||
// Finalizer method implemented by redhawkm.
|
||||
extern "C" void __cdecl ProcessFinalizers();
|
||||
|
||||
// Unmanaged front-end to the finalizer thread. We require this because at the point the GC creates the
|
||||
// finalizer thread we're still executing the DllMain for RedhawkU. At that point we can't run managed code
|
||||
// successfully (in particular module initialization code has not run for RedhawkM). Instead this method waits
|
||||
// for the first finalization request (by which time everything must be up and running) and kicks off the
|
||||
// managed portion of the thread at that point.
|
||||
UInt32 WINAPI FinalizerStart(void* pContext)
|
||||
{
|
||||
HANDLE hFinalizerEvent = (HANDLE)pContext;
|
||||
|
||||
ThreadStore::AttachCurrentThread();
|
||||
Thread * pThread = GetThread();
|
||||
|
||||
// Disallow gcstress on this thread to work around the current implementation's limitation that it will
|
||||
// get into an infinite loop if performed on the finalizer thread.
|
||||
pThread->SetSuppressGcStress();
|
||||
|
||||
g_pFinalizerThread = PTR_Thread(pThread);
|
||||
|
||||
// Wait for a finalization request.
|
||||
UInt32 uResult = PalWaitForSingleObjectEx(hFinalizerEvent, INFINITE, FALSE);
|
||||
ASSERT(uResult == WAIT_OBJECT_0);
|
||||
|
||||
// Since we just consumed the request (and the event is auto-reset) we must set the event again so the
|
||||
// managed finalizer code will immediately start processing the queue when we run it.
|
||||
UInt32_BOOL fResult = PalSetEvent(hFinalizerEvent);
|
||||
ASSERT(fResult);
|
||||
|
||||
// Run the managed portion of the finalizer. Until we implement (non-process) shutdown this call will
|
||||
// never return.
|
||||
|
||||
ProcessFinalizers();
|
||||
|
||||
ASSERT(!"Finalizer thread should never return");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool RhStartFinalizerThread()
|
||||
{
|
||||
#ifdef APP_LOCAL_RUNTIME
|
||||
|
||||
//
|
||||
// On app-local runtimes, if we're running with the fallback PAL code (meaning we don't have IManagedRuntimeServices)
|
||||
// then we use the WinRT ThreadPool to create the finalizer thread. This might fail at startup, if the current thread
|
||||
// hasn't been CoInitialized. So we need to retry this later. We use fFinalizerThreadCreated to track whether we've
|
||||
// successfully created the finalizer thread yet, and also as a sort of lock to make sure two threads don't try
|
||||
// to create the finalizer thread at the same time.
|
||||
//
|
||||
static volatile Int32 fFinalizerThreadCreated;
|
||||
|
||||
if (Interlocked::Exchange(&fFinalizerThreadCreated, 1) != 1)
|
||||
{
|
||||
if (!PalStartFinalizerThread(FinalizerStart, (void*)g_FinalizerEvent.GetOSEvent()))
|
||||
{
|
||||
// Need to try again another time...
|
||||
Interlocked::Exchange(&fFinalizerThreadCreated, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// We always return true, so the GC can start even if we failed.
|
||||
return true;
|
||||
|
||||
#else // APP_LOCAL_RUNTIME
|
||||
|
||||
//
|
||||
// If this isn't an app-local runtime, then the PAL will just call CreateThread directly, which should succeed
|
||||
// under normal circumstances.
|
||||
//
|
||||
if (PalStartFinalizerThread(FinalizerStart, (void*)g_FinalizerEvent.GetOSEvent()))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
||||
#endif // APP_LOCAL_RUNTIME
|
||||
}
|
||||
|
||||
bool RhInitializeFinalization()
|
||||
{
|
||||
// Allocate the events the GC expects the finalizer thread to have. The g_FinalizerEvent event is signalled
|
||||
// by the GC whenever it completes a collection where it found otherwise unreachable finalizable objects.
|
||||
// The g_FinalizerDoneEvent is set by the finalizer thread every time it wakes up and drains the
|
||||
// queue of finalizable objects. It's mainly used by GC.WaitForPendingFinalizers().
|
||||
if (!g_FinalizerEvent.CreateAutoEventNoThrow(false))
|
||||
return false;
|
||||
if (!g_FinalizerDoneEvent.CreateManualEventNoThrow(false))
|
||||
return false;
|
||||
|
||||
// Create the finalizer thread itself.
|
||||
if (!RhStartFinalizerThread())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RhEnableFinalization()
|
||||
{
|
||||
g_FinalizerEvent.Set();
|
||||
}
|
||||
|
||||
EXTERN_C REDHAWK_API void __cdecl RhWaitForPendingFinalizers(UInt32_BOOL allowReentrantWait)
|
||||
{
|
||||
// This must be called via p/invoke rather than RuntimeImport since it blocks and could starve the GC if
|
||||
// called in cooperative mode.
|
||||
ASSERT(!GetThread()->IsCurrentThreadInCooperativeMode());
|
||||
|
||||
// Can't call this from the finalizer thread itself.
|
||||
if (GetThread() != g_pFinalizerThread)
|
||||
{
|
||||
// Clear any current indication that a finalization pass is finished and wake the finalizer thread up
|
||||
// (if there's no work to do it'll set the done event immediately).
|
||||
g_FinalizerDoneEvent.Reset();
|
||||
g_FinalizerEvent.Set();
|
||||
|
||||
#ifdef APP_LOCAL_RUNTIME
|
||||
// We may have failed to create the finalizer thread at startup.
|
||||
// Try again now.
|
||||
RhStartFinalizerThread();
|
||||
#endif
|
||||
|
||||
// Wait for the finalizer thread to get back to us.
|
||||
g_FinalizerDoneEvent.Wait(INFINITE, false, allowReentrantWait);
|
||||
}
|
||||
}
|
||||
|
||||
// Block the current thread until at least one object needs to be finalized (returns true) or memory is low
|
||||
// (returns false and the finalizer thread should initiate a garbage collection).
|
||||
@@ -39,13 +177,13 @@ EXTERN_C REDHAWK_API UInt32_BOOL __cdecl RhpWaitForFinalizerRequest()
|
||||
HANDLE lowMemEvent = NULL;
|
||||
#if 0 // TODO: hook up low memory notification
|
||||
lowMemEvent = pHeap->GetLowMemoryNotificationEvent();
|
||||
HANDLE rgWaitHandles[] = { FinalizerThread::GetFinalizerEvent(), lowMemEvent };
|
||||
HANDLE rgWaitHandles[] = { g_FinalizerEvent.GetOSEvent(), lowMemEvent };
|
||||
UInt32 cWaitHandles = (fLastEventWasLowMemory || (lowMemEvent == NULL)) ? 1 : 2;
|
||||
UInt32 uTimeout = fLastEventWasLowMemory ? 2000 : INFINITE;
|
||||
|
||||
UInt32 uResult = PalWaitForMultipleObjectsEx(cWaitHandles, rgWaitHandles, FALSE, uTimeout, FALSE);
|
||||
#else
|
||||
UInt32 uResult = PalWaitForSingleObjectEx(FinalizerThread::GetFinalizerEvent(), INFINITE, FALSE);
|
||||
UInt32 uResult = PalWaitForSingleObjectEx(g_FinalizerEvent.GetOSEvent(), INFINITE, FALSE);
|
||||
#endif
|
||||
|
||||
switch (uResult)
|
||||
@@ -77,7 +215,7 @@ EXTERN_C REDHAWK_API UInt32_BOOL __cdecl RhpWaitForFinalizerRequest()
|
||||
// Indicate that the current round of finalizations is complete.
|
||||
EXTERN_C REDHAWK_API void __cdecl RhpSignalFinalizationComplete()
|
||||
{
|
||||
FinalizerThread::SignalFinalizationDone(TRUE);
|
||||
g_FinalizerDoneEvent.Set();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
66
external/corert/src/Native/Runtime/GCHelpers.cpp
vendored
66
external/corert/src/Native/Runtime/GCHelpers.cpp
vendored
@@ -25,15 +25,6 @@
|
||||
#include "threadstore.inl"
|
||||
#include "thread.inl"
|
||||
|
||||
EXTERN_C REDHAWK_API void __cdecl RhWaitForPendingFinalizers(UInt32_BOOL allowReentrantWait)
|
||||
{
|
||||
// This must be called via p/invoke rather than RuntimeImport since it blocks and could starve the GC if
|
||||
// called in cooperative mode.
|
||||
ASSERT(!GetThread()->IsCurrentThreadInCooperativeMode());
|
||||
|
||||
FinalizerThread::Wait(INFINITE, allowReentrantWait);
|
||||
}
|
||||
|
||||
EXTERN_C REDHAWK_API void __cdecl RhpCollect(UInt32 uGeneration, UInt32 uMode)
|
||||
{
|
||||
// This must be called via p/invoke rather than RuntimeImport to make the stack crawlable.
|
||||
@@ -65,6 +56,28 @@ EXTERN_C REDHAWK_API Int64 __cdecl RhpGetGcTotalMemory()
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXTERN_C REDHAWK_API Int32 __cdecl RhpStartNoGCRegion(Int64 totalSize, Boolean hasLohSize, Int64 lohSize, Boolean disallowFullBlockingGC)
|
||||
{
|
||||
Thread *pCurThread = GetThread();
|
||||
ASSERT(!pCurThread->IsCurrentThreadInCooperativeMode());
|
||||
|
||||
pCurThread->SetupHackPInvokeTunnel();
|
||||
pCurThread->DisablePreemptiveMode();
|
||||
|
||||
int result = GCHeapUtilities::GetGCHeap()->StartNoGCRegion(totalSize, hasLohSize, lohSize, disallowFullBlockingGC);
|
||||
|
||||
pCurThread->EnablePreemptiveMode();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
EXTERN_C REDHAWK_API Int32 __cdecl RhpEndNoGCRegion()
|
||||
{
|
||||
ASSERT(!GetThread()->IsCurrentThreadInCooperativeMode());
|
||||
|
||||
return GCHeapUtilities::GetGCHeap()->EndNoGCRegion();
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(void, RhSuppressFinalize, (OBJECTREF refObj))
|
||||
{
|
||||
if (!refObj->get_EEType()->HasFinalizer())
|
||||
@@ -99,9 +112,9 @@ COOP_PINVOKE_HELPER(Int32, RhGetGcLatencyMode, ())
|
||||
return GCHeapUtilities::GetGCHeap()->GetGcLatencyMode();
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(void, RhSetGcLatencyMode, (Int32 newLatencyMode))
|
||||
COOP_PINVOKE_HELPER(Int32, RhSetGcLatencyMode, (Int32 newLatencyMode))
|
||||
{
|
||||
GCHeapUtilities::GetGCHeap()->SetGcLatencyMode(newLatencyMode);
|
||||
return GCHeapUtilities::GetGCHeap()->SetGcLatencyMode(newLatencyMode);
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(Boolean, RhIsServerGc, ())
|
||||
@@ -153,3 +166,34 @@ COOP_PINVOKE_HELPER(Int64, RhGetLastGCDuration, (Int32 generation))
|
||||
{
|
||||
return GCHeapUtilities::GetGCHeap()->GetLastGCDuration(generation);
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(Boolean, RhRegisterForFullGCNotification, (Int32 maxGenerationThreshold, Int32 largeObjectHeapThreshold))
|
||||
{
|
||||
ASSERT(maxGenerationThreshold >= 1 && maxGenerationThreshold <= 99);
|
||||
ASSERT(largeObjectHeapThreshold >= 1 && largeObjectHeapThreshold <= 99);
|
||||
return GCHeapUtilities::GetGCHeap()->RegisterForFullGCNotification(maxGenerationThreshold, largeObjectHeapThreshold)
|
||||
? Boolean_true : Boolean_false;
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(Boolean, RhCancelFullGCNotification, ())
|
||||
{
|
||||
return GCHeapUtilities::GetGCHeap()->CancelFullGCNotification() ? Boolean_true : Boolean_false;
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(Int32, RhWaitForFullGCApproach, (Int32 millisecondsTimeout))
|
||||
{
|
||||
ASSERT(millisecondsTimeout >= -1);
|
||||
ASSERT(GetThread()->IsCurrentThreadInCooperativeMode());
|
||||
|
||||
int timeout = millisecondsTimeout == -1 ? INFINITE : millisecondsTimeout;
|
||||
return GCHeapUtilities::GetGCHeap()->WaitForFullGCApproach(millisecondsTimeout);
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(Int32, RhWaitForFullGCComplete, (Int32 millisecondsTimeout))
|
||||
{
|
||||
ASSERT(millisecondsTimeout >= -1);
|
||||
ASSERT(GetThread()->IsCurrentThreadInCooperativeMode());
|
||||
|
||||
int timeout = millisecondsTimeout == -1 ? INFINITE : millisecondsTimeout;
|
||||
return GCHeapUtilities::GetGCHeap()->WaitForFullGCComplete(millisecondsTimeout);
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ enum class ClasslibFunctionId
|
||||
FailFast = 1,
|
||||
UnhandledExceptionHandler = 2,
|
||||
AppendExceptionStackFrame = 3,
|
||||
CheckStaticClassConstruction = 4,
|
||||
};
|
||||
|
||||
class ICodeManager
|
||||
|
||||
249
external/corert/src/Native/Runtime/MiscHelpers.cpp
vendored
249
external/corert/src/Native/Runtime/MiscHelpers.cpp
vendored
@@ -62,6 +62,15 @@ EXTERN_C REDHAWK_API UInt32_BOOL __cdecl RhYield()
|
||||
return PalSwitchToThread();
|
||||
}
|
||||
|
||||
EXTERN_C REDHAWK_API void __cdecl RhFlushProcessWriteBuffers()
|
||||
{
|
||||
// This must be called via p/invoke -- it's a wait operation and we don't want to block thread suspension on this.
|
||||
ASSERT_MSG(!ThreadStore::GetCurrentThread()->IsCurrentThreadInCooperativeMode(),
|
||||
"You must p/invoke to RhFlushProcessWriteBuffers");
|
||||
|
||||
PalFlushProcessWriteBuffers();
|
||||
}
|
||||
|
||||
// Return the DispatchMap pointer of a type
|
||||
COOP_PINVOKE_HELPER(DispatchMap*, RhGetDispatchMapForType, (EEType * pEEType))
|
||||
{
|
||||
@@ -75,7 +84,7 @@ COOP_PINVOKE_HELPER(DispatchMap*, RhGetDispatchMapForType, (EEType * pEEType))
|
||||
// modules are available based on the return count. It is also possible to call this method without an array,
|
||||
// in which case just the module count is returned (note that it's still possible for the module count to
|
||||
// increase between calls to this method).
|
||||
COOP_PINVOKE_HELPER(UInt32, RhGetLoadedModules, (Array * pResultArray))
|
||||
COOP_PINVOKE_HELPER(UInt32, RhGetLoadedOSModules, (Array * pResultArray))
|
||||
{
|
||||
// Note that we depend on the fact that this is a COOP helper to make writing into an unpinned array safe.
|
||||
|
||||
@@ -99,11 +108,69 @@ COOP_PINVOKE_HELPER(UInt32, RhGetLoadedModules, (Array * pResultArray))
|
||||
}
|
||||
END_FOREACH_MODULE
|
||||
|
||||
ReaderWriterLock::ReadHolder read(&GetRuntimeInstance()->GetTypeManagerLock());
|
||||
|
||||
RuntimeInstance::OsModuleList osModules = GetRuntimeInstance()->GetOsModuleList();
|
||||
|
||||
for (RuntimeInstance::OsModuleList::Iterator iter = osModules.Begin(); iter != osModules.End(); iter++)
|
||||
{
|
||||
if (pResultArray && (cModules < cResultArrayElements))
|
||||
pResultElements[cModules] = iter->m_osModule;
|
||||
cModules++;
|
||||
}
|
||||
|
||||
return cModules;
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(HANDLE, RhGetModuleFromPointer, (PTR_VOID pPointerVal))
|
||||
// Get the list of currently loaded Redhawk modules (as OS HMODULE handles or TypeManager pointers as appropriate).
|
||||
// The caller provides a reference
|
||||
// to an array of pointer-sized elements and we return the total number of modules currently loaded (whether
|
||||
// that is less than, equal to or greater than the number of elements in the array). If there are more modules
|
||||
// loaded than the array will hold then the array is filled to capacity and the caller can tell further
|
||||
// modules are available based on the return count. It is also possible to call this method without an array,
|
||||
// in which case just the module count is returned (note that it's still possible for the module count to
|
||||
// increase between calls to this method).
|
||||
COOP_PINVOKE_HELPER(UInt32, RhGetLoadedModules, (Array * pResultArray))
|
||||
{
|
||||
// Note that we depend on the fact that this is a COOP helper to make writing into an unpinned array safe.
|
||||
|
||||
// If a result array is passed then it should be an array type with pointer-sized components that are not
|
||||
// GC-references.
|
||||
ASSERT(!pResultArray || pResultArray->get_EEType()->IsArray());
|
||||
ASSERT(!pResultArray || !pResultArray->get_EEType()->HasReferenceFields());
|
||||
ASSERT(!pResultArray || pResultArray->get_EEType()->get_ComponentSize() == sizeof(void*));
|
||||
|
||||
UInt32 cResultArrayElements = pResultArray ? pResultArray->GetArrayLength() : 0;
|
||||
TypeManagerHandle * pResultElements = pResultArray ? (TypeManagerHandle*)(pResultArray + 1) : NULL;
|
||||
|
||||
UInt32 cModules = 0;
|
||||
|
||||
FOREACH_MODULE(pModule)
|
||||
{
|
||||
if (pResultArray && (cModules < cResultArrayElements))
|
||||
pResultElements[cModules] = TypeManagerHandle::Create(pModule->GetOsModuleHandle());
|
||||
|
||||
cModules++;
|
||||
}
|
||||
END_FOREACH_MODULE
|
||||
|
||||
ReaderWriterLock::ReadHolder read(&GetRuntimeInstance()->GetTypeManagerLock());
|
||||
|
||||
RuntimeInstance::TypeManagerList typeManagers = GetRuntimeInstance()->GetTypeManagerList();
|
||||
|
||||
for (RuntimeInstance::TypeManagerList::Iterator iter = typeManagers.Begin(); iter != typeManagers.End(); iter++)
|
||||
{
|
||||
if (pResultArray && (cModules < cResultArrayElements))
|
||||
pResultElements[cModules] = TypeManagerHandle::Create(iter->m_pTypeManager);
|
||||
cModules++;
|
||||
}
|
||||
|
||||
return cModules;
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(HANDLE, RhGetOSModuleFromPointer, (PTR_VOID pPointerVal))
|
||||
{
|
||||
// TODO, this will always return nullptr in TypeManager based systems.
|
||||
Module * pModule = GetRuntimeInstance()->FindModuleByAddress(pPointerVal);
|
||||
|
||||
if (pModule != NULL)
|
||||
@@ -112,11 +179,16 @@ COOP_PINVOKE_HELPER(HANDLE, RhGetModuleFromPointer, (PTR_VOID pPointerVal))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(HANDLE, RhGetModuleFromEEType, (EEType * pEEType))
|
||||
COOP_PINVOKE_HELPER(HANDLE, RhGetOSModuleFromEEType, (EEType * pEEType))
|
||||
{
|
||||
#if CORERT
|
||||
return (HANDLE)(pEEType->GetTypeManager());
|
||||
return pEEType->GetTypeManagerPtr()->AsTypeManager()->GetOsModuleHandle();
|
||||
#else
|
||||
#if EETYPE_TYPE_MANAGER
|
||||
if (pEEType->HasTypeManager())
|
||||
return pEEType->GetTypeManagerPtr()->AsTypeManager()->GetOsModuleHandle();
|
||||
#endif
|
||||
|
||||
// For dynamically created types, return the module handle that contains the template type
|
||||
if (pEEType->IsDynamicType())
|
||||
pEEType = pEEType->get_DynamicTemplateType();
|
||||
@@ -137,65 +209,107 @@ COOP_PINVOKE_HELPER(HANDLE, RhGetModuleFromEEType, (EEType * pEEType))
|
||||
#endif // !CORERT
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(Boolean, RhFindBlob, (HANDLE hOsModule, UInt32 blobId, UInt8 ** ppbBlob, UInt32 * pcbBlob))
|
||||
COOP_PINVOKE_HELPER(TypeManagerHandle, RhGetModuleFromEEType, (EEType * pEEType))
|
||||
{
|
||||
#if CORERT
|
||||
ReadyToRunSectionType section =
|
||||
(ReadyToRunSectionType)((UInt32)ReadyToRunSectionType::ReadonlyBlobRegionStart + blobId);
|
||||
ASSERT(section <= ReadyToRunSectionType::ReadonlyBlobRegionEnd);
|
||||
|
||||
TypeManager* pModule = (TypeManager*)hOsModule;
|
||||
|
||||
int length;
|
||||
void* pBlob;
|
||||
pBlob = pModule->GetModuleSection(section, &length);
|
||||
|
||||
*ppbBlob = (UInt8*)pBlob;
|
||||
*pcbBlob = (UInt32)length;
|
||||
|
||||
return pBlob != NULL;
|
||||
return *pEEType->GetTypeManagerPtr();
|
||||
#else
|
||||
// Search for the Redhawk module contained by the OS module.
|
||||
#if EETYPE_TYPE_MANAGER
|
||||
if (pEEType->HasTypeManager())
|
||||
return *pEEType->GetTypeManagerPtr();
|
||||
#endif
|
||||
|
||||
// For dynamically created types, return the module handle that contains the template type
|
||||
if (pEEType->IsDynamicType())
|
||||
pEEType = pEEType->get_DynamicTemplateType();
|
||||
|
||||
if (pEEType->get_DynamicModule() != nullptr)
|
||||
{
|
||||
// We should never get here (an EEType not located in any module) so fail fast to indicate the bug.
|
||||
RhFailFast();
|
||||
return TypeManagerHandle::Null();
|
||||
}
|
||||
|
||||
FOREACH_MODULE(pModule)
|
||||
{
|
||||
if (pModule->GetOsModuleHandle() == hOsModule)
|
||||
{
|
||||
// Found a module match. Look through the blobs for one with a matching ID.
|
||||
UInt32 cbBlobs;
|
||||
BlobHeader * pBlob = pModule->GetReadOnlyBlobs(&cbBlobs);
|
||||
|
||||
while (cbBlobs)
|
||||
{
|
||||
UInt32 cbTotalBlob = sizeof(BlobHeader) + pBlob->m_size;
|
||||
ASSERT(cbBlobs >= cbTotalBlob);
|
||||
|
||||
if (pBlob->m_id == blobId)
|
||||
{
|
||||
// Found the matching blob, return it.
|
||||
*ppbBlob = (UInt8*)(pBlob + 1);
|
||||
*pcbBlob = pBlob->m_size;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cbBlobs -= cbTotalBlob;
|
||||
pBlob = (BlobHeader*)((UInt8*)pBlob + cbTotalBlob);
|
||||
}
|
||||
|
||||
// If we get here then we found a module match but didn't find a blob with a matching ID. That's a
|
||||
// non-catastrophic error.
|
||||
*ppbBlob = NULL;
|
||||
*pcbBlob = 0;
|
||||
return FALSE;
|
||||
}
|
||||
if (pModule->ContainsReadOnlyDataAddress(pEEType) || pModule->ContainsDataAddress(pEEType))
|
||||
return TypeManagerHandle::Create(pModule->GetOsModuleHandle());
|
||||
}
|
||||
END_FOREACH_MODULE
|
||||
|
||||
// We should never get here (an EEType not located in any module) so fail fast to indicate the bug.
|
||||
RhFailFast();
|
||||
return TypeManagerHandle::Null();
|
||||
#endif // !CORERT
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(Boolean, RhFindBlob, (TypeManagerHandle *pTypeManagerHandle, UInt32 blobId, UInt8 ** ppbBlob, UInt32 * pcbBlob))
|
||||
{
|
||||
TypeManagerHandle typeManagerHandle = *pTypeManagerHandle;
|
||||
|
||||
if (typeManagerHandle.IsTypeManager())
|
||||
{
|
||||
ReadyToRunSectionType section =
|
||||
(ReadyToRunSectionType)((UInt32)ReadyToRunSectionType::ReadonlyBlobRegionStart + blobId);
|
||||
ASSERT(section <= ReadyToRunSectionType::ReadonlyBlobRegionEnd);
|
||||
|
||||
TypeManager* pModule = typeManagerHandle.AsTypeManager();
|
||||
|
||||
int length;
|
||||
void* pBlob;
|
||||
pBlob = pModule->GetModuleSection(section, &length);
|
||||
|
||||
*ppbBlob = (UInt8*)pBlob;
|
||||
*pcbBlob = (UInt32)length;
|
||||
|
||||
return pBlob != NULL;
|
||||
}
|
||||
#if !CORERT
|
||||
else
|
||||
{
|
||||
HANDLE hOsModule = typeManagerHandle.AsOsModule();
|
||||
// Search for the Redhawk module contained by the OS module.
|
||||
FOREACH_MODULE(pModule)
|
||||
{
|
||||
if (pModule->GetOsModuleHandle() == hOsModule)
|
||||
{
|
||||
// Found a module match. Look through the blobs for one with a matching ID.
|
||||
UInt32 cbBlobs;
|
||||
BlobHeader * pBlob = pModule->GetReadOnlyBlobs(&cbBlobs);
|
||||
|
||||
while (cbBlobs)
|
||||
{
|
||||
UInt32 cbTotalBlob = sizeof(BlobHeader) + pBlob->m_size;
|
||||
ASSERT(cbBlobs >= cbTotalBlob);
|
||||
|
||||
if (pBlob->m_id == blobId)
|
||||
{
|
||||
// Found the matching blob, return it.
|
||||
*ppbBlob = (UInt8*)(pBlob + 1);
|
||||
*pcbBlob = pBlob->m_size;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cbBlobs -= cbTotalBlob;
|
||||
pBlob = (BlobHeader*)((UInt8*)pBlob + cbTotalBlob);
|
||||
}
|
||||
|
||||
// If we get here then we found a module match but didn't find a blob with a matching ID. That's a
|
||||
// non-catastrophic error.
|
||||
*ppbBlob = NULL;
|
||||
*pcbBlob = 0;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
END_FOREACH_MODULE
|
||||
}
|
||||
#endif // !CORERT
|
||||
|
||||
// If we get here we were passed a bad module handle and should fail fast since this indicates a nasty bug
|
||||
// (which could lead to the wrong blob being returned in some cases).
|
||||
RhFailFast();
|
||||
|
||||
return FALSE;
|
||||
#endif // !CORERT
|
||||
}
|
||||
|
||||
// This helper is not called directly but is used by the implementation of RhpCheckCctor to locate the
|
||||
@@ -203,17 +317,13 @@ COOP_PINVOKE_HELPER(Boolean, RhFindBlob, (HANDLE hOsModule, UInt32 blobId, UInt8
|
||||
// to code in the caller's module and can be used in the lookup.
|
||||
COOP_PINVOKE_HELPER(void *, GetClasslibCCtorCheck, (void * pReturnAddress))
|
||||
{
|
||||
// Locate the calling module from the context structure address (which is in writeable memory in the
|
||||
// Locate the calling module from the context structure address (which is in writable memory in the
|
||||
// module image).
|
||||
Module * pModule = GetRuntimeInstance()->FindModuleByCodeAddress(pReturnAddress);
|
||||
ASSERT(pModule);
|
||||
|
||||
// Locate the classlib module from the calling module.
|
||||
Module * pClasslibModule = pModule->GetClasslibModule();
|
||||
ASSERT(pClasslibModule);
|
||||
ICodeManager * pCodeManager = GetRuntimeInstance()->FindCodeManagerByAddress(pReturnAddress);
|
||||
ASSERT(pCodeManager);
|
||||
|
||||
// Lookup the callback registered by the classlib.
|
||||
void * pCallback = pClasslibModule->GetClasslibCheckStaticClassConstruction();
|
||||
void * pCallback = pCodeManager->GetClasslibFunction(ClasslibFunctionId::CheckStaticClassConstruction);
|
||||
|
||||
// We have no fallback path if we got here but the classlib doesn't implement the callback.
|
||||
if (pCallback == NULL)
|
||||
@@ -639,19 +749,24 @@ COOP_PINVOKE_HELPER(Boolean, RhpRegisterFrozenSegment, (void* pSegmentStart, UIn
|
||||
return RedhawkGCInterface::RegisterFrozenSection(pSegmentStart, length) != NULL;
|
||||
}
|
||||
|
||||
#ifdef CORERT
|
||||
COOP_PINVOKE_HELPER(void*, RhpGetModuleSection, (TypeManager* pModule, Int32 headerId, Int32* length))
|
||||
COOP_PINVOKE_HELPER(void*, RhpGetModuleSection, (TypeManagerHandle *pModule, Int32 headerId, Int32* length))
|
||||
{
|
||||
return pModule->GetModuleSection((ReadyToRunSectionType)headerId, length);
|
||||
return pModule->AsTypeManager()->GetModuleSection((ReadyToRunSectionType)headerId, length);
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(void*, RhpCreateTypeManager, (void* pModuleHeader))
|
||||
{
|
||||
return TypeManager::Create(pModuleHeader);
|
||||
}
|
||||
#endif
|
||||
|
||||
COOP_PINVOKE_HELPER(void, RhGetCurrentThreadStackBounds, (PTR_VOID * ppStackLow, PTR_VOID * ppStackHigh))
|
||||
{
|
||||
ThreadStore::GetCurrentThread()->GetStackBounds(ppStackLow, ppStackHigh);
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_UNIX
|
||||
|
||||
// Function to call when a thread is detached from the runtime
|
||||
ThreadExitCallback g_threadExitCallback;
|
||||
|
||||
COOP_PINVOKE_HELPER(void, RhSetThreadExitCallback, (void * pCallback))
|
||||
{
|
||||
g_threadExitCallback = (ThreadExitCallback)pCallback;
|
||||
}
|
||||
|
||||
#endif // PLATFORM_UNIX
|
||||
|
||||
@@ -498,9 +498,10 @@ typedef enum _EXCEPTION_DISPOSITION {
|
||||
ExceptionCollidedUnwind
|
||||
} EXCEPTION_DISPOSITION;
|
||||
|
||||
#define STATUS_ACCESS_VIOLATION ((UInt32 )0xC0000005L)
|
||||
#define STATUS_STACK_OVERFLOW ((UInt32 )0xC00000FDL)
|
||||
#define STATUS_REDHAWK_NULL_REFERENCE ((UInt32 )0x00000000L)
|
||||
#define STATUS_ACCESS_VIOLATION ((UInt32 )0xC0000005L)
|
||||
#define STATUS_STACK_OVERFLOW ((UInt32 )0xC00000FDL)
|
||||
#define STATUS_REDHAWK_NULL_REFERENCE ((UInt32 )0x00000000L)
|
||||
#define STATUS_REDHAWK_WRITE_BARRIER_NULL_REFERENCE ((UInt32 )0x00000042L)
|
||||
|
||||
#ifdef PLATFORM_UNIX
|
||||
#define NULL_AREA_SIZE (4*1024)
|
||||
@@ -838,6 +839,8 @@ REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalDetachThread(void* thread);
|
||||
|
||||
REDHAWK_PALIMPORT UInt64 PalGetCurrentThreadIdForLogging();
|
||||
|
||||
REDHAWK_PALIMPORT void PalPrintFatalError(const char* message);
|
||||
|
||||
#ifdef PLATFORM_UNIX
|
||||
REDHAWK_PALIMPORT Int32 __cdecl _stricmp(const char *string1, const char *string2);
|
||||
#endif // PLATFORM_UNIX
|
||||
|
||||
@@ -61,13 +61,15 @@ struct PAL_LIMITED_CONTEXT
|
||||
UIntNative GetIp() const { return IP; }
|
||||
UIntNative GetSp() const { return SP; }
|
||||
UIntNative GetFp() const { return R7; }
|
||||
UIntNative GetLr() const { return LR; }
|
||||
void SetIp(UIntNative ip) { IP = ip; }
|
||||
#elif defined(_TARGET_ARM64_)
|
||||
// @TODO: Add ARM64 registers
|
||||
UIntNative IP;
|
||||
UIntNative GetIp() const { PORTABILITY_ASSERT("@TODO: FIXME:ARM64"); }
|
||||
UIntNative GetSp() const { PORTABILITY_ASSERT("@TODO: FIXME:ARM64"); }
|
||||
UIntNative GetFp() const { PORTABILITY_ASSERT("@TODO: FIXME:ARM64"); }
|
||||
|
||||
UIntNative GetLr() const { PORTABILITY_ASSERT("@TODO: FIXME:ARM64"); }
|
||||
#elif defined(UNIX_AMD64_ABI)
|
||||
// Param regs: rdi, rsi, rdx, rcx, r8, r9, scratch: rax, rdx (both return val), preserved: rbp, rbx, r12-r15
|
||||
UIntNative IP;
|
||||
@@ -121,6 +123,10 @@ struct PAL_LIMITED_CONTEXT
|
||||
void RuntimeThreadShutdown(void* thread);
|
||||
|
||||
#ifdef PLATFORM_UNIX
|
||||
typedef void (__fastcall * ThreadExitCallback)();
|
||||
|
||||
extern ThreadExitCallback g_threadExitCallback;
|
||||
|
||||
typedef Int32 (*PHARDWARE_EXCEPTION_HANDLER)(UIntNative faultCode, UIntNative faultAddress, PAL_LIMITED_CONTEXT* palContext, UIntNative* arg0Reg, UIntNative* arg1Reg);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -248,6 +248,11 @@ void RuntimeInstance::EnumAllStaticGCRefs(void * pfnCallback, void * pvCallbackD
|
||||
}
|
||||
END_FOREACH_MODULE
|
||||
|
||||
for (TypeManagerList::Iterator iter = m_TypeManagerList.Begin(); iter != m_TypeManagerList.End(); iter++)
|
||||
{
|
||||
iter->m_pTypeManager->EnumStaticGCRefs(pfnCallback, pvCallbackData);
|
||||
}
|
||||
|
||||
EnumStaticGCRefDescs(pfnCallback, pvCallbackData);
|
||||
EnumThreadStaticGCRefDescs(pfnCallback, pvCallbackData);
|
||||
}
|
||||
@@ -407,6 +412,68 @@ extern "C" void __stdcall UnregisterCodeManager(ICodeManager * pCodeManager)
|
||||
}
|
||||
#endif
|
||||
|
||||
bool RuntimeInstance::RegisterTypeManager(TypeManager * pTypeManager)
|
||||
{
|
||||
TypeManagerEntry * pEntry = new (nothrow) TypeManagerEntry();
|
||||
if (NULL == pEntry)
|
||||
return false;
|
||||
|
||||
pEntry->m_pTypeManager = pTypeManager;
|
||||
|
||||
{
|
||||
ReaderWriterLock::WriteHolder write(&m_ModuleListLock);
|
||||
|
||||
m_TypeManagerList.PushHead(pEntry);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(TypeManagerHandle, RhpCreateTypeManager, (HANDLE osModule, void* pModuleHeader))
|
||||
{
|
||||
TypeManager * typeManager = TypeManager::Create(osModule, pModuleHeader);
|
||||
GetRuntimeInstance()->RegisterTypeManager(typeManager);
|
||||
return TypeManagerHandle::Create(typeManager);
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(HANDLE, RhGetOSModuleForMrt, ())
|
||||
{
|
||||
return GetRuntimeInstance()->GetPalInstance();
|
||||
}
|
||||
|
||||
COOP_PINVOKE_HELPER(void*, RhpRegisterOsModule, (HANDLE hOsModule))
|
||||
{
|
||||
RuntimeInstance::OsModuleEntry * pEntry = new (nothrow) RuntimeInstance::OsModuleEntry();
|
||||
if (NULL == pEntry)
|
||||
return nullptr; // Return null on failure.
|
||||
|
||||
pEntry->m_osModule = hOsModule;
|
||||
|
||||
{
|
||||
RuntimeInstance *pRuntimeInstance = GetRuntimeInstance();
|
||||
ReaderWriterLock::WriteHolder write(&pRuntimeInstance->GetTypeManagerLock());
|
||||
|
||||
pRuntimeInstance->GetOsModuleList().PushHead(pEntry);
|
||||
}
|
||||
|
||||
return hOsModule; // Return non-null on success
|
||||
}
|
||||
|
||||
RuntimeInstance::TypeManagerList& RuntimeInstance::GetTypeManagerList()
|
||||
{
|
||||
return m_TypeManagerList;
|
||||
}
|
||||
|
||||
RuntimeInstance::OsModuleList& RuntimeInstance::GetOsModuleList()
|
||||
{
|
||||
return m_OsModuleList;
|
||||
}
|
||||
|
||||
ReaderWriterLock& RuntimeInstance::GetTypeManagerLock()
|
||||
{
|
||||
return m_ModuleListLock;
|
||||
}
|
||||
|
||||
// static
|
||||
RuntimeInstance * RuntimeInstance::Create(HANDLE hPalInstance)
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user