Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
11 changes: 11 additions & 0 deletions docs/design/datacontracts/CodeVersions.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ public virtual TargetPointer GetGCStressCodeCopy(NativeCodeVersionHandle codeVer

// Gets the IL address given a code version
public virtual TargetPointer GetIL(ILCodeVersionHandle ilCodeVersionHandle);

// Determines whether an IL code version has default IL
public virtual bool HasDefaultIL(ILCodeVersionHandle ilCodeVersionHandle);
```
### Extension Methods
```csharp
Expand Down Expand Up @@ -379,4 +382,12 @@ TargetPointer ICodeVersions.GetIL(ILCodeVersionHandle ilCodeVersionHandle, Targe

return ilAddress;
}
```

### Do we have default IL
```csharp
bool ICodeVersions.HasDefaultIL(ILCodeVersionHandle ilCodeVersionHandle)
{
return ilCodeVersionHandle.IsExplicit ? AsNode(ilCodeVersionHandle).ILAddress == TargetPointer.Null : true;
}
```
30 changes: 17 additions & 13 deletions docs/design/datacontracts/Loader.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ TargetPointer GetHighFrequencyHeap(TargetPointer loaderAllocatorPointer);
TargetPointer GetLowFrequencyHeap(TargetPointer loaderAllocatorPointer);
TargetPointer GetStubHeap(TargetPointer loaderAllocatorPointer);
TargetPointer GetObjectHandle(TargetPointer loaderAllocatorPointer);
TargetPointer GetILHeader(ModuleHandle handle, uint token);
TargetPointer GetDynamicIL(ModuleHandle handle, uint token);
```

## Version 1
Expand Down Expand Up @@ -650,10 +652,20 @@ private sealed class DynamicILBlobTraits : ITraits<uint, DynamicILBlobEntry>

TargetPointer GetILHeader(ModuleHandle handle, uint token)
{
// we need module
ILoader loader = this;
TargetPointer peAssembly = loader.GetPEAssembly(handle);
TargetPointer headerPtr = GetDynamicIL(handle, token);
if (GetDynamicIL(handle, token) == TargetPointer.Null)
{
TargetPointer peAssembly = loader.GetPEAssembly(handle);
IEcmaMetadata ecmaMetadataContract = _target.Contracts.EcmaMetadata;
MetadataReader mdReader = ecmaMetadataContract.GetMetadata(handle)!;
MethodDefinition methodDef = mdReader.GetMethodDefinition(MetadataTokens.MethodDefinitionHandle(token));
int rva = methodDef.RelativeVirtualAddress;
headerPtr = loader.GetILAddr(peAssembly, rva);
}
return headerPtr;
}

TargetPointer GetDynamicIL(ModuleHandle handle, uint token)
{
TargetPointer dynamicBlobTablePtr = target.ReadPointer(handle.Address + /* Module::DynamicILBlobTable offset */);
Contracts.IThread shashContract = target.Contracts.SHash;
DynamicILBlobTraits traits = new();
Expand All @@ -664,15 +676,7 @@ TargetPointer GetILHeader(ModuleHandle handle, uint token)
*/
SHash<uint, Data.DynamicILBlobEntry> shash = shashContract.CreateSHash<uint, Data.DynamicILBlobEntry>(target, dynamicBlobTablePtr, DataType.DynamicILBlobTable, traits)
Data.DynamicILBlobEntry blobEntry = shashContract.LookupSHash(shash, token);
if (blobEntry.EntryIL == TargetPointer.Null)
{
IEcmaMetadata ecmaMetadataContract = _target.Contracts.EcmaMetadata;
MetadataReader mdReader = ecmaMetadataContract.GetMetadata(handle)!;
MethodDefinition methodDef = mdReader.GetMethodDefinition(MetadataTokens.MethodDefinitionHandle(token));
int rva = methodDef.RelativeVirtualAddress;
headerPtr = loader.GetILAddr(peAssembly, rva);
}
return headerPtr;
return /* blob entry IL address */
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public interface ICodeVersions : IContract
public virtual bool CodeVersionManagerSupportsMethod(TargetPointer methodDesc) => throw new NotImplementedException();

public virtual TargetPointer GetIL(ILCodeVersionHandle ilCodeVersionHandle) => throw new NotImplementedException();
public virtual bool HasDefaultIL(ILCodeVersionHandle ilCodeVersionHandle) => throw new NotImplementedException();
}

public readonly struct ILCodeVersionHandle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ public interface ILoader : IContract
TargetPointer GetStubHeap(TargetPointer loaderAllocatorPointer) => throw new NotImplementedException();
TargetPointer GetILHeader(ModuleHandle handle, uint token) => throw new NotImplementedException();
TargetPointer GetObjectHandle(TargetPointer loaderAllocatorPointer) => throw new NotImplementedException();
TargetPointer GetDynamicIL(ModuleHandle handle, uint token) => throw new NotImplementedException();
}

public readonly struct Loader : ILoader
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,4 +408,9 @@ TargetPointer ICodeVersions.GetIL(ILCodeVersionHandle ilCodeVersionHandle)

return ilAddress;
}

bool ICodeVersions.HasDefaultIL(ILCodeVersionHandle iLCodeVersionHandle)
{
return iLCodeVersionHandle.IsExplicit ? AsNode(iLCodeVersionHandle).ILAddress == TargetPointer.Null : true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -540,10 +540,10 @@ TargetPointer ILoader.GetILHeader(ModuleHandle handle, uint token)
{
// we need module
ILoader loader = this;
TargetPointer peAssembly = loader.GetPEAssembly(handle);
TargetPointer headerPtr = GetDynamicIL(handle, token);
TargetPointer headerPtr = loader.GetDynamicIL(handle, token);
if (headerPtr == TargetPointer.Null)
{
TargetPointer peAssembly = loader.GetPEAssembly(handle);
int rva = GetRVAFromMetadata(handle, (int)token);
headerPtr = loader.GetILAddr(peAssembly, rva);
}
Expand Down Expand Up @@ -574,7 +574,7 @@ public DynamicILBlobTable(Target target, TargetPointer address)
public ISHash<uint, DynamicILBlobEntry> HashTable { get; init; }
}

private TargetPointer GetDynamicIL(ModuleHandle handle, uint token)
TargetPointer ILoader.GetDynamicIL(ModuleHandle handle, uint token)
{
Data.Module module = _target.ProcessedData.GetOrAdd<Data.Module>(handle.Address);
if (module.DynamicILBlobTable == TargetPointer.Null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,20 @@ public enum Flags : uint
public ClrDataAddress ilCodeVersionNodePtr;
}

internal struct DacpProfilerILData
{
public enum ModificationType
{
Unmodified,
ILModified,
ReJITModified,
};

public ModificationType type;
public ClrDataAddress il;
public uint rejitID;
};

[GeneratedComInterface]
[Guid("c1020dde-fe98-4536-a53b-f35a74c327eb")]
internal unsafe partial interface ISOSDacInterface7
Expand All @@ -681,7 +695,7 @@ internal unsafe partial interface ISOSDacInterface7
[PreserveSig]
int GetReJITInformation(ClrDataAddress methodDesc, int rejitId, DacpReJitData2* pRejitData);
[PreserveSig]
int GetProfilerModifiedILInformation(ClrDataAddress methodDesc, /*struct DacpProfilerILData*/ void* pILData);
int GetProfilerModifiedILInformation(ClrDataAddress methodDesc, DacpProfilerILData* pILData);
[PreserveSig]
int GetMethodsWithProfilerModifiedIL(ClrDataAddress mod, ClrDataAddress* methodDescs, int cMethodDescs, int* pcMethodDescs);
};
Expand Down
129 changes: 126 additions & 3 deletions src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3248,10 +3248,133 @@ int ISOSDacInterface7.GetReJITInformation(ClrDataAddress methodDesc, int rejitId
#endif
return hr;
}
int ISOSDacInterface7.GetProfilerModifiedILInformation(ClrDataAddress methodDesc, /*struct DacpProfilerILData*/ void* pILData)
=> _legacyImpl7 is not null ? _legacyImpl7.GetProfilerModifiedILInformation(methodDesc, pILData) : HResults.E_NOTIMPL;
int ISOSDacInterface7.GetProfilerModifiedILInformation(ClrDataAddress methodDesc, DacpProfilerILData* pILData)
{
int hr = HResults.S_OK;
try
{
if (methodDesc == 0 || pILData == null)
throw new ArgumentException();
pILData->type = DacpProfilerILData.ModificationType.Unmodified;
pILData->rejitID = 0;
pILData->il = 0;

Contracts.IReJIT rejitContract = _target.Contracts.ReJIT;
Contracts.ICodeVersions codeVersionsContract = _target.Contracts.CodeVersions;
Contracts.ILoader loaderContract = _target.Contracts.Loader;
Contracts.IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem;
TargetPointer methodDescPtr = methodDesc.ToTargetPointer(_target);
// getting the module handle and the token from the method desc
MethodDescHandle mdh = rtsContract.GetMethodDescHandle(methodDescPtr);
TargetPointer mt = rtsContract.GetMethodTable(mdh);
TypeHandle typeHandle = rtsContract.GetTypeHandle(mt);
TargetPointer modulePtr = rtsContract.GetModule(typeHandle);
uint token = rtsContract.GetMethodToken(mdh);
Contracts.ModuleHandle moduleHandle = loaderContract.GetModuleHandleFromModulePtr(modulePtr);

Contracts.ILCodeVersionHandle activeILCodeVersion = codeVersionsContract.GetActiveILCodeVersion(methodDescPtr);

// rejit in progress or rejit applied?
if (rejitContract.GetRejitState(activeILCodeVersion) != RejitState.Active || !codeVersionsContract.HasDefaultIL(activeILCodeVersion))
{
pILData->type = DacpProfilerILData.ModificationType.ReJITModified;
pILData->rejitID = (uint)rejitContract.GetRejitId(activeILCodeVersion).Value;
}

TargetPointer il = loaderContract.GetDynamicIL(moduleHandle, token);
if (il != 0)
{
pILData->type = DacpProfilerILData.ModificationType.ILModified;
pILData->il = il.ToClrDataAddress(_target);
}
}
catch (System.Exception ex)
{
hr = ex.HResult;
}
#if DEBUG
if (_legacyImpl7 is not null)
{
DacpProfilerILData ilDataLocal;
int hrLocal = _legacyImpl7.GetProfilerModifiedILInformation(methodDesc, &ilDataLocal);
Debug.Assert(hrLocal == hr, $"cDAC: {hr:x}, DAC: {hrLocal:x}");
if (hr == HResults.S_OK)
{
Debug.Assert(pILData->type == ilDataLocal.type, $"cDAC: {pILData->type}, DAC: {ilDataLocal.type}");
Debug.Assert(pILData->rejitID == ilDataLocal.rejitID, $"cDAC: {pILData->rejitID}, DAC: {ilDataLocal.rejitID}");
Debug.Assert(pILData->il == ilDataLocal.il, $"cDAC: {pILData->il:x}, DAC: {ilDataLocal.il:x}");
}
}
#endif
return hr;
}
int ISOSDacInterface7.GetMethodsWithProfilerModifiedIL(ClrDataAddress mod, ClrDataAddress* methodDescs, int cMethodDescs, int* pcMethodDescs)
=> _legacyImpl7 is not null ? _legacyImpl7.GetMethodsWithProfilerModifiedIL(mod, methodDescs, cMethodDescs, pcMethodDescs) : HResults.E_NOTIMPL;
{
int hr = HResults.S_OK;
try
{
if (mod == 0 || methodDescs == null || pcMethodDescs == null || cMethodDescs == 0)
throw new ArgumentException();
*pcMethodDescs = 0;
Contracts.ILoader loaderContract = _target.Contracts.Loader;
Contracts.IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem;
Contracts.IReJIT rejitContract = _target.Contracts.ReJIT;
Contracts.ICodeVersions codeVersionsContract = _target.Contracts.CodeVersions;

TargetPointer modulePtr = mod.ToTargetPointer(_target);
Contracts.ModuleHandle moduleHandle = loaderContract.GetModuleHandleFromModulePtr(modulePtr);
// iterate through typedef to method table map
foreach ((TargetPointer ptr, _) in loaderContract.EnumerateModuleLookupMap(loaderContract.GetLookupTables(moduleHandle).TypeDefToMethodTable))
{
if (*pcMethodDescs >= cMethodDescs)
break;
TypeHandle typeHandle = rtsContract.GetTypeHandle(ptr);
foreach (TargetPointer md in rtsContract.GetIntroducedMethodDescs(typeHandle))
{
MethodDescHandle mdh = rtsContract.GetMethodDescHandle(md);
uint token = rtsContract.GetMethodToken(mdh);
Contracts.ILCodeVersionHandle activeILCodeVersion = codeVersionsContract.GetActiveILCodeVersion(md);
// first condition: is method in process of being rejitted?
// second condition: has rejit been applied or null default IL been otherwise used for profiler modification (see src/coreclr/vm/codeversion.cpp comment)?
// third condition: has profiler modified IL through ICorProfilerInfo::SetILFunctionBody?
if (rejitContract.GetRejitState(activeILCodeVersion) != RejitState.Active ||
!codeVersionsContract.HasDefaultIL(activeILCodeVersion) ||
loaderContract.GetDynamicIL(moduleHandle, token) != 0)
{
methodDescs[*pcMethodDescs] = md.ToClrDataAddress(_target);
(*pcMethodDescs)++;
}
if (*pcMethodDescs >= cMethodDescs)
break;
}
}
}
catch (System.Exception ex)
{
hr = ex.HResult;
}
#if DEBUG
if (_legacyImpl7 is not null)
{
ClrDataAddress[] methodDescsLocal = new ClrDataAddress[cMethodDescs];
int pcMethodDescsLocal;
fixed (ClrDataAddress* ptr = methodDescsLocal)
{
int hrLocal = _legacyImpl7.GetMethodsWithProfilerModifiedIL(mod, ptr, cMethodDescs, &pcMethodDescsLocal);
Debug.Assert(hrLocal == hr, $"cDAC: {hr:x}, DAC: {hrLocal:x}");
if (hr == HResults.S_OK)
{
Debug.Assert(*pcMethodDescs == pcMethodDescsLocal, $"cDAC: {*pcMethodDescs}, DAC: {pcMethodDescsLocal}");
for (int i = 0; i < *pcMethodDescs; i++)
{
Debug.Assert(methodDescs[i] == methodDescsLocal[i], $"cDAC: {methodDescs[i]:x}, DAC: {methodDescsLocal[i]:x}");
}
}
}
}
#endif
return hr;
}
#endregion ISOSDacInterface7

#region ISOSDacInterface8
Expand Down