summaryrefslogtreecommitdiff
path: root/src/ToolBox/superpmi/superpmi-shared/asmdumper.cpp
blob: 8fc944ac90687644e4ebc4d7a905f33185115adc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

#include "standardpch.h"
#include "asmdumper.h"

void ASMDumper::DumpToFile(HANDLE hFile, MethodContext* mc, CompileResult* cr)
{
    CORINFO_METHOD_INFO info;
    unsigned            flags = 0;
    mc->repCompileMethod(&info, &flags);

#define bufflen 4096
    DWORD bytesWritten;
    char  buff[bufflen];

    int buff_offset = 0;
    ZeroMemory(buff, bufflen * sizeof(char));
    buff_offset += sprintf_s(&buff[buff_offset], bufflen - buff_offset,
                             ";;Generated from SuperPMI on original input '%s'", cr->repProcessName());
    buff_offset += sprintf_s(&buff[buff_offset], bufflen - buff_offset, "\r\n Method Name \"%s\"",
                             mc->repGetMethodName(info.ftn, nullptr));
    WriteFile(hFile, buff, buff_offset * sizeof(char), &bytesWritten, nullptr);

    ULONG              hotCodeSize;
    ULONG              coldCodeSize;
    ULONG              roDataSize;
    ULONG              xcptnsCount;
    CorJitAllocMemFlag flag;
    unsigned char*     hotCodeBlock;
    unsigned char*     coldCodeBlock;
    unsigned char*     roDataBlock;
    void*              orig_hotCodeBlock;
    void*              orig_coldCodeBlock;
    void*              orig_roDataBlock;

    cr->repAllocMem(&hotCodeSize, &coldCodeSize, &roDataSize, &xcptnsCount, &flag, &hotCodeBlock, &coldCodeBlock,
                    &roDataBlock, &orig_hotCodeBlock, &orig_coldCodeBlock, &orig_roDataBlock);
    cr->applyRelocs(hotCodeBlock, hotCodeSize, orig_hotCodeBlock);
    cr->applyRelocs(coldCodeBlock, coldCodeSize, orig_coldCodeBlock);
    cr->applyRelocs(roDataBlock, roDataSize, orig_roDataBlock);

#ifdef USE_MSVCDIS

#ifdef _TARGET_AMD64_
    DIS* disasm = DIS::PdisNew(DIS::distX8664);
#elif _TARGET_X86_
    DIS* disasm = DIS::PdisNew(DIS::distX86);
#endif
    size_t offset = 0;
    while (offset < hotCodeSize)
    {
        buff_offset = 0;
        ZeroMemory(buff, bufflen * sizeof(char));

        DIS::INSTRUCTION instr;
        DIS::OPERAND     ops[3];

        size_t instrSize = disasm->CbDisassemble(0, (void*)(hotCodeBlock + offset), 15);
        if (instrSize == 0)
        {
            LogWarning("Zero sized instruction");
            break;
        }
        disasm->FDecode(&instr, ops, 3);

        wchar_t instrMnemonic[64]; // I never know how much to allocate...
        disasm->CchFormatInstr(instrMnemonic, 64);
        buff_offset += sprintf_s(&buff[buff_offset], bufflen - buff_offset, "\r\n%p %S",
                                 (void*)((size_t)orig_hotCodeBlock + offset), instrMnemonic);
        buff_offset += sprintf_s(&buff[buff_offset], bufflen - buff_offset, "   ; ");
        for (unsigned int i = 0; i < instrSize; i++)
            buff_offset +=
                sprintf_s(&buff[buff_offset], bufflen - buff_offset, "%02x ", *((BYTE*)(hotCodeBlock + offset + i)));
        WriteFile(hFile, buff, buff_offset * sizeof(char), &bytesWritten, nullptr);
        offset += instrSize;
    }

    delete disasm;

#else // !USE_MSVCDIS

    buff_offset = 0;
    ZeroMemory(buff, bufflen * sizeof(char));
    buff_offset += sprintf_s(&buff[buff_offset], bufflen - buff_offset, ";; No disassembler available");
    WriteFile(hFile, buff, buff_offset * sizeof(char), &bytesWritten, nullptr);

#endif // !USE_MSVCDIS

    FlushFileBuffers(hFile);
}