Skip to content
Closed
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 @@ -418,9 +418,21 @@ internal static Delegate CreateDelegateNoSecurityCheck(Type type, object? target
// internal implementation details (FCALLS and utilities)
//

[DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)]
private static extern bool BindToMethodName(ObjectHandleOnStack delegateObj, ObjectHandleOnStack target, QCallTypeHandle methodType, string method, DelegateBindingFlags flags);

[RequiresUnreferencedCode("The target method might be removed")]
[MethodImpl(MethodImplOptions.InternalCall)]
private extern bool BindToMethodName(object? target, RuntimeType methodType, string method, DelegateBindingFlags flags);
private bool BindToMethodName(object? target, RuntimeType methodType, string method, DelegateBindingFlags flags)
{
Delegate delArg = this;
return BindToMethodName(
ObjectHandleOnStack.Create(ref delArg),
ObjectHandleOnStack.Create(ref target),
new QCallTypeHandle(ref methodType),
method,
flags
);
}

[MethodImpl(MethodImplOptions.InternalCall)]
private extern bool BindToMethodInfo(object? target, IRuntimeMethodInfo method, RuntimeType methodType, DelegateBindingFlags flags);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// and is used for communicating with a debugger.

using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace System.Diagnostics
{
Expand Down Expand Up @@ -50,7 +51,7 @@ public static void NotifyOfCrossThreadDependency()
}
}

[MethodImpl(MethodImplOptions.InternalCall)]
[DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)]
private static extern bool LaunchInternal();

// Returns whether or not a debugger is attached to the process.
Expand All @@ -74,8 +75,11 @@ public static extern bool IsAttached
// Posts a message for the attached debugger. If there is no
// debugger attached, has no effect. The debugger may or may not
// report the message depending on its settings.
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern void Log(int level, string? category, string? message);
public static void Log(int level, string? category, string? message) => LogInternal(level, category, message);


[DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)]
private static extern void LogInternal(int level, string? category, string? message);

// Checks to see if an attached debugger has logging enabled
//
Expand Down
11 changes: 9 additions & 2 deletions src/coreclr/src/System.Private.CoreLib/src/System/StubHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1328,8 +1328,15 @@ internal static void CheckStringLength(uint length)
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern uint CalcVaListSize(IntPtr va_list);

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void ValidateObject(object obj, IntPtr pMD, object pThis);
[DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)]
internal static extern void ValidateObject(ObjectHandleOnStack obj, IntPtr pMD, ObjectHandleOnStack pThis);

internal static void ValidateObject(object obj, IntPtr pMD, object pThis)
{
object objLocal = obj;
object localThis = pThis;
ValidateObject(ObjectHandleOnStack.Create(ref objLocal), pMD, ObjectHandleOnStack.Create(ref localThis));
}

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void LogPinnedArgument(IntPtr localDesc, IntPtr nativeArg);
Expand Down
46 changes: 23 additions & 23 deletions src/coreclr/src/vm/comdelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -789,33 +789,31 @@ static PCODE GetVirtualCallStub(MethodDesc *method, TypeHandle scopeType)
return pTargetCall;
}

FCIMPL5(FC_BOOL_RET, COMDelegate::BindToMethodName,
Object *refThisUNSAFE,
Object *targetUNSAFE,
ReflectClassBaseObject *pMethodTypeUNSAFE,
StringObject* methodNameUNSAFE,
int flags)
BOOL QCALLTYPE COMDelegate::BindToMethodName(
QCall::ObjectHandleOnStack delegate,
QCall::ObjectHandleOnStack target,
QCall::TypeHandle methodTypeHandle,
PCWSTR pwzMethodName,
int flags)
{
FCALL_CONTRACT;
QCALL_CONTRACT;

MethodDesc *pMatchingMethod = NULL;

BEGIN_QCALL;
GCX_COOP();

struct _gc
{
DELEGATEREF refThis;
OBJECTREF target;
STRINGREF methodName;
REFLECTCLASSBASEREF refMethodType;
} gc;

gc.refThis = (DELEGATEREF) ObjectToOBJECTREF(refThisUNSAFE);
gc.target = (OBJECTREF) targetUNSAFE;
gc.methodName = (STRINGREF) methodNameUNSAFE;
gc.refMethodType = (REFLECTCLASSBASEREF) ObjectToOBJECTREF(pMethodTypeUNSAFE);
gc.refThis = (DELEGATEREF) delegate.Get();
gc.target = (OBJECTREF) target.Get();
TypeHandle methodType = methodTypeHandle.AsTypeHandle();

TypeHandle methodType = gc.refMethodType->GetType();

MethodDesc *pMatchingMethod = NULL;

HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
GCPROTECT_BEGIN(gc);

// Caching of MethodDescs (impl and decl) for MethodTable slots provided significant
// performance gain in some reflection emit scenarios.
Expand All @@ -832,7 +830,7 @@ FCIMPL5(FC_BOOL_RET, COMDelegate::BindToMethodName,
//

// get the name in UTF8 format
SString wszName(SString::Literal, gc.methodName->GetBuffer());
SString wszName(SString::Literal, pwzMethodName);
StackScratchBuffer utf8Name;
LPCUTF8 szNameStr = wszName.GetUTF8(utf8Name);

Expand Down Expand Up @@ -900,19 +898,21 @@ FCIMPL5(FC_BOOL_RET, COMDelegate::BindToMethodName,
pCurMethod,
methodType.GetMethodTable(),
fIsOpenDelegate);

pMatchingMethod = pCurMethod;

goto done;
}
}
}
done:
;
HELPER_METHOD_FRAME_END();

FC_RETURN_BOOL(pMatchingMethod != NULL);
GCPROTECT_END();

END_QCALL;

return pMatchingMethod != NULL;
}
FCIMPLEND


FCIMPL5(FC_BOOL_RET, COMDelegate::BindToMethodInfo, Object* refThisUNSAFE, Object* targetUNSAFE, ReflectMethodObject *pMethodUNSAFE, ReflectClassBaseObject *pMethodTypeUNSAFE, int flags)
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/src/vm/comdelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class COMDelegate
static FCDECL3(PCODE, AdjustTarget, Object* refThis, Object* target, PCODE method);
static FCDECL2(PCODE, GetCallStub, Object* refThis, PCODE method);

static FCDECL5(FC_BOOL_RET, BindToMethodName, Object* refThisUNSAFE, Object* targetUNSAFE, ReflectClassBaseObject *pMethodTypeUNSAFE, StringObject* methodNameUNSAFE, int flags);
static BOOL QCALLTYPE BindToMethodName(QCall::ObjectHandleOnStack delegate, QCall::ObjectHandleOnStack target, QCall::TypeHandle methodType, PCWSTR pwzMethodName, int flags);

static FCDECL5(FC_BOOL_RET, BindToMethodInfo, Object* refThisUNSAFE, Object* targetUNSAFE, ReflectMethodObject *method, ReflectClassBaseObject *pMethodTypeUNSAFE, int flags);

Expand Down
73 changes: 30 additions & 43 deletions src/coreclr/src/vm/debugdebugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,35 +158,30 @@ FCIMPL0(void, DebugDebugger::Break)
}
FCIMPLEND

FCIMPL0(FC_BOOL_RET, DebugDebugger::Launch)
BOOL QCALLTYPE DebugDebugger::Launch()
{
FCALL_CONTRACT;
QCALL_CONTRACT;

BOOL retVal = FALSE;

BEGIN_QCALL;

#ifdef DEBUGGING_SUPPORTED
if (CORDebuggerAttached())
{
FC_RETURN_BOOL(TRUE);
retVal = TRUE;
}
else if (g_pDebugInterface != NULL)
{
HRESULT hr = S_OK;

HELPER_METHOD_FRAME_BEGIN_RET_0();

hr = g_pDebugInterface->LaunchDebuggerForUser(GetThread(), NULL, TRUE, TRUE);

HELPER_METHOD_FRAME_END();

if (SUCCEEDED (hr))
{
FC_RETURN_BOOL(TRUE);
}
HRESULT hr = g_pDebugInterface->LaunchDebuggerForUser(GetThread(), NULL, TRUE, TRUE);
retVal = SUCCEEDED(hr);
}
#endif // DEBUGGING_SUPPORTED

FC_RETURN_BOOL(FALSE);
END_QCALL;

return retVal;
}
FCIMPLEND


FCIMPL0(FC_BOOL_RET, DebugDebugger::IsDebuggerAttached)
Expand Down Expand Up @@ -229,42 +224,35 @@ FCIMPLEND
// appending a newline to anything.
// It will also call OutputDebugString() which will send a native debug event. The message
// string there will be a composite of the two managed string parameters and may include a newline.
FCIMPL3(void, DebugDebugger::Log,
INT32 Level,
StringObject* strModuleUNSAFE,
StringObject* strMessageUNSAFE
)
void QCALLTYPE DebugDebugger::Log(INT32 Level, PCWSTR pwzModule, PCWSTR pwzMessage)
{
CONTRACTL
{
FCALL_CHECK;
PRECONDITION(CheckPointer(strModuleUNSAFE, NULL_OK));
PRECONDITION(CheckPointer(strMessageUNSAFE, NULL_OK));
QCALL_CHECK;
PRECONDITION(CheckPointer(pwzModule, NULL_OK));
PRECONDITION(CheckPointer(pwzMessage, NULL_OK));
}
CONTRACTL_END;

STRINGREF strModule = (STRINGREF)ObjectToOBJECTREF(strModuleUNSAFE);
STRINGREF strMessage = (STRINGREF)ObjectToOBJECTREF(strMessageUNSAFE);

HELPER_METHOD_FRAME_BEGIN_2(strModule, strMessage);
BEGIN_QCALL;

// OutputDebugString will log to native/interop debugger.
if (strModule != NULL)
if (pwzModule != NULL)
{
WszOutputDebugString(strModule->GetBuffer());
WszOutputDebugString(pwzModule);
WszOutputDebugString(W(" : "));
}

if (strMessage != NULL)
if (pwzMessage != NULL)
{
WszOutputDebugString(strMessage->GetBuffer());
WszOutputDebugString(pwzMessage);
}

// If we're not logging a module prefix, then don't log the newline either.
// Thus if somebody is just logging messages, there won't be any extra newlines in there.
// If somebody is also logging category / module information, then this call to OutputDebugString is
// already prepending that to the message, so we append a newline for readability.
if (strModule != NULL)
if (pwzModule != NULL)
{
WszOutputDebugString(W("\n"));
}
Expand All @@ -283,21 +271,21 @@ FCIMPL3(void, DebugDebugger::Log,
// Strings may contain embedded nulls, but we need to handle null-terminated
// strings, so use truncate now.
StackSString switchName;
if( strModule != NULL )
if(pwzModule != NULL)
{
// truncate if necessary
COUNT_T iLen = (COUNT_T) wcslen(strModule->GetBuffer());
COUNT_T iLen = (COUNT_T) wcslen(pwzModule);
if (iLen > MAX_LOG_SWITCH_NAME_LEN)
{
iLen = MAX_LOG_SWITCH_NAME_LEN;
}
switchName.Set(strModule->GetBuffer(), iLen);
switchName.Set(pwzModule, iLen);
}

SString message;
if( strMessage != NULL )
if(pwzMessage != NULL)
{
message.Set(strMessage->GetBuffer(), (COUNT_T) wcslen(strMessage->GetBuffer()));
message.Set(pwzMessage, (COUNT_T) wcslen(pwzMessage));
}

g_pDebugInterface->SendLogMessage (Level, &switchName, &message);
Expand All @@ -306,9 +294,8 @@ FCIMPL3(void, DebugDebugger::Log,

#endif // DEBUGGING_SUPPORTED

HELPER_METHOD_FRAME_END();
END_QCALL;
}
FCIMPLEND


FCIMPL0(FC_BOOL_RET, DebugDebugger::IsLogging)
Expand Down Expand Up @@ -1174,14 +1161,14 @@ void DebugStackTrace::DebugStackTraceElement::InitPass2()

_ASSERTE(!ThreadStore::HoldingThreadStore());

bool bRes = false;
bool bRes = false;

#ifdef DEBUGGING_SUPPORTED
// Calculate the IL offset using the debugging services
if ((this->ip != NULL) && g_pDebugInterface)
{
// To get the source line number of the actual code that threw an exception, the dwOffset needs to be
// adjusted in certain cases when calculating the IL offset.
// adjusted in certain cases when calculating the IL offset.
//
// The dwOffset of the stack frame points to either:
//
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/src/vm/debugdebugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ class DebugDebugger
{
public:
static FCDECL0(void, Break);
static FCDECL0(FC_BOOL_RET, Launch);
static BOOL QCALLTYPE Launch();
static FCDECL0(FC_BOOL_RET, IsDebuggerAttached);
static FCDECL3(void, Log, INT32 Level, StringObject* strModule, StringObject* strMessage);
static void QCALLTYPE Log(INT32 Level, PCWSTR pwzModule, PCWSTR pwzMessage);

// receives a custom notification object from the target and sends it to the RS via
// code:Debugger::SendCustomDebuggerNotification
Expand Down
8 changes: 4 additions & 4 deletions src/coreclr/src/vm/ecalllist.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,9 @@ FCFuncEnd()

FCFuncStart(gDiagnosticsDebugger)
FCFuncElement("BreakInternal", DebugDebugger::Break)
FCFuncElement("LaunchInternal", DebugDebugger::Launch)
QCFuncElement("LaunchInternal", DebugDebugger::Launch)
FCFuncElement("get_IsAttached", DebugDebugger::IsDebuggerAttached)
FCFuncElement("Log", DebugDebugger::Log)
QCFuncElement("LogInternal", DebugDebugger::Log)
FCFuncElement("IsLogging", DebugDebugger::IsLogging)
FCFuncElement("CustomNotification", DebugDebugger::CustomNotification)
FCFuncEnd()
Expand Down Expand Up @@ -510,7 +510,7 @@ FCFuncStart(gAssemblyBuilderFuncs)
FCFuncEnd()

FCFuncStart(gDelegateFuncs)
FCFuncElement("BindToMethodName", COMDelegate::BindToMethodName)
QCFuncElement("BindToMethodName", COMDelegate::BindToMethodName)
FCFuncElement("BindToMethodInfo", COMDelegate::BindToMethodInfo)
FCFuncElement("GetMulticastInvoke", COMDelegate::GetMulticastInvoke)
FCFuncElement("GetInvokeMethod", COMDelegate::GetInvokeMethod)
Expand Down Expand Up @@ -971,7 +971,7 @@ FCFuncStart(gStubHelperFuncs)
FCFuncElement("MarshalToUnmanagedVaListInternal", StubHelpers::MarshalToUnmanagedVaListInternal)
FCFuncElement("MarshalToManagedVaListInternal", StubHelpers::MarshalToManagedVaListInternal)
FCFuncElement("CalcVaListSize", StubHelpers::CalcVaListSize)
FCFuncElement("ValidateObject", StubHelpers::ValidateObject)
QCFuncElement("ValidateObject", StubHelpers::ValidateObject)
FCFuncElement("ValidateByref", StubHelpers::ValidateByref)
FCFuncElement("LogPinnedArgument", StubHelpers::LogPinnedArgument)
FCIntrinsic("GetStubContext", StubHelpers::GetStubContext, CORINFO_INTRINSIC_StubHelpers_GetStubContext)
Expand Down
Loading