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;
}