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//----------------------------------------------------------
7// SuperPMI-Shim.cpp - thin shim for the jit
8//----------------------------------------------------------
9
10#include "standardpch.h"
11#include "superpmi-shim-counter.h"
12#include "runtimedetails.h"
13#include "coreclrcallbacks.h"
14#include "icorjitcompiler.h"
15#include "errorhandling.h"
16#include "logging.h"
17#include "spmiutil.h"
18#include "jithost.h"
19
20HMODULE g_hRealJit = 0; // We leak this currently (could do the proper shutdown in process_detach)
21WCHAR* g_realJitPath = nullptr; // We leak this (could do the proper shutdown in process_detach)
22WCHAR* g_logPath = nullptr; // Again, we leak this one too...
23char* g_logFilePath = nullptr; // We *don't* leak this, hooray!
24WCHAR* g_HomeDirectory = nullptr;
25WCHAR* g_DefaultRealJitPath = nullptr;
26MethodCallSummarizer* g_globalContext = nullptr;
27
28void SetDefaultPaths()
29{
30 if (g_HomeDirectory == nullptr)
31 {
32 g_HomeDirectory = GetEnvironmentVariableWithDefaultW(W("HOME"), W("."));
33 }
34
35 if (g_DefaultRealJitPath == nullptr)
36 {
37 size_t len = wcslen(g_HomeDirectory) + 1 + wcslen(DEFAULT_REAL_JIT_NAME_W) + 1;
38 g_DefaultRealJitPath = new WCHAR[len];
39 wcscpy_s(g_DefaultRealJitPath, len, g_HomeDirectory);
40 wcscat_s(g_DefaultRealJitPath, len, DIRECTORY_SEPARATOR_STR_W);
41 wcscat_s(g_DefaultRealJitPath, len, DEFAULT_REAL_JIT_NAME_W);
42 }
43}
44
45void SetLibName()
46{
47 if (g_realJitPath == nullptr)
48 {
49 g_realJitPath = GetEnvironmentVariableWithDefaultW(W("SuperPMIShimPath"), g_DefaultRealJitPath);
50 }
51}
52
53void SetLogPath()
54{
55 if (g_logPath == nullptr)
56 {
57 g_logPath = GetEnvironmentVariableWithDefaultW(W("SuperPMIShimLogPath"), g_HomeDirectory);
58 }
59}
60
61// TODO: this only works for ANSI file paths...
62void SetLogFilePath()
63{
64 if (g_logFilePath == nullptr)
65 {
66 // If the environment variable isn't set, we don't enable file logging
67 g_logFilePath = GetEnvironmentVariableWithDefaultA("SuperPMIShimLogFilePath", nullptr);
68 }
69}
70
71extern "C" BOOL
72#ifndef FEATURE_PAL
73 APIENTRY
74#endif // !FEATURE_PAL
75 DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
76{
77 switch (ul_reason_for_call)
78 {
79 case DLL_PROCESS_ATTACH:
80#ifdef FEATURE_PAL
81 if (0 != PAL_InitializeDLL())
82 {
83 fprintf(stderr, "Error: Fail to PAL_InitializeDLL\n");
84 exit(1);
85 }
86#endif // FEATURE_PAL
87
88 Logger::Initialize();
89 SetLogFilePath();
90 Logger::OpenLogFile(g_logFilePath);
91 break;
92
93 case DLL_PROCESS_DETACH:
94 Logger::Shutdown();
95
96 delete[] g_logFilePath;
97 g_logFilePath = nullptr;
98
99 if (g_globalContext != nullptr)
100 {
101 g_globalContext->SaveTextFile();
102 }
103
104 break;
105
106 case DLL_THREAD_ATTACH:
107 case DLL_THREAD_DETACH:
108 break;
109 }
110 return TRUE;
111}
112
113// Exported via def file
114extern "C" void __stdcall jitStartup(ICorJitHost* host)
115{
116 SetDefaultPaths();
117 SetLibName();
118
119 if (!LoadRealJitLib(g_hRealJit, g_realJitPath))
120 {
121 return;
122 }
123
124 // Get the required entrypoint
125 PjitStartup pnjitStartup = (PjitStartup)::GetProcAddress(g_hRealJit, "jitStartup");
126 if (pnjitStartup == nullptr)
127 {
128 // This portion of the interface is not used by the JIT under test.
129 g_ourJitHost = nullptr;
130 return;
131 }
132
133 g_ourJitHost = new JitHost(host);
134
135 if (g_globalContext == nullptr)
136 {
137 SetLogPath();
138 g_globalContext = new MethodCallSummarizer(g_logPath);
139 }
140
141 g_ourJitHost->setMethodCallSummarizer(g_globalContext);
142
143 pnjitStartup(g_ourJitHost);
144}
145
146// Exported via def file
147extern "C" ICorJitCompiler* __stdcall getJit()
148{
149 DWORD dwRetVal = 0;
150 PgetJit pngetJit;
151 interceptor_ICJC* pJitInstance = nullptr;
152 ICorJitCompiler* tICJI = nullptr;
153
154 SetDefaultPaths();
155 SetLibName();
156
157 if (!LoadRealJitLib(g_hRealJit, g_realJitPath))
158 {
159 return nullptr;
160 }
161
162 // get the required entrypoints
163 pngetJit = (PgetJit)::GetProcAddress(g_hRealJit, "getJit");
164 if (pngetJit == 0)
165 {
166 LogError("getJit() - GetProcAddress 'getJit' failed (0x%08x)", ::GetLastError());
167 return nullptr;
168 }
169
170 tICJI = pngetJit();
171 if (tICJI == nullptr)
172 {
173 LogError("getJit() - pngetJit gave us null");
174 return nullptr;
175 }
176
177 pJitInstance = new interceptor_ICJC();
178 pJitInstance->original_ICorJitCompiler = tICJI;
179
180 if (g_globalContext == nullptr)
181 {
182 SetLogPath();
183 g_globalContext = new MethodCallSummarizer(g_logPath);
184 }
185 pJitInstance->mcs = g_globalContext;
186 return pJitInstance;
187}
188
189// Exported via def file
190extern "C" void __stdcall sxsJitStartup(CoreClrCallbacks const& original_cccallbacks)
191{
192 PsxsJitStartup pnsxsJitStartup;
193
194 SetDefaultPaths();
195 SetLibName();
196
197 if (!LoadRealJitLib(g_hRealJit, g_realJitPath))
198 {
199 return;
200 }
201
202 // get entry point
203 pnsxsJitStartup = (PsxsJitStartup)::GetProcAddress(g_hRealJit, "sxsJitStartup");
204 if (pnsxsJitStartup == 0)
205 {
206 LogError("sxsJitStartup() - GetProcAddress 'sxsJitStartup' failed (0x%08x)", ::GetLastError());
207 return;
208 }
209
210 // Setup CoreClrCallbacks and call sxsJitStartup
211 original_CoreClrCallbacks = new CoreClrCallbacks();
212 original_CoreClrCallbacks->m_hmodCoreCLR = original_cccallbacks.m_hmodCoreCLR;
213 original_CoreClrCallbacks->m_pfnIEE = original_cccallbacks.m_pfnIEE;
214 original_CoreClrCallbacks->m_pfnGetCORSystemDirectory = original_cccallbacks.m_pfnGetCORSystemDirectory;
215 original_CoreClrCallbacks->m_pfnGetCLRFunction = original_cccallbacks.m_pfnGetCLRFunction;
216
217 CoreClrCallbacks* temp = new CoreClrCallbacks();
218
219 temp->m_hmodCoreCLR = original_cccallbacks.m_hmodCoreCLR;
220 temp->m_pfnIEE = IEE_t;
221 temp->m_pfnGetCORSystemDirectory = original_cccallbacks.m_pfnGetCORSystemDirectory;
222 temp->m_pfnGetCLRFunction = GetCLRFunction;
223
224 pnsxsJitStartup(*temp);
225}
226