127 lines
3.7 KiB
C++
Raw Normal View History

2022-09-25 15:47:36 -04:00
#include <cstdlib>
#include <sys/stat.h>
2024-10-20 01:19:08 -04:00
#include <ranges>
2022-09-25 15:47:36 -04:00
#include <LIEF/ELF.hpp>
2024-02-12 00:44:38 -05:00
#include <dlfcn.h>
#include <link.h>
2022-09-25 15:47:36 -04:00
#include <libreborn/libreborn.h>
2024-11-17 22:48:25 -05:00
#include "bootstrap.h"
2022-09-25 15:47:36 -04:00
// Duplicate MCPI Executable Into /tmp
static void duplicate_mcpi_executable(char *new_path) {
// Ensure Temporary Directory
ensure_directory(MCPI_PATCHED_DIR);
2022-09-25 15:47:36 -04:00
// Generate New File
2024-10-20 01:19:08 -04:00
const int new_file_fd = mkstemp(new_path);
2022-09-25 15:47:36 -04:00
if (new_file_fd == -1) {
ERR("Unable To Create Temporary File: %s", strerror(errno));
}
close(new_file_fd);
}
// Fix MCPI Dependencies
2024-10-20 01:19:08 -04:00
static std::vector<std::string> needed_libraries = {
"libmedia-layer-core.so",
"libpng12.so.0",
"libstdc++.so.6",
"libm.so.6",
"libgcc_s.so.1",
"libc.so.6",
"libpthread.so.0"
2022-09-25 15:47:36 -04:00
};
2024-10-20 01:19:08 -04:00
static std::vector<std::string> function_prefixes_to_patch = {
"SDL_",
"gl"
2022-09-25 15:47:36 -04:00
};
2024-10-20 01:19:08 -04:00
void patch_mcpi_elf_dependencies(const std::string &original_path, char *new_path, const std::string &interpreter, const std::vector<std::string> &rpath, const std::vector<std::string> &mods) {
2022-09-25 15:47:36 -04:00
// Duplicate MCPI executable into /tmp so it can be modified.
duplicate_mcpi_executable(new_path);
2024-10-20 01:19:08 -04:00
// Load Binary
2024-11-17 22:48:25 -05:00
const std::unique_ptr<LIEF::ELF::Binary> binary = LIEF::ELF::Parser::parse(original_path);
2024-10-20 01:19:08 -04:00
// Set Interpreter
2024-11-17 22:48:25 -05:00
binary->interpreter(interpreter);
2024-10-20 01:19:08 -04:00
// Remove Existing Needed Libraries
std::vector<std::string> to_remove;
for (const LIEF::ELF::DynamicEntry &entry : binary->dynamic_entries()) {
const LIEF::ELF::DynamicEntryLibrary *library = dynamic_cast<const LIEF::ELF::DynamicEntryLibrary *>(&entry);
if (library) {
to_remove.push_back(library->name());
2022-09-25 15:47:36 -04:00
}
2024-10-20 01:19:08 -04:00
}
for (const std::string &library : to_remove) {
binary->remove_library(library);
}
// Setup RPath
binary->add(LIEF::ELF::DynamicEntryRpath(rpath));
// Add Libraries
std::vector<std::string> all_libraries;
for (const std::vector<std::string> &list : {mods, needed_libraries}) {
all_libraries.insert(all_libraries.end(), list.begin(), list.end());
}
for (const std::string &library : all_libraries | std::views::reverse) {
binary->add_library(library);
}
// Fix Symbol Names
for (LIEF::ELF::Symbol &symbol : binary->dynamic_symbols()) {
if (symbol.is_function()) {
for (const std::string &prefix : function_prefixes_to_patch) {
if (symbol.name().rfind(prefix, 0) == 0) {
symbol.name("media_" + symbol.name());
break;
}
}
2022-09-25 15:47:36 -04:00
}
}
2024-10-20 01:19:08 -04:00
// Write Binary
LIEF::ELF::Builder builder{*binary};
builder.build();
builder.write(new_path);
2022-09-25 15:47:36 -04:00
// Fix Permissions
if (chmod(new_path, S_IRUSR | S_IXUSR) != 0) {
ERR("Unable To Set File Permissions: %s: %s", new_path, strerror(errno));
}
}
2024-11-17 22:48:25 -05:00
// Linker
std::string get_new_linker(const std::string &binary_directory) {
std::string linker = "/lib/ld-linux-armhf.so.3";
#ifdef MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
linker = binary_directory + "/sysroot" + linker;
#else
(void) binary_directory;
#endif
return linker;
}
std::vector<std::string> get_ld_path(const std::string &binary_directory) {
std::vector<std::string> mcpi_ld_path = {
// ARM Sysroot
#ifdef MCPI_USE_PREBUILT_ARMHF_TOOLCHAIN
"sysroot/lib",
"sysroot/lib/arm-linux-gnueabihf",
"sysroot/usr/lib",
"sysroot/usr/lib/arm-linux-gnueabihf",
#endif
// Libraries
"lib/arm"
};
// Fix Paths
for (std::string &path : mcpi_ld_path) {
path.insert(0, 1, '/');
path.insert(0, binary_directory);
}
// Return
return mcpi_ld_path;
}