Skip to content

Commit dd3d5c6

Browse files
jchodorCompute-Runtime-Automation
authored andcommitted
feature: Add logic for reading loaded library's version
getLoadedLibVersion is intended for reading version of a library that was already loaded into the process prior to this call (i.e. new instance of the library willnot be loaded). Note: Currently, only windows version of this functionality is implemented. Related-To: GSD-10248 Signed-off-by: Chodor, Jaroslaw <[email protected]>
1 parent db3f268 commit dd3d5c6

File tree

11 files changed

+477
-6
lines changed

11 files changed

+477
-6
lines changed

CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,12 @@ include(GNUInstallDirs)
7878
if(USE_SANITIZE_UB AND WIN32)
7979
add_definitions(-D_ITERATOR_DEBUG_LEVEL=0)
8080
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Xlinker /NODEFAULTLIB:clang_rt.ubsan_standalone_cxx-x86_64.lib")
81-
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Xlinker /NODEFAULTLIB:clang_rt.ubsan_standalone_cxx-x86_64.lib")
81+
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Xlinker /NODEFAULTLIB:clang_rt.ubsan_standalone_cxx-x86_64.lib")
82+
endif()
83+
84+
if(WIN32 AND NOT MSVC)
85+
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Xlinker onecore.lib")
86+
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Xlinker onecore.lib")
8287
endif()
8388

8489
if(NOT DEFINED NEO_USE_CL_CACHE)

opencl/test/unit_test/offline_compiler/segfault_test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ if(WIN32)
2222
${NEO_SHARED_DIRECTORY}/os_interface/windows/os_library_win.cpp
2323
${NEO_SHARED_DIRECTORY}/os_interface/windows/os_library_win.h
2424
${NEO_SHARED_TEST_DIRECTORY}/common/os_interface/windows/signal_utils.cpp
25+
${NEO_SHARED_TEST_DIRECTORY}/common/os_interface/windows/sys_calls.cpp
2526
${OCLOC_DIRECTORY}/source/utilities/windows/safety_guard_windows.h
2627
${OCLOC_DIRECTORY}/source/utilities/windows/seh_exception.cpp
2728
${OCLOC_DIRECTORY}/source/utilities/windows/seh_exception.h

shared/source/os_interface/linux/os_library_linux.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ const std::string OsLibrary::createFullSystemPath(const std::string &name) {
3131
return name;
3232
}
3333

34+
bool getLoadedLibVersion(const std::string &libName, const std::string &regexVersionPattern, std::string &outVersion, std::string &errReason) {
35+
return false;
36+
}
37+
3438
namespace Linux {
3539

3640
OsLibrary::OsLibrary(const OsLibraryCreateProperties &properties) {

shared/source/os_interface/os_library.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,7 @@ class OsLibrary {
5151
virtual bool isLoaded() = 0;
5252
virtual std::string getFullPath() = 0;
5353
};
54+
55+
bool getLoadedLibVersion(const std::string &libName, const std::string &regexVersionPattern, std::string &outVersion, std::string &errReason);
56+
5457
} // namespace NEO

shared/source/os_interface/windows/os_library_win.cpp

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77

88
#include "shared/source/os_interface/windows/os_library_win.h"
99

10+
#include "shared/source/helpers/debug_helpers.h"
11+
#include "shared/source/os_interface/windows/sys_calls.h"
12+
13+
#include <iomanip>
14+
#include <regex>
15+
#include <sstream>
16+
1017
namespace NEO {
1118

1219
OsLibrary *OsLibrary::load(const OsLibraryCreateProperties &properties) {
@@ -109,4 +116,82 @@ std::string OsLibrary::getFullPath() {
109116
return std::string(dllPath);
110117
}
111118
} // namespace Windows
119+
120+
bool getLoadedLibVersion(const std::string &libName, const std::string &regexVersionPattern, std::string &outVersion, std::string &errReason) {
121+
HMODULE mod = NULL;
122+
auto ret = SysCalls::getModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, std::wstring(libName.begin(), libName.end()).c_str(), &mod);
123+
if (0 == ret) {
124+
errReason = "Failed to read info of " + libName + " - GetModuleHandleExA failed, GetLastError=" + std::to_string(SysCalls::getLastError());
125+
return false;
126+
}
127+
128+
wchar_t path[MAX_PATH];
129+
DWORD length = SysCalls::getModuleFileNameW(mod, path, MAX_PATH);
130+
if (0 == length) {
131+
errReason = "Failed to read info of " + libName + " - GetModuleFileName failed, GetLastError=" + std::to_string(SysCalls::getLastError());
132+
return false;
133+
}
134+
135+
std::wstring trimmedPath = {path, length};
136+
DWORD infoVersioSize = SysCalls::getFileVersionInfoSizeW(trimmedPath.c_str(), nullptr);
137+
if (0 == infoVersioSize) {
138+
errReason = "Failed to read info of " + libName + " - GetFileVersionInfoSize failed, GetLastError=" + std::to_string(SysCalls::getLastError());
139+
return false;
140+
}
141+
142+
std::vector<char> fileInformationBackingStorage;
143+
fileInformationBackingStorage.resize(infoVersioSize);
144+
ret = SysCalls::getFileVersionInfoW(path, 0, static_cast<DWORD>(fileInformationBackingStorage.size()), fileInformationBackingStorage.data());
145+
if (0 == ret) {
146+
errReason = "Failed to read info of " + libName + " - GetFileVersionInfo failed, GetLastError=" + std::to_string(SysCalls::getLastError());
147+
return false;
148+
}
149+
150+
struct LangCodePage {
151+
WORD lang;
152+
WORD codePage;
153+
};
154+
155+
LangCodePage *translateInfo = nullptr;
156+
157+
unsigned int langCodePagesSize = 0;
158+
ret = SysCalls::verQueryValueW(fileInformationBackingStorage.data(), L"\\VarFileInfo\\Translation", reinterpret_cast<LPVOID *>(&translateInfo), &langCodePagesSize);
159+
if (0 == ret) {
160+
errReason = "Failed to read info of " + libName + " - VerQueryValue(\\VarFileInfo\\Translation) failed, GetLastError=" + std::to_string(SysCalls::getLastError());
161+
return false;
162+
}
163+
164+
auto truncateWstringToString = [](const std::wstring &ws) {
165+
std::string ret;
166+
std::transform(ws.begin(), ws.end(), std::back_inserter(ret), [](wchar_t wc) { return static_cast<char>(wc); });
167+
return ret;
168+
};
169+
170+
size_t langCodePagesCount = (langCodePagesSize / sizeof(LangCodePage));
171+
std::regex versionPattern{regexVersionPattern};
172+
for (size_t j = 0; j < langCodePagesCount; ++j) {
173+
std::wstringstream subBlockPath;
174+
subBlockPath << L"\\StringFileInfo\\";
175+
subBlockPath << std::setw(4) << std::setfill(L'0') << std::hex << translateInfo[j].lang;
176+
subBlockPath << std::setw(4) << std::setfill(L'0') << std::hex << translateInfo[j].codePage;
177+
subBlockPath << L"\\ProductVersion";
178+
179+
wchar_t *data;
180+
unsigned int len = 0;
181+
ret = SysCalls::verQueryValueW(fileInformationBackingStorage.data(), subBlockPath.str().c_str(), (LPVOID *)&data, &len);
182+
if (0 == ret) {
183+
errReason = "Failed to read info of " + libName + " - VerQueryValue(" + truncateWstringToString(subBlockPath.str()) + ") failed, GetLastError=" + std::to_string(SysCalls::getLastError());
184+
return false;
185+
}
186+
187+
auto sdata = truncateWstringToString(data);
188+
if (std::regex_search(sdata, versionPattern)) {
189+
outVersion = sdata;
190+
return true;
191+
}
192+
}
193+
194+
errReason = "Could not find version info for " + std::string(libName) + " that would satisfy expected pattern\n";
195+
return false;
196+
}
112197
} // namespace NEO

shared/source/os_interface/windows/sys_calls.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,5 +180,22 @@ BOOL heapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem) {
180180
SIZE_T virtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength) {
181181
return VirtualQuery(lpAddress, lpBuffer, dwLength);
182182
}
183+
184+
BOOL getModuleHandleExW(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE *phModule) {
185+
return ::GetModuleHandleExW(dwFlags, lpModuleName, phModule);
186+
}
187+
DWORD getModuleFileNameW(HMODULE hModule, LPWSTR lpFilename, DWORD nSize) {
188+
return ::GetModuleFileNameW(hModule, lpFilename, nSize);
189+
}
190+
DWORD getFileVersionInfoSizeW(LPCWSTR lptstrFilename, LPDWORD lpdwHandle) {
191+
return ::GetFileVersionInfoSizeW(lptstrFilename, lpdwHandle);
192+
}
193+
BOOL getFileVersionInfoW(LPCWSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData) {
194+
return ::GetFileVersionInfoW(lptstrFilename, dwHandle, dwLen, lpData);
195+
}
196+
BOOL verQueryValueW(LPCVOID pBlock, LPCWSTR lpSubBlock, LPVOID *lpBuffer, PUINT puLen) {
197+
return ::VerQueryValueW(pBlock, lpSubBlock, lpBuffer, puLen);
198+
}
199+
183200
} // namespace SysCalls
184201
} // namespace NEO

shared/source/os_interface/windows/sys_calls.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ CONFIGRET cmGetDeviceInterfaceList(LPGUID interfaceClassGuid, DEVINSTID_W pDevic
5959
LPVOID heapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes);
6060
BOOL heapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem);
6161
SIZE_T virtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength);
62+
BOOL getModuleHandleExW(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE *phModule);
63+
DWORD getModuleFileNameW(HMODULE hModule, LPWSTR lpFilename, DWORD nSize);
64+
DWORD getFileVersionInfoSizeW(LPCWSTR lptstrFilename, LPDWORD lpdwHandle);
65+
BOOL getFileVersionInfoW(LPCWSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData);
66+
BOOL verQueryValueW(LPCVOID pBlock, LPCWSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen);
67+
DWORD getLastError();
68+
6269
} // namespace SysCalls
6370

6471
} // namespace NEO

shared/test/common/common_main.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
#include <iostream>
3535
#include <mutex>
3636
#include <thread>
37+
#if !defined(__linux__) && NDEBUG
38+
#include <regex>
39+
#endif
3740

3841
namespace NEO {
3942
namespace PagaFaultManagerTestConfig {
@@ -139,6 +142,13 @@ void applyCommonWorkarounds() {
139142

140143
bool enableAlarm = true;
141144
int main(int argc, char **argv) {
145+
#if !defined(__linux__) && NDEBUG
146+
std::regex _dummyRegex{"dummyRegex"}; // these dummy objects are neededed to prevent false-positive
147+
std::wstringstream _dummyWstringstream; // leaks when using instances of std::regex and std::wstringstream in tests
148+
_dummyWstringstream << std::setw(4) // in Windows Release builds
149+
<< std::setfill(L'0')
150+
<< std::hex << 5;
151+
#endif
142152
int retVal = 0;
143153
bool useDefaultListener = false;
144154
bool enableAbrt = true;

shared/test/common/os_interface/windows/mock_sys_calls.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
#pragma once
99

10-
#include "sys_calls.h"
10+
#include "shared/source/os_interface/windows/sys_calls.h"
1111

1212
using mockCreateEventClbT = HANDLE (*)(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCSTR lpName, void *data);
1313
inline mockCreateEventClbT mockCreateEventClb = nullptr;
@@ -67,5 +67,12 @@ extern CONFIGRET (*sysCallsCmGetDeviceInterfaceListSize)(PULONG pulLen, LPGUID i
6767
extern CONFIGRET (*sysCallsCmGetDeviceInterfaceList)(LPGUID interfaceClassGuid, DEVINSTID_W pDeviceID, PZZWSTR buffer, ULONG bufferLen, ULONG ulFlags);
6868
extern LPVOID (*sysCallsHeapAlloc)(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes);
6969
extern BOOL (*sysCallsHeapFree)(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem);
70+
71+
extern BOOL (*sysCallsGetModuleHandleExW)(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE *phModule);
72+
extern DWORD (*sysCallsGetModuleFileNameW)(HMODULE hModule, LPWSTR lpFilename, DWORD nSize);
73+
extern DWORD (*sysCallsGetFileVersionInfoSizeW)(LPCWSTR lptstrFilename, LPDWORD lpdwHandle);
74+
extern BOOL (*sysCallsGetFileVersionInfoW)(LPCWSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData);
75+
extern BOOL (*sysCallsVerQueryValueW)(LPCVOID pBlock, LPCWSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen);
76+
extern DWORD (*sysCallsGetLastError)();
7077
} // namespace SysCalls
7178
} // namespace NEO

shared/test/common/os_interface/windows/sys_calls.cpp

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@
55
*
66
*/
77

8-
#include "sys_calls.h"
8+
#include "shared/source/os_interface/windows/sys_calls.h"
99

10+
#include "shared/source/os_interface/windows/os_inc.h"
1011
#include "shared/test/common/os_interface/windows/mock_sys_calls.h"
1112

12-
#include "os_inc.h"
13-
1413
#include <cstdint>
1514
#include <unordered_map>
1615
#include <vector>
@@ -422,6 +421,50 @@ SIZE_T virtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_
422421
memcpy_s(lpBuffer, sizeof(MEMORY_BASIC_INFORMATION), &virtualQueryMemoryBasicInformation, sizeof(MEMORY_BASIC_INFORMATION));
423422
return sizeof(MEMORY_BASIC_INFORMATION);
424423
}
424+
425+
BOOL(*sysCallsGetModuleHandleExW)
426+
(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE *phModule) = nullptr;
427+
DWORD(*sysCallsGetModuleFileNameW)
428+
(HMODULE hModule, LPWSTR lpFilename, DWORD nSize) = nullptr;
429+
DWORD(*sysCallsGetFileVersionInfoSizeW)
430+
(LPCWSTR lptstrFilename, LPDWORD lpdwHandle) = nullptr;
431+
BOOL(*sysCallsGetFileVersionInfoW)
432+
(LPCWSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData) = nullptr;
433+
BOOL(*sysCallsVerQueryValueW)
434+
(LPCVOID pBlock, LPCWSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen) = nullptr;
435+
DWORD(*sysCallsGetLastError)
436+
() = nullptr;
437+
BOOL getModuleHandleExW(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE *phModule) {
438+
if (sysCallsGetModuleHandleExW) {
439+
return sysCallsGetModuleHandleExW(dwFlags, lpModuleName, phModule);
440+
}
441+
return FALSE;
442+
}
443+
DWORD getModuleFileNameW(HMODULE hModule, LPWSTR lpFilename, DWORD nSize) {
444+
if (sysCallsGetModuleFileNameW) {
445+
return sysCallsGetModuleFileNameW(hModule, lpFilename, nSize);
446+
}
447+
return 0;
448+
}
449+
DWORD getFileVersionInfoSizeW(LPCWSTR lptstrFilename, LPDWORD lpdwHandle) {
450+
if (sysCallsGetFileVersionInfoSizeW) {
451+
return sysCallsGetFileVersionInfoSizeW(lptstrFilename, lpdwHandle);
452+
}
453+
return 0;
454+
}
455+
BOOL getFileVersionInfoW(LPCWSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData) {
456+
if (sysCallsGetFileVersionInfoW) {
457+
return sysCallsGetFileVersionInfoW(lptstrFilename, dwHandle, dwLen, lpData);
458+
}
459+
return FALSE;
460+
}
461+
BOOL verQueryValueW(LPCVOID pBlock, LPCWSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen) {
462+
if (sysCallsVerQueryValueW) {
463+
return sysCallsVerQueryValueW(pBlock, lpSubBlock, lplpBuffer, puLen);
464+
}
465+
return FALSE;
466+
}
467+
425468
} // namespace SysCalls
426469

427470
bool isShutdownInProgress() {

0 commit comments

Comments
 (0)