2.3.1
minecraft-pi-reborn/pipeline/head This commit looks good
Details
minecraft-pi-reborn/pipeline/head This commit looks good
Details
parent
bdeb45eed2
commit
03312f44b6
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
@ -1,12 +1,12 @@
|
||||
project(libreborn)
|
||||
|
||||
add_library(reborn-headers INTERFACE)
|
||||
target_include_directories(reborn-headers INTERFACE include)
|
||||
add_library(reborn-util STATIC src/util/elf.c src/util/exec.c src/util/string.c src/util/util.c)
|
||||
target_include_directories(reborn-util PUBLIC include)
|
||||
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
add_library(reborn SHARED src/patch.c)
|
||||
target_link_libraries(reborn dl reborn-headers)
|
||||
target_compile_definitions(reborn PUBLIC -DREBORN_HAS_COMPILED_CODE)
|
||||
add_library(reborn-patch SHARED src/patch/patch.c)
|
||||
target_link_libraries(reborn-patch dl reborn-util)
|
||||
target_compile_definitions(reborn-patch PUBLIC -DREBORN_HAS_PATCH_CODE)
|
||||
# Install
|
||||
install(TARGETS reborn DESTINATION "${MCPI_LIB_DIR}")
|
||||
install(TARGETS reborn-patch DESTINATION "${MCPI_LIB_DIR}")
|
||||
endif()
|
||||
|
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#define GUI_TITLE "Minecraft: Pi Edition: Reborn"
|
@ -0,0 +1,53 @@
|
||||
#include <libreborn/elf.h>
|
||||
|
||||
// Find And Iterate Over All .text Sections In Current Binary
|
||||
void iterate_text_sections(text_section_callback_t callback, void *data) {
|
||||
// Load Main Binary
|
||||
FILE *file_obj = fopen(getenv("MCPI_EXECUTABLE_PATH"), "rb");
|
||||
|
||||
// Verify Binary
|
||||
if (!file_obj) {
|
||||
ERR("%s", "Unable To Open Current Binary");
|
||||
}
|
||||
|
||||
// Get File Size
|
||||
fseek(file_obj, 0L, SEEK_END);
|
||||
long int file_size = ftell(file_obj);
|
||||
fseek(file_obj, 0L, SEEK_SET);
|
||||
|
||||
// Map File To Pointer
|
||||
unsigned char *file_map = (unsigned char *) mmap(0, file_size, PROT_READ, MAP_PRIVATE, fileno(file_obj), 0);
|
||||
|
||||
// Parse ELF
|
||||
ElfW(Ehdr) *elf_header = (ElfW(Ehdr) *) file_map;
|
||||
ElfW(Shdr) *elf_section_headers = (ElfW(Shdr) *) (file_map + elf_header->e_shoff);
|
||||
int elf_section_header_count = elf_header->e_shnum;
|
||||
|
||||
// Locate Section Names
|
||||
ElfW(Shdr) elf_shstrtab = elf_section_headers[elf_header->e_shstrndx];
|
||||
unsigned char *elf_shstrtab_p = file_map + elf_shstrtab.sh_offset;
|
||||
|
||||
// Track .text Sections
|
||||
int text_sections = 0;
|
||||
|
||||
// Iterate Sections
|
||||
for (int i = 0; i < elf_section_header_count; ++i) {
|
||||
ElfW(Shdr) header = elf_section_headers[i];
|
||||
char *name = (char *) (elf_shstrtab_p + header.sh_name);
|
||||
// Check Section Type
|
||||
if (strcmp(name, ".text") == 0) {
|
||||
// .text Section
|
||||
(*callback)(header.sh_addr, header.sh_size, data);
|
||||
text_sections++;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure At Least .text Section Was Scanned
|
||||
if (text_sections < 1) {
|
||||
ERR("%s", "Unable To Find .text Sectons");
|
||||
}
|
||||
|
||||
// Unmap And Close File
|
||||
munmap(file_map, file_size);
|
||||
fclose(file_obj);
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
#include <libreborn/exec.h>
|
||||
|
||||
// Safe execvpe()
|
||||
__attribute__((noreturn)) void safe_execvpe(const char *const argv[], const char *const envp[]) {
|
||||
int ret = execvpe(argv[0], (char *const *) argv, (char *const *) envp);
|
||||
if (ret == -1) {
|
||||
ERR("Unable To Execute Program: %s: %s", argv[0], strerror(errno));
|
||||
} else {
|
||||
IMPOSSIBLE();
|
||||
}
|
||||
}
|
||||
|
||||
// Chop Off Last Component
|
||||
void chop_last_component(char **str) {
|
||||
size_t length = strlen(*str);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
size_t j = length - i - 1;
|
||||
if ((*str)[j] == '/') {
|
||||
(*str)[j] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Get Binary Directory (Remember To Free)
|
||||
char *get_binary_directory() {
|
||||
// Get Path To Current Executable
|
||||
char *exe = realpath("/proc/self/exe", NULL);
|
||||
ALLOC_CHECK(exe);
|
||||
|
||||
// Chop Off Last Component
|
||||
chop_last_component(&exe);
|
||||
|
||||
// Return
|
||||
return exe;
|
||||
}
|
||||
|
||||
// Safe execvpe() Relative To Binary
|
||||
__attribute__((noreturn)) void safe_execvpe_relative_to_binary(const char *const argv[], const char *const envp[]) {
|
||||
// Get Binary Directory
|
||||
char *binary_directory = get_binary_directory();
|
||||
// Create Full Path
|
||||
char *full_path = NULL;
|
||||
safe_asprintf(&full_path, "%s/%s", binary_directory, argv[0]);
|
||||
// Free Binary Directory
|
||||
free(binary_directory);
|
||||
|
||||
// Build New argv
|
||||
int argc;
|
||||
for (argc = 0; argv[argc] != NULL; argc++);
|
||||
const char *new_argv[argc + 1];
|
||||
for (int i = 1; i < argc; i++) {
|
||||
new_argv[i] = argv[i];
|
||||
}
|
||||
new_argv[0] = full_path;
|
||||
new_argv[argc] = NULL;
|
||||
// Run
|
||||
safe_execvpe(new_argv, envp);
|
||||
}
|
||||
|
||||
// Get MCPI Directory
|
||||
char *get_mcpi_directory() {
|
||||
return getenv("MCPI_DIRECTORY");
|
||||
}
|
||||
|
||||
// Run Command And Get Output
|
||||
char *run_command(const char *const command[], int *return_code) {
|
||||
// Store Output
|
||||
int output_pipe[2];
|
||||
safe_pipe2(output_pipe, 0);
|
||||
// Run
|
||||
pid_t ret = fork();
|
||||
if (ret == -1) {
|
||||
ERR("Unable To Run Command: %s", strerror(errno));
|
||||
} else if (ret == 0) {
|
||||
// Child Process
|
||||
|
||||
// Pipe stdout
|
||||
dup2(output_pipe[1], STDOUT_FILENO);
|
||||
close(output_pipe[0]);
|
||||
close(output_pipe[1]);
|
||||
|
||||
// Close stderr (But Not In Debug Mode)
|
||||
const char *is_debug = getenv("MCPI_DEBUG");
|
||||
if (is_debug == NULL || strlen(is_debug) < 1) {
|
||||
int null_fd = open("/dev/null", O_WRONLY);
|
||||
dup2(null_fd, STDERR_FILENO);
|
||||
close(null_fd);
|
||||
}
|
||||
|
||||
// Run
|
||||
safe_execvpe(command, (const char *const *) environ);
|
||||
} else {
|
||||
// Parent Process
|
||||
|
||||
// Read stdout
|
||||
close(output_pipe[1]);
|
||||
char *output = NULL;
|
||||
char c;
|
||||
int bytes_read = 0;
|
||||
while ((bytes_read = read(output_pipe[0], (void *) &c, 1)) > 0) {
|
||||
string_append(&output, "%c", c);
|
||||
}
|
||||
close(output_pipe[0]);
|
||||
|
||||
// Get Return Code
|
||||
int status;
|
||||
waitpid(ret, &status, 0);
|
||||
*return_code = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
|
||||
|
||||
// Return
|
||||
return output;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
#include <libreborn/string.h>
|
||||
|
||||
// Sanitize String
|
||||
#define MINIMUM_SAFE_CHARACTER 32
|
||||
#define MAXIMUM_SAFE_CHARACTER 126
|
||||
void sanitize_string(char **str, int max_length, unsigned int allow_newlines) {
|
||||
// Store Message Length
|
||||
int length = strlen(*str);
|
||||
// Truncate Message
|
||||
if (max_length != -1 && length > max_length) {
|
||||
(*str)[max_length] = '\0';
|
||||
length = max_length;
|
||||
}
|
||||
// Loop Through Message
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (allow_newlines && ((*str)[i] == '\n' || (*str)[i] == '\r')) {
|
||||
continue;
|
||||
}
|
||||
unsigned char c = (unsigned char) (*str)[i];
|
||||
if (c < MINIMUM_SAFE_CHARACTER || c > MAXIMUM_SAFE_CHARACTER) {
|
||||
// Replace Illegal Character
|
||||
(*str)[i] = '?';
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
#include <libreborn/util.h>
|
||||
|
||||
// Safe Version Of pipe()
|
||||
void safe_pipe2(int pipefd[2], int flags) {
|
||||
if (pipe2(pipefd, flags) != 0) {
|
||||
ERR("Unable To Create Pipe: %s", strerror(errno));
|
||||
}
|
||||
}
|
Loading…
Reference in new issue