Skip to content

Update SOS to resolve first level byref fields #2829

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 26, 2022
Merged
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
105 changes: 96 additions & 9 deletions src/SOS/Strike/util.cpp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -368,6 +368,57 @@ BOOL IsValueField (DacpFieldDescData *pFD)
return (pFD->Type == ELEMENT_TYPE_VALUETYPE); return (pFD->Type == ELEMENT_TYPE_VALUETYPE);
} }


static DWORD_PTR ResolveByRefField(DacpFieldDescData* pFD, DWORD_PTR dwAddr, CLRDATA_ADDRESS* methodTable)
{
if (dwAddr == 0)
return 0;

ToRelease<IMetaDataImport> pImport = MDImportForModule(TO_TADDR(pFD->ModuleOfType));

PCCOR_SIGNATURE pSignatureBlob = NULL;
ULONG sigBlobLength = 0;
if(FAILED(pImport->GetFieldProps(pFD->mb, NULL, NULL, 0, NULL, NULL, &pSignatureBlob, &sigBlobLength, NULL, NULL, NULL)))
return 0;

SigParser sigParser(pSignatureBlob, sigBlobLength);
sigParser.SkipExactlyOne();

// Move past and assert the ByRef
CorElementType etype;
if (FAILED(sigParser.GetElemType(&etype)))
return 0;

_ASSERTE(etype == ELEMENT_TYPE_BYREF);

// Get the byref's type. If this is also a byref we give up.
if (FAILED(sigParser.GetElemType(&etype)) || etype == ELEMENT_TYPE_BYREF)
return 0;

// If the type was determined to be a valuetype, we need the methodtable
// to be able to properly display it.
if (etype == ELEMENT_TYPE_VALUETYPE)
{
mdToken token = mdTokenNil;
if (FAILED(sigParser.GetToken(&token)))
return 0;

CLRDATA_ADDRESS methodTableMaybe = 0;
if (FAILED(g_sos->GetMethodDescFromToken(pFD->ModuleOfType, token, &methodTableMaybe)))
return 0;

*methodTable = methodTableMaybe;
}

// The byref has been confirmed and we now have a concrete type to read.
// Now get the target of the byref.
DWORD_PTR tgt;
CLRDATA_ADDRESS address = TO_CDADDR(dwAddr);
if (FAILED(g_ExtData->ReadVirtual(dwAddr, &tgt, sizeof(DWORD_PTR), NULL)))
return 0;

return tgt;
}

void DisplayDataMember (DacpFieldDescData* pFD, DWORD_PTR dwAddr, BOOL fAlign=TRUE) void DisplayDataMember (DacpFieldDescData* pFD, DWORD_PTR dwAddr, BOOL fAlign=TRUE)
{ {
if (dwAddr > 0) if (dwAddr > 0)
Expand Down Expand Up @@ -486,6 +537,25 @@ void DisplayDataMember (DacpFieldDescData* pFD, DWORD_PTR dwAddr, BOOL fAlign=TR
else else
ExtOut("%p", SOS_PTR(0)); ExtOut("%p", SOS_PTR(0));
break; break;
case ELEMENT_TYPE_BYREF:
{
CLRDATA_ADDRESS methodTable = 0;
DWORD_PTR tgt = ResolveByRefField(pFD, value.ptr, &methodTable);
if (tgt)
{
if (methodTable)
DMLOut(DMLByRefValueClass(value.ptr, methodTable, tgt));
else
DMLOut(DMLByRefObject(value.ptr, tgt));
}
else
{
// This will display zero if that is what the value was or the
// supplied value if ResolveByRefField() failed.
ExtOut("%p", SOS_PTR(value.ptr));
}
}
break;
default: default:
if (value.ptr) if (value.ptr)
DMLOut(DMLObject(value.ptr)); DMLOut(DMLObject(value.ptr));
Expand Down Expand Up @@ -4760,7 +4830,7 @@ int GetHex(CLRDATA_ADDRESS addr, __out_ecount(len) char *out, size_t len, bool f
return count; return count;
} }


CachedString Output::BuildHexValue(CLRDATA_ADDRESS addr, FormatType type, bool fill) CachedString Output::BuildHexValue(CLRDATA_ADDRESS disp, CLRDATA_ADDRESS addr, FormatType type, bool fill)
{ {
CachedString ret; CachedString ret;
if (ret.IsOOM()) if (ret.IsOOM())
Expand All @@ -4771,13 +4841,22 @@ CachedString Output::BuildHexValue(CLRDATA_ADDRESS addr, FormatType type, bool f


if (IsDMLEnabled()) if (IsDMLEnabled())
{ {
char hex[POINTERSIZE_BYTES*2 + 1]; char hex1[POINTERSIZE_BYTES*2 + 1];
GetHex(addr, hex, _countof(hex), fill); char hex2[POINTERSIZE_BYTES*2 + 1];
sprintf_s(ret, ret.GetStrLen(), DMLFormats[type], hex, hex); char* d = hex1;
char* a = hex1;
GetHex(addr, hex1, _countof(hex1), fill);
if (disp != addr)
{
GetHex(disp, hex2, _countof(hex2), fill);
d = hex2;
}

sprintf_s(ret, ret.GetStrLen(), DMLFormats[type], a, d);
} }
else else
{ {
GetHex(addr, ret, ret.GetStrLen(), fill); GetHex(disp, ret, ret.GetStrLen(), fill);
} }


return ret; return ret;
Expand Down Expand Up @@ -4806,7 +4885,7 @@ CachedString Output::BuildHexValueWithLength(CLRDATA_ADDRESS addr, size_t len, F
return ret; return ret;
} }


CachedString Output::BuildVCValue(CLRDATA_ADDRESS mt, CLRDATA_ADDRESS addr, FormatType type, bool fill) CachedString Output::BuildVCValue(CLRDATA_ADDRESS disp, CLRDATA_ADDRESS mt, CLRDATA_ADDRESS addr, FormatType type, bool fill)
{ {
_ASSERTE(type == DML_ValueClass); _ASSERTE(type == DML_ValueClass);
CachedString ret; CachedString ret;
Expand All @@ -4818,13 +4897,21 @@ CachedString Output::BuildVCValue(CLRDATA_ADDRESS mt, CLRDATA_ADDRESS addr, Form


if (IsDMLEnabled()) if (IsDMLEnabled())
{ {
char hexaddr[POINTERSIZE_BYTES*2 + 1]; char hexaddr1[POINTERSIZE_BYTES*2 + 1];
char hexaddr2[POINTERSIZE_BYTES*2 + 1];
char hexmt[POINTERSIZE_BYTES*2 + 1]; char hexmt[POINTERSIZE_BYTES*2 + 1];
char* d = hexaddr1;
char* a = hexaddr1;


GetHex(addr, hexaddr, _countof(hexaddr), fill); GetHex(addr, hexaddr1, _countof(hexaddr1), fill);
if (disp != addr)
{
GetHex(disp, hexaddr2, _countof(hexaddr2), fill);
d = hexaddr2;
}
GetHex(mt, hexmt, _countof(hexmt), fill); GetHex(mt, hexmt, _countof(hexmt), fill);


sprintf_s(ret, ret.GetStrLen(), DMLFormats[type], hexmt, hexaddr, hexaddr); sprintf_s(ret, ret.GetStrLen(), DMLFormats[type], hexmt, a, d);
} }
else else
{ {
Expand Down
47 changes: 25 additions & 22 deletions src/SOS/Strike/util.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -577,28 +577,29 @@ namespace Output
* of addr. * * of addr. *
* * * *
* Params: * * Params: *
* disp - the display address of the object *
* mt - the method table of the ValueClass * * mt - the method table of the ValueClass *
* addr - the address of the ValueClass * * addr - the address of the ValueClass *
* type - the format type to use to output this object * * type - the format type to use to output this object *
* fill - whether or not to pad the hex value with zeros * * fill - whether or not to pad the hex value with zeros *
* * * *
\**********************************************************************/ \**********************************************************************/
CachedString BuildVCValue(CLRDATA_ADDRESS mt, CLRDATA_ADDRESS addr, FormatType type, bool fill = true); CachedString BuildVCValue(CLRDATA_ADDRESS disp, CLRDATA_ADDRESS mt, CLRDATA_ADDRESS addr, FormatType type, bool fill = true);



/**********************************************************************\ /**********************************************************************\
* This function builds a DML string for an object. If DML is enabled, * * This function builds a DML string with a display name. If DML is enabled, *
* this function returns a DML string based on the format type. * * this function returns a DML string based on the format type. *
* Otherwise this returns a string containing only the hex value of * * Otherwise this returns a string containing only the hex value of *
* addr. * * addr. *
* * * *
* Params: * * Params: *
* disp - the display address of the object *
* addr - the address of the object * * addr - the address of the object *
* type - the format type to use to output this object * * type - the format type to use to output this object *
* fill - whether or not to pad the hex value with zeros * * fill - whether or not to pad the hex value with zeros *
* * * *
\**********************************************************************/ \**********************************************************************/
CachedString BuildHexValue(CLRDATA_ADDRESS addr, FormatType type, bool fill = true); CachedString BuildHexValue(CLRDATA_ADDRESS disp, CLRDATA_ADDRESS addr, FormatType type, bool fill = true);


/**********************************************************************\ /**********************************************************************\
* This function builds a DML string for an object. If DML is enabled, * * This function builds a DML string for an object. If DML is enabled, *
Expand Down Expand Up @@ -671,25 +672,27 @@ inline void DecrementIndent() { if (Output::g_Indent > 0) Output::g_Indent--; }
inline void ExtOutIndent() { WhitespaceOut(Output::g_Indent << 2); } inline void ExtOutIndent() { WhitespaceOut(Output::g_Indent << 2); }


// DML Generation Methods // DML Generation Methods
#define DMLListNearObj(addr) Output::BuildHexValue(addr, Output::DML_ListNearObj).GetPtr() #define DMLListNearObj(addr) Output::BuildHexValue(addr, addr, Output::DML_ListNearObj).GetPtr()
#define DMLDumpHeapMT(addr) Output::BuildHexValue(addr, Output::DML_DumpHeapMT).GetPtr() #define DMLDumpHeapMT(addr) Output::BuildHexValue(addr, addr, Output::DML_DumpHeapMT).GetPtr()
#define DMLMethodTable(addr) Output::BuildHexValue(addr, Output::DML_MethodTable).GetPtr() #define DMLMethodTable(addr) Output::BuildHexValue(addr, addr, Output::DML_MethodTable).GetPtr()
#define DMLMethodDesc(addr) Output::BuildHexValue(addr, Output::DML_MethodDesc).GetPtr() #define DMLMethodDesc(addr) Output::BuildHexValue(addr, addr, Output::DML_MethodDesc).GetPtr()
#define DMLClass(addr) Output::BuildHexValue(addr, Output::DML_EEClass).GetPtr() #define DMLClass(addr) Output::BuildHexValue(addr, addr, Output::DML_EEClass).GetPtr()
#define DMLModule(addr) Output::BuildHexValue(addr, Output::DML_Module).GetPtr() #define DMLModule(addr) Output::BuildHexValue(addr, addr, Output::DML_Module).GetPtr()
#define DMLIP(ip) Output::BuildHexValue(ip, Output::DML_IP).GetPtr() #define DMLIP(ip) Output::BuildHexValue(ip, ip, Output::DML_IP).GetPtr()
#define DMLObject(addr) Output::BuildHexValue(addr, Output::DML_Object).GetPtr() #define DMLObject(addr) Output::BuildHexValue(addr, addr, Output::DML_Object).GetPtr()
#define DMLDomain(addr) Output::BuildHexValue(addr, Output::DML_Domain).GetPtr() #define DMLByRefObject(byref, addr) Output::BuildHexValue(byref, addr, Output::DML_Object).GetPtr()
#define DMLAssembly(addr) Output::BuildHexValue(addr, Output::DML_Assembly).GetPtr() #define DMLDomain(addr) Output::BuildHexValue(addr, addr, Output::DML_Domain).GetPtr()
#define DMLThreadID(id) Output::BuildHexValue(id, Output::DML_ThreadID, false).GetPtr() #define DMLAssembly(addr) Output::BuildHexValue(addr, addr, Output::DML_Assembly).GetPtr()
#define DMLValueClass(mt, addr) Output::BuildVCValue(mt, addr, Output::DML_ValueClass).GetPtr() #define DMLThreadID(id) Output::BuildHexValue(id, id, Output::DML_ThreadID, false).GetPtr()
#define DMLRCWrapper(addr) Output::BuildHexValue(addr, Output::DML_RCWrapper).GetPtr() #define DMLValueClass(mt, addr) Output::BuildVCValue(addr, mt, addr, Output::DML_ValueClass).GetPtr()
#define DMLCCWrapper(addr) Output::BuildHexValue(addr, Output::DML_CCWrapper).GetPtr() #define DMLByRefValueClass(byref, mt, addr) Output::BuildVCValue(byref, mt, addr, Output::DML_ValueClass).GetPtr()
#define DMLRCWrapper(addr) Output::BuildHexValue(addr, addr, Output::DML_RCWrapper).GetPtr()
#define DMLCCWrapper(addr) Output::BuildHexValue(addr, addr, Output::DML_CCWrapper).GetPtr()
#define DMLManagedVar(expansionName,frame,simpleName) Output::BuildManagedVarValue(expansionName, frame, simpleName, Output::DML_ManagedVar).GetPtr() #define DMLManagedVar(expansionName,frame,simpleName) Output::BuildManagedVarValue(expansionName, frame, simpleName, Output::DML_ManagedVar).GetPtr()
#define DMLAsync(addr) Output::BuildHexValue(addr, Output::DML_Async).GetPtr() #define DMLAsync(addr) Output::BuildHexValue(addr, addr, Output::DML_Async).GetPtr()
#define DMLIL(addr) Output::BuildHexValue(addr, Output::DML_IL).GetPtr() #define DMLIL(addr) Output::BuildHexValue(addr, addr, Output::DML_IL).GetPtr()
#define DMLComWrapperRCW(addr) Output::BuildHexValue(addr, Output::DML_ComWrapperRCW).GetPtr() #define DMLComWrapperRCW(addr) Output::BuildHexValue(addr, addr, Output::DML_ComWrapperRCW).GetPtr()
#define DMLComWrapperCCW(addr) Output::BuildHexValue(addr, Output::DML_ComWrapperCCW).GetPtr() #define DMLComWrapperCCW(addr) Output::BuildHexValue(addr, addr, Output::DML_ComWrapperCCW).GetPtr()
#define DMLTaggedMemory(addr, len) Output::BuildHexValueWithLength(addr, len, Output::DML_TaggedMemory).GetPtr() #define DMLTaggedMemory(addr, len) Output::BuildHexValueWithLength(addr, len, Output::DML_TaggedMemory).GetPtr()


bool IsDMLEnabled(); bool IsDMLEnabled();
Expand Down
3 changes: 3 additions & 0 deletions src/inc/crosscomp.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
#define ARM_MAX_BREAKPOINTS 8 #define ARM_MAX_BREAKPOINTS 8
#define ARM_MAX_WATCHPOINTS 1 #define ARM_MAX_WATCHPOINTS 1


// This is already set in winnt.h when building for Win-x86 or Win-ARM64
#ifndef CONTEXT_UNWOUND_TO_CALL
#define CONTEXT_UNWOUND_TO_CALL 0x20000000 #define CONTEXT_UNWOUND_TO_CALL 0x20000000
#endif


typedef struct _NEON128 { typedef struct _NEON128 {
ULONGLONG Low; ULONGLONG Low;
Expand Down