summaryrefslogtreecommitdiff
path: root/src/ToolBox/superpmi/superpmi/jithost.cpp
blob: d14909bae10e440bbf906d27190426d7a2d2b1bb (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
120
121
//
// 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 "superpmi.h"
#include "jitinstance.h"
#include "icorjitinfo.h"
#include "jithost.h"

// Look for 'key' as an environment variable named COMPlus_<key>. The returned value
// is nullptr if it is not found, or a string if found. If not nullptr, the returned
// value must be freed with jitInstance.freeLongLivedArray(value).
wchar_t* GetCOMPlusVariable(const wchar_t* key, JitInstance& jitInstance)
{
    static const wchar_t Prefix[]  = W("COMPlus_");
    static const size_t  PrefixLen = (sizeof(Prefix) / sizeof(Prefix[0])) - 1;

    // Prepend "COMPlus_" to the provided key
    size_t   keyLen       = wcslen(key);
    size_t   keyBufferLen = keyLen + PrefixLen + 1;
    wchar_t* keyBuffer =
        reinterpret_cast<wchar_t*>(jitInstance.allocateArray(static_cast<ULONG>(sizeof(wchar_t) * keyBufferLen)));
    wcscpy_s(keyBuffer, keyBufferLen, Prefix);
    wcscpy_s(&keyBuffer[PrefixLen], keyLen + 1, key);

    // Look up the environment variable
    DWORD valueLen = GetEnvironmentVariableW(keyBuffer, nullptr, 0);
    if (valueLen == 0)
    {
        jitInstance.freeArray(keyBuffer);
        return nullptr;
    }

    // Note this value must live as long as the jit instance does.
    wchar_t* value       = reinterpret_cast<wchar_t*>(jitInstance.allocateLongLivedArray(sizeof(wchar_t) * valueLen));
    DWORD    newValueLen = GetEnvironmentVariableW(keyBuffer, value, valueLen);

    jitInstance.freeArray(keyBuffer);
    if (valueLen < newValueLen)
    {
        jitInstance.freeLongLivedArray(value);
        return nullptr;
    }

    return value;
}

JitHost::JitHost(JitInstance& jitInstance) : jitInstance(jitInstance)
{
}

void* JitHost::allocateMemory(size_t size, bool usePageAllocator)
{
    return InitIEEMemoryManager(&jitInstance)->ClrVirtualAlloc(nullptr, size, 0, 0);
}

void JitHost::freeMemory(void* block, bool usePageAllocator)
{
    InitIEEMemoryManager(&jitInstance)->ClrVirtualFree(block, 0, 0);
}

int JitHost::getIntConfigValue(const wchar_t* key, int defaultValue)
{
    jitInstance.mc->cr->AddCall("getIntConfigValue");
    int result = jitInstance.mc->repGetIntConfigValue(key, defaultValue);

    if (result != defaultValue)
    {
        return result;
    }

    // Look for special case keys.
    if (wcscmp(key, W("SuperPMIMethodContextNumber")) == 0)
    {
        return jitInstance.mc->index;
    }

    // If the result is the default value, probe the environment for
    // a COMPlus variable with the same name.
    wchar_t* complus = GetCOMPlusVariable(key, jitInstance);
    if (complus == nullptr)
    {
        return defaultValue;
    }

    // Parse the value as a hex integer.
    wchar_t* endPtr;
    result         = static_cast<int>(wcstoul(complus, &endPtr, 16));
    bool succeeded = (errno != ERANGE) && (endPtr != complus);
    jitInstance.freeLongLivedArray(complus);

    return succeeded ? result : defaultValue;
}

const wchar_t* JitHost::getStringConfigValue(const wchar_t* key)
{
    jitInstance.mc->cr->AddCall("getStringConfigValue");
    const wchar_t* result = jitInstance.mc->repGetStringConfigValue(key);

    if (result != nullptr)
    {
        // Now we need to dup it, so you can call freeStringConfigValue() on what we return.
        size_t   resultLenInChars = wcslen(result) + 1;
        wchar_t* dupResult = (wchar_t*)jitInstance.allocateLongLivedArray((ULONG)(sizeof(wchar_t) * resultLenInChars));
        wcscpy_s(dupResult, resultLenInChars, result);

        return dupResult;
    }

    // If the result is the default value, probe the environment for
    // a COMPlus variable with the same name.
    return GetCOMPlusVariable(key, jitInstance);
}

void JitHost::freeStringConfigValue(const wchar_t* value)
{
    jitInstance.mc->cr->AddCall("freeStringConfigValue");
    jitInstance.freeLongLivedArray((void*)value);
}