mirror of
https://github.com/AngelAuraMC/Amethyst-Android.git
synced 2025-09-14 07:05:40 -04:00
Fix[zink]: resolve namespace issues and fix old android support
Note: old android support still requires me to compile a working build of Turnip to work on old android
This commit is contained in:
parent
4cd3ab0fb5
commit
566f0ca36b
@ -2,42 +2,50 @@
|
|||||||
// Created by maks on 05.06.2023.
|
// Created by maks on 05.06.2023.
|
||||||
//
|
//
|
||||||
#include <android/dlext.h>
|
#include <android/dlext.h>
|
||||||
#include <android/log.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
// Silence the warnings about using reserved identifiers (we need to link to these to not pollute the global symtab)
|
||||||
typedef void* (*android_dlopen_ext_t)(const char *filename, int flags, const android_dlextinfo *extinfo);
|
//NOLINTBEGIN
|
||||||
typedef struct android_namespace_t* (*android_get_exported_namespace_t)(const char* name);
|
__attribute__((weak)) void* __loader_android_dlopen_ext(const char* filename,
|
||||||
|
int flags,
|
||||||
|
const android_dlextinfo* extinfo,
|
||||||
|
const void* caller_addr);
|
||||||
|
__attribute__((weak)) struct android_namespace_t* __loader_android_get_exported_namespace(const char* name);
|
||||||
|
//NOLINTEND
|
||||||
static void* ready_handle;
|
static void* ready_handle;
|
||||||
static android_dlopen_ext_t original_func;
|
|
||||||
static android_get_exported_namespace_t android_get_exported_namespace;
|
|
||||||
|
|
||||||
static const char *sphal_namespaces[3] = {
|
static const char *sphal_namespaces[3] = {
|
||||||
"sphal", "vendor", "default"
|
"sphal", "vendor", "default"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
__attribute__((visibility("default"))) void app__pojav_linkerhook_set_data(void* data, void* data1, void* data2) {
|
__attribute__((visibility("default"), used)) void app__pojav_linkerhook_pass_handle(void* data) {
|
||||||
ready_handle = data;
|
ready_handle = data;
|
||||||
original_func = data1;
|
|
||||||
android_get_exported_namespace = data2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((visibility("default"))) void *android_dlopen_ext(const char *filename, int flags, const android_dlextinfo *extinfo) {
|
__attribute__((visibility("default"), used)) void *android_dlopen_ext(const char *filename, int flags, const android_dlextinfo *extinfo) {
|
||||||
if(!strstr(filename, "vulkan."))
|
if(!strstr(filename, "vulkan."))
|
||||||
return original_func(filename, flags, extinfo);
|
return __loader_android_dlopen_ext(filename, flags, extinfo, &android_dlopen_ext);
|
||||||
return ready_handle;
|
return ready_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((visibility("default"))) void *android_load_sphal_library(const char *filename, int flags) {
|
__attribute__((visibility("default"), used)) void *android_load_sphal_library(const char *filename, int flags) {
|
||||||
if(strstr(filename, "vulkan.")) return ready_handle;
|
if(strstr(filename, "vulkan.")) {
|
||||||
|
return ready_handle;
|
||||||
|
}
|
||||||
struct android_namespace_t* androidNamespace;
|
struct android_namespace_t* androidNamespace;
|
||||||
for(int i = 0; i < 3; i++) {
|
for(int i = 0; i < 3; i++) {
|
||||||
androidNamespace = android_get_exported_namespace(sphal_namespaces[i]);
|
androidNamespace = __loader_android_get_exported_namespace(sphal_namespaces[i]);
|
||||||
if(androidNamespace != NULL) break;
|
if(androidNamespace != NULL) break;
|
||||||
}
|
}
|
||||||
android_dlextinfo info;
|
android_dlextinfo info;
|
||||||
info.flags = ANDROID_DLEXT_USE_NAMESPACE;
|
info.flags = ANDROID_DLEXT_USE_NAMESPACE;
|
||||||
info.library_namespace = androidNamespace;
|
info.library_namespace = androidNamespace;
|
||||||
return original_func(filename, flags, &info);
|
return __loader_android_dlopen_ext(filename, flags, &info, &android_dlopen_ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is done for older android versions which don't
|
||||||
|
// export this function. Technically this is wrong
|
||||||
|
// but for our usage it's fine enough
|
||||||
|
__attribute__((visibility("default"), used)) uint64_t atrace_get_enabled_tags() {
|
||||||
|
return 0;
|
||||||
}
|
}
|
@ -38,11 +38,12 @@ typedef struct android_namespace_t* (*ld_android_create_namespace_t)(
|
|||||||
const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
|
const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
|
||||||
const char* permitted_when_isolated_path, struct android_namespace_t* parent, const void* caller_addr);
|
const char* permitted_when_isolated_path, struct android_namespace_t* parent, const void* caller_addr);
|
||||||
|
|
||||||
typedef struct android_namespace_t* (*ld_android_get_exported_namespace_t)(const char* name, const void* caller_addr);
|
typedef void* (*ld_android_link_namespaces_t)(struct android_namespace_t* namespace_from,
|
||||||
|
struct android_namespace_t* namespace_to,
|
||||||
|
const char* shared_libs_sonames);
|
||||||
|
|
||||||
static ld_android_create_namespace_t android_create_namespace;
|
static ld_android_create_namespace_t android_create_namespace;
|
||||||
static ld_android_get_exported_namespace_t android_get_exported_namespace;
|
static struct android_namespace_t* driver_namespace;
|
||||||
static struct android_namespace_t* namespace;
|
|
||||||
|
|
||||||
struct android_namespace_t* local_android_create_namespace(
|
struct android_namespace_t* local_android_create_namespace(
|
||||||
const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
|
const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
|
||||||
@ -51,58 +52,78 @@ struct android_namespace_t* local_android_create_namespace(
|
|||||||
return android_create_namespace(name, ld_library_path, default_library_path, type, permitted_when_isolated_path, parent, caller);
|
return android_create_namespace(name, ld_library_path, default_library_path, type, permitted_when_isolated_path, parent, caller);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct android_namespace_t* ns_android_get_exported_namespace(
|
// Find the first "branch to label" function in the function provided in func_start
|
||||||
const char* name) {
|
static void* find_branch_label(void* func_start) {
|
||||||
void* caller = __builtin_return_address(0);
|
// round down the pointer to get the start of the function's page
|
||||||
return android_get_exported_namespace(name, caller);
|
void* func_page_start = (void*)(((uintptr_t)func_start) & ~(PAGE_SIZE-1));
|
||||||
|
// remap to r-x to bypass "execute only" protections on MIUI
|
||||||
|
mprotect(func_page_start, PAGE_SIZE, PROT_READ | PROT_EXEC);
|
||||||
|
uint32_t* bl_addr = func_start;
|
||||||
|
// search for the "branch to label" opcode
|
||||||
|
while((*bl_addr & OP_MS) != BL_OP) {
|
||||||
|
bl_addr++; // walk through memory until we find it or die
|
||||||
|
}
|
||||||
|
// offset the address to find where the "branch to label" instrunction
|
||||||
|
// points to.
|
||||||
|
return ((char*)bl_addr) + (*bl_addr & BL_IM) * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool linker_ns_load(const char* lib_search_path) {
|
bool linker_ns_load(const char* lib_search_path) {
|
||||||
#ifndef ADRENO_POSSIBLE
|
#ifndef ADRENO_POSSIBLE
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#else
|
||||||
uint32_t *dlext_bl_addr = (uint32_t*)&dlopen;
|
loader_dlopen_t loader_dlopen = find_branch_label(&dlopen);
|
||||||
while((*dlext_bl_addr & OP_MS) !=
|
// reprotecting the functions removes protection from indirect jumps
|
||||||
BL_OP) dlext_bl_addr++; //walk through the function until we find the label that we need to go to
|
mprotect(loader_dlopen, PAGE_SIZE, PROT_WRITE | PROT_READ | PROT_EXEC);
|
||||||
__android_log_print(ANDROID_LOG_INFO, "nsbypass", "found branch label: %u", *dlext_bl_addr);
|
|
||||||
loader_dlopen_t loader_dlopen;
|
|
||||||
loader_dlopen = (loader_dlopen_t)(((char *) dlext_bl_addr) + (*dlext_bl_addr & BL_IM)*4);
|
|
||||||
mprotect(loader_dlopen, PAGE_SIZE, PROT_WRITE | PROT_READ | PROT_EXEC); // reprotecting the function removes protection from indirect jumps
|
|
||||||
void* ld_android_handle = loader_dlopen("ld-android.so", RTLD_LAZY, &dlopen);
|
void* ld_android_handle = loader_dlopen("ld-android.so", RTLD_LAZY, &dlopen);
|
||||||
__android_log_print(ANDROID_LOG_INFO, "nsbypass", "ld-android.so handle: %p", ld_android_handle);
|
if(ld_android_handle == NULL) {
|
||||||
if(ld_android_handle == NULL) return false;
|
return false;
|
||||||
|
}
|
||||||
|
// load the two functions we need
|
||||||
android_create_namespace = dlsym(ld_android_handle, "__loader_android_create_namespace");
|
android_create_namespace = dlsym(ld_android_handle, "__loader_android_create_namespace");
|
||||||
android_get_exported_namespace = dlsym(ld_android_handle, "__loader_android_get_exported_namespace");
|
ld_android_link_namespaces_t android_link_namespaces = dlsym(ld_android_handle, "__loader_android_link_namespaces");
|
||||||
if(android_create_namespace == NULL || android_get_exported_namespace == NULL) {
|
__android_log_print(ANDROID_LOG_INFO, "nsbypass", "found functions at %p %p", android_create_namespace, android_link_namespaces);
|
||||||
|
if(android_create_namespace == NULL || android_link_namespaces == NULL) {
|
||||||
dlclose(ld_android_handle);
|
dlclose(ld_android_handle);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// assemble the full path search path
|
||||||
char full_path[strlen(SEARCH_PATH) + strlen(lib_search_path) + 2 + 1];
|
char full_path[strlen(SEARCH_PATH) + strlen(lib_search_path) + 2 + 1];
|
||||||
sprintf(full_path, "%s:%s", SEARCH_PATH, lib_search_path);
|
sprintf(full_path, "%s:%s", SEARCH_PATH, lib_search_path);
|
||||||
namespace = local_android_create_namespace("pojav-driver",
|
driver_namespace = local_android_create_namespace("pojav-driver",
|
||||||
full_path,
|
full_path,
|
||||||
full_path,
|
full_path,
|
||||||
3 /* TYPE_SHAFED | TYPE_ISOLATED */,
|
3 /* TYPE_SHAFED | TYPE_ISOLATED */,
|
||||||
"/system/:/data/:/vendor/:/apex/", NULL);
|
"/system/:/data/:/vendor/:/apex/", NULL);
|
||||||
//dlclose(ld_android_handle);
|
// THIS IS VERY IMPORTANT and how I trolled FoldCraft:
|
||||||
|
// You need to link the new driver_namespace with NULL and and add ld-android.so
|
||||||
|
// in the link list, to pass through the driver_namespace correctly.
|
||||||
|
// Not doing this fucks up internal __loader symbol lookup
|
||||||
|
// inside the new driver_namespace, thus breaking it on
|
||||||
|
// a lot of android versions
|
||||||
|
// FoldCraft got trolled because they copied the
|
||||||
|
// old broken code verbatim and didn't even test it thoroughly
|
||||||
|
android_link_namespaces(driver_namespace, NULL, "ld-android.so");
|
||||||
|
dlclose(ld_android_handle);
|
||||||
return true;
|
return true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void* linker_ns_dlopen(const char* name, int flag) {
|
void* linker_ns_dlopen(const char* name, int flag) {
|
||||||
#ifndef ADRENO_POSSIBLE
|
#ifndef ADRENO_POSSIBLE
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
#else
|
||||||
android_dlextinfo dlextinfo;
|
android_dlextinfo dlextinfo;
|
||||||
dlextinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
|
dlextinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
|
||||||
dlextinfo.library_namespace = namespace;
|
dlextinfo.library_namespace = driver_namespace;
|
||||||
return android_dlopen_ext(name, flag, &dlextinfo);
|
return android_dlopen_ext(name, flag, &dlextinfo);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool patch_elf_soname(int patchfd, int realfd, uint16_t patchid) {
|
bool patch_elf_soname(int patchfd, int realfd, uint16_t patchid) {
|
||||||
struct stat realstat;
|
struct stat realstat;
|
||||||
if(fstat(realfd, &realstat)) return false;
|
if(fstat(realfd, &realstat)) return false;
|
||||||
if(ftruncate(patchfd, realstat.st_size) == -1) return false;
|
if(ftruncate64(patchfd, realstat.st_size) == -1) return false;
|
||||||
char* target = mmap(NULL, realstat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, patchfd, 0);
|
char* target = mmap(NULL, realstat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, patchfd, 0);
|
||||||
if(!target) return false;
|
if(!target) return false;
|
||||||
if(read(realfd, target, realstat.st_size) != realstat.st_size) {
|
if(read(realfd, target, realstat.st_size) != realstat.st_size) {
|
||||||
@ -118,6 +139,7 @@ bool patch_elf_soname(int patchfd, int realfd, uint16_t patchid) {
|
|||||||
ELF_SHDR *hdr = &shdr[i];
|
ELF_SHDR *hdr = &shdr[i];
|
||||||
if(hdr->sh_type == SHT_DYNAMIC) {
|
if(hdr->sh_type == SHT_DYNAMIC) {
|
||||||
char* strtab = target + shdr[hdr->sh_link].sh_offset;
|
char* strtab = target + shdr[hdr->sh_link].sh_offset;
|
||||||
|
// If there's a warning below, it's bogus, ignore it
|
||||||
ELF_DYN *dynEntries = (ELF_DYN*)(target + hdr->sh_offset);
|
ELF_DYN *dynEntries = (ELF_DYN*)(target + hdr->sh_offset);
|
||||||
for(ELF_XWORD k = 0; k < (hdr->sh_size / hdr->sh_entsize);k++) {
|
for(ELF_XWORD k = 0; k < (hdr->sh_size / hdr->sh_entsize);k++) {
|
||||||
ELF_DYN* dynEntry = &dynEntries[k];
|
ELF_DYN* dynEntry = &dynEntries[k];
|
||||||
@ -138,7 +160,7 @@ bool patch_elf_soname(int patchfd, int realfd, uint16_t patchid) {
|
|||||||
void* linker_ns_dlopen_unique(const char* tmpdir, const char* name, int flags) {
|
void* linker_ns_dlopen_unique(const char* tmpdir, const char* name, int flags) {
|
||||||
#ifndef ADRENO_POSSIBLE
|
#ifndef ADRENO_POSSIBLE
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
#else
|
||||||
char pathbuf[PATH_MAX];
|
char pathbuf[PATH_MAX];
|
||||||
static uint16_t patch_id;
|
static uint16_t patch_id;
|
||||||
int patch_fd, real_fd;
|
int patch_fd, real_fd;
|
||||||
@ -159,7 +181,8 @@ void* linker_ns_dlopen_unique(const char* tmpdir, const char* name, int flags) {
|
|||||||
android_dlextinfo extinfo;
|
android_dlextinfo extinfo;
|
||||||
extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE | ANDROID_DLEXT_USE_LIBRARY_FD;
|
extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE | ANDROID_DLEXT_USE_LIBRARY_FD;
|
||||||
extinfo.library_fd = patch_fd;
|
extinfo.library_fd = patch_fd;
|
||||||
extinfo.library_namespace = namespace;
|
extinfo.library_namespace = driver_namespace;
|
||||||
snprintf(pathbuf, PATH_MAX, "/proc/self/fd/%d", patch_fd);
|
snprintf(pathbuf, PATH_MAX, "/proc/self/fd/%d", patch_fd);
|
||||||
return android_dlopen_ext(pathbuf, flags, &extinfo);
|
return android_dlopen_ext(pathbuf, flags, &extinfo);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,5 @@
|
|||||||
bool linker_ns_load(const char* lib_search_path);
|
bool linker_ns_load(const char* lib_search_path);
|
||||||
void* linker_ns_dlopen(const char* name, int flag);
|
void* linker_ns_dlopen(const char* name, int flag);
|
||||||
void* linker_ns_dlopen_unique(const char* tmpdir, const char* name, int flag);
|
void* linker_ns_dlopen_unique(const char* tmpdir, const char* name, int flag);
|
||||||
struct android_namespace_t* ns_android_get_exported_namespace(const char*);
|
|
||||||
|
|
||||||
#endif //POJAVLAUNCHER_NSBYPASS_H
|
#endif //POJAVLAUNCHER_NSBYPASS_H
|
||||||
|
@ -187,11 +187,22 @@ void* load_turnip_vulkan() {
|
|||||||
if(!checkAdrenoGraphics()) return NULL;
|
if(!checkAdrenoGraphics()) return NULL;
|
||||||
const char* native_dir = getenv("POJAV_NATIVEDIR");
|
const char* native_dir = getenv("POJAV_NATIVEDIR");
|
||||||
const char* cache_dir = getenv("TMPDIR");
|
const char* cache_dir = getenv("TMPDIR");
|
||||||
linker_ns_load(native_dir);
|
if(!linker_ns_load(native_dir)) return NULL;
|
||||||
void* linkerhook = linker_ns_dlopen("liblinkerhook.so", RTLD_LOCAL | RTLD_NOW);
|
void* linkerhook = linker_ns_dlopen("liblinkerhook.so", RTLD_LOCAL | RTLD_NOW);
|
||||||
|
if(linkerhook == NULL) return NULL;
|
||||||
void* turnip_driver_handle = linker_ns_dlopen("libvulkan.adr.so", RTLD_LOCAL | RTLD_NOW);
|
void* turnip_driver_handle = linker_ns_dlopen("libvulkan.adr.so", RTLD_LOCAL | RTLD_NOW);
|
||||||
void (*linkerhook_set_data)(void*, void*, void*) = dlsym(linkerhook, "app__pojav_linkerhook_set_data");
|
if(turnip_driver_handle == NULL) {
|
||||||
linkerhook_set_data(turnip_driver_handle, &android_dlopen_ext, &ns_android_get_exported_namespace);
|
printf("AdrenoSupp: Failed to load Turnip!\n%s\n", dlerror());
|
||||||
|
dlclose(linkerhook);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void (*linkerhook_set_data)(void*) = dlsym(linkerhook, "app__pojav_linkerhook_pass_handle");
|
||||||
|
if(linkerhook_set_data == NULL) {
|
||||||
|
dlclose(linkerhook);
|
||||||
|
dlclose(turnip_driver_handle);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
linkerhook_set_data(turnip_driver_handle);
|
||||||
void* libvulkan = linker_ns_dlopen_unique(cache_dir, "libvulkan.so", RTLD_LOCAL | RTLD_NOW);
|
void* libvulkan = linker_ns_dlopen_unique(cache_dir, "libvulkan.so", RTLD_LOCAL | RTLD_NOW);
|
||||||
return libvulkan;
|
return libvulkan;
|
||||||
}
|
}
|
||||||
@ -217,7 +228,7 @@ void load_vulkan() {
|
|||||||
}
|
}
|
||||||
printf("OSMDroid: loading vulkan regularly...\n");
|
printf("OSMDroid: loading vulkan regularly...\n");
|
||||||
void* vulkan_ptr = dlopen("libvulkan.so", RTLD_LAZY | RTLD_LOCAL);
|
void* vulkan_ptr = dlopen("libvulkan.so", RTLD_LAZY | RTLD_LOCAL);
|
||||||
printf("OSMDroid: loaded vulkan, ptr=%p", vulkan_ptr);
|
printf("OSMDroid: loaded vulkan, ptr=%p\n", vulkan_ptr);
|
||||||
set_vulkan_ptr(vulkan_ptr);
|
set_vulkan_ptr(vulkan_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user