Closed goldshtn closed 9 years ago
The IXCLR* interfaces can be grabbed from CoreCLR sources.
Initial support in 5a27f4c58830708352261c1a99f784452aa1299e. Still not handling value type parameters at all, and there are some seemingly timing-related bugs with the parameter grabbing in general.
Fixed the marshaling issue in 57628e981157230116113ee2b3cc1cbe5ac63e76 that caused name and type retrieval to fail randomly.
Almost done in ee1c0bccf78753ffe98a1a6f2d498d1c99cc287d. Turns out there was no marshaling issue and currently it looks like there is a codegen issue in the mscordacwks.dll for CLR v2.0.50727.8009 x64. Investigating. If it indeed is a bug, can introduce a workaround that detects this specific version -- because it looks like only the return HRESULT is affected, but the values come out fine.
Never getting local variables names though, even where sosex is able to get them.
The mscordacwks!ClrDataFrame::GetLocalVariableByIndex
implementation never returns names for local variables. See the source for GetLocalVariableByIndex here.
What we need to do instead is the following:
1) Get the PDB path for the module that contains the method
2) Get the IMetadataImport
interface from ClrMD's ModuleInfo
3) Create a SymBinder
(from .NET's ISymWrapper.dll) and call GetReader
to get an ISymbolReader
for that IMetadataImport
, module, and PDB path
4) Call ISymbolReader.GetMethod
with the method's mdToken to get an ISymbolMethod
5) Enumerate its scopes recursively from ISymbolMethod.RootScope
through its GetChildren()
6) In each scope, inspect the locals with ISymbolScope.GetLocals()
7) For each local, verify AddressKind == SymAddressKind.ILOffset
and AddressField1
is the local variable index
8) Get the matching local's name
It seems that getting the ISymbolReader
is a time-consuming operation, so it's worthwhile to cache the ISymbolReader
s already obtained on a module basis.
There's another problem. If the local/argument's type is an array type (e.g. System.Byte[]
), or a pointer type (e.g. System.Byte*
), or a by-ref type (e.g. System.Byte&
), ClrHeap.GetTypeByName
will never return a good value. Think if we want to parse the name and "understand" its kind and then look at the associated type and do a reconstruction, or maybe IXCLRDataTypeInstance
has some magic way of telling us what kind of type it is (IXCLRDataTypeInstance::GetFlags
always returns 0). This is only a problem with variables that are either ref types and null (and then we can't get the type name from the object itself; but we also don't really need it for anything), variables that are pointers, and variables that are by-ref types.
Some starting points:
IXCLRDataValue::GetFlags
(doesn't always return 0 :-))IXCLRDataValue::GetAssociatedType
returns the array element type/pointed to typeIXCLRDataValue::GetAssociatedValue
returns the pointed to valueAdded an implementation that uses SymReader in 4e23d80922f1bfc077f2cc0dca4e99c7cabf7103.
Added handling for by-ref and pointer types in 285f149b67bc0a4a62d01b651d38558c4a59373a. Almost done, except there's some race condition with finalizing SymBinder/SymReader/SymMethod objects.
b4f8b03feb8bc7a20b1db7f8c71b4ae5fdf3e08a: added workaround for CLR v2 DAC bug where certain IXCLRData* methods would return garbage HRESULTs, while otherwise succeeding.
d8f6f3d225f997768e9af121d1a3be54a9df0e79: fixed finalization issue around SymStore objects. All the interfaces aren't IDisposable, but the underlying objects are. If they aren't disposed of, their finalizers might run on exit and when they do, they crash with an AV. This issue is now done.
To do this, we need to get the
IXCLRDataProcess
out of ClrMD and use theIXCLRDataStackWalk
interface to get frames and retrieve parameters and locals. This is what SOSEX does.