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