diff options
author | Jan Kotas <jkotas@microsoft.com> | 2018-05-11 18:35:24 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-11 18:35:24 +0300 |
commit | e19bace28a18a0d39a451bb0f0dbd325551508e1 (patch) | |
tree | 4a59bcf0cd83e8c412c71851a6659304bdd1e638 /src/System.Private.Reflection.Execution | |
parent | 8f12ec10abe7ec1eeee33955589a78fde94308d0 (diff) |
Fix diagnostic stacktrace for shared generic methods (#5796)
Diagnostic stacktraces were missing symbols for shared generic methods. TryGetMethodForOriginalLdFtnResult is expecting fat pointer for these, and failed to find the method when used for method entrypoint.
The fix is to create a clone of TryGetMethodForOriginalLdFtnResult that does not require instantiation argument and does not return exact instantiation.
Diffstat (limited to 'src/System.Private.Reflection.Execution')
3 files changed, 115 insertions, 57 deletions
diff --git a/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs b/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs index ad2675351..284e2c25b 100644 --- a/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs +++ b/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs @@ -907,25 +907,74 @@ namespace Internal.Reflection.Execution { GetFunctionPointerAndInstantiationArgumentForOriginalLdFtnResult(originalLdFtnResult, out IntPtr canonOriginalLdFtnResult, out IntPtr instantiationArgument); - // Search TemplateMethodMap - if ((instantiationArgument != IntPtr.Zero) && TryGetMethodForOriginalLdFtnResult_GenericMethodWithInstantiationArgument(instantiationArgument, ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles)) + if (instantiationArgument != IntPtr.Zero) { - return true; + // Search TemplateMethodMap + if (TryGetMethodForOriginalLdFtnResult_GenericMethodWithInstantiationArgument(instantiationArgument, ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles)) + return true; + } + else + { + // Search ExactInstantiationsMap + foreach (KeyValuePair<NativeFormatModuleInfo, FunctionPointersToOffsets> perModuleLookup in GetLdFtnReverseLookups_ExactInstantations()) + { + int startIndex; + int endIndex; + + if (perModuleLookup.Value.TryGetOffsetsRange(canonOriginalLdFtnResult, out startIndex, out endIndex)) + { + for (int curIndex = startIndex; curIndex <= endIndex; curIndex++) + { + uint parserOffset = perModuleLookup.Value.Data[curIndex].Offset; + if (TryGetMethodForOriginalLdFtnResult_ExactInstantiation_Inner(perModuleLookup.Key, forStartAddress: false, canonOriginalLdFtnResult, parserOffset, + ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles)) + return true; + } + } + } } + // Search InvokeMap + foreach (KeyValuePair<NativeFormatModuleInfo, FunctionPointersToOffsets> perModuleLookup in GetLdFtnReverseLookups_InvokeMap()) + { + int startIndex; + int endIndex; + + if (perModuleLookup.Value.TryGetOffsetsRange(canonOriginalLdFtnResult, out startIndex, out endIndex)) + { + for (int curIndex = startIndex; curIndex <= endIndex; curIndex++) + { + uint parserOffset = perModuleLookup.Value.Data[curIndex].Offset; + if (TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(perModuleLookup.Key, forStartAddress: false, canonOriginalLdFtnResult, instantiationArgument, parserOffset, ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles)) + return true; + } + } + } + + methodHandle = default(QMethodDefinition); + genericMethodTypeArgumentHandles = null; + return false; + } + + internal bool TryGetMethodForStartAddress(IntPtr methodStartAddress, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle) + { // Search ExactInstantiationsMap foreach (KeyValuePair<NativeFormatModuleInfo, FunctionPointersToOffsets> perModuleLookup in GetLdFtnReverseLookups_ExactInstantations()) { int startIndex; int endIndex; - if (perModuleLookup.Value.TryGetOffsetsRange(canonOriginalLdFtnResult, out startIndex, out endIndex)) + if (perModuleLookup.Value.TryGetOffsetsRange(methodStartAddress, out startIndex, out endIndex)) { for (int curIndex = startIndex; curIndex <= endIndex; curIndex++) { uint parserOffset = perModuleLookup.Value.Data[curIndex].Offset; - if (TryGetMethodForOriginalLdFtnResult_ExactInstantiation_Inner(perModuleLookup.Key, canonOriginalLdFtnResult, instantiationArgument, parserOffset, ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles)) + if (TryGetMethodForOriginalLdFtnResult_ExactInstantiation_Inner(perModuleLookup.Key, forStartAddress: true, methodStartAddress, parserOffset, ref declaringTypeHandle, out methodHandle, out _)) + { + if (RuntimeAugments.IsGenericType(declaringTypeHandle)) + declaringTypeHandle = RuntimeAugments.GetGenericDefinition(declaringTypeHandle); return true; + } } } } @@ -936,19 +985,22 @@ namespace Internal.Reflection.Execution int startIndex; int endIndex; - if (perModuleLookup.Value.TryGetOffsetsRange(canonOriginalLdFtnResult, out startIndex, out endIndex)) + if (perModuleLookup.Value.TryGetOffsetsRange(methodStartAddress, out startIndex, out endIndex)) { for (int curIndex = startIndex; curIndex <= endIndex; curIndex++) { uint parserOffset = perModuleLookup.Value.Data[curIndex].Offset; - if (TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(perModuleLookup.Key, canonOriginalLdFtnResult, instantiationArgument, parserOffset, ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles)) + if (TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(perModuleLookup.Key, forStartAddress: true, methodStartAddress, IntPtr.Zero, parserOffset, ref declaringTypeHandle, out methodHandle, out _)) + { + if (RuntimeAugments.IsGenericType(declaringTypeHandle)) + declaringTypeHandle = RuntimeAugments.GetGenericDefinition(declaringTypeHandle); return true; + } } } } methodHandle = default(QMethodDefinition); - genericMethodTypeArgumentHandles = null; return false; } @@ -1013,7 +1065,7 @@ namespace Internal.Reflection.Execution return functionPointerToOffsetInInvokeMap; } - private unsafe bool TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(NativeFormatModuleInfo mappingTableModule, IntPtr canonOriginalLdFtnResult, IntPtr instantiationArgument, uint parserOffset, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles) + private unsafe bool TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(NativeFormatModuleInfo mappingTableModule, bool forStartAddress, IntPtr canonOriginalLdFtnResult, IntPtr instantiationArgument, uint parserOffset, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles) { methodHandle = default(QMethodDefinition); genericMethodTypeArgumentHandles = null; @@ -1035,7 +1087,7 @@ namespace Internal.Reflection.Execution // If the passed in method was a fat function pointer, but the entry in the mapping table doesn't need // an instantiation argument (or the other way around), trivially reject it. - if ((instantiationArgument == IntPtr.Zero) != ((entryFlags & InvokeTableFlags.RequiresInstArg) == 0)) + if (!forStartAddress && ((instantiationArgument == IntPtr.Zero) != ((entryFlags & InvokeTableFlags.RequiresInstArg) == 0))) return false; Debug.Assert((entryFlags & InvokeTableFlags.HasEntrypoint) != 0); @@ -1046,39 +1098,46 @@ namespace Internal.Reflection.Execution IntPtr entryMethodEntrypoint = externalReferences.GetFunctionPointerFromIndex(entryParser.GetUnsigned()); if ((entryFlags & InvokeTableFlags.NeedsParameterInterpretation) == 0) - entryParser.GetUnsigned(); // skip dynamic invoke cookie + entryParser.SkipInteger(); // skip dynamic invoke cookie + if (forStartAddress) + { + declaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryDeclaringTypeRaw); + } + else + { #if DEBUG - IntPtr targetAddress; - Debug.Assert(entryMethodEntrypoint == canonOriginalLdFtnResult || - RuntimeAugments.GetCodeTarget(entryMethodEntrypoint) == canonOriginalLdFtnResult || - TypeLoaderEnvironment.TryGetTargetOfUnboxingAndInstantiatingStub(entryMethodEntrypoint, out targetAddress) && - targetAddress == canonOriginalLdFtnResult); + IntPtr targetAddress; + Debug.Assert(entryMethodEntrypoint == canonOriginalLdFtnResult || + RuntimeAugments.GetCodeTarget(entryMethodEntrypoint) == canonOriginalLdFtnResult || + TypeLoaderEnvironment.TryGetTargetOfUnboxingAndInstantiatingStub(entryMethodEntrypoint, out targetAddress) && + targetAddress == canonOriginalLdFtnResult); #endif - if ((entryFlags & InvokeTableFlags.RequiresInstArg) == 0 && declaringTypeHandle.IsNull()) - declaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryDeclaringTypeRaw); + if ((entryFlags & InvokeTableFlags.RequiresInstArg) == 0 && declaringTypeHandle.IsNull()) + declaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryDeclaringTypeRaw); - if ((entryFlags & InvokeTableFlags.IsGenericMethod) != 0) - { - if ((entryFlags & InvokeTableFlags.RequiresInstArg) != 0) + if ((entryFlags & InvokeTableFlags.IsGenericMethod) != 0) { - MethodNameAndSignature dummyNameAndSignature; - bool success = TypeLoaderEnvironment.Instance.TryGetGenericMethodComponents(instantiationArgument, out declaringTypeHandle, out dummyNameAndSignature, out genericMethodTypeArgumentHandles); - Debug.Assert(success); + if ((entryFlags & InvokeTableFlags.RequiresInstArg) != 0) + { + MethodNameAndSignature dummyNameAndSignature; + bool success = TypeLoaderEnvironment.Instance.TryGetGenericMethodComponents(instantiationArgument, out declaringTypeHandle, out dummyNameAndSignature, out genericMethodTypeArgumentHandles); + Debug.Assert(success); + } + else + genericMethodTypeArgumentHandles = GetTypeSequence(ref externalReferences, ref entryParser); } else - genericMethodTypeArgumentHandles = GetTypeSequence(ref externalReferences, ref entryParser); - } - else - { - genericMethodTypeArgumentHandles = null; - if ((entryFlags & InvokeTableFlags.RequiresInstArg) != 0) - declaringTypeHandle = RuntimeAugments.CreateRuntimeTypeHandle(instantiationArgument); - } + { + genericMethodTypeArgumentHandles = null; + if ((entryFlags & InvokeTableFlags.RequiresInstArg) != 0) + declaringTypeHandle = RuntimeAugments.CreateRuntimeTypeHandle(instantiationArgument); + } - RuntimeTypeHandle entryType = externalReferences.GetRuntimeTypeHandleFromIndex(entryDeclaringTypeRaw); - declaringTypeHandle = GetExactDeclaringType(entryType, declaringTypeHandle); + RuntimeTypeHandle entryType = externalReferences.GetRuntimeTypeHandleFromIndex(entryDeclaringTypeRaw); + declaringTypeHandle = GetExactDeclaringType(entryType, declaringTypeHandle); + } if ((entryFlags & InvokeTableFlags.HasMetadataHandle) != 0) { @@ -1139,17 +1198,17 @@ namespace Internal.Reflection.Execution uint parserOffset = entryParser.Offset; // Declaring Handle - entryParser.GetUnsigned(); + entryParser.SkipInteger(); // NameAndSig - entryParser.GetUnsigned(); + entryParser.SkipInteger(); // generic method arity int parsedArity = (int)entryParser.GetSequenceCount(); for (int i = 0; i < parsedArity; i++) { - entryParser.GetUnsigned(); + entryParser.SkipInteger(); } IntPtr functionPointer = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned()); @@ -1162,14 +1221,11 @@ namespace Internal.Reflection.Execution return functionPointerToOffsetInInvokeMap; } - private unsafe bool TryGetMethodForOriginalLdFtnResult_ExactInstantiation_Inner(NativeFormatModuleInfo mappingTableModule, IntPtr canonOriginalLdFtnResult, IntPtr instantiationArgument, uint parserOffset, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles) + private unsafe bool TryGetMethodForOriginalLdFtnResult_ExactInstantiation_Inner(NativeFormatModuleInfo mappingTableModule, bool forStartAddress, IntPtr canonOriginalLdFtnResult, uint parserOffset, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles) { methodHandle = default(QMethodDefinition); genericMethodTypeArgumentHandles = null; - if (instantiationArgument != IntPtr.Zero) - return false; - NativeReader invokeMapReader; if (!TryGetNativeReaderForBlob(mappingTableModule, ReflectionMapBlob.ExactMethodInstantiationsHashtable, out invokeMapReader)) { @@ -1191,11 +1247,22 @@ namespace Internal.Reflection.Execution return false; int parsedArity = (int)entryParser.GetSequenceCount(); - genericMethodTypeArgumentHandles = new RuntimeTypeHandle[parsedArity]; - for (int i = 0; i < parsedArity; i++) + if (forStartAddress) { - genericMethodTypeArgumentHandles[i] = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); + for (int i = 0; i < parsedArity; i++) + { + entryParser.SkipInteger(); + } + } + else + { + genericMethodTypeArgumentHandles = new RuntimeTypeHandle[parsedArity]; + + for (int i = 0; i < parsedArity; i++) + { + genericMethodTypeArgumentHandles[i] = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); + } } IntPtr functionPointer = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned()); diff --git a/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecution.cs b/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecution.cs index d2135fd08..f0261574f 100644 --- a/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecution.cs +++ b/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecution.cs @@ -98,16 +98,13 @@ namespace Internal.Reflection.Execution methodHandle = default(MethodHandle); RuntimeTypeHandle declaringTypeHandle = default(RuntimeTypeHandle); - if (!ExecutionEnvironment.TryGetMethodForOriginalLdFtnResult(methodStartAddress, - ref declaringTypeHandle, out QMethodDefinition qMethodDefinition, out _)) + if (!ExecutionEnvironment.TryGetMethodForStartAddress(methodStartAddress, + ref declaringTypeHandle, out QMethodDefinition qMethodDefinition)) return false; if (!qMethodDefinition.IsNativeFormatMetadataBased) return false; - if (RuntimeAugments.IsGenericType(declaringTypeHandle)) - declaringTypeHandle = RuntimeAugments.GetGenericDefinition(declaringTypeHandle); - if (!ExecutionEnvironment.TryGetMetadataForNamedType(declaringTypeHandle, out QTypeDefinition qTypeDefinition)) return false; diff --git a/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecutionDomainCallbacksImplementation.cs b/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecutionDomainCallbacksImplementation.cs index 1a004f50d..b6ba92e2b 100644 --- a/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecutionDomainCallbacksImplementation.cs +++ b/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecutionDomainCallbacksImplementation.cs @@ -104,18 +104,12 @@ namespace Internal.Reflection.Execution { RuntimeTypeHandle declaringTypeHandle = default(RuntimeTypeHandle); QMethodDefinition methodHandle; - RuntimeTypeHandle[] genericMethodTypeArgumentHandles; - if (!ReflectionExecution.ExecutionEnvironment.TryGetMethodForOriginalLdFtnResult(methodStartAddress, - ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles)) + if (!ReflectionExecution.ExecutionEnvironment.TryGetMethodForStartAddress(methodStartAddress, + ref declaringTypeHandle, out methodHandle)) { return null; } - if (RuntimeAugments.IsGenericType(declaringTypeHandle)) - { - declaringTypeHandle = RuntimeAugments.GetGenericDefinition(declaringTypeHandle); - } - // We don't use the type argument handles as we want the uninstantiated method info return ReflectionCoreExecution.ExecutionDomain.GetMethod(declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles: null); } |