Initial commit

This commit is contained in:
Billy Laws
2021-12-04 22:22:58 +00:00
commit 332425ac2e
17 changed files with 607 additions and 0 deletions

4
.gitmodules vendored Normal file
View File

@@ -0,0 +1,4 @@
[submodule "lib/linkernsbypass"]
path = lib/linkernsbypass
url = https://github.com/bylaws/liblinkernsbypass/
branch = master

27
CMakeLists.txt Normal file
View File

@@ -0,0 +1,27 @@
cmake_minimum_required(VERSION 3.14)
if(NOT ${CMAKE_ANDROID_ARCH_ABI} STREQUAL arm64-v8a)
message(FATAL_ERROR "Unsupported target architecture: ${CMAKE_ANDROID_ARCH_ABI}. Please make an issue on the repo!")
endif()
project(adrenotools LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
include_directories(lib/linkernsbypass)
add_subdirectory(lib/linkernsbypass)
set(LIB_SOURCES src/bcenabler.cpp
src/driver.cpp
include/adrenotools/bcenabler.h
include/adrenotools/driver.h
include/adrenotools/priv.h)
add_library(adrenotools ${LIB_SOURCES})
target_include_directories(adrenotools PUBLIC include)
target_include_directories(adrenotools PRIVATE .)
target_compile_options(adrenotools PRIVATE -Wall -Wextra)
target_link_libraries(adrenotools vulkan android linkernsbypass)
add_subdirectory(src/hook)

24
LICENSE Normal file
View File

@@ -0,0 +1,24 @@
BSD 2-Clause License
Copyright (c) 2021, Billy Laws
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

12
README.md Normal file
View File

@@ -0,0 +1,12 @@
### Adreno Tools
A library for applying rootless Adreno GPU driver modifications/replacements. Currently supports loading custom GPU drivers such as [turnip](https://docs.mesa3d.org/android.html#building-using-the-android-ndk), enabling BCn textures and redirecting file operations to allow accessing shader dumps and modification of the [driver config file](https://gist.github.com/bylaws/04130932e2634d1c6a2a9729e3940d60) without root.
#### Documentation
API is documented in the `include/adrenotools` headers.
#### Support
Android 9+
Arm64
Please create an issue if support for anything else is desired.

10
build_asm.sh Executable file
View File

@@ -0,0 +1,10 @@
#!/bin/sh
aarch64-linux-gnu-gcc -c src/bcenabler_patch.s -o /tmp/patch.o
aarch64-linux-gnu-objcopy -O binary -j .text /tmp/patch.o /tmp/patch.bin
# Must be smaller than a single page
bin2c -o gen/bcenabler_patch.h -n PatchRawData /tmp/patch.bin
rm /tmp/patch.o
rm /tmp/patch.bin

23
gen/bcenabler_patch.h Normal file
View File

@@ -0,0 +1,23 @@
/* Generated by bin2c, do not edit manually */
/* Contents of file /tmp/patch.bin */
const long int PatchRawData_size = 264;
const unsigned char PatchRawData[264] = {
0x1F, 0x0C, 0x02, 0x71, 0x61, 0x00, 0x00, 0x54, 0xE0, 0x08, 0x80, 0x52, 0x3E, 0x00, 0x00, 0x14,
0x1F, 0x14, 0x02, 0x71, 0x61, 0x00, 0x00, 0x54, 0xE0, 0x08, 0x80, 0x52, 0x3A, 0x00, 0x00, 0x14,
0x1F, 0x10, 0x02, 0x71, 0x61, 0x00, 0x00, 0x54, 0x00, 0x09, 0x80, 0x52, 0x36, 0x00, 0x00, 0x14,
0x1F, 0x18, 0x02, 0x71, 0x61, 0x00, 0x00, 0x54, 0x00, 0x09, 0x80, 0x52, 0x32, 0x00, 0x00, 0x14,
0x1F, 0x1C, 0x02, 0x71, 0x61, 0x00, 0x00, 0x54, 0x40, 0x09, 0x80, 0x52, 0x2E, 0x00, 0x00, 0x14,
0x1F, 0x20, 0x02, 0x71, 0x61, 0x00, 0x00, 0x54, 0x60, 0x09, 0x80, 0x52, 0x2A, 0x00, 0x00, 0x14,
0x1F, 0x24, 0x02, 0x71, 0x61, 0x00, 0x00, 0x54, 0xA0, 0x09, 0x80, 0x52, 0x26, 0x00, 0x00, 0x14,
0x1F, 0x28, 0x02, 0x71, 0x61, 0x00, 0x00, 0x54, 0xC0, 0x09, 0x80, 0x52, 0x22, 0x00, 0x00, 0x14,
0x1F, 0x2C, 0x02, 0x71, 0x61, 0x00, 0x00, 0x54, 0x00, 0x0A, 0x80, 0x52, 0x1E, 0x00, 0x00, 0x14,
0x1F, 0x30, 0x02, 0x71, 0x61, 0x00, 0x00, 0x54, 0x20, 0x0A, 0x80, 0x52, 0x1A, 0x00, 0x00, 0x14,
0x1F, 0x34, 0x02, 0x71, 0x61, 0x00, 0x00, 0x54, 0x60, 0x0A, 0x80, 0x52, 0x16, 0x00, 0x00, 0x14,
0x1F, 0x38, 0x02, 0x71, 0x61, 0x00, 0x00, 0x54, 0x80, 0x0A, 0x80, 0x52, 0x12, 0x00, 0x00, 0x14,
0x1F, 0x3C, 0x02, 0x71, 0x61, 0x00, 0x00, 0x54, 0xE0, 0x0B, 0x80, 0x52, 0x0E, 0x00, 0x00, 0x14,
0x1F, 0x40, 0x02, 0x71, 0x61, 0x00, 0x00, 0x54, 0x00, 0x0C, 0x80, 0x52, 0x0A, 0x00, 0x00, 0x14,
0x1F, 0x44, 0x02, 0x71, 0x61, 0x00, 0x00, 0x54, 0x40, 0x0C, 0x80, 0x52, 0x06, 0x00, 0x00, 0x14,
0x1F, 0x48, 0x02, 0x71, 0x61, 0x00, 0x00, 0x54, 0x60, 0x0C, 0x80, 0x52, 0x02, 0x00, 0x00, 0x14,
0x00, 0x00, 0x80, 0x52, 0xFF, 0xFF, 0xFF, 0xFF
};

View File

@@ -0,0 +1,40 @@
// SPDX-License-Identifier: BSD-2-Clause
// Copyright © 2021 Billy Laws
#pragma once
#ifdef __cplusplus
extern "C" {
#else
#include <stdbool.h>
#endif
#include <stdint.h>
/**
* @brief Describes the level of BCeNabler support for a driver
*/
enum adrenotools_bcn_type {
ADRENOTOOLS_BCN_INCOMPATIBLE, //!< Driver isn't supported by BCeNabler
ADRENOTOOLS_BCN_BLOB, //!< Driver already supports BCn textures so BCeNabler isn't necessary
ADRENOTOOLS_BCN_PATCH //!< Driver can be patched with BCeNabler to support BCn textures
};
/**
* @brief Checks the status of BCn support in the supplied driver
* @param major The major part of VkPhysicalDeviceProperties::driverVersion
* @param minor The minor part of VkPhysicalDeviceProperties::driverVersion
*/
enum adrenotools_bcn_type adrenotools_get_bcn_type(uint32_t major, uint32_t minor);
/**
* @brief Patches the Adreno graphics driver to enable support for BCn compressed formats
* @note adrenotools_get_bcn_type MUST be checked to equal ADRENOTOOLS_BCN_PATCH before calling this
* @param vkGetPhysicalDeviceFormatPropertiesFn A pointer to vkGetPhysicalDeviceFormatProperties obtained through vkGetInstanceProcAddr. This is used to find the correct function to patch
* @return If the patching succeeded, if false the driver will be in an undefined state
*/
bool adrenotools_patch_bcn(void *vkGetPhysicalDeviceFormatPropertiesFn);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,26 @@
// SPDX-License-Identifier: BSD-2-Clause
// Copyright © 2021 Billy Laws
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "priv.h"
/**
* @brief Opens a new libvulkan.so instance according to `flags`
* @param dlopenMode The dlopen mode to use when opening libvulkan
* @param featureFlags Which adrenotools driver features to enable
* @param tmpLibDir A writable directory to hold patched libraries, only used on api < 29 due to the lack of memfd support. If nullptr is passed and the API version is < 29 memfd usage will be attempted and if unsupported nullptr will be returned
* @param hookLibDir The directory holding the built hooks
* @param customDriverDir The directory to load a custom GPU driver named according to `customDriverName` from. Only used if ADRENOTOOLS_DRIVER_CUSTOM is set in `featureFlags`
* @param customDriverName The soname of the custom driver to load. Only used if ADRENOTOOLS_DRIVER_CUSTOM is set in `featureFlags`
* @param fileRedirectDir The directory which to redirect all file accesses performed by the driver to. Only used if ADRENOTOOLS_DRIVER_FILE_REDIRECT is set in `featureFlags`
*/
void *adrenotools_open_libvulkan(int dlopenMode, int featureFlags, const char *tmpLibDir, const char *hookLibDir, const char *customDriverDir, const char *customDriverName, const char *fileRedirectDir);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,12 @@
// SPDX-License-Identifier: BSD-2-Clause
// Copyright © 2021 Billy Laws
#pragma once
/**
* @brief Bitfield enum of additional driver features that can be used with adrenotools_open_libvulkan
*/
enum {
ADRENOTOOLS_DRIVER_CUSTOM = 1 << 0,
ADRENOTOOLS_DRIVER_FILE_REDIRECT = 1 << 1
};

1
lib/linkernsbypass Submodule

Submodule lib/linkernsbypass added at 8a819a35e1

125
src/bcenabler.cpp Normal file
View File

@@ -0,0 +1,125 @@
// SPDX-License-Identifier: BSD-2-Clause
// Copyright © 2021 Billy Laws
#include <fstream>
#include <string>
#include <cstring>
#include <sys/mman.h>
#include <adrenotools/bcenabler.h>
#include "gen/bcenabler_patch.h"
enum adrenotools_bcn_type adrenotools_get_bcn_type(uint32_t major, uint32_t minor) {
if (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;
}
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");
// 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};
// 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++;
// Find the nearest unmapped page where we can place patch code
void *patchPage{find_free_page(reinterpret_cast<uintptr_t>(clearResultPtr))};
if (!patchPage)
return false;
void *ptr{mmap(patchPage, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0)};
if (ptr != patchPage)
return false;
// Ensure we don't write out of bounds
if (PatchRawData_size > PAGE_SIZE)
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;
uint32_t *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,
}
};
void *driverPatchPage{reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(clearResultPtr) & ~(PAGE_SIZE - 1))};
// For some reason mprotect just breaks entirely after we patch the QGL instruction so just set perms to RWX
if (mprotect(driverPatchPage, PAGE_SIZE, PROT_WRITE | PROT_READ | PROT_EXEC))
return false;
*clearResultPtr = branchToPatch.raw;
asm volatile("ISB");
// Done!
return true;
}

83
src/bcenabler_patch.s Normal file
View 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

54
src/driver.cpp Normal file
View File

@@ -0,0 +1,54 @@
// SPDX-License-Identifier: BSD-2-Clause
// Copyright © 2021 Billy Laws
#include <string>
#include <string_view>
#include <sys/stat.h>
#include <dlfcn.h>
#include <android/api-level.h>
#include <android/log.h>
#include <android_linker_ns.h>
#include "hook/main_hook.h"
#include <adrenotools/driver.h>
void *adrenotools_open_libvulkan(int dlopenMode, int featureFlags, const char *tmpLibDir, const char *hookLibDir, const char *customDriverDir, const char *customDriverName, const char *fileRedirectDir) {
// Bail out if linkernsbyapss 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;
// 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;
}
// Will be destroyed by the libmain_hook.so destructor on unload
auto *hookParam{new MainHookParam(featureFlags, tmpLibDir, hookLibDir, customDriverDir, customDriverName, fileRedirectDir)};
return linkernsbypass_dlopen_unique_hooked("/system/lib64/libvulkan.so", tmpLibDir, dlopenMode, hookLibDir, "libmain_hook.so", nullptr, true, reinterpret_cast<void *>(hookParam));
}

15
src/hook/CMakeLists.txt Normal file
View File

@@ -0,0 +1,15 @@
add_library(main_hook SHARED main_hook.cpp)
target_compile_options(main_hook PRIVATE -Wall -Wextra)
target_link_options(main_hook PRIVATE -z global)
target_link_libraries(main_hook linkernsbypass log)
target_include_directories(main_hook PRIVATE ../../include)
set_target_properties(main_hook PROPERTIES CXX_VISIBILITY_PRESET hidden)
add_library(file_redirect_hook SHARED file_redirect_hook.cpp)
target_compile_options(file_redirect_hook PRIVATE -Wall -Wextra)
target_link_options(file_redirect_hook PRIVATE -z global)
target_link_libraries(file_redirect_hook linkernsbypass dl log)
target_include_directories(file_redirect_hook PRIVATE ../../include)
set_target_properties(file_redirect_hook PROPERTIES CXX_VISIBILITY_PRESET hidden)

View File

@@ -0,0 +1,35 @@
#include <string>
#include <cstdio>
#include <dlfcn.h>
#include <android/log.h>
#define TAG "file_redirect_hook"
#define LOGI(fmt, ...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##__VA_ARGS__)
static decltype(&fopen) libc_fopen{[]() {
auto libcHandle{dlopen("libc.so", RTLD_LAZY)};
if (!libcHandle)
__builtin_trap();
auto sym{dlsym(libcHandle, "fopen")};
if (!sym)
__builtin_trap();
return reinterpret_cast<decltype(&fopen)>(sym);
}()};
extern "C" {
__attribute__((visibility("default"))) const char *hook_param; //!< The prefix to add to filesystem calls
__attribute__((visibility("default"))) FILE *fopen(const char *filename, const char *mode) {
if ((strncmp("/proc", filename, 5) == 0) || (strncmp("/sys", filename, 4) == 0)) {
LOGI("fopen: passthrough: %s", filename);
return libc_fopen(filename, mode);
}
auto replacement{std::string{hook_param} + filename};
LOGI("fopen: %s -> %s", filename, replacement.c_str());
return libc_fopen(replacement.c_str(), mode);
}
}

88
src/hook/main_hook.cpp Normal file
View File

@@ -0,0 +1,88 @@
#include <cstring>
#include <android/dlext.h>
#include <android_linker_ns.h>
#include <android/log.h>
#include "main_hook.h"
#define TAG "driver_load_hook"
#define LOGI(fmt, ...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##__VA_ARGS__)
extern "C" {
// The namespace that should be used to load vulkan drivers, set dlopen_hooked from the hookParam argument
__attribute__((visibility("default"))) const MainHookParam *hook_param;
__attribute__((destructor)) static void free_hook_param() {
delete hook_param;
}
__attribute__((visibility("default"))) void *android_dlopen_ext(const char *filename, int flags, const android_dlextinfo *extinfo) {
auto fallback{[&]() {
LOGI("android_dlopen_ext: falling back!");
return libdl_android_dlopen_ext(filename, flags, extinfo);
}};
LOGI("android_dlopen_ext: filename: %s", filename);
// Ignore non-vulkan libraries
if (!strstr(filename, "vulkan."))
return libdl_android_dlopen_ext(filename, flags, extinfo);
if (extinfo->library_namespace == nullptr || !(extinfo->flags & ANDROID_DLEXT_USE_NAMESPACE)) {
LOGI("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_param->customDriverDir.c_str(),
hook_param->hookLibDir.c_str(), ANDROID_NAMESPACE_TYPE_SHARED,
nullptr, extinfo->library_namespace)};
if (!driverNs) {
LOGI("android_dlopen_ext: hook failed: namespace not supplied!");
return fallback();
}
// Hook libs 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");
if (hook_param->featureFlags & ADRENOTOOLS_DRIVER_FILE_REDIRECT) {
if (!linkernsbypass_namespace_apply_hook("libfile_redirect_hook.so", driverNs,
reinterpret_cast<const void *>(hook_param->fileRedirectDir.c_str()))) {
LOGI("android_dlopen_ext: hook failed: failed to apply libfopen_redirect_hook!");
return fallback();
}
LOGI("android_dlopen_ext: applied libfopen_redirect_hook");
}
// Use our new namespace to load the vulkan driver
auto newExtinfo{*extinfo};
newExtinfo.library_namespace = driverNs;
// 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_param->featureFlags & ADRENOTOOLS_DRIVER_CUSTOM) {
LOGI("android_dlopen_ext: loading custom driver: %s%s", hook_param->customDriverDir.c_str(), hook_param->customDriverName.c_str());
return libdl_android_dlopen_ext(hook_param->customDriverName.c_str(), flags, &newExtinfo);
} else {
LOGI("android_dlopen_ext: loading default driver: %s", filename);
return libdl_android_dlopen_ext(filename, flags, &newExtinfo);
}
}
__attribute__((visibility("default"))) void *android_load_sphal_library(const char *filename, int flags) {
// 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 android_dlopen_ext(filename, flags, &dlextinfo);
}
}
return nullptr;
}
}

28
src/hook/main_hook.h Normal file
View File

@@ -0,0 +1,28 @@
// SPDX-License-Identifier: BSD-2-Clause
// Copyright © 2021 Billy Laws
#pragma once
#include <string>
#include <adrenotools/priv.h>
/**
* @brief Holds the parameters for the main libvulkan.so hook
* @note See comments for adrenotools_open_libvulkan as a reference for member variables
*/
struct MainHookParam {
int featureFlags;
std::string tmpLibDir;
std::string hookLibDir;
std::string customDriverDir;
std::string customDriverName;
std::string fileRedirectDir;
MainHookParam(int featureFlags, const char *tmpLibDir, const char *hookLibDir, const char *customDriverDir, const char *customDriverName, const char *fileRedirectDir)
: featureFlags(featureFlags),
tmpLibDir(tmpLibDir ? tmpLibDir : ""),
hookLibDir(hookLibDir),
customDriverDir(customDriverDir ? customDriverDir : ""),
customDriverName(customDriverName ? customDriverName : ""),
fileRedirectDir(fileRedirectDir ? fileRedirectDir : "") {}
};