summaryrefslogtreecommitdiff
path: root/src/vm/dumpdiagnosticprotocolhelper.cpp
blob: 60d1fd05a0af15680839333d74904ea4bd33ec4b (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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include "common.h"
#include "fastserializer.h"
#include "dumpdiagnosticprotocolhelper.h"
#include "diagnosticsipc.h"
#include "diagnosticsprotocol.h"

#ifdef FEATURE_PERFTRACING

#ifdef FEATURE_PAL

void DumpDiagnosticProtocolHelper::HandleIpcMessage(DiagnosticsIpc::IpcMessage& message, IpcStream* pStream)
{
    CONTRACTL
    {
        THROWS;
        GC_TRIGGERS;
        MODE_PREEMPTIVE;
        PRECONDITION(pStream != nullptr);
    }
    CONTRACTL_END;

    switch ((DumpCommandId)message.GetHeader().CommandId)
    {
    case DumpCommandId::GenerateCoreDump:
        DumpDiagnosticProtocolHelper::GenerateCoreDump(message, pStream);
        break;

    default:
        STRESS_LOG1(LF_DIAGNOSTICS_PORT, LL_WARNING, "Received unknown request type (%d)\n", message.GetHeader().CommandSet);
        DiagnosticsIpc::IpcMessage::SendErrorMessage(pStream, CORDIAGIPC_E_UNKNOWN_COMMAND);
        delete pStream;
        break;
    }
}

const GenerateCoreDumpCommandPayload* GenerateCoreDumpCommandPayload::TryParse(BYTE* lpBuffer, uint16_t& BufferSize)
{
    CONTRACTL
    {
        NOTHROW;
        GC_TRIGGERS;
        MODE_PREEMPTIVE;
        PRECONDITION(lpBuffer != nullptr);
    }
    CONTRACTL_END;

    GenerateCoreDumpCommandPayload* payload = new (nothrow) GenerateCoreDumpCommandPayload;
    if (payload == nullptr)
    {
        // OOM
        return nullptr;
    }

    payload->incomingBuffer = lpBuffer;
    uint8_t* pBufferCursor = payload->incomingBuffer;
    uint32_t bufferLen = BufferSize;
    if (!TryParseString(pBufferCursor, bufferLen, payload->dumpName) ||
        !::TryParse(pBufferCursor, bufferLen, payload->dumpType) ||
        !::TryParse(pBufferCursor, bufferLen, payload->diagnostics))
    {
        delete payload;
        return nullptr;
    }

    return payload;
}

void DumpDiagnosticProtocolHelper::GenerateCoreDump(DiagnosticsIpc::IpcMessage& message, IpcStream* pStream)
{
    CONTRACTL
    {
        THROWS;
        GC_TRIGGERS;
        MODE_PREEMPTIVE;
        PRECONDITION(pStream != nullptr);
    }
    CONTRACTL_END;

    if (pStream == nullptr)
        return;

    NewHolder<const GenerateCoreDumpCommandPayload> payload = message.TryParsePayload<GenerateCoreDumpCommandPayload>();
    if (payload == nullptr)
    {
        DiagnosticsIpc::IpcMessage::SendErrorMessage(pStream, CORDIAGIPC_E_BAD_ENCODING);
        delete pStream;
        return;
    }

    MAKE_UTF8PTR_FROMWIDE_NOTHROW(szDumpName, payload->dumpName);
    if (szDumpName != nullptr)
    {
        if (!PAL_GenerateCoreDump(szDumpName, payload->dumpType, payload->diagnostics))
        {
            DiagnosticsIpc::IpcMessage::SendErrorMessage(pStream, E_FAIL);
            delete pStream;
            return;
        }
    }
    else 
    {
        DiagnosticsIpc::IpcMessage::SendErrorMessage(pStream, E_OUTOFMEMORY);
        delete pStream;
        return;
    }

    DiagnosticsIpc::IpcMessage successResponse;
    if (successResponse.Initialize(DiagnosticsIpc::GenericSuccessHeader, S_OK))
        successResponse.Send(pStream);
    delete pStream;
}

#endif // FEATURE_PAL

#endif // FEATURE_PERFTRACING