#include "corhlpr.h"
#include "corhlpr.cpp"
+#include "sildasm.h"
+
+#include <functional>
+
//////////////////////////////////////////////////////////////////////////////////////////////////////////
#undef printf
#define printf ExtOut
#include "opcode.def"
};
-static ULONG position = 0;
-static BYTE *pBuffer = NULL;
-
// The UNALIGNED is because on IA64 alignment rules would prevent
// us from reading a pointer from an unaligned source.
template <typename T>
-T readData ( ) {
+T ReadData (const BYTE* const pBuffer, ULONG& position) {
T val = *((T UNALIGNED*)(pBuffer+position));
position += sizeof(T);
return val;
}
-unsigned int readOpcode()
+unsigned int ReadOpcode(const BYTE* const pBuffer, ULONG& position)
{
- unsigned int c = readData<BYTE>();
+ unsigned int c = ReadData<BYTE>(pBuffer, /* byref */position);
if (c == 0xFE)
{
- c = readData<BYTE>();
+ c = ReadData<BYTE>(pBuffer, /* byref */ position);
c |= 0x100;
}
return c;
ULONG cLen;
WCHAR szName[50];
- if(TypeFromToken(cr) == mdtTypeRef)
+ if (TypeFromToken(cr) == mdtTypeRef)
{
if (FAILED(i->GetTypeRefProps(cr, NULL, szName, 50, &cLen)))
{
StringCchCopyW(szName, COUNTOF(szName), W("<unknown type ref>"));
}
}
- else if(TypeFromToken(cr) == mdtTypeDef)
+ else if (TypeFromToken(cr) == mdtTypeDef)
{
if (FAILED(i->GetTypeDefProps(cr, szName, 49, &cLen,
- NULL, NULL)))
+ NULL, NULL)))
{
StringCchCopyW(szName, COUNTOF(szName), W("<unknown type def>"));
}
}
- else if(TypeFromToken(cr) == mdtTypeSpec)
+ else if (TypeFromToken(cr) == mdtTypeSpec)
{
CQuickBytes out;
ULONG cSig;
else
{
PrettyPrintType(sig, &out, i);
- MultiByteToWideChar (CP_ACP, 0, asString(&out), -1, szName, 50);
+ MultiByteToWideChar(CP_ACP, 0, asString(&out), -1, szName, 50);
}
}
else
{
StringCchCopyW(szName, COUNTOF(szName), W("<unknown type token>"));
}
-
+
printf("%S::%S", szName, pMemberName);
methodPrettyPrinter.HandleArguments(); // Safe to call in all cases if HandleReturnType hasn't been called. Will do nothing.
}
break;
+
+ case mdtString:
+ {
+ ULONG numChars;
+ WCHAR str[84];
+
+ if (i->GetUserString((mdString)token, str, 80, &numChars) == S_OK)
+ {
+ if (numChars < 80)
+ str[numChars] = 0;
+ wcscpy_s(&str[79], 4, W("..."));
+ WCHAR* ptr = str;
+ while (*ptr != 0) {
+ if (*ptr < 0x20 || *ptr >= 0x80) {
+ *ptr = '.';
+ }
+ ptr++;
+ }
+
+ printf("\"%S\"", str);
+ }
+ else
+ {
+ printf("STRING %x", token);
+ }
+ }
+ break;
}
}
return Status;
}
-
+
void DecodeIL(IMetaDataImport *pImport, BYTE *buffer, ULONG bufSize)
{
// First decode the header
COR_ILMETHOD *pHeader = (COR_ILMETHOD *) buffer;
COR_ILMETHOD_DECODER header(pHeader);
- // Set globals
- position = 0;
- pBuffer = (BYTE *) header.Code;
+ ULONG position = 0;
+ BYTE* pBuffer = const_cast<BYTE*>(header.Code);
UINT indentCount = 0;
ULONG endCodePosition = header.GetCodeSize();
- while(position < endCodePosition)
- {
- for (unsigned e=0;e<header.EHCount();e++)
- {
- IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehBuff;
- const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehInfo;
-
- ehInfo = header.EH->EHClause(e,&ehBuff);
- if (ehInfo->TryOffset == position)
- {
- printf ("%*s.try\n%*s{\n", indentCount, "", indentCount, "");
- indentCount+=2;
- }
- else if ((ehInfo->TryOffset + ehInfo->TryLength) == position)
- {
- indentCount-=2;
- printf("%*s} // end .try\n", indentCount, "");
- }
- if (ehInfo->HandlerOffset == position)
- {
- if (ehInfo->Flags == COR_ILEXCEPTION_CLAUSE_FINALLY)
- printf("%*s.finally\n%*s{\n", indentCount, "", indentCount, "");
- else
- printf("%*s.catch\n%*s{\n", indentCount, "", indentCount, "");
+ while (position < endCodePosition)
+ {
+ std::tuple<ULONG, UINT> r = DecodeILAtPosition(
+ pImport, pBuffer, bufSize,
+ position, indentCount, header);
+ position = std::get<0>(r);
+ indentCount = std::get<1>(r);
+ printf("\n");
+ }
+}
- indentCount+=2;
- }
- else if ((ehInfo->HandlerOffset + ehInfo->HandlerLength) == position)
- {
- indentCount-=2;
-
- if (ehInfo->Flags == COR_ILEXCEPTION_CLAUSE_FINALLY)
- printf("%*s} // end .finally\n", indentCount, "");
- else
- printf("%*s} // end .catch\n", indentCount, "");
- }
- }
-
- printf("%*sIL_%04x: ", indentCount, "", position);
- unsigned int c = readOpcode();
- OpCode opcode = opcodes[c];
- printf("%s ", opcode.name);
+std::tuple<ULONG, UINT> DecodeILAtPosition(
+ IMetaDataImport *pImport, BYTE *pBuffer, ULONG bufSize,
+ ULONG position, UINT indentCount, COR_ILMETHOD_DECODER& header)
+{
+ for (unsigned e=0;e<header.EHCount();e++)
+ {
+ IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehBuff;
+ const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehInfo;
- switch(opcode.args)
- {
- case InlineNone: break;
-
- case ShortInlineVar:
- printf("VAR OR ARG %d",readData<BYTE>()); break;
- case InlineVar:
- printf("VAR OR ARG %d",readData<WORD>()); break;
- case InlineI:
- printf("%d",readData<LONG>());
- break;
- case InlineR:
- printf("%f",readData<double>());
- break;
- case InlineBrTarget:
- printf("IL_%04x",readData<LONG>() + position); break;
- case ShortInlineBrTarget:
- printf("IL_%04x",readData<BYTE>() + position); break;
- case InlineI8:
- printf("%ld", readData<__int64>()); break;
-
- case InlineMethod:
- case InlineField:
- case InlineType:
- case InlineTok:
- case InlineSig:
+ ehInfo = header.EH->EHClause(e,&ehBuff);
+ if (ehInfo->TryOffset == position)
{
- LONG l = readData<LONG>();
- if (pImport != NULL)
- {
- DisassembleToken(pImport, l);
- }
- else
- {
- printf("TOKEN %x", l);
- }
- break;
+ printf ("%*s.try\n%*s{\n", indentCount, "", indentCount, "");
+ indentCount+=2;
}
-
- case InlineString:
+ else if ((ehInfo->TryOffset + ehInfo->TryLength) == position)
{
- LONG l = readData<LONG>();
+ indentCount-=2;
+ printf("%*s} // end .try\n", indentCount, "");
+ }
- ULONG numChars;
- WCHAR str[84];
+ if (ehInfo->HandlerOffset == position)
+ {
+ if (ehInfo->Flags == COR_ILEXCEPTION_CLAUSE_FINALLY)
+ printf("%*s.finally\n%*s{\n", indentCount, "", indentCount, "");
+ else
+ printf("%*s.catch\n%*s{\n", indentCount, "", indentCount, "");
- if ((pImport != NULL) && (pImport->GetUserString((mdString) l, str, 80, &numChars) == S_OK))
- {
- if (numChars < 80)
- str[numChars] = 0;
- wcscpy_s(&str[79], 4, W("..."));
- WCHAR* ptr = str;
- while(*ptr != 0) {
- if (*ptr < 0x20 || * ptr >= 0x80) {
- *ptr = '.';
- }
- ptr++;
- }
+ indentCount+=2;
+ }
+ else if ((ehInfo->HandlerOffset + ehInfo->HandlerLength) == position)
+ {
+ indentCount-=2;
- printf("\"%S\"", str);
- }
+ if (ehInfo->Flags == COR_ILEXCEPTION_CLAUSE_FINALLY)
+ printf("%*s} // end .finally\n", indentCount, "");
else
- {
- printf("STRING %x", l);
- }
- break;
+ printf("%*s} // end .catch\n", indentCount, "");
}
-
- case InlineSwitch:
+ }
+ std::function<void(DWORD)> func = [&pImport](DWORD l) {
+ if (pImport != NULL)
{
- LONG cases = readData<LONG>();
- LONG *pArray = new LONG[cases];
- LONG i=0;
- for(i=0;i<cases;i++)
- {
- pArray[i] = readData<LONG>();
- }
- printf("(");
- for(i=0;i<cases;i++)
- {
- if (i != 0)
- printf(", ");
- printf("IL_%04x",pArray[i] + position);
- }
- printf(")");
- delete [] pArray;
- break;
+ DisassembleToken(pImport, l);
}
- case ShortInlineI:
- printf("%d", readData<BYTE>()); break;
- case ShortInlineR:
- printf("%f", readData<float>()); break;
- default: printf("Error, unexpected opcode type\n"); break;
+ else
+ {
+ printf("TOKEN %x", l);
}
+ };
+ position = DisplayILOperation(indentCount, pBuffer, position, func);
+ return std::make_tuple(position, indentCount);
+}
- printf("\n");
+ULONG DisplayILOperation(const UINT indentCount, BYTE *pBuffer, ULONG position, std::function<void(DWORD)>& disassembleTokenFunc)
+{
+ printf("%*sIL_%04x: ", indentCount, "", position);
+ unsigned int c = ReadOpcode(pBuffer, position);
+ OpCode opcode = opcodes[c];
+ printf("%s ", opcode.name);
+
+ switch (opcode.args)
+ {
+ case InlineNone: break;
+
+ case ShortInlineVar:
+ printf("VAR OR ARG %d", ReadData<BYTE>(pBuffer, /* byref */ position)); break;
+ case InlineVar:
+ printf("VAR OR ARG %d", ReadData<WORD>(pBuffer, /* byref */ position)); break;
+ case InlineI:
+ printf("%d", ReadData<LONG>(pBuffer, /* byref */ position));
+ break;
+ case InlineR:
+ printf("%f", ReadData<double>(pBuffer, /* byref */ position));
+ break;
+ case InlineBrTarget:
+ printf("IL_%04x", ReadData<LONG>(pBuffer, /* byref */ position) + position); break;
+ case ShortInlineBrTarget:
+ printf("IL_%04x", ReadData<BYTE>(pBuffer, /* byref */ position) + position); break;
+ case InlineI8:
+ printf("%ld", ReadData<__int64>(pBuffer, /* byref */ position)); break;
+
+ case InlineMethod:
+ case InlineField:
+ case InlineType:
+ case InlineTok:
+ case InlineSig:
+ case InlineString:
+ {
+ LONG l = ReadData<LONG>(pBuffer, /* byref */ position);
+ disassembleTokenFunc(l);
+ break;
+ }
+
+ case InlineSwitch:
+ {
+ LONG cases = ReadData<LONG>(pBuffer, /* byref */ position);
+ LONG* pArray = new LONG[cases];
+ LONG i = 0;
+ for (i = 0;i<cases;i++)
+ {
+ pArray[i] = ReadData<LONG>(pBuffer, /* byref */ position);
+ }
+ printf("(");
+ for (i = 0;i<cases;i++)
+ {
+ if (i != 0)
+ printf(", ");
+ printf("IL_%04x", pArray[i] + position);
+ }
+ printf(")");
+ delete[] pArray;
+ break;
}
+ case ShortInlineI:
+ printf("%d", ReadData<BYTE>(pBuffer, /* byref */ position)); break;
+ case ShortInlineR:
+ printf("%f", ReadData<float>(pBuffer, /* byref */ position)); break;
+ default: printf("Error, unexpected opcode type\n"); break;
+ }
+ return position;
}
DWORD_PTR GetObj(DacpObjectData& tokenArray, UINT item)
void DecodeDynamicIL(BYTE *data, ULONG Size, DacpObjectData& tokenArray)
{
// There is no header for this dynamic guy.
- // Set globals
- position = 0;
- pBuffer = data;
+ ULONG position = 0;
+ BYTE *pBuffer = data;
// At this time no exception information will be displayed (fix soon)
UINT indentCount = 0;
ULONG endCodePosition = Size;
while(position < endCodePosition)
- {
- printf("%*sIL_%04x: ", indentCount, "", position);
- unsigned int c = readOpcode();
- OpCode opcode = opcodes[c];
- printf("%s ", opcode.name);
-
- switch(opcode.args)
- {
- case InlineNone: break;
-
- case ShortInlineVar:
- printf("VAR OR ARG %d",readData<BYTE>()); break;
- case InlineVar:
- printf("VAR OR ARG %d",readData<WORD>()); break;
- case InlineI:
- printf("%d",readData<LONG>());
- break;
- case InlineR:
- printf("%f",readData<double>());
- break;
- case InlineBrTarget:
- printf("IL_%04x",readData<LONG>() + position); break;
- case ShortInlineBrTarget:
- printf("IL_%04x",readData<BYTE>() + position); break;
- case InlineI8:
- printf("%ld", readData<__int64>()); break;
-
- case InlineMethod:
- case InlineField:
- case InlineType:
- case InlineTok:
- case InlineSig:
- case InlineString:
- {
- LONG l = readData<LONG>();
- DisassembleToken(tokenArray, l);
- break;
- }
-
- case InlineSwitch:
- {
- LONG cases = readData<LONG>();
- LONG *pArray = new LONG[cases];
- LONG i=0;
- for(i=0;i<cases;i++)
- {
- pArray[i] = readData<LONG>();
- }
- printf("(");
- for(i=0;i<cases;i++)
- {
- if (i != 0)
- printf(", ");
- printf("IL_%04x",pArray[i] + position);
- }
- printf(")");
- delete [] pArray;
- break;
- }
- case ShortInlineI:
- printf("%d", readData<BYTE>()); break;
- case ShortInlineR:
- printf("%f", readData<float>()); break;
- default: printf("Error, unexpected opcode type\n"); break;
- }
-
+ {
+ std::function<void(DWORD)> func = [&tokenArray](DWORD l) {
+ DisassembleToken(tokenArray, l);
+ };
+ position = DisplayILOperation(indentCount, pBuffer, position, func);
printf("\n");
}
}
out->ReSize(oldSize + 1);
char* cur = &((char*) out->Ptr())[oldSize];
*cur = 0;
- out->ReSize(oldSize); // Don't count the null character
+ out->ReSize(oldSize); // Don't count the null character
return((char*) out->Ptr());
}
break;
}
- case ELEMENT_TYPE_PINNED :
+ case ELEMENT_TYPE_PINNED:
str = " pinned"; goto MODIFIER;
case ELEMENT_TYPE_PTR :
str = "*"; goto MODIFIER;
const char* PrettyPrintClass(
CQuickBytes *out, // where to put the pretty printed string
- mdToken tk, // The class token to look up
+ mdToken tk, // The class token to look up
IMetaDataImport *pIMD, // ptr to IMetaDataImport class with ComSig
DWORD formatFlags /*= formatILDasm*/)
{
case mdtAssemblyRef:
{
- LPCSTR szName = NULL;
+ LPCSTR szName = NULL;
ULONG unused;
ToRelease<IMetaDataAssemblyImport> pAsmImport;
if (SUCCEEDED(pIMD->QueryInterface(IID_IMetaDataAssemblyImport, (LPVOID *)&pAsmImport)))
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
+#include <stdexcept>
+#include <deque>
#include "strike.h"
#include "sos.h"
#include <set>
#include <vector>
#include <map>
+#include <tuple>
+#include <memory>
+#include <functional>
BOOL CallStatus;
BOOL ControlC = FALSE;
return bRet;
}
+typedef std::tuple<TADDR, IMetaDataImport* > GetILAddressResult;
+GetILAddressResult GetILAddress(const DacpMethodDescData& MethodDescData);
+
+/**********************************************************************\
+* Routine Description: *
+* *
+* Displays the Microsoft intermediate language (MSIL) that is *
+* associated with a managed method. *
+\**********************************************************************/
DECLARE_API(DumpIL)
{
INIT_API();
}
else
{
- TADDR ilAddr = NULL;
- struct DacpProfilerILData ilData;
- ReleaseHolder<ISOSDacInterface7> sos7;
- if (SUCCEEDED(g_sos->QueryInterface(__uuidof(ISOSDacInterface7), &sos7)) &&
- SUCCEEDED(sos7->GetProfilerModifiedILInformation(MethodDescData.MethodDescPtr, &ilData)))
- {
- if (ilData.type == DacpProfilerILData::ILModified)
- {
- ExtOut("Found profiler modified IL\n");
- ilAddr = TO_TADDR(ilData.il);
- }
- }
-
- // Factor this so that it returns a map from IL offset to the textual representation of the decoding
- // to be consumed by !u -il
- // The disassemble function can give a MethodDescData as well as the set of keys IL offsets
-
- // This is not a dynamic method, print the IL for it.
- // Get the module
- DacpModuleData dmd;
- if (dmd.Request(g_sos, MethodDescData.ModulePtr) != S_OK)
+ GetILAddressResult result = GetILAddress(MethodDescData);
+ if (std::get<0>(result) == NULL)
{
- ExtOut("Unable to get module\n");
- return Status;
- }
-
- ToRelease<IMetaDataImport> pImport = MDImportForModule(&dmd);
- if (pImport == NULL)
- {
- ExtOut("bad import\n");
- return Status;
- }
-
- if (ilAddr == NULL)
- {
- ULONG pRva;
- DWORD dwFlags;
- if (pImport->GetRVA(MethodDescData.MDToken, &pRva, &dwFlags) != S_OK)
- {
- ExtOut("error in import\n");
- return Status;
- }
-
- CLRDATA_ADDRESS ilAddrClr;
- if (g_sos->GetILForModule(MethodDescData.ModulePtr, pRva, &ilAddrClr) != S_OK)
- {
- ExtOut("FindIL failed\n");
- return Status;
- }
-
- ilAddr = TO_TADDR(ilAddrClr);
- }
-
- if (ilAddr == NULL)
- {
- ExtOut("Unkown error in reading function IL\n");
+ ExtOut("ilAddr is %p\n", SOS_PTR(std::get<0>(result)));
return E_FAIL;
}
+ ExtOut("ilAddr is %p pImport is %p\n", SOS_PTR(std::get<0>(result)), SOS_PTR(std::get<1>(result)));
+ TADDR ilAddr = std::get<0>(result);
+ ToRelease<IMetaDataImport> pImport(std::get<1>(result));
IfFailRet(DecodeILFromAddress(pImport, ilAddr));
}
}
#include "sos_stacktrace.h"
+#include "sildasm.h"
+
class StringOutput
{
public:
void ExtOutStateMachineFields(AsyncRecord& ar)
{
- DacpMethodTableData mtabledata;
- DacpMethodTableFieldData vMethodTableFields;
- if (mtabledata.Request(g_sos, ar.StateMachineMT) == S_OK &&
- vMethodTableFields.Request(g_sos, ar.StateMachineMT) == S_OK &&
- vMethodTableFields.wNumInstanceFields + vMethodTableFields.wNumStaticFields > 0)
- {
- DisplayFields(ar.StateMachineMT, &mtabledata, &vMethodTableFields, (DWORD_PTR)ar.StateMachineAddr, TRUE, ar.IsValueType);
- }
+ DacpMethodTableData mtabledata;
+ DacpMethodTableFieldData vMethodTableFields;
+ if (mtabledata.Request(g_sos, ar.StateMachineMT) == S_OK &&
+ vMethodTableFields.Request(g_sos, ar.StateMachineMT) == S_OK &&
+ vMethodTableFields.wNumInstanceFields + vMethodTableFields.wNumStaticFields > 0)
+ {
+ DisplayFields(ar.StateMachineMT, &mtabledata, &vMethodTableFields, (DWORD_PTR)ar.StateMachineAddr, TRUE, ar.IsValueType);
+ }
}
void FindStateMachineTypes(DWORD_PTR* corelibModule, mdTypeDef* stateMachineBox, mdTypeDef* debugStateMachineBox, mdTypeDef* task)
sos::MethodTable contMT = TO_TADDR(contAsyncRecord->second.StateMachineMT);
if (contAsyncRecord->second.IsStateMachine) ExtOut("(%d) ", contAsyncRecord->second.StateValue);
ExtOut("%S\n", contMT.GetName());
- if (contAsyncRecord->second.IsStateMachine && dumpFields) ExtOutStateMachineFields(contAsyncRecord->second);
- }
+ if (contAsyncRecord->second.IsStateMachine && dumpFields) ExtOutStateMachineFields(contAsyncRecord->second);
+ }
else
{
ExtOut("%S\n", cont.GetTypeName());
___in ULONG64 NativeOffset,
___out IXCLRDataMethodInstance** Method);
+typedef std::tuple<DacpMethodDescData, DacpCodeHeaderData, HRESULT> ExtractionCodeHeaderResult;
+
+ExtractionCodeHeaderResult extractCodeHeaderData(DWORD_PTR methodDesc, DWORD_PTR dwStartAddr);
+HRESULT displayGcInfo(BOOL fWithGCInfo, const DacpCodeHeaderData& codeHeaderData);
+HRESULT GetIntermediateLangMap(BOOL bIL, const DacpCodeHeaderData& codeHeaderData,
+ std::unique_ptr<CLRDATA_IL_ADDRESS_MAP[]>& map,
+ ULONG32& mapCount,
+ BOOL dumpMap);
+
+GetILAddressResult GetILAddress(const DacpMethodDescData& MethodDescData)
+{
+ GetILAddressResult error = std::make_tuple(NULL, nullptr);
+ TADDR ilAddr = NULL;
+ struct DacpProfilerILData ilData;
+ ReleaseHolder<ISOSDacInterface7> sos7;
+ if (SUCCEEDED(g_sos->QueryInterface(__uuidof(ISOSDacInterface7), &sos7)) &&
+ SUCCEEDED(sos7->GetProfilerModifiedILInformation(MethodDescData.MethodDescPtr, &ilData)))
+ {
+ if (ilData.type == DacpProfilerILData::ILModified)
+ {
+ ExtOut("Found profiler modified IL\n");
+ ilAddr = TO_TADDR(ilData.il);
+ }
+ }
+
+ // Factor this so that it returns a map from IL offset to the textual representation of the decoding
+ // to be consumed by !u -il
+ // The disassemble function can give a MethodDescData as well as the set of keys IL offsets
+
+ // This is not a dynamic method, print the IL for it.
+ // Get the module
+ DacpModuleData dmd;
+ if (dmd.Request(g_sos, MethodDescData.ModulePtr) != S_OK)
+ {
+ ExtOut("Unable to get module\n");
+ return error;
+ }
+
+ ToRelease<IMetaDataImport> pImport(MDImportForModule(&dmd));
+ if (pImport == NULL)
+ {
+ ExtOut("bad import\n");
+ return error;
+ }
+
+ if (ilAddr == NULL)
+ {
+ ULONG pRva;
+ DWORD dwFlags;
+ if (pImport->GetRVA(MethodDescData.MDToken, &pRva, &dwFlags) != S_OK)
+ {
+ ExtOut("error in import\n");
+ return error;
+ }
+
+ CLRDATA_ADDRESS ilAddrClr;
+ if (g_sos->GetILForModule(MethodDescData.ModulePtr, pRva, &ilAddrClr) != S_OK)
+ {
+ ExtOut("FindIL failed\n");
+ return error;
+ }
+
+ ilAddr = TO_TADDR(ilAddrClr);
+ }
+
+ if (ilAddr == NULL)
+ {
+ ExtOut("Unknown error in reading function IL\n");
+ return error;
+ }
+ GetILAddressResult result = std::make_tuple(ilAddr, pImport.Detach());
+ return result;
+}
+
/**********************************************************************\
* Routine Description: *
* *
}
}
+ ExtractionCodeHeaderResult p = extractCodeHeaderData(methodDesc, dwStartAddr);
+ Status = std::get<2>(p);
+ if (Status != S_OK)
+ {
+ return Status;
+ }
+
+ NameForMD_s(methodDesc, g_mdName, mdNameLen);
+ ExtOut("%S\n", g_mdName);
+
+ DacpMethodDescData& MethodDescData = std::get<0>(p);
+ DacpCodeHeaderData& codeHeaderData = std::get<1>(p);
+ std::unique_ptr<CLRDATA_IL_ADDRESS_MAP[]> map(nullptr);
+ ULONG32 mapCount = 0;
+ Status = GetIntermediateLangMap(bIL, codeHeaderData, map /*out*/, mapCount /* out */, false);
+ if (Status != S_OK)
+ {
+ return Status;
+ }
+
+ // ///////////////////////////////////////////////////////////////////////////
+ // This can be reused with sildasm but kept as-is largely since it just
+ // works so it can be fixed later.
+ // ///////////////////////////////////////////////////////////////////////////
+
+ if (MethodDescData.bIsDynamic && MethodDescData.managedDynamicMethodObject)
+ {
+ ExtOut("Can only work with dynamic not implemented\n");
+ return Status;
+ }
+
+ GetILAddressResult result = GetILAddress(MethodDescData);
+ if (std::get<0>(result) == NULL)
+ {
+ ExtOut("ilAddr is %p\n", SOS_PTR(std::get<0>(result)));
+ return E_FAIL;
+ }
+ ExtOut("ilAddr is %p pImport is %p\n", SOS_PTR(std::get<0>(result)), SOS_PTR(std::get<1>(result)));
+ TADDR ilAddr = std::get<0>(result);
+ ToRelease<IMetaDataImport> pImport(std::get<1>(result));
+
+ /// Taken from DecodeILFromAddress(IMetaDataImport *pImport, TADDR ilAddr)
+ ULONG Size = GetILSize(ilAddr);
+ if (Size == 0)
+ {
+ ExtOut("error decoding IL\n");
+ return Status;
+ }
+ // Read the memory into a local buffer
+ ArrayHolder<BYTE> pArray = new BYTE[Size];
+ Status = g_ExtData->ReadVirtual(TO_CDADDR(ilAddr), pArray, Size, NULL);
+ if (Status != S_OK)
+ {
+ ExtOut("Failed to read memory\n");
+ return Status;
+ }
+ /// Taken from DecodeIL(pImport, pArray, Size);
+ // First decode the header
+ BYTE *buffer = pArray;
+ ULONG bufSize = Size;
+ COR_ILMETHOD *pHeader = (COR_ILMETHOD *) buffer;
+ COR_ILMETHOD_DECODER header(pHeader);
+ ULONG position = 0;
+ BYTE* pBuffer = const_cast<BYTE*>(header.Code);
+ UINT indentCount = 0;
+ ULONG endCodePosition = header.GetCodeSize();
+ struct ILLocationRange {
+ ULONG mStartPosition;
+ ULONG mEndPosition;
+ BYTE* mStartAddress;
+ BYTE* mEndAddress;
+ };
+ std::deque<ILLocationRange> ilCodePositions;
+
+ if (mapCount > 0)
+ {
+ while (position < endCodePosition)
+ {
+ ULONG mapIndex = 0;
+ do
+ {
+ while ((mapIndex < mapCount) && (position != map[mapIndex].ilOffset))
+ {
+ ++mapIndex;
+ }
+ if (map[mapIndex].endAddress > map[mapIndex].startAddress)
+ {
+ break;
+ }
+ ++mapIndex;
+ } while (mapIndex < mapCount);
+ std::tuple<ULONG, UINT> r = DecodeILAtPosition(
+ pImport, pBuffer, bufSize,
+ position, indentCount, header);
+ ExtOut("\n");
+ if (mapIndex < mapCount)
+ {
+ ILLocationRange entry = {
+ position,
+ std::get<0>(r) - 1,
+ (BYTE*)map[mapIndex].startAddress,
+ (BYTE*)map[mapIndex].endAddress
+ };
+ ilCodePositions.push_back(std::move(entry));
+ }
+ else
+ {
+ if (!ilCodePositions.empty())
+ {
+ auto& entry = ilCodePositions.back();
+ entry.mEndPosition = position;
+ }
+ }
+ position = std::get<0>(r);
+ indentCount = std::get<1>(r);
+ }
+ }
+
+ position = 0;
+ indentCount = 0;
+ std::function<void(ULONG*, UINT*, BYTE*)> displayILFun =
+ [&pImport, &pBuffer, bufSize, &header, &ilCodePositions](ULONG *pPosition, UINT *pIndentCount,
+ BYTE *pIp) -> void {
+ for (auto iter = ilCodePositions.begin(); iter != ilCodePositions.end(); ++iter)
+ {
+ if ((pIp >= iter->mStartAddress) && (pIp < iter->mEndAddress))
+ {
+ ULONG position = iter->mStartPosition;
+ ULONG endPosition = iter->mEndPosition;
+ while (position <= endPosition)
+ {
+ std::tuple<ULONG, UINT> r = DecodeILAtPosition(
+ pImport, pBuffer, bufSize,
+ position, *pIndentCount, header);
+ ExtOut("\n");
+ position = std::get<0>(r);
+ *pIndentCount = std::get<1>(r);
+ }
+ ilCodePositions.erase(iter);
+ break;
+ }
+ }
+ };
+
+ if (codeHeaderData.ColdRegionStart != NULL)
+ {
+ ExtOut("Begin %p, size %x. Cold region begin %p, size %x\n",
+ SOS_PTR(codeHeaderData.MethodStart), codeHeaderData.HotRegionSize,
+ SOS_PTR(codeHeaderData.ColdRegionStart), codeHeaderData.ColdRegionSize);
+ }
+ else
+ {
+ ExtOut("Begin %p, size %x\n", SOS_PTR(codeHeaderData.MethodStart), codeHeaderData.MethodSize);
+ }
+
+ Status = displayGcInfo(fWithGCInfo, codeHeaderData);
+ if (Status != S_OK)
+ {
+ return Status;
+ }
+
+ SOSEHInfo *pInfo = NULL;
+ if (fWithEHInfo)
+ {
+ pInfo = new NOTHROW SOSEHInfo;
+ if (pInfo == NULL)
+ {
+ ReportOOM();
+ }
+ else if (g_sos->TraverseEHInfo(codeHeaderData.MethodStart, gatherEh, (LPVOID)pInfo) != S_OK)
+ {
+ ExtOut("Failed to gather EHInfo data\n");
+ delete pInfo;
+ pInfo = NULL;
+ }
+ }
+
+ if (codeHeaderData.ColdRegionStart == NULL)
+ {
+ g_targetMachine->Unassembly (
+ (DWORD_PTR) codeHeaderData.MethodStart,
+ ((DWORD_PTR)codeHeaderData.MethodStart) + codeHeaderData.MethodSize,
+ dwStartAddr,
+ (DWORD_PTR) MethodDescData.GCStressCodeCopy,
+ fWithGCInfo ? &g_gcEncodingInfo : NULL,
+ pInfo,
+ bSuppressLines,
+ bDisplayOffsets,
+ displayILFun);
+ }
+ else
+ {
+ ExtOut("Hot region:\n");
+ g_targetMachine->Unassembly (
+ (DWORD_PTR) codeHeaderData.MethodStart,
+ ((DWORD_PTR)codeHeaderData.MethodStart) + codeHeaderData.HotRegionSize,
+ dwStartAddr,
+ (DWORD_PTR) MethodDescData.GCStressCodeCopy,
+ fWithGCInfo ? &g_gcEncodingInfo : NULL,
+ pInfo,
+ bSuppressLines,
+ bDisplayOffsets,
+ displayILFun);
+
+ ExtOut("Cold region:\n");
+
+ // Displaying gcinfo for a cold region requires knowing the size of
+ // the hot region preceeding.
+ g_gcEncodingInfo.hotSizeToAdd = codeHeaderData.HotRegionSize;
+
+ g_targetMachine->Unassembly (
+ (DWORD_PTR) codeHeaderData.ColdRegionStart,
+ ((DWORD_PTR)codeHeaderData.ColdRegionStart) + codeHeaderData.ColdRegionSize,
+ dwStartAddr,
+ ((DWORD_PTR) MethodDescData.GCStressCodeCopy) + codeHeaderData.HotRegionSize,
+ fWithGCInfo ? &g_gcEncodingInfo : NULL,
+ pInfo,
+ bSuppressLines,
+ bDisplayOffsets,
+ displayILFun);
+
+ }
+
+ if (pInfo)
+ {
+ delete pInfo;
+ pInfo = NULL;
+ }
+
+ if (fWithGCInfo)
+ {
+ g_gcEncodingInfo.Deinitialize();
+ }
+
+ return Status;
+}
+
+inline ExtractionCodeHeaderResult extractCodeHeaderData(DWORD_PTR methodDesc, DWORD_PTR dwStartAddr)
+{
DacpMethodDescData MethodDescData;
- Status =
+ HRESULT Status =
g_sos->GetMethodDescData(
TO_CDADDR(methodDesc),
dwStartAddr == methodDesc ? NULL : dwStartAddr,
if (Status != S_OK)
{
ExtOut("Failed to get method desc for %p.\n", SOS_PTR(dwStartAddr));
- return Status;
- }
+ return ExtractionCodeHeaderResult(std::move(MethodDescData), DacpCodeHeaderData(), Status);
+ }
if (!MethodDescData.bHasNativeCode)
{
ExtOut("Not jitted yet\n");
- return Status;
+ return ExtractionCodeHeaderResult(std::move(MethodDescData), DacpCodeHeaderData(), S_FALSE);
}
// Get the appropriate code header. If we were passed an MD, then use
// disassemble the rejit version that the user explicitly specified with their IP.
DacpCodeHeaderData codeHeaderData;
if (codeHeaderData.Request(
- g_sos,
+ g_sos,
TO_CDADDR(
- (dwStartAddr == methodDesc) ? MethodDescData.NativeCodeAddr : dwStartAddr)
- ) != S_OK)
-
+ (dwStartAddr == methodDesc) ? MethodDescData.NativeCodeAddr : dwStartAddr)
+ ) != S_OK)
{
ExtOut("Unable to get codeHeader information\n");
- return Status;
- }
-
+ return ExtractionCodeHeaderResult(std::move(MethodDescData), DacpCodeHeaderData(), S_FALSE);
+ }
+
if (codeHeaderData.MethodStart == 0)
{
ExtOut("not a valid MethodDesc\n");
- return Status;
+ return ExtractionCodeHeaderResult(std::move(MethodDescData), DacpCodeHeaderData(), S_FALSE);
}
-
+
if (codeHeaderData.JITType == TYPE_UNKNOWN)
{
ExtOut("unknown Jit\n");
- return Status;
+ return ExtractionCodeHeaderResult(std::move(MethodDescData), DacpCodeHeaderData(), S_FALSE);
}
else if (codeHeaderData.JITType == TYPE_JIT)
{
{
ExtOut("preJIT generated code\n");
}
+ return ExtractionCodeHeaderResult(std::move(MethodDescData), std::move(codeHeaderData), S_OK);
+}
- NameForMD_s(methodDesc, g_mdName, mdNameLen);
- ExtOut("%S\n", g_mdName);
-
- if (bIL)
- {
- ToRelease<IXCLRDataMethodInstance> pMethodInst(NULL);
-
- if ((Status = GetClrMethodInstance(codeHeaderData.MethodStart, &pMethodInst)) != S_OK)
- {
- return Status;
- }
-
- ArrayHolder<CLRDATA_IL_ADDRESS_MAP> map(nullptr);
- ULONG32 mapCount = 0;
-
- if ((Status = pMethodInst->GetILAddressMap(mapCount, &mapCount, map)) != S_OK)
- {
- return Status;
- }
-
- map = new NOTHROW CLRDATA_IL_ADDRESS_MAP[mapCount];
- if (map == NULL)
- {
- ReportOOM();
- return E_OUTOFMEMORY;
- }
-
- if ((Status = pMethodInst->GetILAddressMap(mapCount, &mapCount, map)) != S_OK)
- {
- return Status;
- }
-
- for (ULONG32 i = 0; i < mapCount; i++)
- {
- // TODO: These information should be interleaved with the disassembly
- // Decoded IL can be obtained through refactoring DumpIL code.
- ExtOut("%04x %p %p\n", map[i].ilOffset, map[i].startAddress, map[i].endAddress);
- }
- }
-
- if (codeHeaderData.ColdRegionStart != NULL)
- {
- ExtOut("Begin %p, size %x. Cold region begin %p, size %x\n",
- SOS_PTR(codeHeaderData.MethodStart), codeHeaderData.HotRegionSize,
- SOS_PTR(codeHeaderData.ColdRegionStart), codeHeaderData.ColdRegionSize);
- }
- else
- {
- ExtOut("Begin %p, size %x\n", SOS_PTR(codeHeaderData.MethodStart), codeHeaderData.MethodSize);
- }
-
+HRESULT displayGcInfo(BOOL fWithGCInfo, const DacpCodeHeaderData& codeHeaderData)
+{
//
// Set up to mix gc info with the code if requested. To do this, we first generate all the textual
// gc info up front. This text is the same as the "!gcinfo" command, and looks like:
ExtOut("Could not allocate memory to read the gc info.\n");
return E_OUTOFMEMORY;
}
-
- memset (table, 0, tableSize);
+
+ memset(table, 0, tableSize);
// We avoid using move here, because we do not want to return
if (!SafeReadMemory(TO_TADDR(codeHeaderData.GCInfo), table, tableSize, NULL))
{
ExtOut("Could not read memory %p\n", SOS_PTR(codeHeaderData.GCInfo));
- return Status;
+ return ERROR_INVALID_DATA;
}
//
{
return E_OUTOFMEMORY;
}
-
+
GCInfoToken gcInfoToken = { table, GCINFO_VERSION };
g_targetMachine->DumpGCInfo(gcInfoToken, methodSize, DecodeGCTableEntry, false /*encBytes*/, false /*bPrintHeader*/);
- }
+ }
+ return S_OK;
+}
- SOSEHInfo *pInfo = NULL;
- if (fWithEHInfo)
+HRESULT GetIntermediateLangMap(BOOL bIL, const DacpCodeHeaderData& codeHeaderData,
+ std::unique_ptr<CLRDATA_IL_ADDRESS_MAP[]>& map,
+ ULONG32& mapCount,
+ BOOL dumpMap)
+{
+ HRESULT Status = S_OK;
+ if (bIL)
{
- pInfo = new NOTHROW SOSEHInfo;
- if (pInfo == NULL)
+ ToRelease<IXCLRDataMethodInstance> pMethodInst(NULL);
+
+ if ((Status = GetClrMethodInstance(codeHeaderData.MethodStart, &pMethodInst)) != S_OK)
{
- ReportOOM();
+ return Status;
}
- else if (g_sos->TraverseEHInfo(codeHeaderData.MethodStart, gatherEh, (LPVOID)pInfo) != S_OK)
+
+ if ((Status = pMethodInst->GetILAddressMap(mapCount, &mapCount, map.get())) != S_OK)
{
- ExtOut("Failed to gather EHInfo data\n");
- delete pInfo;
- pInfo = NULL;
+ return Status;
}
- }
-
- if (codeHeaderData.ColdRegionStart == NULL)
- {
- g_targetMachine->Unassembly (
- (DWORD_PTR) codeHeaderData.MethodStart,
- ((DWORD_PTR)codeHeaderData.MethodStart) + codeHeaderData.MethodSize,
- dwStartAddr,
- (DWORD_PTR) MethodDescData.GCStressCodeCopy,
- fWithGCInfo ? &g_gcEncodingInfo : NULL,
- pInfo,
- bSuppressLines,
- bDisplayOffsets
- );
- }
- else
- {
- ExtOut("Hot region:\n");
- g_targetMachine->Unassembly (
- (DWORD_PTR) codeHeaderData.MethodStart,
- ((DWORD_PTR)codeHeaderData.MethodStart) + codeHeaderData.HotRegionSize,
- dwStartAddr,
- (DWORD_PTR) MethodDescData.GCStressCodeCopy,
- fWithGCInfo ? &g_gcEncodingInfo : NULL,
- pInfo,
- bSuppressLines,
- bDisplayOffsets
- );
-
- ExtOut("Cold region:\n");
-
- // Displaying gcinfo for a cold region requires knowing the size of
- // the hot region preceeding.
- g_gcEncodingInfo.hotSizeToAdd = codeHeaderData.HotRegionSize;
- g_targetMachine->Unassembly (
- (DWORD_PTR) codeHeaderData.ColdRegionStart,
- ((DWORD_PTR)codeHeaderData.ColdRegionStart) + codeHeaderData.ColdRegionSize,
- dwStartAddr,
- ((DWORD_PTR) MethodDescData.GCStressCodeCopy) + codeHeaderData.HotRegionSize,
- fWithGCInfo ? &g_gcEncodingInfo : NULL,
- pInfo,
- bSuppressLines,
- bDisplayOffsets
- );
-
- }
+ map.reset(new NOTHROW CLRDATA_IL_ADDRESS_MAP[mapCount]);
+ if (map.get() == NULL)
+ {
+ ReportOOM();
+ return E_OUTOFMEMORY;
+ }
- if (pInfo)
- {
- delete pInfo;
- pInfo = NULL;
- }
+ if ((Status = pMethodInst->GetILAddressMap(mapCount, &mapCount, map.get())) != S_OK)
+ {
+ return Status;
+ }
- if (fWithGCInfo)
- {
- g_gcEncodingInfo.Deinitialize();
+ if (dumpMap)
+ {
+ for (ULONG32 i = 0; i < mapCount; i++)
+ {
+ // TODO: These information should be interleaved with the disassembly
+ // Decoded IL can be obtained through refactoring DumpIL code.
+ ExtOut("%04x %p %p\n", map[i].ilOffset, map[i].startAddress, map[i].endAddress);
+ }
+ }
}
-
- return Status;
+ return S_OK;
}
/**********************************************************************\