android: format l2c_fcr_hook.cpp

This commit is contained in:
Kavish Devar
2026-04-23 18:44:46 +05:30
parent 113ee0a966
commit 6ac6700be6

View File

@@ -40,8 +40,8 @@ extern "C" {
static HookFunType hook_func = nullptr; static HookFunType hook_func = nullptr;
static uint8_t (*original_l2c_fcr_chk_chan_modes)(void *) = nullptr; static uint8_t (*original_l2c_fcr_chk_chan_modes)(void *) = nullptr;
static tBTA_STATUS (*original_BTA_DmSetLocalDiRecord)(
tSDP_DI_RECORD*, uint32_t*) = nullptr; static tBTA_STATUS (*original_BTA_DmSetLocalDiRecord)(tSDP_DI_RECORD *, uint32_t *) = nullptr;
static std::atomic<bool> enableSdpHook(false); static std::atomic<bool> enableSdpHook(false);
@@ -55,13 +55,13 @@ uint8_t fake_l2c_fcr_chk_chan_modes(void* p_ccb) {
return 1; return 1;
} }
tBTA_STATUS fake_BTA_DmSetLocalDiRecord( tBTA_STATUS fake_BTA_DmSetLocalDiRecord(tSDP_DI_RECORD *p_device_info, uint32_t *p_handle) {
tSDP_DI_RECORD* p_device_info,
uint32_t* p_handle) {
LOGI("fake_BTA_DmSetLocalDiRecord called"); LOGI("fake_BTA_DmSetLocalDiRecord called");
if (original_BTA_DmSetLocalDiRecord && enableSdpHook.load(std::memory_order_relaxed)) original_BTA_DmSetLocalDiRecord(p_device_info, p_handle); if (original_BTA_DmSetLocalDiRecord &&
enableSdpHook.load(std::memory_order_relaxed))
original_BTA_DmSetLocalDiRecord(p_device_info, p_handle);
LOGI("fake_BTA_DmSetLocalDiRecord: modifying vendor to 0x004C, vendor_id_source to 0x0001"); LOGI("fake_BTA_DmSetLocalDiRecord: modifying vendor to 0x004C, vendor_id_source to 0x0001");
@@ -70,14 +70,15 @@ tBTA_STATUS fake_BTA_DmSetLocalDiRecord(
p_device_info->vendor_id_source = 0x0001; p_device_info->vendor_id_source = 0x0001;
} }
LOGI("fake_BTA_DmSetLocalDiRecord: returning status %d", original_BTA_DmSetLocalDiRecord ? original_BTA_DmSetLocalDiRecord(p_device_info, p_handle) : BTA_FAILURE); LOGI("fake_BTA_DmSetLocalDiRecord: returning status %d",
return original_BTA_DmSetLocalDiRecord ? original_BTA_DmSetLocalDiRecord(p_device_info, p_handle) : BTA_FAILURE; original_BTA_DmSetLocalDiRecord ? original_BTA_DmSetLocalDiRecord(p_device_info, p_handle)
: BTA_FAILURE);
return original_BTA_DmSetLocalDiRecord ? original_BTA_DmSetLocalDiRecord(p_device_info,
p_handle)
: BTA_FAILURE;
} }
static bool decompressXZ( static bool decompressXZ(const uint8_t *input, size_t input_size, std::vector<uint8_t> &output) {
const uint8_t* input,
size_t input_size,
std::vector<uint8_t>& output) {
LOGI("decompressXZ called with input_size: %zu", input_size); LOGI("decompressXZ called with input_size: %zu", input_size);
@@ -106,7 +107,8 @@ static bool decompressXZ(
LOGI("decompressXZ: entering decompression loop"); LOGI("decompressXZ: entering decompression loop");
while (true) { while (true) {
LOGI("decompressXZ: xz_dec_run iteration, buf.in_pos: %zu, buf.out_pos: %zu", buf.in_pos, buf.out_pos); LOGI("decompressXZ: xz_dec_run iteration, buf.in_pos: %zu, buf.out_pos: %zu", buf.in_pos,
buf.out_pos);
enum xz_ret ret = xz_dec_run(dec, &buf); enum xz_ret ret = xz_dec_run(dec, &buf);
LOGI("decompressXZ: xz_dec_run returned %d", ret); LOGI("decompressXZ: xz_dec_run returned %d", ret);
@@ -192,9 +194,8 @@ static uintptr_t getModuleBase(const char* name) {
return base; return base;
} }
static uint64_t findSymbolOffsetDynsym( static uint64_t
const std::vector<uint8_t>& elf, findSymbolOffsetDynsym(const std::vector<uint8_t> &elf, const char *symbol_substring) {
const char* symbol_substring) {
LOGI("findSymbolOffsetDynsym called with %s", symbol_substring); LOGI("findSymbolOffsetDynsym called with %s", symbol_substring);
@@ -202,8 +203,7 @@ static uint64_t findSymbolOffsetDynsym(
auto *shdr = reinterpret_cast<const Elf64_Shdr *>( auto *shdr = reinterpret_cast<const Elf64_Shdr *>(
elf.data() + eh->e_shoff); elf.data() + eh->e_shoff);
const char* shstr = const char *shstr = reinterpret_cast<const char *>(
reinterpret_cast<const char*>(
elf.data() + shdr[eh->e_shstrndx].sh_offset); elf.data() + shdr[eh->e_shstrndx].sh_offset);
const Elf64_Shdr *dynsym = nullptr; const Elf64_Shdr *dynsym = nullptr;
@@ -226,8 +226,7 @@ static uint64_t findSymbolOffsetDynsym(
auto *symbols = reinterpret_cast<const Elf64_Sym *>( auto *symbols = reinterpret_cast<const Elf64_Sym *>(
elf.data() + dynsym->sh_offset); elf.data() + dynsym->sh_offset);
const char* strings = const char *strings = reinterpret_cast<const char *>(
reinterpret_cast<const char*>(
elf.data() + dynstr->sh_offset); elf.data() + dynstr->sh_offset);
size_t count = dynsym->sh_size / sizeof(Elf64_Sym); size_t count = dynsym->sh_size / sizeof(Elf64_Sym);
@@ -237,11 +236,10 @@ static uint64_t findSymbolOffsetDynsym(
for (size_t i = 0; i < count; ++i) { for (size_t i = 0; i < count; ++i) {
const char *name = strings + symbols[i].st_name; const char *name = strings + symbols[i].st_name;
if (strstr(name, symbol_substring) && if (strstr(name, symbol_substring) && ELF64_ST_TYPE(symbols[i].st_info) == STT_FUNC) {
ELF64_ST_TYPE(symbols[i].st_info) == STT_FUNC) {
LOGI("findSymbolOffsetDynsym: matched %s @ 0x%lx", LOGI("findSymbolOffsetDynsym: matched %s @ 0x%lx", name,
name, (unsigned long)symbols[i].st_value); (unsigned long) symbols[i].st_value);
return symbols[i].st_value; return symbols[i].st_value;
} }
@@ -251,9 +249,7 @@ static uint64_t findSymbolOffsetDynsym(
return 0; return 0;
} }
static uint64_t findSymbolOffset( static uint64_t findSymbolOffset(const std::vector<uint8_t> &elf, const char *symbol_substring) {
const std::vector<uint8_t>& elf,
const char* symbol_substring) {
LOGI("findSymbolOffset called with symbol_substring: %s", symbol_substring); LOGI("findSymbolOffset called with symbol_substring: %s", symbol_substring);
@@ -261,8 +257,7 @@ static uint64_t findSymbolOffset(
auto *shdr = reinterpret_cast<const Elf64_Shdr *>( auto *shdr = reinterpret_cast<const Elf64_Shdr *>(
elf.data() + eh->e_shoff); elf.data() + eh->e_shoff);
const char* shstr = const char *shstr = reinterpret_cast<const char *>(
reinterpret_cast<const char*>(
elf.data() + shdr[eh->e_shstrndx].sh_offset); elf.data() + shdr[eh->e_shstrndx].sh_offset);
const Elf64_Shdr *symtab = nullptr; const Elf64_Shdr *symtab = nullptr;
@@ -286,8 +281,7 @@ static uint64_t findSymbolOffset(
auto *symbols = reinterpret_cast<const Elf64_Sym *>( auto *symbols = reinterpret_cast<const Elf64_Sym *>(
elf.data() + symtab->sh_offset); elf.data() + symtab->sh_offset);
const char* strings = const char *strings = reinterpret_cast<const char *>(
reinterpret_cast<const char*>(
elf.data() + strtab->sh_offset); elf.data() + strtab->sh_offset);
size_t count = symtab->sh_size / sizeof(Elf64_Sym); size_t count = symtab->sh_size / sizeof(Elf64_Sym);
@@ -296,10 +290,10 @@ static uint64_t findSymbolOffset(
for (size_t i = 0; i < count; ++i) { for (size_t i = 0; i < count; ++i) {
const char *name = strings + symbols[i].st_name; const char *name = strings + symbols[i].st_name;
if (strstr(name, symbol_substring) && if (strstr(name, symbol_substring) && ELF64_ST_TYPE(symbols[i].st_info) == STT_FUNC) {
ELF64_ST_TYPE(symbols[i].st_info) == STT_FUNC) {
LOGI("findSymbolOffset: matched symbol %s at 0x%lx", name, (unsigned long)symbols[i].st_value); LOGI("findSymbolOffset: matched symbol %s at 0x%lx", name,
(unsigned long) symbols[i].st_value);
return symbols[i].st_value; return symbols[i].st_value;
} }
@@ -346,8 +340,7 @@ static bool hookLibrary(const char* libname) {
auto *shdr = reinterpret_cast<Elf64_Shdr *>( auto *shdr = reinterpret_cast<Elf64_Shdr *>(
file.data() + eh->e_shoff); file.data() + eh->e_shoff);
const char* shstr = const char *shstr = reinterpret_cast<const char *>(
reinterpret_cast<const char*>(
file.data() + shdr[eh->e_shstrndx].sh_offset); file.data() + shdr[eh->e_shstrndx].sh_offset);
uint64_t chk_offset = 0; uint64_t chk_offset = 0;
@@ -357,22 +350,16 @@ static bool hookLibrary(const char* libname) {
if (!strcmp(shstr + shdr[i].sh_name, ".gnu_debugdata")) { if (!strcmp(shstr + shdr[i].sh_name, ".gnu_debugdata")) {
LOGI("hookLibrary: found .gnu_debugdata section"); LOGI("hookLibrary: found .gnu_debugdata section");
std::vector<uint8_t> compressed( std::vector<uint8_t> compressed(file.begin() + shdr[i].sh_offset,
file.begin() + shdr[i].sh_offset,
file.begin() + shdr[i].sh_offset + shdr[i].sh_size); file.begin() + shdr[i].sh_offset + shdr[i].sh_size);
std::vector<uint8_t> decompressed; std::vector<uint8_t> decompressed;
if (decompressXZ( if (decompressXZ(compressed.data(), compressed.size(), decompressed)) {
compressed.data(),
compressed.size(),
decompressed)) {
chk_offset = findSymbolOffset(decompressed, chk_offset = findSymbolOffset(decompressed, "l2c_fcr_chk_chan_modes");
"l2c_fcr_chk_chan_modes");
sdp_offset = findSymbolOffset(decompressed, sdp_offset = findSymbolOffset(decompressed, "BTA_DmSetLocalDiRecord");
"BTA_DmSetLocalDiRecord");
} else { } else {
LOGE("debugdata decompress failed"); LOGE("debugdata decompress failed");
} }
@@ -383,14 +370,12 @@ static bool hookLibrary(const char* libname) {
if (!chk_offset) { if (!chk_offset) {
LOGI("fallback dynsym chk"); LOGI("fallback dynsym chk");
chk_offset = findSymbolOffsetDynsym(file, chk_offset = findSymbolOffsetDynsym(file, "l2c_fcr_chk_chan_modes");
"l2c_fcr_chk_chan_modes");
} }
if (!sdp_offset) { if (!sdp_offset) {
LOGI("fallback dynsym sdp"); LOGI("fallback dynsym sdp");
sdp_offset = findSymbolOffsetDynsym(file, sdp_offset = findSymbolOffsetDynsym(file, "BTA_DmSetLocalDiRecord");
"BTA_DmSetLocalDiRecord");
} }
uintptr_t base = getModuleBase(libname); uintptr_t base = getModuleBase(libname);
@@ -401,16 +386,14 @@ static bool hookLibrary(const char* libname) {
if (chk_offset) { if (chk_offset) {
void *target = reinterpret_cast<void *>(base + chk_offset); void *target = reinterpret_cast<void *>(base + chk_offset);
hook_func(target, hook_func(target, (void *) fake_l2c_fcr_chk_chan_modes,
(void*)fake_l2c_fcr_chk_chan_modes,
(void **) &original_l2c_fcr_chk_chan_modes); (void **) &original_l2c_fcr_chk_chan_modes);
LOGI("hooked chk"); LOGI("hooked chk");
} }
if (sdp_offset) { if (sdp_offset) {
void *target = reinterpret_cast<void *>(base + sdp_offset); void *target = reinterpret_cast<void *>(base + sdp_offset);
hook_func(target, hook_func(target, (void *) fake_BTA_DmSetLocalDiRecord,
(void*)fake_BTA_DmSetLocalDiRecord,
(void **) &original_BTA_DmSetLocalDiRecord); (void **) &original_BTA_DmSetLocalDiRecord);
LOGI("hooked sdp"); LOGI("hooked sdp");
} }
@@ -432,20 +415,19 @@ static void on_library_loaded(const char* name, void*) {
} }
} }
extern "C" extern "C" [[gnu::visibility("default")]]
[[gnu::visibility("default")]]
[[gnu::used]] [[gnu::used]]
NativeOnModuleLoaded native_init(const NativeAPIEntries *entries) { NativeOnModuleLoaded native_init(const NativeAPIEntries *entries) {
LOGI("native_init called with entries: %p", entries); LOGI("native_init called with entries: %p", entries);
hook_func = (HookFunType) entries->hook_func; hook_func = (HookFunType) entries->hook_func;
LOGI("LibrePodsNativeHook initialized, sdp hook enabled: %d", enableSdpHook.load(std::memory_order_relaxed)); LOGI("LibrePodsNativeHook initialized, sdp hook enabled: %d",
enableSdpHook.load(std::memory_order_relaxed));
return on_library_loaded; return on_library_loaded;
} }
extern "C" extern "C" JNIEXPORT void JNICALL
JNIEXPORT void JNICALL Java_me_kavishdevar_librepods_utils_NativeBridge_setSdpHook(JNIEnv *, jobject thiz,
Java_me_kavishdevar_librepods_utils_NativeBridge_setSdpHook( jboolean enable) {
JNIEnv*, jobject thiz, jboolean enable) {
LOGI("setSdpHook called with enable: %d", enable); LOGI("setSdpHook called with enable: %d", enable);
enableSdpHook.store(enable, std::memory_order_relaxed); enableSdpHook.store(enable, std::memory_order_relaxed);