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);
}
}