aboutsummaryrefslogtreecommitdiff
path: root/backends/platform/ds/arm9
diff options
context:
space:
mode:
Diffstat (limited to 'backends/platform/ds/arm9')
-rw-r--r--backends/platform/ds/arm9/source/dsloader.cpp83
-rw-r--r--backends/platform/ds/arm9/source/elf32.h11
2 files changed, 70 insertions, 24 deletions
diff --git a/backends/platform/ds/arm9/source/dsloader.cpp b/backends/platform/ds/arm9/source/dsloader.cpp
index a4fe0573d2..2f953cc33b 100644
--- a/backends/platform/ds/arm9/source/dsloader.cpp
+++ b/backends/platform/ds/arm9/source/dsloader.cpp
@@ -27,7 +27,6 @@
#include <string.h>
#include <stdarg.h>
-#include <stdarg.h>
#include <stdio.h>
#include <malloc.h>
#include <unistd.h>
@@ -35,6 +34,7 @@
//#include "backends/fs/stdiostream.h"
#include "backends/fs/ds/ds-fs.h"
+#include "dsmain.h"
#include "backends/platform/ds/arm9/source/dsloader.h"
@@ -92,24 +92,74 @@ bool DLObject::relocate(Common::SeekableReadStream* DLFile, unsigned long offset
// Treat each relocation entry. Loop over all of them
int cnt = size / sizeof(*rel);
- DBG("# of relocation entries is %d.\n", cnt);
+ DBG("Loaded relocation table. %d entries. base address=%p\n", cnt, relSegment);
+
+ int a = 0;
+ unsigned int relocation = 0;
- // TODO: Loop over relocation entries
for (int i = 0; i < cnt; i++) {
- //Elf32_Sym *sym = ???;
+ Elf32_Sym *sym = (Elf32_Sym *)(_symtab) + (REL_INDEX(rel[i].r_info));
+
+ unsigned int *target = (unsigned int *)((char *)relSegment + rel[i].r_offset);
+
+ unsigned int origTarget = *target; // Save for debugging
+
+ //DBG("%d, ", REL_TYPE(rel[i].r_info));
+
+ switch (REL_TYPE(rel[i].r_info)) {
+
+ case R_ARM_ABS32:
+ if (sym->st_shndx < SHN_LOPROC) { // Only shift for plugin section.
+ a = *target; // Get full 32 bits of addend
+ relocation = a + (Elf32_Addr)_segment; // Shift by main offset
+
+ /*TODO:
+ * if (SYM_TYPE(sym->st_info) == STT_FUNC && symbol addresses a thumb instruction) {
+ * relocation |= 1;
+ * }
+ */
+
+ *target = relocation;
+
+ DBG("R_ARM_ABS32: i=%d, a=%x, origTarget=%x, target=%x\n", i, a, origTarget, *target);
+ }
+ break;
+
+ case R_ARM_THM_CALL:
+
+ if (sym->st_shndx < SHN_LOPROC) { // Only shift for plugin section.
+ a = *target & 0x00000fff; // Get the correct bits for addend:
+ a += ((*target & 0x0fff0000) >> 4); // Bits 0-11 of the first half-word encode the 12 most significant bits of the branch offset,
+ // bits 0-11 of the next half-word encode the 12 least significant bits.
+ a = (a << 8) >> 8; // sign-extend
+ a = a << 1; // branch offset is in units of half-bytes
+
+ relocation = a + (Elf32_Addr)_segment; // Shift by main offset
+
+ /*TODO:
+ * if (SYM_TYPE(sym->st_info) == STT_FUNC && symbol addresses a thumb instruction) {
+ * relocation |= 1;
+ * }
+ */
- //void *target = ???;
+ relocation -= rel[i].r_offset;
- /*switch (REL_TYPE()) {*/
- //case ??? :
- //TODO: Cases for each relocation type.
- //break;
- // default:
- //seterror("Unknown relocation type %d.", ?? ?);
+ *target = relocation;
+
+ DBG("R_ARM_THM_CALL: i=%d, a=%x, origTarget=%x, target=%x\n", i, a, origTarget, *target);
+ }
+ break;
+
+ case R_ARM_V4BX:
+ DBG("R_ARM_V4BX: No relocation calculation necessary\n");
+ break;
+
+ default:
+ seterror("Unknown relocation type %d.", REL_TYPE(rel[i].r_info));
free(rel);
return false;
- // }
+ }
}
@@ -400,7 +450,8 @@ bool DLObject::open(const char *path) {
//DLFile->finalize();
- //TODO?: flush data cache
+ //flush data cache
+ DC_FlushAll();
ctors_start = symbol("___plugin_ctors");
ctors_end = symbol("___plugin_ctors_end");
@@ -444,9 +495,9 @@ void *DLObject::symbol(const char *name) {
Elf32_Sym *s = (Elf32_Sym *)_symtab;
for (int c = _symbol_cnt; c--; s++)
- //TODO: Figure out which symbols should be detected here
- if ((s->st_info >> 4 == 1 || s->st_info >> 4 == 2) &&
- _strtab[s->st_name] == '_' && !strcmp(name, _strtab + s->st_name + 1)) {
+ // We can only import symbols that are global or weak in the plugin
+ if ((SYM_BIND(s->st_info) == STB_GLOBAL || SYM_BIND(s->st_info) == STB_WEAK) &&
+ !strcmp(name, _strtab + s->st_name)) {
// We found the symbol
DBG("=> %p\n", (void*)s->st_value);
diff --git a/backends/platform/ds/arm9/source/elf32.h b/backends/platform/ds/arm9/source/elf32.h
index c7971891fe..8167a40551 100644
--- a/backends/platform/ds/arm9/source/elf32.h
+++ b/backends/platform/ds/arm9/source/elf32.h
@@ -174,18 +174,13 @@ typedef struct {
} Elf32_Rel;
// Access macros for the relocation info
-#define REL_TYPE(x) ((unsigned char) (x)) /* Extract relocation type */
+#define REL_TYPE(x) ((unsigned char) (x)) /* Extract relocation type */
#define REL_INDEX(x) ((x)>>8) /* Extract relocation index into symbol table */
// ARM relocation types
#define R_ARM_NONE 0
-#define R_ARM_PC24 1
#define R_ARM_ABS32 2
-#define R_ARM_COPY 20
-#define R_ARM_GLOB_DAT 21
-#define R_ARM_JUMP_SLOT 22
-#define R_ARM_BASE_PREL 25
-#define R_ARM_GOT_BREL 26
-#define R_ARM_PLT32 27
+#define R_ARM_THM_CALL 10
+#define R_ARM_V4BX 40
#endif /* BACKENDS_ELF_H */