void DecodeIL(IMetaDataImport *pImport, BYTE *buffer, ULONG bufSize) { // First decode the header COR_ILMETHOD *pHeader = (COR_ILMETHOD *) buffer; COR_ILMETHOD_DECODER header(pHeader); // Set globals position = 0; pBuffer = (BYTE *) header.Code; UINT indentCount = 0; ULONG endCodePosition = header.GetCodeSize(); while(position < endCodePosition) { for (unsigned e=0;e<header.EHCount();e++) { IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehBuff; const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehInfo; ehInfo = header.EH->EHClause(e,&ehBuff); if (ehInfo->TryOffset == position) { printf ("%*s.try\n%*s{\n", indentCount, "", indentCount, ""); indentCount+=2; } else if ((ehInfo->TryOffset + ehInfo->TryLength) == position) { indentCount-=2; printf("%*s} // end .try\n", indentCount, ""); } if (ehInfo->HandlerOffset == position) { if (ehInfo->Flags == COR_ILEXCEPTION_CLAUSE_FINALLY) printf("%*s.finally\n%*s{\n", indentCount, "", indentCount, ""); else printf("%*s.catch\n%*s{\n", indentCount, "", indentCount, ""); indentCount+=2; } else if ((ehInfo->HandlerOffset + ehInfo->HandlerLength) == position) { indentCount-=2; if (ehInfo->Flags == COR_ILEXCEPTION_CLAUSE_FINALLY) printf("%*s} // end .finally\n", indentCount, ""); else printf("%*s} // end .catch\n", indentCount, ""); } } printf("%*sIL_%04x: ", indentCount, "", position); unsigned int c = readOpcode(); OpCode opcode = opcodes[c]; printf("%s ", opcode.name); switch(opcode.args) { case InlineNone: break; case ShortInlineVar: printf("VAR OR ARG %d",readData<BYTE>()); break; case InlineVar: printf("VAR OR ARG %d",readData<unsigned short>()); break; case InlineI: printf("%d",readData<long>()); break; case InlineR: printf("%f",readData<double>()); break; case InlineBrTarget: printf("IL_%04x",readData<long>() + position); break; case ShortInlineBrTarget: printf("IL_%04x",readData<BYTE>() + position); break; case InlineI8: printf("%ld", readData<__int64>()); break; case InlineMethod: case InlineField: case InlineType: case InlineTok: case InlineSig: { long l = readData<long>(); if (pImport != NULL) { DisassembleToken(pImport, l); } else { printf("TOKEN %x", l); } break; } case InlineString: { long l = readData<long>(); ULONG numChars; WCHAR str[84]; if ((pImport != NULL) && (pImport->GetUserString((mdString) l, str, 80, &numChars) == S_OK)) { if (numChars < 80) str[numChars] = 0; wcscpy_s(&str[79], 4, L"..."); WCHAR* ptr = str; while(*ptr != 0) { if (*ptr < 0x20 || * ptr >= 0x80) { *ptr = '.'; } ptr++; } printf("\"%S\"", str); } else { printf("STRING %x", l); } break; } case InlineSwitch: { long cases = readData<long>(); long *pArray = new long[cases]; long i=0; for(i=0;i<cases;i++) { pArray[i] = readData<long>(); } printf("("); for(i=0;i<cases;i++) { if (i != 0) printf(", "); printf("IL_%04x",pArray[i] + position); } printf(")"); delete [] pArray; break; } case ShortInlineI: printf("%d", readData<char>()); break; case ShortInlineR: printf("%f", readData<float>()); break; default: printf("Error, unexpected opcode type\n"); break; } printf("\n"); } }
// Similar to the function above. TODO: factor them together before checkin. void DecodeDynamicIL(BYTE *data, ULONG Size, DacpObjectData& tokenArray) { // There is no header for this dynamic guy. // Set globals position = 0; pBuffer = data; // At this time no exception information will be displayed (fix soon) UINT indentCount = 0; ULONG endCodePosition = Size; while(position < endCodePosition) { printf("%*sIL_%04x: ", indentCount, "", position); unsigned int c = readOpcode(); OpCode opcode = opcodes[c]; printf("%s ", opcode.name); switch(opcode.args) { case InlineNone: break; case ShortInlineVar: printf("VAR OR ARG %d",readData<BYTE>()); break; case InlineVar: printf("VAR OR ARG %d",readData<unsigned short>()); break; case InlineI: printf("%d",readData<long>()); break; case InlineR: printf("%f",readData<double>()); break; case InlineBrTarget: printf("IL_%04x",readData<long>() + position); break; case ShortInlineBrTarget: printf("IL_%04x",readData<BYTE>() + position); break; case InlineI8: printf("%ld", readData<__int64>()); break; case InlineMethod: case InlineField: case InlineType: case InlineTok: case InlineSig: case InlineString: { long l = readData<long>(); DisassembleToken(tokenArray, l); break; } case InlineSwitch: { long cases = readData<long>(); long *pArray = new long[cases]; long i=0; for(i=0;i<cases;i++) { pArray[i] = readData<long>(); } printf("("); for(i=0;i<cases;i++) { if (i != 0) printf(", "); printf("IL_%04x",pArray[i] + position); } printf(")"); delete [] pArray; break; } case ShortInlineI: printf("%d", readData<char>()); break; case ShortInlineR: printf("%f", readData<float>()); break; default: printf("Error, unexpected opcode type\n"); break; } printf("\n"); } }
/*static*/ SIZE_T DebuggerFunction::Disassemble(BOOL native, SIZE_T offset, BYTE *codeStart, BYTE *codeEnd, WCHAR *buffer, BOOL noAddress, DebuggerModule *module, BYTE *ilCode) { SIZE_T ret; if (!native) { // // Write the address // swprintf(buffer, L"[IL:%.4x] ", offset); buffer += wcslen(buffer); // // Read next opcode // BYTE *ip = codeStart + offset; DWORD opcode; BYTE *prevIP = ip; ip = (BYTE *) ReadNextOpcode(ip, &opcode); // // Get the end of the instruction // BYTE *nextIP = (BYTE *) SkipIP(ip, opcode); BYTE *bytes = prevIP; // // Dump the raw value of the stream // while (bytes < ip) { swprintf(buffer, L"%.2x", *bytes++); buffer += wcslen(buffer); } *buffer++ = ':'; while (bytes < nextIP) { swprintf(buffer, L"%.2x", *bytes++); buffer += wcslen(buffer); } while (bytes++ - prevIP < 8) { *buffer++ = L' '; *buffer++ = L' '; } // // Print the opcode // swprintf(buffer, L"%s\t", opcodeName[opcode]); buffer += wcslen(buffer); int tokenType = operandDescription[opcode]; if (tokenType == InlineSwitch) { *buffer++ = L'\n'; DWORD caseCount = GET_UNALIGNED_VAL32(ip); ip += 4; DWORD index = 0; while (index < caseCount) { swprintf(buffer, L"\t\t\t%.5d:[%.4x]\n", index, GET_UNALIGNED_VAL16(ip)); buffer += wcslen(buffer); index++; ip += 4; } } else if (tokenType == InlinePhi) { *buffer++ = L'\n'; DWORD caseCount = *(unsigned char*)ip; ip += 1; DWORD index = 0; while (index < caseCount) { swprintf(buffer, L"\t\t\t%.5d: [%.4x]\n", index, GET_UNALIGNED_VAL16(ip)); buffer += wcslen(buffer); index++; ip += 2; } } else if (tokenType == InlineTok || tokenType == InlineType || tokenType == InlineField || tokenType == InlineMethod) { DisassembleToken(module->GetMetaData(), GET_UNALIGNED_VAL32(ip), buffer); buffer += wcslen(buffer); } else { DisassembleArgument(ip, ip - ilCode, tokenType, buffer); buffer += wcslen(buffer); } ret = nextIP - ilCode; } else { // Write the address if (!noAddress) { swprintf(buffer, L"[%.4x] ", offset); buffer += wcslen(buffer); } ret = 0xffff; } *buffer++ = L'\n'; *buffer = L'\0'; return (ret); }