summaryrefslogtreecommitdiff
path: root/src/ildasm/dis.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ildasm/dis.cpp')
-rw-r--r--src/ildasm/dis.cpp2792
1 files changed, 2792 insertions, 0 deletions
diff --git a/src/ildasm/dis.cpp b/src/ildasm/dis.cpp
new file mode 100644
index 0000000000..ad5e5a7141
--- /dev/null
+++ b/src/ildasm/dis.cpp
@@ -0,0 +1,2792 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+// Disassembler
+//
+#include "ildasmpch.h"
+
+#include "debugmacros.h"
+#include "corpriv.h"
+#include "dasmenum.hpp"
+#include "dasmgui.h"
+#include "formattype.h"
+#include "dis.h"
+#include "resource.h"
+#include "ilformatter.h"
+#include "outstring.h"
+
+#include "ceeload.h"
+#include "dynamicarray.h"
+extern PELoader * g_pPELoader;
+#include <corsym.h>
+
+extern ISymUnmanagedReader* g_pSymReader;
+extern BOOL g_fDumpAsmCode;
+extern char g_szAsmCodeIndent[];
+extern BOOL g_fShowBytes;
+extern BOOL g_fShowSource;
+extern BOOL g_fInsertSourceLines;
+extern BOOL g_fTryInCode;
+extern BOOL g_fQuoteAllNames;
+extern BOOL g_fDumpTokens;
+extern DynamicArray<__int32> *g_pPtrTags; //to keep track of all "ldptr"
+extern DynamicArray<DWORD> *g_pPtrSize; //to keep track of all "ldptr"
+extern int g_iPtrCount;
+static BOOL ConvToLiteral(__inout __nullterminated char* retBuff, const WCHAR* str, int cbStr);
+extern DWORD g_Mode;
+extern unsigned g_uConsoleCP;
+
+#define PADDING 28
+
+extern BOOL g_fThisIsInstanceMethod;
+extern unsigned g_uCodePage;
+extern HANDLE hConsoleOut;
+extern HANDLE hConsoleErr;
+// globals for source file info
+ULONG_PTR ulWasFileToken = 0xFFFFFFFF;
+GUID guidWasLang={0}, guidWasLangVendor={0},guidWasDoc={0};
+WCHAR wzWasFileName[2048];
+ULONG ulWasLine = 0;
+FILE* pFile=NULL;
+BOOL bIsNewFile = TRUE;
+WCHAR wzUniBuf[UNIBUF_SIZE];
+char szString[SZSTRING_SIZE];
+//-----------------------------------
+struct LexScope
+{
+ DWORD dwStart;
+ DWORD dwEnd;
+ ISymUnmanagedScope* pISymScope;
+ DWORD dwZOrder;
+ inline bool IsOpen() { return (dwZOrder != 0); };
+ inline bool Covers(DWORD dwOffset) { return ((dwStart <= dwOffset) && (dwOffset < dwEnd)); };
+};
+//-----------------------------------
+
+OPCODE DecodeOpcode(const BYTE *pCode, DWORD *pdwLen)
+{
+ OPCODE opcode;
+
+ *pdwLen = 1;
+ opcode = OPCODE(pCode[0]);
+ switch(opcode) {
+ case CEE_PREFIX1:
+ opcode = OPCODE(pCode[1] + 256);
+ if (opcode < 0 || opcode >= CEE_COUNT)
+ opcode = CEE_COUNT;
+ *pdwLen = 2;
+ break;
+ case CEE_PREFIXREF:
+ case CEE_PREFIX2:
+ case CEE_PREFIX3:
+ case CEE_PREFIX4:
+ case CEE_PREFIX5:
+ case CEE_PREFIX6:
+ case CEE_PREFIX7:
+ *pdwLen = 3;
+ return CEE_COUNT;
+ default:
+ break;
+ }
+ return opcode;
+}
+//------------------------------------------------------------------
+WCHAR* UtfToUnicode(__in __nullterminated const char* sz)
+{
+ WCHAR* wz = wzUniBuf;
+ if (WszMultiByteToWideChar(CP_UTF8,0,sz,-1,wz,UNIBUF_SIZE/2) == 0)
+ {
+ wz[UNIBUF_SIZE/2 - 1] = 0;
+ }
+ return wz;
+}
+char* UnicodeToAnsi(__in __nullterminated const WCHAR* wz)
+{
+ char* sz = (char*)(&wzUniBuf[UNIBUF_SIZE/2]);
+ if (WszWideCharToMultiByte(g_uConsoleCP,0,wz,-1,sz,UNIBUF_SIZE,NULL,NULL) == 0)
+ {
+ sz[UNIBUF_SIZE - 1] = 0;
+ }
+ return sz;
+}
+WCHAR* AnsiToUnicode(__in __nullterminated const char* sz)
+{
+ WCHAR* wz = wzUniBuf;
+ if (WszMultiByteToWideChar(g_uConsoleCP,0,sz,-1,wz,UNIBUF_SIZE/2) == 0)
+ {
+ wz[UNIBUF_SIZE/2 - 1] = 0;
+ }
+ return wz;
+}
+char* UnicodeToUtf(__in __nullterminated const WCHAR* wz)
+{
+ char* sz = (char*)(&wzUniBuf[UNIBUF_SIZE/2]);
+ if (WszWideCharToMultiByte(CP_UTF8,0,wz,-1,sz,UNIBUF_SIZE,NULL,NULL) == 0)
+ {
+ sz[UNIBUF_SIZE - 1] = 0;
+ }
+ return sz;
+}
+char* AnsiToUtf(__in __nullterminated const char* sz) { return UnicodeToUtf(AnsiToUnicode(sz));}
+
+static void UnicodeToConsoleOrMsgBox(__in __nullterminated const WCHAR* wz)
+{
+#ifndef FEATURE_CORECLR
+ if (g_Mode & MODE_GUI)
+ WszMessageBox(NULL,wz,RstrW(IDS_ERRORCAPTION),MB_OK|MB_ICONERROR|GetDasmMBRTLStyle());
+ else
+#endif
+ {
+ //DWORD dw;
+ //char* sz = UnicodeToAnsi(wz);
+ //WriteFile(hConsoleOut,(CONST VOID *)sz, (ULONG32)strlen(sz),&dw,NULL);
+ //WriteFile(hConsoleOut,(CONST VOID *)"\r\n", 2,&dw,NULL);
+ printf("%s\n",UnicodeToAnsi(wz));
+ }
+}
+static void UnicodeToFile(__in __nullterminated const WCHAR* wz, FILE* pF)
+{
+ unsigned endofline = 0x000A000D;
+ int L;
+ if((L=(int)wcslen(wz))) fwrite(wz,L*sizeof(WCHAR),1,pF);
+ fwrite(&endofline,4,1,pF);
+}
+static void ToGUIOrFile(__in __nullterminated const char* sz, void* GUICookie)
+{
+#ifndef FEATURE_CORECLR
+ if (g_Mode & MODE_GUI)
+ GUIAddOpcode(sz, GUICookie);
+ else
+#endif
+ {
+ if(g_fDumpRTF) fprintf((FILE*)GUICookie,"%s\\line\n",sz);
+ else fprintf((FILE*)GUICookie,"%s\n",sz);
+ }
+}
+//------------------------------------------------------------------
+void printError(void* GUICookie, __in __nullterminated const char* string)
+{
+ if(g_Mode & MODE_GUI) printLine(GUICookie, ERRORMSG(string));
+ else
+ {
+ //DWORD dw;
+ const char* sz = ERRORMSG(string);
+ if(GUICookie) printLine(GUICookie, sz);
+ //sz = UnicodeToAnsi(UtfToUnicode(string));
+ //WriteFile(hConsoleErr,(CONST VOID *)sz, (ULONG32)strlen(sz),&dw,NULL);
+ //WriteFile(hConsoleErr,(CONST VOID *)"\r\n", 2,&dw,NULL);
+ fprintf(stderr,"%s\n",UnicodeToAnsi(UtfToUnicode(string)));
+ }
+}
+void printLine(void* GUICookie, __in __nullterminated const char* string)
+{
+ const char* sz = string;
+
+ if (GUICookie == NULL)
+ {
+ UnicodeToConsoleOrMsgBox(UtfToUnicode(string));
+ return;
+ }
+
+
+ if(g_uCodePage != CP_UTF8)
+ {
+ WCHAR* wz = UtfToUnicode(string);
+ if(g_uCodePage != 0xFFFFFFFF)
+ {
+ sz = UnicodeToAnsi(wz);
+ }
+ else if(GUICookie && (!(g_Mode & MODE_GUI)))
+ {
+ UnicodeToFile(wz,(FILE*)GUICookie);
+ return;
+ }
+ else sz = (char*)wz;
+ }
+ ToGUIOrFile(sz,GUICookie);
+}
+
+void printLineW(void* GUICookie, __in __nullterminated const WCHAR* string)
+{
+ const char* sz = (const char*)string;
+
+ if (GUICookie == NULL)
+ {
+ UnicodeToConsoleOrMsgBox(string);
+ return;
+ }
+ if(g_uCodePage == 0xFFFFFFFF)
+ {
+ if(!(g_Mode & MODE_GUI))
+ {
+ UnicodeToFile(string,(FILE*)GUICookie);
+ return;
+ }
+ }
+ else if(g_uCodePage == CP_UTF8)
+ sz = UnicodeToUtf(string);
+ else if(g_uCodePage == g_uConsoleCP)
+ sz = UnicodeToAnsi(string);
+
+ ToGUIOrFile(sz,GUICookie);
+}
+
+char * DumpQString(void* GUICookie,
+ __in __nullterminated const char* szToDump,
+ __in __nullterminated const char* szPrefix,
+ unsigned uMaxLen)
+{
+ unsigned Lwt = (unsigned)strlen(szString);
+ char* szptr = &szString[Lwt];
+ const char* p = szToDump;
+ unsigned L = (unsigned)strlen(szToDump);
+ unsigned l,i;
+ unsigned tally=0;
+ *szptr++ = '"';
+
+ do
+ {
+ l = L;
+ if(l > uMaxLen+2) // +2 - to account for leading/trailing doublequotes in szToDump
+ {
+ l = uMaxLen;
+ while((p[l-1] == '\\')&& l) l--;
+ if(l == 0) l = (uMaxLen+1) & 0xFFFFFFFE;
+ }
+ if(tally)
+ {
+ printLine(GUICookie,szString);
+ szptr = szString;
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%s+ \"",szPrefix);
+ }
+ else uMaxLen = uMaxLen - (ULONG32)strlen(szPrefix) + Lwt;
+ tally++;
+ for(i=0; i < l; i++, szptr++, p++)
+ {
+ switch(*p)
+ {
+ case '\n': *szptr++ = '\\'; *szptr = 'n'; break;
+ case '\r': *szptr++ = '\\'; *szptr = 'r'; break;
+ case '\t': *szptr++ = '\\'; *szptr = 't'; break;
+ case '\b': *szptr++ = '\\'; *szptr = 'b'; break;
+ case '\f': *szptr++ = '\\'; *szptr = 'f'; break;
+ case '\v': *szptr++ = '\\'; *szptr = 'v'; break;
+ case '\a': *szptr++ = '\\'; *szptr = 'a'; break;
+ case '\?': *szptr++ = '\\'; *szptr = '?'; break;
+ case '\\': *szptr++ = '\\'; *szptr = '\\'; break;
+ case '"': *szptr++ = '\\'; *szptr = '"'; break;
+ case '{': szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),SCOPE()); szptr--; break;
+ case '}': szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),UNSCOPE()); szptr--; break;
+ case '<': szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),LTN()); szptr--; break;
+ case '>': szptr += sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),GTN()); szptr--; break;
+ default: *szptr = *p; break;
+ }
+ }
+ *szptr++ = '"';
+ *szptr = 0;
+ L -= l;
+ } while(L);
+ return szptr;
+}
+struct DasmExceptionInfoClause : COR_ILMETHOD_SECT_EH_CLAUSE_FAT {
+public:
+ bool ClauseIsFat;
+};
+DasmExceptionInfoClause* g_ehInfo = NULL;
+ULONG g_ehCount = 0;
+/********************************************************************************/
+/* used by qsort to sort the g_ehInfo table */
+static int __cdecl ehInfoCmp(const void *op1, const void *op2)
+{
+ DasmExceptionInfoClause* p1 = (DasmExceptionInfoClause*)op1;
+ DasmExceptionInfoClause* p2 = (DasmExceptionInfoClause*)op2;
+ int d;
+ d = p1->GetTryOffset() - p2->GetTryOffset(); if(d) return d;
+ d = p1->GetTryLength() - p2->GetTryLength(); if(d) return d;
+ d = p1->GetHandlerOffset() - p2->GetHandlerOffset(); if(d) return d;
+ d = p1->GetHandlerLength() - p2->GetHandlerLength(); if(d) return d;
+ return 0;
+}
+
+BOOL enumEHInfo(const COR_ILMETHOD_SECT_EH* eh, IMDInternalImport *pImport, DWORD dwCodeSize)
+{
+ COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehBuff;
+ const COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehInfo;
+ BOOL fTryInCode = FALSE;
+ if(g_ehInfo) VDELETE(g_ehInfo);
+ g_ehCount = 0;
+ if(eh && (g_ehCount = eh->EHCount()))
+ {
+ g_ehInfo = new DasmExceptionInfoClause[g_ehCount];
+ _ASSERTE(g_ehInfo != NULL);
+ unsigned i;
+ for (i = 0; i < g_ehCount; i++)
+ {
+ ehInfo = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)eh->EHClause(i, &ehBuff);
+ memcpy(&g_ehInfo[i],ehInfo,sizeof(COR_ILMETHOD_SECT_EH_CLAUSE_FAT));
+ g_ehInfo[i].ClauseIsFat = eh->IsFat();
+ //_ASSERTE((ehInfo->GetFlags() & SEH_NEW_PUT_MASK) == 0); // we are using 0x80000000 and 0x40000000
+ g_ehInfo[i].SetFlags((CorExceptionFlag)((int)ehInfo->GetFlags() & ~SEH_NEW_PUT_MASK));
+ }
+ // check if all boundaries are within method code:
+ fTryInCode = g_fTryInCode;
+ for(i=0; i < g_ehCount; i++)
+ {
+ if( (g_ehInfo[i].GetTryOffset() >= dwCodeSize) ||
+ (g_ehInfo[i].GetTryOffset() + g_ehInfo[i].GetTryLength() >= dwCodeSize)||
+ (g_ehInfo[i].GetHandlerOffset() >= dwCodeSize) ||
+ (g_ehInfo[i].GetHandlerOffset() + g_ehInfo[i].GetHandlerLength() > dwCodeSize))
+ {
+ g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | ERR_OUT_OF_CODE));
+ fTryInCode = FALSE; // if out of code, don't expand
+ }
+ }
+
+ if(fTryInCode)
+ {
+ DWORD dwWasTryOffset=0xFFFFFFFF, dwWasTryLength=0xFFFFFFFF, dwLastOffset=0xFFFFFFFF;
+ unsigned iNewTryBlock=0;
+ qsort(g_ehInfo, g_ehCount, sizeof(DasmExceptionInfoClause), ehInfoCmp);
+ for(i=0; i < g_ehCount; i++)
+ {
+ if((g_ehInfo[i].GetTryOffset() != dwWasTryOffset)||(g_ehInfo[i].GetTryLength() != dwWasTryLength))
+ {
+ g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | NEW_TRY_BLOCK)); // insert try in source
+ dwLastOffset = g_ehInfo[i].GetTryOffset() + g_ehInfo[i].GetTryLength();
+ dwWasTryOffset = g_ehInfo[i].GetTryOffset();
+ dwWasTryLength = g_ehInfo[i].GetTryLength();
+ iNewTryBlock = i;
+ }
+
+ // determine offset of the block that lexically follows the try block (filter or handler)
+ DWORD dwFilterOrHandlerOffset;
+ if (g_ehInfo[i].GetFlags() & COR_ILEXCEPTION_CLAUSE_FILTER)
+ {
+ dwFilterOrHandlerOffset = g_ehInfo[i].GetFilterOffset();
+ }
+ else
+ dwFilterOrHandlerOffset = g_ehInfo[i].GetHandlerOffset();
+
+ if (dwFilterOrHandlerOffset == dwLastOffset)
+ {
+ if((i == iNewTryBlock)||((int)g_ehInfo[iNewTryBlock].GetFlags() & PUT_INTO_CODE))
+ g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | PUT_INTO_CODE)); // insert catch/filter/finally in source
+ else
+ g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | NEW_TRY_BLOCK)); // insert catch/filter/finally in source
+
+ dwLastOffset = (g_ehInfo[i].GetHandlerOffset() + g_ehInfo[i].GetHandlerLength());
+ }
+ else
+ g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | NEW_TRY_BLOCK)); // insert try in source
+ }
+ }
+ else
+ {
+ for(i=0; i < g_ehCount; i++)
+ {
+ g_ehInfo[i].SetFlags((CorExceptionFlag)((int)g_ehInfo[i].GetFlags() | NEW_TRY_BLOCK)); // insert try in source
+ }
+ }
+ }
+ return fTryInCode;
+}
+
+// This dumps the hex bytes for the given EHINFO clause
+void DumpHexEHInfo(DasmExceptionInfoClause *ehInfo, void *GUICookie)
+{
+ char *szptr = &szString[0];
+ _ASSERTE(g_fShowBytes);
+ COR_ILMETHOD_SECT_EH_CLAUSE_SMALL eh; // Temporary holder if we should dump the small version
+ BYTE *pb;
+ size_t sizeToDump; // Size of the hex data we're dumping
+
+ szptr = &szString[0];
+ szptr += sprintf_s(szptr, SZSTRING_SIZE,"%s// HEX:", g_szAsmCodeIndent);
+ ehInfo->SetFlags((CorExceptionFlag)((int)ehInfo->GetFlags() & ~SEH_NEW_PUT_MASK));
+
+ if (ehInfo->ClauseIsFat)
+ {
+ // Easy, though probably less common case
+ pb = (BYTE *)ehInfo;
+ sizeToDump = sizeof(COR_ILMETHOD_SECT_EH_CLAUSE_FAT);
+ } else
+ {
+ // Dev11 #2227 - we should dump small clauses as such in the hex dump
+ // Recreate the small EH clause, here, if it came is as a small clause
+ eh.SetFlags(ehInfo->GetFlags());
+ eh.TryOffset = ehInfo->TryOffset;
+ eh.TryLength = ehInfo->TryLength;
+ eh.HandlerOffset = ehInfo->HandlerOffset;
+ eh.HandlerLength = ehInfo->HandlerLength;
+
+ // A couple of sanity checks to make sure things the hex bites recreated are alright
+ _ASSERTE(sizeof(eh.FilterOffset) == sizeof(eh.ClassToken));
+ _ASSERTE(offsetof(COR_ILMETHOD_SECT_EH_CLAUSE_SMALL, FilterOffset) == offsetof(COR_ILMETHOD_SECT_EH_CLAUSE_SMALL, ClassToken));
+ eh.FilterOffset = ehInfo->FilterOffset;
+
+ pb = (BYTE *)&eh;
+ sizeToDump = sizeof(COR_ILMETHOD_SECT_EH_CLAUSE_SMALL);
+ }
+ // Now dump the bytes out
+ for (size_t i = 0; i < sizeToDump; i++)
+ szptr += sprintf_s(szptr, SZSTRING_REMAINING_SIZE(szptr), " %2.2X", *pb++);
+ printLine(GUICookie, COMMENT(szString));
+ // ehInfo->SetFlags((CorExceptionFlag)((dwFlags & ~SEH_NEW_PUT_MASK) | PUT_INTO_CODE));
+}
+
+void dumpOneEHInfo(DasmExceptionInfoClause* ehInfo, IMDInternalImport *pImport, void *GUICookie)
+{
+ //char szString[4096];
+ char* szptr = &szString[0];
+ if(!ehInfo) return;
+ DWORD dwFlags = ehInfo->GetFlags();
+ if(dwFlags & PUT_INTO_CODE)
+ return; // by the time dumpEHInfo is called, this ehInfo is done
+ if(dwFlags & NEW_TRY_BLOCK)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s%s IL_%04x ",g_szAsmCodeIndent,KEYWORD(".try"),ehInfo->GetTryOffset());
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s IL_%04x ",KEYWORD("to"),ehInfo->GetTryOffset()+ehInfo->GetTryLength());
+ }
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s ",g_szAsmCodeIndent);
+
+ if (dwFlags & COR_ILEXCEPTION_CLAUSE_FILTER)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%s IL_%04x ",KEYWORD("filter"),ehInfo->GetFilterOffset());
+ else if (dwFlags & COR_ILEXCEPTION_CLAUSE_FAULT)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), KEYWORD("fault "));
+ else if (dwFlags & COR_ILEXCEPTION_CLAUSE_FINALLY || IsNilToken(ehInfo->GetClassToken()))
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), KEYWORD("finally "));
+ else
+ {
+ CQuickBytes out;
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%s %s ",KEYWORD("catch"),PrettyPrintClass(&out, ehInfo->GetClassToken(), pImport));
+ REGISTER_REF(g_tkRefUser,ehInfo->GetClassToken());
+ }
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%s IL_%04x",KEYWORD("handler"),ehInfo->GetHandlerOffset());
+ if(ehInfo->GetHandlerLength() != (DWORD) -1)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), " %s IL_%04x",KEYWORD("to"),ehInfo->GetHandlerOffset()+ehInfo->GetHandlerLength());
+
+ printLine(GUICookie, szString);
+
+ if(g_fShowBytes)
+ DumpHexEHInfo(ehInfo, GUICookie);
+ /*
+ if(ehInfo->GetFlags() & ERR_OUT_OF_CODE)
+ {
+ sprintf(szString,"%s// WARNING: Boundary outside the method code",g_szAsmCodeIndent);
+ printLine(GUICookie,szString);
+ }
+ */
+}
+void dumpEHInfo(IMDInternalImport *pImport, void *GUICookie)
+{
+ //char szString[4096];
+
+ if(! g_ehCount) return;
+ sprintf_s(szString, SZSTRING_SIZE, "%s// Exception count %d", g_szAsmCodeIndent, g_ehCount);
+ //sprintf_s(szString, SZSTRING_SIZE, "%s// %d irregular exception clauses", g_szAsmCodeIndent, g_ehCount);
+ printLine(GUICookie, COMMENT(szString));
+
+ for (unsigned i = 0; i < g_ehCount; i++)
+ {
+ DasmExceptionInfoClause* ehInfo = &g_ehInfo[i];
+ dumpOneEHInfo(ehInfo,pImport,GUICookie);
+ }
+}
+
+static int __cdecl cmpLineCode(const void *p1, const void *p2)
+{ int ret = (((LineCodeDescr*)p1)->PC - ((LineCodeDescr*)p2)->PC);
+ if(ret==0)
+ {
+ ret= (((LineCodeDescr*)p1)->Line - ((LineCodeDescr*)p2)->Line);
+ if(ret==0) ret= (((LineCodeDescr*)p1)->Column - ((LineCodeDescr*)p2)->Column);
+ }
+ return ret;
+}
+
+static int __cdecl cmpLexScope(const void *p1, const void *p2)
+{
+ LexScope* pls1 = (LexScope*)p1;
+ LexScope* pls2 = (LexScope*)p2;
+ int d;
+ if((d = pls1->dwStart - pls2->dwStart)) return d;
+ return (pls2->dwEnd - pls1->dwEnd);
+}
+
+char* DumpDataPtr(__inout __nullterminated char* buffer, DWORD ptr, DWORD size)
+{
+ // check if ptr really points to some data in one of sections
+ IMAGE_SECTION_HEADER *pSecHdr = NULL;
+ DWORD i;
+ DWORD dwNumberOfSections;
+ if(g_pPELoader->IsPE32())
+ {
+ pSecHdr = IMAGE_FIRST_SECTION(g_pPELoader->ntHeaders32());
+ dwNumberOfSections = VAL16(g_pPELoader->ntHeaders32()->FileHeader.NumberOfSections);
+ }
+ else
+ {
+ pSecHdr = IMAGE_FIRST_SECTION(g_pPELoader->ntHeaders64());
+ dwNumberOfSections = VAL16(g_pPELoader->ntHeaders64()->FileHeader.NumberOfSections);
+ }
+
+ for (i=0; i < dwNumberOfSections; i++,pSecHdr++)
+ {
+ if((ptr >= VAL32(pSecHdr->VirtualAddress))&&
+ (ptr < VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize)))
+ {
+ if(ptr+size > VAL32(pSecHdr->VirtualAddress)+VAL32(pSecHdr->Misc.VirtualSize)) i = dwNumberOfSections;
+ break;
+ }
+ }
+ if(i < dwNumberOfSections)
+ { // yes, the pointer points to real data
+ int j;
+ for(j=0; (j < g_iPtrCount)&&((*g_pPtrTags)[j] != (__int32)ptr); j++);
+ if(j == g_iPtrCount)
+ {
+ if (g_pPtrSize == NULL)
+ {
+ g_pPtrSize = new DynamicArray<DWORD>;
+ }
+ if (g_pPtrTags == NULL)
+ {
+ g_pPtrTags = new DynamicArray<__int32>;
+ }
+
+ (*g_pPtrSize)[g_iPtrCount] = size;
+ (*g_pPtrTags)[g_iPtrCount++] = ptr;
+ }
+ else if((*g_pPtrSize)[j] < size) (*g_pPtrSize)[j] = size;
+ const char* szTls = "D_";
+ if(strcmp((const char*)(pSecHdr->Name),".tls") == 0) szTls = "T_";
+ else if(strcmp((const char*)(pSecHdr->Name),".text") == 0) szTls = "I_";
+ buffer+=sprintf_s(buffer,SZSTRING_REMAINING_SIZE(buffer), "%s%8.8X",szTls,ptr);
+ } //else print as hex
+ else
+ {
+ buffer+=sprintf_s(buffer,SZSTRING_REMAINING_SIZE(buffer),ERRORMSG("0x%8.8X /* WARNING: rogue pointer! (size 0x%8.8X) */"),ptr,size);
+ }
+ return buffer;
+}
+
+void DumpLocals(IMDInternalImport *pImport,COR_ILMETHOD_DECODER *pMethod, __in __nullterminated char* szVarPrefix, void* GUICookie)
+{
+ if (pMethod->GetLocalVarSigTok())
+ {
+ DWORD cbSigLen;
+ PCCOR_SIGNATURE pComSig;
+ CQuickBytes qbMemberSig;
+ size_t dwL;
+
+
+ if (FAILED(pImport->GetSigFromToken(pMethod->GetLocalVarSigTok(), &cbSigLen, &pComSig)))
+ {
+ printLine(GUICookie, "Invalid record");
+ return;
+ }
+
+ _ASSERTE(*pComSig == IMAGE_CEE_CS_CALLCONV_LOCAL_SIG);
+
+ appendStr(&qbMemberSig, g_szAsmCodeIndent);
+ appendStr(&qbMemberSig, KEYWORD(".locals "));
+ if(g_fDumpTokens)
+ {
+ char sz[32];
+ sprintf_s(sz,32,"/*%08X*/ ",pMethod->GetLocalVarSigTok());
+ appendStr(&qbMemberSig,COMMENT(sz));
+ }
+ if(pMethod->GetFlags() & CorILMethod_InitLocals) appendStr(&qbMemberSig, KEYWORD("init "));
+ dwL = qbMemberSig.Size();
+
+ char* pszTailSig = (char *) PrettyPrintSig(pComSig, cbSigLen, 0, &qbMemberSig, pImport,szVarPrefix);
+ if(strlen(pszTailSig) < dwL+3) return;
+
+ {
+ ULONG32 i,j,k,indent = (ULONG32)strlen(g_szAsmCodeIndent)+9; // indent+.locals (
+ char chAfterComma;
+ char *pComma = pszTailSig, *pch;
+ while((pComma = strchr(pComma,',')))
+ {
+ for(pch = pszTailSig, i=0, j=0, k=0; pch < pComma; pch++)
+ {
+ if(*pch == '\'') j=1-j;
+ else if(j==0)
+ {
+ if(*pch == '[') i++;
+ else if(*pch == ']') i--;
+ else if(strncmp(pch,LTN(),strlen(LTN()))==0) k++;
+ else if(strncmp(pch,GTN(),strlen(GTN()))==0) k--;
+ }
+ }
+ pComma++;
+ if((i==0)&&(k==0)&&(j==0)) // no brackets or all opened/closed
+ {
+ chAfterComma = *pComma;
+ *pComma = 0;
+ printLine(GUICookie,pszTailSig);
+ *pComma = chAfterComma;
+ for(i=0; i<indent; i++) pszTailSig[i] = ' ';
+ strcpy_s(&pszTailSig[indent],strlen(pComma)+1,pComma);
+ pComma = pszTailSig;
+ }
+ }
+ }
+ printLine(GUICookie, pszTailSig);
+ }
+}
+void LoadScope(ISymUnmanagedScope *pIScope,
+ DynamicArray<LexScope> *pdaScope,
+ ULONG *pulScopes)
+{
+ ULONG32 ulVars;
+ ULONG32 ulStart;
+ ULONG32 ulEnd;
+ ISymUnmanagedScope** ppChildScope = new ISymUnmanagedScope*[4096];
+ ULONG32 ulChildren;
+ unsigned i;
+
+ if(SUCCEEDED(pIScope->GetLocalCount(&ulVars)) && ulVars)
+ {
+ if(SUCCEEDED(pIScope->GetStartOffset(&ulStart)) &&
+ SUCCEEDED(pIScope->GetEndOffset(&ulEnd)))
+ {
+ (*pdaScope)[*pulScopes].dwStart = ulStart;
+ (*pdaScope)[*pulScopes].dwEnd = ulEnd;
+ (*pdaScope)[*pulScopes].dwZOrder = 0;
+ (*pdaScope)[*pulScopes].pISymScope = pIScope;
+ pIScope->AddRef();
+ (*pulScopes)++;
+ }
+ }
+ if(SUCCEEDED(pIScope->GetChildren(4096,&ulChildren,ppChildScope)))
+ {
+ for(i = 0; i < ulChildren; i++)
+ {
+ if(ppChildScope[i]) {
+ LoadScope(ppChildScope[i],pdaScope,pulScopes);
+ ppChildScope[i]->Release();
+ }
+ }
+ }
+ VDELETE(ppChildScope);
+
+}
+//#define SHOW_LEXICAL_SCOPES
+void OpenScope(ISymUnmanagedScope *pIScope,
+ __inout_ecount(ulLocals) ParamDescriptor *pLV,
+ ULONG ulLocals)
+{
+ ULONG32 dummy;
+ ULONG32 ulVars;
+ ULONG32 ulSlot;
+ ISymUnmanagedVariable** pVars = NULL;
+
+ if(FAILED(pIScope->GetLocalCount(&ulVars))) return;
+
+ ULONG32 ulNameLen;
+#ifdef SHOW_LEXICAL_SCOPES
+ for(unsigned jj = 0; jj < ulLocals; jj++) pLV[jj].attr = 0xFFFFFFFF;
+#endif
+ if(ulVars)
+ {
+ pVars = new ISymUnmanagedVariable*[ulVars+4];
+ memset(pVars,0,sizeof(PVOID)*(ulVars+4));
+
+ if(SUCCEEDED(pIScope->GetLocals(ulVars+4,&dummy,pVars)))
+ {
+ WCHAR* wzName = wzUniBuf;
+ char* szName = NULL;
+ for(ULONG ilv = 0; ilv < ulVars; ilv++)
+ {
+ if(pVars[ilv])
+ {
+ // get the local var slot number and make sure that it's in bounds:
+ if(SUCCEEDED(pVars[ilv]->GetAddressField1(&ulSlot)) && ulSlot < ulLocals)
+ {
+ if(SUCCEEDED(pVars[ilv]->GetName(UNIBUF_SIZE/2,&ulNameLen,wzName)))
+ {
+ szName = UnicodeToUtf(wzName);
+#ifndef SHOW_LEXICAL_SCOPES
+ for(ULONG32 j=0; j<ulLocals; j++)
+ {
+ if(j == ulSlot) continue;
+ if((pLV[ulSlot].name!=NULL)&&(!strcmp(szName,pLV[j].name)))
+ {
+ sprintf_s(szName,UNIBUF_SIZE/2,"V_%d",ulSlot);
+ break;
+ }
+ }
+#endif
+ if (!*szName)
+ sprintf_s(szName,UNIBUF_SIZE/2,"V_%d",ulSlot);
+ ulNameLen = (ULONG32) strlen(szName);
+ if((pLV[ulSlot].name==NULL)||(ulNameLen > (ULONG32)strlen(pLV[ulSlot].name)))
+ {
+ VDELETE(pLV[ulSlot].name);
+ pLV[ulSlot].name = new char[ulNameLen+1];
+ }
+ if(pLV[ulSlot].name != NULL)
+ strcpy_s(pLV[ulSlot].name,ulNameLen+1,szName);
+ }
+ pLV[ulSlot].attr = ulSlot;
+ }
+ pVars[ilv]->Release();
+ }
+ }
+ }
+ VDELETE(pVars);
+ }
+}
+
+char* DumpUnicodeString(void* GUICookie,
+ __inout __nullterminated char* szString,
+ __in_ecount(cbString) WCHAR* pszString,
+ ULONG cbString,
+ bool SwapString )
+{
+ unsigned i,L;
+ char* szStr=NULL, *szRet = NULL;
+#if defined(ALIGN_ACCESS) || BIGENDIAN
+ WCHAR* pszStringCopy = NULL;
+ // Make a copy if the string is unaligned or we have to modify it
+ if (cbString > 0)
+ {
+#if !BIGENDIAN
+ if((size_t)pszString & (sizeof(WCHAR)-1))
+#endif
+ {
+ L = (cbString+1)*sizeof(WCHAR);
+ pszStringCopy = new WCHAR[cbString+1];
+ memcpy(pszStringCopy, pszString, L);
+ pszString=pszStringCopy;
+ }
+ }
+#endif
+
+#if BIGENDIAN
+ if (SwapString)
+ SwapStringLength(pszString, cbString);
+#endif
+
+ // first, check for embedded zeros:
+ for(i=0; i < cbString; i++)
+ {
+ if(pszString[i] == 0) goto DumpAsByteArray;
+ }
+ szStr = new char[cbString*3 + 5];
+ memset(szStr,0,cbString*3 + 5);
+
+ WszWideCharToMultiByte(CP_UTF8,0,pszString,cbString,&szStr[0],cbString*3,NULL,NULL);
+ L = (unsigned)strlen(szStr);
+
+ szStr[L] = 0;
+ for(i=0; i < L; i++)
+ {
+ if((!isprint(((BYTE)(szStr[i]))))&&(szStr[i]!='\t')&&(szStr[i]!='\n')&&(szStr[i]!='\r')) break;
+ }
+
+ if(i == L)
+ {
+ szRet = DumpQString(GUICookie,szStr,g_szAsmCodeIndent, 50);
+ }
+ else
+ {
+DumpAsByteArray:
+ strcat_s(szString,SZSTRING_SIZE,KEYWORD("bytearray"));
+ strcat_s(szString,SZSTRING_SIZE," (");
+
+#if BIGENDIAN
+ SwapStringLength(pszString, cbString);
+#endif
+ DumpByteArray(szString,(BYTE*)pszString,cbString*sizeof(WCHAR),GUICookie);
+ szRet = &szString[strlen(szString)];
+ }
+ if(szStr) VDELETE(szStr);
+#if defined(ALIGN_ACCESS) || BIGENDIAN
+ if(pszStringCopy) VDELETE(pszStringCopy);
+#endif
+ return szRet;
+}
+
+// helper to avoid mixing of SEH and stack objects with destructors
+BOOL SourceLinesHelper(void *GUICookie, LineCodeDescr* pLCD, __out_ecount(nSize) WCHAR* pFileName, UINT nSize)
+{
+ _ASSERTE(nSize > 0);
+ memset(pFileName, 0, nSize * sizeof(WCHAR));
+
+ if(pLCD->FileToken == 0)
+ {
+ return FALSE;
+ }
+
+ struct Param
+ {
+ void *GUICookie;
+ LineCodeDescr* pLCD;
+ WCHAR* pFileName;
+ UINT nSize;
+ BOOL fRet;
+ } param;
+ param.GUICookie = GUICookie;
+ param.pLCD = pLCD;
+ param.pFileName = pFileName;
+ param.nSize = nSize;
+ param.fRet = FALSE;
+
+ PAL_TRY(Param *, pParam, &param) {
+ GUID guidLang={0},guidLangVendor={0},guidDoc={0};
+ WCHAR wzLang[64],wzVendor[64],wzDoc[64];
+ ULONG32 k;
+ if(pParam->pLCD->FileToken != ulWasFileToken)
+ {
+ ((ISymUnmanagedDocument*)(pParam->pLCD->FileToken))->GetLanguage(&guidLang);
+ ((ISymUnmanagedDocument*)(pParam->pLCD->FileToken))->GetLanguageVendor(&guidLangVendor);
+ ((ISymUnmanagedDocument*)(pParam->pLCD->FileToken))->GetDocumentType(&guidDoc);
+ if(memcmp(&guidLang,&guidWasLang,sizeof(GUID))
+ ||memcmp(&guidLangVendor,&guidWasLangVendor,sizeof(GUID))
+ ||memcmp(&guidDoc,&guidWasDoc,sizeof(GUID)))
+ {
+ GuidToLPWSTR(guidLang,wzLang,64);
+ GuidToLPWSTR(guidLangVendor,wzVendor,64);
+ GuidToLPWSTR(guidDoc,wzDoc,64);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s '%ls', '%ls', '%ls'", g_szAsmCodeIndent,KEYWORD(".language"),
+ wzLang,wzVendor,wzDoc);
+ printLine(pParam->GUICookie,szString);
+ memcpy(&guidWasLang,&guidLang,sizeof(GUID));
+ memcpy(&guidWasLangVendor,&guidLangVendor,sizeof(GUID));
+ memcpy(&guidWasDoc,&guidDoc,sizeof(GUID));
+ }
+
+ /*
+ BOOL fHasEmbeddedSource=FALSE;
+ ((ISymUnmanagedDocument*)(pParam->pLCD->FileToken))->HasEmbeddedSource(&fHasEmbeddedSource);
+ sprintf(szString,"%s// PDB has %sembedded source",g_szAsmCodeIndent,
+ fHasEmbeddedSource ? "" : "no ");
+ printLine(pParam->GUICookie,szString);
+ */
+ }
+ ((ISymUnmanagedDocument*)(pParam->pLCD->FileToken))->GetURL(pParam->nSize,&k,pParam->pFileName);
+ ulWasFileToken = pParam->pLCD->FileToken;
+ pParam->fRet = TRUE;
+ } PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_ERRORREOPENINGFILE),pLCD->FileToken);
+ printError(GUICookie, szString);
+ }
+ PAL_ENDTRY
+
+ return param.fRet;
+}
+
+#ifdef _PREFAST_
+#pragma warning(push)
+#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
+#endif
+BOOL Disassemble(IMDInternalImport *pImport, BYTE *ILHeader, void *GUICookie, mdToken FuncToken, ParamDescriptor* pszArgname, ULONG ulArgs)
+{
+ HRESULT hr;
+ DWORD PC;
+ BOOL fNeedNewLine = FALSE;
+ //char szString[4096];
+ char* szptr;
+ BYTE* pCode = NULL;
+ BOOL fTryInCode;
+
+ COR_ILMETHOD_DECODER method((COR_ILMETHOD*) ILHeader);
+
+ pCode = const_cast<BYTE*>(method.Code);
+
+ sprintf_s(szString,SZSTRING_SIZE, RstrUTF(IDS_E_CODESIZE),g_szAsmCodeIndent, method.GetCodeSize(), method.GetCodeSize());
+ printLine(GUICookie, szString);
+
+ if(method.GetCodeSize() == 0) return TRUE;
+
+ sprintf_s(szString,SZSTRING_SIZE, "%s%s %d",g_szAsmCodeIndent, KEYWORD(".maxstack"),method.GetMaxStack());
+ printLine(GUICookie, szString);
+
+ //------------ Source lines display ---------------------------------
+ ULONG32 ulLines =0;
+ LineCodeDescr* LineCode = NULL;
+ BOOL fShowSource = FALSE;
+ BOOL fInsertSourceLines = FALSE;
+ LineCodeDescr* pLCD = NULL;
+ ParamDescriptor* pszLVname = NULL;
+ ULONG ulVars=0;
+ char szVarPrefix[MAX_PREFIX_SIZE];
+ // scope handling:
+ DynamicArray<LexScope> daScope;
+ ULONG ulScopes=0;
+ DWORD dwScopeZOrder = 0;
+ ISymUnmanagedScope* pRootScope = NULL;
+ ISymUnmanagedMethod* pSymMethod = NULL;
+ char szFileName[2048];
+ ISymUnmanagedDocument* pMethodDoc[2] = {NULL,NULL};
+ ULONG32 ulMethodLine[2];
+ ULONG32 ulMethodCol[2];
+ BOOL fHasRangeInfo = FALSE;
+
+ strcpy_s(szVarPrefix,MAX_PREFIX_SIZE,"V0");
+ if(g_pSymReader)
+ {
+ g_pSymReader->GetMethod(FuncToken,&pSymMethod);
+ if(g_fShowSource || g_fInsertSourceLines)
+ {
+ if(pSymMethod)
+ {
+ unsigned ulActualLines=0; // VS compilers produce "Hidden" line numbers, don't count them
+ if(FAILED(pSymMethod->GetSourceStartEnd(pMethodDoc,ulMethodLine,ulMethodCol,&fHasRangeInfo)))
+ {
+ fHasRangeInfo = FALSE;
+ }
+ pSymMethod->GetSequencePointCount(&ulLines);
+ if (ulLines != 0)
+ {
+ LineCode = new LineCodeDescr[ulLines+2];
+ memset(LineCode, 0, sizeof(LineCodeDescr) * (ulLines + 2));
+ }
+ if(ulLines != 0 && LineCode != NULL)
+ {
+ pLCD = &LineCode[0];
+ if(fHasRangeInfo)
+ {
+ //printLine(GUICookie,"// Has source range info");
+ pLCD->Line = ulMethodLine[0];
+ pLCD->Column = ulMethodCol[0];
+ pLCD->PC = 0;
+ pLCD->FileToken = (ULONG_PTR)pMethodDoc[0];
+ ulActualLines++;
+ pLCD++;
+ }
+ if(ulLines)
+ {
+ ULONG32 *offsets=new ULONG32[ulLines], *lines=new ULONG32[ulLines], *columns=new ULONG32[ulLines];
+ ULONG32 *endlines=new ULONG32[ulLines], *endcolumns=new ULONG32[ulLines];
+ ISymUnmanagedDocument** docs = (ISymUnmanagedDocument**)(new PVOID[ulLines]);
+ ULONG32 actualCount;
+ pSymMethod->GetSequencePoints(ulLines,&actualCount, offsets,docs,lines,columns, endlines, endcolumns);
+ for(ULONG i = 0; i < ulLines; i++)
+ {
+ pLCD->Line = lines[i];
+ pLCD->Column = columns[i];
+ pLCD->LineEnd = endlines[i];
+ pLCD->ColumnEnd = endcolumns[i];
+ pLCD->PC = offsets[i];
+ pLCD->FileToken = (ULONG_PTR)docs[i];
+ ulActualLines++;
+ pLCD++;
+ }
+ VDELETE(offsets);
+ VDELETE(lines);
+ VDELETE(columns);
+ VDELETE(endlines);
+ VDELETE(endcolumns);
+ VDELETE(docs);
+ } // end if(ulLines)
+ if(fHasRangeInfo)
+ {
+ pLCD->Line = ulMethodLine[1];
+ pLCD->Column = ulMethodCol[1];
+ pLCD->PC = method.GetCodeSize();
+ pLCD->FileToken = (ULONG_PTR)pMethodDoc[1];
+ ulActualLines++;
+ pLCD++;
+ }
+
+ ulLines = ulActualLines;
+ qsort(LineCode,ulLines,sizeof(LineCodeDescr),cmpLineCode);
+ fShowSource = g_fShowSource;
+ fInsertSourceLines = g_fInsertSourceLines;
+ pLCD = &LineCode[0];
+ } // end if(LineCode)
+ } //end if (pSymMethod)
+ }//end if(g_fShowSource)
+ if (method.GetLocalVarSigTok())
+ {
+ // first, get the real number of local vars from signature
+ DWORD cbSigLen;
+ PCCOR_SIGNATURE pComSig;
+ mdSignature mdLocalVarSigTok = method.GetLocalVarSigTok();
+ if ((TypeFromToken(mdLocalVarSigTok) != mdtSignature) ||
+ (!pImport->IsValidToken(mdLocalVarSigTok)) || (RidFromToken(mdLocalVarSigTok) == 0))
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_BOGUSLVSIG),mdLocalVarSigTok);
+ printError(GUICookie,szString);
+ return FALSE;
+ }
+ if (FAILED(pImport->GetSigFromToken(mdLocalVarSigTok, &cbSigLen, &pComSig)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, RstrUTF(IDS_E_INVALIDRECORD), mdLocalVarSigTok);
+ printError(GUICookie, szString);
+ return FALSE;
+ }
+ _ASSERTE(*pComSig == IMAGE_CEE_CS_CALLCONV_LOCAL_SIG);
+ pComSig++;
+
+ ULONG ulVarsInSig = CorSigUncompressData(pComSig);
+ if(pSymMethod) pSymMethod->GetRootScope(&pRootScope);
+ else pRootScope = NULL;
+
+ if(pRootScope)
+ {
+ ulVars = ulVarsInSig;
+ }
+ else ulVars = 0;
+ if(ulVars)
+ {
+ ULONG ilvs;
+ pszLVname = new ParamDescriptor[ulVars];
+ memset(pszLVname,0,ulVars*sizeof(ParamDescriptor));
+ for(ilvs = 0; ilvs < ulVars; ilvs++)
+ {
+ pszLVname[ilvs].name = new char[16];
+ sprintf_s(pszLVname[ilvs].name,16,"V_%d",ilvs);
+ pszLVname[ilvs].attr = ilvs;
+ }
+ LoadScope(pRootScope,&daScope,&ulScopes);
+ qsort(&daScope[0],ulScopes,sizeof(LexScope),cmpLexScope);
+ OpenScope(pRootScope,pszLVname,ulVars);
+ sprintf_s(szVarPrefix,MAX_PREFIX_SIZE,"@%Id0",(size_t)pszLVname);
+
+#ifndef SHOW_LEXICAL_SCOPES
+ for(unsigned jjj = 0; jjj < ulScopes; jjj++)
+ {
+ OpenScope(daScope[jjj].pISymScope,pszLVname,ulVars);
+ daScope[jjj].pISymScope->Release();
+ }
+ ulScopes = 0;
+#endif
+ } //end if(ulLVScount)
+ if(pRootScope) pRootScope->Release();
+ } //end if (method.LocalVarSigTok)
+ } //end if(g_pDebugImport)
+ //-------------------------------------------------------------------
+ g_tkRefUser = FuncToken;
+ DumpLocals(pImport,&method, szVarPrefix, GUICookie);
+ g_tkRefUser = 0;
+
+#if defined(_DEBUG)
+ const BYTE* curFormat = pCode;
+ #pragma warning(disable : 4640)
+ static ILFormatter ilFormatter;
+ static OutString formatOut;
+ static OutString line;
+ #pragma warning(default : 4640)
+
+ if (g_fPrettyPrint) {
+ extern IMetaDataImport2* g_pPubImport;
+ ilFormatter.init(g_pPubImport, method.Code, &method.Code[method.CodeSize], method.MaxStack, method.EH);
+ }
+#endif
+
+ PC = 0;
+ fTryInCode = enumEHInfo(method.EH, pImport, method.GetCodeSize());
+ DasmExceptionInfoClause* ehInfoToPutNext = NULL;
+ if(g_Mode & MODE_GUI)
+ { // in GUI, reset everything for each method
+ ulWasFileToken = 0xFFFFFFFF;
+ memset(&guidWasLang,0,sizeof(GUID));
+ memset(&guidWasLangVendor,0,sizeof(GUID));
+ memset(&guidWasDoc,0,sizeof(GUID));
+ memset(wzWasFileName,0,sizeof(wzWasFileName));
+ ulWasLine = 0;
+ }
+ while (PC < method.GetCodeSize())
+ {
+ DWORD Len;
+ DWORD i,ii;
+ OPCODE instr;
+ char sz[1024];
+
+ instr = DecodeOpcode(&pCode[PC], &Len);
+ if (instr == CEE_COUNT)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,RstrUTF(IDS_E_INSTRDECOD), pCode[PC],PC,PC);
+ printError(GUICookie, szString);
+ /*
+ while (PC < method.CodeSize)
+ {
+ printf("%02x\n", pCode[PC]);
+ PC++;
+ }
+ */
+ return FALSE;
+ }
+
+ if (fNeedNewLine)
+ {
+ fNeedNewLine = FALSE;
+ if (!(g_Mode & MODE_GUI))
+ printLine(GUICookie,"");
+ }
+
+ if(fShowSource || fInsertSourceLines)
+ {
+ while(PC == pLCD->PC)
+ {
+ bIsNewFile = FALSE;
+ if((pLCD->FileToken != ulWasFileToken) || (pLCD->Line < ulWasLine))
+ {
+ WCHAR wzFileName[2048];
+ SourceLinesHelper(GUICookie, pLCD, wzFileName, 2048);
+ bIsNewFile = (wcscmp(wzFileName,wzWasFileName)!=0);
+ if(bIsNewFile||(pLCD->Line < ulWasLine))
+ {
+ wcscpy_s(wzWasFileName,2048,wzFileName);
+ memset(szFileName,0,2048);
+ WszWideCharToMultiByte(CP_UTF8,0,wzFileName,-1,szFileName,2048,NULL,NULL);
+ if(fShowSource)
+ {
+ if(pFile) fclose(pFile);
+ pFile = NULL;
+ if(fopen_s(&pFile,szFileName,"rt") != 0)
+ {
+ char* pch = strrchr(szFileName,'\\');
+ if(pch == NULL) pch = strrchr(szFileName,':');
+ pFile = NULL;
+ if(pch) fopen_s(&pFile,pch+1,"rt");
+ }
+ if(bIsNewFile)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"// Source File '%s' %s",szFileName,(pFile ? "" : "not found"));
+ printLine(GUICookie, COMMENT(szString));
+ }
+ ulWasLine = 0;
+ }
+ }
+ }
+ if(fInsertSourceLines)
+ {
+ if(bIsNewFile)
+ {
+ const char* pszFN = ProperName(szFileName);
+ sprintf_s(szString,SZSTRING_SIZE,(*pszFN == '\'' ? "%s%s %d,%d : %d,%d %s"
+ : "%s%s %d,%d : %d,%d '%s'"),
+ g_szAsmCodeIndent,KEYWORD(".line"),pLCD->Line,pLCD->LineEnd,
+ pLCD->Column,pLCD->ColumnEnd,pszFN);
+ }
+ else
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s %d,%d : %d,%d ''",g_szAsmCodeIndent,KEYWORD(".line"),
+ pLCD->Line,pLCD->LineEnd,pLCD->Column,pLCD->ColumnEnd);
+
+ printLine(GUICookie,szString);
+ }
+
+ ULONG k= pLCD->Line;
+ if(pFile)
+ {
+ for(k = ulWasLine; k < pLCD->Line; k++)
+ {
+ if(NULL==fgets(sz,1024,pFile)) { k--; break;}
+ if((ulWasLine != 0)||(k == (pLCD->Line-1)))
+ {
+ while((sz[strlen(sz)-1]=='\n') || (sz[strlen(sz)-1]=='\r')) sz[strlen(sz)-1]=0;
+ sprintf_s(szString,SZSTRING_SIZE,"//%6.6d: %s",k+1,sz);
+ printLine(GUICookie, COMMENT(szString));
+ }
+ }
+ ulWasLine = k;
+ }
+ if(pLCD < &LineCode[ulLines-1]) pLCD++;
+ else { fShowSource = FALSE; break; }
+ }
+ }
+ if(fTryInCode)
+ {
+ g_tkRefUser = FuncToken;
+ // dumpOneEHInfo(ehInfoToPutNext,pImport,GUICookie); //doesn't do anything if ehInfoToPutNext == NULL
+ g_tkRefUser = 0;
+ ehInfoToPutNext = NULL;
+
+ for(ii = g_ehCount; ii > 0; ii--)
+ {
+ i = g_ehCount - ii;
+ DWORD theEnd = g_ehInfo[i].GetHandlerOffset()+g_ehInfo[i].GetHandlerLength();
+ if(g_ehInfo[i].GetFlags() & PUT_INTO_CODE)
+ {
+ if(PC == theEnd)
+ {
+ // reduce indent, close }
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,UNSCOPE(),COMMENT("// end handler"));
+ printLine(GUICookie,szString);
+ if(g_fShowBytes)
+ DumpHexEHInfo(&g_ehInfo[i], GUICookie);
+ g_ehInfo[i].SetTryOffset(0xFF000000);
+ g_ehInfo[i].SetHandlerOffset(0xFF000000);
+ }
+ }
+ else
+ {
+ DWORD theTryEnd = g_ehInfo[i].GetTryOffset()+g_ehInfo[i].GetTryLength();
+ if(theTryEnd > theEnd) theEnd = theTryEnd; // try block after the handler
+ if(PC == theEnd) // If we've already found the first, don't skip to the next one
+ ehInfoToPutNext = &g_ehInfo[i];
+ }
+ }
+
+ for(i = 0; i < g_ehCount; i++)
+ {
+ if(g_ehInfo[i].GetFlags() & PUT_INTO_CODE)
+ {
+ if(g_ehInfo[i].GetFlags() & NEW_TRY_BLOCK)
+ {
+ if(PC == g_ehInfo[i].GetTryOffset()+g_ehInfo[i].GetTryLength())
+ {
+ // reduce indent, close }
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,UNSCOPE(),COMMENT("// end .try"));
+ printLine(GUICookie,szString);
+ }
+ if(PC == g_ehInfo[i].GetTryOffset())
+ {
+ // Put try, {, increase indent
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,KEYWORD(".try"));
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+ }
+ }
+
+ DWORD dwFlags = g_ehInfo[i].GetFlags();
+
+ if ((dwFlags & COR_ILEXCEPTION_CLAUSE_FILTER) && PC == g_ehInfo[i].GetFilterOffset())
+ {
+ // Dump filter clause, {, increase indent
+ sprintf_s(szString,SZSTRING_SIZE, "%s%s", g_szAsmCodeIndent, KEYWORD("filter"));
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+ }
+
+ if(PC == g_ehInfo[i].GetHandlerOffset())
+ {
+ if (dwFlags & COR_ILEXCEPTION_CLAUSE_FILTER)
+ {
+ // reduce indent, close } (of the filter block)
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE, "%s%s %s", g_szAsmCodeIndent, UNSCOPE(), COMMENT("// end filter"));
+
+ // Dump handler clause, {, increase indent
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE, "%s%s %s", g_szAsmCodeIndent, SCOPE(), COMMENT("// handler"));
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+ }
+ else
+ {
+ // Dump catch or finally clause, {, increase indent
+ if (dwFlags & COR_ILEXCEPTION_CLAUSE_FAULT)
+ sprintf_s(szString,SZSTRING_SIZE, "%s%s", g_szAsmCodeIndent, KEYWORD("fault"));
+ else if (dwFlags & COR_ILEXCEPTION_CLAUSE_FINALLY || IsNilToken(g_ehInfo[i].GetClassToken()))
+ sprintf_s(szString,SZSTRING_SIZE, "%s%s", g_szAsmCodeIndent,KEYWORD("finally"));
+ else
+ {
+ CQuickBytes out;
+ sprintf_s(szString,SZSTRING_SIZE, "%s%s %s ",g_szAsmCodeIndent,KEYWORD("catch"),
+ PrettyPrintClass(&out, g_ehInfo[i].GetClassToken(), pImport));
+ REGISTER_REF(FuncToken,g_ehInfo[i].GetClassToken());
+ }
+ printLine(GUICookie,szString);
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+ }
+ }
+ } // end if(g_ehInfo[i].Flags & PUT_INTO_CODE)
+ } // end for(i<g_ehCount)
+ } // end if(fTryInCode)
+ //----------------- lexical scope handling -----------------------------
+ if(ulScopes) // non-zero only if local var info present
+ {
+ for(i=0; i < ulScopes; i++)
+ {
+ if(daScope[i].pISymScope != pRootScope)
+ {
+ if(daScope[i].IsOpen())
+ {
+ if(!daScope[i].Covers(PC))
+ {
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
+ printLine(GUICookie,szString);
+ daScope[i].dwZOrder = 0;
+ dwScopeZOrder--;
+ if(PC > daScope[i].dwEnd)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,COMMENT("%s// PDB ERROR: scope end (0x%8.8X) is not opcode-aligned"),
+ g_szAsmCodeIndent,daScope[i].dwEnd);
+ printLine(GUICookie,szString);
+ }
+ } // end if(!daScope[i].Covers(PC))
+ }
+ else // i.e., if scope is not open
+ {
+ if(daScope[i].Covers(PC))
+ {
+ if(g_fShowBytes)
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s // 0x%8.8X - 0x%8.8X",g_szAsmCodeIndent,SCOPE(),
+ daScope[i].dwStart,daScope[i].dwEnd);
+ else
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,SCOPE());
+ printLine(GUICookie,szString);
+ strcat_s(g_szAsmCodeIndent,MAX_MEMBER_LENGTH," ");
+ OpenScope(daScope[i].pISymScope,pszLVname,ulVars);
+ DumpLocals(pImport,&method, szVarPrefix, GUICookie);
+ dwScopeZOrder++;
+ daScope[i].dwZOrder = dwScopeZOrder;
+ if(PC > daScope[i].dwStart)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,COMMENT("%s// PDB ERROR: scope start (0x%8.8X) is not opcode-aligned"),
+ g_szAsmCodeIndent,daScope[i].dwStart);
+ printLine(GUICookie,szString);
+ }
+ } // end if(daScope[i].Covers(PC))
+ } // end if(daScope[i].IsOpen()) -- else
+ } // end if(daScope[i].pISymScope != pRootScope)
+ } // end for(i=0; i < ulScopes; i++)
+ } // end if(ulScopes)
+
+#if defined(_DEBUG)
+ if (g_fPrettyPrint && &pCode[PC] >= curFormat) {
+ formatOut.clear();
+ curFormat = ilFormatter.formatStatement(curFormat, &formatOut);
+ char* ptr = const_cast<char*>(formatOut.val());
+ do {
+ char* newLine = strchr(ptr, '\n');
+ if (newLine)
+ *newLine++ = 0;
+ line.clear();
+ line << COMMENT((char*)0)<<"// **** " << ptr<<COMMENT((char*)-1);
+ printLine(GUICookie, const_cast<char*>(line.val()));
+ ptr = newLine;
+ } while (ptr != 0 && *ptr != 0);
+ }
+#endif
+
+ szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_SIZE,"%sIL_%04x: ",g_szAsmCodeIndent, PC);
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s/* ",COMMENT((char*)0));
+ for(i=0; i<Len; i++) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%2.2X",pCode[PC+i]);
+ for(; i<2; i++) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," "); // 2 is max.opcode length
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," | ");
+ }
+
+ PC += Len;
+ Len = 0;
+
+ const char *pszInstrName = KEYWORD(OpcodeInfo[instr].pszName);
+
+ switch (OpcodeInfo[instr].Type)
+ {
+ DWORD tk;
+ DWORD tkType;
+ default:
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),RstrUTF(IDS_E_INSTRTYPE),
+ OpcodeInfo[instr].Type,instr);
+ printLine(GUICookie, szString);
+ return FALSE;
+ }
+
+#define PadTheString { if(Len < 16) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-*s", (16-Len), ""); \
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," */%s ",COMMENT((char*)-1)); }
+
+ case InlineNone:
+ {
+ if(g_fShowBytes)
+ PadTheString;
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), pszInstrName);
+
+ switch (instr)
+ {
+ case CEE_RET:
+ case CEE_THROW:
+ fNeedNewLine = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ break;
+ }
+
+ case ShortInlineI:
+ case ShortInlineVar:
+ {
+ unsigned char ch= pCode[PC];
+ short sh = OpcodeInfo[instr].Type==ShortInlineVar ? ch : (ch > 127 ? -(256-ch) : ch);
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X ", ch);
+ Len += 3;
+ PadTheString;
+ }
+ switch(instr)
+ {
+ case CEE_LDARG_S:
+ case CEE_LDARGA_S:
+ case CEE_STARG_S:
+ if(g_fThisIsInstanceMethod &&(ch==0))
+ { // instance methods have arg0="this", do not label it!
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %d", pszInstrName, ch);
+ }
+ else
+ {
+ if(pszArgname)
+ {
+ unsigned char ch1 = g_fThisIsInstanceMethod ? ch-1 : ch;
+ if(ch1 < ulArgs)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%-10s %s",pszInstrName,
+ ProperLocalName(pszArgname[ch1].name));
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(RstrUTF(IDS_E_ARGINDEX)),pszInstrName, ch,ulArgs);
+ }
+ else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s A_%d",pszInstrName, ch);
+ }
+ break;
+
+ case CEE_LDLOC_S:
+ case CEE_LDLOCA_S:
+ case CEE_STLOC_S:
+ if(pszLVname)
+ {
+ if(ch < ulVars) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %s", pszInstrName,
+ ProperLocalName(pszLVname[ch].name));
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(RstrUTF(IDS_E_LVINDEX)),pszInstrName, ch, ulVars);
+ }
+ else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s V_%d",pszInstrName, ch);
+ break;
+
+ default:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %d", pszInstrName,sh);
+ }
+
+ PC++;
+ break;
+ }
+
+ case InlineVar:
+ {
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X ", pCode[PC], pCode[PC+1]);
+ Len += 5;
+ PadTheString;
+ }
+
+ USHORT v = pCode[PC] + (pCode[PC+1] << 8);
+ long l = OpcodeInfo[instr].Type==InlineVar ? v : (v > 0x7FFF ? -(0x10000 - v) : v);
+
+ switch(instr)
+ {
+ case CEE_LDARGA:
+ case CEE_LDARG:
+ case CEE_STARG:
+ if(g_fThisIsInstanceMethod &&(v==0))
+ { // instance methods have arg0="this", do not label it!
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %d", pszInstrName, v);
+ }
+ else
+ {
+ if(pszArgname)
+ {
+ USHORT v1 = g_fThisIsInstanceMethod ? v-1 : v;
+ if(v1 < ulArgs)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%-10s %s",pszInstrName,
+ ProperLocalName(pszArgname[v1].name));
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(RstrUTF(IDS_E_ARGINDEX)),pszInstrName, v,ulArgs);
+ }
+ else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s A_%d",pszInstrName, v);
+ }
+ break;
+
+ case CEE_LDLOCA:
+ case CEE_LDLOC:
+ case CEE_STLOC:
+ if(pszLVname)
+ {
+ if(v < ulVars) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %s", pszInstrName,
+ ProperLocalName(pszLVname[v].name));
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(RstrUTF(IDS_E_LVINDEX)),pszInstrName, v,ulVars);
+ }
+ else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s V_%d",pszInstrName, v);
+ break;
+
+ default:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %d", pszInstrName, l);
+ break;
+ }
+ PC += 2;
+ break;
+ }
+
+ case InlineI:
+ case InlineRVA:
+ {
+ DWORD v = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ", pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
+ Len += 9;
+ PadTheString;
+ }
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s 0x%x", pszInstrName, v);
+ PC += 4;
+ break;
+ }
+
+ case InlineI8:
+ {
+ __int64 v = (__int64) pCode[PC] +
+ (((__int64) pCode[PC+1]) << 8) +
+ (((__int64) pCode[PC+2]) << 16) +
+ (((__int64) pCode[PC+3]) << 24) +
+ (((__int64) pCode[PC+4]) << 32) +
+ (((__int64) pCode[PC+5]) << 40) +
+ (((__int64) pCode[PC+6]) << 48) +
+ (((__int64) pCode[PC+7]) << 56);
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),
+ "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
+ pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3],
+ pCode[PC+4], pCode[PC+5], pCode[PC+6], pCode[PC+7]);
+ Len += 8*2;
+ PadTheString;
+ }
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s 0x%I64x", pszInstrName, v);
+ PC += 8;
+ break;
+ }
+
+ case ShortInlineR:
+ {
+ __int32 v = (__int32) pCode[PC] +
+ (((__int32) pCode[PC+1]) << 8) +
+ (((__int32) pCode[PC+2]) << 16) +
+ (((__int32) pCode[PC+3]) << 24);
+
+ float f = (float&)v;
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ", pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
+ Len += 9;
+ PadTheString;
+ }
+
+ char szf[32];
+ if(f==0.0)
+ strcpy_s(szf,32,((v>>24)==0)? "0.0" : "-0.0");
+ else
+ _gcvt_s(szf,32,(double)f, 8);
+ float fd = (float)atof(szf);
+ // Must compare as underlying bytes, not floating point otherwise optmizier will
+ // try to enregister and comapre 80-bit precision number with 32-bit precision number!!!!
+ if(((__int32&)fd == v)&&!IsSpecialNumber(szf))
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %s", pszInstrName, szf);
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s (%2.2X %2.2X %2.2X %2.2X)",
+ pszInstrName, pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
+ PC += 4;
+ break;
+ }
+
+ case InlineR:
+ {
+ __int64 v = (__int64) pCode[PC] +
+ (((__int64) pCode[PC+1]) << 8) +
+ (((__int64) pCode[PC+2]) << 16) +
+ (((__int64) pCode[PC+3]) << 24) +
+ (((__int64) pCode[PC+4]) << 32) +
+ (((__int64) pCode[PC+5]) << 40) +
+ (((__int64) pCode[PC+6]) << 48) +
+ (((__int64) pCode[PC+7]) << 56);
+
+ double d = (double&)v;
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),
+ "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
+ pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3],
+ pCode[PC+4], pCode[PC+5], pCode[PC+6], pCode[PC+7]);
+ Len += 8*2;
+ PadTheString;
+ }
+ char szf[32],*pch;
+ if(d==0.0)
+ strcpy_s(szf,32,((v>>56)==0)? "0.0" : "-0.0");
+ else
+ _gcvt_s(szf,32,d, 17);
+ double df = strtod(szf, &pch); //atof(szf);
+ // Must compare as underlying bytes, not floating point otherwise optmizier will
+ // try to enregister and comapre 80-bit precision number with 64-bit precision number!!!!
+ if (((__int64&)df == v)&&!IsSpecialNumber(szf))
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %s", pszInstrName, szf);
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s (%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X)",
+ pszInstrName, pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3],
+ pCode[PC+4], pCode[PC+5], pCode[PC+6], pCode[PC+7]);
+ PC += 8;
+ break;
+ }
+
+ case ShortInlineBrTarget:
+ {
+ char offset = (char) pCode[PC];
+ long dest = (PC + 1) + (long) offset;
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X ", pCode[PC]);
+ Len += 3;
+ PadTheString;
+ }
+ PC++;
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s IL_%04x", pszInstrName, dest);
+
+ fNeedNewLine = TRUE;
+ break;
+ }
+
+ case InlineBrTarget:
+ {
+ long offset = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
+ long dest = (PC + 4) + (long) offset;
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ", pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
+ Len += 9;
+ PadTheString;
+ }
+ PC += 4;
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s IL_%04x", pszInstrName, dest);
+
+ fNeedNewLine = TRUE;
+ break;
+ }
+
+ case InlineSwitch:
+ {
+ DWORD cases = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ", pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
+ Len += 9;
+ PadTheString;
+ }
+ if(cases) szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s ( ", pszInstrName);
+ else szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s ( )", pszInstrName);
+ printLine(GUICookie, szString);
+ PC += 4;
+ DWORD PC_nextInstr = PC + 4 * cases;
+ for (i = 0; i < cases; i++)
+ {
+ long offset = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
+ long dest = PC_nextInstr + (long) offset;
+ szptr = &szString[0];
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"%s ",g_szAsmCodeIndent); //indent+label
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),"/* | %2.2X%2.2X%2.2X%2.2X ", // comment
+ pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
+ Len = 9;
+ PadTheString;
+ }
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," IL_%04x%s", dest,(i == cases-1)? ")" : ",");
+ PC += 4;
+ printLine(GUICookie, szString);
+ }
+ continue;
+ }
+
+ case InlinePhi:
+ {
+ DWORD cases = pCode[PC];
+ unsigned short *pus;
+ DWORD i;
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X", cases);
+ Len += 2;
+ for(i=0; i < cases*2; i++)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X", pCode[PC+1+i]);
+ Len += 2;
+ }
+ PadTheString;
+ }
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s", pszInstrName);
+ for(i=0, pus=(unsigned short *)(&pCode[PC+1]); i < cases; i++,pus++)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr)," %d",*pus);
+ }
+ PC += 2 * cases + 1;
+ break;
+ }
+
+ case InlineString:
+ case InlineField:
+ case InlineType:
+ case InlineTok:
+ case InlineMethod:
+ {
+ tk = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
+ tkType = TypeFromToken(tk);
+
+ // Backwards compatible ldstr instruction.
+ if (instr == CEE_LDSTR && TypeFromToken(tk) != mdtString)
+ {
+ const WCHAR *v1 = W("");
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ",
+ pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
+ Len += 9;
+ PadTheString;
+ }
+
+ if(!g_pPELoader->getVAforRVA(tk, (void**) &v1))
+ {
+ char szStr[256];
+ sprintf_s(szStr,256,RstrUTF(IDS_E_SECTHEADER),tk);
+ printLine(GUICookie,szStr);
+ }
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s ", pszInstrName);
+ ConvToLiteral(szptr, v1, 0xFFFF);
+ PC += 4;
+ break;
+ }
+
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "(%2.2X)%2.2X%2.2X%2.2X ",
+ pCode[PC+3], pCode[PC+2], pCode[PC+1], pCode[PC]);
+ Len += 11;
+ PadTheString;
+ }
+ PC += 4;
+
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s ", pszInstrName);
+
+ if ((tk & 0xFF000000) == 0)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%#x ", tk);
+ break;
+ }
+ if(!pImport->IsValidToken(tk))
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),ERRORMSG(" [ERROR: INVALID TOKEN 0x%8.8X] "),tk);
+ break;
+ }
+ if(OpcodeInfo[instr].Type== InlineTok)
+ {
+ switch (tkType)
+ {
+ default:
+ break;
+
+ case mdtMethodDef:
+ case mdtMethodSpec:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("method "));
+ break;
+
+ case mdtFieldDef:
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("field "));
+ break;
+
+ case mdtMemberRef:
+ {
+ PCCOR_SIGNATURE typePtr;
+ const char* pszMemberName;
+ ULONG cComSig;
+
+ if (FAILED(pImport->GetNameAndSigOfMemberRef(
+ tk,
+ &typePtr,
+ &cComSig,
+ &pszMemberName)))
+ {
+ szptr += sprintf_s(szptr, SZSTRING_REMAINING_SIZE(szptr), "ERROR ");
+ break;
+ }
+ unsigned callConv = CorSigUncompressData(typePtr);
+
+ if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD))
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("field "));
+ else
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),KEYWORD("method "));
+ break;
+ }
+ }
+ }
+ PrettyPrintToken(szString, tk, pImport,GUICookie,FuncToken); //TypeDef,TypeRef,TypeSpec,MethodDef,FieldDef,MemberRef,MethodSpec,String
+ break;
+ }
+
+ case InlineSig:
+ {
+ if(g_fShowBytes)
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X%2.2X%2.2X%2.2X ",
+ pCode[PC], pCode[PC+1], pCode[PC+2], pCode[PC+3]);
+ // output the offset and the raw bytes
+ Len += 9;
+ PadTheString;
+ }
+
+ // get the signature token
+ tk = pCode[PC] + (pCode[PC+1] << 8) + (pCode[PC+2] << 16) + (pCode[PC+3] << 24);
+ PC += 4;
+ tkType = TypeFromToken(tk);
+ if (tkType == mdtSignature)
+ {
+ // get the signature from the token
+ DWORD cbSigLen;
+ PCCOR_SIGNATURE pComSig;
+ CQuickBytes qbMemberSig;
+ if (FAILED(pImport->GetSigFromToken(tk, &cbSigLen, &pComSig)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, COMMENT("// ERROR: Invalid %08X record"), tk);
+ break;
+ }
+
+ qbMemberSig.Shrink(0);
+ const char* pszTailSig = PrettyPrintSig(pComSig, cbSigLen, "", &qbMemberSig, pImport,NULL);
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s %s", pszInstrName, pszTailSig);
+ if (g_fDumpTokens)
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr),COMMENT(" /*%08X*/"),tk);
+ }
+ else
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), ERRORMSG(RstrUTF(IDS_E_BADTOKENTYPE)), pszInstrName, tk);
+ }
+ break;
+ }
+ }
+
+ printLine(GUICookie, szString);
+ } // end while (PC < method.CodeSize)
+
+ // We've finished looping over all the instructions,
+ // Close of anything that may still be open
+ // First, dump any remaining EH regions
+ if(g_ehCount)
+ {
+ g_tkRefUser = FuncToken;
+ DWORD i;
+ if(fTryInCode)
+ {
+ for (DWORD ii = g_ehCount; ii > 0; ii--)
+ {
+ i = g_ehCount - ii;
+ DWORD theEnd = g_ehInfo[i].GetHandlerOffset()+g_ehInfo[i].GetHandlerLength();
+ if(g_ehInfo[i].GetFlags() & PUT_INTO_CODE)
+ {
+ if(PC == theEnd)
+ {
+ // reduce indent, close }
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s %s",g_szAsmCodeIndent,UNSCOPE(),COMMENT("// end handler"));
+ printLine(GUICookie,szString);
+ if(g_fShowBytes)
+ DumpHexEHInfo(&g_ehInfo[i], GUICookie);
+ g_ehInfo[i].SetTryOffset(0xFF000000);
+ g_ehInfo[i].SetHandlerOffset(0xFF000000);
+ }
+ }
+ }
+ //dumpOneEHInfo(ehInfoToPutNext,pImport,GUICookie); //doesn't do anything if ehInfoToPutNext == NULL
+ }
+ bool fMoreToDisplay = false;
+ for (i = 0; i < g_ehCount && !fMoreToDisplay; i++)
+ fMoreToDisplay = !(g_ehInfo[i].GetTryOffset() == 0xFF000000 && g_ehInfo[i].GetHandlerOffset() == 0xFF000000);
+ if (fMoreToDisplay)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,"%sIL_%04x: ",g_szAsmCodeIndent, method.GetCodeSize()); //add dummy label
+ printLine(GUICookie, szString);
+ dumpEHInfo(pImport,GUICookie);
+ }
+ g_tkRefUser = 0;
+ }
+ //----------------- lexical scope handling -----------------------------
+ if(ulScopes) // non-zero only if local var info present
+ {
+ for(unsigned i=0; i < ulScopes; i++)
+ {
+ if(daScope[i].pISymScope != pRootScope)
+ {
+ if((daScope[i].dwZOrder > 0)&&(PC >= daScope[i].dwEnd))
+ {
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
+ printLine(GUICookie,szString);
+ daScope[i].dwZOrder = 0;
+ dwScopeZOrder--;
+ if(PC > daScope[i].dwEnd)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,COMMENT("%s// PDB ERROR: scope end (0x%8.8X) is not opcode-aligned"),
+ g_szAsmCodeIndent,daScope[i].dwEnd);
+ printLine(GUICookie,szString);
+ }
+ }
+ }
+ daScope[i].pISymScope->Release();
+ }
+ }
+ if(dwScopeZOrder != 0)
+ {
+ sprintf_s(szString,SZSTRING_SIZE,COMMENT("%s// PDB ERROR: %d unclosed lexical scopes, forcing closure."),
+ g_szAsmCodeIndent,dwScopeZOrder);
+ printLine(GUICookie,szString);
+ for(DWORD i=0; i < dwScopeZOrder; i++)
+ {
+ g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-2] = 0;
+ sprintf_s(szString,SZSTRING_SIZE,"%s%s",g_szAsmCodeIndent,UNSCOPE());
+ printLine(GUICookie,szString);
+ }
+ }
+ if(pSymMethod) pSymMethod->Release();
+ if(LineCode) VDELETE(LineCode);
+ if(pszLVname)
+ {
+ for(ULONG i = 0; i < ulVars; i++) SDELETE(pszLVname[i].name);
+ VDELETE(pszLVname);
+ }
+// dumpEHInfo(pImport, GUICookie);
+
+ return TRUE;
+}
+#ifdef _PREFAST_
+#pragma warning(pop)
+#endif
+
+void SplitSignatureByCommas(__inout __nullterminated char* szString,
+ __inout __nullterminated char* pszTailSig,
+ mdToken tk,
+ size_t indent,
+ void* GUICookie)
+{
+ char chAfterComma;
+ char *pComma, *pch;
+ size_t i,j,k,l;
+ if(indent < strlen(pszTailSig))
+ {
+ pComma = pszTailSig+indent;
+ while((pComma = strchr(pComma,',')) != NULL)
+ {
+ for(pch = pszTailSig, i=0,j=0,k=0,l=0; pch < pComma; pch++)
+ {
+ if(*pch == '\'') j=1-j;
+ else if(j==0)
+ {
+ if(*pch == '[') i++;
+ else if(*pch == ']') i--;
+ else if(*pch == '(') k++;
+ else if(*pch == ')') k--;
+ else if(strncmp(pch,LTN(),strlen(LTN()))==0) l++;
+ else if(strncmp(pch,GTN(),strlen(GTN()))==0) l--;
+ }
+ }
+ pComma++;
+ if((i==0)&&(j==0)&&(k<=1)&&(l==0)) // no brackets or all opened/closed
+ {
+ chAfterComma = *pComma;
+ *pComma = 0;
+ printLine(GUICookie,pszTailSig);
+ *pComma = chAfterComma;
+ strcpy_s(pszTailSig,strlen(g_szAsmCodeIndent)+1,g_szAsmCodeIndent);
+ for(i=(ULONG32)strlen(g_szAsmCodeIndent); i<indent; i++) pszTailSig[i] = ' ';
+ strcpy_s(&pszTailSig[indent],strlen(pComma)+1,pComma);
+ pComma = pszTailSig;
+ }
+ }
+ }
+ pch = szString;
+ pch+=sprintf_s(pch,SZSTRING_SIZE,"%s",pszTailSig);
+ if(g_fDumpTokens)
+ pch+=sprintf_s(pch,SZSTRING_REMAINING_SIZE(pch),COMMENT(" /* %08X */"),tk);
+}
+
+//#define TOKEN_SIG
+#ifdef TOKEN_SIG
+struct TokenSig
+{
+ size_t indent;
+ char* str;
+ TokenSig() { indent = 0; str = NULL; };
+ ~TokenSig() { if(str) VDELETE(str); };
+};
+struct TokenSigArray
+{
+ TokenSig* ptsArray;
+ ULONG ulCount;
+ mdToken tkType;
+ TokenSigArray(mdToken tk, IMDInternalImport *pImport)
+ {
+ HENUMInternal hEnum;
+ pImport->EnumAllInit(tk,&hEnum);
+ ulCount=pImport->EnumGetCount(&hEnum)+1;
+ pImport->EnumClose(&hEnum);
+ ptsArray = new TokenSig[ulCount];
+ tkType = tk;
+ };
+ ~TokenSigArray()
+ {
+ VDELETE(ptsArray);
+ }
+};
+
+TokenSigArray *TSA_TD = NULL;
+TokenSigArray *TSA_TR = NULL;
+TokenSigArray *TSA_TS = NULL;
+TokenSigArray *TSA_AR = NULL;
+TokenSigArray *TSA_MR = NULL;
+TokenSigArray *TSA_FD = NULL;
+TokenSigArray *TSA_MD = NULL;
+TokenSigArray *TSA_ME = NULL;
+TokenSigArray *TSA_MS = NULL;
+
+#endif
+void TokenSigInit(IMDInternalImport *pImport)
+{
+#ifdef TOKEN_SIG
+ TSA_TD = new TokenSigArray(mdtTypeDef,pImport);
+ TSA_TR = new TokenSigArray(mdtTypeRef,pImport);
+ TSA_TS = new TokenSigArray(mdtTypeSpec,pImport);
+ TSA_AR = new TokenSigArray(mdtAssemblyRef,pImport);
+ TSA_MR = new TokenSigArray(mdtModuleRef,pImport);
+ TSA_FD = new TokenSigArray(mdtFieldDef,pImport);
+ TSA_MD = new TokenSigArray(mdtMethodDef,pImport);
+ TSA_ME = new TokenSigArray(mdtMemberRef,pImport);
+ TSA_MS = new TokenSigArray(mdtMethodSpec,pImport);
+#endif
+}
+void TokenSigDelete()
+{
+#ifdef TOKEN_SIG
+ SDELETE(TSA_TD);
+ SDELETE(TSA_TR);
+ SDELETE(TSA_TS);
+ SDELETE(TSA_AR);
+ SDELETE(TSA_MR);
+ SDELETE(TSA_FD);
+ SDELETE(TSA_MD);
+ SDELETE(TSA_ME);
+ SDELETE(TSA_MS);
+#endif
+}
+
+// Returns S_OK as TRUE or S_FALSE as FALSE or error code
+HRESULT
+IsGenericInst(mdToken tk, IMDInternalImport *pImport)
+{
+ HRESULT hr;
+ if (TypeFromToken(tk) == mdtTypeSpec)
+ {
+ if (pImport->IsValidToken(tk))
+ {
+ ULONG cSig;
+ PCCOR_SIGNATURE sig;
+ IfFailRet(pImport->GetSigFromToken(tk, &cSig, &sig));
+
+ PCCOR_SIGNATURE sigEnd = sig + cSig;
+ while (sig < sigEnd)
+ {
+ unsigned t = (unsigned)*sig;
+ switch (t)
+ {
+ case ELEMENT_TYPE_PTR:
+ case ELEMENT_TYPE_SZARRAY:
+ case ELEMENT_TYPE_ARRAY:
+ case ELEMENT_TYPE_BYREF:
+ sig++;
+ break;
+ default:
+ {
+ if (*sig == ELEMENT_TYPE_GENERICINST)
+ {
+ return S_OK;
+ }
+ else
+ {
+ return S_FALSE;
+ }
+ }
+ }
+ }
+ }
+ }
+ return S_FALSE;
+}
+
+char* PrettyPrintMemberRef(__inout __nullterminated char* szString, mdToken tk, PCCOR_SIGNATURE pInstSig, ULONG cInstSig,
+ IMDInternalImport *pImport, void* GUICookie, size_t* pIndent,
+ CQuickBytes *pqbMemberSig)
+{
+ HRESULT hr;
+ mdTypeRef cr;
+ const char * pszMemberName;
+ char* curPos;
+ char* pszTailSig;
+ char* pszOffset;
+ PCCOR_SIGNATURE pComSig;
+ ULONG cComSig;
+ size_t L, indent;
+ mdToken tkVarOwner = g_tkVarOwner;
+ DWORD dwAttrs=0xFFFFFFFF; // used only if Parent==MethodDef
+ mdToken tkMethodDef = 0; // used only if Parent==MethodDef
+
+ L = strlen(szString);
+
+ if (FAILED(pImport->GetNameAndSigOfMemberRef(
+ tk,
+ &pComSig,
+ &cComSig,
+ &pszMemberName)))
+ {
+ pComSig = NULL;
+ cComSig = 0;
+ pszMemberName = "Invalid MemberRef record";
+ }
+ MAKE_NAME_IF_NONE(pszMemberName,tk);
+
+ curPos = &szString[L+1];
+ *curPos = 0;
+ if (FAILED(pImport->GetParentOfMemberRef(tk, &cr)))
+ {
+ curPos += sprintf_s(curPos, SZSTRING_REMAINING_SIZE(curPos), "Invalid MemberRef %08X record", tk);
+ cr = mdTypeRefNil;
+ }
+ if (TypeFromToken(cr) == mdtMethodDef) //get the parent's parent
+ {
+ if (FAILED(pImport->GetMethodDefProps(cr, &dwAttrs)))
+ {
+ curPos += sprintf_s(curPos, SZSTRING_REMAINING_SIZE(curPos), "Invalid MethodDef %08X record", cr);
+ }
+ tkMethodDef = cr;
+
+ mdTypeRef cr1;
+ if(FAILED(pImport->GetParentToken(cr,&cr1))) cr1 = mdTypeRefNil;
+ cr = cr1;
+ }
+ pqbMemberSig->Shrink(0);
+ if (RidFromToken(cr)&&(cr != 0x02000001))
+ {
+ const char* pszClass = PrettyPrintClass(pqbMemberSig,cr,pImport);
+ sprintf_s(curPos,SZSTRING_REMAINING_SIZE(curPos),"%s::",pszClass);
+ pqbMemberSig->Shrink(0);
+
+ hr = IsGenericInst(cr,pImport);
+ if (FAILED(hr))
+ {
+ sprintf_s(curPos, SZSTRING_REMAINING_SIZE(curPos), "Invalid token %08X record", cr);
+ }
+ if (hr == S_OK)
+ {
+ g_tkVarOwner = 0;
+ }
+ }
+ {
+ char* curPos1 = &curPos[strlen(curPos)];
+ if (IsMdPrivateScope(dwAttrs))
+ {
+ sprintf_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),"%s$PST%08X",pszMemberName,tkMethodDef);
+ }
+ else
+ {
+ strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),pszMemberName);
+ }
+ if (tkMethodDef != 0)
+ {
+ strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),JUMPPT(ProperName(curPos1),tkMethodDef));
+ }
+ else
+ {
+ strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),ProperName(curPos1));
+ }
+ }
+
+ appendStr(pqbMemberSig, szString);
+ if (pInstSig != NULL)
+ {
+ CQuickBytes qbInstSig;
+ qbInstSig.Shrink(0);
+ PrettyPrintSig(pInstSig, cInstSig, curPos, &qbInstSig, pImport, NULL);
+ strcat_s(curPos,SZSTRING_REMAINING_SIZE(curPos), (char*) qbInstSig.Ptr());
+ }
+ pszTailSig = (char*)PrettyPrintSig(pComSig, cComSig, curPos, pqbMemberSig, pImport,NULL,(pInstSig==NULL));
+ pszOffset = strstr(pszTailSig,curPos);
+ indent = pszOffset - pszTailSig + strlen(curPos) + 1;
+ if(pIndent) *pIndent = indent;
+ g_tkVarOwner = tkVarOwner;
+ return pszTailSig;
+}
+
+char* PrettyPrintMethodDef(__inout __nullterminated char* szString, mdToken tk, PCCOR_SIGNATURE pInstSig, ULONG cInstSig,
+ IMDInternalImport *pImport,void* GUICookie, size_t* pIndent,
+ CQuickBytes *pqbMemberSig)
+{
+ HRESULT hr;
+ mdTypeRef cr;
+ const char * pszMemberName;
+ char* curPos;
+ char* pszTailSig;
+ char* pszOffset;
+ DWORD dwAttrs;
+ PCCOR_SIGNATURE pComSig;
+ ULONG cComSig;
+ size_t L, indent;
+ mdToken tkVarOwner = g_tkVarOwner;
+
+ L = strlen(szString);
+ if (FAILED(pImport->GetNameOfMethodDef(tk, &pszMemberName)))
+ {
+ pszMemberName = "Invalid MethodDef record";
+ }
+ MAKE_NAME_IF_NONE(pszMemberName,tk);
+ if (FAILED(pImport->GetMethodDefProps(tk, &dwAttrs)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "Invalid MethodDef %08X record", tk);
+ return szString;
+ }
+
+ if (FAILED(pImport->GetSigOfMethodDef(tk, &cComSig, &pComSig)))
+ {
+ cComSig = 0;
+ pComSig = NULL;
+ }
+
+ hr = pImport->GetParentToken(
+ tk,
+ &cr
+ );
+ if (FAILED(hr))
+ {
+ strcat_s(szString, SZSTRING_SIZE, "??");
+ return szString;
+ }
+ // use the tail as a buffer
+ curPos = &szString[L+1];
+ *curPos=0;
+ pqbMemberSig->Shrink(0);
+ if(RidFromToken(cr)&&(cr != 0x02000001))
+ {
+ const char* pszClass = PrettyPrintClass(pqbMemberSig,cr,pImport);
+ sprintf_s(curPos,SZSTRING_REMAINING_SIZE(curPos),"%s::",pszClass);
+ pqbMemberSig->Shrink(0);
+
+ hr = IsGenericInst(cr,pImport);
+ if (FAILED(hr))
+ {
+ sprintf_s(curPos, SZSTRING_REMAINING_SIZE(curPos), "/*Invalid token %08X record*/", cr);
+ }
+ if (hr == S_OK)
+ {
+ g_tkVarOwner = 0;
+ }
+ }
+ {
+ char* curPos1 = &curPos[strlen(curPos)];
+ if(IsMdPrivateScope(dwAttrs))
+ sprintf_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),"%s$PST%08X",pszMemberName,tk);
+ else
+ strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),pszMemberName);
+ strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),JUMPPT(ProperName(curPos1),tk));
+ }
+ appendStr(pqbMemberSig, szString);
+ if (pInstSig)
+ {
+ CQuickBytes qbInstSig;
+ qbInstSig.Shrink(0);
+ pszTailSig = (char*)PrettyPrintSig(pInstSig, cInstSig, curPos, &qbInstSig, pImport, NULL);
+ strcat_s(curPos,SZSTRING_REMAINING_SIZE(curPos), (char*) qbInstSig.Ptr());
+ }
+
+ pszTailSig = (char*)PrettyPrintSig(pComSig, cComSig, curPos, pqbMemberSig, pImport, NULL, (pInstSig == NULL));
+ pszOffset = strstr(pszTailSig,curPos);
+ indent = pszOffset - pszTailSig + strlen(curPos) + 1;
+ if(pIndent) *pIndent = indent;
+ g_tkVarOwner = tkVarOwner;
+ return pszTailSig;
+}
+
+void PrettyPrintTokenWithSplit(__inout __nullterminated char* szString, mdToken tk, IMDInternalImport *pImport, void* GUICookie)
+{
+ CQuickBytes qbMemberSig;
+ char* pszTailSig = NULL;
+ size_t L, indent;
+
+ L = strlen(szString);
+
+#ifdef TOKEN_SIG
+ TokenSig* SigToken=NULL;
+ switch(TypeFromToken(tk))
+ {
+ case mdtMethodDef: SigToken = TSA_MD->ptsArray; break;
+ case mdtMethodSpec: SigToken = TSA_MS->ptsArray; break;
+ case mdtMemberRef: SigToken = TSA_ME->ptsArray; break;
+ default: return; // other token types aren't served
+ }
+ if(SigToken[RidFromToken(tk)].str)
+ {
+ qbMemberSig.Shrink(0);
+ appendStr(&qbMemberSig, szString);
+ appendStr(&qbMemberSig, SigToken[RidFromToken(tk)].str);
+ pszTailSig = asString(&qbMemberSig);
+ indent = SigToken[RidFromToken(tk)].indent + L;
+ }
+ else
+#endif
+ {
+ switch(TypeFromToken(tk))
+ {
+ case mdtMethodDef:
+ pszTailSig = PrettyPrintMethodDef(szString,tk,NULL,0,pImport,GUICookie,&indent,&qbMemberSig);
+ break;
+ case mdtMemberRef:
+ pszTailSig = PrettyPrintMemberRef(szString,tk,NULL,0,pImport,GUICookie,&indent,&qbMemberSig);
+ break;
+ case mdtMethodSpec:
+ {
+ mdToken meth=0;
+ PCCOR_SIGNATURE pSig=NULL;
+ ULONG cSig=0;
+ mdToken tkMVarOwner = g_tkMVarOwner;
+ g_tkMVarOwner = 0;
+ if (FAILED(pImport->GetMethodSpecProps(tk, &meth, &pSig, &cSig)))
+ {
+ return;
+ }
+ pszTailSig = (TypeFromToken(meth) == mdtMethodDef) ?
+ PrettyPrintMethodDef(szString,meth,pSig,cSig,pImport,GUICookie,&indent,&qbMemberSig) :
+ PrettyPrintMemberRef(szString,meth,pSig,cSig,pImport,GUICookie,&indent,&qbMemberSig);
+ g_tkMVarOwner = tkMVarOwner;
+ }
+ break;
+ default:
+ return;
+ }
+
+#ifdef TOKEN_SIG
+ SigToken[RidFromToken(tk)].str = new char[strlen(pszTailSig+L)+1];
+ if(SigToken[RidFromToken(tk)].str)
+ {
+ strcpy_s(SigToken[RidFromToken(tk)].str,strlen(pszTailSig+L)+1,pszTailSig+L);
+ SigToken[RidFromToken(tk)].indent = indent - L;
+ }
+#endif
+ }
+ SplitSignatureByCommas(szString,pszTailSig,tk,indent,GUICookie);
+}
+
+void PrettyPrintToken(__inout __nullterminated char* szString, mdToken tk, IMDInternalImport *pImport,void* GUICookie, mdToken FuncToken)
+{
+#ifdef TOKEN_SIG
+
+ TokenSig* SigToken=NULL;
+
+#endif
+ char *szptr = &szString[strlen(szString)];
+ if(!pImport->IsValidToken(tk))
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), ERRORMSG("<invalid token 0x%8.8x>"), tk);
+ return;
+ }
+ mdToken tkType = TypeFromToken(tk);
+
+ DWORD ix;
+ for(ix = 0; ix < g_NumTypedefs; ix++)
+ {
+ if((*g_typedefs)[ix].tkTypeSpec == tk) break;
+ }
+ if(ix < g_NumTypedefs)
+ {
+ REGISTER_REF(FuncToken,tk);
+ strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr),JUMPPT(ProperName((*g_typedefs)[ix].szName),(*g_typedefs)[ix].tkSelf));
+ return;
+ }
+
+#ifdef TOKEN_SIG
+ switch (tkType)
+ {
+ case mdtTypeDef: SigToken = TSA_TD->ptsArray; break;
+ case mdtTypeRef: SigToken = TSA_TR->ptsArray; break;
+ case mdtTypeSpec: SigToken = TSA_TS->ptsArray; break;
+ case mdtAssemblyRef: SigToken = TSA_AR->ptsArray; break;
+ case mdtModuleRef: SigToken = TSA_MR->ptsArray; break;
+ case mdtFieldDef: SigToken = TSA_FD->ptsArray; break;
+ default: SigToken = NULL; break;
+ }
+
+ if(SigToken && SigToken[RidFromToken(tk)].str)
+ {
+ REGISTER_REF(FuncToken,tk);
+ strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr),SigToken[RidFromToken(tk)].str);
+ return;
+ }
+#endif
+ CQuickBytes out;
+ char* pszForTokenSig = NULL;
+
+ switch (tkType)
+ {
+ default:
+ {
+ szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), ERRORMSG("<unknown token type 0x%02x>"), (BYTE) (tkType >> 24));
+ pszForTokenSig = NULL;
+ break;
+ }
+
+ case mdtTypeDef:
+ case mdtTypeRef:
+ case mdtTypeSpec:
+ case mdtAssemblyRef:
+ case mdtAssembly:
+ case mdtModuleRef:
+ case mdtModule:
+ {
+ REGISTER_REF(FuncToken,tk);
+ strcpy_s(szptr,SZSTRING_REMAINING_SIZE(szptr), PrettyPrintClass(&out, tk, pImport));
+ pszForTokenSig = szptr;
+ break;
+ }
+
+ case mdtMethodDef:
+ case mdtMemberRef:
+ PrettyPrintTokenWithSplit(szString,tk,pImport,GUICookie);
+ REGISTER_REF(FuncToken,tk);
+ break;
+
+ case mdtMethodSpec:
+ {
+ mdToken meth=0;
+ PCCOR_SIGNATURE pSig;
+ ULONG cSig;
+ if (FAILED(pImport->GetMethodSpecProps(tk, &meth, &pSig, &cSig)))
+ {
+ meth = mdTokenNil;
+ }
+ //g_tkMVarOwner = 0;
+ PrettyPrintTokenWithSplit(szString,tk,pImport,GUICookie);
+ REGISTER_REF(FuncToken,meth);
+ break;
+ }
+
+ case mdtFieldDef:
+ {
+ HRESULT hr;
+ mdTypeRef cr=0;
+ const char * pszMemberName;
+ CQuickBytes qbMemberSig;
+ DWORD dwAttrs;
+
+ PCCOR_SIGNATURE pComSig;
+ ULONG cComSig;
+
+ REGISTER_REF(FuncToken,tk);
+ if (FAILED(pImport->GetNameOfFieldDef(tk, &pszMemberName)))
+ {
+ strcat_s(szString, SZSTRING_SIZE, "??");
+ break;
+ }
+ MAKE_NAME_IF_NONE(pszMemberName,tk);
+ if (FAILED(pImport->GetFieldDefProps(tk, &dwAttrs)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "Invalid FieldDef %08X record", tk);
+ break;
+ }
+
+ if (FAILED(pImport->GetSigOfFieldDef(tk, &cComSig, &pComSig)) ||
+ FAILED(pImport->GetParentToken(tk, &cr)))
+ {
+ sprintf_s(szString, SZSTRING_SIZE, "Invalid FieldDef %08X record", tk);
+ break;
+ }
+
+ // use the tail as a buffer
+ char* curPos = &szString[strlen(szString)+1];
+ *curPos = 0;
+ if((cr != 0x02000001) && RidFromToken(cr))
+ {
+ const char* pszClass = PrettyPrintClass(&out, cr, pImport);
+ REGISTER_REF(FuncToken,cr);
+ sprintf_s(curPos,SZSTRING_REMAINING_SIZE(curPos),"%s::", pszClass);
+ }
+ char* curPos1 = &curPos[strlen(curPos)];
+ if(IsFdPrivateScope(dwAttrs))
+ sprintf_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),"%s$PST%08X",pszMemberName,tk);
+ else
+ strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),pszMemberName);
+ strcpy_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),JUMPPT(ProperName(curPos1),tk));
+ qbMemberSig.Shrink(0);
+ strcpy_s(curPos-1,SZSTRING_REMAINING_SIZE(curPos), PrettyPrintSig(pComSig, cComSig, curPos, &qbMemberSig, pImport,NULL));
+ curPos1 = &curPos[strlen(curPos)];
+ if(g_fDumpTokens)
+ sprintf_s(curPos1,SZSTRING_REMAINING_SIZE(curPos1),COMMENT(" /* %08X */"),tk);
+ pszForTokenSig = szptr;
+ break;
+ }
+
+ case mdtString:
+ {
+ const WCHAR *pszString = NULL;
+ ULONG cbString = 0;
+ if (pImport->IsValidToken(tk))
+ {
+ if (FAILED(pImport->GetUserString(tk, &cbString, NULL, &pszString)))
+ {
+ pszString = NULL;
+ }
+ }
+ if (pszString != NULL)
+ {
+ DumpUnicodeString(GUICookie,szString,(WCHAR *)pszString,cbString, true);
+ }
+ else
+ {
+ sprintf_s(szString,SZSTRING_SIZE,ERRORMSG("INVALID TOKEN: 0x%8.8X"),tk);
+ }
+ if (g_fDumpTokens)
+ sprintf_s(&szString[strlen(szString)],SZSTRING_SIZE-strlen(szString),COMMENT(" /* %08X */"),tk);
+ break;
+ }
+ } //end switch(TypeFromToken(tk))
+
+#ifdef TOKEN_SIG
+ if(SigToken && pszForTokenSig)
+ {
+ unsigned N = RidFromToken(tk);
+ SigToken[N].str = new char[strlen(pszForTokenSig)+1];
+ if(SigToken[N].str)
+ strcpy_s(SigToken[N].str,strlen(pszForTokenSig)+1,pszForTokenSig);
+ }
+#endif
+}
+
+/* not const char * const because it gets sorted at runtime; arguably a bad time to sort it. */
+static const char* keyword[] = {
+#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) s,
+#define OPALIAS(alias_c, s, c) s,
+#include "opcode.def"
+#undef OPALIAS
+#undef OPDEF
+#define KYWD(name, sym, val) name,
+#include "il_kywd.h"
+#undef KYWD
+};
+static bool KywdNotSorted = TRUE;
+static const char* szAllowedSymbols = "#_@$.";
+static char DisallowedStarting[256];
+static char DisallowedCont[256];
+
+struct Indx
+{
+ void* table[128];
+ Indx() { memset(table,0,sizeof(table)); };
+ ~Indx()
+ {
+ for(int i = 1; i < 128; i++) delete ((Indx*)(table[i]));
+ };
+ void IndexString(__in __nullterminated const char* psz, __out const char** pkywd)
+ {
+ int i = (int) *psz;
+ if(i == 0)
+ table[0] = pkywd;
+ else
+ {
+ _ASSERTE((i > 0)&&(i <= 127));
+ Indx* pInd = (Indx*)(table[i]);
+ if(pInd == NULL)
+ {
+ pInd = new Indx;
+ _ASSERTE(pInd);
+ table[i] = pInd;
+ }
+ pInd->IndexString(psz+1,pkywd);
+ }
+ }
+ const char** FindString(__in __nullterminated const char* psz)
+ {
+ if(*psz == 0)
+ return (const char**)(table[0]);
+ if(*psz > 0)
+ {
+ Indx* pInd = (Indx*)(table[(unsigned char)*psz]);
+ return (pInd == NULL) ? NULL : pInd->FindString(psz+1);
+ }
+ return NULL;
+ }
+};
+
+/********************************************************************************/
+/* looks up the keyword 'name' Returns FALSE on failure */
+bool IsNameToQuote(const char *name)
+{
+ BYTE* p;
+ BOOL bStarting;
+ static Indx* indx;
+
+ if (indx==NULL)
+ indx = new Indx();
+
+ if((name==NULL)||(*name==0)) return TRUE;
+
+ if(g_fQuoteAllNames)
+ return ((strcmp(name,COR_CTOR_METHOD_NAME)!=0) && (strcmp(name,COR_CCTOR_METHOD_NAME)!=0));
+
+ if(KywdNotSorted)
+ {
+ int j;
+ const char** const low = keyword;
+ const char** const high = &keyword[sizeof(keyword) / sizeof(*keyword)];
+ const char** mid;
+ // name must start with alpha or one of allowed chars: #_$@.
+ memset(DisallowedStarting,1,256);
+ for(p = (BYTE*)szAllowedSymbols; *p; DisallowedStarting[*p]=0,p++);
+ for(j='a'; j<= 'z'; DisallowedStarting[j]=0,j++);
+ for(j='A'; j<= 'Z'; DisallowedStarting[j]=0,j++);
+ // name must continue with the same chars, plus digits, and ? instead of #
+ memcpy(DisallowedCont,DisallowedStarting,256);
+ for(j='0'; j<= '9'; DisallowedCont[j]=0,j++);
+ DisallowedCont[(unsigned char)'#'] = 1;
+ DisallowedCont[(unsigned char)'?'] = 0;
+ DisallowedCont[(unsigned char)'`'] = 0;
+ // Sort the keywords for fast lookup
+ for(mid = low; mid < high; mid++)
+ {
+ indx->IndexString(*mid,mid);
+ }
+ KywdNotSorted = FALSE;
+ }
+ //first, check for forbidden characters
+ for(p = (BYTE*)name, bStarting = TRUE; *p; p++)
+ {
+ if(bStarting)
+ {
+ if(DisallowedStarting[*p]) return TRUE;
+ }
+ else
+ {
+ if(DisallowedCont[*p]) return TRUE;
+ }
+ bStarting = (*p == '.');
+ if(bStarting && (*(p+1) == '.')) return TRUE;
+ }
+
+ //second, check for matching keywords (remember: .ctor and .cctor are names AND keywords)
+ if(indx->FindString((char*)name))
+ {
+ return ((strcmp(name,COR_CTOR_METHOD_NAME)!=0) && (strcmp(name,COR_CCTOR_METHOD_NAME)!=0));
+ }
+ //third, check if the name starts or ends with dot (.ctor and .cctor are out of the way)
+ return ((*name == '.') || (name[strlen(name)-1] == '.'));
+}
+
+/* Returns true if this name requires a single quote to be properly displayed as a local */
+bool IsLocalToQuote(const char *name)
+{
+ // Anything that would otherwise require a quote gets a quote
+ if (IsNameToQuote(name))
+ return true;
+ // No such thing as an empty name that doesn't require quoting (handled in IsNameToQuote)
+ _ASSERTE(*name);
+ // return true if there's a '.' anywhere in the name, after position 1
+ return !!strchr(name + 1, '.');
+}
+
+/********************************************************************/
+/*
+ * This is currently unused, with all calls to it commented out. In
+ * the event that those calls return, add this function back.
+static char* ConvNumericEscape(char* retBuff, unsigned val) {
+ _ASSERTE(val < 256);
+
+ // print as octal
+ *retBuff++ = '\\';
+ *retBuff++ = (val >> 6) + '0';
+ *retBuff++ = ((val >> 3) & 7) + '0';
+ *retBuff++ = (val & 7) + '0';
+ return(retBuff);
+}
+ */
+
+/********************************************************************/
+/* returns the quoted version of a string (including the quotes) */
+
+static BOOL ConvToLiteral(__inout __nullterminated char* retBuff, const WCHAR* str, int cbString)
+{
+ BOOL ret = TRUE;
+ char* was_retBuff = retBuff;
+
+ *retBuff++ = '"';
+
+ for(int tally=0; (tally < cbString)&&ret; tally++)
+ {
+ if (*str > 255)
+ {
+ //retBuff = ConvNumericEscape(retBuff, *str >> 8);
+ //retBuff = ConvNumericEscape(retBuff, *str & 0xFF);
+ ret = FALSE;
+ }
+ else if(!isprint(*str))
+ {
+ if (*str == '\n')
+ {
+ *retBuff++ = '\\';
+ *retBuff++ = 'n';
+ }
+ else
+ //retBuff = ConvNumericEscape(retBuff, *str);
+ ret = FALSE;
+ }
+ else if (*str == '"')
+ {
+ *retBuff++ = '\\';
+ *retBuff++ = '"';
+ }
+ else if (*str == '\\')
+ {
+ *retBuff++ = '\\';
+ *retBuff++ = '\\';
+ }
+ else if (*str == '\t')
+ {
+ *retBuff++ = '\\';
+ *retBuff++ = 't';
+ }
+ else
+ *retBuff++ = (char) *str;
+ str++;
+ }
+ *retBuff++ = '"';
+ *retBuff++ = 0;
+ if(!ret) *was_retBuff = 0;
+ return ret;
+}
+
+bool IsSpecialNumber(const char* szf)
+{
+ return (strchr(szf, '#') != NULL)
+ || (strstr(szf, "nan") != NULL) || (strstr(szf, "NAN") != NULL)
+ || (strstr(szf, "inf") != NULL) || (strstr(szf, "INF") != NULL);
+}