BOOL Disassemble()

in src/coreclr/ildasm/dis.cpp [868:1963]


BOOL Disassemble(IMDInternalImport *pImport, BYTE *ILHeader, void *GUICookie, mdToken FuncToken, ParamDescriptor* pszArgname, ULONG ulArgs)
{
    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,"@%zd0",(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;

    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;
            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 = (u16_strcmp(wzFileName,wzWasFileName)!=0);
                    if(bIsNewFile||(pLCD->Line < ulWasLine))
                    {
                        wcscpy_s(wzWasFileName,2048,wzFileName);
                        memset(szFileName,0,2048);
                        WideCharToMultiByte(CP_UTF8,0,wzFileName,-1,szFileName,2048,NULL,NULL);
                        if(fShowSource)
                        {
                            if(pFile) fclose(pFile);
                            pFile = NULL;
#ifdef HOST_WINDOWS
                            const char* const mode = "rt";
#else
                            const char* const mode = "r";
#endif
                            if(fopen_s(&pFile,szFileName, mode) != 0)
                            {
                                char* pch = strrchr(szFileName, DIRECTORY_SEPARATOR_CHAR_A);
#ifdef HOST_WINDOWS
                                if(pch == NULL) pch = strrchr(szFileName,':');
#endif
                                pFile = NULL;
                                if(pch) fopen_s(&pFile,pch+1, mode);
                            }
                            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+1], pCode[PC]);
                    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+3], pCode[PC+2], pCode[PC+1], pCode[PC]);
                    Len += 9;
                    PadTheString;
                }
                szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s 0x%x", pszInstrName, v);
                PC += 4;
                break;
            }

            case InlineI8:
            {
                int64_t v = (int64_t) pCode[PC] +
                            (((int64_t) pCode[PC+1]) << 8) +
                            (((int64_t) pCode[PC+2]) << 16) +
                            (((int64_t) pCode[PC+3]) << 24) +
                            (((int64_t) pCode[PC+4]) << 32) +
                            (((int64_t) pCode[PC+5]) << 40) +
                            (((int64_t) pCode[PC+6]) << 48) +
                            (((int64_t) 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+7], pCode[PC+6], pCode[PC+5], pCode[PC+4],
                        pCode[PC+3], pCode[PC+2], pCode[PC+1], pCode[PC]);
                    Len += 8*2;
                    PadTheString;
                }

                szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%-10s 0x%llx", pszInstrName, v);
                PC += 8;
                break;
            }

            case ShortInlineR:
            {
                int32_t v = (int32_t) pCode[PC] +
                            (((int32_t) pCode[PC+1]) << 8) +
                            (((int32_t) pCode[PC+2]) << 16) +
                            (((int32_t) 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+3], pCode[PC+2], pCode[PC+1], pCode[PC]);
                    Len += 9;
                    PadTheString;
                }

                char szf[32];
                if(f==0.0)
                    strcpy_s(szf,32,((v>>24)==0)? "0.0" : "-0.0");
                else
                    sprintf_s(szf, 32, "%.*g", 8, (double)f);
                float fd = (float)atof(szf);
                // Must compare as underlying bytes, not floating point otherwise optimizer will
                // try to enregister and compare 80-bit precision number with 32-bit precision number!!!!
                if(((int32_t&)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_t v = (int64_t) pCode[PC] +
                            (((int64_t) pCode[PC+1]) << 8) +
                            (((int64_t) pCode[PC+2]) << 16) +
                            (((int64_t) pCode[PC+3]) << 24) +
                            (((int64_t) pCode[PC+4]) << 32) +
                            (((int64_t) pCode[PC+5]) << 40) +
                            (((int64_t) pCode[PC+6]) << 48) +
                            (((int64_t) 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+7], pCode[PC+6], pCode[PC+5], pCode[PC+4],
                        pCode[PC+3], pCode[PC+2], pCode[PC+1], pCode[PC]);
                    Len += 8*2;
                    PadTheString;
                }
                char szf[32],*pch;
                if(d==0.0)
                    strcpy_s(szf,32,((v>>56)==0)? "0.0" : "-0.0");
                else
                    sprintf_s(szf, 32, "%.*g", 17, d);
                double df = strtod(szf, &pch); //atof(szf);
                // Must compare as underlying bytes, not floating point otherwise optimizer will
                // try to enregister and compare 80-bit precision number with 64-bit precision number!!!!
                if (((int64_t&)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+3], pCode[PC+2], pCode[PC+1], pCode[PC]);
                    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+3], pCode[PC+2], pCode[PC+1], pCode[PC]);
                    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+3], pCode[PC+2], pCode[PC+1], pCode[PC]);
                        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=cases*2; i > 0; i--)
                    {
                        szptr+=sprintf_s(szptr,SZSTRING_REMAINING_SIZE(szptr), "%2.2X", pCode[PC+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+3], pCode[PC+2], pCode[PC+1], pCode[PC]);
                        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+3], pCode[PC+2], pCode[PC+1], pCode[PC]);
                    // 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;
}