mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2025-07-21 01:45:47 +00:00
Move dead submodules in-tree
Signed-off-by: swurl <swurl@swurl.xyz>
This commit is contained in:
parent
c0cceff365
commit
6c655321e6
4081 changed files with 1185566 additions and 45 deletions
135
externals/libadrenotools/src/bcenabler.cpp
vendored
Normal file
135
externals/libadrenotools/src/bcenabler.cpp
vendored
Normal file
|
@ -0,0 +1,135 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
// Copyright © 2021 Billy Laws
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <adrenotools/bcenabler.h>
|
||||
#include "gen/bcenabler_patch.h"
|
||||
|
||||
enum adrenotools_bcn_type adrenotools_get_bcn_type(uint32_t major, uint32_t minor, uint32_t vendorId) {
|
||||
if (vendorId != 0x5143 || major != 512)
|
||||
return ADRENOTOOLS_BCN_INCOMPATIBLE;
|
||||
|
||||
if (minor >= 514)
|
||||
return ADRENOTOOLS_BCN_BLOB;
|
||||
|
||||
return ADRENOTOOLS_BCN_PATCH;
|
||||
}
|
||||
|
||||
// Searches /proc/self/maps for the first free page after the given address
|
||||
static void *find_free_page(uintptr_t address) {
|
||||
std::ifstream procMaps("/proc/self/maps");
|
||||
|
||||
uintptr_t end{};
|
||||
|
||||
for (std::string line; std::getline(procMaps, line); ) {
|
||||
std::size_t addressSeparator{line.find('-')};
|
||||
uintptr_t start{std::strtoull(line.substr(0, addressSeparator).c_str(), nullptr, 16)};
|
||||
|
||||
if (end > address && start != end)
|
||||
return reinterpret_cast<void *>(end);
|
||||
|
||||
end = std::strtoull(line.substr(addressSeparator + 1, line.find( ' ')).c_str(), nullptr, 16);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void *align_ptr(void *ptr) {
|
||||
return reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(ptr) & ~(getpagesize() - 1));
|
||||
}
|
||||
|
||||
bool adrenotools_patch_bcn(void *vkGetPhysicalDeviceFormatPropertiesFn) {
|
||||
union Branch {
|
||||
struct {
|
||||
int32_t offset : 26; //!< 26-bit branch offset
|
||||
uint8_t sig : 6; //!< 6-bit signature (0x25 for linked, 0x5 for jump)
|
||||
};
|
||||
|
||||
uint32_t raw{};
|
||||
};
|
||||
static_assert(sizeof(Branch) == 4, "Branch size is invalid");
|
||||
|
||||
// Find the nearest unmapped page where we can place patch code
|
||||
void *patchPage{find_free_page(reinterpret_cast<uintptr_t>(vkGetPhysicalDeviceFormatPropertiesFn))};
|
||||
if (!patchPage)
|
||||
return false;
|
||||
|
||||
// Map patch region
|
||||
void *ptr{mmap(patchPage, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0)};
|
||||
if (ptr != patchPage)
|
||||
return false;
|
||||
|
||||
// Allow reading from the blob's .text section since some devices enable ---X
|
||||
// Protect two pages just in case we happen to land on a page boundary
|
||||
if (mprotect(align_ptr(vkGetPhysicalDeviceFormatPropertiesFn), getpagesize() * 2, PROT_WRITE | PROT_READ | PROT_EXEC))
|
||||
return false;
|
||||
|
||||
// First branch in this function is targeted at the function we want to patch
|
||||
Branch *blInst{reinterpret_cast<Branch *>(vkGetPhysicalDeviceFormatPropertiesFn)};
|
||||
|
||||
constexpr uint8_t BranchLinkSignature{0x25};
|
||||
|
||||
// Search for first instruction with the BL signature
|
||||
while (blInst->sig != BranchLinkSignature)
|
||||
blInst++;
|
||||
|
||||
// Internal QGL format conversion function that we need to patch
|
||||
uint32_t *convFormatFn{reinterpret_cast<uint32_t *>(blInst) + blInst->offset};
|
||||
|
||||
// See mprotect call above
|
||||
// This time we also set PROT_WRITE so we can write our patch to the page
|
||||
if (mprotect(align_ptr(convFormatFn), getpagesize() * 2, PROT_WRITE | PROT_READ | PROT_EXEC))
|
||||
return false;
|
||||
|
||||
// This would normally set the default result to 0 (error) in the format not found case
|
||||
constexpr uint32_t ClearResultSignature{0x2a1f03e0};
|
||||
|
||||
// We replace it with a branch to our own extended if statement which adds in the extra things for BCn
|
||||
uint32_t *clearResultPtr{convFormatFn};
|
||||
while (*clearResultPtr != ClearResultSignature)
|
||||
clearResultPtr++;
|
||||
|
||||
// Ensure we don't write out of bounds
|
||||
if (PatchRawData_size > getpagesize())
|
||||
return false;
|
||||
|
||||
// Copy the patch function to our mapped page
|
||||
memcpy(patchPage, PatchRawData, PatchRawData_size);
|
||||
|
||||
// Fixup the patch code so it correctly returns back to the driver after running
|
||||
constexpr uint32_t PatchReturnFixupMagic{0xffffffff};
|
||||
constexpr uint8_t BranchSignature{0x5};
|
||||
|
||||
uint32_t *fixupTargetPtr{clearResultPtr + 1};
|
||||
auto *fixupPtr{reinterpret_cast<uint32_t *>(patchPage)};
|
||||
for (long unsigned int i{}; i < (PatchRawData_size / sizeof(uint32_t)); i++, fixupPtr++) {
|
||||
if (*fixupPtr == PatchReturnFixupMagic) {
|
||||
Branch branchToDriver{
|
||||
{
|
||||
.offset = static_cast<int32_t>((reinterpret_cast<intptr_t>(fixupTargetPtr) - reinterpret_cast<intptr_t>(fixupPtr)) / sizeof(int32_t)),
|
||||
.sig = BranchSignature,
|
||||
}
|
||||
};
|
||||
|
||||
*fixupPtr = branchToDriver.raw;
|
||||
}
|
||||
}
|
||||
|
||||
Branch branchToPatch{
|
||||
{
|
||||
.offset = static_cast<int32_t>((reinterpret_cast<intptr_t>(patchPage) - reinterpret_cast<intptr_t>(clearResultPtr)) / sizeof(int32_t)),
|
||||
.sig = BranchSignature,
|
||||
}
|
||||
};
|
||||
|
||||
*clearResultPtr = branchToPatch.raw;
|
||||
|
||||
asm volatile("ISB");
|
||||
|
||||
// Done!
|
||||
return true;
|
||||
}
|
83
externals/libadrenotools/src/bcenabler_patch.s
vendored
Normal file
83
externals/libadrenotools/src/bcenabler_patch.s
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
cmp w0, 131
|
||||
bne .L2
|
||||
mov w0, 71
|
||||
b .L3
|
||||
.L2:
|
||||
cmp w0, 133
|
||||
bne .L4
|
||||
mov w0, 71
|
||||
b .L3
|
||||
.L4:
|
||||
cmp w0, 132
|
||||
bne .L5
|
||||
mov w0, 72
|
||||
b .L3
|
||||
.L5:
|
||||
cmp w0, 134
|
||||
bne .L6
|
||||
mov w0, 72
|
||||
b .L3
|
||||
.L6:
|
||||
cmp w0, 135
|
||||
bne .L7
|
||||
mov w0, 74
|
||||
b .L3
|
||||
.L7:
|
||||
cmp w0, 136
|
||||
bne .L8
|
||||
mov w0, 75
|
||||
b .L3
|
||||
.L8:
|
||||
cmp w0, 137
|
||||
bne .L9
|
||||
mov w0, 77
|
||||
b .L3
|
||||
.L9:
|
||||
cmp w0, 138
|
||||
bne .L10
|
||||
mov w0, 78
|
||||
b .L3
|
||||
.L10:
|
||||
cmp w0, 139
|
||||
bne .L11
|
||||
mov w0, 80
|
||||
b .L3
|
||||
.L11:
|
||||
cmp w0, 140
|
||||
bne .L12
|
||||
mov w0, 81
|
||||
b .L3
|
||||
.L12:
|
||||
cmp w0, 141
|
||||
bne .L13
|
||||
mov w0, 83
|
||||
b .L3
|
||||
.L13:
|
||||
cmp w0, 142
|
||||
bne .L14
|
||||
mov w0, 84
|
||||
b .L3
|
||||
.L14:
|
||||
cmp w0, 143
|
||||
bne .L15
|
||||
mov w0, 95
|
||||
b .L3
|
||||
.L15:
|
||||
cmp w0, 144
|
||||
bne .L16
|
||||
mov w0, 96
|
||||
b .L3
|
||||
.L16:
|
||||
cmp w0, 145
|
||||
bne .L17
|
||||
mov w0, 98
|
||||
b .L3
|
||||
.L17:
|
||||
cmp w0, 146
|
||||
bne .L18
|
||||
mov w0, 99
|
||||
b .L3
|
||||
.L18:
|
||||
mov w0, 0
|
||||
.L3:
|
||||
.word 0xffffffff // Branch fixup
|
210
externals/libadrenotools/src/driver.cpp
vendored
Normal file
210
externals/libadrenotools/src/driver.cpp
vendored
Normal file
|
@ -0,0 +1,210 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
// Copyright © 2021 Billy Laws
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <android/api-level.h>
|
||||
#include <android/log.h>
|
||||
#include <android_linker_ns.h>
|
||||
#include "hook/kgsl.h"
|
||||
#include "hook/hook_impl_params.h"
|
||||
#include <adrenotools/driver.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void *adrenotools_open_libvulkan(int dlopenFlags, int featureFlags, const char *tmpLibDir, const char *hookLibDir, const char *customDriverDir, const char *customDriverName, const char *fileRedirectDir, void **userMappingHandle) {
|
||||
// Bail out if linkernsbypass failed to load, this probably means we're on api < 28
|
||||
if (!linkernsbypass_load_status())
|
||||
return nullptr;
|
||||
|
||||
// Always use memfd on Q+ since it's guaranteed to work
|
||||
if (android_get_device_api_level() >= 29)
|
||||
tmpLibDir = nullptr;
|
||||
|
||||
// Verify that params for specific features are only passed if they are enabled
|
||||
if (!(featureFlags & ADRENOTOOLS_DRIVER_FILE_REDIRECT) && fileRedirectDir)
|
||||
return nullptr;
|
||||
|
||||
if (!(featureFlags & ADRENOTOOLS_DRIVER_CUSTOM) && (customDriverDir || customDriverName))
|
||||
return nullptr;
|
||||
|
||||
if (!(featureFlags & ADRENOTOOLS_DRIVER_GPU_MAPPING_IMPORT) && userMappingHandle)
|
||||
return nullptr;
|
||||
|
||||
// Verify that params for enabled features are correct
|
||||
struct stat buf{};
|
||||
|
||||
if (featureFlags & ADRENOTOOLS_DRIVER_CUSTOM) {
|
||||
if (!customDriverName || !customDriverDir)
|
||||
return nullptr;
|
||||
|
||||
if (stat((std::string(customDriverDir) + customDriverName).c_str(), &buf) != 0)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Verify that params for enabled features are correct
|
||||
if (featureFlags & ADRENOTOOLS_DRIVER_FILE_REDIRECT) {
|
||||
if (!fileRedirectDir)
|
||||
return nullptr;
|
||||
|
||||
if (stat(fileRedirectDir, &buf) != 0)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create a namespace that can isolate our hook from the classloader namespace
|
||||
auto hookNs{android_create_namespace("adrenotools-libvulkan", hookLibDir, nullptr, ANDROID_NAMESPACE_TYPE_SHARED, nullptr, nullptr)};
|
||||
|
||||
// Link it to the default namespace so the hook can use libandroid etc
|
||||
if (!linkernsbypass_link_namespace_to_default_all_libs(hookNs))
|
||||
return nullptr;
|
||||
|
||||
// Preload the hook implementation, otherwise we get a weird issue where despite being in NEEDED of the hook lib the hook's symbols will overwrite ours and cause an infinite loop
|
||||
auto hookImpl{linkernsbypass_namespace_dlopen("libhook_impl.so", RTLD_NOW, hookNs)};
|
||||
if (!hookImpl)
|
||||
return nullptr;
|
||||
|
||||
// Pass parameters to the hook implementation
|
||||
auto initHookParam{reinterpret_cast<void (*)(const void *)>(dlsym(hookImpl, "init_hook_param"))};
|
||||
if (!initHookParam)
|
||||
return nullptr;
|
||||
|
||||
|
||||
auto importMapping{[&]() -> adrenotools_gpu_mapping * {
|
||||
if (featureFlags & ADRENOTOOLS_DRIVER_GPU_MAPPING_IMPORT) {
|
||||
// This will be leaked, but it's not a big deal since it's only a few bytes
|
||||
adrenotools_gpu_mapping *mapping{new adrenotools_gpu_mapping{}};
|
||||
*userMappingHandle = mapping;
|
||||
return mapping;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}()};
|
||||
|
||||
initHookParam(new HookImplParams(featureFlags, tmpLibDir, hookLibDir, customDriverDir, customDriverName, fileRedirectDir, importMapping));
|
||||
|
||||
// Load the libvulkan hook into the isolated namespace
|
||||
if (!linkernsbypass_namespace_dlopen("libmain_hook.so", RTLD_GLOBAL, hookNs))
|
||||
return nullptr;
|
||||
|
||||
return linkernsbypass_namespace_dlopen_unique("/system/lib64/libvulkan.so", tmpLibDir, dlopenFlags, hookNs);
|
||||
}
|
||||
|
||||
bool adrenotools_import_user_mem(void *handle, void *hostPtr, uint64_t size) {
|
||||
auto importMapping{reinterpret_cast<adrenotools_gpu_mapping *>(handle)};
|
||||
|
||||
kgsl_gpuobj_import_useraddr addr{
|
||||
.virtaddr = reinterpret_cast<uint64_t>(hostPtr),
|
||||
};
|
||||
|
||||
kgsl_gpuobj_import userMemImport{
|
||||
.priv = reinterpret_cast<uint64_t>(&addr),
|
||||
.priv_len = size,
|
||||
.flags = KGSL_CACHEMODE_WRITEBACK << KGSL_CACHEMODE_SHIFT | KGSL_MEMFLAGS_IOCOHERENT,
|
||||
.type = KGSL_USER_MEM_TYPE_ADDR,
|
||||
|
||||
};
|
||||
|
||||
kgsl_gpuobj_info info{};
|
||||
|
||||
int kgslFd{open("/dev/kgsl-3d0", O_RDWR)};
|
||||
if (kgslFd < 0)
|
||||
return false;
|
||||
|
||||
int ret{ioctl(kgslFd, IOCTL_KGSL_GPUOBJ_IMPORT, &userMemImport)};
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
info.id = userMemImport.id;
|
||||
ret = ioctl(kgslFd, IOCTL_KGSL_GPUOBJ_INFO, &info);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
importMapping->host_ptr = hostPtr;
|
||||
importMapping->gpu_addr = info.gpuaddr;
|
||||
importMapping->size = size;
|
||||
importMapping->flags = 0xc2600; //!< Unknown flags, but they are required for the mapping to work
|
||||
|
||||
close(kgslFd);
|
||||
return true;
|
||||
|
||||
err:
|
||||
close(kgslFd);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool adrenotools_mem_gpu_allocate(void *handle, uint64_t *size) {
|
||||
auto mapping{reinterpret_cast<adrenotools_gpu_mapping *>(handle)};
|
||||
|
||||
kgsl_gpuobj_alloc gpuobjAlloc{
|
||||
.size = *size,
|
||||
.flags = KGSL_CACHEMODE_WRITEBACK << KGSL_CACHEMODE_SHIFT | KGSL_MEMFLAGS_IOCOHERENT,
|
||||
};
|
||||
|
||||
kgsl_gpuobj_info info{};
|
||||
|
||||
int kgslFd{open("/dev/kgsl-3d0", O_RDWR)};
|
||||
if (kgslFd < 0)
|
||||
return false;
|
||||
|
||||
int ret{ioctl(kgslFd, IOCTL_KGSL_GPUOBJ_ALLOC, &gpuobjAlloc)};
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
*size = gpuobjAlloc.mmapsize;
|
||||
|
||||
info.id = gpuobjAlloc.id;
|
||||
|
||||
ret = ioctl(kgslFd, IOCTL_KGSL_GPUOBJ_INFO, &info);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
mapping->host_ptr = nullptr;
|
||||
mapping->gpu_addr = info.gpuaddr;
|
||||
mapping->size = *size;
|
||||
mapping->flags = 0xc2600; //!< Unknown flags, but they are required for the mapping to work
|
||||
|
||||
close(kgslFd);
|
||||
return true;
|
||||
|
||||
err:
|
||||
close(kgslFd);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool adrenotools_mem_cpu_map(void *handle, void *hostPtr, uint64_t size) {
|
||||
auto mapping{reinterpret_cast<adrenotools_gpu_mapping *>(handle)};
|
||||
|
||||
int kgslFd{open("/dev/kgsl-3d0", O_RDWR)};
|
||||
if (kgslFd < 0)
|
||||
return false;
|
||||
|
||||
mapping->host_ptr = mmap(hostPtr, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, kgslFd, mapping->gpu_addr);
|
||||
close(kgslFd);
|
||||
return mapping->host_ptr != nullptr;
|
||||
}
|
||||
|
||||
bool adrenotools_validate_gpu_mapping(void *handle) {
|
||||
auto importMapping{reinterpret_cast<adrenotools_gpu_mapping *>(handle)};
|
||||
return importMapping->gpu_addr == ADRENOTOOLS_GPU_MAPPING_SUCCEEDED_MAGIC;
|
||||
}
|
||||
|
||||
void adrenotools_set_turbo(bool turbo) {
|
||||
uint32_t enable{turbo ? 0U : 1U};
|
||||
kgsl_device_getproperty prop{
|
||||
.type = KGSL_PROP_PWRCTRL,
|
||||
.value = reinterpret_cast<void *>(&enable),
|
||||
.sizebytes = sizeof(enable),
|
||||
};
|
||||
|
||||
int kgslFd{open("/dev/kgsl-3d0", O_RDWR)};
|
||||
if (kgslFd < 0)
|
||||
return;
|
||||
|
||||
ioctl(kgslFd, IOCTL_KGSL_SETPROPERTY, &prop);
|
||||
close (kgslFd);
|
||||
}
|
27
externals/libadrenotools/src/hook/CMakeLists.txt
vendored
Normal file
27
externals/libadrenotools/src/hook/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
add_library(hook_impl SHARED hook_impl.cpp hook_impl.h hook_impl_params.h)
|
||||
|
||||
target_compile_options(hook_impl PRIVATE -Wall -Wextra)
|
||||
target_link_libraries(hook_impl linkernsbypass log)
|
||||
target_include_directories(hook_impl PRIVATE ../../include)
|
||||
set_target_properties(hook_impl PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
||||
|
||||
add_library(main_hook SHARED main_hook.c)
|
||||
|
||||
target_compile_options(main_hook PRIVATE -Wall -Wextra)
|
||||
target_link_options(main_hook PRIVATE -z global)
|
||||
target_link_libraries(main_hook hook_impl)
|
||||
set_target_properties(main_hook PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
||||
|
||||
add_library(file_redirect_hook SHARED file_redirect_hook.c)
|
||||
|
||||
target_compile_options(file_redirect_hook PRIVATE -Wall -Wextra)
|
||||
target_link_options(file_redirect_hook PRIVATE -z global)
|
||||
target_link_libraries(file_redirect_hook hook_impl)
|
||||
set_target_properties(file_redirect_hook PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
||||
|
||||
add_library(gsl_alloc_hook SHARED gsl_alloc_hook.c)
|
||||
|
||||
target_compile_options(gsl_alloc_hook PRIVATE -Wall -Wextra)
|
||||
target_link_options(gsl_alloc_hook PRIVATE -z global)
|
||||
target_link_libraries(gsl_alloc_hook hook_impl)
|
||||
set_target_properties(gsl_alloc_hook PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
5
externals/libadrenotools/src/hook/file_redirect_hook.c
vendored
Normal file
5
externals/libadrenotools/src/hook/file_redirect_hook.c
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
#include "hook_impl.h"
|
||||
|
||||
__attribute__((visibility("default"))) FILE *fopen(const char *filename, const char *mode) {
|
||||
return hook_fopen(filename, mode);
|
||||
}
|
13
externals/libadrenotools/src/hook/gsl_alloc_hook.c
vendored
Normal file
13
externals/libadrenotools/src/hook/gsl_alloc_hook.c
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include "hook_impl.h"
|
||||
|
||||
__attribute__((visibility("default"))) int gsl_memory_alloc_pure(uint32_t size, uint32_t flags, void *memDesc) {
|
||||
return hook_gsl_memory_alloc_pure_64((uint64_t)size, flags, memDesc);
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) int gsl_memory_alloc_pure_64(uint64_t size, uint32_t flags, void *memDesc) {
|
||||
return hook_gsl_memory_alloc_pure_64(size, flags, memDesc);
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) int gsl_memory_free_pure(void *memDesc) {
|
||||
return hook_gsl_memory_free_pure(memDesc);
|
||||
}
|
229
externals/libadrenotools/src/hook/hook_impl.cpp
vendored
Normal file
229
externals/libadrenotools/src/hook/hook_impl.cpp
vendored
Normal file
|
@ -0,0 +1,229 @@
|
|||
#include <initializer_list>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <android_linker_ns.h>
|
||||
#include <android/dlext.h>
|
||||
#include <android/log.h>
|
||||
#include "kgsl.h"
|
||||
#include "hook_impl_params.h"
|
||||
#include "hook_impl.h"
|
||||
|
||||
#define TAG "hook_impl"
|
||||
#define LOGI(fmt, ...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##__VA_ARGS__)
|
||||
|
||||
const HookImplParams *hook_params; //!< Bunch of info needed to load/patch the driver
|
||||
int (*gsl_memory_alloc_pure_sym)(uint32_t, uint32_t, void *);
|
||||
int (*gsl_memory_alloc_pure_64_sym)(uint64_t, uint32_t, void *);
|
||||
int (*gsl_memory_free_pure_sym)(void *);
|
||||
int kgsl_fd;
|
||||
|
||||
using gsl_memory_alloc_pure_t = decltype(gsl_memory_alloc_pure_sym);
|
||||
using gsl_memory_alloc_pure_64_t = decltype(gsl_memory_alloc_pure_64_sym);
|
||||
using gsl_memory_free_pure_t = decltype(gsl_memory_free_pure_sym);
|
||||
|
||||
__attribute__((visibility("default"))) void init_hook_param(const void *param) {
|
||||
hook_params = reinterpret_cast<const HookImplParams *>(param);
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) void init_gsl(void *alloc, void *alloc64, void *free) {
|
||||
gsl_memory_alloc_pure_sym = reinterpret_cast<gsl_memory_alloc_pure_t>(alloc);
|
||||
gsl_memory_alloc_pure_64_sym = reinterpret_cast<gsl_memory_alloc_pure_64_t>(alloc64);
|
||||
gsl_memory_free_pure_sym = reinterpret_cast<gsl_memory_free_pure_t>(free);
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) void *hook_android_dlopen_ext(const char *filename, int flags, const android_dlextinfo *extinfo) {
|
||||
auto fallback{[&]() {
|
||||
LOGI("hook_android_dlopen_ext: falling back!");
|
||||
return android_dlopen_ext(filename, flags, extinfo);
|
||||
}};
|
||||
|
||||
LOGI("hook_android_dlopen_ext: filename: %s", filename);
|
||||
|
||||
// Ignore non-vulkan libraries
|
||||
if (!strstr(filename, "vulkan."))
|
||||
return android_dlopen_ext(filename, flags, extinfo);
|
||||
|
||||
if (extinfo->library_namespace == nullptr || !(extinfo->flags & ANDROID_DLEXT_USE_NAMESPACE)) {
|
||||
LOGI("hook_android_dlopen_ext: hook failed: namespace not supplied!");
|
||||
return fallback();
|
||||
}
|
||||
|
||||
// customDriverDir will be empty if ADRENOTOOLS_DRIVER_CUSTOM isn't set therefore it's fine to have either way
|
||||
auto driverNs{android_create_namespace(filename, hook_params->customDriverDir.c_str(),
|
||||
hook_params->hookLibDir.c_str(), ANDROID_NAMESPACE_TYPE_SHARED,
|
||||
nullptr, extinfo->library_namespace)};
|
||||
if (!driverNs) {
|
||||
LOGI("hook_android_dlopen_ext: hook failed: namespace not supplied!");
|
||||
return fallback();
|
||||
}
|
||||
|
||||
// We depend on libandroid which is unlikely to be in the supplied driver namespace so we have to link it over
|
||||
android_link_namespaces(driverNs, nullptr, "libandroid.so");
|
||||
|
||||
// Preload ourself, a new instance will be created since we have different linker ancestory
|
||||
// If we don't preload we get a weird issue where despite being in NEEDED of the hook lib the hook's symbols will overwrite ours and cause an infinite loop
|
||||
auto hookImpl{linkernsbypass_namespace_dlopen("libhook_impl.so", RTLD_NOW, driverNs)};
|
||||
if (!hookImpl)
|
||||
return nullptr;
|
||||
|
||||
// Pass parameters to ourself
|
||||
auto initHookParam{reinterpret_cast<void (*)(const void *)>(dlsym(hookImpl, "init_hook_param"))};
|
||||
if (!initHookParam)
|
||||
return nullptr;
|
||||
|
||||
initHookParam(hook_params);
|
||||
|
||||
if (hook_params->featureFlags & ADRENOTOOLS_DRIVER_FILE_REDIRECT) {
|
||||
if (!linkernsbypass_namespace_dlopen("libfile_redirect_hook.so", RTLD_GLOBAL, driverNs)) {
|
||||
LOGI("hook_android_dlopen_ext: hook failed: failed to apply libfopen_redirect_hook!");
|
||||
return fallback();
|
||||
}
|
||||
|
||||
LOGI("hook_android_dlopen_ext: applied libfile_redirect_hook");
|
||||
}
|
||||
|
||||
// Use our new namespace to load the vulkan driver
|
||||
auto newExtinfo{*extinfo};
|
||||
newExtinfo.library_namespace = driverNs;
|
||||
|
||||
if (hook_params->featureFlags & ADRENOTOOLS_DRIVER_GPU_MAPPING_IMPORT) {
|
||||
if (!linkernsbypass_namespace_dlopen("libgsl_alloc_hook.so", RTLD_GLOBAL, driverNs)) {
|
||||
LOGI("hook_android_dlopen_ext: hook failed: failed to apply libgsl_alloc_hook!");
|
||||
return fallback();
|
||||
}
|
||||
|
||||
auto libgslHandle{android_dlopen_ext("vkbgsl.so", RTLD_NOW, &newExtinfo)};
|
||||
if (!libgslHandle) {
|
||||
libgslHandle = android_dlopen_ext("notgsl.so", RTLD_NOW, &newExtinfo);
|
||||
if (!libgslHandle)
|
||||
libgslHandle = android_dlopen_ext("libgsl.so", RTLD_NOW, &newExtinfo);
|
||||
}
|
||||
|
||||
if (libgslHandle) {
|
||||
gsl_memory_alloc_pure_sym = reinterpret_cast<decltype(gsl_memory_alloc_pure_sym)>(dlsym(libgslHandle, "gsl_memory_alloc_pure"));
|
||||
gsl_memory_alloc_pure_64_sym = reinterpret_cast<decltype(gsl_memory_alloc_pure_64_sym)>(dlsym(libgslHandle, "gsl_memory_alloc_pure_64"));
|
||||
gsl_memory_free_pure_sym = reinterpret_cast<decltype(gsl_memory_free_pure_sym)>(dlsym(libgslHandle, "gsl_memory_free_pure"));
|
||||
if ((gsl_memory_alloc_pure_sym || gsl_memory_alloc_pure_64_sym) && gsl_memory_free_pure_sym) {
|
||||
auto initGsl{reinterpret_cast<void (*)(gsl_memory_alloc_pure_t, gsl_memory_alloc_pure_64_t, gsl_memory_free_pure_t)>(dlsym(hookImpl, "init_gsl"))};
|
||||
if (!initGsl)
|
||||
return fallback();
|
||||
|
||||
initGsl(gsl_memory_alloc_pure_sym, gsl_memory_alloc_pure_64_sym, gsl_memory_free_pure_sym);
|
||||
LOGI("hook_android_dlopen_ext: applied libgsl_alloc_hook");
|
||||
hook_params->nextGpuMapping->gpu_addr = ADRENOTOOLS_GPU_MAPPING_SUCCEEDED_MAGIC;
|
||||
}
|
||||
}
|
||||
|
||||
if (!((gsl_memory_alloc_pure_sym || gsl_memory_alloc_pure_64_sym) && gsl_memory_free_pure_sym))
|
||||
LOGI("hook_android_dlopen_ext: hook failed: failed to apply libgsl_alloc_hook!");
|
||||
}
|
||||
|
||||
// TODO: If there is already an instance of a Vulkan driver loaded hooks won't be applied, this will only be the case for skiavk generally
|
||||
// To fix this we would need to search /proc/self/maps for the file to a loaded instance of the library in order to read it to patch the soname and load it uniquely
|
||||
if (hook_params->featureFlags & ADRENOTOOLS_DRIVER_CUSTOM) {
|
||||
LOGI("hook_android_dlopen_ext: loading custom driver: %s%s", hook_params->customDriverDir.c_str(), hook_params->customDriverName.c_str());
|
||||
void *handle{android_dlopen_ext(hook_params->customDriverName.c_str(), flags, &newExtinfo)};
|
||||
if (!handle) {
|
||||
LOGI("hook_android_dlopen_ext: hook failed: failed to load custom driver: %s!", dlerror());
|
||||
return fallback();
|
||||
}
|
||||
|
||||
return handle;
|
||||
} else {
|
||||
LOGI("hook_android_dlopen_ext: loading default driver: %s", filename);
|
||||
return android_dlopen_ext(filename, flags, &newExtinfo);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) void *hook_android_load_sphal_library(const char *filename, int flags) {
|
||||
LOGI("hook_android_load_sphal_library: filename: %s", filename);
|
||||
|
||||
// https://android.googlesource.com/platform/system/core/+/master/libvndksupport/linker.cpp
|
||||
for (const char *name : {"sphal", "vendor", "default"}) {
|
||||
if (auto vendorNs{android_get_exported_namespace(name)}) {
|
||||
android_dlextinfo dlextinfo{
|
||||
.flags = ANDROID_DLEXT_USE_NAMESPACE,
|
||||
.library_namespace = vendorNs,
|
||||
};
|
||||
|
||||
return hook_android_dlopen_ext(filename, flags, &dlextinfo);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) FILE *hook_fopen(const char *filename, const char *mode) {
|
||||
if (!strncmp("/proc", filename, 5) || !strncmp("/sys", filename, 4)) {
|
||||
LOGI("hook_fopen: passthrough: %s", filename);
|
||||
return fopen(filename, mode);
|
||||
}
|
||||
|
||||
auto replacement{hook_params->fileRedirectDir + filename};
|
||||
LOGI("hook_fopen: %s -> %s", filename, replacement.c_str());
|
||||
|
||||
return fopen(replacement.c_str(), mode);
|
||||
}
|
||||
|
||||
static constexpr uintptr_t GslMemDescImportedPrivMagic{0xdeadb33f};
|
||||
struct GslMemDesc {
|
||||
void *hostptr;
|
||||
uint64_t gpuaddr;
|
||||
uint64_t size;
|
||||
uint64_t flags;
|
||||
uintptr_t priv;
|
||||
};
|
||||
|
||||
__attribute__((visibility("default"))) int hook_gsl_memory_alloc_pure_64(uint64_t size, uint32_t flags, void *memDesc) {
|
||||
auto gslMemDesc{reinterpret_cast<GslMemDesc *>(memDesc)};
|
||||
if (hook_params->nextGpuMapping && hook_params->nextGpuMapping->size == size && (hook_params->nextGpuMapping->flags & flags) == hook_params->nextGpuMapping->flags) {
|
||||
auto &nextMapping{*hook_params->nextGpuMapping};
|
||||
|
||||
gslMemDesc->hostptr = nextMapping.host_ptr;
|
||||
gslMemDesc->gpuaddr = nextMapping.gpu_addr;
|
||||
gslMemDesc->size = nextMapping.size;
|
||||
gslMemDesc->flags = nextMapping.flags;
|
||||
gslMemDesc->priv = GslMemDescImportedPrivMagic;
|
||||
hook_params->nextGpuMapping->size = 0;
|
||||
hook_params->nextGpuMapping->gpu_addr = ADRENOTOOLS_GPU_MAPPING_SUCCEEDED_MAGIC;
|
||||
return 0;
|
||||
} else {
|
||||
if (gsl_memory_alloc_pure_64_sym)
|
||||
return gsl_memory_alloc_pure_64_sym(size, flags, gslMemDesc);
|
||||
else
|
||||
return gsl_memory_alloc_pure_sym((uint32_t)size, flags, gslMemDesc);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) int hook_gsl_memory_free_pure(void *memDesc) {
|
||||
auto gslMemDesc{reinterpret_cast<GslMemDesc *>(memDesc)};
|
||||
|
||||
if (gslMemDesc->priv == GslMemDescImportedPrivMagic) {
|
||||
if (!kgsl_fd)
|
||||
kgsl_fd = open("/dev/kgsl-3d0", O_RDWR);
|
||||
|
||||
kgsl_gpumem_get_info info{
|
||||
.gpuaddr = gslMemDesc->gpuaddr
|
||||
};
|
||||
|
||||
if (ioctl(kgsl_fd, IOCTL_KGSL_GPUMEM_GET_INFO, &info) < 0) {
|
||||
LOGI("IOCTL_KGSL_GPUMEM_GET_INFO failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
kgsl_gpuobj_free args{
|
||||
.id = info.id,
|
||||
};
|
||||
|
||||
if (ioctl(kgsl_fd, IOCTL_KGSL_GPUOBJ_FREE, &args) < 0)
|
||||
LOGI("IOCTL_KGSL_GPUOBJ_FREE failed");
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
return gsl_memory_free_pure_sym(memDesc);
|
||||
}
|
||||
}
|
30
externals/libadrenotools/src/hook/hook_impl.h
vendored
Normal file
30
externals/libadrenotools/src/hook/hook_impl.h
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
// Copyright © 2021 Billy Laws
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <android/dlext.h>
|
||||
|
||||
void init_hook_param(const void *param);
|
||||
|
||||
void init_gsl(void *alloc, void *alloc64, void *free);
|
||||
|
||||
void *hook_android_dlopen_ext(const char *filename, int flags, const android_dlextinfo *extinfo);
|
||||
|
||||
void *hook_android_load_sphal_library(const char *filename, int flags);
|
||||
|
||||
FILE *hook_fopen(const char *filename, const char *mode);
|
||||
|
||||
int hook_gsl_memory_alloc_pure_64(uint64_t size, uint32_t flags, void *memDesc);
|
||||
|
||||
int hook_gsl_memory_free_pure(void *memDesc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
31
externals/libadrenotools/src/hook/hook_impl_params.h
vendored
Normal file
31
externals/libadrenotools/src/hook/hook_impl_params.h
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
// Copyright © 2021 Billy Laws
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <adrenotools/priv.h>
|
||||
|
||||
/**
|
||||
* @brief Holds the parameters needed for all hooks
|
||||
* @note See comments for adrenotools_open_libvulkan as a reference for member variables
|
||||
*/
|
||||
struct HookImplParams {
|
||||
int featureFlags;
|
||||
std::string tmpLibDir;
|
||||
std::string hookLibDir;
|
||||
std::string customDriverDir;
|
||||
std::string customDriverName;
|
||||
std::string fileRedirectDir;
|
||||
adrenotools_gpu_mapping *nextGpuMapping;
|
||||
|
||||
HookImplParams(int featureFlags, const char *tmpLibDir, const char *hookLibDir, const char *customDriverDir,
|
||||
const char *customDriverName, const char *fileRedirectDir, adrenotools_gpu_mapping *nextGpuMapping)
|
||||
: featureFlags(featureFlags),
|
||||
tmpLibDir(tmpLibDir ? tmpLibDir : ""),
|
||||
hookLibDir(hookLibDir),
|
||||
customDriverDir(customDriverDir ? customDriverDir : ""),
|
||||
customDriverName(customDriverName ? customDriverName : ""),
|
||||
fileRedirectDir(fileRedirectDir ? fileRedirectDir : ""),
|
||||
nextGpuMapping(nextGpuMapping) {}
|
||||
};
|
2124
externals/libadrenotools/src/hook/kgsl.h
vendored
Normal file
2124
externals/libadrenotools/src/hook/kgsl.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
9
externals/libadrenotools/src/hook/main_hook.c
vendored
Normal file
9
externals/libadrenotools/src/hook/main_hook.c
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
#include "hook_impl.h"
|
||||
|
||||
__attribute__((visibility("default"))) void *android_dlopen_ext(const char *filename, int flags, const android_dlextinfo *extinfo) {
|
||||
return hook_android_dlopen_ext(filename, flags, extinfo);
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) void *android_load_sphal_library(const char *filename, int flags) {
|
||||
return hook_android_load_sphal_library(filename, flags);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue