mirror of
https://github.com/0O0o0oOoO00/Alas.git
synced 2026-05-21 07:39:31 +08:00
add: migrate source code of luahook
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
#include "shared_cache_ctx.h"
|
||||
|
||||
#include <mach/mach.h>
|
||||
#include <mach/task.h>
|
||||
#include <mach-o/dyld_images.h>
|
||||
|
||||
#include "logging/logging.h"
|
||||
|
||||
#include "mmap_file_util.h"
|
||||
|
||||
typedef uintptr_t addr_t;
|
||||
|
||||
extern "C" {
|
||||
extern const char *dyld_shared_cache_file_path();
|
||||
extern int __shared_region_check_np(uint64_t *startaddress);
|
||||
}
|
||||
|
||||
const char *shared_cache_get_file_path() {
|
||||
return dyld_shared_cache_file_path();
|
||||
}
|
||||
|
||||
struct dyld_cache_header *shared_cache_get_load_addr() {
|
||||
addr_t shared_cache_base = 0;
|
||||
if (__shared_region_check_np((uint64_t *)&shared_cache_base) != 0) {
|
||||
WARN_LOG("__shared_region_check_np failed");
|
||||
}
|
||||
|
||||
if (shared_cache_base)
|
||||
return (struct dyld_cache_header *)shared_cache_base;
|
||||
|
||||
// task info
|
||||
task_dyld_info_data_t task_dyld_info;
|
||||
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
|
||||
kern_return_t ret = task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&task_dyld_info, &count);
|
||||
if (ret != KERN_SUCCESS) {
|
||||
ERROR_LOG("task_info failed, ret: %d", ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get dyld load address
|
||||
auto *infos = (struct dyld_all_image_infos *)(uintptr_t)task_dyld_info.all_image_info_addr;
|
||||
auto *shared_cache = (struct dyld_cache_header *)infos->sharedCacheBaseAddress;
|
||||
return shared_cache;
|
||||
}
|
||||
|
||||
int shared_cache_load_symbols(shared_cache_ctx_t *ctx) {
|
||||
uint64_t localSymbolsOffset = 0;
|
||||
|
||||
bool latest_shared_cache_format = true;
|
||||
|
||||
const char *shared_cache_path = shared_cache_get_file_path();
|
||||
char shared_cache_symbols_path[4096] = {0};
|
||||
{
|
||||
strcat(shared_cache_symbols_path, shared_cache_path);
|
||||
strcat(shared_cache_symbols_path, ".symbols");
|
||||
}
|
||||
|
||||
auto mmapSharedCacheSymbolsMng = new MmapFileManager(shared_cache_symbols_path);
|
||||
auto mmap_buffer = mmapSharedCacheSymbolsMng->map();
|
||||
if (mmap_buffer) { // iphoneos >= 15.0, which has .symbols file
|
||||
ctx->mmap_shared_cache = (struct dyld_cache_header *)mmap_buffer;
|
||||
|
||||
localSymbolsOffset = ctx->mmap_shared_cache->localSymbolsOffset;
|
||||
} else {
|
||||
// iphoneos < 15.0, which has no .symbols file
|
||||
auto mmapSharedCacheMng = new MmapFileManager(shared_cache_symbols_path);
|
||||
|
||||
auto runtime_shared_cache = ctx->runtime_shared_cache;
|
||||
uint64_t mmap_length = runtime_shared_cache->localSymbolsSize;
|
||||
uint64_t mmap_offset = runtime_shared_cache->localSymbolsOffset;
|
||||
|
||||
if (mmap_length == 0)
|
||||
return -1;
|
||||
|
||||
auto mmap_buffer = mmapSharedCacheMng->map_options(mmap_length, mmap_offset);
|
||||
if (!mmap_buffer) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// fake shared cache header
|
||||
auto mmap_shared_cache =
|
||||
(struct dyld_cache_header *)((addr_t)mmap_buffer - runtime_shared_cache->localSymbolsOffset);
|
||||
ctx->mmap_shared_cache = mmap_shared_cache;
|
||||
|
||||
localSymbolsOffset = runtime_shared_cache->localSymbolsOffset;
|
||||
|
||||
latest_shared_cache_format = false;
|
||||
}
|
||||
ctx->latest_shared_cache_format = latest_shared_cache_format;
|
||||
|
||||
{
|
||||
auto mmap_shared_cache = ctx->mmap_shared_cache;
|
||||
auto localInfo = (struct dyld_cache_local_symbols_info *)((char *)mmap_shared_cache + localSymbolsOffset);
|
||||
ctx->local_symbols_info = localInfo;
|
||||
|
||||
if (ctx->latest_shared_cache_format) {
|
||||
auto localEntries_64 = (struct dyld_cache_local_symbols_entry_64 *)((char *)localInfo + localInfo->entriesOffset);
|
||||
ctx->local_symbols_entries_64 = localEntries_64;
|
||||
} else {
|
||||
auto localEntries = (struct dyld_cache_local_symbols_entry *)((char *)localInfo + localInfo->entriesOffset);
|
||||
ctx->local_symbols_entries = localEntries;
|
||||
}
|
||||
|
||||
ctx->symtab = (nlist_t *)((char *)localInfo + localInfo->nlistOffset);
|
||||
ctx->strtab = ((char *)localInfo) + localInfo->stringsOffset;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int shared_cache_ctx_init(shared_cache_ctx_t *ctx) {
|
||||
memset(ctx, 0, sizeof(shared_cache_ctx_t));
|
||||
|
||||
auto runtime_shared_cache = shared_cache_get_load_addr();
|
||||
if (!runtime_shared_cache) {
|
||||
return -1;
|
||||
}
|
||||
ctx->runtime_shared_cache = runtime_shared_cache;
|
||||
|
||||
// shared cache slide
|
||||
auto mappings =
|
||||
(struct dyld_cache_mapping_info *)((char *)runtime_shared_cache + runtime_shared_cache->mappingOffset);
|
||||
uintptr_t slide = (uintptr_t)runtime_shared_cache - (uintptr_t)(mappings[0].address);
|
||||
ctx->runtime_slide = slide;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// refer: dyld
|
||||
bool shared_cache_is_contain(shared_cache_ctx_t *ctx, addr_t addr, size_t length) {
|
||||
struct dyld_cache_header *runtime_shared_cache;
|
||||
if (ctx) {
|
||||
runtime_shared_cache = ctx->runtime_shared_cache;
|
||||
} else {
|
||||
runtime_shared_cache = shared_cache_get_load_addr();
|
||||
}
|
||||
|
||||
addr_t region_start = runtime_shared_cache->sharedRegionStart + ctx->runtime_slide;
|
||||
addr_t region_end = region_start + runtime_shared_cache->sharedRegionSize;
|
||||
if (addr >= region_start && addr < region_end)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int shared_cache_get_symbol_table(shared_cache_ctx_t *ctx, mach_header_t *image_header, nlist_t **out_symtab,
|
||||
uint32_t *out_symtab_count, char **out_strtab) {
|
||||
uint64_t textOffsetInCache = (uint64_t)image_header - (uint64_t)ctx->runtime_shared_cache;
|
||||
|
||||
nlist_t *localNlists = NULL;
|
||||
uint32_t localNlistCount = 0;
|
||||
const char *localStrings = NULL;
|
||||
|
||||
const uint32_t entriesCount = ctx->local_symbols_info->entriesCount;
|
||||
for (uint32_t i = 0; i < entriesCount; ++i) {
|
||||
if (ctx->latest_shared_cache_format) {
|
||||
if (ctx->local_symbols_entries_64[i].dylibOffset == textOffsetInCache) {
|
||||
uint32_t localNlistStart = ctx->local_symbols_entries_64[i].nlistStartIndex;
|
||||
localNlistCount = ctx->local_symbols_entries_64[i].nlistCount;
|
||||
localNlists = &ctx->symtab[localNlistStart];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (ctx->local_symbols_entries[i].dylibOffset == textOffsetInCache) {
|
||||
uint32_t localNlistStart = ctx->local_symbols_entries[i].nlistStartIndex;
|
||||
localNlistCount = ctx->local_symbols_entries[i].nlistCount;
|
||||
localNlists = &ctx->symtab[localNlistStart];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static struct dyld_cache_image_info *imageInfos = NULL;
|
||||
imageInfos = (struct dyld_cache_image_info *)((addr_t)g_mmap_shared_cache + g_mmap_shared_cache->imagesOffset);
|
||||
char *image_name = (char *)g_mmap_shared_cache + imageInfos[i].pathFileOffset;
|
||||
INFO_LOG("dyld image: %s", image_name);
|
||||
#endif
|
||||
}
|
||||
*out_symtab = localNlists;
|
||||
*out_symtab_count = (uint32_t)localNlistCount;
|
||||
*out_strtab = (char *)ctx->strtab;
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user