Replace PatcheLF With LIEF
This commit is contained in:
parent
eb3c5d2e6f
commit
bedd5ea53a
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -11,6 +11,6 @@
|
|||||||
[submodule "dependencies/zenity/src"]
|
[submodule "dependencies/zenity/src"]
|
||||||
path = dependencies/zenity/src
|
path = dependencies/zenity/src
|
||||||
url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/zenity.git
|
url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/zenity.git
|
||||||
[submodule "launcher/dependencies/patchelf/src"]
|
[submodule "dependencies/LIEF/src"]
|
||||||
path = launcher/dependencies/patchelf/src
|
path = dependencies/LIEF/src
|
||||||
url = https://github.com/NixOS/patchelf.git
|
url = https://github.com/lief-project/LIEF.git
|
||||||
|
@ -117,6 +117,7 @@ if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
|||||||
set(DEFAULT_PREFIX "/")
|
set(DEFAULT_PREFIX "/")
|
||||||
endif()
|
endif()
|
||||||
set(CMAKE_INSTALL_PREFIX "${DEFAULT_PREFIX}" CACHE PATH "" FORCE)
|
set(CMAKE_INSTALL_PREFIX "${DEFAULT_PREFIX}" CACHE PATH "" FORCE)
|
||||||
|
set(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT FALSE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Required Compile Flags
|
# Required Compile Flags
|
||||||
|
4
dependencies/CMakeLists.txt
vendored
4
dependencies/CMakeLists.txt
vendored
@ -12,3 +12,7 @@ endif()
|
|||||||
if(BUILD_NATIVE_COMPONENTS AND NOT MCPI_SERVER_MODE)
|
if(BUILD_NATIVE_COMPONENTS AND NOT MCPI_SERVER_MODE)
|
||||||
add_subdirectory(zenity)
|
add_subdirectory(zenity)
|
||||||
endif()
|
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()
|
||||||
|
39
dependencies/LIEF/CMakeLists.txt
vendored
Normal file
39
dependencies/LIEF/CMakeLists.txt
vendored
Normal file
@ -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")
|
1
dependencies/LIEF/src
vendored
Submodule
1
dependencies/LIEF/src
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit c7b3ce3b2ce6917855a72709f73ef6d00b50e1f7
|
@ -1,17 +1,14 @@
|
|||||||
project(launcher)
|
project(launcher)
|
||||||
|
|
||||||
# Dependencies
|
|
||||||
add_subdirectory(dependencies)
|
|
||||||
|
|
||||||
# Launcher
|
# 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)
|
if(MCPI_SERVER_MODE)
|
||||||
target_sources(launcher PRIVATE src/server/launcher.c)
|
target_sources(launcher PRIVATE src/server/launcher.c)
|
||||||
else()
|
else()
|
||||||
embed_resource(launcher src/client/available-feature-flags)
|
embed_resource(launcher src/client/available-feature-flags)
|
||||||
target_sources(launcher PRIVATE src/client/launcher.cpp src/client/cache.cpp)
|
target_sources(launcher PRIVATE src/client/launcher.cpp src/client/cache.cpp)
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(launcher reborn-util)
|
target_link_libraries(launcher reborn-util LIB_LIEF)
|
||||||
# RPath
|
# RPath
|
||||||
set_target_properties(launcher PROPERTIES INSTALL_RPATH "$ORIGIN/lib/native")
|
set_target_properties(launcher PROPERTIES INSTALL_RPATH "$ORIGIN/lib/native")
|
||||||
|
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
project(launcher-dependencies)
|
|
||||||
|
|
||||||
# PatchELF
|
|
||||||
add_subdirectory(patchelf)
|
|
@ -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")
|
|
@ -1 +0,0 @@
|
|||||||
Subproject commit c2b419dc2a0d6095eaa69b65ad5854ce847bdd01
|
|
@ -272,10 +272,7 @@ void bootstrap(int argc, char *argv[]) {
|
|||||||
safe_asprintf(&linker, "%s/sysroot/lib/ld-linux-armhf.so.3", binary_directory);
|
safe_asprintf(&linker, "%s/sysroot/lib/ld-linux-armhf.so.3", binary_directory);
|
||||||
#else
|
#else
|
||||||
// Use Current Linker
|
// Use Current Linker
|
||||||
char *exe = realpath("/proc/self/exe", NULL);
|
linker = patch_get_interpreter();
|
||||||
ALLOC_CHECK(exe);
|
|
||||||
linker = patch_get_interpreter(exe);
|
|
||||||
free(exe);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Patch
|
// Patch
|
||||||
|
@ -1,136 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
91
launcher/src/patchelf.cpp
Normal file
91
launcher/src/patchelf.cpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#include <cstdlib>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <LIEF/ELF.hpp>
|
||||||
|
|
||||||
|
#include <libreborn/libreborn.h>
|
||||||
|
|
||||||
|
#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<LIEF::ELF::Binary> 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;
|
||||||
|
}
|
@ -7,7 +7,7 @@ extern "C" {
|
|||||||
#define MCPI_PATCHED_DIR "/tmp/.minecraft-pi-patched"
|
#define MCPI_PATCHED_DIR "/tmp/.minecraft-pi-patched"
|
||||||
|
|
||||||
void patch_mcpi_elf_dependencies(const char *original_path, char *new_path, const char *linker);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <elf.h>
|
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
|
|
||||||
|
@ -28,5 +28,5 @@ if(NOT MCPI_HEADLESS_MODE)
|
|||||||
# OpenAL
|
# OpenAL
|
||||||
find_library(OPENAL_LIBRARY NAMES openal REQUIRED)
|
find_library(OPENAL_LIBRARY NAMES openal REQUIRED)
|
||||||
# Link
|
# 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()
|
endif()
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
// Matrix Common
|
// Matrix Common
|
||||||
#define MATRIX_SIZE 4
|
#define MATRIX_SIZE 4
|
||||||
#define MATRIX_DATA_SIZE (sizeof (float) * MATRIX_SIZE * MATRIX_SIZE)
|
#define MATRIX_DATA_SIZE (sizeof (GLfloat) * MATRIX_SIZE * MATRIX_SIZE)
|
||||||
// OpenGL Matricies Are Column-Major
|
// OpenGL Matrices Are Column-Major
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GLfloat data[MATRIX_SIZE][MATRIX_SIZE];
|
GLfloat data[MATRIX_SIZE][MATRIX_SIZE];
|
||||||
} matrix_t;
|
} matrix_t;
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <cstdint>
|
|
||||||
#include <cstring>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <elf.h>
|
|
||||||
|
|
||||||
#include <AL/al.h>
|
#include <AL/al.h>
|
||||||
|
|
||||||
|
#include <LIEF/ELF.hpp>
|
||||||
|
|
||||||
#include <libreborn/libreborn.h>
|
#include <libreborn/libreborn.h>
|
||||||
|
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
@ -16,121 +13,16 @@
|
|||||||
|
|
||||||
// Load Symbol From ELF File
|
// Load Symbol From ELF File
|
||||||
static void load_symbol(const char *source, const char *name, std::function<void(unsigned char *, uint32_t)> callback) {
|
static void load_symbol(const char *source, const char *name, std::function<void(unsigned char *, uint32_t)> callback) {
|
||||||
// File Data
|
static std::unique_ptr<LIEF::ELF::Binary> binary = NULL;
|
||||||
FILE *file_obj = NULL;
|
if (binary == NULL) {
|
||||||
unsigned char *file_map = NULL;
|
binary = LIEF::ELF::Parser::parse(source);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
const LIEF::ELF::Symbol *symbol = binary->get_dynamic_symbol(name);
|
||||||
end:
|
if (symbol != NULL) {
|
||||||
// Unmap And Close File
|
std::vector<uint8_t> data = binary->get_content_from_virtual_address(symbol->value(), symbol->size(), LIEF::Binary::VA_TYPES::VA);
|
||||||
if (file_map != NULL) {
|
callback(data.data(), data.size());
|
||||||
munmap(file_map, file_size);
|
} else {
|
||||||
}
|
WARN("Unable To Find Symbol: %s", name);
|
||||||
if (file_obj != NULL) {
|
|
||||||
fclose(file_obj);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user