Skip to content

Commit

Permalink
Intercept loader_log in testing framework
Browse files Browse the repository at this point in the history
Allows capturing the output of loader_log and comparing it with expected
values using fputs/fputc on *nix, and OutputDebugString on Windows.

This interception is necessary due to the differing behavior between the
debug log (through debug utils messenger) and the actual stderr output.
  • Loading branch information
charles-lunarg committed Nov 12, 2024
1 parent 50349c4 commit 002838d
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 84 deletions.
10 changes: 8 additions & 2 deletions tests/framework/shim/shim.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,15 @@ struct FrameworkEnvironment; // forward declaration
// Necessary to have inline definitions as shim is a dll and thus functions
// defined in the .cpp wont be found by the rest of the application
struct PlatformShim {
PlatformShim() = default;
PlatformShim(std::vector<fs::FolderManager>* folders) : folders(folders) {}
PlatformShim() { fputs_stderr_log.reserve(65536); }
PlatformShim(std::vector<fs::FolderManager>* folders) : folders(folders) { fputs_stderr_log.reserve(65536); }

// Used to get info about which drivers & layers have been added to folders
std::vector<fs::FolderManager>* folders;

// Captures the output to stderr from fputs & fputc - aka the output of loader_log()
std::string fputs_stderr_log;

// Test Framework interface
void reset();

Expand All @@ -156,6 +159,9 @@ struct PlatformShim {
void add_manifest(ManifestCategory category, std::filesystem::path const& path);
void add_unsecured_manifest(ManifestCategory category, std::filesystem::path const& path);

void clear_logs() { fputs_stderr_log.clear(); }
bool find_in_log(std::string const& search_text) const { return fputs_stderr_log.find(search_text) != std::string::npos; }

// platform specific shim interface
#if defined(WIN32)
// Control Platform Elevation Level
Expand Down
33 changes: 33 additions & 0 deletions tests/framework/shim/unix_shim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ FRAMEWORK_EXPORT PlatformShim* get_platform_shim(std::vector<fs::FolderManager>*
#if defined(HAVE___SECURE_GETENV)
#define __SECURE_GETENV_FUNC_NAME __secure_getenv
#endif
#define PRINTF_FUNC_NAME printf
#define FPUTS_FUNC_NAME fputs
#define FPUTC_FUNC_NAME fputc
#elif defined(__APPLE__)
#define OPENDIR_FUNC_NAME my_opendir
#define READDIR_FUNC_NAME my_readdir
Expand All @@ -80,6 +83,8 @@ FRAMEWORK_EXPORT PlatformShim* get_platform_shim(std::vector<fs::FolderManager>*
#define __SECURE_GETENV_FUNC_NAME my__secure_getenv
#endif
#endif
#define FPUTS_FUNC_NAME my_fputs
#define FPUTC_FUNC_NAME my_fputc
#endif

using PFN_OPENDIR = DIR* (*)(const char* path_name);
Expand All @@ -93,6 +98,8 @@ using PFN_GETEGID = gid_t (*)(void);
#if defined(HAVE_SECURE_GETENV) || defined(HAVE___SECURE_GETENV)
using PFN_SEC_GETENV = char* (*)(const char* name);
#endif
using PFN_FPUTS = int (*)(const char* str, FILE* stream);
using PFN_FPUTC = int (*)(int c, FILE* stream);

#if defined(__APPLE__)
#define real_opendir opendir
Expand All @@ -109,6 +116,8 @@ using PFN_SEC_GETENV = char* (*)(const char* name);
#if defined(HAVE___SECURE_GETENV)
#define real__secure_getenv __secure_getenv
#endif
#define real_fputs fputs
#define real_fputc fputc
#else
PFN_OPENDIR real_opendir = nullptr;
PFN_READDIR real_readdir = nullptr;
Expand All @@ -124,6 +133,8 @@ PFN_SEC_GETENV real_secure_getenv = nullptr;
#if defined(HAVE___SECURE_GETENV)
PFN_SEC_GETENV real__secure_getenv = nullptr;
#endif
PFN_FPUTS real_fputs = nullptr;
PFN_FPUTC real_fputc = nullptr;
#endif

FRAMEWORK_EXPORT DIR* OPENDIR_FUNC_NAME(const char* path_name) {
Expand Down Expand Up @@ -327,6 +338,27 @@ FRAMEWORK_EXPORT char* __SECURE_GETENV_FUNC_NAME(const char* name) {
}
#endif
#endif

FRAMEWORK_EXPORT int FPUTS_FUNC_NAME(const char* str, FILE* stream) {
#if !defined(__APPLE__)
if (!real_fputs) real_fputs = (PFN_FPUTS)dlsym(RTLD_NEXT, "fputs");
#endif
if (stream == stderr) {
platform_shim.fputs_stderr_log += str;
}
return real_fputs(str, stream);
}

FRAMEWORK_EXPORT int FPUTC_FUNC_NAME(int ch, FILE* stream) {
#if !defined(__APPLE__)
if (!real_fputc) real_fputc = (PFN_FPUTC)dlsym(RTLD_NEXT, "fputc");
#endif
if (stream == stderr) {
platform_shim.fputs_stderr_log += ch;
}
return real_fputc(ch, stream);
}

#if defined(__APPLE__)
FRAMEWORK_EXPORT CFBundleRef my_CFBundleGetMainBundle() {
static CFBundleRef global_bundle{};
Expand Down Expand Up @@ -383,6 +415,7 @@ __attribute__((used)) static Interposer _interpose__secure_getenv MACOS_ATTRIB =
VOIDP_CAST(__secure_getenv)};
#endif
#endif
__attribute__((used)) static Interposer _interpose_fputs MACOS_ATTRIB = {VOIDP_CAST(my_fputs), VOIDP_CAST(fputs)};
__attribute__((used)) static Interposer _interpose_CFBundleGetMainBundle MACOS_ATTRIB = {VOIDP_CAST(my_CFBundleGetMainBundle),
VOIDP_CAST(CFBundleGetMainBundle)};
__attribute__((used)) static Interposer _interpose_CFBundleCopyResourcesDirectoryURL MACOS_ATTRIB = {
Expand Down
14 changes: 14 additions & 0 deletions tests/framework/shim/windows_shim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
#include <ntstatus.h>
#endif

#include <windows.h>
#include <debugapi.h>

#include "shim.h"

#include "detours.h"
Expand Down Expand Up @@ -405,6 +408,15 @@ LONG WINAPI ShimGetPackagePathByFullName(_In_ PCWSTR packageFullName, _Inout_ UI
return 0;
}

using PFN_OutputDebugStringA = void (*)(LPCSTR lpOutputString);
static PFN_OutputDebugStringA fp_OutputDebugStringA = OutputDebugStringA;

void intercept_OutputDebugStringA(LPCSTR lpOutputString) {
if (lpOutputString != nullptr) {
platform_shim.fputs_stderr_log += lpOutputString;
}
}

// Initialization
void WINAPI DetourFunctions() {
if (!gdi32_dll) {
Expand Down Expand Up @@ -454,6 +466,7 @@ void WINAPI DetourFunctions() {
DetourAttach(&(PVOID &)fpRegCloseKey, (PVOID)ShimRegCloseKey);
DetourAttach(&(PVOID &)fpGetPackagesByPackageFamily, (PVOID)ShimGetPackagesByPackageFamily);
DetourAttach(&(PVOID &)fpGetPackagePathByFullName, (PVOID)ShimGetPackagePathByFullName);
DetourAttach(&(PVOID &)fp_OutputDebugStringA, (PVOID)intercept_OutputDebugStringA);
LONG error = DetourTransactionCommit();

if (error != NO_ERROR) {
Expand Down Expand Up @@ -483,6 +496,7 @@ void DetachFunctions() {
DetourDetach(&(PVOID &)fpRegCloseKey, (PVOID)ShimRegCloseKey);
DetourDetach(&(PVOID &)fpGetPackagesByPackageFamily, (PVOID)ShimGetPackagesByPackageFamily);
DetourDetach(&(PVOID &)fpGetPackagePathByFullName, (PVOID)ShimGetPackagePathByFullName);
DetourDetach(&(PVOID &)fp_OutputDebugStringA, (PVOID)intercept_OutputDebugStringA);
DetourTransactionCommit();
}

Expand Down
Loading

0 comments on commit 002838d

Please sign in to comment.