// See the LICENSE file in the project root for more information.
// ==++==
-//
+//
-//
+//
// ==--==
#include "sos.h"
#include "disasm.h"
/**********************************************************************\
* Routine Description: *
* *
-* This function is called to get the memory address given a symbol *
+* This function is called to get the memory address given a symbol *
* name. It handles difference in symbol name between ntsd and *
* windbg. *
* *
ULONG Class;
ULONG Qualifier;
g_ExtControl->GetDebuggeeType(&Class,&Qualifier);
- if (Qualifier == DEBUG_DUMP_SMALL)
+ if (Qualifier == DEBUG_DUMP_SMALL)
{
g_ExtControl->GetDumpFormatFlags(&Qualifier);
if ((Qualifier & DEBUG_FORMAT_USER_SMALL_FULL_MEMORY) == 0)
return TRUE;
}
}
-
-#endif // FEATURE_PAL
+
+#endif // FEATURE_PAL
return FALSE;
}
// experience. This is primarily for testing.
return g_InMinidumpSafeMode;
}
-
+
#endif // FEATURE_PAL
return FALSE;
}
/**********************************************************************\
* Routine Description: *
* *
-* This function is called to find out if a dll is bbt-ized *
+* This function is called to find out if a dll is bbt-ized *
* *
\**********************************************************************/
BOOL IsRetailBuild (size_t base)
/**********************************************************************\
* Routine Description: *
* *
-* This function is called to read memory from the debugee's *
+* This function is called to read memory from the debugee's *
* address space. If the initial read fails, it attempts to read *
* only up to the edge of the page containing "offset". *
* *
/**********************************************************************\
* Routine Description: *
* *
-* This function is called to get the address of MethodDesc *
+* This function is called to get the address of MethodDesc *
* given an ip address *
* *
\**********************************************************************/
CLRDATA_ADDRESS EIP = TO_CDADDR(IP);
DacpCodeHeaderData codeHeaderData;
-
+
methodDesc = NULL;
gcinfoAddr = NULL;
-
+
if (codeHeaderData.Request(g_sos, EIP) != S_OK)
{
return;
methodDesc = (DWORD_PTR) codeHeaderData.MethodDescPtr;
jitType = (JITTypes) codeHeaderData.JITType;
- gcinfoAddr = (DWORD_PTR) codeHeaderData.GCInfo;
+ gcinfoAddr = (DWORD_PTR) codeHeaderData.GCInfo;
}
BOOL IsValueField (DacpFieldDescData *pFD)
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)
{
if (dwAddr > 0)
moveBlock (value, dwTmp, gElementTypeInfo[pFD->Type]);
}
- switch (pFD->Type)
+ switch (pFD->Type)
{
case ELEMENT_TYPE_I1:
- // there's no ANSI conformant type specifier for
- // signed char, so use the next best thing,
+ // there's no ANSI conformant type specifier for
+ // signed char, so use the next best thing,
// signed short (sign extending)
if (fAlign)
ExtOut("%" POINTERSIZE "hd", (short)value.ch);
case ELEMENT_TYPE_U1:
case ELEMENT_TYPE_BOOLEAN:
if (fAlign)
- // there's no ANSI conformant type specifier for
- // unsigned char, so use the next best thing,
+ // there's no ANSI conformant type specifier for
+ // unsigned char, so use the next best thing,
// unsigned short, not extending the sign
ExtOut("%" POINTERSIZE "hu", (USHORT)value.Short);
else
else
ExtOut("%p", SOS_PTR(0));
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:
if (value.ptr)
DMLOut(DMLObject(value.ptr));
}
*pOutPtr = 0;
-
+
if (pMTD->bIsDynamic)
{
ExtOut("dynamic statics NYI");
if (pFlags && pMTD->bIsShared)
{
BYTE flags;
- DWORD_PTR pTargetFlags = (DWORD_PTR) pDLMD->pClassData + RidFromToken(pMTD->cl) - 1;
+ DWORD_PTR pTargetFlags = (DWORD_PTR) pDLMD->pClassData + RidFromToken(pMTD->cl) - 1;
move_xp (flags, pTargetFlags);
*pFlags = flags;
}
-
-
- *pOutPtr = dwTmp;
+
+
+ *pOutPtr = dwTmp;
}
return;
}
void GetDLMFlags(DacpDomainLocalModuleData* pDLMD, DacpMethodTableData* pMTD, BYTE* pFlags)
-{
+{
if (pMTD->bIsDynamic)
{
ExtOut("dynamic statics NYI");
if (pFlags)
{
BYTE flags;
- DWORD_PTR pTargetFlags = (DWORD_PTR) pDLMD->pClassData + RidFromToken(pMTD->cl) - 1;
+ DWORD_PTR pTargetFlags = (DWORD_PTR) pDLMD->pClassData + RidFromToken(pMTD->cl) - 1;
move_xp (flags, pTargetFlags);
*pFlags = flags;
- }
+ }
}
return;
}
}
*pOutPtr = 0;
-
+
if (pMTD->bIsDynamic)
{
ExtOut("dynamic thread statics NYI");
*pFlags = flags;
}
- *pOutPtr = dwTmp;
+ *pOutPtr = dwTmp;
}
return;
}
DacpAppDomainStoreData adsData;
if (adsData.Request(g_sos)!=S_OK)
{
- ExtOut("Unable to get AppDomain information\n");
+ ExtOut("Unable to get AppDomain information\n");
}
ArrayHolder<CLRDATA_ADDRESS> pArray = new CLRDATA_ADDRESS[adsData.DomainCount];
if (pArray==NULL)
{
- ReportOOM();
+ ReportOOM();
return;
}
}
DMLOut(" %s:", DMLDomain(appdomainData.AppDomainPtr));
- DisplayDataMember(pFD, dwTmp, FALSE);
- }
+ DisplayDataMember(pFD, dwTmp, FALSE);
+ }
ExtOut(" <<\n");
}
ExtOut(" error getting thread %p, aborting this field\n", SOS_PTR(CurThread));
return;
}
-
+
if (vThread.osThreadId != 0)
- {
+ {
CLRDATA_ADDRESS appDomainAddr = vThread.domain;
// Get the DLM (we need this to check the ClassInit flags).
// It's annoying that we have to issue one request for
// domain-neutral modules and domain-specific modules.
- DacpDomainLocalModuleData vDomainLocalModule;
+ DacpDomainLocalModuleData vDomainLocalModule;
if (fIsShared)
{
if (g_sos->GetDomainLocalModuleDataFromAppDomain(appDomainAddr, (int)dwModuleDomainID, &vDomainLocalModule) != S_OK)
CurThread = vThread.nextThread;
continue;
}
-
+
DWORD_PTR dwTmp;
BYTE Flags = 0;
GetThreadStaticFieldPTR(&dwTmp, &vThreadLocalModule, pMT, pFD, &Flags);
-
- if ((Flags&4) == 0)
+
+ if ((Flags&4) == 0)
{
// Not allocated, go to next thread
// and continue looping
Flags = 0;
GetDLMFlags(&vDomainLocalModule, pMT, &Flags);
- if ((Flags&1) == 0)
+ if ((Flags&1) == 0)
{
// Not initialized, go to next thread
// and continue looping
CurThread = vThread.nextThread;
continue;
}
-
+
ExtOut(" %x:", vThread.osThreadId);
- DisplayDataMember(pFD, dwTmp, FALSE);
+ DisplayDataMember(pFD, dwTmp, FALSE);
}
// Go to next thread
iStart = iLen - maxChars;
UINT numDots = (maxChars < 3) ? maxChars : 3;
for (UINT i=0; i < numDots; i++)
- pszName[iStart+i] = '.';
+ pszName[iStart+i] = '.';
}
return pszName + iStart;
}
/**********************************************************************\
* Routine Description: *
* *
-* This function is called to dump all fields of a managed object. *
+* This function is called to dump all fields of a managed object. *
* dwStartAddr specifies the beginning memory address. *
* bFirst is used to avoid printing header every time. *
* *
if (bFirst)
{
ExtOutIndent();
- ExtOut("%" POINTERSIZE "s %8s %8s %20s %2s %8s %" POINTERSIZE "s %s\n",
+ ExtOut("%" POINTERSIZE "s %8s %8s %20s %2s %8s %" POINTERSIZE "s %s\n",
"MT", "Field", "Offset", "Type", "VT", "Attr", "Value", "Name");
numInstanceFields = 0;
}
-
+
BOOL fIsShared = pMTD->bIsShared;
if (pMTD->ParentMethodTable)
{
ExtOut("Invalid parent MethodTable\n");
return;
- }
+ }
DacpMethodTableFieldData vParentMethTableFields;
if (vParentMethTableFields.Request(g_sos,pMTD->ParentMethodTable) != S_OK)
{
ExtOut("Invalid parent EEClass\n");
return;
- }
+ }
DisplayFields(pMTD->ParentMethodTable, &vParentMethTable, &vParentMethTableFields, dwStartAddr, FALSE, bValueClass);
}
// Get the module name
DacpModuleData module;
if (module.Request(g_sos, pMTD->Module)!=S_OK)
- return;
+ return;
ToRelease<IMetaDataImport> pImport = MDImportForModule(&module);
-
+
while (numInstanceFields < pMTFD->wNumInstanceFields
|| numStaticFields < pMTFD->wNumStaticFields)
{
return;
ExtOutIndent ();
-
+
if ((vFieldDesc.Request(g_sos, dwAddr)!=S_OK) ||
(vFieldDesc.Type >= ELEMENT_TYPE_MAX))
{
offset);
char ElementName[mdNameLen];
- if ((vFieldDesc.Type == ELEMENT_TYPE_VALUETYPE ||
+ if ((vFieldDesc.Type == ELEMENT_TYPE_VALUETYPE ||
vFieldDesc.Type == ELEMENT_TYPE_CLASS) && vFieldDesc.MTOfType)
{
- NameForMT_s((DWORD_PTR)vFieldDesc.MTOfType, g_mdName, mdNameLen);
- ExtOut("%20.20S ", FormatTypeName(g_mdName, 20));
+ NameForMT_s((DWORD_PTR)vFieldDesc.MTOfType, g_mdName, mdNameLen);
+ ExtOut("%20.20S ", FormatTypeName(g_mdName, 20));
}
- else
- {
+ else
+ {
if (vFieldDesc.Type == ELEMENT_TYPE_CLASS && vFieldDesc.TokenOfType != mdTypeDefNil)
{
// Get the name from Metadata!!!
}
else
{
- // If ET type from signature is different from fielddesc, then the signature one is more descriptive.
+ // If ET type from signature is different from fielddesc, then the signature one is more descriptive.
// For example, E_T_STRING in field desc will be E_T_CLASS. In minidump's case, we won't have
// the method table for it.
ComposeName_s(vFieldDesc.Type != vFieldDesc.sigType ? vFieldDesc.sigType : vFieldDesc.Type, ElementName, sizeof(ElementName)/sizeof(ElementName[0]));
- ExtOut("%20.20s ", ElementName);
+ ExtOut("%20.20s ", ElementName);
}
}
-
+
ExtOut("%2s ", (IsElementValueType(vFieldDesc.Type)) ? "1" : "0");
if (vFieldDesc.bIsStatic && (vFieldDesc.bIsThreadLocal || vFieldDesc.bIsContextLocal))
ExtOut("\nDisplay of context static variables is not implemented\n");
}
}
-
+
}
else if (vFieldDesc.bIsStatic)
{
else
{
ExtOut("%8s ", "static");
-
+
DacpDomainLocalModuleData vDomainLocalModule;
-
+
// The MethodTable isn't shared, so the module must not be loaded domain neutral. We can
// get the specific DomainLocalModule instance without needing to know the AppDomain in advance.
if (g_sos->GetDomainLocalModuleDataFromModule(pMTD->Module, &vDomainLocalModule) != S_OK)
NameForToken_s(TokenFromRid(vFieldDesc.mb, mdtFieldDef), pImport, g_mdName, mdNameLen, false);
ExtOut(" %S\n", g_mdName);
}
-
+
}
-
+
return;
}
return S_OK;
}
-// Return value: -1 = error,
-// 0 = field not found,
+// Return value: -1 = error,
+// 0 = field not found,
// > 0 = offset to field from objAddr
int GetObjFieldOffset(CLRDATA_ADDRESS cdaObj, __in_z LPCWSTR wszFieldName, BOOL bFirst)
{
return GetObjFieldOffset(cdaObj, TO_CDADDR(mt), wszFieldName, bFirst);
}
-// Return value: -1 = error,
-// 0 = field not found,
+// Return value: -1 = error,
+// 0 = field not found,
// > 0 = offset to field from objAddr
int GetObjFieldOffset(CLRDATA_ADDRESS cdaObj, CLRDATA_ADDRESS cdaMT, __in_z LPCWSTR wszFieldName,
BOOL bFirst/*=TRUE*/, DacpFieldDescData* pDacpFieldDescData/*=NULL*/)
{
#define EXITPOINT(EXPR) do { if(!(EXPR)) { return -1; } } while (0)
-
+
DacpObjectData objData;
DacpMethodTableData dmtd;
DacpMethodTableFieldData vMethodTableFields;
{
numInstanceFields = 0;
}
-
- EXITPOINT(objData.Request(g_sos, cdaObj) == S_OK);
+
+ EXITPOINT(objData.Request(g_sos, cdaObj) == S_OK);
EXITPOINT(dmtd.Request(g_sos, cdaMT) == S_OK);
if (dmtd.ParentMethodTable)
{
- DWORD retVal = GetObjFieldOffset (cdaObj, dmtd.ParentMethodTable,
+ DWORD retVal = GetObjFieldOffset (cdaObj, dmtd.ParentMethodTable,
wszFieldName, FALSE, pDacpFieldDescData);
if (retVal != 0)
{
return retVal;
}
}
-
+
EXITPOINT (vMethodTableFields.Request(g_sos,cdaMT) == S_OK);
EXITPOINT (module.Request(g_sos,dmtd.Module) == S_OK);
-
- CLRDATA_ADDRESS dwAddr = vMethodTableFields.FirstField;
+
+ CLRDATA_ADDRESS dwAddr = vMethodTableFields.FirstField;
ToRelease<IMetaDataImport> pImport = MDImportForModule(&module);
-
+
while (numInstanceFields < vMethodTableFields.wNumInstanceFields)
- {
+ {
EXITPOINT (vFieldDesc.Request(g_sos, dwAddr) == S_OK);
if (!vFieldDesc.bIsStatic)
{
- DWORD offset = vFieldDesc.dwOffset + sizeof(BaseObject);
+ DWORD offset = vFieldDesc.dwOffset + sizeof(BaseObject);
NameForToken_s (TokenFromRid(vFieldDesc.mb, mdtFieldDef), pImport, g_mdName, mdNameLen, false);
if (_wcscmp (wszFieldName, g_mdName) == 0)
{
}
return offset;
}
- numInstanceFields ++;
+ numInstanceFields ++;
}
- dwAddr = vFieldDesc.NextField;
+ dwAddr = vFieldDesc.NextField;
}
// Field name not found...
return 0;
-#undef EXITPOINT
+#undef EXITPOINT
}
// Field name not found...
return NOT_FOUND;
-#undef EXITPOINT
+#undef EXITPOINT
}
// Returns an AppDomain address if AssemblyPtr is loaded into that domain only. Otherwise
{
ExtOut("Unable to get appdomain store\n");
return NULL;
- }
+ }
size_t AllocSize;
if (!ClrSafeInt<size_t>::multiply(sizeof(CLRDATA_ADDRESS), adstore.DomainCount, AllocSize))
{
- ReportOOM();
+ ReportOOM();
return NULL;
}
ArrayHolder<CLRDATA_ADDRESS> pArray = new CLRDATA_ADDRESS[adstore.DomainCount];
if (pArray==NULL)
{
- ReportOOM();
+ ReportOOM();
return NULL;
}
-
+
if (g_sos->GetAppDomainList(adstore.DomainCount, pArray, NULL)!=S_OK)
{
ExtOut ("Failed to get appdomain list\n");
size_t AssemblyAllocSize;
if (!ClrSafeInt<size_t>::multiply(sizeof(CLRDATA_ADDRESS), dadd.AssemblyCount, AssemblyAllocSize))
{
- ReportOOM();
+ ReportOOM();
return NULL;
}
ArrayHolder<CLRDATA_ADDRESS> pAsmArray = new CLRDATA_ADDRESS[dadd.AssemblyCount];
if (pAsmArray==NULL)
{
- ReportOOM();
+ ReportOOM();
return NULL;
}
-
+
if (g_sos->GetAssemblyList(dadd.AppDomainPtr,dadd.AssemblyCount,pAsmArray, NULL)!=S_OK)
{
ExtOut("Unable to get array of Assemblies\n");
- return NULL;
+ return NULL;
}
-
+
for (LONG n = 0; n < dadd.AssemblyCount; n ++)
{
if (IsInterrupt())
return NULL;
}
appDomain = dadd.AppDomainPtr;
- }
- }
+ }
+ }
}
- }
+ }
+
-
return appDomain;
}
{
return NULL;
}
-
+
DacpModuleData module;
if (module.Request(g_sos, mt.Module) != S_OK)
{
CLRDATA_ADDRESS GetAppDomain(CLRDATA_ADDRESS objPtr)
{
CLRDATA_ADDRESS appDomain = NULL;
-
+
DacpObjectData objData;
if (objData.Request(g_sos,objPtr) != S_OK)
- {
+ {
return NULL;
}
if (adstore.Request(g_sos) != S_OK)
{
return NULL;
- }
-
+ }
+
if (assembly.ParentDomain == adstore.sharedDomain)
{
sos::Object obj(TO_TADDR(objPtr));
{
return NULL;
}
-
+
DWORD adIndex = (value >> SBLK_APPDOMAIN_SHIFT) & SBLK_MASK_APPDOMAININDEX;
if ( ((value & BIT_SBLK_IS_HASH_OR_SYNCBLKINDEX) != 0) || adIndex==0)
{
}
}
else if ((value & BIT_SBLK_IS_HASH_OR_SYNCBLKINDEX) == 0)
- {
+ {
size_t AllocSize;
if (!ClrSafeInt<size_t>::multiply(sizeof(CLRDATA_ADDRESS), adstore.DomainCount, AllocSize))
{
{
return NULL;
}
-
+
if (g_sos->GetAppDomainList(adstore.DomainCount, pArray, NULL)!=S_OK)
{
return NULL;
appDomain = pArray[i];
break;
}
- }
+ }
}
}
else
{
DacpModuleData ModuleData;
fileName[0] = L'\0';
-
+
HRESULT hr = ModuleData.Request(g_sos, TO_CDADDR(pModuleAddr));
if (SUCCEEDED(hr))
{
hr = FileNameForModule(&ModuleData,fileName);
}
-
+
return hr;
}
/**********************************************************************\
* Routine Description: *
* *
-* This function is called to find the file name given a Module. *
+* This function is called to find the file name given a Module. *
* *
\**********************************************************************/
// fileName should be at least MAX_LONGPATH
ULONG32 nameLen = 0;
hr = pModule->GetFileName(MAX_LONGPATH, &nameLen, fileName);
}
-
+
return hr;
}
if ((ULONG64)pAssembly->AssemblySecDesc != NULL)
ExtOut("SecurityDescriptor: %p\n", SOS_PTR(pAssembly->AssemblySecDesc));
ExtOut(" Module\n");
-
+
ArrayHolder<CLRDATA_ADDRESS> Modules = new CLRDATA_ADDRESS[pAssembly->ModuleCount];
- if (Modules == NULL
+ if (Modules == NULL
|| g_sos->GetAssemblyModuleList(pAssembly->AssemblyPtr, pAssembly->ModuleCount, Modules, NULL) != S_OK)
{
- ReportOOM();
+ ReportOOM();
return;
}
-
+
for (UINT n = 0; n < pAssembly->ModuleCount; n++)
{
if (IsInterrupt())
{
ExtOut("%S\n", (moduleData.bIsReflection) ? W("Dynamic Module") : W("Unknown Module"));
}
- }
+ }
else
{
ExtOut("Request module data FAILED\n");
/**********************************************************************\
* Routine Description: *
* *
-* This function is called to dump the contents of a domain. *
+* This function is called to dump the contents of a domain. *
* *
\**********************************************************************/
void DomainInfo (DacpAppDomainData *pDomain)
if (pDomain->AssemblyCount == 0)
return;
-
+
ArrayHolder<CLRDATA_ADDRESS> pArray = new CLRDATA_ADDRESS[pDomain->AssemblyCount];
if (pArray==NULL)
{
if (g_sos->GetAssemblyList(pDomain->AppDomainPtr,pDomain->AssemblyCount,pArray, NULL)!=S_OK)
{
ExtOut("Unable to get array of Assemblies\n");
- return;
+ return;
}
LONG n;
{
if (IsInterrupt())
return;
-
+
if (n != 0)
ExtOut("\n");
{
if (assemblyData.isDynamic)
ExtOut(" (Dynamic)");
-
+
ExtOut(" [");
if (g_sos->GetAssemblyName(pArray[n], mdNameLen, g_mdName, NULL) == S_OK)
ExtOut("%S", g_mdName);
AssemblyInfo(&assemblyData);
}
- }
+ }
ExtOut("\n");
}
/**********************************************************************\
* Routine Description: *
* *
-* This function is called to find the name of a MethodDesc using *
+* This function is called to find the name of a MethodDesc using *
* metadata API. *
* *
\**********************************************************************/
/**********************************************************************\
* Routine Description: *
* *
-* This function is called to find the name of a MethodTable using *
+* This function is called to find the name of a MethodTable using *
* metadata API. *
* *
\**********************************************************************/
{
bool array = false;
WCHAR *res = NULL;
-
+
if (mt == sos::MethodTable::GetFreeMT())
{
res = new WCHAR[5];
wcscpy_s(res, 5, W("Free"));
return res;
}
-
+
if (mt == sos::MethodTable::GetArrayMT() && cmt != NULL)
{
mt = cmt;
array = true;
}
-
+
unsigned int needed = 0;
HRESULT hr = g_sos->GetMethodTableName(mt, 0, NULL, &needed);
-
+
// If failed, we will return null.
if (SUCCEEDED(hr))
{
// +2 for [], if we need it.
res = new WCHAR[needed+2];
hr = g_sos->GetMethodTableName(mt, needed, res, NULL);
-
+
if (FAILED(hr))
{
delete [] res;
res = NULL;
}
else if (array)
- {
+ {
res[needed-1] = '[';
res[needed] = ']';
res[needed+1] = 0;
/**********************************************************************\
* Routine Description: *
* *
-* Return TRUE if str2 is a substring of str1 and str1 and str2 *
+* Return TRUE if str2 is a substring of str1 and str1 and str2 *
* share the same file path.
* *
\**********************************************************************/
/**********************************************************************\
* Routine Description: *
* *
-* Return TRUE if moduleAddr is the address of a module. *
+* Return TRUE if moduleAddr is the address of a module. *
* *
\**********************************************************************/
BOOL IsModule (DWORD_PTR moduleAddr)
/**********************************************************************\
* Routine Description: *
* *
-* Return TRUE if value is the address of a MethodTable. *
+* Return TRUE if value is the address of a MethodTable. *
* We verify that MethodTable and EEClass are right.
* *
\**********************************************************************/
{
return FALSE;
}
-
+
return TRUE;
}
/**********************************************************************\
* Routine Description: *
* *
-* Return TRUE if value is the address of a MethodDesc. *
+* Return TRUE if value is the address of a MethodDesc. *
* We verify that MethodTable and EEClass are right.
* *
\**********************************************************************/
BOOL IsMethodDesc (DWORD_PTR value)
-{
+{
// Just by retrieving one successfully from the DAC, we know we have a MethodDesc.
DacpMethodDescData MethodDescData;
if (MethodDescData.Request(g_sos, TO_CDADDR(value)) != S_OK)
{
return FALSE;
}
-
+
return TRUE;
}
{
if (pData->ObjectType == OBJ_ARRAY)
return g_special_usefulGlobals.ArrayMethodTable == pData->MethodTable;
-
+
return FALSE;
}
DWORD_PTR mtAddr = NULL;
if (SUCCEEDED(GetMTOfObject(obj, &mtAddr)))
return TO_TADDR(g_special_usefulGlobals.ArrayMethodTable) == mtAddr;
-
+
return FALSE;
}
BOOL IsDerivedFrom(CLRDATA_ADDRESS mtObj, DWORD_PTR modulePtr, mdTypeDef typeDef)
{
DacpMethodTableData dmtd;
-
+
for (CLRDATA_ADDRESS walkMT = mtObj;
walkMT != NULL && dmtd.Request(g_sos, walkMT) == S_OK;
walkMT = dmtd.ParentMethodTable)
ExtOut(" ");
StringObjectContent(objAddr, FALSE, 40);
}
- else if (IsObjectArray(objAddr) &&
+ else if (IsObjectArray(objAddr) &&
(g_sos->GetMethodTableName(objectData.ElementTypeHandle, mdNameLen, g_mdName, NULL) == S_OK))
{
ExtOut(" ");
void DumpStackObjectsInternal(size_t StackTop, size_t StackBottom, BOOL verifyFields)
{
for (DWORD_PTR ptr = StackTop; ptr <= StackBottom; ptr += sizeof(DWORD_PTR))
- {
+ {
if (IsInterrupt())
return;
void DumpRegObjectHelper(const char *regName, BOOL verifyFields)
{
DWORD_PTR reg;
-#ifdef FEATURE_PAL
+#ifdef FEATURE_PAL
if (FAILED(g_ExtRegisters->GetValueByName(regName, ®)))
return;
#else
}
void DumpStackObjectsHelper (
- TADDR StackTop,
- TADDR StackBottom,
+ TADDR StackTop,
+ TADDR StackBottom,
BOOL verifyFields)
{
ExtOut(g_targetMachine->GetDumpStackObjectsHeading());
{
return FALSE;
}
-
+
#ifndef FEATURE_PAL
if (tolower(*fusionName) != tolower(*mName))
#else
fusionName++;
mName++;
}
- return TRUE;
+ return TRUE;
}
return FALSE;
}
-
+
BOOL DebuggerModuleNamesMatch (CLRDATA_ADDRESS PEFileAddr, ___in __in_z LPSTR mName)
{
// Another way to see if a module is the same is
ULONG Index;
ULONG64 base;
if (g_ExtSymbols->GetModuleByOffset(pebase, 0, &Index, &base) == S_OK)
- {
+ {
CHAR ModuleName[MAX_LONGPATH+1];
- if (g_ExtSymbols->GetModuleNames(Index, base, NULL, 0, NULL, ModuleName,
+ if (g_ExtSymbols->GetModuleNames(Index, base, NULL, 0, NULL, ModuleName,
MAX_LONGPATH, NULL, NULL, 0, NULL) == S_OK)
{
if (_stricmp (ModuleName, mName) == 0)
return TRUE;
}
}
- }
+ }
}
- }
+ }
}
return FALSE;
}
ExtOut("<integer overflow>\n");
return NULL;
}
-
+
moduleList = new DWORD_PTR[maxList];
if (moduleList == NULL)
{
}
ArrayHolder<char> fileName = new char[MAX_LONGPATH];
-
+
// Search all domains to find a module
for (int n = 0; n < adsData.DomainCount+numSpecialDomains; n++)
{
ExtOut("<interrupted>\n");
goto Failure;
}
-
+
DacpAppDomainData appDomain;
if (FAILED(hr = appDomain.Request(g_sos, pArray[n])))
{
// >sxe ld:clr
// >g
// ...
- // ModLoad: runtime dll
+ // ModLoad: runtime dll
// >!bpmd Foo.dll Foo.Bar
// we will correctly give the answer that whatever module you were looking for, it isn't loaded yet
}
if (appDomain.AssemblyCount)
- {
+ {
pAssemblyArray = new CLRDATA_ADDRESS[appDomain.AssemblyCount];
if (pAssemblyArray==NULL)
{
int bytesWritten = WideCharToMultiByte(CP_ACP, 0, moduleName, -1, fileName, MAX_LONGPATH, NULL, NULL);
_ASSERTE(bytesWritten > 0);
}
-
- if ((mName == NULL) ||
+
+ if ((mName == NULL) ||
IsSameModuleName(fileName, mName) ||
DebuggerModuleNamesMatch(ModuleData.File, mName) ||
IsFusionLoadedModule(fileName, mName))
{
AddToModuleList(moduleList, *numModule, maxList, (DWORD_PTR)ModuleAddr);
- }
- }
+ }
+ }
pModules = NULL;
}
}
return moduleList;
-
+
// We do not want to return a half-constructed list. Instead, we return NULL on a failure.
Failure:
delete [] moduleList;
/**********************************************************************\
* Routine Description: *
* *
-* Find the EE data given a name. *
+* Find the EE data given a name. *
* *
\**********************************************************************/
void GetInfoFromName(DWORD_PTR ModulePtr, const char* name, mdTypeDef* retMdTypeDef)
if (retMdTypeDef)
*retMdTypeDef = 0;
- ToRelease<IMetaDataImport> pImport = MDImportForModule (ModulePtr);
+ ToRelease<IMetaDataImport> pImport = MDImportForModule (ModulePtr);
if (pImport == 0)
return;
for (n = 0; n <= length; n ++)
wszName[n] = name[n];
- // First enumerate methods. We're taking advantage of the DAC's
+ // First enumerate methods. We're taking advantage of the DAC's
// CLRDataModule::EnumMethodDefinitionByName which can parse
// method names (whether in nested classes, or explicit interface
// method implementations).
{
if (retMdTypeDef)
*retMdTypeDef = cl;
-
+
GetInfoFromModule(ModulePtr, cl, retMdTypeDef ? &ignoredModuleInfoRet : NULL);
return;
}
-
+
// See if it is a method
WCHAR *pwzMethod;
if ((pwzMethod = _wcsrchr(pName, L'.')) == NULL)
pwzMethod --;
pwzMethod[0] = L'\0';
pwzMethod ++;
-
+
// @todo: Handle Nested classes correctly.
if (SUCCEEDED(pImport->FindTypeDefByName (pName, tkEnclose, &cl)))
{
/**********************************************************************\
* Routine Description: *
* *
-* Find the EE data given a token. *
+* Find the EE data given a token. *
* *
\**********************************************************************/
DWORD_PTR GetMethodDescFromModule(DWORD_PTR ModuleAddr, ULONG token)
{
// a NULL ReturnValue means the method desc is not loaded yet
return MD_NOT_YET_LOADED;
- }
+ }
else if ( !IsMethodDesc((DWORD_PTR)md))
{
return NULL;
}
-
- return (DWORD_PTR)md;
+
+ return (DWORD_PTR)md;
}
/**********************************************************************\
* Routine Description: *
* *
-* Find the MethodDefinitions given a name. *
+* Find the MethodDefinitions given a name. *
* *
\**********************************************************************/
HRESULT GetMethodDefinitionsFromName(TADDR ModulePtr, IXCLRDataModule* mod, const char *name, IXCLRDataMethodDefinition **ppOut, int numMethods, int *numMethodsNeeded)
mod->EndEnumMethodDefinitionsByName(h);
}
}
-
+
return S_OK;
}
/**********************************************************************\
* Routine Description: *
* *
-* Find the EE data given a name. *
+* Find the EE data given a name. *
* *
\**********************************************************************/
HRESULT GetMethodDescsFromName(TADDR ModulePtr, IXCLRDataModule* mod, const char *name, DWORD_PTR **pOut,int *numMethods)
mod->EndEnumMethodDefinitionsByName(h);
}
}
-
+
return S_OK;
}
-
+
/**********************************************************************\
* Routine Description: *
* *
-* Find the EE data given a token. *
+* Find the EE data given a token. *
* *
\**********************************************************************/
void GetInfoFromModule (DWORD_PTR ModuleAddr, ULONG token, DWORD_PTR *ret)
case mdtTypeRef:
break;
case mdtFieldDef:
- break;
+ break;
default:
ExtOut("This token type is not supported\n");
return;
break;
}
-
+
CLRDATA_ADDRESS md = 0;
if (FAILED(g_sos->GetMethodDescFromToken(ModuleAddr, token, &md)) || !IsValidToken (ModuleAddr, token))
{
ExtOut("<invalid module token>\n");
return;
}
-
+
if (ret != NULL)
{
*ret = (DWORD_PTR)md;
}
ExtOut("Token: %p\n", SOS_PTR(token));
-
+
switch (TypeFromToken(token))
{
case mdtFieldDef:
}
else
{
- ExtOut("MethodDesc: <not loaded yet>\n");
+ ExtOut("MethodDesc: <not loaded yet>\n");
NameForToken_s(ModuleAddr, token, g_mdName, mdNameLen);
}
-
+
ExtOut("Name: %S\n", g_mdName);
// Nice to have a little more data
if (md)
{
if (MethodDescData.bHasNativeCode)
{
- DMLOut("JITTED Code Address: %s\n", DMLIP(MethodDescData.NativeCodeAddr));
+ DMLOut("JITTED Code Address: %s\n", DMLIP(MethodDescData.NativeCodeAddr));
}
else
{
}
else
{
- ExtOut("Not JITTED yet.\n");
+ ExtOut("Not JITTED yet.\n");
}
break;
}
else
{
ExtOut("EEClass: <error getting EEClass>\n");
- }
+ }
}
else
{
ExtOut("MethodTable: <not loaded yet>\n");
- ExtOut("EEClass: <not loaded yet>\n");
+ ExtOut("EEClass: <not loaded yet>\n");
}
NameForToken_s(ModuleAddr, token, g_mdName, mdNameLen);
ExtOut("Name: %S\n", g_mdName);
}
}
-void DumpTieredNativeCodeAddressInfo(struct DacpTieredVersionData * pTieredVersionData, const UINT cTieredVersionData,
+void DumpTieredNativeCodeAddressInfo(struct DacpTieredVersionData * pTieredVersionData, const UINT cTieredVersionData,
ULONG rejitID, CLRDATA_ADDRESS ilAddr, CLRDATA_ADDRESS ilNodeAddr)
{
ExtOut(" ILCodeVersion: %p\n", SOS_PTR(ilNodeAddr));
}
void DumpRejitData(CLRDATA_ADDRESS pMethodDesc, DacpReJitData * pReJitData)
-{
+{
int rejitID = (int)pReJitData->rejitID;
CLRDATA_ADDRESS ilAddr = 0;
CLRDATA_ADDRESS ilNodeAddr = 0;
struct DacpReJitData2 rejitData;
ReleaseHolder<ISOSDacInterface7> sos7;
- if (SUCCEEDED(g_sos->QueryInterface(__uuidof(ISOSDacInterface7), &sos7)) &&
- SUCCEEDED(sos7->GetReJITInformation(pMethodDesc,
+ if (SUCCEEDED(g_sos->QueryInterface(__uuidof(ISOSDacInterface7), &sos7)) &&
+ SUCCEEDED(sos7->GetReJITInformation(pMethodDesc,
rejitID,
&rejitData)))
{
int cCodeAddrs;
ReleaseHolder<ISOSDacInterface5> sos5;
- if (SUCCEEDED(g_sos->QueryInterface(__uuidof(ISOSDacInterface5), &sos5)) &&
- SUCCEEDED(sos5->GetTieredVersions(pMethodDesc,
+ if (SUCCEEDED(g_sos->QueryInterface(__uuidof(ISOSDacInterface5), &sos5)) &&
+ SUCCEEDED(sos5->GetTieredVersions(pMethodDesc,
rejitID,
codeAddrs,
kcMaxTieredVersions,
BOOL bFailed = FALSE;
if (g_sos->GetMethodDescName(pMethodDescData->MethodDescPtr, 1024, wszNameBuffer, NULL) != S_OK)
{
- wcscpy_s(wszNameBuffer, _countof(wszNameBuffer), W("UNKNOWN"));
- bFailed = TRUE;
+ wcscpy_s(wszNameBuffer, _countof(wszNameBuffer), W("UNKNOWN"));
+ bFailed = TRUE;
}
if (!fStackTraceFormat)
if (SUCCEEDED(mtdata.Request(g_sos, pMethodDescData->MethodTablePtr)))
{
DMLOut("Class: %s\n", DMLClass(mtdata.Class));
- }
+ }
DMLOut("MethodTable: %s\n", DMLMethodTable(pMethodDescData->MethodTablePtr));
ExtOut("mdToken: %p\n", SOS_PTR(pMethodDescData->MDToken));
DMLOut("Module: %s\n", DMLModule(pMethodDescData->ModulePtr));
ExtOut("IsJitted: %s\n", pMethodDescData->bHasNativeCode ? "yes" : "no");
- DMLOut("Current CodeAddr: %s\n", DMLIP(pMethodDescData->NativeCodeAddr));
+ DMLOut("Current CodeAddr: %s\n", DMLIP(pMethodDescData->NativeCodeAddr));
int rejitID = (int)pMethodDescData->rejitDataCurrent.rejitID;
CLRDATA_ADDRESS ilAddr = 0;
ReleaseHolder<ISOSDacInterface7> sos7;
if (SUCCEEDED(g_sos->QueryInterface(__uuidof(ISOSDacInterface7), &sos7)))
{
- if SUCCEEDED(sos7->GetReJITInformation(pMethodDescData->MethodDescPtr,
+ if SUCCEEDED(sos7->GetReJITInformation(pMethodDescData->MethodDescPtr,
rejitID,
&rejitData))
{
int cCodeAddrs;
ReleaseHolder<ISOSDacInterface5> sos5;
- if (SUCCEEDED(g_sos->QueryInterface(__uuidof(ISOSDacInterface5), &sos5)) &&
- SUCCEEDED(sos5->GetTieredVersions(pMethodDescData->MethodDescPtr,
+ if (SUCCEEDED(g_sos->QueryInterface(__uuidof(ISOSDacInterface5), &sos5)) &&
+ SUCCEEDED(sos5->GetTieredVersions(pMethodDescData->MethodDescPtr,
rejitID,
codeAddrs,
kcMaxTieredVersions,
{
// Only clutter the display with module/token for cases where we
// can't get the MethodDesc name for some reason.
- DMLOut("Unknown MethodDesc (Module %s, mdToken %08x)",
+ DMLOut("Unknown MethodDesc (Module %s, mdToken %08x)",
DMLModule(pMethodDescData->ModulePtr),
pMethodDescData->MDToken);
}
DacpReJitData revertedRejitData[kcMaxRevertedRejitData];
ULONG cNeededRevertedRejitData;
if (g_sos->GetMethodDescData(
- TO_CDADDR(dwMethodDescAddr),
+ TO_CDADDR(dwMethodDescAddr),
dwRequestedIP,
- &MethodDescData,
+ &MethodDescData,
_countof(revertedRejitData),
revertedRejitData,
&cNeededRevertedRejitData) != S_OK)
{
DacpAppDomainStoreData adsData;
- numDomain = 0;
-
+ numDomain = 0;
+
if (adsData.Request(g_sos)!=S_OK)
{
return;
{
domainList[numDomain++] = (DWORD_PTR) adsData.sharedDomain;
}
-
+
CLRDATA_ADDRESS *pArray = new CLRDATA_ADDRESS[adsData.DomainCount];
if (pArray==NULL)
{
ExtOut("Failed to request threads from the thread store.");
return E_FAIL;
}
-
+
*threadList = new DWORD_PTR[ThreadStore.threadCount];
if (*threadList == NULL)
{
ReportOOM();
return E_OUTOFMEMORY;
}
-
+
CLRDATA_ADDRESS CurThread = ThreadStore.firstThread;
while (CurThread != NULL)
{
ULONG Tid;
g_ExtSystem->GetCurrentThreadSystemId(&Tid);
-
+
CLRDATA_ADDRESS CurThread = ThreadStore.firstThread;
while (CurThread)
{
if (Thread.Request(g_sos, CurThread) != S_OK)
{
return NULL;
- }
-
+ }
+
if (Thread.osThreadId == Tid)
- {
+ {
return CurThread;
}
-
+
CurThread = Thread.nextThread;
}
return NULL;
reloadCommand.append(GetRuntimeDllName());
g_ExtSymbols->Reload(reloadCommand.c_str());
}
-
+
// reload mscoree.pdb and clrjit.pdb to get line info
bLoadSymbol = TRUE;
}
// If there is no COMHeader, this can not be managed code.
if (Header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COMHEADER].VirtualAddress == 0)
return 0;
-
+
IMAGE_COR20_HEADER ComPlusHeader;
if (g_ExtData->ReadVirtual(TO_CDADDR(base + Header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COMHEADER].VirtualAddress),
&ComPlusHeader, sizeof(ComPlusHeader), NULL) != S_OK)
return 0;
-
+
// If there is no Precompiled image info, it can not be prejit code
if (ComPlusHeader.ManagedNativeHeader.VirtualAddress == 0) {
return 0;
}
//
-// Return true if major runtime version (logical product version like 2.1,
+// Return true if major runtime version (logical product version like 2.1,
// 3.0 or 5.x). Currently only major versions of 3 or 5 are supported.
//
bool IsRuntimeVersion(DWORD major)
_ASSERTE(readLen <= num);
Flatten(data, readLen);
-
+
ExtOut("%s", data.GetPtr());
}
}
ExtOut("<Invalid Object>");
return;
}
-
+
strobjInfo stInfo { 0, 0 };
if (MOVE(stInfo, obj) != S_OK)
{
ExtOut ("<String is invalid or too large to print>\n");
return;
}
-
+
ArrayHolder<WCHAR> pwszBuf = new WCHAR[stInfo.m_StringLength+1];
if (pwszBuf == NULL)
{
return;
}
-
+
DWORD_PTR dwAddr = (DWORD_PTR)pwszBuf.GetPtr();
if (g_sos->GetObjectStringData(TO_CDADDR(obj), stInfo.m_StringLength+1, pwszBuf, NULL)!=S_OK)
{
return;
}
- if (!fLiteral)
+ if (!fLiteral)
{
pwszBuf[stInfo.m_StringLength] = L'\0';
ExtOut ("%S", pwszBuf.GetPtr());
ULONG32 count = stInfo.m_StringLength;
WCHAR buffer[256];
WCHAR out[512];
- while (count)
+ while (count)
{
DWORD toRead = 255;
if (count < toRead)
bytesRead = toRead*sizeof(WCHAR);
DWORD wcharsRead = bytesRead/2;
buffer[wcharsRead] = L'\0';
-
+
ULONG j,k=0;
- for (j = 0; j < wcharsRead; j ++)
+ for (j = 0; j < wcharsRead; j ++)
{
if (_iswprint (buffer[j])) {
out[k] = buffer[j];
{
__int64 value = 0;
unsigned char nCount = 0;
-
+
if(ptr==NULL)
return 0;
ptr = ptr + 2;
}
- while (1) {
+ while (1) {
char digit;
-
+
if (isdigit(*ptr)) {
digit = *ptr - '0';
} else if (isalpha(*ptr)) {
if (nCount>15) {
return _UI64_MAX; // would be an overflow
}
-
- value = value << 4;
+
+ value = value << 4;
value |= digit;
ptr++;
nCount++;
}
-
- return value;
+
+ return value;
}
#endif // _TARGET_WIN64_
BOOL GetValueForCMD (const char *ptr, const char *end, ARGTYPE type, size_t *value)
-{
+{
if (type == COSTRING) {
// Allocate memory for the length of the string. Whitespace terminates
- // User must free the string data.
+ // User must free the string data.
char *pszValue = NULL;
- size_t dwSize = (end - ptr);
+ size_t dwSize = (end - ptr);
pszValue= new char[dwSize+1];
if (pszValue == NULL)
{
return FALSE;
}
strncpy_s(pszValue,dwSize+1,ptr,dwSize); // _TRUNCATE
- *value = (size_t) pszValue;
+ *value = (size_t) pszValue;
} else {
char *last;
if (type == COHEX) {
*value = strtoul(ptr,&last,16);
#endif
}
- else {
+ else {
#ifdef _TARGET_WIN64_
*value = _atoi64(ptr);
#else
{
if (IsInterrupt())
return FALSE;
-
+
option[n].hasSeen = FALSE;
}
{
if (IsInterrupt())
return FALSE;
-
+
// skip any space
if (isspace (ptr[0])) {
while (isspace (ptr[0]))
{
if (IsInterrupt())
return FALSE;
-
+
ptr ++;
}
-
+
continue;
}
// allow spaces to exist in the string.
BOOL bQuotedArg = FALSE;
if (ptr[0] == '\'' && ptr[1] != '-')
- {
+ {
bQuotedArg = TRUE;
// skip quote
ptr++;
end++;
-
+
while (end[0] != '\'' && end[0] != '\0')
{
if (IsInterrupt())
return FALSE;
-
+
end ++;
}
if (end[0] != '\'')
{
if (IsInterrupt())
return FALSE;
-
+
end ++;
}
}
ExtOut ("Incorrect argument: %s\n", ptr);
return FALSE;
}
-
+
size_t value;
if (!GetValueForCMD (ptr,end,arg[*nArg].type,&value)) {
*(char *)end = '\0';
value = (size_t)GetExpression (ptr);
*(char *)end = oldChar;
-
+
/*
It is silly to do this, what if 0 is a valid expression for
the command?
-
+
if (value == 0) {
ExtOut ("Invalid argument: %s\n", ptr);
return FALSE;
{
if (IsInterrupt())
return FALSE;
-
+
if (_stricmp (buffer, option[n].name) == 0) {
if (option[n].hasSeen) {
ExtOut ("Invalid option: option specified multiple times: %s\n", buffer);
{
if (IsInterrupt())
return FALSE;
-
+
ptr ++;
}
}
{
if (IsInterrupt())
return FALSE;
-
+
end ++;
}
}
/// <summary>
-/// Loads the runtime module symbols for the commands like dumplog that
-/// lookup runtime symbols. This is done on-demand because it takes a
+/// Loads the runtime module symbols for the commands like dumplog that
+/// lookup runtime symbols. This is done on-demand because it takes a
/// long time under windbg/cdb and not needed for most commands.
/// </summary>
void LoadRuntimeSymbols()
/**********************************************************************\
* Routine Description: *
* *
-* This function is called to find out if runtime is server build *
+* This function is called to find out if runtime is server build *
* *
\**********************************************************************/
BOOL InitializeHeapData()
{
if (g_pHeapData == NULL)
- {
+ {
if (g_HeapData.Request(g_sos) != S_OK)
{
return FALSE;
return TRUE;
}
-BOOL IsServerBuild()
+BOOL IsServerBuild()
{
return InitializeHeapData() ? g_pHeapData->bServerMode : FALSE;
}
void GetAllocContextPtrs(AllocInfo *pallocInfo)
{
- // gets the allocation contexts for all threads. This provides information about how much of
- // the current allocation quantum has been allocated and the heap to which the quantum belongs.
+ // gets the allocation contexts for all threads. This provides information about how much of
+ // the current allocation quantum has been allocated and the heap to which the quantum belongs.
// The allocation quantum is a fixed size chunk of zeroed memory from which allocations will come
- // until it's filled. Each managed thread has its own allocation context.
-
+ // until it's filled. Each managed thread has its own allocation context.
+
pallocInfo->num = 0;
- pallocInfo->array = NULL;
-
+ pallocInfo->array = NULL;
+
// get the thread store (See code:ClrDataAccess::RequestThreadStoreData for details)
DacpThreadStoreData ThreadStore;
if ( ThreadStore.Request(g_sos) != S_OK)
if (Thread.allocContextPtr != 0)
{
- // get a list of all the allocation contexts
- int j;
+ // get a list of all the allocation contexts
+ int j;
for (j = 0; j < pallocInfo->num; j ++)
{
if (pallocInfo->array[j].alloc_ptr == (BYTE *) Thread.allocContextPtr)
pallocInfo->array[j].alloc_limit = (BYTE *) Thread.allocContextLimit;
}
}
-
+
CurThread = Thread.nextThread;
}
}
return hr;
}
- m_cacheSize = cbBytesRead;
+ m_cacheSize = cbBytesRead;
m_cacheValid = TRUE;
}
StressLogMem::~StressLogMem ()
{
MemRange * range = list;
-
+
while (range)
{
MemRange * temp = range->next;
bool StressLogMem::Init (ULONG64 stressLogAddr, IDebugDataSpaces* memCallBack)
{
size_t ThreadStressLogAddr = NULL;
- HRESULT hr = memCallBack->ReadVirtual(UL64_TO_CDA(stressLogAddr + offsetof (StressLog, logs)),
+ HRESULT hr = memCallBack->ReadVirtual(UL64_TO_CDA(stressLogAddr + offsetof (StressLog, logs)),
&ThreadStressLogAddr, sizeof (ThreadStressLogAddr), 0);
if (hr != S_OK)
{
return false;
- }
-
- while(ThreadStressLogAddr != NULL)
+ }
+
+ while(ThreadStressLogAddr != NULL)
{
size_t ChunkListHeadAddr = NULL;
- hr = memCallBack->ReadVirtual(TO_CDADDR(ThreadStressLogAddr + ThreadStressLog::OffsetOfListHead ()),
+ hr = memCallBack->ReadVirtual(TO_CDADDR(ThreadStressLogAddr + ThreadStressLog::OffsetOfListHead ()),
&ChunkListHeadAddr, sizeof (ChunkListHeadAddr), 0);
if (hr != S_OK || ChunkListHeadAddr == NULL)
{
}
size_t StressLogChunkAddr = ChunkListHeadAddr;
-
+
do
{
AddRange (StressLogChunkAddr, sizeof (StressLogChunk));
- hr = memCallBack->ReadVirtual(TO_CDADDR(StressLogChunkAddr + offsetof (StressLogChunk, next)),
+ hr = memCallBack->ReadVirtual(TO_CDADDR(StressLogChunkAddr + offsetof (StressLogChunk, next)),
&StressLogChunkAddr, sizeof (StressLogChunkAddr), 0);
if (hr != S_OK)
{
if (StressLogChunkAddr == NULL)
{
return true;
- }
+ }
} while (StressLogChunkAddr != ChunkListHeadAddr);
- hr = memCallBack->ReadVirtual(TO_CDADDR(ThreadStressLogAddr + ThreadStressLog::OffsetOfNext ()),
+ hr = memCallBack->ReadVirtual(TO_CDADDR(ThreadStressLogAddr + ThreadStressLog::OffsetOfNext ()),
&ThreadStressLogAddr, sizeof (ThreadStressLogAddr), 0);
if (hr != S_OK)
{
return false;
- }
+ }
}
return true;
{
Clear();
mPtr = new char[size];
-
+
if (mPtr)
{
mSize = size;
}
return ret;
-}
+}
// SOS is single threaded so a global buffer doesn't need any locking
char g_printBuffer[8192];
// Because debuggers and hosts SOS runs on now output formatting always
// happens with the C++ runtime functions and not dbgeng. This means
// the special dbgeng formatting charaters are not supported: %N, %I,
-// %ma, %mu, %msa, %msu, %y, %ly and %p takes an architecture size
+// %ma, %mu, %msa, %msu, %y, %ly and %p takes an architecture size
// pointer (size_t) instead of always a 64bit one.
//---------------------------------------------------------------------
-HRESULT
+HRESULT
OutputVaList(
ULONG mask,
PCSTR format,
return E_FAIL;
}
-HRESULT
+HRESULT
ControlledOutputVaList(
ULONG outputControl,
ULONG mask,
return E_FAIL;
}
-HRESULT
+HRESULT
OutputText(
ULONG mask,
PCSTR format,
return;
va_list args;
-
+
va_start(args, format);
ExtOutIndent();
g_ExtControl->ControlledOutputVaList(DEBUG_OUTCTL_AMBIENT_DML, DEBUG_OUTPUT_NORMAL, format, args);
return;
va_list Args;
-
+
va_start(Args, Format);
ExtOutIndent();
OutputVaList(DEBUG_OUTPUT_NORMAL, Format, Args);
return;
va_list Args;
-
+
va_start(Args, Format);
OutputVaList(DEBUG_OUTPUT_WARNING, Format, Args);
va_end(Args);
void ExtErr(PCSTR Format, ...)
{
va_list Args;
-
+
va_start(Args, Format);
OutputVaList(DEBUG_OUTPUT_ERROR, Format, Args);
va_end(Args);
int GetHex(CLRDATA_ADDRESS addr, __out_ecount(len) char *out, size_t len, bool fill)
{
int count = sprintf_s(out, len, fill ? "%p" : "%x", (size_t)addr);
-
+
ConvertToLower(out, len);
-
+
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;
if (ret.IsOOM())
if (IsDMLEnabled())
{
- char hex[POINTERSIZE_BYTES*2 + 1];
- GetHex(addr, hex, _countof(hex), fill);
- sprintf_s(ret, ret.GetStrLen(), DMLFormats[type], hex, hex);
+ char hex1[POINTERSIZE_BYTES*2 + 1];
+ char hex2[POINTERSIZE_BYTES*2 + 1];
+ 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
{
- GetHex(addr, ret, ret.GetStrLen(), fill);
+ GetHex(disp, ret, ret.GetStrLen(), fill);
}
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);
CachedString ret;
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* 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);
- sprintf_s(ret, ret.GetStrLen(), DMLFormats[type], hexmt, hexaddr, hexaddr);
+ sprintf_s(ret, ret.GetStrLen(), DMLFormats[type], hexmt, a, d);
}
else
{
{
numFrameDigits = 1;
}
-
+
size_t totalStringLength = strlen(DMLFormats[type]) + _wcslen(expansionName) + numFrameDigits + _wcslen(simpleName) + 1;
if (totalStringLength > ret.GetStrLen())
{
return ret;
}
}
-
+
if (IsDMLEnabled())
{
sprintf_s(ret, ret.GetStrLen(), DMLFormats[type], expansionName, frame, simpleName);
// Code to support mapping RVAs to managed code line numbers.
//
-//
+//
// Retrieves the IXCLRDataMethodInstance* instance associated with the
// passed in native offset.
HRESULT
return (Status == S_OK || FAILED(Status)) ? Status : E_NOINTERFACE;
}
-//
-// Enumerates over the IL address map associated with the passed in
+//
+// Enumerates over the IL address map associated with the passed in
// managed method, and returns the highest non-epilog offset.
HRESULT
GetLastMethodIlOffset(
- ___in IXCLRDataMethodInstance* Method,
+ ___in IXCLRDataMethodInstance* Method,
___out PULONG32 MethodOffs)
{
HRESULT Status;
return S_OK;
}
-//
+//
// Convert a native offset (possibly already associated with a managed
// method identified by the passed in IXCLRDataMethodInstance) to a
-// triplet (ImageInfo, MethodToken, MethodOffset) that can be used to
+// triplet (ImageInfo, MethodToken, MethodOffset) that can be used to
// represent an "IL offset".
HRESULT
ConvertNativeToIlOffset(
{
case CLRDATA_IL_OFFSET_NO_MAPPING:
return E_NOINTERFACE;
-
+
case CLRDATA_IL_OFFSET_PROLOG:
// Treat all of the prologue as part of
// the first source line.
*methodOffs = 0;
break;
-
+
case CLRDATA_IL_OFFSET_EPILOG:
// Back up until we find the last real
// IL offset.
}
return count;
}
-
+
// IDiaReadExeAtOffsetCallback implementation
HRESULT __stdcall PEOffsetMemoryReader::ReadExecutableAt(DWORDLONG fileOffset, DWORD cbData, DWORD* pcbData, BYTE data[])
{
}
return count;
}
-
+
// IDiaReadExeAtOffsetCallback implementation
HRESULT __stdcall PERvaMemoryReader::ReadExecutableAtRVA(DWORD relativeVirtualAddress, DWORD cbData, DWORD* pcbData, BYTE data[])
{
frameOutput += g_mdName;
else
frameOutput += W("Frame");
-
+
frameOutput += WString(W(": ")) + Pointer(frameAddr) + W("] ");
// Print the frame's associated function info, if it has any.
}
}
}
-
+
return frameOutput;
}
ULONG linenum;
WString methodOutput;
CLRDATA_ADDRESS mdesc = 0;
-
+
if (FAILED(g_sos->GetMethodDescPtrFromIP(ip, &mdesc)))
{
methodOutput = W("<unknown>");
ULONG Index;
ULONG64 moduleBase;
if (SUCCEEDED(g_ExtSymbols->GetModuleByOffset(UL64_TO_CDA(addrInModule), 0, &Index, &moduleBase)))
- {
+ {
ArrayHolder<char> szModuleName = new char[MAX_LONGPATH+1];
if (SUCCEEDED(g_ExtSymbols->GetModuleNames(Index, moduleBase, NULL, 0, NULL, szModuleName, MAX_LONGPATH, NULL, NULL, 0, NULL)))
methodOutput += WString(W(" [")) + wszFileName + W(" @ ") + Decimal(linenum) + W("]");
}
}
-
+
return methodOutput;
}
{
if (ppRefs == NULL || pRefCnt == NULL)
return E_POINTER;
-
+
if (pErrCount)
*pErrCount = 0;
-
+
*pRefCnt = 0;
unsigned int count = 0;
ToRelease<ISOSStackRefEnum> pEnum;
ExtOut("Failed to enumerate GC references.\n");
return E_FAIL;
}
-
+
*ppRefs = new SOSStackRefData[count];
if (FAILED(pEnum->Next(count, *ppRefs, pRefCnt)))
{
ExtOut("Failed to enumerate GC references.\n");
return E_FAIL;
}
-
+
SOS_Assert(count == *pRefCnt);
-
+
// Enumerate errors found. Any bad HRESULT recieved while enumerating errors is NOT a fatal error.
// Hence we return S_FALSE if we encounter one.
-
+
if (ppErrors && pErrCount)
{
ToRelease<ISOSStackRefErrorEnum> pErrors;
ExtOut("Failed to enumerate GC reference errors.\n");
return S_FALSE;
}
-
+
if (FAILED(pErrors->GetCount(&count)))
{
ExtOut("Failed to enumerate GC reference errors.\n");
return S_FALSE;
}
-
+
*ppErrors = new SOSStackRefError[count];
if (FAILED(pErrors->Next(count, *ppErrors, pErrCount)))
{
*pErrCount = 0;
return S_FALSE;
}
-
+
SOS_Assert(count == *pErrCount);
}
return S_OK;
#ifdef FEATURE_PAL
-struct MemoryRegion
+struct MemoryRegion
{
private:
uint64_t m_startAddress;
}
public:
- MemoryRegion(uint64_t start, uint64_t end, CLRDATA_ADDRESS peFile) :
+ MemoryRegion(uint64_t start, uint64_t end, CLRDATA_ADDRESS peFile) :
m_startAddress(start),
m_endAddress(end),
m_peFile(peFile),