diff --git a/crt/crt0.S b/crt/crt0.S index bae6626..c855fad 100644 --- a/crt/crt0.S +++ b/crt/crt0.S @@ -5,6 +5,10 @@ _start: bl main b exit -.global __eabi -__eabi: +.global __wrap___eabi +__wrap___eabi: + blr + +.global __init +__init: blr diff --git a/crt/memory.c b/crt/memory.c new file mode 100644 index 0000000..d97ac83 --- /dev/null +++ b/crt/memory.c @@ -0,0 +1,103 @@ +/**************************************************************************** + * Copyright (C) 2015 Dimok + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ +#include +#include +#include +#include + +//!------------------------------------------------------------------------------------------- +//! wraps +//!------------------------------------------------------------------------------------------- +void *__wrap_malloc(size_t size) +{ + return MEMAllocFromExpHeapEx(MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2), size, 4); +} + +void *__wrap_memalign(size_t align, size_t size) +{ + if (align < 4) + align = 4; + + // pointer to a function resolve + return MEMAllocFromExpHeapEx(MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2), size, align); +} + +void __wrap_free(void *p) +{ + // pointer to a function resolve + if(p != 0) + MEMFreeToExpHeap(MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2), p); +} + +void *__wrap_calloc(size_t n, size_t size) +{ + void *p = __wrap_malloc(n * size); + if (p != 0) { + memset(p, 0, n * size); + } + return p; +} + +size_t __wrap_malloc_usable_size(void *p) +{ + //! TODO: this is totally wrong and needs to be addressed + return 0x7FFFFFFF; +} + +void *__wrap_realloc(void *p, size_t size) +{ + void *new_ptr = __wrap_malloc(size); + if (new_ptr != 0) + { + memcpy(new_ptr, p, __wrap_malloc_usable_size(p) < size ? __wrap_malloc_usable_size(p) : size); + __wrap_free(p); + } + return new_ptr; +} + +//!------------------------------------------------------------------------------------------- +//! reent versions +//!------------------------------------------------------------------------------------------- +void *__wrap__malloc_r(struct _reent *r, size_t size) +{ + return __wrap_malloc(size); +} + +void *__wrap__calloc_r(struct _reent *r, size_t n, size_t size) +{ + return __wrap_calloc(n, size); +} + +void *__wrap__memalign_r(struct _reent *r, size_t align, size_t size) +{ + return __wrap_memalign(align, size); +} + +void __wrap__free_r(struct _reent *r, void *p) +{ + __wrap_free(p); +} + +size_t __wrap__malloc_usable_size_r(struct _reent *r, void *p) +{ + return __wrap_malloc_usable_size(p); +} + +void *__wrap__realloc_r(struct _reent *r, void *p, size_t size) +{ + return __wrap_realloc(p, size); +} diff --git a/include/coreinit/internal.h b/include/coreinit/internal.h new file mode 100644 index 0000000..bd0f087 --- /dev/null +++ b/include/coreinit/internal.h @@ -0,0 +1,13 @@ +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int +__os_snprintf(char *buf, size_t n, const char *format, ... ); + +#ifdef __cplusplus +} +#endif diff --git a/rpl/libcoreinit/exports.h b/rpl/libcoreinit/exports.h index 7507556..5b1665f 100644 --- a/rpl/libcoreinit/exports.h +++ b/rpl/libcoreinit/exports.h @@ -297,3 +297,6 @@ EXPORT(MEMAllocFromUnitHeap); EXPORT(MEMFreeToUnitHeap); EXPORT(MEMCountFreeBlockForUnitHeap); EXPORT(MEMCalcHeapSizeForUnitHeap); + +// coreinit/internal.h +EXPORT(__os_snprintf); diff --git a/rules/ppc.mk b/rules/ppc.mk index 8cb2105..61b5703 100644 --- a/rules/ppc.mk +++ b/rules/ppc.mk @@ -5,7 +5,7 @@ WUT_ROOT := $(WUT_ROOT) endif LIBPATHS := -L$(WUT_ROOT)/lib -CFLAGS := -I$(WUT_ROOT)/include -fno-builtin -ffreestanding +CFLAGS := -I$(WUT_ROOT)/include -fno-builtin -ffreestanding -fno-jump-tables CXXFLAGS := $(CFLAGS) LDFLAGS := -nostdlib -nostartfiles diff --git a/rules/rpl.ld b/rules/rpl.ld index 011cb32..d8bddee 100644 --- a/rules/rpl.ld +++ b/rules/rpl.ld @@ -20,12 +20,154 @@ PHDRS { SECTIONS { . = ORIGIN(code); + .syscall ALIGN(32) : { *(.syscall) } : hdr_text + /* Standard code section */ .text ALIGN(32) : { - *(.text .stub .text.*) + /* .init */ + KEEP( *(.crt0) ) + KEEP( *(.init) ) + . = ALIGN(4); + + /* .text */ + *(.text) + *(.text.*) + *(.glue_7) + *(.glue_7t) + *(.stub) + *(.gnu.warning) + *(.gnu.linkonce.t*) + . = ALIGN(4); + *(.rplTramp.text) *(SORT(.rplTramp.text.*)) + . = ALIGN(4); + + /* .fini */ + KEEP( *(.fini) ) + . = ALIGN(4); + } : hdr_text + + /* Standard data sections */ + . = ORIGIN(data); + + .rodata ALIGN(256) : { + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + } : hdr_sdata + .rodata1 : { *(.rodata1) } + + .data ALIGN(256) : { + *(.data) + *(.data.*) + *(.eh_frame) + *(.eh_frame_hdr) + *(.gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + + . = ALIGN(32); + __sdata_start = .; + *(.sdata) + *(.sdata.*) + __sdata_end = .; + + . = ALIGN(32); + __sdata2_start = .; + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + __sdata2_end = .; + } : hdr_sdata + + .tdata ALIGN(256) : + { + __tdata_lma = .; + *(.tdata) + *(.tdata.*) + *(.gnu.linkonce.td.*) + . = ALIGN(4); + __tdata_lma_end = .; + } : hdr_data + + .tbss ALIGN(256) : + { + *(.tbss) + *(.tbss.*) + *(.gnu.linkonce.tb.*) + *(.tcommon) + . = ALIGN(4); + } : hdr_data + + .preinit_array ALIGN(256) : + { + PROVIDE (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE (__preinit_array_end = .); + } : hdr_data + + .init_array ALIGN(256) : + { + PROVIDE (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE (__init_array_end = .); + } : hdr_data + + .fini_array ALIGN(256) : + { + PROVIDE (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE (__fini_array_end = .); + } : hdr_data + + .ctors ALIGN(256) : + { + KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */ + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } : hdr_data + + .dtors ALIGN(256) : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } : hdr_data + + __bss_start__ = .; + .bss ALIGN(4) : + { + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b*) + *(COMMON) + . = ALIGN(4); + + __sbss_start = .; + *(.sbss) + *(.sbss.*) + __sbss_end = .; + . = ALIGN(4); + + __sbss2_start = .; + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + __sbss2_end = .; + . = ALIGN(4); + + /* Reserve space for the TLS segment of the main thread */ + __tls_start = .; + . += + SIZEOF(.tdata) + SIZEOF(.tbss); + __tls_end = .; + . = ALIGN(32); + } : hdr_data + __bss_end__ = .; /* System stuff is for our elf2rpl converter to go through */ . = ORIGIN(system); @@ -53,7 +195,8 @@ SECTIONS { } /* Required compiler trash */ - .got ALIGN(32) : { *(.got) } + .fixup ALIGN(32) : { *(.fixup*) } + .got ALIGN(32) : { *(.got*) } .hash ALIGN(32) : { *(.hash) } .dynsym ALIGN(32) : { *(.dynsym) } @@ -94,51 +237,6 @@ SECTIONS { .symtab ALIGN(32) : { *(.symtab) } .strtab ALIGN(32) : { *(.strtab) } - /* Standard data sections */ - . = ORIGIN(data); - - .rodata ALIGN(256) : { - *(.rodata .rodata.*) - } : hdr_srodata - - .data ALIGN(256) : { - *(.data) - *(.eh_frame) - *(.eh_frame_hdr) - } : hdr_sdata - - .bss ALIGN(256) : { - *(.bss) - } - - .sdata ALIGN(256) : { - __sdata_start = .; - *(.sdata) - *(.sdata.*) - __sdata_end = .; - } - - .sbss ALIGN(256) : { - __sbss_start = .; - *(.sbss) - *(.sbss.*) - __sbss_end = .; - } - - .sdata2 ALIGN(256) : { - __sdata2_start = .; - *(.sdata2) - *(.sdata2.*) - __sdata2_end = .; - } - - .sbss2 ALIGN(256) : { - __sbss2_start = .; - *(.sbss2) - *(.sbss2.*) - __sbss2_end = .; - } - /DISCARD/ : { *(.interp) *(.dynstr) @@ -152,6 +250,6 @@ SECTIONS { __SDATA2_START__ = __sdata2_start; __SBSS2_END__ = __sbss2_end; - _SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2); + _SDA_BASE_ = __sbss_end; _SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2); } diff --git a/rules/rpl.mk b/rules/rpl.mk index 3012863..2f079a6 100644 --- a/rules/rpl.mk +++ b/rules/rpl.mk @@ -1,7 +1,10 @@ -LIBPATHS := -L$(WUT_ROOT)/lib -CFLAGS := -I$(WUT_ROOT)/include -fno-builtin -ffreestanding +LIBPATHS := -L$(WUT_ROOT)/lib -L$(DEVKITPPC)/lib +CFLAGS := -I$(WUT_ROOT)/include -fno-builtin -ffreestanding -fno-jump-tables CXXFLAGS := $(CFLAGS) -LDFLAGS := -nostdlib -nostartfiles -T $(WUT_ROOT)/rules/rpl.ld -pie -fPIE -z common-page-size=64 -z max-page-size=64 -lcoreinit -lcrt +LDFLAGS := -nostartfiles -T $(WUT_ROOT)/rules/rpl.ld -pie -fPIE -z common-page-size=64 -z max-page-size=64 -lcrt \ + -Wl,-wrap,malloc,-wrap,free,-wrap,memalign,-wrap,calloc,-wrap,realloc,-wrap,malloc_usable_size \ + -Wl,-wrap,_malloc_r,-wrap,_free_r,-wrap,_realloc_r,-wrap,_calloc_r,-wrap,_memalign_r,-wrap,_malloc_usable_size_r \ + -Wl,-wrap,valloc,-wrap,_valloc_r,-wrap,_pvalloc_r,-wrap,__eabi ELF2RPL := $(WUT_ROOT)/bin/elf2rpl include $(WUT_ROOT)/rules/base.mk diff --git a/tools/elf2rpl/main.cpp b/tools/elf2rpl/main.cpp index 22dccc2..5f699d5 100644 --- a/tools/elf2rpl/main.cpp +++ b/tools/elf2rpl/main.cpp @@ -434,12 +434,12 @@ read(ElfFile &file, const std::string &filename) auto addend = static_cast(rela.addend); - if (auto symbol = findSymbol(file, addend)) { - relocation->symbol = symbol; - relocation->addend = 0; - } else if (auto import = findImport(file, addend)) { + if (auto import = findImport(file, addend)) { relocation->symbol = import->stubSymbol; relocation->addend = 0; + } else if (auto symbol = findSymbol(file, addend)) { + relocation->symbol = symbol; + relocation->addend = 0; } else if (addend >= DataAddress && addend < WiiuLoadAddress) { relocation->symbol = findSymbol(file, DataAddress); relocation->addend = addend - DataAddress; @@ -453,6 +453,73 @@ read(ElfFile &file, const std::string &filename) file.relocations.emplace_back(relocation); } } + + // Read dyn relocations + for (auto §ion : inSections) { + if (section.header.type != elf::SHT_RELA) { + continue; + } + + auto name = std::string { shStrTab + section.header.name }; + + if (name.compare(".rela.dyn") != 0) { + continue; + } + + auto symSection = inSections[section.header.link]; + auto relas = reinterpret_cast(section.data.data()); + auto count = section.data.size() / sizeof(elf::Rela); + + for (auto i = 0u; i < count; ++i) { + auto relocation = new ElfFile::Relocation(); + auto &rela = relas[i]; + + auto type = rela.info & 0xff; + auto index = rela.info >> 8; + auto symbol = getSectionSymbol(symSection, index); + auto addr = symbol->value + rela.addend; + + if(index == 0) + { + auto addend = static_cast(rela.addend); + + if (auto import = findImport(file, addend)) { + relocation->symbol = import->stubSymbol; + relocation->addend = 0; + } else if (auto symbol = findSymbol(file, addend)) { + relocation->symbol = symbol; + relocation->addend = 0; + } else if (addr >= CodeAddress && addr < DataAddress) { + index = 1; + relocation->symbol = findSymbol(file, CodeAddress); + relocation->addend = rela.addend - CodeAddress; + } else if (addr >= DataAddress && addr < WiiuLoadAddress) { + index = 2; + relocation->symbol = findSymbol(file, DataAddress); + relocation->addend = rela.addend - DataAddress; + } else { + std::cout << "Unexpected symbol address in .rela.dyn section" << std::endl; + return false; + } + } + + switch (type) { + case elf::R_PPC_RELATIVE: + type = elf::R_PPC_ADDR32; + break; + default: + std::cout << "Unexpected relocation type in .rela.dyn section" << std::endl; + return false; + } + + relocation->target = rela.offset; + relocation->type = static_cast(type); + + // Scrap any compiler/linker garbage + if(relocation->target >= CodeAddress && relocation->target < WiiuLoadAddress) + file.relocations.emplace_back(relocation); + } + } return true; } @@ -656,7 +723,7 @@ write(ElfFile &file, const std::string &filename) // Prune out unneeded symbols for (auto i = 0u; i < file.symbols.size(); ++i) { - if (!file.symbols[i]->name.empty() && file.symbols[i]->type == elf::STT_NOTYPE) { + if (!file.symbols[i]->name.empty() && file.symbols[i]->type == elf::STT_NOTYPE && file.symbols[i]->size == 0) { file.symbols.erase(file.symbols.begin() + i); i--; } @@ -691,16 +758,32 @@ write(ElfFile &file, const std::string &filename) return val.get() == relocation->symbol; }); - if (itr == file.symbols.end()) { - std::cout << "Could not find matching symbol for relocation" << std::endl; - return false; - } - auto idx = itr - file.symbols.begin(); + // If the symbol doesn't exist but it is within DATA or TEXT, use those symbols + an addend + if (itr == file.symbols.end()) { + if (relocation->symbol->address >= CodeAddress && relocation->symbol->address < DataAddress) { + idx = 1; + relocation->addend = relocation->symbol->address - CodeAddress; + relocation->symbol = findSymbol(file, CodeAddress); + } else if (relocation->symbol->address >= DataAddress && relocation->symbol->address < WiiuLoadAddress) { + idx = 2; + relocation->addend = relocation->symbol->address - DataAddress; + relocation->symbol = findSymbol(file, DataAddress); + } else { + std::cout << "Could not find matching symbol for relocation" << std::endl; + return false; + } + } + // Create relocation elf::Rela rela; rela.info = relocation->type | idx << 8; + + if(relocation->type == elf::R_PPC_RELATIVE) { + rela.info = elf::R_PPC_ADDR32 | idx << 8; + } + rela.addend = relocation->addend; rela.offset = relocation->target; @@ -799,7 +882,7 @@ write(ElfFile &file, const std::string &filename) sym.info = symbol->type | (symbol->binding << 4); sym.other = 0; sym.shndx = shndx; - + //Compound symbol crc into section crc auto crcSection = outSections[shndx]; if(crcSection->header.type == elf::SHT_RPL_IMPORTS && symbol->type != elf::STT_SECTION) { @@ -925,7 +1008,7 @@ write(ElfFile &file, const std::string &filename) fileInfo.loadSize = val; } } else if (section->header.type == elf::SHT_RELA) { - fileInfo.tempSize += size; + fileInfo.tempSize += align_up(size, 64); } }