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