From bedd5ea53a4409aded66657825413fec3c7a18f3 Mon Sep 17 00:00:00 2001 From: TheBrokenRail Date: Sun, 25 Sep 2022 15:47:36 -0400 Subject: [PATCH] Replace PatcheLF With LIEF --- .gitmodules | 6 +- CMakeLists.txt | 1 + dependencies/CMakeLists.txt | 4 + dependencies/LIEF/CMakeLists.txt | 39 +++++ dependencies/LIEF/src | 1 + launcher/CMakeLists.txt | 7 +- launcher/dependencies/CMakeLists.txt | 4 - launcher/dependencies/patchelf/CMakeLists.txt | 17 --- launcher/dependencies/patchelf/src | 1 - launcher/src/bootstrap.c | 5 +- launcher/src/patchelf.c | 136 ------------------ launcher/src/patchelf.cpp | 91 ++++++++++++ launcher/src/patchelf.h | 2 +- libreborn/src/patch/patch.c | 1 - media-layer/core/CMakeLists.txt | 2 +- .../gles/src/compatibility-layer/matrix.h | 4 +- media-layer/core/src/audio/file.cpp | 130 ++--------------- 17 files changed, 157 insertions(+), 294 deletions(-) create mode 100644 dependencies/LIEF/CMakeLists.txt create mode 160000 dependencies/LIEF/src delete mode 100644 launcher/dependencies/CMakeLists.txt delete mode 100644 launcher/dependencies/patchelf/CMakeLists.txt delete mode 160000 launcher/dependencies/patchelf/src delete mode 100644 launcher/src/patchelf.c create mode 100644 launcher/src/patchelf.cpp diff --git a/.gitmodules b/.gitmodules index 9640f58..75ff9ad 100644 --- a/.gitmodules +++ b/.gitmodules @@ -11,6 +11,6 @@ [submodule "dependencies/zenity/src"] path = dependencies/zenity/src url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/zenity.git -[submodule "launcher/dependencies/patchelf/src"] - path = launcher/dependencies/patchelf/src - url = https://github.com/NixOS/patchelf.git +[submodule "dependencies/LIEF/src"] + path = dependencies/LIEF/src + url = https://github.com/lief-project/LIEF.git diff --git a/CMakeLists.txt b/CMakeLists.txt index f57cafe..cca2442 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,6 +117,7 @@ if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(DEFAULT_PREFIX "/") endif() set(CMAKE_INSTALL_PREFIX "${DEFAULT_PREFIX}" CACHE PATH "" FORCE) + set(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT FALSE) endif() # Required Compile Flags diff --git a/dependencies/CMakeLists.txt b/dependencies/CMakeLists.txt index 6868924..f975e73 100644 --- a/dependencies/CMakeLists.txt +++ b/dependencies/CMakeLists.txt @@ -12,3 +12,7 @@ endif() if(BUILD_NATIVE_COMPONENTS AND NOT MCPI_SERVER_MODE) add_subdirectory(zenity) endif() +# LIEF +if(BUILD_NATIVE_COMPONENTS OR (BUILD_ARM_COMPONENTS AND NOT MCPI_SERVER_MODE AND NOT MCPI_USE_MEDIA_LAYER_PROXY)) + add_subdirectory(LIEF) +endif() diff --git a/dependencies/LIEF/CMakeLists.txt b/dependencies/LIEF/CMakeLists.txt new file mode 100644 index 0000000..3cbdb18 --- /dev/null +++ b/dependencies/LIEF/CMakeLists.txt @@ -0,0 +1,39 @@ +project(LIEF) + +# Silence Warnings +add_compile_options(-w -Wno-psabi) + +## LIEF + +# Options +set(BUILD_SHARED_LIBS TRUE CACHE BOOL "" FORCE) +set(LIEF_C_API FALSE CACHE BOOL "" FORCE) +set(LIEF_EXAMPLES FALSE CACHE BOOL "" FORCE) +set(LIEF_PYTHON_API FALSE CACHE BOOL "" FORCE) +set(LIEF_TESTS FALSE CACHE BOOL "" FORCE) +set(LIEF_USE_CCACHE FALSE CACHE BOOL "" FORCE) +set(LIEF_LOGGING FALSE CACHE BOOL "" FORCE) +set(LIEF_LOGGING_DEBUG FALSE CACHE BOOL "" FORCE) +set(LIEF_ENABLE_JSON FALSE CACHE BOOL "" FORCE) +set(LIEF_ELF TRUE CACHE BOOL "" FORCE) +set(LIEF_PE FALSE CACHE BOOL "" FORCE) +set(LIEF_MACHO FALSE CACHE BOOL "" FORCE) +set(LIEF_DEX FALSE CACHE BOOL "" FORCE) +set(LIEF_ART FALSE CACHE BOOL "" FORCE) +set(LIEF_OAT FALSE CACHE BOOL "" FORCE) +set(LIEF_VDEX FALSE CACHE BOOL "" FORCE) + +# Download +add_subdirectory(src EXCLUDE_FROM_ALL) + +# Ensure Build +add_custom_target(LIEF-build ALL DEPENDS LIB_LIEF) + +# Install +install(TARGETS LIB_LIEF DESTINATION "${MCPI_LIB_DIR}") +if(BUILD_ARM_COMPONENTS) + install(TARGETS LIB_LIEF EXPORT sdk DESTINATION "${MCPI_SDK_LIB_DIR}") +endif() + +# License +install(FILES src/LICENSE DESTINATION "${MCPI_LEGAL_DIR}/LIEF") diff --git a/dependencies/LIEF/src b/dependencies/LIEF/src new file mode 160000 index 0000000..c7b3ce3 --- /dev/null +++ b/dependencies/LIEF/src @@ -0,0 +1 @@ +Subproject commit c7b3ce3b2ce6917855a72709f73ef6d00b50e1f7 diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 8060d7a..f56f864 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1,17 +1,14 @@ project(launcher) -# Dependencies -add_subdirectory(dependencies) - # Launcher -add_executable(launcher src/bootstrap.c src/patchelf.c src/crash-report.c) +add_executable(launcher src/bootstrap.c src/patchelf.cpp src/crash-report.c) if(MCPI_SERVER_MODE) target_sources(launcher PRIVATE src/server/launcher.c) else() embed_resource(launcher src/client/available-feature-flags) target_sources(launcher PRIVATE src/client/launcher.cpp src/client/cache.cpp) endif() -target_link_libraries(launcher reborn-util) +target_link_libraries(launcher reborn-util LIB_LIEF) # RPath set_target_properties(launcher PROPERTIES INSTALL_RPATH "$ORIGIN/lib/native") diff --git a/launcher/dependencies/CMakeLists.txt b/launcher/dependencies/CMakeLists.txt deleted file mode 100644 index 19ac04e..0000000 --- a/launcher/dependencies/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -project(launcher-dependencies) - -# PatchELF -add_subdirectory(patchelf) diff --git a/launcher/dependencies/patchelf/CMakeLists.txt b/launcher/dependencies/patchelf/CMakeLists.txt deleted file mode 100644 index 8475bbd..0000000 --- a/launcher/dependencies/patchelf/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -project(patchelf) - -# Silence Warnings -add_compile_options(-w) - -## PatchELF - -# Build -add_executable(patchelf src/src/patchelf.cc) -target_compile_definitions(patchelf PRIVATE -D_FILE_OFFSET_BITS=64) -set_target_properties(patchelf PROPERTIES CXX_STANDARD 17) - -# Install -install(TARGETS patchelf DESTINATION "${MCPI_BIN_DIR}") - -# License -install(FILES src/COPYING DESTINATION "${MCPI_LEGAL_DIR}/patchelf") diff --git a/launcher/dependencies/patchelf/src b/launcher/dependencies/patchelf/src deleted file mode 160000 index c2b419d..0000000 --- a/launcher/dependencies/patchelf/src +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c2b419dc2a0d6095eaa69b65ad5854ce847bdd01 diff --git a/launcher/src/bootstrap.c b/launcher/src/bootstrap.c index 3325a3c..fdf2a50 100644 --- a/launcher/src/bootstrap.c +++ b/launcher/src/bootstrap.c @@ -272,10 +272,7 @@ void bootstrap(int argc, char *argv[]) { safe_asprintf(&linker, "%s/sysroot/lib/ld-linux-armhf.so.3", binary_directory); #else // Use Current Linker - char *exe = realpath("/proc/self/exe", NULL); - ALLOC_CHECK(exe); - linker = patch_get_interpreter(exe); - free(exe); + linker = patch_get_interpreter(); #endif // Patch diff --git a/launcher/src/patchelf.c b/launcher/src/patchelf.c deleted file mode 100644 index 5111b42..0000000 --- a/launcher/src/patchelf.c +++ /dev/null @@ -1,136 +0,0 @@ -#include -#include -#include - -#include - -#include "bootstrap.h" -#include "patchelf.h" - -// Duplicate MCPI Executable Into /tmp -static void duplicate_mcpi_executable(const char *original_path, char *new_path) { - // Ensure Temporary Directory - { - // Check If It Exists - struct stat tmp_stat; - int exists = stat(MCPI_PATCHED_DIR, &tmp_stat) != 0 ? 0 : S_ISDIR(tmp_stat.st_mode); - if (!exists) { - // Doesn't Exist - if (mkdir(MCPI_PATCHED_DIR, S_IRUSR | S_IWUSR | S_IXUSR) != 0) { - ERR("Unable To Create Temporary Folder: %s", strerror(errno)); - } - } - } - - // Generate New File - int new_file_fd = mkstemp(new_path); - if (new_file_fd == -1) { - ERR("Unable To Create Temporary File: %s", strerror(errno)); - } - FILE *new_file = fdopen(new_file_fd, "wb"); - if (new_file == NULL) { - ERR("Unable To Open Temporary File: %s", strerror(errno)); - } - - // Copy Original File - { - // Open Original File - FILE *original_file = fopen(original_path, "rb"); - if (original_file == NULL) { - ERR("Unable To Open File: %s", original_path); - } - - // Copy -#define BUFFER_SIZE 1024 - char buf[BUFFER_SIZE]; - size_t bytes_read = 0; - while ((bytes_read = fread((void *) buf, 1, BUFFER_SIZE, original_file)) > 0) { - fwrite((void *) buf, 1, bytes_read, new_file); - if (ferror(new_file) != 0) { - ERR("Unable To Write File: %s", new_path); - } - } - if (ferror(original_file) != 0) { - ERR("Unable To Read File: %s", original_path); - } - - // Close Original File - fclose(original_file); - } - - // Close New File - fclose(new_file); - close(new_file_fd); -} - -// Fix MCPI Dependencies -#define patch_mcpi_elf_dependencies_with_extra_patchelf_args(...) \ - ({ \ - const char *const _macro_command[] = { \ - "patchelf", \ - ##__VA_ARGS__, \ - "--remove-needed", "libbcm_host.so", \ - "--remove-needed", "libX11.so.6", \ - "--remove-needed", "libEGL.so", \ - "--remove-needed", "libGLESv2.so", \ - "--remove-needed", "libSDL-1.2.so.0", \ - "--add-needed", "libmedia-layer-core.so", \ - new_path, \ - NULL \ - }; \ - int _macro_return_code = 0; \ - char *_macro_output = run_command(_macro_command, &_macro_return_code); \ - if (_macro_output != NULL) { \ - free(_macro_output); \ - } \ - _macro_return_code; \ - }) -void patch_mcpi_elf_dependencies(const char *original_path, char *new_path, const char *linker) { - // Duplicate MCPI executable into /tmp so it can be modified. - duplicate_mcpi_executable(original_path, new_path); - - // Run patchelf - int return_code; - if (linker == NULL) { - return_code = patch_mcpi_elf_dependencies_with_extra_patchelf_args(); - } else { - return_code = patch_mcpi_elf_dependencies_with_extra_patchelf_args("--set-interpreter", linker); - } - if (!is_exit_status_success(return_code)) { - char *exit_status_line = NULL; - get_exit_status_string(return_code, &exit_status_line); - ERR("patchelf Failed%s", exit_status_line); - } - - // Fix Permissions - if (chmod(new_path, S_IRUSR | S_IXUSR) != 0) { - ERR("Unable To Set File Permissions: %s: %s", new_path, strerror(errno)); - } -} - -// Get Interpreter -char *patch_get_interpreter(const char *file) { - // Run - const char *const command[] = { - "patchelf", - "--print-interpreter", - file, - NULL - }; - int return_code; - char *output = run_command(command, &return_code); - if (!is_exit_status_success(return_code)) { - char *exit_status_line = NULL; - get_exit_status_string(return_code, &exit_status_line); - ERR("patchelf Failed%s", exit_status_line); - } - if (output != NULL) { - // Trim - int length = strlen(output); - if (output[length - 1] == '\n') { - output[length - 1] = '\0'; - } - } - // Return - return output; -} diff --git a/launcher/src/patchelf.cpp b/launcher/src/patchelf.cpp new file mode 100644 index 0000000..148eb35 --- /dev/null +++ b/launcher/src/patchelf.cpp @@ -0,0 +1,91 @@ +#include +#include + +#include + +#include + +#include "patchelf.h" + +// Duplicate MCPI Executable Into /tmp +static void duplicate_mcpi_executable(char *new_path) { + // Ensure Temporary Directory + { + // Check If It Exists + struct stat tmp_stat; + int exists = stat(MCPI_PATCHED_DIR, &tmp_stat) != 0 ? 0 : S_ISDIR(tmp_stat.st_mode); + if (!exists) { + // Doesn't Exist + if (mkdir(MCPI_PATCHED_DIR, S_IRUSR | S_IWUSR | S_IXUSR) != 0) { + ERR("Unable To Create Temporary Folder: %s", strerror(errno)); + } + } + } + + // Generate New File + int new_file_fd = mkstemp(new_path); + if (new_file_fd == -1) { + ERR("Unable To Create Temporary File: %s", strerror(errno)); + } + close(new_file_fd); +} + +// Fix MCPI Dependencies +static const char *libraries_to_remove[] = { + "libbcm_host.so", + "libX11.so.6", + "libEGL.so", + "libGLESv2.so", + "libSDL-1.2.so.0" +}; +static const char *libraries_to_add[] = { + "libmedia-layer-core.so" +}; +void patch_mcpi_elf_dependencies(const char *original_path, char *new_path, const char *linker) { + // Duplicate MCPI executable into /tmp so it can be modified. + duplicate_mcpi_executable(new_path); + + // Patch File + { + std::unique_ptr binary = LIEF::ELF::Parser::parse(original_path); + if (linker != NULL) { + binary->interpreter(linker); + } + for (size_t i = 0; i < (sizeof (libraries_to_remove) / sizeof (const char *)); i++) { + binary->remove_library(libraries_to_remove[i]); + } + for (size_t i = 0; i < (sizeof (libraries_to_add) / sizeof (const char *)); i++) { + binary->add_library(libraries_to_add[i]); + } + LIEF::ELF::Builder builder{*binary}; + builder.build(); + builder.write(new_path); + } + + // Fix Permissions + if (chmod(new_path, S_IRUSR | S_IXUSR) != 0) { + ERR("Unable To Set File Permissions: %s: %s", new_path, strerror(errno)); + } +} + +// Get Interpreter +static int dl_iterate_callback(struct dl_phdr_info *info, __attribute__((unused)) size_t size, void *data) { + // Only Search Current Program + if (strcmp(info->dlpi_name, "") == 0) { + for (int i = 0; i < info->dlpi_phnum; i++) { + if (info->dlpi_phdr[i].p_type == PT_INTERP) { + // Callback + *(char **) data = (char *) info->dlpi_phdr[i].p_vaddr; + } + } + } + return 0; +} +char *patch_get_interpreter() { + char *interpreter = NULL; + dl_iterate_phdr(dl_iterate_callback, &interpreter); + if (interpreter != NULL) { + interpreter = strdup(interpreter); + } + return interpreter; +} diff --git a/launcher/src/patchelf.h b/launcher/src/patchelf.h index 4513109..4a95dce 100644 --- a/launcher/src/patchelf.h +++ b/launcher/src/patchelf.h @@ -7,7 +7,7 @@ extern "C" { #define MCPI_PATCHED_DIR "/tmp/.minecraft-pi-patched" void patch_mcpi_elf_dependencies(const char *original_path, char *new_path, const char *linker); -char *patch_get_interpreter(const char *file); +char *patch_get_interpreter(); #ifdef __cplusplus } diff --git a/libreborn/src/patch/patch.c b/libreborn/src/patch/patch.c index 50ac4ea..cd678b5 100644 --- a/libreborn/src/patch/patch.c +++ b/libreborn/src/patch/patch.c @@ -5,7 +5,6 @@ #include #include #include -#include #include diff --git a/media-layer/core/CMakeLists.txt b/media-layer/core/CMakeLists.txt index 5012ae9..cd13c73 100644 --- a/media-layer/core/CMakeLists.txt +++ b/media-layer/core/CMakeLists.txt @@ -28,5 +28,5 @@ if(NOT MCPI_HEADLESS_MODE) # OpenAL find_library(OPENAL_LIBRARY NAMES openal REQUIRED) # Link - target_link_libraries(media-layer-core PRIVATE "${OPENAL_LIBRARY}" PRIVATE m PRIVATE glfw) + target_link_libraries(media-layer-core PRIVATE "${OPENAL_LIBRARY}" PRIVATE m PRIVATE glfw PRIVATE LIB_LIEF) endif() diff --git a/media-layer/core/gles/src/compatibility-layer/matrix.h b/media-layer/core/gles/src/compatibility-layer/matrix.h index 796fb21..e4a8f9b 100644 --- a/media-layer/core/gles/src/compatibility-layer/matrix.h +++ b/media-layer/core/gles/src/compatibility-layer/matrix.h @@ -2,8 +2,8 @@ // Matrix Common #define MATRIX_SIZE 4 -#define MATRIX_DATA_SIZE (sizeof (float) * MATRIX_SIZE * MATRIX_SIZE) -// OpenGL Matricies Are Column-Major +#define MATRIX_DATA_SIZE (sizeof (GLfloat) * MATRIX_SIZE * MATRIX_SIZE) +// OpenGL Matrices Are Column-Major typedef struct { GLfloat data[MATRIX_SIZE][MATRIX_SIZE]; } matrix_t; diff --git a/media-layer/core/src/audio/file.cpp b/media-layer/core/src/audio/file.cpp index e5a0300..c5e76af 100644 --- a/media-layer/core/src/audio/file.cpp +++ b/media-layer/core/src/audio/file.cpp @@ -1,14 +1,11 @@ #include #include #include -#include -#include -#include -#include -#include #include +#include + #include #include "file.h" @@ -16,121 +13,16 @@ // Load Symbol From ELF File static void load_symbol(const char *source, const char *name, std::function callback) { - // File Data - FILE *file_obj = NULL; - unsigned char *file_map = NULL; - long int file_size = 0; - - // Code - { - // Load Main Binary - file_obj = fopen(source, "rb"); - - // Verify Binary - if (!file_obj) { - WARN("Unable To Open: %s", source); - goto end; - } - - // Get File Size - fseek(file_obj, 0L, SEEK_END); - file_size = ftell(file_obj); - fseek(file_obj, 0L, SEEK_SET); - - // Map File To Pointer - file_map = (unsigned char *) mmap(0, file_size, PROT_READ, MAP_PRIVATE, fileno(file_obj), 0); - - // Check ELF Magic - if (file_map[EI_MAG0] != ELFMAG0 || file_map[EI_MAG1] != ELFMAG1 || file_map[EI_MAG2] != ELFMAG2 || file_map[EI_MAG3] != ELFMAG3) { - WARN("Not An ELF File: %s", source); - goto end; - } - if (file_map[EI_CLASS] != ELFCLASS32) { - WARN("ELF File Isn't 32-Bit: %s", source); - goto end; - } - if (file_map[EI_DATA] != ELFDATA2LSB) { - WARN("ELF File Isn't Little-Endian: %s", source); - goto end; - } - - // Parse ELF - Elf32_Ehdr *elf_header = (Elf32_Ehdr *) file_map; - Elf32_Shdr *elf_section_headers = (Elf32_Shdr *) (file_map + elf_header->e_shoff); - int elf_section_header_count = elf_header->e_shnum; - - // Locate Section Names - Elf32_Shdr elf_shstrtab = elf_section_headers[elf_header->e_shstrndx]; - unsigned char *elf_shstrtab_p = file_map + elf_shstrtab.sh_offset; - - // Locate String Table - unsigned char *elf_strtab_p = NULL; - for (int i = 0; i < elf_section_header_count; ++i) { - Elf32_Shdr header = elf_section_headers[i]; - // Check Section Type - if (header.sh_type == SHT_STRTAB) { - // Check Section Name - char *section_name = (char *) (elf_shstrtab_p + header.sh_name); - if (strcmp(section_name, ".dynstr") == 0) { - // Found - elf_strtab_p = file_map + header.sh_offset; - break; - } - } - } - if (elf_strtab_p == NULL) { - WARN("Unable To Find String Table In: %s", source); - goto end; - } - - // Locate Symbol Tables - Elf32_Sym *symbol = NULL; - for (int i = 0; i < elf_section_header_count; ++i) { - // Exit Loop If Finished - if (symbol != NULL) { - break; - } - // Get Section Header - Elf32_Shdr header = elf_section_headers[i]; - // Check Section Type - if (header.sh_type == SHT_DYNSYM) { - // Symbol Table - Elf32_Sym *table = (Elf32_Sym *) (file_map + header.sh_offset); - for (int j = 0; (j * sizeof (Elf32_Sym)) < header.sh_size; j++) { - // Check Symbol Name - char *symbol_name = (char *) (elf_strtab_p + table[j].st_name); - if (strcmp(symbol_name, name) == 0) { - // Found - symbol = &table[j]; - break; - } - } - } - } - - // Check Symbol - if (symbol != NULL) { - // Convert Virtual Address To File Offset - Elf32_Shdr symbol_section_header = elf_section_headers[symbol->st_shndx]; - int vaddr_to_offset = -symbol_section_header.sh_addr + symbol_section_header.sh_offset; - Elf32_Off symbol_offset = symbol->st_value + vaddr_to_offset; - // Access Symbol - unsigned char *value = file_map + symbol_offset; - uint32_t size = symbol->st_size; - callback(value, size); - } else { - // Unable To Find Symbol - WARN("Unable To Find Symbol: %s", name); - } + static std::unique_ptr binary = NULL; + if (binary == NULL) { + binary = LIEF::ELF::Parser::parse(source); } - - end: - // Unmap And Close File - if (file_map != NULL) { - munmap(file_map, file_size); - } - if (file_obj != NULL) { - fclose(file_obj); + const LIEF::ELF::Symbol *symbol = binary->get_dynamic_symbol(name); + if (symbol != NULL) { + std::vector data = binary->get_content_from_virtual_address(symbol->value(), symbol->size(), LIEF::Binary::VA_TYPES::VA); + callback(data.data(), data.size()); + } else { + WARN("Unable To Find Symbol: %s", name); } }