make use of std::format

This commit is contained in:
Chloe committed 2026-02-25 21:54:47 -07:00
1 parent 5caa533a4a
commit a677cab912
2 files changed
+73 -32

No files matched your search

+39 -32
View File
@@ -4,13 +4,12 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <cstdint> #include <cstdint>
#include <android/log.h>
#include <link.h> #include <link.h>
#include <span> #include <span>
#include <unistd.h> #include <unistd.h>
#include <sys/mman.h> #include <sys/mman.h>
#define LOG_TAG "GeodeLauncher-Fix" #include "log.hpp"
class DataPaths { class DataPaths {
public: public:
@@ -142,17 +141,17 @@ bool patch_symbol(std::uint32_t* hash_table, char* str_table, ElfW(Sym)* sym_tab
if (ELF_ST_BIND(sym->st_info) == STB_GLOBAL && ELF_ST_TYPE(sym->st_info) == STT_FUNC) { if (ELF_ST_BIND(sym->st_info) == STB_GLOBAL && ELF_ST_TYPE(sym->st_info) == STT_FUNC) {
// we found it! now go rename the symbol // we found it! now go rename the symbol
__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "Disabling symbol at %p (%s)", sym_name, sym_name); log::debug("Disabling symbol at {} ({})", reinterpret_cast<void*>(sym_name), sym_name);
if (!set_mprotect(reinterpret_cast<std::uintptr_t>(sym_name), SYMBOL_PATCH_VALUE.size(), PROT_READ | PROT_WRITE)) { if (!set_mprotect(reinterpret_cast<std::uintptr_t>(sym_name), SYMBOL_PATCH_VALUE.size(), PROT_READ | PROT_WRITE)) {
__android_log_print(ANDROID_LOG_WARN, LOG_TAG, "failed to patch symbol: could not set writable flag"); log::warn("failed to patch symbol: could not set writable flag");
return false; return false;
} }
memcpy(sym_name, SYMBOL_PATCH_VALUE.data(), SYMBOL_PATCH_VALUE.size()); memcpy(sym_name, SYMBOL_PATCH_VALUE.data(), SYMBOL_PATCH_VALUE.size());
if (!set_mprotect(reinterpret_cast<std::uintptr_t>(sym_name), SYMBOL_PATCH_VALUE.size(), PROT_READ)) { if (!set_mprotect(reinterpret_cast<std::uintptr_t>(sym_name), SYMBOL_PATCH_VALUE.size(), PROT_READ)) {
__android_log_print(ANDROID_LOG_WARN, LOG_TAG, "failed to patch symbol: could not remove writable flag"); log::warn("failed to patch symbol: could not remove writable flag");
return false; return false;
} }
@@ -161,7 +160,8 @@ bool patch_symbol(std::uint32_t* hash_table, char* str_table, ElfW(Sym)* sym_tab
} }
} }
__android_log_print(ANDROID_LOG_WARN, LOG_TAG, "could not find symbol %s to patch (hash: %u)", orig_name, hash); log::warn("could not find symbol {} to patch (hash: {})", orig_name, hash);
return false; return false;
} }
@@ -186,13 +186,8 @@ constexpr std::array remove_symbols{
bool perform_symbol_patches(dl_phdr_info* info, const ElfDynamicState& state) { bool perform_symbol_patches(dl_phdr_info* info, const ElfDynamicState& state) {
// patch symbol names // patch symbol names
auto so_name = state.str_table + state.soname_idx;
if (strcmp(so_name, "libcocos2dcpp.so") != 0) {
__android_log_print(ANDROID_LOG_WARN, LOG_TAG, "DT_SONAME gives us %s! that's not good", so_name);
}
auto has_error = false; auto has_error = false;
for (const auto& symbol : remove_symbols) { for (const auto symbol : remove_symbols) {
if (!patch_symbol(state.hash_table, state.str_table, state.sym_table, symbol)) { if (!patch_symbol(state.hash_table, state.str_table, state.sym_table, symbol)) {
has_error = true; has_error = true;
} }
@@ -218,7 +213,7 @@ bool rewrite_symbol_reloc(std::uintptr_t addr, T& r, ElfW(Sym)* sym, void* func)
// we're only interested in JUMP_SLOT symbols // we're only interested in JUMP_SLOT symbols
if (type != R_AARCH64_JUMP_SLOT && type != R_ARM_JUMP_SLOT) { if (type != R_AARCH64_JUMP_SLOT && type != R_ARM_JUMP_SLOT) {
__android_log_print(ANDROID_LOG_WARN, LOG_TAG, "asked to patch unknown symbol type: %llu", type); log::warn("asked to patch unknown symbol type: {:#x}", type);
return false; return false;
} }
@@ -229,10 +224,10 @@ bool rewrite_symbol_reloc(std::uintptr_t addr, T& r, ElfW(Sym)* sym, void* func)
val += r.r_addend; val += r.r_addend;
} }
__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "Patching relocation at vaddr %#lx (offset=%#llx): %#lx => %#lx", addr, r.r_offset, *write_addr, val); log::debug("Patching relocation at vaddr {:#x} (offset={:#x}): {:#x} => {:#x}", addr, r.r_offset, *write_addr, val);
if (!set_mprotect(addr, sizeof(std::uintptr_t), PROT_WRITE | PROT_READ)) { if (!set_mprotect(addr, sizeof(std::uintptr_t), PROT_WRITE | PROT_READ)) {
__android_log_print(ANDROID_LOG_WARN, LOG_TAG, "Failed to patch relocation: failed to add writable flag"); log::warn("Failed to patch relocation: failed to add writable flag");
return false; return false;
} }
@@ -240,7 +235,7 @@ bool rewrite_symbol_reloc(std::uintptr_t addr, T& r, ElfW(Sym)* sym, void* func)
*write_addr = val; *write_addr = val;
if (!set_mprotect(addr, sizeof(std::uintptr_t), PROT_READ)) { if (!set_mprotect(addr, sizeof(std::uintptr_t), PROT_READ)) {
__android_log_print(ANDROID_LOG_WARN, LOG_TAG, "Failed to patch relocation: failed to remove writable flag"); log::warn("Failed to patch relocation: failed to remove writable flag");
return false; return false;
} }
@@ -284,7 +279,7 @@ bool perform_reloc_patches(dl_phdr_info* info, const ElfDynamicState& state) {
int on_dl_iterate(dl_phdr_info* info, size_t size, void* data) { int on_dl_iterate(dl_phdr_info* info, size_t size, void* data) {
// this is probably going to be gd // this is probably going to be gd
if (info->dlpi_name != nullptr && strstr(info->dlpi_name, "libcocos2dcpp.so") != nullptr) { if (info->dlpi_name != nullptr && strstr(info->dlpi_name, "libcocos2dcpp.so") != nullptr) {
__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "Base address of libcocos2dcpp: %#llx", info->dlpi_addr); log::debug("Base address of libcocos2dcpp: {:#x}", info->dlpi_addr);
// step 1: get the dynamic table // step 1: get the dynamic table
std::uintptr_t dyn_addr = 0u; std::uintptr_t dyn_addr = 0u;
@@ -297,7 +292,7 @@ int on_dl_iterate(dl_phdr_info* info, size_t size, void* data) {
} }
if (dyn_addr == 0u) { if (dyn_addr == 0u) {
__android_log_print(ANDROID_LOG_WARN, LOG_TAG, "failed to find libcocos dynamic section"); log::warn("failed to find libcocos dynamic section");
return 0; return 0;
} }
@@ -333,7 +328,7 @@ int on_dl_iterate(dl_phdr_info* info, size_t size, void* data) {
auto val = dyn_entry->d_un.d_val; auto val = dyn_entry->d_un.d_val;
state.plt_table_rela = val == DT_RELA; state.plt_table_rela = val == DT_RELA;
if (val != DT_RELA && val != DT_REL) { if (val != DT_RELA && val != DT_REL) {
__android_log_print(ANDROID_LOG_WARN, LOG_TAG, "unrecognized PLTREL type %llx", val); log::warn("unrecognized PLTREL type {:#x}", val);
} }
break; break;
} }
@@ -349,13 +344,24 @@ int on_dl_iterate(dl_phdr_info* info, size_t size, void* data) {
} }
if (state.is_empty()) { if (state.is_empty()) {
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "failed to parse dynamic section (at least one table is null)"); log::error("failed to parse dynamic section (at least one table is null)");
return -1; return -1;
} }
bool failed = state.plt_table_rela bool failed = false;
auto so_name = state.str_table + state.soname_idx;
if (strcmp(so_name, "libcocos2dcpp.so") != 0) {
log::warn("DT_SONAME gives us {}! that's not good", so_name);
failed = true;
}
auto reloc_failed = state.plt_table_rela
? !perform_reloc_patches<ElfW(Rela)>(info, state) ? !perform_reloc_patches<ElfW(Rela)>(info, state)
: !perform_reloc_patches<ElfW(Rel)>(info, state); : !perform_reloc_patches<ElfW(Rel)>(info, state);
if (reloc_failed) {
failed = true;
}
if (DataPaths::get_instance().patch_exceptions) { if (DataPaths::get_instance().patch_exceptions) {
if (!perform_symbol_patches(info, state)) { if (!perform_symbol_patches(info, state)) {
@@ -364,11 +370,14 @@ int on_dl_iterate(dl_phdr_info* info, size_t size, void* data) {
} }
if (failed) { if (failed) {
__android_log_print( log::info(
ANDROID_LOG_INFO, "symbol patch diagnostics\nlibrary path: {}\naddrs: base={:#x} sym={} str={} hash={} plt={}",
LOG_TAG, info->dlpi_name,
"symbol patch diagnostics\nlibrary path: %s\naddrs: base=%p sym=%p str=%p hash=%p plt=%p", info->dlpi_addr,
info->dlpi_name, reinterpret_cast<void*>(info->dlpi_addr), state.sym_table, state.str_table, state.hash_table, state.plt_table reinterpret_cast<void*>(state.sym_table),
reinterpret_cast<void*>(state.str_table),
reinterpret_cast<void*>(state.hash_table),
state.plt_table
); );
} }
@@ -384,15 +393,13 @@ extern "C" JNIEXPORT void JNICALL Java_com_geode_launcher_LauncherFix_performPat
} }
std::optional<std::string> redirect_path(const char* pathname) { std::optional<std::string> redirect_path(const char* pathname) {
auto& data_path = DataPaths::get_instance().data_path; std::string_view data_path = DataPaths::get_instance().data_path;
auto& original_data_path = DataPaths::get_instance().original_data_path; std::string_view original_data_path = DataPaths::get_instance().original_data_path;
if (!data_path.empty() && !original_data_path.empty()) { if (!data_path.empty() && !original_data_path.empty()) {
// call this a c string optimization // call this a c string optimization
if (std::strncmp(pathname, original_data_path.c_str(), original_data_path.size()) == 0) { if (std::strncmp(pathname, original_data_path.data(), original_data_path.size()) == 0) {
auto path = data_path + (pathname + original_data_path.size()); return std::format("{}{}", data_path, (pathname + original_data_path.size()));
return path;
} }
} }
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#define LOG_TAG "GeodeLauncher-Fix"
#include <android/log.h>
#include <format>
namespace log {
template<typename... Args>
void log_internal(android_LogPriority prio, std::format_string<Args...> fmt, Args&&... args) {
std::string str = std::format(fmt, std::forward<Args>(args)...);
__android_log_write(prio, LOG_TAG, str.c_str());
}
template<typename... Args>
inline void debug(std::format_string<Args...> fmt, Args&&... args) {
log_internal(ANDROID_LOG_DEBUG, fmt, std::forward<Args>(args)...);
}
template<typename... Args>
inline void info(std::format_string<Args...> fmt, Args&&... args) {
log_internal(ANDROID_LOG_INFO, fmt, std::forward<Args>(args)...);
}
template<typename... Args>
inline void warn(std::format_string<Args...> fmt, Args&&... args) {
log_internal(ANDROID_LOG_WARN, fmt, std::forward<Args>(args)...);
}
template<typename... Args>
inline void error(std::format_string<Args...> fmt, Args&&... args) {
log_internal(ANDROID_LOG_ERROR, fmt, std::forward<Args>(args)...);
}
}