From 425f5a28d22faa21d33aaa0539c402a6e7a6e526 Mon Sep 17 00:00:00 2001 From: chaoskagami Date: Tue, 20 Dec 2016 02:24:53 -0500 Subject: [PATCH] Big commit malloc(3) is now newlib's implementation instead of my shitty one. Turns out; after poking around the latest linker.ld in libctr9, all this time... It was a linker script issue. I. Hate. Everything. Miscellaneous changes also here: * f{whatever} -> cr{whatever} to avoid clashes with newlib (and hopefully facillitate replacement) * FIRM allocation size was made to be fixed at 0x100000 as a stopgap. Turns out that memory corruption was massive, and the only thing saving my ass before was the allocator being...dumb. --- Makefile.am | 2 +- include/common.h | 1 + include/patcher.h | 4 +- include/std/draw.h | 2 +- include/std/fs.h | 20 +-- source/arm11.c | 2 +- source/chainloader.c | 18 +-- source/config-backend-file.c | 42 ++--- source/firm/firm.c | 43 +++--- source/firm/firmlaunch.c | 4 +- source/firm/keys.c | 12 +- source/firm/util.c | 14 +- source/firm/version.c | 2 +- source/interpreter.c | 36 ++--- source/linker.ld | 287 +++++++++++++++++++++++++++++------ source/main.c | 12 +- source/menu.c | 10 +- source/patch/emunand.c | 10 +- source/patch/module.c | 12 +- source/patch/reboot.c | 22 +-- source/patch/svc.c | 8 +- source/patcher.c | 10 +- source/start.s | 4 +- source/std/draw.c | 56 +++---- source/std/fs.c | 40 ++--- 25 files changed, 443 insertions(+), 230 deletions(-) diff --git a/Makefile.am b/Makefile.am index aa492ac..658bd04 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ SUBDIRS = include host external source patch contrib ACLOCAL_AMFLAGS = -I m4 -source: include host external +source: include host external patch contrib external: include host diff --git a/include/common.h b/include/common.h index 9fa1ce2..1b2940b 100644 --- a/include/common.h +++ b/include/common.h @@ -2,6 +2,7 @@ #define __COMMON_H #include +#include #include diff --git a/include/patcher.h b/include/patcher.h index 456e95f..d13ab36 100644 --- a/include/patcher.h +++ b/include/patcher.h @@ -5,7 +5,7 @@ * * \return zero on success */ -int patch_firm_all(uint64_t tid, firm_h* firm, const char* module_path); +int patch_firm_all(uint64_t tid, firm_h** firm, const char* module_path); /* Generates patch cache for boot/loader for the current configuration. * @@ -15,6 +15,6 @@ int generate_patch_cache(void); int patch_svc_calls(firm_h* firm_loc); int patch_reboot(firm_h* firm_loc); -int patch_modules(firm_h* firm_loc, const char* module_path); +int patch_modules(firm_h** firm_loc, const char* module_path); #endif diff --git a/include/std/draw.h b/include/std/draw.h index 5ef14df..82fa6bc 100644 --- a/include/std/draw.h +++ b/include/std/draw.h @@ -125,7 +125,7 @@ void puts(void *buf, char *string); * * \param channel Handle to flush output on */ -void fflush(void *channel); +void crflush(void *channel); /* Moves the cursor/output location on a display device * diff --git a/include/std/fs.h b/include/std/fs.h index d2a933a..6f4162d 100644 --- a/include/std/fs.h +++ b/include/std/fs.h @@ -18,29 +18,29 @@ typedef struct #define SEEK_CUR 1 #define SEEK_END 2 -int fmount(void); +int crmount(void); -int fumount(void); +int crumount(void); void recurse_call(const char *name, void (*call_fun)(char*)); int rrmdir(const char *dir_path); -FILE *fopen(const char *filename, const char *mode); +FILE *cropen(const char *filename, const char *mode); -void fclose(FILE *fp); +void crclose(FILE *fp); -void fseek(FILE *fp, int64_t offset, int whence); +void crseek(FILE *fp, int64_t offset, int whence); -size_t ftell(FILE *fp); +size_t crtell(FILE *fp); -int feof(FILE *fp); +int creof(FILE *fp); -size_t fsize(FILE *fp); +size_t crsize(FILE *fp); -size_t fwrite(const void *buffer, size_t elementSize, size_t elementCnt, FILE *fp); +size_t crwrite(const void *buffer, size_t elementSize, size_t elementCnt, FILE *fp); -size_t fread(void *buffer, size_t elementSize, size_t elementCnt, FILE *fp); +size_t crread(void *buffer, size_t elementSize, size_t elementCnt, FILE *fp); size_t write_file(void *data, const char *path, size_t size); diff --git a/source/arm11.c b/source/arm11.c index f3441ba..bb7148d 100644 --- a/source/arm11.c +++ b/source/arm11.c @@ -168,7 +168,7 @@ void screen_mode(uint32_t mode) { // Look ma, dynamically allocating the CakeHax struct! (joking) // We literally just discard the previous state - for sanity's sake. // On chainload, it is needed to copy the framebuffer struct. - framebuffers = malloc(sizeof(struct framebuffers)); + framebuffers = memalign(16, sizeof(struct framebuffers)); } void __attribute__((naked)) ARM11(void) { diff --git a/source/chainloader.c b/source/chainloader.c index 20da0fb..15ac103 100644 --- a/source/chainloader.c +++ b/source/chainloader.c @@ -25,27 +25,27 @@ void chainload_file(void* data) uint32_t size = 0, b_size = 0; uint8_t* chain_data; - FILE* f = fopen(code_file, "r"); + FILE* f = cropen(code_file, "r"); if (!f) { // File missing. panic("Missing chainloader.\n"); } - b_size = fsize(f); - fread(bootstrap, 1, b_size, f); - fclose(f); + b_size = crsize(f); + crread(bootstrap, 1, b_size, f); + crclose(f); chain_data = bootstrap + b_size; - f = fopen(chain_file, "r"); + f = cropen(chain_file, "r"); if (!f) { // File missing. panic("Missing program to chainload?\n"); } - size = fsize(f); - fread(chain_data, 1, size, f); - fclose(f); + size = crsize(f); + crread(chain_data, 1, size, f); + crclose(f); fprintf(stderr, "Setting argc, argv...\n"); @@ -135,7 +135,7 @@ list_chain_build(const char *name) void chainload_menu() { if (chains == NULL) { - chains = malloc(sizeof(struct options_s) * 100); + chains = memalign(16, sizeof(struct options_s) * 100); list_chain_build(PATH_CHAINS); } diff --git a/source/config-backend-file.c b/source/config-backend-file.c index 1d72774..254aa20 100644 --- a/source/config-backend-file.c +++ b/source/config-backend-file.c @@ -20,11 +20,11 @@ regenerate_config(void) config->options[OPTION_ACCENT_COLOR] = 2; config->options[OPTION_BRIGHTNESS] = 3; - if (!(conf_handle = fopen(config_file_path, "w"))) + if (!(conf_handle = cropen(config_file_path, "w"))) poweroff(); - fwrite(config, 1, sizeof(struct config_file) + PATCH_MAX, conf_handle); - fclose(conf_handle); + crwrite(config, 1, sizeof(struct config_file) + PATCH_MAX, conf_handle); + crclose(conf_handle); } void @@ -82,21 +82,21 @@ load_config(void) mk_structure(); // Make directory structure if needed. if (!config_file_path) { - config_file_path = malloc(256); // MAX_PATH + config_file_path = memalign(16, 256); // MAX_PATH memset(config_file_path, 0, 256); sdmmc_get_cid(1, cid); - FILE* f = fopen(SYSCONFDIR "/current-nand-cid", "r"); + FILE* f = cropen(SYSCONFDIR "/current-nand-cid", "r"); if (!f) { // Nonexistent. Write it. - f = fopen(SYSCONFDIR "/current-nand-cid", "w"); - fwrite(cid, 1, 4, f); - fclose(f); - f = fopen(SYSCONFDIR "/current-nand-cid", "r"); + f = cropen(SYSCONFDIR "/current-nand-cid", "w"); + crwrite(cid, 1, 4, f); + crclose(f); + f = cropen(SYSCONFDIR "/current-nand-cid", "r"); } - fread(&cid[1], 1, 4, f); + crread(&cid[1], 1, 4, f); // If our console's CID doesn't match what was read, we need to regenerate caches immediately when we can. if (cid[0] != cid[1]) { @@ -113,19 +113,19 @@ load_config(void) cid_cp >>= 4; } - config = (struct config_file*)malloc(sizeof(struct config_file) + PATCH_MAX); + config = (struct config_file*)memalign(16, sizeof(struct config_file) + PATCH_MAX); memset(config, 0, sizeof(struct config_file) + PATCH_MAX); enable_list = (uint8_t*)config + sizeof(struct config_file); - fclose(f); + crclose(f); } // Zero on success. - if (!(conf_handle = fopen(config_file_path, "r"))) { + if (!(conf_handle = cropen(config_file_path, "r"))) { regenerate_config(); } else { - fread(config, 1, sizeof(struct config_file) + PATCH_MAX, conf_handle); + crread(config, 1, sizeof(struct config_file) + PATCH_MAX, conf_handle); - fclose(conf_handle); + crclose(conf_handle); if (memcmp(&(config->magic), CONFIG_MAGIC, 4)) { f_unlink(config_file_path); @@ -149,19 +149,19 @@ void save_config(void) { if (changed_consoles) { - FILE* f = fopen(SYSCONFDIR "/current-nand-cid", "w"); - fwrite(cid, 1, 4, f); - fclose(f); + FILE* f = cropen(SYSCONFDIR "/current-nand-cid", "w"); + crwrite(cid, 1, 4, f); + crclose(f); } f_unlink(config_file_path); - if (!(conf_handle = fopen(config_file_path, "w"))) + if (!(conf_handle = cropen(config_file_path, "w"))) while(1); - fwrite(config, 1, sizeof(struct config_file) + PATCH_MAX, conf_handle); + crwrite(config, 1, sizeof(struct config_file) + PATCH_MAX, conf_handle); - fclose(conf_handle); + crclose(conf_handle); } void change_opt(void* val) { diff --git a/source/firm/firm.c b/source/firm/firm.c index 5dd1e7c..f0b7b5b 100644 --- a/source/firm/firm.c +++ b/source/firm/firm.c @@ -20,32 +20,33 @@ load_firm(const char *path, size_t *size_out) int save_dec = 0; char* decpath = strdupcat(path, ".dec"); - firm_file = fopen(decpath, "r"); + firm_file = cropen(decpath, "r"); if (!firm_file) { - firm_file = fopen(path, "r"); + firm_file = cropen(path, "r"); if (!firm_file) { return NULL; } } - size = fsize(firm_file); + size = crsize(firm_file); if (size_out) *size_out = size; - mem = malloc(size); + // FIXME - Temp fix; allocating way more memory than needed to prevent memory corruption + mem = memalign(16, 0x1000000); firm_h *firm = (firm_h*)mem; - fread(mem, 1, size, firm_file); + crread(mem, 1, size, firm_file); - fclose(firm_file); + crclose(firm_file); if (memcmp(firm->magic, "FIRM", 4)) { char *key_path = strdupcat(path, ".key"); // Attempt to open keyfile. - uint8_t* firmkey = malloc(16); + uint8_t* firmkey = memalign(16, 16); if (read_file(firmkey, key_path, 16) != 16) { // Keyfile couldn't be opened, try the cetk. free(firmkey); @@ -56,9 +57,9 @@ load_firm(const char *path, size_t *size_out) free(cetk_path); // Save firmkey. - FILE* keyfile = fopen(key_path, "w"); - fwrite(firmkey, 1, 16, keyfile); - fclose(keyfile); + FILE* keyfile = cropen(key_path, "w"); + crwrite(firmkey, 1, 16, keyfile); + crclose(keyfile); } free(key_path); @@ -101,9 +102,9 @@ load_firm(const char *path, size_t *size_out) // Save decrypted FIRM. if (save_dec == 1) { - firm_file = fopen(decpath, "w"); - fwrite(firm, 1, size, firm_file); - fclose(firm_file); + firm_file = cropen(decpath, "w"); + crwrite(firm, 1, size, firm_file); + crclose(firm_file); } free(decpath); @@ -144,14 +145,14 @@ prepatch_firm(const char* firm_path, const char* prepatch_path, const char* modu free(sig); - if (patch_firm_all(tid, firm, module_path)) { + if (patch_firm_all(tid, &firm, module_path)) { free(firm); return 1; } - FILE* f = fopen(prepatch_path, "w"); - fwrite(firm, 1, size, f); - fclose(f); + FILE* f = cropen(prepatch_path, "w"); + crwrite(firm, 1, size, f); + crclose(f); free(firm); @@ -178,14 +179,14 @@ boot_firm(const char* firm_path, const char* prepatch_path, const char* module_p free(sig); - if (patch_firm_all(tid, firm, module_path)) { + if (patch_firm_all(tid, &firm, module_path)) { free(firm); return 1; } - FILE* f = fopen(prepatch_path, "w"); - fwrite(firm, 1, size, f); - fclose(f); + FILE* f = cropen(prepatch_path, "w"); + crwrite(firm, 1, size, f); + crclose(f); firmlaunch(firm); // <- should NOT return if all is well diff --git a/source/firm/firmlaunch.c b/source/firm/firmlaunch.c index f115ffd..b84f269 100644 --- a/source/firm/firmlaunch.c +++ b/source/firm/firmlaunch.c @@ -19,9 +19,9 @@ void firmlaunch(firm_h* firm) { free(firm); // Really, no point in this. Why not, though. - fflush(stderr); // Flush logs if need be before unmount. + crflush(stderr); // Flush logs if need be before unmount. - fumount(); // Unmount SD. + crumount(); // Unmount SD. deinitScreens(); // Turn off display diff --git a/source/firm/keys.c b/source/firm/keys.c index 44211b6..2b409ed 100644 --- a/source/firm/keys.c +++ b/source/firm/keys.c @@ -14,19 +14,19 @@ int set_N11_K9L(uint32_t index) { if (ss_keyn[0][0] == 0) { ss_keyn[0][0] = 1; - FILE* key = fopen(PATH_SLOT0X11KEY95, "r"); + FILE* key = cropen(PATH_SLOT0X11KEY95, "r"); if (key) { - fread(ss_keyn[0], 1, AES_BLOCK_SIZE, key); - fclose(key); + crread(ss_keyn[0], 1, AES_BLOCK_SIZE, key); + crclose(key); } } if (ss_keyn[1][0] == 0) { ss_keyn[1][0] = 1; - FILE* key = fopen(PATH_SLOT0X11KEY96, "r"); + FILE* key = cropen(PATH_SLOT0X11KEY96, "r"); if (key) { - fread(ss_keyn[1], 1, AES_BLOCK_SIZE, key); - fclose(key); + crread(ss_keyn[1], 1, AES_BLOCK_SIZE, key); + crclose(key); } } diff --git a/source/firm/util.c b/source/firm/util.c index 0b9d1d4..11fc78c 100644 --- a/source/firm/util.c +++ b/source/firm/util.c @@ -52,14 +52,14 @@ int patch_entry(firm_h *firm, enum firm_type type) { uint8_t* get_titlekey(char *cetk_filename) { - FILE* f = fopen(cetk_filename, "r"); - size_t size = fsize(f); + FILE* f = cropen(cetk_filename, "r"); + size_t size = crsize(f); - uint8_t* cetk = malloc(size); + uint8_t* cetk = memalign(16, size); - fread(cetk, 1, size, f); + crread(cetk, 1, size, f); - fclose(f); + crclose(f); uint8_t iv[AES_BLOCK_SIZE] = { 0 }; uint32_t sigtype = __builtin_bswap32(*(const uint32_t *)cetk); @@ -73,7 +73,7 @@ get_titlekey(char *cetk_filename) set_Y3D_cetk(1); - uint8_t *key = malloc(AES_BLOCK_SIZE); + uint8_t *key = memalign(16, AES_BLOCK_SIZE); memcpy(iv, ticket->titleID, sizeof(ticket->titleID)); memcpy(key, ticket->titleKey, sizeof(ticket->titleKey)); @@ -149,7 +149,7 @@ extract_firm_from_ncch(ncch_h *ncch, uint8_t *titlekey, size_t size) return NULL; } - firm_h* dest = malloc(size); + firm_h* dest = memalign(16, size); memcpy(dest, firm, size); diff --git a/source/firm/version.c b/source/firm/version.c index 1762448..f7c0bc0 100644 --- a/source/firm/version.c +++ b/source/firm/version.c @@ -8,7 +8,7 @@ get_firm_info(firm_h *firm) { // What follows is a heuristic to detect the firmware's properties. Checks are as follows: - struct firm_signature *signature = (struct firm_signature*)malloc(sizeof(struct firm_signature)); + struct firm_signature *signature = (struct firm_signature*)memalign(16, sizeof(struct firm_signature)); signature->type = type_native; signature->k9l = 0; diff --git a/source/interpreter.c b/source/interpreter.c index 82dda65..2e2fd64 100644 --- a/source/interpreter.c +++ b/source/interpreter.c @@ -441,11 +441,11 @@ exec_bytecode(uint8_t *bytecode, uint32_t len, uint16_t ver, int debug) (void)fname; // NYI #else - FILE* f = fopen(fname, "r"); - fread(current_mode->memory + offset, 1, fsize(f), f); - offset += fsize(f); + FILE* f = cropen(fname, "r"); + crread(current_mode->memory + offset, 1, crsize(f), f); + offset += crsize(f); code += strlen(fname); - fclose(f); + crclose(f); #endif break; default: @@ -601,18 +601,18 @@ execb(uint64_t tid, firm_h* firm_patch) // Read patch to scrap memory. - FILE *f = fopen(cache_path, "r"); + FILE *f = cropen(cache_path, "r"); if (!f) { // File wasn't found. The user didn't enable anything. return 0; } - patch_len = fsize(f); + patch_len = crsize(f); - uint8_t* patch_mem = malloc(patch_len); + uint8_t* patch_mem = memalign(16, patch_len); - fread(patch_mem, 1, patch_len, f); - fclose(f); + crread(patch_mem, 1, patch_len, f); + crclose(f); #endif int debug = 0; @@ -641,18 +641,18 @@ int cache_patch(const char *filename) { uint8_t *patch_mem; // Read patch to scrap memory. - FILE *f = fopen(filename, "r"); + FILE *f = cropen(filename, "r"); if (!f) { // File wasn't found. The user didn't enable anything. return 0; } - uint32_t len = fsize(f); + uint32_t len = crsize(f); uint8_t* patch_loc = malloc(len); - fread(patch_loc, 1, len, f); - fclose(f); + crread(patch_loc, 1, len, f); + crclose(f); patch = (struct system_patch*)patch_loc; @@ -692,11 +692,11 @@ int cache_patch(const char *filename) { char reset = 0xFF; - FILE *cache = fopen(cache_path, "w"); - fseek(cache, 0, SEEK_END); - fwrite(patch_mem, 1, patch_len, cache); - fwrite(&reset, 1, 1, cache); - fclose(cache); + FILE *cache = cropen(cache_path, "w"); + crseek(cache, 0, SEEK_END); + crwrite(patch_mem, 1, patch_len, cache); + crwrite(&reset, 1, 1, cache); + crclose(cache); // Add to cache. } } diff --git a/source/linker.ld b/source/linker.ld index e87c23a..904e932 100644 --- a/source/linker.ld +++ b/source/linker.ld @@ -1,52 +1,253 @@ +/* Script for -z combreloc: combine and sort reloc sections */ +/* Copyright (C) 2014 Free Software Foundation, Inc. + Copying and distribution of this script, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. */ +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", + "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(_start) +/* SEARCH_DIR("/opt/devkitpro/devkitARM/arm-none-eabi/lib"); */ SECTIONS { - . = 0x23F00000; - - .text.start : { - *(.text.start) + /* Read-only sections, merged into text segment: */ + /* Changed default address to 0x23F00000 */ + PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x23F00000)); . = SEGMENT_START("text-segment", 0x23F00000); + .interp : { *(.interp) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro .rel.data.rel.ro.* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + PROVIDE_HIDDEN (__rel_iplt_start = .); + *(.rel.iplt) + PROVIDE_HIDDEN (__rel_iplt_end = .); } - - . = ALIGN(4); - - .text : { - *(.text) - } - - . = ALIGN(4); - - .data : { - *(.data) + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + PROVIDE_HIDDEN (__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN (__rela_iplt_end = .); } - - . = ALIGN(4); - - .rodata : { - *(.rodata) + .rel.plt : + { + *(.rel.plt) } - - . = ALIGN(4); - - .rel : { - *(.rel) + .rela.plt : + { + *(.rela.plt) } - - . = ALIGN(4); - - .symtab : { - *(.symtab) - } - - . = ALIGN(4); - - .bss : { - __bss_start = .; - *(.bss COMMON) - } - __bss_end = .; - - . = ALIGN(4); - - __end__ = 0x24000000; + /* Make sure the start.o entry is at the beginning since that's the default alh entry */ + arm9loaderhax_entry : + { + KEEP (*(.text.start)) + } + arm9loaderhax_screeninit (INFO): + { + KEEP (*(screeninit)) + } + .init : + { + KEEP (*(SORT_NONE(.init))) + } + .plt : { *(.plt) } + .iplt : { *(.iplt) } + .text : + { + *(.text.unlikely .text.*_unlikely .text.unlikely.*) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub EXCLUDE_FILE (start.o) .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx) + } + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + PROVIDE_HIDDEN (__exidx_end = .); + .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table + .gcc_except_table.*) } + /* These sections are generated by the Sun/Oracle C++ compiler. */ + .exception_ranges : ONLY_IF_RO { *(.exception_ranges + .exception_ranges*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array )) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array )) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + .data : + { + __data_start = . ; + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + . = .; + __bss_start = .; + __bss_start__ = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + _bss_end__ = . ; __bss_end__ = . ; + . = ALIGN(32 / 8); + . = SEGMENT_START("ldata-segment", .); + . = ALIGN(32 / 8); + __end__ = . ; + _end = .; PROVIDE (end = .); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF Extension. */ + .debug_macro 0 : { *(.debug_macro) } + .stack 0x27F00000 : + { + _stack = .; + *(.stack) + } + .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) } + .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } } + diff --git a/source/main.c b/source/main.c index f7a363b..9dfe557 100644 --- a/source/main.c +++ b/source/main.c @@ -24,7 +24,7 @@ main(int argc, char** argv) std_init(); - if (fmount()) + if (crmount()) poweroff(); // Failed to mount SD. Bomb out. load_config(); // Load configuration. @@ -75,6 +75,16 @@ main(int argc, char** argv) wait(); } + if (get_opt_u32(OPTION_OVERLY_VERBOSE) && !get_opt_u32(OPTION_SILENCE)) { + struct mallinfo mal = mallinfo(); + fprintf(stderr, "arena: %u\n" + "ordblks: %u\n" + "uordblks: %u\n" + "fordblks: %u\n", + mal.arena, mal.ordblks, mal.uordblks, mal.fordblks); + wait(); + } + boot_firm(config->firm[0], PATH_NATIVE_P, PATH_MODULE_NATIVE); fprintf(stderr, "Firmlaunch failed, returning to menu\n"); diff --git a/source/menu.c b/source/menu.c index 659e2b0..1a7d127 100644 --- a/source/menu.c +++ b/source/menu.c @@ -244,9 +244,9 @@ void patch_func(char* fpath) { void reset() { - fflush(stderr); + crflush(stderr); - fumount(); // Unmount SD. + crumount(); // Unmount SD. // Reboot. fprintf(BOTTOM_SCREEN, "Rebooting system...\n"); @@ -257,9 +257,9 @@ reset() void poweroff() { - fflush(stderr); + crflush(stderr); - fumount(); // Unmount SD. + crumount(); // Unmount SD. // Power off fprintf(BOTTOM_SCREEN, "Powering off system...\n"); @@ -273,7 +273,7 @@ reset_patch_menu(void) current_menu_index_patches = 0; if (!patches) - patches = malloc(sizeof(struct options_s) * 258); // FIXME - hard limit. Implement realloc. + patches = memalign(16, sizeof(struct options_s) * 258); // FIXME - hard limit. Implement realloc. patches[0].name = "Patches"; patches[0].desc = ""; diff --git a/source/patch/emunand.c b/source/patch/emunand.c index b3e5852..abb6471 100644 --- a/source/patch/emunand.c +++ b/source/patch/emunand.c @@ -10,7 +10,7 @@ verify_emunand(uint32_t index, uint32_t *off, uint32_t *head) { uint32_t nandSize = getMMCDevice(0)->total_size; - uint8_t *emunand_temp = (uint8_t*)malloc(2048); + uint8_t *emunand_temp = (uint8_t*)memalign(16, 2048); uint32_t offset; if (nandSize > 0x200000) @@ -130,13 +130,13 @@ patch_emunand(firm_h* firm_loc, uint32_t index) if (!emuCodeOffset) return 1; - FILE *f = fopen(PATH_EMUNAND_CODE, "r"); + FILE *f = cropen(PATH_EMUNAND_CODE, "r"); if (!f) return 1; - uint32_t emunand_size = fsize(f); - fread(emuCodeOffset, 1, emunand_size, f); - fclose(f); + uint32_t emunand_size = crsize(f); + crread(emuCodeOffset, 1, emunand_size, f); + crclose(f); uint32_t branchOffset = (uintptr_t)emuCodeOffset - ((uintptr_t)firm_loc + firm_loc->section[2].offset - firm_loc->section[2].address); diff --git a/source/patch/module.c b/source/patch/module.c index d148e51..9fce54e 100644 --- a/source/patch/module.c +++ b/source/patch/module.c @@ -15,16 +15,16 @@ inject_module(char* fpath) return; // TODO - load other module cxis here - FILE *f = fopen(fpath, "r"); + FILE *f = cropen(fpath, "r"); if (!f) { fprintf(stderr, "Module: %s not found\n", fpath); return; } - size_t size = fsize(f); + size_t size = crsize(f); uint8_t* temp = malloc(size); - fread(temp, 1, size, f); - fclose(f); + crread(temp, 1, size, f); + crclose(f); int section_index = 0; firm_section_h *sysmodule_section = &firm_modules->section[0]; @@ -87,9 +87,9 @@ end_inj: } int -patch_modules(firm_h* firm_loc, const char* module_path) +patch_modules(firm_h** firm_loc, const char* module_path) { - firm_modules = firm_loc; + firm_modules = *firm_loc; recurse_call(module_path, inject_module); return 0; diff --git a/source/patch/reboot.c b/source/patch/reboot.c index 80c557b..c5e354b 100644 --- a/source/patch/reboot.c +++ b/source/patch/reboot.c @@ -35,25 +35,25 @@ patch_reboot(firm_h* firm_loc) // Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1 uint32_t fOpenOffset = (uint32_t)(off + 9 - (-((*(uint32_t *)off & 0x00FFFFFF) << 2) & (0xFFFFFF << 2)) - (uint32_t)process9Offset + process9MemAddr); - fprintf(stderr, "reboot: fopen @ %lx\n", fOpenOffset); + fprintf(stderr, "reboot: cropen @ %lx\n", fOpenOffset); wait(); // Copy firmlaunch code - FILE *f = fopen(PATH_REBOOT_HOOK, "r"); + FILE *f = cropen(PATH_REBOOT_HOOK, "r"); if (!f) panic("reboot: hook not found on SD\n"); - uint32_t size = fsize(f); - fread(off, 1, size, f); - fclose(f); + uint32_t size = crsize(f); + crread(off, 1, size, f); + crclose(f); // Put the fOpen offset in the right location - uint32_t *pos_fopen = (uint32_t *)memfind(off, size, "open", 4); - if (!pos_fopen) + uint32_t *pos_cropen = (uint32_t *)memfind(off, size, "open", 4); + if (!pos_cropen) return 1; - *pos_fopen = fOpenOffset; + *pos_cropen = fOpenOffset; uint32_t *pos_native = (uint32_t *)memfind(off, size, "NATF", 4); uint32_t *pos_twl = (uint32_t *)memfind(off, size, "TWLF", 4); @@ -102,12 +102,12 @@ patch_reboot(firm_h* firm_loc) fprintf(stderr, "reboot: rebc @ %lx\n", (uint32_t)pos_rebc); - f = fopen(PATH_REBOOT_CODE, "r"); + f = cropen(PATH_REBOOT_CODE, "r"); if (!f) return 1; - fread(mem, 1, fsize(f), f); - fclose(f); + crread(mem, 1, crsize(f), f); + crclose(f); return 0; } diff --git a/source/patch/svc.c b/source/patch/svc.c index 48f13f5..466869b 100644 --- a/source/patch/svc.c +++ b/source/patch/svc.c @@ -31,15 +31,15 @@ patch_svc_calls(firm_h* firm_loc) if (!svcTable[0x7B]) { fprintf(stderr, "svc: 0x7B (backdoor) missing.\n"); - FILE *data = fopen(PATH_BACKDOOR, "r"); - uint32_t size = fsize(data); + FILE *data = cropen(PATH_BACKDOOR, "r"); + uint32_t size = crsize(data); fprintf(stderr, "Svc: backdoor is %lu bytes\n", size); fprintf(stderr, "Svc: Read code to %lx\n", (uint32_t)svc_tab_open); - fread(svc_tab_open, 1, size, data); + crread(svc_tab_open, 1, size, data); - fclose(data); + crclose(data); // memcpy(svc_tab_open, svcbackdoor, sizeof(svcbackdoor)); svcTable[0x7B] = 0xFFFF0000 + (uint32_t)((uint8_t *)svc_tab_open - (uint8_t *)exceptionsPage); diff --git a/source/patcher.c b/source/patcher.c index cee87cd..a91d345 100644 --- a/source/patcher.c +++ b/source/patcher.c @@ -46,26 +46,26 @@ generate_patch_cache(void) } int -patch_firm_all(uint64_t tid, firm_h* firm, const char* module_path) +patch_firm_all(uint64_t tid, firm_h** firm, const char* module_path) { int exit = 0; - execb(tid, firm); + execb(tid, *firm); switch (tid) { case 0x0004013800000002LLu: // NFIRM case 0x0004013820000002LLu: // Hook firmlaunch? if (get_opt_u32(OPTION_REBOOT)) - patch_reboot(firm); + patch_reboot(*firm); // Use EmuNAND? if (get_opt_u32(OPTION_EMUNAND)) - patch_emunand(firm, get_opt_u32(OPTION_EMUNAND_INDEX)); + patch_emunand(*firm, get_opt_u32(OPTION_EMUNAND_INDEX)); // Inject services? if (get_opt_u32(OPTION_SVCS)) - if (patch_svc_calls(firm)) + if (patch_svc_calls(*firm)) exit |= 2; break; case 0x0004013800000102LLu: diff --git a/source/start.s b/source/start.s index fd286a3..a379eca 100644 --- a/source/start.s +++ b/source/start.s @@ -133,10 +133,10 @@ setup_stacks_offset: .word setup_stacks-. __bss_start_offset: -.word __bss_start-. +.word __bss_start__-. __bss_end_offset: -.word __bss_end-. +.word __bss_end__-. clear_bss_offset: .word clear_bss-. diff --git a/source/std/draw.c b/source/std/draw.c index 84a8ebf..2294e0d 100644 --- a/source/std/draw.c +++ b/source/std/draw.c @@ -108,11 +108,11 @@ void screenshot(void) { f_unlink(PATH_TEMP "/screenshot.ppm"); // Open the screenshot blob used by hbmenu et al - FILE* f = fopen(PATH_TEMP "/screenshot.ppm", "w"); + FILE* f = cropen(PATH_TEMP "/screenshot.ppm", "w"); if (!f) return; - fwrite("P6 400 480 255 ", 1, 15, f); + crwrite("P6 400 480 255 ", 1, 15, f); for(int y = 0; y < 240; y++) { for(int x = 0; x < 400; x++) { @@ -120,9 +120,9 @@ void screenshot(void) { int yDisplacement = ((240 - y - 1) * SCREEN_DEPTH); int pos = xDisplacement + yDisplacement; - fwrite(& framebuffers->top_left[pos + 3], 1, 1, f); - fwrite(& framebuffers->top_left[pos + 2], 1, 1, f); - fwrite(& framebuffers->top_left[pos + 1], 1, 1, f); + crwrite(& framebuffers->top_left[pos + 3], 1, 1, f); + crwrite(& framebuffers->top_left[pos + 2], 1, 1, f); + crwrite(& framebuffers->top_left[pos + 1], 1, 1, f); } } @@ -130,23 +130,23 @@ void screenshot(void) { for(int y = 0; y < 240; y++) { for (int i = 0; i < 40 * 3; i++) - fwrite(& zero, 1, 1, f); + crwrite(& zero, 1, 1, f); for (int x = 0; x < 320; x++) { int xDisplacement = (x * SCREEN_DEPTH * 240); int yDisplacement = ((240 - y - 1) * SCREEN_DEPTH); int pos = xDisplacement + yDisplacement; - fwrite(& framebuffers->bottom[pos + 3], 1, 1, f); - fwrite(& framebuffers->bottom[pos + 2], 1, 1, f); - fwrite(& framebuffers->bottom[pos + 1], 1, 1, f); + crwrite(& framebuffers->bottom[pos + 3], 1, 1, f); + crwrite(& framebuffers->bottom[pos + 2], 1, 1, f); + crwrite(& framebuffers->bottom[pos + 1], 1, 1, f); } for (int i = 0; i < 40 * 3; i++) - fwrite(& zero, 1, 1, f); + crwrite(& zero, 1, 1, f); } - fclose(f); + crclose(f); fprintf(stderr, "Screenshot: %s\n", PATH_TEMP "/screenshot.ppm"); } @@ -157,39 +157,39 @@ void clear_bg(void) { } void load_bg_top(const char* fname_top) { - FILE* f = fopen(fname_top, "r"); + FILE* f = cropen(fname_top, "r"); if (!f) return; for (int i=1; i < TOP_SIZE; i += 4) { - fread(&top_bg[i], 1, 3, f); + crread(&top_bg[i], 1, 3, f); } - fclose(f); + crclose(f); } void load_bg_bottom(const char* fname_bottom) { - FILE* f = fopen(fname_bottom, "r"); + FILE* f = cropen(fname_bottom, "r"); if (!f) return; for (int i=1; i < BOTTOM_SIZE; i += 4) { - fread(&bottom_bg[i], 1, 3, f); + crread(&bottom_bg[i], 1, 3, f); } - fclose(f); + crclose(f); } void set_font(const char* filename) { // TODO - Unicode support. Right now, we only load 32 - FILE* f = fopen(filename, "r"); + FILE* f = cropen(filename, "r"); if (!f) panic("Failed to load font file!\n"); unsigned int new_w, new_h; - fread(&new_w, 1, 4, f); - fread(&new_h, 1, 4, f); + crread(&new_w, 1, 4, f); + crread(&new_h, 1, 4, f); if (new_w == 0 || new_h == 0) { panic("Invalid font file: w/h is 0 - not loaded\n"); @@ -199,9 +199,9 @@ void set_font(const char* filename) { font_data = malloc(c_font_w * new_h * (256 - ' ')); - fread(font_data, 1, c_font_w * new_h * (256 - ' '), f); // Skip non-printing chars. + crread(font_data, 1, c_font_w * new_h * (256 - ' '), f); // Skip non-printing chars. - fclose(f); + crclose(f); font_w = new_w; font_h = new_h; @@ -223,12 +223,12 @@ void dump_log(unsigned int force) { if (log_size == 0) return; - FILE *f = fopen(PATH_BOOTLOG, "w"); - fseek(f, 0, SEEK_END); + FILE *f = cropen(PATH_BOOTLOG, "w"); + crseek(f, 0, SEEK_END); - fwrite(log_buffer, 1, log_size, f); + crwrite(log_buffer, 1, log_size, f); - fclose(f); + crclose(f); log_size = 0; } @@ -522,7 +522,7 @@ putc(void *buf, int c) } } else { // FILE*, not stdin or stdout. - fwrite(&c, 1, 1, (FILE *)buf); + crwrite(&c, 1, 1, (FILE *)buf); } } @@ -621,7 +621,7 @@ put_int(void *channel, int n, int length) } void -fflush(void *channel) +crflush(void *channel) { if (channel == BOTTOM_SCREEN) { dump_log(1); diff --git a/source/std/fs.c b/source/std/fs.c index 37055d3..3094c7a 100644 --- a/source/std/fs.c +++ b/source/std/fs.c @@ -64,7 +64,7 @@ rrmdir(const char *name) } int -fmount(void) +crmount(void) { if(!set_up_fs && ctr_fatfs_initialize(&nand_io, NULL, NULL, &sd_io)) return 1; @@ -81,7 +81,7 @@ fmount(void) } int -fumount(void) +crumount(void) { if (f_mount(NULL, "SD:", 1)) return 1; @@ -92,7 +92,7 @@ fumount(void) } FILE * -fopen(const char *filename, const char *mode) +cropen(const char *filename, const char *mode) { if (mode[0] != 'r' && mode[0] != 'w' && mode[0] != 'a') return NULL; // Mode not valid. @@ -112,7 +112,7 @@ fopen(const char *filename, const char *mode) } void -fclose(FILE *fp) +crclose(FILE *fp) { if (fp == NULL || !fp->is_open) return; @@ -125,7 +125,7 @@ fclose(FILE *fp) } void -fseek(FILE *fp, int64_t offset, int whence) +crseek(FILE *fp, int64_t offset, int whence) { if (fp == NULL || !fp->is_open) return; @@ -136,10 +136,10 @@ fseek(FILE *fp, int64_t offset, int whence) fixed_offset = 0; break; case SEEK_CUR: - fixed_offset = ftell(fp); + fixed_offset = crtell(fp); break; case SEEK_END: - fixed_offset = fsize(fp); + fixed_offset = crsize(fp); break; default: return; @@ -149,7 +149,7 @@ fseek(FILE *fp, int64_t offset, int whence) } size_t -ftell(FILE *fp) +crtell(FILE *fp) { if (fp == NULL || !fp->is_open) return 0; @@ -158,7 +158,7 @@ ftell(FILE *fp) } int -feof(FILE *fp) +creof(FILE *fp) { if (fp == NULL || !fp->is_open) return 0; @@ -167,7 +167,7 @@ feof(FILE *fp) } size_t -fsize(FILE *fp) +crsize(FILE *fp) { if (fp == NULL || !fp->is_open) return 0; @@ -176,7 +176,7 @@ fsize(FILE *fp) } size_t -fwrite(const void *buffer, size_t elementSize, size_t elementCnt, FILE *fp) +crwrite(const void *buffer, size_t elementSize, size_t elementCnt, FILE *fp) { if (fp == NULL || !fp->is_open) return 0; @@ -190,7 +190,7 @@ fwrite(const void *buffer, size_t elementSize, size_t elementCnt, FILE *fp) } size_t -fread(void *buffer, size_t elementSize, size_t elementCnt, FILE *fp) +crread(void *buffer, size_t elementSize, size_t elementCnt, FILE *fp) { if (!fp->is_open) return 0; @@ -207,19 +207,19 @@ fread(void *buffer, size_t elementSize, size_t elementCnt, FILE *fp) size_t write_file(void *data, const char *path, size_t size) { - FILE *temp = fopen(path, "w"); + FILE *temp = cropen(path, "w"); if (!temp) return 0; if (!temp->is_open) { - fclose(temp); + crclose(temp); return 0; } - size_t wrote = fwrite(data, 1, size, temp); + size_t wrote = crwrite(data, 1, size, temp); - fclose(temp); + crclose(temp); return wrote; } @@ -227,19 +227,19 @@ write_file(void *data, const char *path, size_t size) size_t read_file(void *data, const char *path, size_t size) { - FILE *temp = fopen(path, "r"); + FILE *temp = cropen(path, "r"); if (!temp) return 0; if (!temp->is_open) { - fclose(temp); + crclose(temp); return 0; } - size_t read = fread(data, 1, size, temp); + size_t read = crread(data, 1, size, temp); - fclose(temp); + crclose(temp); return read; } -- 2.39.5