Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions src/vulkan/wrapper/graphics_env_hooks.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "graphics_env_hooks.h"
#include <iostream>
#include <vector>
#include <string>
#include <dlfcn.h>

extern "C" {
#include "wrapper_log.h"
#include "wrapper_debug.h"
}

#define PATH "/data/data/com.winlator.cmod/files/imagefs/usr/lib"

extern "C"
bool set_layer_paths() {
void* handle = dlopen("libgraphicsenv.so", RTLD_NOW);
#define LAYER_ERROR(fmt, ...) \
WLOGE(fmt, ## __VA_ARGS__); \
dlclose(handle); \
return false

if (!handle) {
LAYER_ERROR("Cannot open libgraphicsenv.so");
}

#define FIND(var, sig, name) auto var = sig (dlsym(handle, name)); \
if (!var) { \
LAYER_ERROR("Cannot find symbol in libgraphicsenv.so: " #name); \
} \
WLOGD("Found " #name " in libgraphicsenv.so at %p", var);

FIND(getInstance, (void* (*)()), "_ZN7android11GraphicsEnv11getInstanceEv");
FIND(getLayerPaths, (const std::string&(*)(void*)), "_ZN7android11GraphicsEnv13getLayerPathsEv");
FIND(getAppNamespace, (void* (*)(void*)), "_ZN7android11GraphicsEnv15getAppNamespaceEv");
FIND(setLayerPaths, (void (*)(void*, void*, const std::string)), "_ZN7android11GraphicsEnv13setLayerPathsEPNS_21NativeLoaderNamespaceENSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE");

void* instance = getInstance();
if (!instance) {
LAYER_ERROR("GraphicsEnv::getInstance() failed");
}

auto path = getLayerPaths(instance);
if (!path.empty()) {
if (path == PATH) {
WLOGD("GraphicsEnv::mLayerPaths is already set correctly");
dlclose(handle);
return true;
}
LAYER_ERROR("GraphicsEnv::mLayerPaths is already set to %s, cannot perform hijacking", path.c_str());
}
void* app_namespace = getAppNamespace(instance);
setLayerPaths(instance, app_namespace, PATH);
path = getLayerPaths(instance);
if (path != PATH) {
LAYER_ERROR("GraphicsEnv::mLayerPaths failed to be set correctly, found %s", path.c_str());
}

WLOGD("GraphicsEnv::mLayerPaths set to %s", path.c_str());
return true;
}
11 changes: 11 additions & 0 deletions src/vulkan/wrapper/graphics_env_hooks.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

#ifdef __cplusplus
extern "C" {
#endif

bool set_layer_paths(void);

#ifdef __cplusplus
}
#endif
1 change: 1 addition & 0 deletions src/vulkan/wrapper/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ wrapper_files = files(
'wrapper_debug.c',
'wrapper_objects.c',
'spirv_edit.cpp',
'graphics_env_hooks.cpp',
)

wrapper_deps = [
Expand Down
153 changes: 114 additions & 39 deletions src/vulkan/wrapper/wrapper_instance.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "vk_debug_utils.h"
#include "wrapper_debug.h"
#include "vk_printers.h"
#include "graphics_env_hooks.h"

const struct vk_instance_extension_table wrapper_instance_extensions = {
.KHR_get_surface_capabilities2 = true,
Expand Down Expand Up @@ -52,6 +53,8 @@ static struct vk_instance_extension_table *supported_instance_extensions;

#include <dlfcn.h>

static bool g_intercepted_layer_path = false;

static void *get_vulkan_handle_icd()
{
char *path = getenv("ADRENOTOOLS_DRIVER_PATH");
Expand All @@ -64,6 +67,10 @@ static void *get_vulkan_handle_icd()

struct stat sb;

if (CHECK_FLAG("USE_VVL")) {
g_intercepted_layer_path = set_layer_paths();
}

if (hooks && path && (stat(path, &sb) == 0)) {
WLOG("get_vulkan_handle: hooks=%s, path=%s, name=%s", hooks, path, name);
char *temp;
Expand All @@ -76,15 +83,8 @@ static void *get_vulkan_handle_icd()
}
}

// static void* icd_handle;

static void *get_vulkan_handle()
{
// __log("in get_vulkan_handle");
// if (!icd_handle)
// icd_handle = get_vulkan_handle_icd();
// void* vvl = dlopen("/data/user/0/com.winlator.cmod/files/imagefs/usr/lib/libVkLayer_khronos_validation.so", RTLD_NOW | RTLD_LOCAL);
// __log("Got vvl layer: %p", vvl);
return get_vulkan_handle_icd();
}

Expand Down Expand Up @@ -298,43 +298,118 @@ WRAPPER_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
wrapper_create_info.pApplicationInfo = &wrapper_application_info;
wrapper_create_info.enabledExtensionCount = wrapper_enable_extension_count;
wrapper_create_info.ppEnabledExtensionNames = wrapper_enable_extensions;

const char* layers[wrapper_create_info.enabledLayerCount + 1];
char time_str[20];
char path[256];
const char* log_filename[] = { path };
const char* report_flags[] = { "error", "info", "warn" };
VkBool32 validate_sync[] = { VK_TRUE };
VkBool32 printf_enable[] = { VK_TRUE };
VkBool32 printf_verbose[] = { VK_TRUE };
VkBool32 validate_best_practices[] = { VK_TRUE };
VkBool32 validate_best_practices_arm[] = { VK_TRUE };

const VkLayerSettingEXT layer_setting[] = {
{
"VK_LAYER_KHRONOS_validation",
"log_filename",
VK_LAYER_SETTING_TYPE_STRING_EXT,
1,
log_filename,
},
{
"VK_LAYER_KHRONOS_validation",
"report_flags",
VK_LAYER_SETTING_TYPE_STRING_EXT,
3,
report_flags,
},
{
"VK_LAYER_KHRONOS_validation",
"validate_sync",
VK_LAYER_SETTING_TYPE_BOOL32_EXT,
1,
validate_sync,
},
{
"VK_LAYER_KHRONOS_validation",
"printf_enable",
VK_LAYER_SETTING_TYPE_BOOL32_EXT,
1,
printf_enable,
},
{
"VK_LAYER_KHRONOS_validation",
"printf_verbose",
VK_LAYER_SETTING_TYPE_BOOL32_EXT,
1,
printf_verbose,
},
{
"VK_LAYER_KHRONOS_validation",
"validate_best_practices",
VK_LAYER_SETTING_TYPE_BOOL32_EXT,
1,
validate_best_practices,
},
{
"VK_LAYER_KHRONOS_validation",
"validate_best_practices_arm",
VK_LAYER_SETTING_TYPE_BOOL32_EXT,
1,
validate_best_practices_arm,
},
};

VkLayerSettingsCreateInfoEXT layer_settings_create_info = {
VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT,
NULL,
3,
layer_setting,
};

if (CHECK_FLAG("USE_VVL")) {
if (!g_intercepted_layer_path) {
WLOGE("Failed to intercept GraphicsEnv::SetLayerPaths(), cannot load VVL");
return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
}

uint32_t layerCount;
_vkEnumerateInstanceLayerProperties(&layerCount, NULL);

// Initialize vvl
// if (icd_handle != vulkan_library_handle) {
// __log("Additional initialization - adding more pnext chains");
// VkLayerInstanceCreateInfo *chain_info = (VkLayerInstanceCreateInfo *)&wrapper_create_info;
// while ((chain_info->sType != VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO || chain_info->function != 0) && chain_info->pNext) {
// chain_info = (VkLayerInstanceCreateInfo *)&chain_info->pNext;
// }
// if (chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && chain_info->function == 0) {
// __log("ERROR: Found a loader create info");
// unreachable("");
// } else {
// if (!chain_info->pNext) {
// __log("Starting new loader create info");
// void* next = dlsym(icd_handle, "vkGetInstanceProcAddr");
// __log("Next: %p", next);
// VkLayerInstanceLink deviceInfo = {
// .pfnNextGetInstanceProcAddr = next
// };

// VkLayerInstanceCreateInfo info = {
// .sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO,
// .function = 0,
// .u.pLayerInfo = &deviceInfo
// };
// chain_info->pNext = &info;
// __log("Created new loader create info");
// } else {
// __log("ERROR");
// unreachable("");
// }
// }
// }
if (layerCount == 0) {
WLOGE("No layers found, make sure that /data/data/com.winlator.cmod/files/imagefs/usr/lib/libVkLayer_khronos_validation.so exists");
return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
} else {
VkLayerProperties availableLayers[layerCount];
_vkEnumerateInstanceLayerProperties(&layerCount, availableLayers);

WLOGD("Found %d layers in /data/data/com.winlator.cmod/files/imagefs/usr/lib/", layerCount);
for (int i = 0; i < layerCount; i++) {
WLOGD(" Layer[%d]: %s", i, availableLayers[i].layerName);
}
}

wrapper_create_info.enabledLayerCount += 1;
for (int i = 0; i < wrapper_create_info.enabledLayerCount - 1; i++) {
WLOGD("enabled_layer[%d]: %s", i, wrapper_create_info.ppEnabledLayerNames[i]);
layers[i] = wrapper_create_info.ppEnabledLayerNames[i];
}
layers[wrapper_create_info.enabledLayerCount - 1] = "VK_LAYER_KHRONOS_validation";
wrapper_create_info.ppEnabledLayerNames = layers;

get_current_time_string(time_str, sizeof(time_str));
sprintf(path, "/sdcard/Documents/Wrapper/%s_%s.%s.%d.txt", "vvl", time_str, getprogname(), getpid());
layer_settings_create_info.pNext = wrapper_create_info.pNext;
wrapper_create_info.pNext = &layer_settings_create_info;
}

result = dispatch_create_instance(&wrapper_create_info, pAllocator,
&instance->dispatch_handle);

if (result != VK_SUCCESS) {
WLOGE("vkCreateInstance failed, result = %d", result);
vk_instance_finish(&instance->vk);
vk_free2(vk_default_allocator(), pAllocator, instance);
return vk_error(NULL, result);
Expand Down
56 changes: 0 additions & 56 deletions src/vulkan/wrapper/wrapper_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,62 +163,6 @@ static inline uint32_t get_bc_block_size(VkFormat format) {
}
}


typedef enum VkLayerFunction_ {
VK_LAYER_FUNCTION_LINK = 0,
VK_LAYER_FUNCTION_DEVICE = 1,
VK_LAYER_FUNCTION_INSTANCE = 2
} VkLayerFunction;
/*
* When creating the device chain the loader needs to pass
* down information about it's device structure needed at
* the end of the chain. Passing the data via the
* VkLayerInstanceInfo avoids issues with finding the
* exact instance being used.
*/
typedef struct VkLayerInstanceInfo_ {
void* instance_info;
PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
} VkLayerInstanceInfo;
typedef struct VkLayerInstanceLink_ {
struct VkLayerInstanceLink_* pNext;
PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
} VkLayerInstanceLink;
/*
* When creating the device chain the loader needs to pass
* down information about it's device structure needed at
* the end of the chain. Passing the data via the
* VkLayerDeviceInfo avoids issues with finding the
* exact instance being used.
*/
typedef struct VkLayerDeviceInfo_ {
void* device_info;
PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
} VkLayerDeviceInfo;
typedef struct {
VkStructureType sType; // VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO
const void* pNext;
VkLayerFunction function;
union {
VkLayerInstanceLink* pLayerInfo;
VkLayerInstanceInfo instanceInfo;
} u;
} VkLayerInstanceCreateInfo;
typedef struct VkLayerDeviceLink_ {
struct VkLayerDeviceLink_* pNext;
PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
PFN_vkGetDeviceProcAddr pfnNextGetDeviceProcAddr;
} VkLayerDeviceLink;
typedef struct {
VkStructureType sType; // VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO
const void* pNext;
VkLayerFunction function;
union {
VkLayerDeviceLink* pLayerInfo;
VkLayerDeviceInfo deviceInfo;
} u;
} VkLayerDeviceCreateInfo;

static VkFormat unwrap_vk_format_physical_device(struct wrapper_physical_device* pdevice, VkFormat in_format) {
if (!pdevice) {
WLOGE("unwrap_vk_format: null pdevice");
Expand Down
Loading