| 1 | // |
| 2 | // Copyright (c) Microsoft. All rights reserved. |
| 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. |
| 4 | // |
| 5 | |
| 6 | #include "standardpch.h" |
| 7 | #include "asmdumper.h" |
| 8 | |
| 9 | void ASMDumper::DumpToFile(HANDLE hFile, MethodContext* mc, CompileResult* cr) |
| 10 | { |
| 11 | CORINFO_METHOD_INFO info; |
| 12 | unsigned flags = 0; |
| 13 | mc->repCompileMethod(&info, &flags); |
| 14 | |
| 15 | #define bufflen 4096 |
| 16 | DWORD bytesWritten; |
| 17 | char buff[bufflen]; |
| 18 | |
| 19 | int buff_offset = 0; |
| 20 | ZeroMemory(buff, bufflen * sizeof(char)); |
| 21 | buff_offset += sprintf_s(&buff[buff_offset], bufflen - buff_offset, |
| 22 | ";;Generated from SuperPMI on original input '%s'" , cr->repProcessName()); |
| 23 | buff_offset += sprintf_s(&buff[buff_offset], bufflen - buff_offset, "\r\n Method Name \"%s\"" , |
| 24 | mc->repGetMethodName(info.ftn, nullptr)); |
| 25 | WriteFile(hFile, buff, buff_offset * sizeof(char), &bytesWritten, nullptr); |
| 26 | |
| 27 | ULONG hotCodeSize; |
| 28 | ULONG coldCodeSize; |
| 29 | ULONG roDataSize; |
| 30 | ULONG xcptnsCount; |
| 31 | CorJitAllocMemFlag flag; |
| 32 | unsigned char* hotCodeBlock; |
| 33 | unsigned char* coldCodeBlock; |
| 34 | unsigned char* roDataBlock; |
| 35 | void* orig_hotCodeBlock; |
| 36 | void* orig_coldCodeBlock; |
| 37 | void* orig_roDataBlock; |
| 38 | |
| 39 | cr->repAllocMem(&hotCodeSize, &coldCodeSize, &roDataSize, &xcptnsCount, &flag, &hotCodeBlock, &coldCodeBlock, |
| 40 | &roDataBlock, &orig_hotCodeBlock, &orig_coldCodeBlock, &orig_roDataBlock); |
| 41 | cr->applyRelocs(hotCodeBlock, hotCodeSize, orig_hotCodeBlock); |
| 42 | cr->applyRelocs(coldCodeBlock, coldCodeSize, orig_coldCodeBlock); |
| 43 | cr->applyRelocs(roDataBlock, roDataSize, orig_roDataBlock); |
| 44 | |
| 45 | #ifdef USE_MSVCDIS |
| 46 | |
| 47 | #ifdef _TARGET_AMD64_ |
| 48 | DIS* disasm = DIS::PdisNew(DIS::distX8664); |
| 49 | #elif _TARGET_X86_ |
| 50 | DIS* disasm = DIS::PdisNew(DIS::distX86); |
| 51 | #endif |
| 52 | size_t offset = 0; |
| 53 | while (offset < hotCodeSize) |
| 54 | { |
| 55 | buff_offset = 0; |
| 56 | ZeroMemory(buff, bufflen * sizeof(char)); |
| 57 | |
| 58 | DIS::INSTRUCTION instr; |
| 59 | DIS::OPERAND ops[3]; |
| 60 | |
| 61 | size_t instrSize = disasm->CbDisassemble(0, (void*)(hotCodeBlock + offset), 15); |
| 62 | if (instrSize == 0) |
| 63 | { |
| 64 | LogWarning("Zero sized instruction" ); |
| 65 | break; |
| 66 | } |
| 67 | disasm->FDecode(&instr, ops, 3); |
| 68 | |
| 69 | wchar_t instrMnemonic[64]; // I never know how much to allocate... |
| 70 | disasm->CchFormatInstr(instrMnemonic, 64); |
| 71 | buff_offset += sprintf_s(&buff[buff_offset], bufflen - buff_offset, "\r\n%p %S" , |
| 72 | (void*)((size_t)orig_hotCodeBlock + offset), instrMnemonic); |
| 73 | buff_offset += sprintf_s(&buff[buff_offset], bufflen - buff_offset, " ; " ); |
| 74 | for (unsigned int i = 0; i < instrSize; i++) |
| 75 | buff_offset += |
| 76 | sprintf_s(&buff[buff_offset], bufflen - buff_offset, "%02x " , *((BYTE*)(hotCodeBlock + offset + i))); |
| 77 | WriteFile(hFile, buff, buff_offset * sizeof(char), &bytesWritten, nullptr); |
| 78 | offset += instrSize; |
| 79 | } |
| 80 | |
| 81 | delete disasm; |
| 82 | |
| 83 | #else // !USE_MSVCDIS |
| 84 | |
| 85 | buff_offset = 0; |
| 86 | ZeroMemory(buff, bufflen * sizeof(char)); |
| 87 | buff_offset += sprintf_s(&buff[buff_offset], bufflen - buff_offset, ";; No disassembler available" ); |
| 88 | WriteFile(hFile, buff, buff_offset * sizeof(char), &bytesWritten, nullptr); |
| 89 | |
| 90 | #endif // !USE_MSVCDIS |
| 91 | |
| 92 | FlushFileBuffers(hFile); |
| 93 | } |