aboutsummaryrefslogtreecommitdiff
path: root/backends
diff options
context:
space:
mode:
authorYotam Barnoy2010-11-03 22:01:01 +0000
committerYotam Barnoy2010-11-03 22:01:01 +0000
commit13b904d282ea607db94069b927d6cb1b19aa0d0b (patch)
treecbc8efcc281f735beb9f45117e82a30872995ac7 /backends
parent0ac1eb82c65e7f20f51f6337df5aa64e02a1af29 (diff)
parent27182f266f48a6d55dd5d830ed19e2c4285ac1ba (diff)
downloadscummvm-rg350-13b904d282ea607db94069b927d6cb1b19aa0d0b.tar.gz
scummvm-rg350-13b904d282ea607db94069b927d6cb1b19aa0d0b.tar.bz2
scummvm-rg350-13b904d282ea607db94069b927d6cb1b19aa0d0b.zip
Merge from gsoc2010-plugins
This merge was extremely difficult to carry out. It wasn't entirely SVN's fault -- there were several merges to the branch that were done by hand. Please check for any issues and regressions. Also note that the DS makefile was not copied over since the "one at a time" plugin mode currently has too much fragmentation ie. it doesn't work. svn-id: r54051
Diffstat (limited to 'backends')
-rw-r--r--backends/module.mk17
-rw-r--r--backends/platform/ds/arm9/source/dsmain.cpp4
-rw-r--r--backends/platform/ps2/systemps2.cpp11
-rw-r--r--backends/platform/psp/Makefile9
-rw-r--r--backends/platform/psp/module.mk1
-rw-r--r--backends/platform/psp/plugin.ld239
-rw-r--r--backends/platform/psp/plugin.syms8
-rw-r--r--backends/platform/psp/psploader.cpp732
-rw-r--r--backends/platform/psp/psploader.h137
-rw-r--r--backends/platform/wii/main.cpp5
-rw-r--r--backends/platform/wii/wii.mk4
-rw-r--r--backends/plugins/ds/ds-provider.cpp76
-rw-r--r--backends/plugins/ds/ds-provider.h42
-rw-r--r--backends/plugins/ds/plugin.ld218
-rw-r--r--backends/plugins/elf/arm-loader.cpp134
-rw-r--r--backends/plugins/elf/arm-loader.h50
-rw-r--r--backends/plugins/elf/elf-loader.cpp430
-rw-r--r--backends/plugins/elf/elf-loader.h105
-rw-r--r--backends/plugins/elf/elf-provider.cpp178
-rw-r--r--backends/plugins/elf/elf-provider.h85
-rw-r--r--backends/plugins/elf/elf32.h259
-rw-r--r--backends/plugins/elf/mips-loader.cpp340
-rw-r--r--backends/plugins/elf/mips-loader.h60
-rw-r--r--backends/plugins/elf/plugin.syms10
-rw-r--r--backends/plugins/elf/ppc-loader.cpp130
-rw-r--r--backends/plugins/elf/ppc-loader.h50
-rw-r--r--backends/plugins/elf/shorts-segment-manager.cpp91
-rw-r--r--backends/plugins/elf/shorts-segment-manager.h118
-rw-r--r--backends/plugins/elf/version.cpp33
-rw-r--r--backends/plugins/elf/version.h36
-rw-r--r--backends/plugins/ps2/main_prog.ld100
-rw-r--r--backends/plugins/ps2/plugin.ld95
-rw-r--r--backends/plugins/ps2/ps2-provider.cpp73
-rw-r--r--backends/plugins/ps2/ps2-provider.h42
-rw-r--r--backends/plugins/psp/plugin.ld239
-rw-r--r--backends/plugins/psp/psp-provider.cpp93
-rw-r--r--backends/plugins/psp/psp-provider.h22
-rw-r--r--backends/plugins/wii/plugin.ld264
-rw-r--r--backends/plugins/wii/wii-provider.cpp76
-rw-r--r--backends/plugins/wii/wii-provider.h42
40 files changed, 3429 insertions, 1229 deletions
diff --git a/backends/module.mk b/backends/module.mk
index e0a3f4c683..b3a23f10e7 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -22,6 +22,14 @@ MODULE_OBJS := \
midi/timidity.o \
midi/dmedia.o \
midi/windows.o \
+ plugins/elf/elf-loader.o \
+ plugins/elf/mips-loader.o \
+ plugins/elf/shorts-segment-manager.o \
+ plugins/elf/ppc-loader.o \
+ plugins/elf/arm-loader.o \
+ plugins/elf/elf-provider.o \
+ plugins/elf/version.o \
+ plugins/dc/dc-provider.o \
plugins/posix/posix-provider.o \
plugins/sdl/sdl-provider.o \
plugins/win32/win32-provider.o \
@@ -43,7 +51,8 @@ endif
ifeq ($(BACKEND),ds)
MODULE_OBJS += \
fs/ds/ds-fs-factory.o \
- fs/ds/ds-fs.o
+ fs/ds/ds-fs.o \
+ plugins/ds/ds-provider.o
endif
ifeq ($(BACKEND),n64)
@@ -54,7 +63,8 @@ endif
ifeq ($(BACKEND),ps2)
MODULE_OBJS += \
- fs/ps2/ps2-fs-factory.o
+ fs/ps2/ps2-fs-factory.o \
+ plugins/ps2/ps2-provider.o
endif
ifeq ($(BACKEND),psp)
@@ -68,7 +78,8 @@ endif
ifeq ($(BACKEND),wii)
MODULE_OBJS += \
- fs/wii/wii-fs-factory.o
+ fs/wii/wii-fs-factory.o \
+ plugins/wii/wii-provider.o
endif
# Include common rules
diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp
index 1525647c2e..a9dc05b89c 100644
--- a/backends/platform/ds/arm9/source/dsmain.cpp
+++ b/backends/platform/ds/arm9/source/dsmain.cpp
@@ -105,6 +105,7 @@
#endif
#include "engine.h"
+#include "backends/plugins/ds/ds-provider.h"
#include "backends/fs/ds/ds-fs.h"
#include "base/version.h"
#include "common/util.h"
@@ -3213,6 +3214,9 @@ int main(void) {
const char *argv[] = {"/scummvmds"};
#endif
+#ifdef DYNAMIC_MODULES
+ PluginManager::instance().addPluginProvider(new DSPluginProvider());
+#endif
while (1) {
scummvm_main(ARRAYSIZE(argv), (char **) &argv);
diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp
index fd2bf80761..1b3ae6ba47 100644
--- a/backends/platform/ps2/systemps2.cpp
+++ b/backends/platform/ps2/systemps2.cpp
@@ -26,6 +26,9 @@
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
+// Disable symbol overrides so that we can use system headers.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
#include <kernel.h>
#include <stdio.h>
#include <stdlib.h>
@@ -62,6 +65,8 @@
#include "backends/platform/ps2/ps2debug.h"
#include "backends/fs/ps2/ps2-fs-factory.h"
+#include "backends/plugins/ps2/ps2-provider.h"
+
#include "backends/saves/default/default-saves.h"
#include "common/config-manager.h"
@@ -108,7 +113,6 @@ extern "C" int scummvm_main(int argc, char *argv[]);
extern "C" int main(int argc, char *argv[]) {
SifInitRpc(0);
-
ee_thread_t thisThread;
int tid = GetThreadId();
ReferThreadStatus(tid, &thisThread);
@@ -133,8 +137,11 @@ extern "C" int main(int argc, char *argv[]) {
sioprintf("Creating system\n");
g_system = g_systemPs2 = new OSystem_PS2(argv[0]);
- g_systemPs2->init();
+#ifdef DYNAMIC_MODULES
+ PluginManager::instance().addPluginProvider(new PS2PluginProvider());
+#endif
+ g_systemPs2->init();
sioprintf("init done. starting ScummVM.\n");
int res = scummvm_main(argc, argv);
sioprintf("scummvm_main terminated: %d\n", res);
diff --git a/backends/platform/psp/Makefile b/backends/platform/psp/Makefile
index a104e3297a..9f6b5c8921 100644
--- a/backends/platform/psp/Makefile
+++ b/backends/platform/psp/Makefile
@@ -67,7 +67,7 @@ endif
# Variables for common Scummvm makefile
CXX = psp-g++
CXXFLAGS = -O3 -Wall -Wno-multichar -fno-exceptions -fno-rtti
-DEFINES = -D__PSP__ -DNONSTANDARD_PORT -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE -DUSE_ZLIB -DDISABLE_DOSBOX_OPL -DUSE_RGB_COLOR
+DEFINES = -D__PSP__ -DNONSTANDARD_PORT -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE -DUSE_ZLIB -DDISABLE_DOSBOX_OPL -DUSE_RGB_COLOR -DUSE_ELF_LOADER -DMIPS_TARGET
LDFLAGS :=
INCDIR := $(srcdir) . $(srcdir)/engines/ $(PSPSDK)/include
@@ -87,8 +87,8 @@ CXX_UPDATE_DEP_FLAG = -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP
# Variables for dynamic plugin building
PLUGIN_PREFIX =
PLUGIN_SUFFIX = .plg
-PLUGIN_EXTRA_DEPS = plugin.syms scummvm-psp.elf
-PLUGIN_LDFLAGS = -nostartfiles -Wl,-q,--just-symbols=scummvm-psp.org.elf,-Tplugin.ld,--retain-symbols-file,plugin.syms -lstdc++ -lc
+PLUGIN_EXTRA_DEPS = $(srcdir)/backends/plugins/elf/plugin.syms scummvm-psp.elf
+PLUGIN_LDFLAGS = -nostartfiles -Wl,-q,--just-symbols=scummvm-psp.org.elf,-T$(srcdir)/backends/plugins/psp/plugin.ld,--retain-symbols-file,$(srcdir)/backends/plugins/elf/plugin.syms -lstdc++ -lc
# PSP-specific variables
STRIP = psp-strip
@@ -128,6 +128,7 @@ PSPLIBS = -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl
-lpsputility -lpspuser -lpsppower -lpsphprm -lpspsdk -lpsprtc -lpspaudio -lpspaudiocodec \
-lpspkernel -lpspnet_inet
+
# Add in PSPSDK includes and libraries.
LIBS += -lpng -lz -lstdc++ -lc -lm $(PSPLIBS)
@@ -142,7 +143,6 @@ OBJS := powerman.o \
input.o \
cursor.o \
trace.o \
- psploader.o \
pspkeyboard.o \
audio.o \
thread.o \
@@ -153,6 +153,7 @@ OBJS := powerman.o \
tests.o \
dummy.o
+
BACKEND := psp
# Include common Scummvm makefile
diff --git a/backends/platform/psp/module.mk b/backends/platform/psp/module.mk
index cdd0fa0ef5..e3eac153dd 100644
--- a/backends/platform/psp/module.mk
+++ b/backends/platform/psp/module.mk
@@ -11,7 +11,6 @@ MODULE_OBJS := powerman.o \
input.o \
cursor.o \
trace.o \
- psploader.o \
pspkeyboard.o \
audio.o \
thread.o \
diff --git a/backends/platform/psp/plugin.ld b/backends/platform/psp/plugin.ld
deleted file mode 100644
index 7534c15290..0000000000
--- a/backends/platform/psp/plugin.ld
+++ /dev/null
@@ -1,239 +0,0 @@
-OUTPUT_FORMAT("elf32-littlemips", "elf32-bigmips",
- "elf32-littlemips")
-OUTPUT_ARCH(mips:allegrex)
-PHDRS
-{
- plugin PT_LOAD ;
- shorts PT_LOAD ;
-}
-/* Do we need any of these for elf?
- __DYNAMIC = 0; */
-SECTIONS
-{
- /* Read-only sections, merged into text segment: */
- . = 0;
- .interp : { *(.interp) } : plugin
- .reginfo : { *(.reginfo) } : plugin
- .dynamic : { *(.dynamic) }
- .hash : { *(.hash) }
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .gnu.version : { *(.gnu.version) }
- .gnu.version_d : { *(.gnu.version_d) }
- .gnu.version_r : { *(.gnu.version_r) }
- .rel.init : { *(.rel.init) }
- .rela.init : { *(.rela.init) }
- .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
- .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
- .rel.fini : { *(.rel.fini) }
- .rela.fini : { *(.rela.fini) }
- /* PSP-specific relocations. */
- .rel.sceStub.text : { *(.rel.sceStub.text) *(SORT(.rel.sceStub.text.*)) }
- .rel.lib.ent.top : { *(.rel.lib.ent.top) }
- .rel.lib.ent : { *(.rel.lib.ent) }
- .rel.lib.ent.btm : { *(.rel.lib.ent.btm) }
- .rel.lib.stub.top : { *(.rel.lib.stub.top) }
- .rel.lib.stub : { *(.rel.lib.stub) }
- .rel.lib.stub.btm : { *(.rel.lib.stub.btm) }
- .rel.rodata.sceModuleInfo : { *(.rel.rodata.sceModuleInfo) }
- .rel.rodata.sceResident : { *(.rel.rodata.sceResident) }
- .rel.rodata.sceNid : { *(.rel.rodata.sceNid) }
- .rel.rodata.sceVstub : { *(.rel.rodata.sceVstub) *(SORT(.rel.rodata.sceVstub.*)) }
- .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
- .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
- .rel.data.rel.ro : { *(.rel.data.rel.ro*) }
- .rela.data.rel.ro : { *(.rel.data.rel.ro*) }
- .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
- .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
- .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
- .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
- .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
- .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
- .rel.ctors : { *(.rel.ctors) }
- .rela.ctors : { *(.rela.ctors) }
- .rel.dtors : { *(.rel.dtors) }
- .rela.dtors : { *(.rela.dtors) }
- .rel.got : { *(.rel.got) }
- .rela.got : { *(.rela.got) }
- .rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) }
- .rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) }
- .rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) }
- .rela.sbss : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) }
- .rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) }
- .rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) }
- .rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) }
- .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) }
- .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
- .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
- .rel.plt : { *(.rel.plt) }
- .rela.plt : { *(.rela.plt) }
- .init :
- {
- KEEP (*(.init))
- } =0
- .plt : { *(.plt) }
- .text :
- {
- _ftext = . ;
- *(.text .stub .text.* .gnu.linkonce.t.*)
- KEEP (*(.text.*personality*))
- /* .gnu.warning sections are handled specially by elf32.em. */
- *(.gnu.warning)
- *(.mips16.fn.*) *(.mips16.call.*)
- } =0
- .fini :
- {
- KEEP (*(.fini))
- } =0
- /* PSP library stub functions. */
- .sceStub.text : { *(.sceStub.text) *(SORT(.sceStub.text.*)) }
- PROVIDE (__etext = .);
- PROVIDE (_etext = .);
- PROVIDE (etext = .);
- /* PSP library entry table and library stub table. */
- .lib.ent.top : { *(.lib.ent.top) }
- .lib.ent : { *(.lib.ent) }
- .lib.ent.btm : { *(.lib.ent.btm) }
- .lib.stub.top : { *(.lib.stub.top) }
- .lib.stub : { *(.lib.stub) }
- .lib.stub.btm : { *(.lib.stub.btm) }
- /* PSP read-only data for module info, NIDs, and Vstubs. The
- .rodata.sceModuleInfo section must appear before the .rodata section
- otherwise it would get absorbed into .rodata and the PSP bootloader
- would be unable to locate the module info structure. */
- .rodata.sceModuleInfo : { *(.rodata.sceModuleInfo) }
- .rodata.sceResident : { *(.rodata.sceResident) }
- .rodata.sceNid : { *(.rodata.sceNid) }
- .rodata.sceVstub : { *(.rodata.sceVstub) *(SORT(.rodata.sceVstub.*)) }
- .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
- .rodata1 : { *(.rodata1) }
- .sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) }
- .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
- .eh_frame_hdr : { *(.eh_frame_hdr) }
- .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
- .gcc_except_table : ONLY_IF_RO { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) }
- /* 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(256) + (. & (256 - 1));
- /* Exception handling */
- .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
- .gcc_except_table : ONLY_IF_RW { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) }
- /* Thread Local Storage sections */
- .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
- .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
- /* Ensure the __preinit_array_start label is properly aligned. We
- could instead move the label definition inside the section, but
- the linker would then create the section even if it turns out to
- be empty, which isn't pretty. */
- . = ALIGN(32 / 8);
- PROVIDE (__preinit_array_start = .);
- .preinit_array : { KEEP (*(.preinit_array)) }
- PROVIDE (__preinit_array_end = .);
- PROVIDE (__init_array_start = .);
- .init_array : { KEEP (*(.init_array)) }
- PROVIDE (__init_array_end = .);
- PROVIDE (__fini_array_start = .);
- .fini_array : { KEEP (*(.fini_array)) }
- PROVIDE (__fini_array_end = .);
- .ctors :
- {
- ___plugin_ctors = .;
- KEEP (*(SORT(.ctors.*)))
- KEEP (*(.ctors))
- ___plugin_ctors_end = .;
- }
- .dtors :
- {
- ___plugin_dtors = .;
- KEEP (*(SORT(.dtors.*)))
- KEEP (*(.dtors))
- ___plugin_dtors_end = .;
- }
- .jcr : { KEEP (*(.jcr)) }
- .data.rel.ro : { *(.data.rel.ro.local) *(.data.rel.ro*) }
- .data :
- {
- _fdata = . ;
- *(.data .data.* .gnu.linkonce.d.*)
- KEEP (*(.gnu.linkonce.d.*personality*))
- SORT(CONSTRUCTORS)
- }
- .data1 : { *(.data1) }
- . = .;
- .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. */
- . = ALIGN(32 / 8);
- }
- . = ALIGN(32 / 8);
- _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_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) }
- /DISCARD/ : { *(.comment) *(.pdr) }
- /DISCARD/ : { *(.note.GNU-stack) }
-
- . = __plugin_hole_start;
- .got : { *(.got.plt) *(.got) } : shorts
- /* We want the small data sections together, so single-instruction offsets
- can access them all, and initialized data all before uninitialized, so
- we can shorten the on-disk segment size. */
- .sdata :
- {
- *(.sdata .sdata.* .gnu.linkonce.s.*)
- }
- .lit8 : { *(.lit8) }
- .lit4 : { *(.lit4) }
- _edata = .;
- PROVIDE (edata = .);
- __bss_start = .;
- _fbss = .;
- .sbss :
- {
- PROVIDE (__sbss_start = .);
- PROVIDE (___sbss_start = .);
- *(.dynsbss)
- *(.sbss .sbss.* .gnu.linkonce.sb.*)
- *(.scommon)
- PROVIDE (__sbss_end = .);
- PROVIDE (___sbss_end = .);
- }
-
-
-}
diff --git a/backends/platform/psp/plugin.syms b/backends/platform/psp/plugin.syms
deleted file mode 100644
index 24ee1a19dc..0000000000
--- a/backends/platform/psp/plugin.syms
+++ /dev/null
@@ -1,8 +0,0 @@
-PLUGIN_getVersion
-PLUGIN_getType
-PLUGIN_getTypeVersion
-PLUGIN_getObject
-___plugin_ctors
-___plugin_ctors_end
-___plugin_dtors
-___plugin_dtors_end
diff --git a/backends/platform/psp/psploader.cpp b/backends/platform/psp/psploader.cpp
deleted file mode 100644
index 464e20770c..0000000000
--- a/backends/platform/psp/psploader.cpp
+++ /dev/null
@@ -1,732 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * 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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#if defined(DYNAMIC_MODULES) && defined(__PSP__)
-
-#include <string.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <malloc.h>
-#include <unistd.h>
-#include <sys/_default_fcntl.h>
-
-#include <psputils.h>
-
-#include "backends/platform/psp/psploader.h"
-#include "backends/platform/psp/powerman.h"
-
-//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */
-//#define __PSP_DEBUG_PRINT__
-
-#include "backends/platform/psp/trace.h"
-
-extern char __plugin_hole_start; // Indicates start of hole in program file for shorts
-extern char __plugin_hole_end; // Indicates end of hole in program file
-extern char _gp[]; // Value of gp register
-
-DECLARE_SINGLETON(ShortSegmentManager) // For singleton
-
-// Get rid of symbol table in memory
-void DLObject::discard_symtab() {
- DEBUG_ENTER_FUNC();
- free(_symtab);
- free(_strtab);
- _symtab = NULL;
- _strtab = NULL;
- _symbol_cnt = 0;
-}
-
-// Unload all objects from memory
-void DLObject::unload() {
- DEBUG_ENTER_FUNC();
- discard_symtab();
- free(_segment);
- _segment = NULL;
-
- if (_shortsSegment) {
- ShortsMan.deleteSegment(_shortsSegment);
- _shortsSegment = NULL;
- }
-}
-
-/**
- * Follow the instruction of a relocation section.
- *
- * @param fd File Descriptor
- * @param offset Offset into the File
- * @param size Size of relocation section
- * @param relSegment Base address of relocated segment in memory (memory offset)
- *
- */
-bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void *relSegment) {
- DEBUG_ENTER_FUNC();
- Elf32_Rel *rel = NULL; // relocation entry
-
- // Allocate memory for relocation table
- if (!(rel = (Elf32_Rel *)malloc(size))) {
- PSP_ERROR("Out of memory.");
- return false;
- }
-
- // Read in our relocation table
- if (lseek(fd, offset, SEEK_SET) < 0 ||
- read(fd, rel, size) != (ssize_t)size) {
- PSP_ERROR("Relocation table load failed.");
- free(rel);
- return false;
- }
-
- // Treat each relocation entry. Loop over all of them
- int cnt = size / sizeof(*rel);
-
- PSP_DEBUG_PRINT("Loaded relocation table. %d entries. base address=%p\n", cnt, relSegment);
-
- bool seenHi16 = false; // For treating HI/LO16 commands
- int firstHi16 = -1; // Mark the point of the first hi16 seen
- Elf32_Addr ahl = 0; // Calculated addend
- int a = 0; // Addend: taken from the target
-
- unsigned int *lastTarget = 0; // For processing hi16 when lo16 arrives
- unsigned int relocation = 0;
- int debugRelocs[10] = {0}; // For debugging
- int extendedHi16 = 0; // Count extended hi16 treatments
- Elf32_Addr lastHiSymVal = 0;
- bool hi16InShorts = false;
-
-#define DEBUG_NUM 2
-
- // Loop over relocation entries
- for (int i = 0; i < cnt; i++) {
- // Get the symbol this relocation entry is referring to
- Elf32_Sym *sym = (Elf32_Sym *)(_symtab) + (REL_INDEX(rel[i].r_info));
-
- // Get the target instruction in the code
- unsigned int *target = (unsigned int *)((char *)relSegment + rel[i].r_offset);
-
- PSP_DEBUG_DO(unsigned int origTarget = *target); // Save for debugging
-
- // Act differently based on the type of relocation
- switch (REL_TYPE(rel[i].r_info)) {
-
- case R_MIPS_HI16: // Absolute addressing.
- if (sym->st_shndx < SHN_LOPROC && // Only shift for plugin section (ie. has a real section index)
- firstHi16 < 0) { // Only process first in block of HI16s
- firstHi16 = i; // Keep the first Hi16 we saw
- seenHi16 = true;
- ahl = (*target & 0xffff) << 16; // Take lower 16 bits shifted up
-
- lastHiSymVal = sym->st_value;
- hi16InShorts = (ShortsMan.inGeneralSegment((char *)sym->st_value)); // Fix for problem with switching btw segments
- if (debugRelocs[0]++ < DEBUG_NUM) // Print only a set number
- PSP_DEBUG_PRINT("R_MIPS_HI16: i=%d, offset=%x, ahl = %x, target = %x\n",
- i, rel[i].r_offset, ahl, *target);
- }
- break;
-
- case R_MIPS_LO16: // Absolute addressing. Needs a HI16 to come before it
- if (sym->st_shndx < SHN_LOPROC) { // Only shift for plugin section. (ie. has a real section index)
- if (!seenHi16) { // We MUST have seen HI16 first
- PSP_ERROR("R_MIPS_LO16 w/o preceding R_MIPS_HI16 at relocation %d!\n", i);
- free(rel);
- return false;
- }
-
- // Fix: bug in gcc makes LO16s connect to wrong HI16s sometimes (shorts and regular segment)
- // Note that we can check the entire shorts segment because the executable's shorts don't belong to this plugin section
- // and will be screened out above
- bool lo16InShorts = ShortsMan.inGeneralSegment((char *)sym->st_value);
-
- // Correct the bug by getting the proper value in ahl (taken from the current symbol)
- if ((hi16InShorts && !lo16InShorts) || (!hi16InShorts && lo16InShorts)) {
- ahl -= (lastHiSymVal & 0xffff0000); // We assume gcc meant the same offset
- ahl += (sym->st_value & 0xffff0000);
- }
-
- ahl &= 0xffff0000; // Clean lower 16 bits for repeated LO16s
- a = *target & 0xffff; // Take lower 16 bits of the target
- a = (a << 16) >> 16; // Sign extend them
- ahl += a; // Add lower 16 bits. AHL is now complete
-
- // Fix: we can have LO16 access to the short segment sometimes
- if (lo16InShorts) {
- relocation = ahl + _shortsSegment->getOffset(); // Add in the short segment offset
- } else // It's in the regular segment
- relocation = ahl + (Elf32_Addr)_segment; // Add in the new offset for the segment
-
- if (firstHi16 >= 0) { // We haven't treated the HI16s yet so do it now
- for (int j = firstHi16; j < i; j++) {
- if (REL_TYPE(rel[j].r_info) != R_MIPS_HI16) continue; // Skip over non-Hi16s
-
- lastTarget = (unsigned int *)((char *)relSegment + rel[j].r_offset); // get hi16 target
- *lastTarget &= 0xffff0000; // Clear the lower 16 bits of the last target
- *lastTarget |= (relocation >> 16) & 0xffff; // Take the upper 16 bits of the relocation
- if (relocation & 0x8000)(*lastTarget)++; // Subtle: we need to add 1 to the HI16 in this case
- }
- firstHi16 = -1; // Reset so we'll know we treated it
- } else {
- extendedHi16++;
- }
-
- *target &= 0xffff0000; // Clear the lower 16 bits of current target
- *target |= relocation & 0xffff; // Take the lower 16 bits of the relocation
-
- if (debugRelocs[1]++ < DEBUG_NUM)
- PSP_DEBUG_PRINT("R_MIPS_LO16: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n",
- i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target);
- if (lo16InShorts && debugRelocs[2]++ < DEBUG_NUM)
- PSP_DEBUG_PRINT("R_MIPS_LO16s: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n",
- i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target);
- }
- break;
-
- case R_MIPS_26: // Absolute addressing (for jumps and branches only)
- if (sym->st_shndx < SHN_LOPROC) { // Only relocate for main segment
- a = *target & 0x03ffffff; // Get 26 bits' worth of the addend
- a = (a << 6) >> 6; // Sign extend a
- relocation = ((a << 2) + (Elf32_Addr)_segment) >> 2; // a already points to the target. Subtract our offset
- *target &= 0xfc000000; // Clean lower 26 target bits
- *target |= (relocation & 0x03ffffff);
-
- if (debugRelocs[3]++ < DEBUG_NUM)
- PSP_DEBUG_PRINT("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n",
- i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target);
- } else {
- if (debugRelocs[4]++ < DEBUG_NUM)
- PSP_DEBUG_PRINT("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n",
- i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target);
- }
- break;
-
- case R_MIPS_GPREL16: // GP Relative addressing
- if (_shortsSegment->getOffset() != 0 && // Only relocate if we shift the shorts section
- ShortsMan.inGeneralSegment((char *)sym->st_value)) { // Only relocate things in the plugin hole
- a = *target & 0xffff; // Get 16 bits' worth of the addend
- a = (a << 16) >> 16; // Sign extend it
-
- relocation = a + _shortsSegment->getOffset();
-
- *target &= 0xffff0000; // Clear the lower 16 bits of the target
- *target |= relocation & 0xffff;
-
- if (debugRelocs[5]++ < DEBUG_NUM)
- PSP_DEBUG_PRINT("R_MIPS_GPREL16: i=%d, a=%x, gpVal=%x, origTarget=%x, target=%x, offset=%x\n",
- i, a, _gpVal, origTarget, *target, _shortsSegment->getOffset());
- }
-
- break;
-
- case R_MIPS_32: // Absolute addressing
- if (sym->st_shndx < SHN_LOPROC) { // Only shift for plugin section.
- a = *target; // Get full 32 bits of addend
-
- if (ShortsMan.inGeneralSegment((char *)sym->st_value)) // Check if we're in the shorts segment
- relocation = a + _shortsSegment->getOffset(); // Shift by shorts offset
- else // We're in the main section
- relocation = a + (Elf32_Addr)_segment; // Shift by main offset
- *target = relocation;
-
- if (debugRelocs[6]++ < DEBUG_NUM)
- PSP_DEBUG_PRINT("R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x\n", i, a, origTarget, *target);
- }
- break;
-
- default:
- PSP_ERROR("Unknown relocation type %x at relocation %d.\n", REL_TYPE(rel[i].r_info), i);
- free(rel);
- return false;
- }
- }
-
- PSP_DEBUG_PRINT("Done with relocation. extendedHi16=%d\n\n", extendedHi16);
-
- free(rel);
- return true;
-}
-
-bool DLObject::readElfHeader(int fd, Elf32_Ehdr *ehdr) {
- DEBUG_ENTER_FUNC();
- // Start reading the elf header. Check for errors
- if (read(fd, ehdr, sizeof(*ehdr)) != sizeof(*ehdr) ||
- memcmp(ehdr->e_ident, ELFMAG, SELFMAG) || // Check MAGIC
- ehdr->e_type != ET_EXEC || // Check for executable
- ehdr->e_machine != EM_MIPS || // Check for MIPS machine type
- ehdr->e_phentsize < sizeof(Elf32_Phdr) || // Check for size of program header
- ehdr->e_shentsize != sizeof(Elf32_Shdr)) { // Check for size of section header
- PSP_ERROR("Invalid file type.");
- return false;
- }
-
- PSP_DEBUG_PRINT("phoff = %d, phentsz = %d, phnum = %d\n",
- ehdr->e_phoff, ehdr->e_phentsize, ehdr->e_phnum);
-
- return true;
-}
-
-bool DLObject::readProgramHeaders(int fd, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, int num) {
- DEBUG_ENTER_FUNC();
- // Read program header
- if (lseek(fd, ehdr->e_phoff + sizeof(*phdr)*num, SEEK_SET) < 0 ||
- read(fd, phdr, sizeof(*phdr)) != sizeof(*phdr)) {
- PSP_ERROR("Program header load failed.");
- return false;
- }
-
- // Check program header values
- if (phdr->p_type != PT_LOAD || phdr->p_filesz > phdr->p_memsz) {
- PSP_ERROR("Invalid program header.");
- return false;
- }
-
- PSP_DEBUG_PRINT("offs = %x, filesz = %x, memsz = %x, align = %x\n",
- phdr->p_offset, phdr->p_filesz, phdr->p_memsz, phdr->p_align);
-
- return true;
-
-}
-
-bool DLObject::loadSegment(int fd, Elf32_Phdr *phdr) {
- DEBUG_ENTER_FUNC();
-
- char *baseAddress = 0;
-
- // We need to take account of non-allocated segment for shorts
- if (phdr->p_flags & PF_X) { // This is a relocated segment
-
- // Attempt to allocate memory for segment
- int extra = phdr->p_vaddr % phdr->p_align; // Get extra length TODO: check logic here
- PSP_DEBUG_PRINT("extra mem is %x\n", extra);
-
- if (phdr->p_align < 0x10000) phdr->p_align = 0x10000; // Fix for wrong alignment on e.g. AGI
-
- if (!(_segment = (char *)memalign(phdr->p_align, phdr->p_memsz + extra))) {
- PSP_ERROR("Out of memory.\n");
- return false;
- }
- PSP_DEBUG_PRINT("allocated segment @ %p\n", _segment);
-
- // Get offset to load segment into
- baseAddress = (char *)_segment + phdr->p_vaddr;
- _segmentSize = phdr->p_memsz + extra;
- } else { // This is a shorts section.
- _shortsSegment = ShortsMan.newSegment(phdr->p_memsz, (char *)phdr->p_vaddr);
-
- baseAddress = _shortsSegment->getStart();
- PSP_DEBUG_PRINT("shorts segment @ %p to %p. Segment wants to be at %x. Offset=%x\n",
- _shortsSegment->getStart(), _shortsSegment->getEnd(), phdr->p_vaddr, _shortsSegment->getOffset());
-
- }
-
- // Set bss segment to 0 if necessary (assumes bss is at the end)
- if (phdr->p_memsz > phdr->p_filesz) {
- PSP_DEBUG_PRINT("Setting %p to %p to 0 for bss\n", baseAddress + phdr->p_filesz, baseAddress + phdr->p_memsz);
- memset(baseAddress + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz);
- }
- // Read the segment into memory
- if (lseek(fd, phdr->p_offset, SEEK_SET) < 0 ||
- read(fd, baseAddress, phdr->p_filesz) != (ssize_t)phdr->p_filesz) {
- PSP_ERROR("Segment load failed.");
- return false;
- }
-
- return true;
-}
-
-
-Elf32_Shdr * DLObject::loadSectionHeaders(int fd, Elf32_Ehdr *ehdr) {
- DEBUG_ENTER_FUNC();
-
- Elf32_Shdr *shdr = NULL;
-
- // Allocate memory for section headers
- if (!(shdr = (Elf32_Shdr *)malloc(ehdr->e_shnum * sizeof(*shdr)))) {
- PSP_ERROR("Out of memory.");
- return NULL;
- }
-
- // Read from file into section headers
- if (lseek(fd, ehdr->e_shoff, SEEK_SET) < 0 ||
- read(fd, shdr, ehdr->e_shnum * sizeof(*shdr)) !=
- (ssize_t)(ehdr->e_shnum * sizeof(*shdr))) {
- PSP_ERROR("Section headers load failed.");
- return NULL;
- }
-
- return shdr;
-}
-
-int DLObject::loadSymbolTable(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
- DEBUG_ENTER_FUNC();
-
- // Loop over sections, looking for symbol table linked to a string table
- for (int i = 0; i < ehdr->e_shnum; i++) {
- PSP_DEBUG_PRINT("Section %d: type = %x, size = %x, entsize = %x, link = %x\n",
- i, shdr[i].sh_type, shdr[i].sh_size, shdr[i].sh_entsize, shdr[i].sh_link);
-
- if (shdr[i].sh_type == SHT_SYMTAB &&
- shdr[i].sh_entsize == sizeof(Elf32_Sym) &&
- shdr[i].sh_link < ehdr->e_shnum &&
- shdr[shdr[i].sh_link].sh_type == SHT_STRTAB &&
- _symtab_sect < 0) {
- _symtab_sect = i;
- }
- }
-
- // Check for no symbol table
- if (_symtab_sect < 0) {
- PSP_ERROR("No symbol table.");
- return -1;
- }
-
- PSP_DEBUG_PRINT("Symbol section at section %d, size %x\n", _symtab_sect, shdr[_symtab_sect].sh_size);
-
- // Allocate memory for symbol table
- if (!(_symtab = malloc(shdr[_symtab_sect].sh_size))) {
- PSP_ERROR("Out of memory.");
- return -1;
- }
-
- // Read symbol table into memory
- if (lseek(fd, shdr[_symtab_sect].sh_offset, SEEK_SET) < 0 ||
- read(fd, _symtab, shdr[_symtab_sect].sh_size) !=
- (ssize_t)shdr[_symtab_sect].sh_size) {
- PSP_ERROR("Symbol table load failed.");
- return -1;
- }
-
- // Set number of symbols
- _symbol_cnt = shdr[_symtab_sect].sh_size / sizeof(Elf32_Sym);
- PSP_DEBUG_PRINT("Loaded %d symbols.\n", _symbol_cnt);
-
- return _symtab_sect;
-
-}
-
-bool DLObject::loadStringTable(int fd, Elf32_Shdr *shdr) {
- DEBUG_ENTER_FUNC();
-
- int string_sect = shdr[_symtab_sect].sh_link;
-
- // Allocate memory for string table
- if (!(_strtab = (char *)malloc(shdr[string_sect].sh_size))) {
- PSP_ERROR("Out of memory.");
- return false;
- }
-
- // Read string table into memory
- if (lseek(fd, shdr[string_sect].sh_offset, SEEK_SET) < 0 ||
- read(fd, _strtab, shdr[string_sect].sh_size) !=
- (ssize_t)shdr[string_sect].sh_size) {
- PSP_ERROR("Symbol table strings load failed.");
- return false;
- }
- return true;
-}
-
-void DLObject::relocateSymbols(Elf32_Addr offset, Elf32_Addr shortsOffset) {
- DEBUG_ENTER_FUNC();
-
- int shortsCount = 0, othersCount = 0;
- PSP_DEBUG_PRINT("Relocating symbols by %x. Shorts offset=%x\n", offset, shortsOffset);
-
- // Loop over symbols, add relocation offset
- Elf32_Sym *s = (Elf32_Sym *)_symtab;
- for (int c = _symbol_cnt; c--; s++) {
- // Make sure we don't relocate special valued symbols
- if (s->st_shndx < SHN_LOPROC) {
- if (!ShortsMan.inGeneralSegment((char *)s->st_value)) {
- othersCount++;
- s->st_value += offset;
- if (s->st_value < (Elf32_Addr)_segment || s->st_value > (Elf32_Addr)_segment + _segmentSize)
- PSP_ERROR("Symbol out of bounds! st_value = %x\n", s->st_value);
- } else { // shorts section
- shortsCount++;
- s->st_value += shortsOffset;
- if (!_shortsSegment->inSegment((char *)s->st_value))
- PSP_ERROR("Symbol out of bounds! st_value = %x\n", s->st_value);
- }
-
- }
-
- }
-
- PSP_DEBUG_PRINT("Relocated %d short symbols, %d others.\n", shortsCount, othersCount);
-}
-
-bool DLObject::relocateRels(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
- DEBUG_ENTER_FUNC();
-
- // Loop over sections, finding relocation sections
- for (int i = 0; i < ehdr->e_shnum; i++) {
-
- Elf32_Shdr *curShdr = &(shdr[i]);
- //Elf32_Shdr *linkShdr = &(shdr[curShdr->sh_info]);
-
- if (curShdr->sh_type == SHT_REL && // Check for a relocation section
- curShdr->sh_entsize == sizeof(Elf32_Rel) && // Check for proper relocation size
- (int)curShdr->sh_link == _symtab_sect && // Check that the sh_link connects to our symbol table
- curShdr->sh_info < ehdr->e_shnum && // Check that the relocated section exists
- (shdr[curShdr->sh_info].sh_flags & SHF_ALLOC)) { // Check if relocated section resides in memory
- if (!ShortsMan.inGeneralSegment((char *)shdr[curShdr->sh_info].sh_addr)) { // regular segment
- if (!relocate(fd, curShdr->sh_offset, curShdr->sh_size, _segment)) {
- return false;
- }
- } else { // In Shorts segment
- if (!relocate(fd, curShdr->sh_offset, curShdr->sh_size, (void *)_shortsSegment->getOffset())) {
- return false;
- }
- }
-
- }
- }
-
- return true;
-}
-
-
-bool DLObject::load(int fd) {
- DEBUG_ENTER_FUNC();
-
- Elf32_Ehdr ehdr; // ELF header
- Elf32_Phdr phdr; // Program header
- Elf32_Shdr *shdr; // Section header
- bool ret = true;
-
- if (readElfHeader(fd, &ehdr) == false) {
- return false;
- }
-
- for (int i = 0; i < ehdr.e_phnum; i++) { // Load our 2 segments
- PSP_DEBUG_PRINT("Loading segment %d\n", i);
-
- if (readProgramHeaders(fd, &ehdr, &phdr, i) == false)
- return false;
-
- if (!loadSegment(fd, &phdr))
- return false;
- }
-
- if ((shdr = loadSectionHeaders(fd, &ehdr)) == NULL)
- ret = false;
-
- if (ret && ((_symtab_sect = loadSymbolTable(fd, &ehdr, shdr)) < 0))
- ret = false;
-
- if (ret && (loadStringTable(fd, shdr) == false))
- ret = false;
-
- if (ret)
- relocateSymbols((Elf32_Addr)_segment, _shortsSegment->getOffset()); // Offset by our segment allocated address
-
- if (ret && (relocateRels(fd, &ehdr, shdr) == false))
- ret = false;
-
- free(shdr);
-
- return ret;
-}
-
-bool DLObject::open(const char *path) {
- DEBUG_ENTER_FUNC();
- int fd;
- void *ctors_start, *ctors_end;
-
- PSP_DEBUG_PRINT("open(\"%s\")\n", path);
-
- // Get the address of the global pointer
- _gpVal = (unsigned int) & _gp;
- PSP_DEBUG_PRINT("_gpVal is %x\n", _gpVal);
-
- PowerMan.beginCriticalSection();
-
- if ((fd = ::open(path, O_RDONLY)) < 0) {
- PSP_ERROR("%s not found.", path);
- return false;
- }
-
- // Try to load and relocate
- if (!load(fd)) {
- ::close(fd);
- unload();
- return false;
- }
-
- ::close(fd);
-
- PowerMan.endCriticalSection();
-
- // flush data cache
- sceKernelDcacheWritebackAll();
-
- // Get the symbols for the global constructors and destructors
- ctors_start = symbol("___plugin_ctors");
- ctors_end = symbol("___plugin_ctors_end");
- _dtors_start = symbol("___plugin_dtors");
- _dtors_end = symbol("___plugin_dtors_end");
-
- if (ctors_start == NULL || ctors_end == NULL || _dtors_start == NULL ||
- _dtors_end == NULL) {
- PSP_ERROR("Missing ctors/dtors.");
- _dtors_start = _dtors_end = NULL;
- unload();
- return false;
- }
-
- PSP_DEBUG_PRINT("Calling constructors.\n");
- for (void (**f)(void) = (void (**)(void))ctors_start; f != ctors_end; f++)
- (**f)();
-
- PSP_DEBUG_PRINT("%s opened ok.\n", path);
- return true;
-}
-
-bool DLObject::close() {
- DEBUG_ENTER_FUNC();
- if (_dtors_start != NULL && _dtors_end != NULL)
- for (void (**f)(void) = (void (**)(void))_dtors_start; f != _dtors_end; f++)
- (**f)();
- _dtors_start = _dtors_end = NULL;
- unload();
- return true;
-}
-
-void *DLObject::symbol(const char *name) {
- DEBUG_ENTER_FUNC();
- PSP_DEBUG_PRINT("symbol(\"%s\")\n", name);
-
- if (_symtab == NULL || _strtab == NULL || _symbol_cnt < 1) {
- PSP_ERROR("No symbol table loaded.");
- return NULL;
- }
-
- Elf32_Sym *s = (Elf32_Sym *)_symtab;
- for (int c = _symbol_cnt; c--; s++) {
-
- // 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) &&
- /*_strtab[s->st_name] == '_' && */ // Try to make this more efficient
- !strcmp(name, _strtab + s->st_name)) {
-
- // We found the symbol
- PSP_DEBUG_PRINT("=> %p\n", (void*)s->st_value);
- return (void*)s->st_value;
- }
- }
-
- PSP_ERROR("Symbol \"%s\" not found.", name);
- return NULL;
-}
-
-
-
-ShortSegmentManager::ShortSegmentManager() {
- DEBUG_ENTER_FUNC();
- _shortsStart = &__plugin_hole_start ;
- _shortsEnd = &__plugin_hole_end;
-}
-
-ShortSegmentManager::Segment *ShortSegmentManager::newSegment(int size, char *origAddr) {
- DEBUG_ENTER_FUNC();
- char *lastAddress = origAddr;
- Common::List<Segment *>::iterator i;
-
- // Find a block that fits, starting from the beginning
- for (i = _list.begin(); i != _list.end(); ++i) {
- char *currAddress = (*i)->getStart();
-
- if ((int)(currAddress - lastAddress) >= size) break;
-
- lastAddress = (*i)->getEnd();
- }
-
- if ((Elf32_Addr)lastAddress & 3)
- lastAddress += 4 - ((Elf32_Addr)lastAddress & 3); // Round up to multiple of 4
-
- if (lastAddress + size > _shortsEnd) {
- PSP_ERROR("No space in shorts segment for %x bytes. Last address is %p, max address is %p.\n",
- size, lastAddress, _shortsEnd);
- return NULL;
- }
-
- Segment *seg = new Segment(lastAddress, size, origAddr); // Create a new segment
-
- if (lastAddress + size > _highestAddress) _highestAddress = lastAddress + size; // Keep track of maximum
-
- _list.insert(i, seg);
-
- PSP_DEBUG_PRINT("Shorts segment size %x allocated. End = %p. Remaining space = %x. Highest so far is %p.\n",
- size, lastAddress + size, _shortsEnd - _list.back()->getEnd(), _highestAddress);
-
- return seg;
-}
-
-void ShortSegmentManager::deleteSegment(ShortSegmentManager::Segment *seg) {
- DEBUG_ENTER_FUNC();
- PSP_DEBUG_PRINT("Deleting shorts segment from %p to %p.\n\n", seg->getStart(), seg->getEnd());
- _list.remove(seg);
- delete seg;
-}
-
-static char dlerr[MAXDLERRLEN];
-
-void *dlopen(const char *filename, int flags) {
- DLObject *obj = new DLObject(dlerr);
- if (obj->open(filename))
- return (void *)obj;
- delete obj;
- return NULL;
-}
-
-int dlclose(void *handle) {
- DLObject *obj = (DLObject *)handle;
- if (obj == NULL) {
- strcpy(dlerr, "Handle is NULL.");
- return -1;
- }
- if (obj->close()) {
- delete obj;
- return 0;
- }
- return -1;
-}
-
-void *dlsym(void *handle, const char *symbol) {
- if (handle == NULL) {
- strcpy(dlerr, "Handle is NULL.");
- return NULL;
- }
- return ((DLObject *)handle)->symbol(symbol);
-}
-
-const char *dlerror() {
- return dlerr;
-}
-
-void dlforgetsyms(void *handle) {
- if (handle != NULL)
- ((DLObject *)handle)->discard_symtab();
-}
-
-
-#endif /* DYNAMIC_MODULES && __PSP__ */
diff --git a/backends/platform/psp/psploader.h b/backends/platform/psp/psploader.h
deleted file mode 100644
index 13dcf6ef98..0000000000
--- a/backends/platform/psp/psploader.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * 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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#ifndef PSPLOADER_H
-#define PSPLOADER_H
-
-#include "elf32.h"
-#include "common/list.h"
-#include "common/singleton.h"
-
-#define MAXDLERRLEN 80
-
-#define ShortsMan ShortSegmentManager::instance()
-
-class ShortSegmentManager : public Common::Singleton<ShortSegmentManager> {
-private:
- char *_shortsStart;
- char *_shortsEnd;
-
-public:
- char *getShortsStart() {
- return _shortsStart;
- }
- bool inGeneralSegment(char *addr) {
- return ((char *)addr >= _shortsStart && (char *)addr < _shortsEnd);
- }
-
- class Segment {
- private:
- friend class ShortSegmentManager;
- Segment(char *start, int size, char *origAddr) : _startAddress(start), _size(size), _origAddress(origAddr) {}
- ~Segment() {}
- char *_startAddress; // Start of shorts segment in memory
- int _size; // Size of shorts segment
- char *_origAddress; // Original address this segment was supposed to be at
- public:
- char *getStart() {
- return _startAddress;
- }
- char *getEnd() {
- return (_startAddress + _size);
- }
- Elf32_Addr getOffset() {
- return (Elf32_Addr)(_startAddress - _origAddress);
- }
- bool inSegment(char *addr) {
- return ((char *)addr >= _startAddress && (char *)addr <= _startAddress + _size);
- }
- };
-
- Segment *newSegment(int size, char *origAddr);
- void deleteSegment(Segment *);
-
-private:
- ShortSegmentManager();
- friend class Common::Singleton<ShortSegmentManager>;
- Common::List<Segment *> _list;
- char *_highestAddress;
-};
-
-
-
-
-class DLObject {
-protected:
- char *_errbuf; /* For error messages, at least MAXDLERRLEN in size */
-
- ShortSegmentManager::Segment *_shortsSegment; // For assigning shorts ranges
- void *_segment, *_symtab;
- char *_strtab;
- int _symbol_cnt;
- int _symtab_sect;
- void *_dtors_start, *_dtors_end;
-
- unsigned int _gpVal; // Value of Global Pointer
- int _segmentSize;
-
- void seterror(const char *fmt, ...);
- void unload();
- bool relocate(int fd, unsigned long offset, unsigned long size, void *);
- bool load(int fd);
-
- bool readElfHeader(int fd, Elf32_Ehdr *ehdr);
- bool readProgramHeaders(int fd, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, int num);
- bool loadSegment(int fd, Elf32_Phdr *phdr);
- Elf32_Shdr *loadSectionHeaders(int fd, Elf32_Ehdr *ehdr);
- int loadSymbolTable(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr);
- bool loadStringTable(int fd, Elf32_Shdr *shdr);
- void relocateSymbols(Elf32_Addr offset, Elf32_Addr shortsOffset);
- bool relocateRels(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr);
-
-public:
- bool open(const char *path);
- bool close();
- void *symbol(const char *name);
- void discard_symtab();
-
- DLObject(char *errbuf = NULL) : _errbuf(_errbuf), _shortsSegment(NULL), _segment(NULL), _symtab(NULL),
- _strtab(NULL), _symbol_cnt(0), _symtab_sect(-1), _dtors_start(NULL), _dtors_end(NULL), _gpVal(0) ,
- _segmentSize(0) {}
-};
-
-
-
-#define RTLD_LAZY 0
-
-extern "C" {
- void *dlopen(const char *filename, int flags);
- int dlclose(void *handle);
- void *dlsym(void *handle, const char *symbol);
- const char *dlerror();
- void dlforgetsyms(void *handle);
-}
-
-#endif /* PSPLOADER_H */
diff --git a/backends/platform/wii/main.cpp b/backends/platform/wii/main.cpp
index 7f141f2339..aa688534fc 100644
--- a/backends/platform/wii/main.cpp
+++ b/backends/platform/wii/main.cpp
@@ -25,6 +25,7 @@
#include <unistd.h>
#include "osystem.h"
+#include "backends/plugins/wii/wii-provider.h"
#include <ogc/machine/processor.h>
#include <fat.h>
@@ -210,6 +211,10 @@ int main(int argc, char *argv[]) {
g_system = new OSystem_Wii();
assert(g_system);
+#ifdef DYNAMIC_MODULES
+ PluginManager::instance().addPluginProvider(new WiiPluginProvider());
+#endif
+
res = scummvm_main(argc, argv);
g_system->quit();
diff --git a/backends/platform/wii/wii.mk b/backends/platform/wii/wii.mk
index c1512551d7..28066df8d4 100644
--- a/backends/platform/wii/wii.mk
+++ b/backends/platform/wii/wii.mk
@@ -32,6 +32,10 @@ else
$(CP) $(srcdir)/dists/wii/icon.png wiidist/scummvm/
sed "s/@REVISION@/$(VER_SVNREV)/;s/@TIMESTAMP@/`date +%Y%m%d%H%M%S`/" < $(srcdir)/dists/wii/meta.xml > wiidist/scummvm/meta.xml
endif
+ifeq ($(DYNAMIC_MODULES),1)
+ $(MKDIR) wiidist/scummvm/plugins
+ for i in $(PLUGINS); do $(STRIP) --strip-debug $$i -o wiidist/scummvm/plugins/`basename $$i`; done
+endif
sed 's/$$/\r/' < $(srcdir)/dists/wii/READMII > wiidist/scummvm/READMII.txt
for i in $(DIST_FILES_DOCS); do sed 's/$$/\r/' < $$i > wiidist/scummvm/`basename $$i`.txt; done
$(CP) $(DIST_FILES_THEMES) wiidist/scummvm/
diff --git a/backends/plugins/ds/ds-provider.cpp b/backends/plugins/ds/ds-provider.cpp
index 2995a4d0e7..c188b6c9df 100644
--- a/backends/plugins/ds/ds-provider.cpp
+++ b/backends/plugins/ds/ds-provider.cpp
@@ -1 +1,75 @@
-dummy \ No newline at end of file
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(DYNAMIC_MODULES) && defined(__DS__)
+
+#include <malloc.h>
+#include <nds.h>
+
+#include "backends/plugins/ds/ds-provider.h"
+#include "backends/plugins/elf/arm-loader.h"
+
+class DSDLObject : public ARMDLObject {
+public:
+ DSDLObject() :
+ ARMDLObject() {
+ }
+
+ virtual ~DSDLObject() {
+ unload();
+ }
+
+protected:
+ virtual void *allocSegment(size_t boundary, size_t size) const {
+ return memalign(boundary, size);
+ }
+
+ virtual void freeSegment(void *segment) const {
+ free(segment);
+ }
+
+ virtual void flushDataCache(void *ptr, uint32 len) const {
+ DC_FlushRange(ptr, len);
+ IC_InvalidateRange(ptr, len);
+ }
+};
+
+class DSPlugin : public ELFPlugin {
+public:
+ DSPlugin(const Common::String &filename) :
+ ELFPlugin(filename) {
+ }
+
+ virtual DLObject *makeDLObject() {
+ return new DSDLObject();
+ }
+};
+
+Plugin *DSPluginProvider::createPlugin(const Common::FSNode &node) const {
+ return new DSPlugin(node.getPath());
+}
+
+#endif // defined(DYNAMIC_MODULES) && defined(__DS__)
+
diff --git a/backends/plugins/ds/ds-provider.h b/backends/plugins/ds/ds-provider.h
index 5692c8a07b..dcb93c085f 100644
--- a/backends/plugins/ds/ds-provider.h
+++ b/backends/plugins/ds/ds-provider.h
@@ -1 +1,41 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(DYNAMIC_MODULES) && defined(__DS__)
+
+#ifndef BACKENDS_PLUGINS_DS_PROVIDER_H
+#define BACKENDS_PLUGINS_DS_PROVIDER_H
+
+#include "backends/plugins/elf/elf-provider.h"
+
+class DSPluginProvider : public ELFPluginProvider {
+public:
+ Plugin *createPlugin(const Common::FSNode &node) const;
+};
+
+#endif // BACKENDS_PLUGINS_DS_PROVIDER_H
+
+#endif // defined(DYNAMIC_MODULES) && defined(__DS__)
+
diff --git a/backends/plugins/ds/plugin.ld b/backends/plugins/ds/plugin.ld
index 5692c8a07b..04035b0169 100644
--- a/backends/plugins/ds/plugin.ld
+++ b/backends/plugins/ds/plugin.ld
@@ -1 +1,217 @@
-dummy
+OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+
+/* PHDRS specifies ELF Program Headers (or segments) to the plugin linker */
+PHDRS {
+ plugin PT_LOAD ; /* Specifies that the plugin segment should be loaded from file */
+}
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = 0;
+ .interp : { *(.interp) } : plugin
+ .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.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 = .);
+ PROVIDE_HIDDEN (__rela_iplt_start = .);
+ PROVIDE_HIDDEN (__rela_iplt_end = .);
+ }
+ .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 (__rel_iplt_start = .);
+ PROVIDE_HIDDEN (__rel_iplt_end = .);
+ PROVIDE_HIDDEN (__rela_iplt_start = .);
+ *(.rela.iplt)
+ PROVIDE_HIDDEN (__rela_iplt_end = .);
+ }
+ .rel.plt :
+ {
+ *(.rel.plt)
+ }
+ .rela.plt :
+ {
+ *(.rela.plt)
+ }
+ .init :
+ {
+ KEEP (*(.init))
+ } =0
+ .plt : { *(.plt) }
+ .iplt : { *(.iplt) }
+ .text :
+ {
+ *(.text.unlikely .text.*_unlikely)
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx)
+ } =0
+ .fini :
+ {
+ KEEP (*(.fini))
+ } =0
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+ .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) }
+ __exidx_start = .;
+ .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) }
+ __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.*) }
+ /* 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.*) }
+ /* 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 (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ }
+ .ctors :
+ {
+ ___plugin_ctors = .;
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ ___plugin_ctors_end = .;
+ }
+ .dtors :
+ {
+ ___plugin_dtors = .;
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ ___plugin_dtors_end = .;
+ }
+ .jcr : { KEEP (*(.jcr)) }
+ .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.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);
+ . = 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_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) }
+ .stack 0x80000 :
+ {
+ _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/backends/plugins/elf/arm-loader.cpp b/backends/plugins/elf/arm-loader.cpp
index 5692c8a07b..93d3c60f84 100644
--- a/backends/plugins/elf/arm-loader.cpp
+++ b/backends/plugins/elf/arm-loader.cpp
@@ -1 +1,133 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/scummsys.h"
+
+#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(ARM_TARGET)
+
+#include "backends/plugins/elf/arm-loader.h"
+
+#include "common/debug.h"
+
+bool ARMDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment) {
+ Elf32_Rel *rel = 0; //relocation entry
+
+ // Allocate memory for relocation table
+ if (!(rel = (Elf32_Rel *)malloc(size))) {
+ warning("elfloader: Out of memory.");
+ return false;
+ }
+
+ // Read in our relocation table
+ if (!_file->seek(offset, SEEK_SET) || _file->read(rel, size) != size) {
+ warning("elfloader: Relocation table load failed.");
+ free(rel);
+ return false;
+ }
+
+ // Treat each relocation entry. Loop over all of them
+ uint32 cnt = size / sizeof(*rel);
+
+ debug(2, "elfloader: Loaded relocation table. %d entries. base address=%p", cnt, relSegment);
+
+ int32 a = 0;
+ uint32 relocation = 0;
+
+ // Loop over relocation entries
+ for (uint32 i = 0; i < cnt; i++) {
+ // Get the symbol this relocation entry is referring to
+ Elf32_Sym *sym = _symtab + (REL_INDEX(rel[i].r_info));
+
+ // Get the target instruction in the code. TODO: repect _segmentVMA
+ uint32 *target = (uint32 *)((byte *)relSegment + rel[i].r_offset);
+
+ uint32 origTarget = *target; //Save for debugging
+
+ // Act differently based on the type of relocation
+ 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
+
+ *target = relocation;
+
+ debug(8, "elfloader: R_ARM_ABS32: i=%d, a=%x, origTarget=%x, target=%x", i, a, origTarget, *target);
+ }
+ break;
+
+ case R_ARM_THM_CALL:
+ debug(8, "elfloader: R_ARM_THM_CALL: PC-relative jump, ld takes care of necessary relocation work for us.");
+ break;
+
+ case R_ARM_CALL:
+ debug(8, "elfloader: R_ARM_CALL: PC-relative jump, ld takes care of necessary relocation work for us.");
+ break;
+
+ case R_ARM_JUMP24:
+ debug(8, "elfloader: R_ARM_JUMP24: PC-relative jump, ld takes care of all relocation work for us.");
+ break;
+
+ case R_ARM_V4BX:
+ debug(8, "elfloader: R_ARM_V4BX: No relocation calculation necessary.");
+ break;
+
+ default:
+ warning("elfloader: Unknown relocation type %d.", REL_TYPE(rel[i].r_info));
+ free(rel);
+ return false;
+ }
+ }
+
+ free(rel);
+ return true;
+}
+
+bool ARMDLObject::relocateRels(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
+ // Loop over sections, finding relocation sections
+ for (uint32 i = 0; i < ehdr->e_shnum; i++) {
+ Elf32_Shdr *curShdr = &(shdr[i]);
+
+ if ((curShdr->sh_type == SHT_REL || curShdr->sh_type == SHT_RELA) && // Check for a relocation section
+ curShdr->sh_entsize == sizeof(Elf32_Rel) && // Check for proper relocation size
+ int32(curShdr->sh_link) == _symtab_sect && // Check that the sh_link connects to our symbol table
+ curShdr->sh_info < ehdr->e_shnum && // Check that the relocated section exists
+ (shdr[curShdr->sh_info].sh_flags & SHF_ALLOC)) { // Check if relocated section resides in memory
+
+ if (curShdr->sh_type == SHT_RELA) {
+ warning("elfloader: RELA entries not supported yet!");
+ return false;
+ }
+
+ if (!relocate(curShdr->sh_offset, curShdr->sh_size, _segment))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(ARM_TARGET) */
+
diff --git a/backends/plugins/elf/arm-loader.h b/backends/plugins/elf/arm-loader.h
index 5692c8a07b..e08f8cd0a5 100644
--- a/backends/plugins/elf/arm-loader.h
+++ b/backends/plugins/elf/arm-loader.h
@@ -1 +1,49 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef BACKENDS_PLUGINS_ARM_LOADER_H
+#define BACKENDS_PLUGINS_ARM_LOADER_H
+
+#include "common/scummsys.h"
+
+#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(ARM_TARGET)
+
+#include "backends/plugins/elf/elf-loader.h"
+
+class ARMDLObject : public DLObject {
+protected:
+ virtual bool relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment);
+ virtual bool relocateRels(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr);
+
+public:
+ ARMDLObject() :
+ DLObject() {
+ }
+};
+
+#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(ARM_TARGET) */
+
+#endif /* BACKENDS_PLUGINS_ARM_LOADER_H */
+
diff --git a/backends/plugins/elf/elf-loader.cpp b/backends/plugins/elf/elf-loader.cpp
index 5692c8a07b..17a67f4d02 100644
--- a/backends/plugins/elf/elf-loader.cpp
+++ b/backends/plugins/elf/elf-loader.cpp
@@ -1 +1,429 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/scummsys.h"
+
+#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER)
+
+#include "backends/plugins/elf/elf-loader.h"
+
+#include "common/debug.h"
+#include "common/file.h"
+#include "common/fs.h"
+#include "common/ptr.h"
+
+DLObject::DLObject() :
+ _file(0),
+ _segment(0),
+ _symtab(0),
+ _strtab(0),
+ _segmentSize(0),
+ _segmentOffset(0),
+ _segmentVMA(0),
+ _symbol_cnt(0),
+ _symtab_sect(-1),
+ _dtors_start(0),
+ _dtors_end(0) {
+}
+
+DLObject::~DLObject() {
+}
+
+// Expel the symbol table from memory
+void DLObject::discard_symtab() {
+ free(_symtab);
+ _symtab = 0;
+
+ free(_strtab);
+ _strtab = 0;
+
+ _symbol_cnt = 0;
+}
+
+// Unload all objects from memory
+void DLObject::unload() {
+ discard_symtab();
+
+ freeSegment(_segment);
+
+ _segment = 0;
+ _segmentSize = 0;
+ _segmentOffset = 0;
+ _segmentVMA = 0;
+}
+
+bool DLObject::readElfHeader(Elf32_Ehdr *ehdr) {
+ assert(_file);
+
+ // Start reading the elf header. Check for errors and magic
+ if (_file->read(ehdr, sizeof(*ehdr)) != sizeof(*ehdr) ||
+ memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
+ warning("elfloader: No ELF file.");
+ return false;
+ }
+
+ if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
+ warning("elfloader: Wrong ELF file class.");
+ return false;
+ }
+
+ if (ehdr->e_ident[EI_DATA] !=
+#ifdef SCUMM_BIG_ENDIAN
+ ELFDATA2MSB
+#else
+ ELFDATA2LSB
+#endif
+ ) {
+ warning("elfloader: Wrong ELF file endianess.");
+ return false;
+ }
+
+ if (ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
+ warning("elfloader: Wrong ELF file version.");
+ return false;
+ }
+
+ if (ehdr->e_type != ET_EXEC) {
+ warning("elfloader: No executable ELF file.");
+ return false;
+ }
+
+ if (ehdr->e_machine !=
+#ifdef ARM_TARGET
+ EM_ARM
+#endif
+#ifdef MIPS_TARGET
+ EM_MIPS
+#endif
+#ifdef PPC_TARGET
+ EM_PPC
+#endif
+ ) {
+ warning("elfloader: Wrong ELF file architecture.");
+ return false;
+ }
+
+ if (ehdr->e_phentsize < sizeof(Elf32_Phdr) || // Check for size of program header
+ ehdr->e_shentsize != sizeof(Elf32_Shdr)) { // Check for size of section header
+ warning("elfloader: Invalid ELF structure sizes.");
+ return false;
+ }
+
+ debug(2, "elfloader: phoff = %d, phentsz = %d, phnum = %d",
+ ehdr->e_phoff, ehdr->e_phentsize, ehdr->e_phnum);
+
+ return true;
+}
+
+bool DLObject::readProgramHeaders(Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, Elf32_Half num) {
+ assert(_file);
+
+ // Read program header
+ if (!_file->seek(ehdr->e_phoff + sizeof(*phdr) * num, SEEK_SET) ||
+ _file->read(phdr, sizeof(*phdr)) != sizeof(*phdr)) {
+ warning("elfloader: Program header load failed.");
+ return false;
+ }
+
+ // Check program header values
+ if (phdr->p_type != PT_LOAD || phdr->p_filesz > phdr->p_memsz) {
+ warning("elfloader: Invalid program header.");
+ return false;
+ }
+
+ debug(2, "elfloader: offs = %x, filesz = %x, memsz = %x, align = %x",
+ phdr->p_offset, phdr->p_filesz, phdr->p_memsz, phdr->p_align);
+
+ return true;
+}
+
+bool DLObject::loadSegment(Elf32_Phdr *phdr) {
+ _segment = (byte *)allocSegment(phdr->p_align, phdr->p_memsz);
+
+ if (!_segment) {
+ warning("elfloader: Out of memory.");
+ return false;
+ }
+
+ debug(2, "elfloader: Allocated segment @ %p", _segment);
+
+ // Get offset to load segment into
+ _segmentSize = phdr->p_memsz;
+ _segmentVMA = phdr->p_vaddr;
+
+ // Set .bss segment to 0 if necessary
+ if (phdr->p_memsz > phdr->p_filesz) {
+ debug(2, "elfloader: Setting %p to %p to 0 for bss",
+ _segment + phdr->p_filesz, _segment + phdr->p_memsz);
+ memset(_segment + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz);
+ }
+
+ debug(2, "elfloader: Reading the segment into memory");
+
+ // Read the segment into memory
+ if (!_file->seek(phdr->p_offset, SEEK_SET) ||
+ _file->read(_segment, phdr->p_filesz) != phdr->p_filesz) {
+ warning("elfloader: Segment load failed.");
+ return false;
+ }
+
+ debug(2, "elfloader: Segment has been read into memory");
+
+ return true;
+}
+
+Elf32_Shdr * DLObject::loadSectionHeaders(Elf32_Ehdr *ehdr) {
+ assert(_file);
+
+ Elf32_Shdr *shdr = 0;
+
+ // Allocate memory for section headers
+ if (!(shdr = (Elf32_Shdr *)malloc(ehdr->e_shnum * sizeof(*shdr)))) {
+ warning("elfloader: Out of memory.");
+ return 0;
+ }
+
+ // Read from file into section headers
+ if (!_file->seek(ehdr->e_shoff, SEEK_SET) ||
+ _file->read(shdr, ehdr->e_shnum * sizeof(*shdr)) !=
+ ehdr->e_shnum * sizeof(*shdr)) {
+ warning("elfloader: Section headers load failed.");
+ free(shdr);
+ return 0;
+ }
+
+ return shdr;
+}
+
+int DLObject::loadSymbolTable(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
+ assert(_file);
+
+ // Loop over sections, looking for symbol table linked to a string table
+ for (uint32 i = 0; i < ehdr->e_shnum; i++) {
+ if (shdr[i].sh_type == SHT_SYMTAB &&
+ shdr[i].sh_entsize == sizeof(Elf32_Sym) &&
+ shdr[i].sh_link < ehdr->e_shnum &&
+ shdr[shdr[i].sh_link].sh_type == SHT_STRTAB &&
+ _symtab_sect < 0) {
+ _symtab_sect = i;
+ }
+ }
+
+ // Check for no symbol table
+ if (_symtab_sect < 0) {
+ warning("elfloader: No symbol table.");
+ return -1;
+ }
+
+ debug(2, "elfloader: Symbol section at section %d, size %x",
+ _symtab_sect, shdr[_symtab_sect].sh_size);
+
+ // Allocate memory for symbol table
+ if (!(_symtab = (Elf32_Sym *)malloc(shdr[_symtab_sect].sh_size))) {
+ warning("elfloader: Out of memory.");
+ return -1;
+ }
+
+ // Read symbol table into memory
+ if (!_file->seek(shdr[_symtab_sect].sh_offset, SEEK_SET) ||
+ _file->read(_symtab, shdr[_symtab_sect].sh_size) !=
+ shdr[_symtab_sect].sh_size) {
+ warning("elfloader: Symbol table load failed.");
+ free(_symtab);
+ _symtab = 0;
+ return -1;
+ }
+
+ // Set number of symbols
+ _symbol_cnt = shdr[_symtab_sect].sh_size / sizeof(Elf32_Sym);
+ debug(2, "elfloader: Loaded %d symbols.", _symbol_cnt);
+
+ return _symtab_sect;
+}
+
+bool DLObject::loadStringTable(Elf32_Shdr *shdr) {
+ assert(_file);
+
+ uint32 string_sect = shdr[_symtab_sect].sh_link;
+
+ // Allocate memory for string table
+ if (!(_strtab = (char *)malloc(shdr[string_sect].sh_size))) {
+ warning("elfloader: Out of memory.");
+ return false;
+ }
+
+ // Read string table into memory
+ if (!_file->seek(shdr[string_sect].sh_offset, SEEK_SET) ||
+ _file->read(_strtab, shdr[string_sect].sh_size) !=
+ shdr[string_sect].sh_size) {
+ warning("elfloader: Symbol table strings load failed.");
+ free(_strtab);
+ _strtab = 0;
+ return false;
+ }
+
+ return true;
+}
+
+void DLObject::relocateSymbols(ptrdiff_t offset) {
+ // Loop over symbols, add relocation offset
+ Elf32_Sym *s = _symtab;
+
+ for (uint32 c = _symbol_cnt; c--; s++) {
+ // Make sure we don't relocate special valued symbols
+ if (s->st_shndx < SHN_LOPROC) {
+ s->st_value += offset;
+
+ if (s->st_value < Elf32_Addr(_segment) ||
+ s->st_value > Elf32_Addr(_segment) + _segmentSize)
+ warning("elfloader: Symbol out of bounds! st_value = %x", s->st_value);
+ }
+ }
+}
+
+bool DLObject::load() {
+ Elf32_Ehdr ehdr;
+ Elf32_Phdr phdr;
+
+ if (readElfHeader(&ehdr) == false)
+ return false;
+
+ for (uint32 i = 0; i < ehdr.e_phnum; i++) { //Load our segments
+ debug(2, "elfloader: Loading segment %d", i);
+
+ if (readProgramHeaders(&ehdr, &phdr, i) == false)
+ return false;
+
+ if (!loadSegment(&phdr))
+ return false;
+ }
+
+ Common::ScopedPtrC<Elf32_Shdr> shdr(loadSectionHeaders(&ehdr));
+ if (!shdr)
+ return false;
+
+ _symtab_sect = loadSymbolTable(&ehdr, shdr);
+ if (_symtab_sect < 0)
+ return false;
+
+ if (!loadStringTable(shdr))
+ return false;
+
+ // Offset by our segment allocated address
+ // must use _segmentVMA here for multiple segments (MIPS)
+ _segmentOffset = ptrdiff_t(_segment) - _segmentVMA;
+ relocateSymbols(_segmentOffset);
+
+ if (!relocateRels(&ehdr, shdr))
+ return false;
+
+ return true;
+}
+
+bool DLObject::open(const char *path) {
+ void *ctors_start, *ctors_end;
+
+ debug(2, "elfloader: open(\"%s\")", path);
+
+ _file = Common::FSNode(path).createReadStream();
+
+ if (!_file) {
+ warning("elfloader: File %s not found.", path);
+ return false;
+ }
+
+ debug(2, "elfloader: %s found!", path);
+
+ /*Try to load and relocate*/
+ if (!load()) {
+ unload();
+ return false;
+ }
+
+ debug(2, "elfloader: Loaded!");
+
+ delete _file;
+ _file = 0;
+
+ flushDataCache(_segment, _segmentSize);
+
+ ctors_start = symbol("___plugin_ctors");
+ ctors_end = symbol("___plugin_ctors_end");
+ _dtors_start = symbol("___plugin_dtors");
+ _dtors_end = symbol("___plugin_dtors_end");
+
+ if (!ctors_start || !ctors_end || !_dtors_start || !_dtors_end) {
+ warning("elfloader: Missing ctors/dtors.");
+ _dtors_start = _dtors_end = 0;
+ unload();
+ return false;
+ }
+
+ debug(2, "elfloader: Calling constructors.");
+ for (void (**f)(void) = (void (**)(void))ctors_start; f != ctors_end; f++)
+ (**f)();
+
+ debug(2, "elfloader: %s opened ok.", path);
+
+ return true;
+}
+
+bool DLObject::close() {
+ if (_dtors_start && _dtors_end)
+ for (void (**f)(void) = (void (**)(void))_dtors_start; f != _dtors_end; f++)
+ (**f)();
+
+ _dtors_start = _dtors_end = 0;
+ unload();
+ return true;
+}
+
+void *DLObject::symbol(const char *name) {
+ debug(2, "elfloader: Symbol(\"%s\")", name);
+
+ if (!_symtab || !_strtab || _symbol_cnt < 1) {
+ warning("elfloader: No symbol table loaded.");
+ return 0;
+ }
+
+ Elf32_Sym *s = _symtab;
+
+ for (uint32 c = _symbol_cnt; c--; s++)
+ // 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
+ debug(2, "elfloader: => 0x%08x", s->st_value);
+ return (void*)s->st_value;
+ }
+
+ // We didn't find the symbol
+ warning("elfloader: Symbol \"%s\" not found.", name);
+ return 0;
+}
+
+#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) */
+
diff --git a/backends/plugins/elf/elf-loader.h b/backends/plugins/elf/elf-loader.h
index 5692c8a07b..87907d67c9 100644
--- a/backends/plugins/elf/elf-loader.h
+++ b/backends/plugins/elf/elf-loader.h
@@ -1 +1,104 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef BACKENDS_PLUGINS_ELF_LOADER_H
+#define BACKENDS_PLUGINS_ELF_LOADER_H
+
+#include "common/scummsys.h"
+
+#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER)
+
+#include <stddef.h>
+
+#include "backends/plugins/elf/elf32.h"
+#include "backends/plugins/dynamic-plugin.h"
+
+#include "common/stream.h"
+
+/**
+ * DLObject
+ *
+ * Class that most directly handles operations on a plugin file
+ * (opening it for reading, loading/unloading it in memory, finding a specific symbol in the file, etc.)
+ * Subclasses have the same functionality, but implementations specific to different processors/platforms.
+ */
+class DLObject {
+protected:
+ Common::SeekableReadStream *_file;
+
+ byte *_segment;
+ Elf32_Sym *_symtab;
+ char *_strtab;
+
+ uint32 _segmentSize;
+ ptrdiff_t _segmentOffset;
+ uint32 _segmentVMA;
+
+ uint32 _symbol_cnt;
+ int32 _symtab_sect;
+ void *_dtors_start, *_dtors_end;
+
+ virtual void unload();
+ bool load();
+
+ bool readElfHeader(Elf32_Ehdr *ehdr);
+ bool readProgramHeaders(Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, Elf32_Half num);
+ virtual bool loadSegment(Elf32_Phdr *phdr);
+ Elf32_Shdr *loadSectionHeaders(Elf32_Ehdr *ehdr);
+ int loadSymbolTable(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr);
+ bool loadStringTable(Elf32_Shdr *shdr);
+ virtual void relocateSymbols(ptrdiff_t offset);
+
+ // architecture specific
+
+ /**
+ * Follow the instruction of a relocation section.
+ *
+ * @param fileOffset Offset into the File
+ * @param size Size of relocation section
+ * @param relSegment Base address of relocated segment in memory (memory offset)
+ */
+ virtual bool relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment) = 0;
+ virtual bool relocateRels(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) = 0;
+
+ // platform specific
+ virtual void *allocSegment(size_t boundary, size_t size) const = 0;
+ virtual void freeSegment(void *segment) const = 0;
+ virtual void flushDataCache(void *ptr, uint32 len) const = 0;
+
+public:
+ DLObject();
+ virtual ~DLObject();
+
+ bool open(const char *path);
+ bool close();
+ void *symbol(const char *name);
+ void discard_symtab();
+};
+
+#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) */
+
+#endif /* BACKENDS_PLUGINS_ELF_LOADER_H */
+
diff --git a/backends/plugins/elf/elf-provider.cpp b/backends/plugins/elf/elf-provider.cpp
index 5692c8a07b..d1c8f6aa05 100644
--- a/backends/plugins/elf/elf-provider.cpp
+++ b/backends/plugins/elf/elf-provider.cpp
@@ -1 +1,177 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/scummsys.h"
+
+#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER)
+
+#ifdef ELF_LOADER_CXA_ATEXIT
+#include <cxxabi.h>
+#endif
+
+#include "backends/plugins/elf/elf-provider.h"
+#include "backends/plugins/dynamic-plugin.h"
+
+#include "common/debug.h"
+#include "common/fs.h"
+
+/* Note about ELF_LOADER_CXA_ATEXIT:
+ *
+ * consider the code:
+ *
+ * class Foobar {
+ * const char *work() {
+ * static String foo = "bar";
+ * return s.c_str();
+ * }
+ * }
+ *
+ * When instantiating Foobar and calling work() for the first time the String
+ * foo will be constructed. GCC automatically registers its destruction via
+ * either atexit() or __cxa_atexit(). Only the latter will add information
+ * about which DSO did the construction (Using &__dso_handle).
+ *
+ * __cxa_atexit allows plugins to reference C++ ABI symbols in the main
+ * executable without code duplication (No need to link the plugin against
+ * libstdc++), since we can distinguish which registered exit functions belong
+ * to a specific DSO. When unloading a plugin, we just use the C++ ABI call
+ * __cxa_finalize(&__dso_handle) to call all destructors of only that DSO.
+ *
+ * Prerequisites:
+ * - The used libc needs to support __cxa_atexit
+ * - -fuse-cxa-atexit in CXXFLAGS
+ * - Every plugin needs its own hidden __dso_handle symbol
+ * This is automatically done via REGISTER_PLUGIN_DYNAMIC, see base/plugins.h
+ *
+ * When __cxa_atexit can not be used, each plugin needs to link against
+ * libstdc++ to embed its own set of C++ ABI symbols. When not doing so,
+ * registered destructors of already unloaded plugins will crash the
+ * application upon returning from main().
+ *
+ * See "3.3.5 DSO Object Destruction API" of the C++ ABI
+ */
+
+DynamicPlugin::VoidFunc ELFPlugin::findSymbol(const char *symbol) {
+ void *func = 0;
+
+ if (_dlHandle)
+ func = _dlHandle->symbol(symbol);
+
+ if (!func) {
+ if (!_dlHandle)
+ warning("elfloader: Failed loading symbol '%s' from plugin '%s' (Handle is NULL)", symbol, _filename.c_str());
+ else
+ warning("elfloader: Failed loading symbol '%s' from plugin '%s'", symbol, _filename.c_str());
+ }
+
+ // FIXME HACK: This is a HACK to circumvent a clash between the ISO C++
+ // standard and POSIX: ISO C++ disallows casting between function pointers
+ // and data pointers, but dlsym always returns a void pointer. For details,
+ // see e.g. <http://www.trilithium.com/johan/2004/12/problem-with-dlsym/>.
+ assert(sizeof(VoidFunc) == sizeof(func));
+ VoidFunc tmp;
+ memcpy(&tmp, &func, sizeof(VoidFunc));
+ return tmp;
+}
+
+bool ELFPlugin::loadPlugin() {
+ assert(!_dlHandle);
+
+ DLObject *obj = makeDLObject();
+ if (obj->open(_filename.c_str())) {
+ _dlHandle = obj;
+ } else {
+ delete obj;
+ _dlHandle = 0;
+ }
+
+ if (!_dlHandle) {
+ warning("elfloader: Failed loading plugin '%s'", _filename.c_str());
+ return false;
+ }
+
+ CharFunc buildDateFunc = (CharFunc)findSymbol("PLUGIN_getBuildDate");
+ if (!buildDateFunc) {
+ unloadPlugin();
+ warning("elfloader: plugin '%s' is missing symbols", _filename.c_str());
+ return false;
+ }
+
+ if (strncmp(gScummVMPluginBuildDate, buildDateFunc(), strlen(gScummVMPluginBuildDate))) {
+ unloadPlugin();
+ warning("elfloader: plugin '%s' has a different build date", _filename.c_str());
+ return false;
+ }
+
+ bool ret = DynamicPlugin::loadPlugin();
+
+#ifdef ELF_LOADER_CXA_ATEXIT
+ if (ret) {
+ // FIXME HACK: Reverse HACK of findSymbol() :P
+ VoidFunc tmp;
+ tmp = findSymbol("__dso_handle");
+ memcpy(&_dso_handle, &tmp, sizeof(VoidFunc));
+ debug(2, "elfloader: __dso_handle is %p", _dso_handle);
+ }
+#endif
+
+ _dlHandle->discard_symtab();
+
+ return ret;
+}
+
+void ELFPlugin::unloadPlugin() {
+ DynamicPlugin::unloadPlugin();
+
+ if (_dlHandle) {
+#ifdef ELF_LOADER_CXA_ATEXIT
+ if (_dso_handle) {
+ debug(2, "elfloader: calling __cxa_finalize");
+ __cxxabiv1::__cxa_finalize(_dso_handle);
+ _dso_handle = 0;
+ }
+#endif
+
+ if (!_dlHandle->close())
+ warning("elfloader: Failed unloading plugin '%s'", _filename.c_str());
+
+ delete _dlHandle;
+ _dlHandle = 0;
+ }
+}
+
+bool ELFPluginProvider::isPluginFilename(const Common::FSNode &node) const {
+ // Check the plugin suffix
+ Common::String filename = node.getName();
+
+ if (!filename.hasSuffix(".PLG") && !filename.hasSuffix(".plg") &&
+ !filename.hasSuffix(".PLUGIN") && !filename.hasSuffix(".plugin"))
+ return false;
+
+ return true;
+}
+
+#endif // defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER)
+
diff --git a/backends/plugins/elf/elf-provider.h b/backends/plugins/elf/elf-provider.h
index 5692c8a07b..0309ffcece 100644
--- a/backends/plugins/elf/elf-provider.h
+++ b/backends/plugins/elf/elf-provider.h
@@ -1 +1,84 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef BACKENDS_PLUGINS_ELF_PROVIDER_H
+#define BACKENDS_PLUGINS_ELF_PROVIDER_H
+
+#include "common/scummsys.h"
+
+#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER)
+
+#include "backends/plugins/elf/elf-loader.h"
+
+#include "common/fs.h"
+
+/**
+ * ELFPlugin
+ *
+ * Objects of this class are returned when the PluginManager calls
+ * getPlugins() on an ELFPluginProvider. An intermediary class for
+ * dealing with plugin files, ELFPlugin is responsible for creating/destroying
+ * a DLObject that handles the opening/loading/unloading of the plugin file whose
+ * path in the target backend's file system is "_filename".
+ */
+class ELFPlugin : public DynamicPlugin {
+protected:
+ typedef const char *(*CharFunc)();
+
+ DLObject *_dlHandle;
+ Common::String _filename;
+ void *_dso_handle;
+
+ virtual VoidFunc findSymbol(const char *symbol);
+
+public:
+ ELFPlugin(const Common::String &filename) :
+ _dlHandle(0),
+ _filename(filename),
+ _dso_handle(0) {
+ }
+
+ virtual ~ELFPlugin() {
+ if (_dlHandle)
+ unloadPlugin();
+ }
+
+ virtual DLObject *makeDLObject() = 0;
+
+ bool loadPlugin();
+ void unloadPlugin();
+};
+
+class ELFPluginProvider : public FilePluginProvider {
+protected:
+ virtual Plugin *createPlugin(const Common::FSNode &node) const = 0;
+
+ bool isPluginFilename(const Common::FSNode &node) const;
+};
+
+#endif // defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER)
+
+#endif /* BACKENDS_PLUGINS_ELF_PROVIDER_H */
+
diff --git a/backends/plugins/elf/elf32.h b/backends/plugins/elf/elf32.h
index 5692c8a07b..d3a8d2e436 100644
--- a/backends/plugins/elf/elf32.h
+++ b/backends/plugins/elf/elf32.h
@@ -1 +1,258 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef BACKENDS_ELF_H
+#define BACKENDS_ELF_H
+
+#include "common/scummsys.h"
+
+#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER)
+
+/**
+ * ELF stuff:
+ * The contents of this file were gathered mainly from the SYSTEM V APPLICATION BINARY INTERFACE.
+ * Processor-specific things were garnered from processor-specific supplements to the abi.
+ */
+
+typedef uint16 Elf32_Half, Elf32_Section;
+typedef uint32 Elf32_Word, Elf32_Addr, Elf32_Off;
+typedef int32 Elf32_Sword;
+typedef Elf32_Half Elf32_Versym;
+
+#define EI_NIDENT (16)
+#define SELFMAG 4
+
+/* ELF File format structures. Look up ELF structure for more details */
+
+// ELF header (contains info about the file)
+typedef struct {
+ byte e_ident[EI_NIDENT]; /* Magic number and other info */
+ Elf32_Half e_type; /* Object file type */
+ Elf32_Half e_machine; /* Architecture */
+ Elf32_Word e_version; /* Object file version */
+ Elf32_Addr e_entry; /* Entry point virtual address */
+ Elf32_Off e_phoff; /* Program header table file offset */
+ Elf32_Off e_shoff; /* Section header table file offset */
+ Elf32_Word e_flags; /* Processor-specific flags */
+ Elf32_Half e_ehsize; /* ELF header size in bytes */
+ Elf32_Half e_phentsize; /* Program header table entry size */
+ Elf32_Half e_phnum; /* Program header table entry count */
+ Elf32_Half e_shentsize; /* Section header table entry size */
+ Elf32_Half e_shnum; /* Section header table entry count */
+ Elf32_Half e_shstrndx; /* Section header string table index */
+} Elf32_Ehdr;
+
+// Should be in e_ident
+#define ELFMAG "\177ELF" /* ELF Magic number */
+
+#define EI_CLASS 4 /* File class byte index */
+#define ELFCLASS32 1 /* 32-bit objects */
+
+#define EI_DATA 5 /* Data encoding byte index */
+#define ELFDATA2LSB 1 /* 2's complement, little endian */
+#define ELFDATA2MSB 2 /* 2's complement, big endian */
+
+#define EI_VERSION 6
+#define EV_CURRENT 1 /* Current version */
+
+// e_type values
+#define ET_NONE 0 /* no file type */
+#define ET_REL 1 /* relocatable */
+#define ET_EXEC 2 /* executable */
+#define ET_DYN 3 /* shared object */
+#define ET_CORE 4 /* core file */
+
+// e_machine values
+#define EM_MIPS 8
+#define EM_PPC 20
+#define EM_ARM 40
+
+// Program header (contains info about segment)
+typedef struct {
+ Elf32_Word p_type; /* Segment type */
+ Elf32_Off p_offset; /* Segment file offset */
+ Elf32_Addr p_vaddr; /* Segment virtual address */
+ Elf32_Addr p_paddr; /* Segment physical address */
+ Elf32_Word p_filesz; /* Segment size in file */
+ Elf32_Word p_memsz; /* Segment size in memory */
+ Elf32_Word p_flags; /* Segment flags */
+ Elf32_Word p_align; /* Segment alignment */
+} Elf32_Phdr;
+
+// p_type values
+#define PT_NULL 0 /* ignored */
+#define PT_LOAD 1 /* loadable segment */
+#define PT_DYNAMIC 2 /* dynamic linking info */
+#define PT_INTERP 3 /* info about interpreter */
+#define PT_NOTE 4 /* note segment */
+#define PT_SHLIB 5 /* reserved */
+#define PT_PHDR 6 /* Program header table */
+#define PT_MIPS_REGINFO 0x70000000 /* Register usage info for MIPS */
+#define PT_ARM_ARCHEXT 0x70000000 /* Platform architecture compatibility info for ARM */
+#define PT_ARM_EXIDX 0x70000001 /* Exception unwind tables for ARM */
+
+// p_flags value
+#define PF_X 1 /* execute */
+#define PF_W 2 /* write */
+#define PF_R 4 /* read */
+
+// Section header (contains info about section)
+typedef struct {
+ Elf32_Word sh_name; /* Section name (string tbl index) */
+ Elf32_Word sh_type; /* Section type */
+ Elf32_Word sh_flags; /* Section flags */
+ Elf32_Addr sh_addr; /* Section virtual addr at execution */
+ Elf32_Off sh_offset; /* Section file offset */
+ Elf32_Word sh_size; /* Section size in bytes */
+ Elf32_Word sh_link; /* Link to another section */
+ Elf32_Word sh_info; /* Additional section information */
+ Elf32_Word sh_addralign; /* Section alignment */
+ Elf32_Word sh_entsize; /* Entry size if section holds table */
+} Elf32_Shdr;
+
+// sh_type values
+#define SHT_NULL 0 /* Inactive section */
+#define SHT_PROGBITS 1 /* Proprietary */
+#define SHT_SYMTAB 2 /* Symbol table */
+#define SHT_STRTAB 3 /* String table */
+#define SHT_RELA 4 /* Relocation entries with addend */
+#define SHT_HASH 5 /* Symbol hash table */
+#define SHT_DYNAMIC 6 /* Info for dynamic linking */
+#define SHT_NOTE 7 /* Note section */
+#define SHT_NOBITS 8 /* Occupies no space */
+#define SHT_REL 9 /* Relocation entries without addend */
+#define SHT_SHLIB 10 /* Reserved */
+#define SHT_DYNSYM 11 /* Minimal set of dynamic linking symbols */
+#define SHT_MIPS_LIBLSIT 0x70000000 /* Info about dynamic shared object libs for MIPS*/
+#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicts btw executables and shared objects for MIPS */
+#define SHT_MIPS_GPTAB 0x70000003 /* Global pointer table for MIPS*/
+#define SHT_ARM_EXIDX 0x70000001 /* Exception Index table for ARM*/
+#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking pre-emption map for ARM */
+#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility attributes for ARM*/
+
+// sh_flags values
+#define SHF_WRITE 0 /* writable section */
+#define SHF_ALLOC 2 /* section occupies memory */
+#define SHF_EXECINSTR 4 /* machine instructions */
+#define SHF_MIPS_GPREL 0x10000000 /* Must be made part of global data area for MIPS */
+
+// Symbol entry (contain info about a symbol)
+typedef struct {
+ Elf32_Word st_name; /* Symbol name (string tbl index) */
+ Elf32_Addr st_value; /* Symbol value */
+ Elf32_Word st_size; /* Symbol size */
+ byte st_info; /* Symbol type and binding */
+ byte st_other; /* Symbol visibility */
+ Elf32_Section st_shndx; /* Section index */
+} Elf32_Sym;
+
+// Extract from the st_info
+#define SYM_TYPE(x) ((x) & 0xf)
+#define SYM_BIND(x) ((x) >> 4)
+
+// Symbol binding values from st_info
+#define STB_LOCAL 0 /* Symbol not visible outside object */
+#define STB_GLOBAL 1 /* Symbol visible to all object files */
+#define STB_WEAK 2 /* Similar to STB_GLOBAL */
+
+// Symbol type values from st_info
+#define STT_NOTYPE 0 /* Not specified */
+#define STT_OBJECT 1 /* Data object e.g. variable */
+#define STT_FUNC 2 /* Function */
+#define STT_SECTION 3 /* Section */
+#define STT_FILE 4 /* Source file associated with object file */
+
+// Special section header index values from st_shndex
+#define SHN_UNDEF 0
+#define SHN_LOPROC 0xFF00 /* Extended values */
+#define SHN_ABS 0xFFF1 /* Absolute value: don't relocate */
+#define SHN_COMMON 0xFFF2 /* Common block. Not allocated yet */
+#define SHN_HIPROC 0xFF1F
+#define SHN_HIRESERVE 0xFFFF
+
+// Relocation entry with implicit addend (info about how to relocate)
+typedef struct {
+ Elf32_Addr r_offset; /* Address */
+ Elf32_Word r_info; /* Relocation type and symbol index */
+} Elf32_Rel;
+
+// Relocation entry with explicit addend (info about how to relocate)
+typedef struct {
+ Elf32_Addr r_offset; /* Address */
+ Elf32_Word r_info; /* Relocation type and symbol index */
+ Elf32_Sword r_addend; /* Addend */
+} Elf32_Rela;
+
+// Access macros for the relocation info
+#define REL_TYPE(x) ((byte) (x)) /* Extract relocation type */
+#define REL_INDEX(x) ((x)>>8) /* Extract relocation index into symbol table */
+
+//MIPS relocation types
+#define R_MIPS_NONE 0
+#define R_MIPS_16 1
+#define R_MIPS_32 2
+#define R_MIPS_REL32 3
+#define R_MIPS_26 4
+#define R_MIPS_HI16 5
+#define R_MIPS_LO16 6
+#define R_MIPS_GPREL16 7
+#define R_MIPS_LITERAL 8
+#define R_MIPS_GOT16 9
+#define R_MIPS_PC16 10
+#define R_MIPS_CALL16 11
+#define R_MIPS_GPREL32 12
+#define R_MIPS_GOTHI16 13
+#define R_MIPS_GOTLO16 14
+#define R_MIPS_CALLHI16 15
+#define R_MIPS_CALLLO16 16
+
+// ARM relocation types
+#define R_ARM_NONE 0
+#define R_ARM_ABS32 2
+#define R_ARM_THM_CALL 10
+#define R_ARM_CALL 28
+#define R_ARM_JUMP24 29
+#define R_ARM_TARGET1 38
+#define R_ARM_V4BX 40
+
+// PPC relocation types
+#define R_PPC_ADDR32 1
+#define R_PPC_ADDR16_LO 4
+#define R_PPC_ADDR16_HI 5
+#define R_PPC_ADDR16_HA 6
+#define R_PPC_REL24 10
+#define R_PPC_REL32 26
+
+// Mock function to get value of global pointer for MIPS
+#define getGP() { \
+ uint32 __valgp; \
+ __asm__ ("add %0, $gp, $0" : "=r"(__valgp) : ); \
+ __valgp; \
+}
+
+#endif // defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER)
+
+#endif /* BACKENDS_ELF_H */
+
diff --git a/backends/plugins/elf/mips-loader.cpp b/backends/plugins/elf/mips-loader.cpp
index 5692c8a07b..53ffc2f01b 100644
--- a/backends/plugins/elf/mips-loader.cpp
+++ b/backends/plugins/elf/mips-loader.cpp
@@ -1 +1,339 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/scummsys.h"
+
+#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(MIPS_TARGET)
+
+#include "backends/plugins/elf/mips-loader.h"
+
+#include "common/debug.h"
+
+#define DEBUG_NUM 2
+
+bool MIPSDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment) {
+ Elf32_Rel *rel = 0; // relocation entry
+
+ // Allocate memory for relocation table
+ if (!(rel = (Elf32_Rel *)malloc(size))) {
+ warning("elfloader: Out of memory.");
+ return false;
+ }
+
+ // Read in our relocation table
+ if (!_file->seek(offset, SEEK_SET) || _file->read(rel, size) != size) {
+ warning("elfloader: Relocation table load failed.");
+ free(rel);
+ return false;
+ }
+
+ // Treat each relocation entry. Loop over all of them
+ uint32 cnt = size / sizeof(*rel);
+
+ debug(2, "elfloader: Loaded relocation table. %d entries. base address=%p", cnt, relSegment);
+
+ Elf32_Addr adjustedMainSegment = Elf32_Addr(_segment) - _segmentVMA; // adjust for VMA offset
+
+ bool seenHi16 = false; // For treating HI/LO16 commands
+ int32 firstHi16 = -1; // Mark the point of the first hi16 seen
+ Elf32_Addr ahl = 0; // Calculated addend
+ int32 a = 0; // Addend: taken from the target
+
+ uint32 *lastTarget = 0; // For processing hi16 when lo16 arrives
+ uint32 relocation = 0;
+ uint debugRelocs[10] = { 0 }; // For debugging
+ uint extendedHi16 = 0; // Count extended hi16 treatments
+ Elf32_Addr lastHiSymVal = 0;
+ bool hi16InShorts = false;
+
+ // Loop over relocation entries
+ for (uint32 i = 0; i < cnt; i++) {
+ // Get the symbol this relocation entry is referring to
+ Elf32_Sym *sym = _symtab + (REL_INDEX(rel[i].r_info));
+
+ // Get the target instruction in the code.
+ uint32 *target = (uint32 *)((byte *)relSegment + rel[i].r_offset);
+
+ uint32 origTarget = *target; // Save for debugging
+
+ // Act differently based on the type of relocation
+ switch (REL_TYPE(rel[i].r_info)) {
+ case R_MIPS_HI16: // Absolute addressing.
+ if (sym->st_shndx < SHN_LOPROC && // Only shift for plugin section (ie. has a real section index)
+ firstHi16 < 0) { // Only process first in block of HI16s
+ firstHi16 = i; // Keep the first Hi16 we saw
+ seenHi16 = true;
+ ahl = (*target & 0xffff) << 16; // Take lower 16 bits shifted up
+
+ lastHiSymVal = sym->st_value;
+ hi16InShorts = ShortsMan.inGeneralSegment((char *)sym->st_value); // Fix for problem with switching btw segments
+ if (debugRelocs[0]++ < DEBUG_NUM) // Print only a set number
+ debug(8, "elfloader: R_MIPS_HI16: i=%d, offset=%x, ahl = %x, target = %x",
+ i, rel[i].r_offset, ahl, *target);
+ }
+ break;
+
+ case R_MIPS_LO16: // Absolute addressing. Needs a HI16 to come before it
+ if (sym->st_shndx < SHN_LOPROC) { // Only shift for plugin section. (ie. has a real section index)
+ if (!seenHi16) { // We MUST have seen HI16 first
+ debug(8, "elfloader: R_MIPS_LO16 w/o preceding R_MIPS_HI16 at relocation %d!", i);
+ free(rel);
+ return false;
+ }
+
+ // Fix: bug in gcc makes LO16s connect to wrong HI16s sometimes (shorts and regular segment)
+ // Note that we can check the entire shorts segment because the executable's shorts don't belong to this plugin section
+ // and will be screened out above
+ bool lo16InShorts = ShortsMan.inGeneralSegment((char *)sym->st_value);
+
+ // Correct the bug by getting the proper value in ahl (taken from the current symbol)
+ if ((hi16InShorts && !lo16InShorts) || (!hi16InShorts && lo16InShorts)) {
+ ahl -= (lastHiSymVal & 0xffff0000); // We assume gcc meant the same offset
+ ahl += (sym->st_value & 0xffff0000);
+ }
+
+ ahl &= 0xffff0000; // Clean lower 16 bits for repeated LO16s
+ a = *target & 0xffff; // Take lower 16 bits of the target
+ a = (a << 16) >> 16; // Sign extend them
+ ahl += a; // Add lower 16 bits. AHL is now complete
+
+ // Fix: we can have LO16 access to the short segment sometimes
+ if (lo16InShorts)
+ relocation = ahl + _shortsSegment->getOffset(); // Add in the short segment offset
+ else // It's in the regular segment
+ relocation = ahl + adjustedMainSegment; // Add in the new offset for the segment
+
+ if (firstHi16 >= 0) { // We haven't treated the HI16s yet so do it now
+ for (uint32 j = firstHi16; j < i; j++) {
+ if (REL_TYPE(rel[j].r_info) != R_MIPS_HI16)
+ continue; // Skip over non-Hi16s
+
+ lastTarget = (uint32 *)((char *)relSegment + rel[j].r_offset); // get hi16 target
+ *lastTarget &= 0xffff0000; // Clear the lower 16 bits of the last target
+ *lastTarget |= (relocation >> 16) & 0xffff; // Take the upper 16 bits of the relocation
+ if (relocation & 0x8000)
+ (*lastTarget)++; // Subtle: we need to add 1 to the HI16 in this case
+ }
+
+ firstHi16 = -1; // Reset so we'll know we treated it
+ } else {
+ extendedHi16++;
+ }
+
+ *target &= 0xffff0000; // Clear the lower 16 bits of current target
+ *target |= relocation & 0xffff; // Take the lower 16 bits of the relocation
+
+ if (debugRelocs[1]++ < DEBUG_NUM)
+ debug(8, "elfloader: R_MIPS_LO16: i=%d, offset=%x, a=%x, ahl = %x, "
+ "lastTarget = %x, origt = %x, target = %x",
+ i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target);
+
+ if (lo16InShorts && debugRelocs[2]++ < DEBUG_NUM)
+ debug(8, "elfloader: R_MIPS_LO16s: i=%d, offset=%x, a=%x, ahl = %x, "
+ "lastTarget = %x, origt = %x, target = %x",
+ i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target);
+ }
+ break;
+
+ case R_MIPS_26: // Absolute addressing (for jumps and branches only)
+ if (sym->st_shndx < SHN_LOPROC) { // Only relocate for main segment
+ a = *target & 0x03ffffff; // Get 26 bits' worth of the addend
+ a = (a << 6) >> 6; // Sign extend a
+ relocation = ((a << 2) + adjustedMainSegment) >> 2; // a already points to the target. Add our offset
+ *target &= 0xfc000000; // Clean lower 26 target bits
+ *target |= (relocation & 0x03ffffff);
+
+ if (debugRelocs[3]++ < DEBUG_NUM)
+ debug(8, "elfloader: R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, "
+ "a=%x, origTarget=%x, target=%x",
+ i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target);
+ } else {
+ if (debugRelocs[4]++ < DEBUG_NUM)
+ debug(8, "elfloader: R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, "
+ "a=%x, origTarget=%x, target=%x",
+ i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target);
+ }
+ break;
+
+ case R_MIPS_GPREL16: // GP Relative addressing
+ if (_shortsSegment->getOffset() != 0 && // Only relocate if we shift the shorts section
+ ShortsMan.inGeneralSegment((char *) sym->st_value)) { // Only relocate things in the plugin hole
+ a = *target & 0xffff; // Get 16 bits' worth of the addend
+ a = (a << 16) >> 16; // Sign extend it
+
+ relocation = a + _shortsSegment->getOffset();
+
+ *target &= 0xffff0000; // Clear the lower 16 bits of the target
+ *target |= relocation & 0xffff;
+
+ if (debugRelocs[5]++ < DEBUG_NUM)
+ debug(8, "elfloader: R_MIPS_GPREL16: i=%d, a=%x, gpVal=%x, origTarget=%x, "
+ "target=%x, offset=%x",
+ i, a, _gpVal, origTarget, *target, _shortsSegment->getOffset());
+ }
+
+ break;
+
+ case R_MIPS_32: // Absolute addressing
+ if (sym->st_shndx < SHN_LOPROC) { // Only shift for plugin section.
+ a = *target; // Get full 32 bits of addend
+
+ if (ShortsMan.inGeneralSegment((char *)sym->st_value)) // Check if we're in the shorts segment
+ relocation = a + _shortsSegment->getOffset(); // Shift by shorts offset
+ else // We're in the main section
+ relocation = a + adjustedMainSegment; // Shift by main offset
+
+ *target = relocation;
+
+ if (debugRelocs[6]++ < DEBUG_NUM)
+ debug(8, "elfloader: R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x",
+ i, a, origTarget, *target);
+ }
+
+ break;
+
+ default:
+ warning("elfloader: Unknown relocation type %x at relocation %d.", REL_TYPE(rel[i].r_info), i);
+ free(rel);
+ return false;
+ }
+ }
+
+ debug(2, "elfloader: Done with relocation. extendedHi16=%d", extendedHi16);
+
+ free(rel);
+ return true;
+}
+
+bool MIPSDLObject::relocateRels(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
+ // Loop over sections, finding relocation sections
+ for (uint32 i = 0; i < ehdr->e_shnum; i++) {
+ Elf32_Shdr *curShdr = &(shdr[i]);
+ //Elf32_Shdr *linkShdr = &(shdr[curShdr->sh_info]);
+
+ if (curShdr->sh_type == SHT_REL && // Check for a relocation section
+ curShdr->sh_entsize == sizeof(Elf32_Rel) && // Check for proper relocation size
+ int32(curShdr->sh_link) == _symtab_sect && // Check that the sh_link connects to our symbol table
+ curShdr->sh_info < ehdr->e_shnum && // Check that the relocated section exists
+ (shdr[curShdr->sh_info].sh_flags & SHF_ALLOC)) { // Check if relocated section resides in memory
+ if (!ShortsMan.inGeneralSegment((char *)shdr[curShdr->sh_info].sh_addr)) { // regular segment
+ if (!relocate(curShdr->sh_offset, curShdr->sh_size, _segment - _segmentVMA))
+ return false;
+ } else { // In Shorts segment
+ if (!relocate(curShdr->sh_offset, curShdr->sh_size, (byte *)_shortsSegment->getOffset()))
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+void MIPSDLObject::relocateSymbols(ptrdiff_t offset) {
+ // Loop over symbols, add relocation offset
+ Elf32_Sym *s = _symtab;
+
+ for (uint32 c = _symbol_cnt; c--; s++) {
+ // Make sure we don't relocate special valued symbols
+ if (s->st_shndx < SHN_LOPROC) {
+ if (!ShortsMan.inGeneralSegment((char *)s->st_value)) {
+ if (s->st_value < _segmentVMA)
+ s->st_value = _segmentVMA; // deal with symbols referring to sections, which start before the VMA
+
+ s->st_value += offset;
+
+ if (s->st_value < Elf32_Addr(_segment) || s->st_value > Elf32_Addr(_segment) + _segmentSize)
+ warning("elfloader: Symbol out of bounds! st_value = %x", s->st_value);
+ } else { // shorts section
+ s->st_value += _shortsSegment->getOffset();
+ if (!_shortsSegment->inSegment((char *)s->st_value))
+ warning("elfloader: Symbol out of bounds! st_value = %x", s->st_value);
+ }
+ }
+ }
+}
+
+bool MIPSDLObject::loadSegment(Elf32_Phdr *phdr) {
+ byte *baseAddress = 0;
+
+ // We need to take account of non-allocated segment for shorts
+ if (phdr->p_flags & PF_X) { // This is a relocated segment
+ // Attempt to allocate memory for segment
+ _segment = (byte *)allocSegment(phdr->p_align, phdr->p_memsz);
+
+ if (!_segment) {
+ warning("elfloader: Out of memory.");
+ return false;
+ }
+
+ debug(2, "elfloader: Allocated segment @ %p", _segment);
+
+ // Get offset to load segment into
+ baseAddress = _segment;
+ _segmentSize = phdr->p_memsz;
+ _segmentVMA = phdr->p_vaddr;
+
+ } else { // This is a shorts section.
+ _shortsSegment = ShortsMan.newSegment(phdr->p_memsz, (char *)phdr->p_vaddr);
+
+ baseAddress = (byte *)_shortsSegment->getStart();
+ debug(2, "elfloader: Shorts segment @ %p to %p. Segment wants to be at %x. Offset=%x",
+ _shortsSegment->getStart(), _shortsSegment->getEnd(), phdr->p_vaddr,
+ _shortsSegment->getOffset());
+ }
+
+ // Set .sbss segment to 0 if necessary
+ if (phdr->p_memsz > phdr->p_filesz) {
+ debug(2, "elfloader: Setting %p to %p to 0 for bss", baseAddress + phdr->p_filesz,
+ baseAddress + phdr->p_memsz);
+ memset(baseAddress + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz);
+ }
+
+ debug(2, "elfloader: Reading the segment into memory");
+
+ // Read the segment into memory
+ if (!_file->seek(phdr->p_offset, SEEK_SET) ||
+ _file->read(baseAddress, phdr->p_filesz) != phdr->p_filesz) {
+ warning("elfloader: Segment load failed.");
+ return false;
+ }
+
+ debug(2, "elfloader: Segment has been read into memory");
+
+ return true;
+}
+
+// Unload all objects from memory
+void MIPSDLObject::unload() {
+ DLObject::unload();
+
+ if (_shortsSegment) {
+ ShortsMan.deleteSegment(_shortsSegment);
+ _shortsSegment = 0;
+ }
+}
+
+#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(MIPS_TARGET) */
+
diff --git a/backends/plugins/elf/mips-loader.h b/backends/plugins/elf/mips-loader.h
index 5692c8a07b..f8f31f1e7a 100644
--- a/backends/plugins/elf/mips-loader.h
+++ b/backends/plugins/elf/mips-loader.h
@@ -1 +1,59 @@
-dummy
+
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef BACKENDS_PLUGINS_MIPS_LOADER_H
+#define BACKENDS_PLUGINS_MIPS_LOADER_H
+
+#include "common/scummsys.h"
+
+#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(MIPS_TARGET)
+
+#include "backends/plugins/elf/elf-loader.h"
+#include "backends/plugins/elf/shorts-segment-manager.h"
+
+class MIPSDLObject : public DLObject {
+protected:
+ ShortSegmentManager::Segment *_shortsSegment; // For assigning shorts ranges
+ uint32 _gpVal; // Value of Global Pointer
+
+ virtual bool relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment);
+ virtual bool relocateRels(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr);
+ virtual void relocateSymbols(ptrdiff_t offset);
+ virtual bool loadSegment(Elf32_Phdr *phdr);
+ virtual void unload();
+
+public:
+ MIPSDLObject() :
+ DLObject() {
+ _shortsSegment = NULL;
+ _gpVal = 0;
+ }
+};
+
+#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(MIPS_TARGET) */
+
+#endif /* BACKENDS_PLUGINS_MIPS_LOADER_H */
+
diff --git a/backends/plugins/elf/plugin.syms b/backends/plugins/elf/plugin.syms
index 5692c8a07b..70465ae976 100644
--- a/backends/plugins/elf/plugin.syms
+++ b/backends/plugins/elf/plugin.syms
@@ -1 +1,9 @@
-dummy
+PLUGIN_getBuildDate
+PLUGIN_getVersion
+PLUGIN_getType
+PLUGIN_getTypeVersion
+PLUGIN_getObject
+___plugin_ctors
+___plugin_ctors_end
+___plugin_dtors
+___plugin_dtors_end
diff --git a/backends/plugins/elf/ppc-loader.cpp b/backends/plugins/elf/ppc-loader.cpp
index 5692c8a07b..ec6d442876 100644
--- a/backends/plugins/elf/ppc-loader.cpp
+++ b/backends/plugins/elf/ppc-loader.cpp
@@ -1 +1,129 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/scummsys.h"
+
+#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(PPC_TARGET)
+
+#include "backends/plugins/elf/elf-loader.h"
+#include "backends/plugins/elf/ppc-loader.h"
+
+#include "common/debug.h"
+
+bool PPCDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment) {
+ Elf32_Rela *rel = NULL;
+
+ if (!(rel = (Elf32_Rela *)malloc(size))) {
+ warning("elfloader: Out of memory.");
+ return false;
+ }
+
+ if (!_file->seek(offset, SEEK_SET) || _file->read(rel, size) != size) {
+ warning("elfloader: Relocation table load failed.");
+ free(rel);
+ return false;
+ }
+
+ uint32 cnt = size / sizeof(*rel);
+
+ debug(2, "elfloader: Loaded relocation table. %d entries. base address=%p", cnt, relSegment);
+
+ uint32 *src;
+ uint32 value;
+
+ for (uint32 i = 0; i < cnt; i++) {
+ // Get the symbol this relocation entry is referring to
+ Elf32_Sym *sym = _symtab + (REL_INDEX(rel[i].r_info));
+
+ // Get the target instruction in the code
+ src = (uint32 *)((char *)relSegment + rel[i].r_offset - _segmentVMA);
+ value = sym->st_value + rel[i].r_addend;
+
+ //debug(8, "elfloader: i=%05d %p +0x%04x: (0x%08x) 0x%08x ", i, src, rel[i].r_addend, sym->st_value, *src);
+
+ switch (REL_TYPE(rel[i].r_info)) {
+ case R_PPC_ADDR32:
+ *src = value;
+ debug(8, "elfloader: R_PPC_ADDR32 -> 0x%08x", *src);
+ break;
+ case R_PPC_ADDR16_LO:
+ *(uint16 *)src = value;
+ debug(8, "elfloader: R_PPC_ADDR16_LO -> 0x%08x", *src);
+ break;
+ case R_PPC_ADDR16_HI:
+ *(uint16 *)src = value >> 16;
+ debug(8, "elfloader: R_PPC_ADDR16_HA -> 0x%08x", *src);
+ break;
+ case R_PPC_ADDR16_HA:
+ *(uint16 *)src = (value + 0x8000) >> 16;
+ debug(8, "elfloader: R_PPC_ADDR16_HA -> 0x%08x", *src);
+ break;
+ case R_PPC_REL24:
+ *src = (*src & ~0x03fffffc) | ((value - (uint32)src) & 0x03fffffc);
+ debug(8, "elfloader: R_PPC_REL24 -> 0x%08x", *src);
+ break;
+ case R_PPC_REL32:
+ *src = value - (uint32)src;
+ debug(8, "elfloader: R_PPC_REL32 -> 0x%08x", *src);
+ break;
+ default:
+ warning("elfloader: Unknown relocation type %d", REL_TYPE(rel[i].r_info));
+ free(rel);
+ return false;
+ }
+ }
+
+ free(rel);
+ return true;
+}
+
+bool PPCDLObject::relocateRels(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
+ for (uint32 i = 0; i < ehdr->e_shnum; i++) {
+ Elf32_Shdr *curShdr = &(shdr[i]);
+
+ if ((curShdr->sh_type == SHT_REL) &&
+ curShdr->sh_entsize == sizeof(Elf32_Rel) &&
+ int32(curShdr->sh_link) == _symtab_sect &&
+ curShdr->sh_info < ehdr->e_shnum &&
+ (shdr[curShdr->sh_info].sh_flags & SHF_ALLOC)) {
+ warning("elfloader: REL entries not supported!");
+ return false;
+ }
+
+ if ((curShdr->sh_type == SHT_RELA) &&
+ curShdr->sh_entsize == sizeof(Elf32_Rela) &&
+ int32(curShdr->sh_link) == _symtab_sect &&
+ curShdr->sh_info < ehdr->e_shnum &&
+ (shdr[curShdr->sh_info].sh_flags & SHF_ALLOC)) {
+ if (!relocate(curShdr->sh_offset, curShdr->sh_size, _segment))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(PPC_TARGET) */
+
diff --git a/backends/plugins/elf/ppc-loader.h b/backends/plugins/elf/ppc-loader.h
index 5692c8a07b..f9340a6a7b 100644
--- a/backends/plugins/elf/ppc-loader.h
+++ b/backends/plugins/elf/ppc-loader.h
@@ -1 +1,49 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef BACKENDS_PLUGINS_PPC_LOADER_H
+#define BACKENDS_PLUGINS_PPC_LOADER_H
+
+#include "common/scummsys.h"
+
+#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(PPC_TARGET)
+
+#include "backends/plugins/elf/elf-loader.h"
+
+class PPCDLObject : public DLObject {
+protected:
+ virtual bool relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment);
+ virtual bool relocateRels(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr);
+
+public:
+ PPCDLObject() :
+ DLObject() {
+ }
+};
+
+#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(PPC_TARGET) */
+
+#endif /* BACKENDS_PLUGINS_PPC_LOADER_H */
+
diff --git a/backends/plugins/elf/shorts-segment-manager.cpp b/backends/plugins/elf/shorts-segment-manager.cpp
index 5692c8a07b..99a765287b 100644
--- a/backends/plugins/elf/shorts-segment-manager.cpp
+++ b/backends/plugins/elf/shorts-segment-manager.cpp
@@ -1 +1,90 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/scummsys.h"
+
+#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(MIPS_TARGET)
+
+#include "backends/plugins/elf/shorts-segment-manager.h"
+
+#include "common/debug.h"
+#include "common/textconsole.h"
+
+extern char __plugin_hole_start; // Indicates start of hole in program file for shorts
+extern char __plugin_hole_end; // Indicates end of hole in program file
+extern char _gp[]; // Value of gp register
+
+DECLARE_SINGLETON(ShortSegmentManager); // For singleton
+
+ShortSegmentManager::ShortSegmentManager() {
+ _shortsStart = &__plugin_hole_start ; //shorts segment begins at the plugin hole we made when linking
+ _shortsEnd = &__plugin_hole_end; //and ends at the end of that hole.
+}
+
+ShortSegmentManager::Segment *ShortSegmentManager::newSegment(uint32 size, char *origAddr) {
+ char *lastAddress = origAddr;
+ Common::List<Segment *>::iterator i;
+
+ // Find a block that fits, starting from the beginning
+ for (i = _list.begin(); i != _list.end(); ++i) {
+ char *currAddress = (*i)->getStart();
+
+ if (uint32(currAddress) - uint32(lastAddress) >= size)
+ break;
+
+ lastAddress = (*i)->getEnd();
+ }
+
+ if ((Elf32_Addr)lastAddress & 3)
+ lastAddress += 4 - ((Elf32_Addr)lastAddress & 3); // Round up to multiple of 4
+
+ if (lastAddress + size > _shortsEnd) {
+ warning("elfloader: No space in shorts segment for %x bytes. Last address is %p, max address is %p.",
+ size, lastAddress, _shortsEnd);
+ return 0;
+ }
+
+ Segment *seg = new Segment(lastAddress, size, origAddr); // Create a new segment
+
+ if (lastAddress + size > _highestAddress)
+ _highestAddress = lastAddress + size; // Keep track of maximum
+
+ _list.insert(i, seg);
+
+ debug(2, "elfloader: Shorts segment size %x allocated. End = %p. Remaining space = %x. Highest so far is %p.",
+ size, lastAddress + size, _shortsEnd - _list.back()->getEnd(), _highestAddress);
+
+ return seg;
+}
+
+void ShortSegmentManager::deleteSegment(ShortSegmentManager::Segment *seg) {
+ debug(2, "elfloader: Deleting shorts segment from %p to %p.", seg->getStart(), seg->getEnd());
+ _list.remove(seg);
+ delete seg;
+}
+
+#endif // defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(MIPS_TARGET)
+
+
diff --git a/backends/plugins/elf/shorts-segment-manager.h b/backends/plugins/elf/shorts-segment-manager.h
index 5692c8a07b..219648d91d 100644
--- a/backends/plugins/elf/shorts-segment-manager.h
+++ b/backends/plugins/elf/shorts-segment-manager.h
@@ -1 +1,117 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef SHORTS_SEGMENT_MANAGER_H
+#define SHORTS_SEGMENT_MANAGER_H
+
+#include "common/scummsys.h"
+
+#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(MIPS_TARGET)
+
+#include "backends/plugins/elf/elf32.h"
+
+#include "common/singleton.h"
+#include "common/list.h"
+
+#define ShortsMan ShortSegmentManager::instance()
+
+/**
+ * ShortSegmentManager
+ *
+ * Since MIPS is limited to 32 bits per instruction, loading data that's further away than 16 bits
+ * takes several instructions. Thus, small global data (which is likely to be accessed a lot from
+ * multiple locations) is often put into a GP-relative area (GP standing for the global pointer register)
+ * in MIPS processors. This class manages these segments of small global data, and is used by the
+ * member functions of MIPSDLObject, which query in information from this manager in order to deal with
+ * this segment during the loading/unloading of plugins.
+ *
+ * Since there's no true dynamic linker to change the GP register between plugins and the main engine,
+ * custom ld linker scripts for both the main executable and the plugins ensure the GP-area is in the
+ * same place for both. The ShortSegmentManager accesses this place via the symbols __plugin_hole_start
+ * and __plugin_hole_end, which are defined in those custom ld linker scripts.
+ */
+class ShortSegmentManager : public Common::Singleton<ShortSegmentManager> {
+private:
+ char *_shortsStart;
+ char *_shortsEnd;
+
+public:
+ char *getShortsStart() {
+ return _shortsStart;
+ }
+
+ // Returns whether or not an absolute address is in the GP-relative section.
+ bool inGeneralSegment(char *addr) {
+ return (addr >= _shortsStart && addr < _shortsEnd);
+ }
+
+ class Segment {
+ private:
+ friend class ShortSegmentManager;
+ Segment(char *start, uint32 size, char *origAddr) :
+ _startAddress(start),
+ _size(size),
+ _origAddress(origAddr) {
+ }
+
+ virtual ~Segment() {
+ }
+
+ char *_startAddress; // Start of shorts segment in memory
+ uint32 _size; // Size of shorts segment
+ char *_origAddress; // Original address this segment was supposed to be at
+
+ public:
+ char *getStart() {
+ return _startAddress;
+ }
+
+ char *getEnd() {
+ return (_startAddress + _size);
+ }
+
+ Elf32_Addr getOffset() {
+ return (Elf32_Addr)(_startAddress - _origAddress);
+ }
+
+ bool inSegment(char *addr) {
+ return (addr >= _startAddress && addr <= _startAddress + _size);
+ }
+ };
+
+ Segment *newSegment(uint32 size, char *origAddr);
+ void deleteSegment(Segment *);
+
+private:
+ ShortSegmentManager();
+ friend class Common::Singleton<ShortSegmentManager>;
+ Common::List<Segment *> _list;
+ char *_highestAddress;
+};
+
+#endif // defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(MIPS_TARGET)
+
+#endif /* SHORTS_SEGMENT_MANAGER_H */
+
diff --git a/backends/plugins/elf/version.cpp b/backends/plugins/elf/version.cpp
index 5692c8a07b..0277c6ae1c 100644
--- a/backends/plugins/elf/version.cpp
+++ b/backends/plugins/elf/version.cpp
@@ -1 +1,32 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "backends/plugins/elf/version.h"
+
+#ifdef USE_ELF_LOADER
+const char *gScummVMPluginBuildDate __attribute__((visibility("hidden"))) =
+ __DATE__ " " __TIME__ ;
+#endif
+
diff --git a/backends/plugins/elf/version.h b/backends/plugins/elf/version.h
index 5692c8a07b..726204aeb7 100644
--- a/backends/plugins/elf/version.h
+++ b/backends/plugins/elf/version.h
@@ -1 +1,35 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef BACKENDS_PLUGINS_ELF_VERSION_H
+#define BACKENDS_PLUGINS_ELF_VERSION_H
+
+#include "common/scummsys.h"
+
+#ifdef USE_ELF_LOADER
+extern const char *gScummVMPluginBuildDate;
+#endif
+
+#endif
+
diff --git a/backends/plugins/ps2/main_prog.ld b/backends/plugins/ps2/main_prog.ld
index 5692c8a07b..9dba69c50e 100644
--- a/backends/plugins/ps2/main_prog.ld
+++ b/backends/plugins/ps2/main_prog.ld
@@ -1 +1,99 @@
-dummy
+ENTRY(_start);
+
+SECTIONS {
+ .text 0x00100000: {
+ _ftext = . ;
+ *(.text)
+ *(.text.*)
+ *(.gnu.linkonce.t*)
+ KEEP(*(.init))
+ KEEP(*(.fini))
+ QUAD(0)
+ }
+
+ PROVIDE(_etext = .);
+ PROVIDE(etext = .);
+
+ .reginfo : { *(.reginfo) }
+
+ /* Global/static constructors and deconstructors. */
+ .ctors ALIGN(16): {
+ KEEP(*crtbegin*.o(.ctors))
+ KEEP(*(EXCLUDE_FILE(*crtend*.o) .ctors))
+ KEEP(*(SORT(.ctors.*)))
+ KEEP(*(.ctors))
+ }
+ .dtors ALIGN(16): {
+ KEEP(*crtbegin*.o(.dtors))
+ KEEP(*(EXCLUDE_FILE(*crtend*.o) .dtors))
+ KEEP(*(SORT(.dtors.*)))
+ KEEP(*(.dtors))
+ }
+
+ /* Static data. */
+ .rodata ALIGN(128): {
+ *(.rodata)
+ *(.rodata.*)
+ *(.gnu.linkonce.r*)
+ }
+
+ .data ALIGN(128): {
+ _fdata = . ;
+ *(.data)
+ *(.data.*)
+ *(.gnu.linkonce.d*)
+ SORT(CONSTRUCTORS)
+ }
+
+ .rdata ALIGN(128): { *(.rdata) }
+ .gcc_except_table ALIGN(128): { *(.gcc_except_table) }
+
+ _gp = ALIGN(128) + 0x7ff0;
+ .lit4 ALIGN(128): { *(.lit4) }
+ .lit8 ALIGN(128): { *(.lit8) }
+
+ .sdata ALIGN(128): {
+ *(.sdata)
+ *(.sdata.*)
+ *(.gnu.linkonce.s*)
+ }
+
+ _edata = .;
+ PROVIDE(edata = .);
+
+ /* Uninitialized data. */
+ .sbss ALIGN(128) : {
+ _fbss = . ;
+ *(.sbss)
+ *(.sbss.*)
+ *(.gnu.linkonce.sb*)
+ *(.scommon)
+ }
+
+ /*This "plugin hole" is so the plugins can all have global small data
+ in the same place.*/
+ __plugin_hole_start = .;
+ . = _gp + 0x7ff0;
+ __plugin_hole_end = .;
+
+ COMMON :
+ {
+ *(COMMON)
+ }
+ . = ALIGN(128);
+
+ .bss ALIGN(128) : {
+ *(.bss)
+ *(.bss.*)
+ *(.gnu.linkonce.b*)
+ }
+ _end_bss = .;
+
+ _end = . ;
+ PROVIDE(end = .);
+
+ /* Symbols needed by crt0.s. */
+ PROVIDE(_heap_size = -1);
+ PROVIDE(_stack = -1);
+ PROVIDE(_stack_size = 128 * 1024);
+}
diff --git a/backends/plugins/ps2/plugin.ld b/backends/plugins/ps2/plugin.ld
index 5692c8a07b..45efe4db7a 100644
--- a/backends/plugins/ps2/plugin.ld
+++ b/backends/plugins/ps2/plugin.ld
@@ -1 +1,94 @@
-dummy
+/* PHDRS specifies ELF Program Headers (or segments) to the plugin linker */
+PHDRS {
+ plugin PT_LOAD ; /* Specifies that the plugin segment should be loaded from file */
+ shorts PT_LOAD ; /* Specifies that the shorts segment should be loaded from file */
+}
+
+SECTIONS {
+ .text 0: {
+ _ftext = . ;
+ *(.text)
+ *(.text.*)
+ *(.gnu.linkonce.t*)
+ KEEP(*(.init))
+ KEEP(*(.fini))
+ QUAD(0)
+ } : plugin /*The ": plugin" tells the linker to assign this and
+ the following sections to the "plugin" segment*/
+ PROVIDE(_etext = .);
+ PROVIDE(etext = .);
+
+ .reginfo : { *(.reginfo) }
+
+ /* Global/static constructors and deconstructors. */
+ .ctors ALIGN(16): {
+ ___plugin_ctors = .;
+ KEEP(*(SORT(.ctors.*)))
+ KEEP(*(.ctors))
+ ___plugin_ctors_end = .;
+ }
+ .dtors ALIGN(16): {
+ ___plugin_dtors = .;
+ KEEP(*(SORT(.dtors.*)))
+ KEEP(*(.dtors))
+ ___plugin_dtors_end = .;
+ }
+
+ /* Static data. */
+ .rodata ALIGN(128): {
+ *(.rodata)
+ *(.rodata.*)
+ *(.gnu.linkonce.r*)
+ }
+
+ .data ALIGN(128): {
+ _fdata = . ;
+ *(.data)
+ *(.data.*)
+ *(.gnu.linkonce.d*)
+ SORT(CONSTRUCTORS)
+ }
+
+ .rdata ALIGN(128): { *(.rdata) }
+ .gcc_except_table ALIGN(128): { *(.gcc_except_table) }
+
+ .bss ALIGN(128) : {
+ *(.bss)
+ *(.bss.*)
+ *(.gnu.linkonce.b*)
+ *(COMMON)
+ }
+ _end_bss = .;
+
+ _end = . ;
+ PROVIDE(end = .);
+
+ /* Symbols needed by crt0.s. */
+ PROVIDE(_heap_size = -1);
+ PROVIDE(_stack = -1);
+ PROVIDE(_stack_size = 128 * 1024);
+
+ /*We assign the output location counter to the plugin hole made
+ in main_prog.ld, then assign the small data sections to the shorts segment*/
+ . = __plugin_hole_start;
+ .lit4 ALIGN(128): { *(.lit4) } : shorts
+ .lit8 ALIGN(128): { *(.lit8) }
+
+ .sdata ALIGN(128): {
+ *(.sdata)
+ *(.sdata.*)
+ *(.gnu.linkonce.s*)
+ }
+
+ _edata = .;
+ PROVIDE(edata = .);
+
+ /* Uninitialized data. */
+ .sbss ALIGN(128) : {
+ _fbss = . ;
+ *(.sbss)
+ *(.sbss.*)
+ *(.gnu.linkonce.sb*)
+ *(.scommon)
+ }
+}
diff --git a/backends/plugins/ps2/ps2-provider.cpp b/backends/plugins/ps2/ps2-provider.cpp
index 5692c8a07b..71e715ae50 100644
--- a/backends/plugins/ps2/ps2-provider.cpp
+++ b/backends/plugins/ps2/ps2-provider.cpp
@@ -1 +1,72 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(DYNAMIC_MODULES) && defined(__PLAYSTATION2__)
+
+#include "backends/plugins/ps2/ps2-provider.h"
+#include "backends/plugins/elf/mips-loader.h"
+
+class PS2DLObject : public MIPSDLObject {
+public:
+ PS2DLObject() :
+ MIPSDLObject() {
+ }
+
+ virtual ~PS2DLObject() {
+ unload();
+ }
+
+protected:
+ virtual void *allocSegment(size_t boundary, size_t size) const {
+ return memalign(boundary, size);
+ }
+
+ virtual void freeSegment(void *segment) const {
+ free(segment);
+ }
+
+ virtual void flushDataCache(void *, uint32) const {
+ FlushCache(0);
+ FlushCache(2);
+ }
+};
+
+class PS2Plugin : public ELFPlugin {
+public:
+ PS2Plugin(const Common::String &filename) :
+ ELFPlugin(filename) {
+ }
+
+ virtual DLObject *makeDLObject() {
+ return new PS2DLObject();
+ }
+};
+
+Plugin *PS2PluginProvider::createPlugin(const Common::FSNode &node) const {
+ return new PS2Plugin(node.getPath());
+}
+
+#endif // defined(DYNAMIC_MODULES) && defined(__PLAYSTATION2__)
+
diff --git a/backends/plugins/ps2/ps2-provider.h b/backends/plugins/ps2/ps2-provider.h
index 5692c8a07b..3d4b4b0128 100644
--- a/backends/plugins/ps2/ps2-provider.h
+++ b/backends/plugins/ps2/ps2-provider.h
@@ -1 +1,41 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(DYNAMIC_MODULES) && defined(__PLAYSTATION2__)
+
+#ifndef BACKENDS_PLUGINS_PS2_PROVIDER_H
+#define BACKENDS_PLUGINS_PS2_PROVIDER_H
+
+#include "backends/plugins/elf/elf-provider.h"
+
+class PS2PluginProvider : public ELFPluginProvider {
+public:
+ Plugin *createPlugin(const Common::FSNode &node) const;
+};
+
+#endif // BACKENDS_PLUGINS_PS2_PROVIDER_H
+
+#endif // defined(DYNAMIC_MODULES) && defined(__PLAYSTATION2__)
+
diff --git a/backends/plugins/psp/plugin.ld b/backends/plugins/psp/plugin.ld
index 5692c8a07b..a4456d199d 100644
--- a/backends/plugins/psp/plugin.ld
+++ b/backends/plugins/psp/plugin.ld
@@ -1 +1,238 @@
-dummy
+OUTPUT_FORMAT("elf32-littlemips", "elf32-bigmips", "elf32-littlemips")
+OUTPUT_ARCH(mips:allegrex)
+
+PHDRS
+{
+ plugin PT_LOAD ;
+ shorts PT_LOAD ;
+}
+
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = 0;
+ .interp : { *(.interp) } : plugin
+ .reginfo : { *(.reginfo) } : plugin
+ .dynamic : { *(.dynamic) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
+ .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ /* PSP-specific relocations. */
+ .rel.sceStub.text : { *(.rel.sceStub.text) *(SORT(.rel.sceStub.text.*)) }
+ .rel.lib.ent.top : { *(.rel.lib.ent.top) }
+ .rel.lib.ent : { *(.rel.lib.ent) }
+ .rel.lib.ent.btm : { *(.rel.lib.ent.btm) }
+ .rel.lib.stub.top : { *(.rel.lib.stub.top) }
+ .rel.lib.stub : { *(.rel.lib.stub) }
+ .rel.lib.stub.btm : { *(.rel.lib.stub.btm) }
+ .rel.rodata.sceModuleInfo : { *(.rel.rodata.sceModuleInfo) }
+ .rel.rodata.sceResident : { *(.rel.rodata.sceResident) }
+ .rel.rodata.sceNid : { *(.rel.rodata.sceNid) }
+ .rel.rodata.sceVstub : { *(.rel.rodata.sceVstub) *(SORT(.rel.rodata.sceVstub.*)) }
+ .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
+ .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
+ .rel.data.rel.ro : { *(.rel.data.rel.ro*) }
+ .rela.data.rel.ro : { *(.rel.data.rel.ro*) }
+ .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
+ .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
+ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
+ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
+ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
+ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) }
+ .rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) }
+ .rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) }
+ .rela.sbss : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) }
+ .rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) }
+ .rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) }
+ .rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) }
+ .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) }
+ .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
+ .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init :
+ {
+ KEEP (*(.init))
+ } =0
+ .plt : { *(.plt) }
+ .text :
+ {
+ _ftext = . ;
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ KEEP (*(.text.*personality*))
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.mips16.fn.*) *(.mips16.call.*)
+ } =0
+ .fini :
+ {
+ KEEP (*(.fini))
+ } =0
+ /* PSP library stub functions. */
+ .sceStub.text : { *(.sceStub.text) *(SORT(.sceStub.text.*)) }
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+ /* PSP library entry table and library stub table. */
+ .lib.ent.top : { *(.lib.ent.top) }
+ .lib.ent : { *(.lib.ent) }
+ .lib.ent.btm : { *(.lib.ent.btm) }
+ .lib.stub.top : { *(.lib.stub.top) }
+ .lib.stub : { *(.lib.stub) }
+ .lib.stub.btm : { *(.lib.stub.btm) }
+ /* PSP read-only data for module info, NIDs, and Vstubs. The
+ .rodata.sceModuleInfo section must appear before the .rodata section
+ otherwise it would get absorbed into .rodata and the PSP bootloader
+ would be unable to locate the module info structure. */
+ .rodata.sceModuleInfo : { *(.rodata.sceModuleInfo) }
+ .rodata.sceResident : { *(.rodata.sceResident) }
+ .rodata.sceNid : { *(.rodata.sceNid) }
+ .rodata.sceVstub : { *(.rodata.sceVstub) *(SORT(.rodata.sceVstub.*)) }
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+ .sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) }
+ .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) }
+ .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RO { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) }
+ /* 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(256) + (. & (256 - 1));
+ /* Exception handling */
+ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RW { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) }
+ /* Thread Local Storage sections */
+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+ /* Ensure the __preinit_array_start label is properly aligned. We
+ could instead move the label definition inside the section, but
+ the linker would then create the section even if it turns out to
+ be empty, which isn't pretty. */
+ . = ALIGN(32 / 8);
+ PROVIDE (__preinit_array_start = .);
+ .preinit_array : { KEEP (*(.preinit_array)) }
+ PROVIDE (__preinit_array_end = .);
+ PROVIDE (__init_array_start = .);
+ .init_array : { KEEP (*(.init_array)) }
+ PROVIDE (__init_array_end = .);
+ PROVIDE (__fini_array_start = .);
+ .fini_array : { KEEP (*(.fini_array)) }
+ PROVIDE (__fini_array_end = .);
+ .ctors :
+ {
+ ___plugin_ctors = .;
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ ___plugin_ctors_end = .;
+ }
+ .dtors :
+ {
+ ___plugin_dtors = .;
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ ___plugin_dtors_end = .;
+ }
+ .jcr : { KEEP (*(.jcr)) }
+ .data.rel.ro : { *(.data.rel.ro.local) *(.data.rel.ro*) }
+ .data :
+ {
+ _fdata = . ;
+ *(.data .data.* .gnu.linkonce.d.*)
+ KEEP (*(.gnu.linkonce.d.*personality*))
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ . = .;
+ .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. */
+ . = ALIGN(32 / 8);
+ }
+ . = ALIGN(32 / 8);
+ _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_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) }
+ /DISCARD/ : { *(.comment) *(.pdr) }
+ /DISCARD/ : { *(.note.GNU-stack) }
+
+ . = __plugin_hole_start;
+ .got : { *(.got.plt) *(.got) } : shorts
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata :
+ {
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ }
+ .lit8 : { *(.lit8) }
+ .lit4 : { *(.lit4) }
+ _edata = .;
+ PROVIDE (edata = .);
+ __bss_start = .;
+ _fbss = .;
+ .sbss :
+ {
+ PROVIDE (__sbss_start = .);
+ PROVIDE (___sbss_start = .);
+ *(.dynsbss)
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ PROVIDE (__sbss_end = .);
+ PROVIDE (___sbss_end = .);
+ }
+}
diff --git a/backends/plugins/psp/psp-provider.cpp b/backends/plugins/psp/psp-provider.cpp
index 5760424cbf..5bf9b0cc20 100644
--- a/backends/plugins/psp/psp-provider.cpp
+++ b/backends/plugins/psp/psp-provider.cpp
@@ -25,86 +25,51 @@
#if defined(DYNAMIC_MODULES) && defined(__PSP__)
-#include "backends/plugins/psp/psp-provider.h"
-#include "backends/plugins/dynamic-plugin.h"
-#include "common/fs.h"
+#include <psputils.h>
+#include <psputilsforkernel.h>
-#include "backends/platform/psp/psploader.h"
+#include "backends/plugins/psp/psp-provider.h"
+#include "backends/plugins/elf/mips-loader.h"
-#include "backends/platform/psp/trace.h"
+class PSPDLObject : public MIPSDLObject {
+public:
+ PSPDLObject() :
+ MIPSDLObject() {
+ }
+ virtual ~PSPDLObject() {
+ unload();
+ }
-class PSPPlugin : public DynamicPlugin {
protected:
- void *_dlHandle;
- Common::String _filename;
-
- virtual VoidFunc findSymbol(const char *symbol) {
- void *func = dlsym(_dlHandle, symbol);
- if (!func)
- warning("Failed loading symbol '%s' from plugin '%s' (%s)", symbol, _filename.c_str(), dlerror());
-
- // FIXME HACK: This is a HACK to circumvent a clash between the ISO C++
- // standard and POSIX: ISO C++ disallows casting between function pointers
- // and data pointers, but dlsym always returns a void pointer. For details,
- // see e.g. <http://www.trilithium.com/johan/2004/12/problem-with-dlsym/>.
- assert(sizeof(VoidFunc) == sizeof(func));
- VoidFunc tmp;
- memcpy(&tmp, &func, sizeof(VoidFunc));
- return tmp;
+ virtual void *allocSegment(size_t boundary, size_t size) const {
+ return memalign(boundary, size);
}
-public:
- PSPPlugin(const Common::String &filename)
- : _dlHandle(0), _filename(filename) {}
-
- ~PSPPlugin() {
- if (_dlHandle) unloadPlugin();
+ virtual void freeSegment(void *segment) const {
+ free(segment);
}
- bool loadPlugin() {
- assert(!_dlHandle);
- _dlHandle = dlopen(_filename.c_str(), RTLD_LAZY);
-
- if (!_dlHandle) {
- warning("Failed loading plugin '%s' (%s)", _filename.c_str(), dlerror());
- return false;
- }
-
- bool ret = DynamicPlugin::loadPlugin();
-
- if (ret)
- dlforgetsyms(_dlHandle);
+ virtual void flushDataCache(void *ptr, uint32 len) const {
+ sceKernelDcacheWritebackRange(ptr, len);
+ sceKernelIcacheInvalidateRange(ptr, len);
+ }
+};
- return ret;
+class PSPPlugin : public ELFPlugin {
+public:
+ PSPPlugin(const Common::String &filename) :
+ ELFPlugin(filename) {
}
- void unloadPlugin() {
- DynamicPlugin::unloadPlugin();
- if (_dlHandle) {
- if (dlclose(_dlHandle) != 0)
- warning("Failed unloading plugin '%s' (%s)", _filename.c_str(), dlerror());
- _dlHandle = 0;
- }
+ virtual DLObject *makeDLObject() {
+ return new PSPDLObject();
}
};
-
-Plugin* PSPPluginProvider::createPlugin(const Common::FSNode &node) const {
+Plugin *PSPPluginProvider::createPlugin(const Common::FSNode &node) const {
return new PSPPlugin(node.getPath());
}
-bool PSPPluginProvider::isPluginFilename(const Common::FSNode &node) const {
- // Check the plugin suffix
- Common::String filename = node.getName();
- PSP_DEBUG_PRINT("Testing name %s", filename.c_str());
- if (!filename.hasSuffix(".PLG") && !filename.hasSuffix(".plg")) {
- PSP_DEBUG_PRINT(" fail.\n");
- return false;
- }
-
- PSP_DEBUG_PRINT(" success!\n");
- return true;
-}
-
#endif // defined(DYNAMIC_MODULES) && defined(__PSP__)
+
diff --git a/backends/plugins/psp/psp-provider.h b/backends/plugins/psp/psp-provider.h
index d6c44c5a85..39e0d32caa 100644
--- a/backends/plugins/psp/psp-provider.h
+++ b/backends/plugins/psp/psp-provider.h
@@ -18,26 +18,24 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL$
- * $Id$
+ * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2010-plugins/backends/plugins/ds/ds-provider.h $
+ * $Id: ds-provider.h 52112 2010-08-16 08:41:04Z toneman1138 $
*
*/
-#ifndef BACKENDS_PLUGINS_PSP_PSP_PROVIDER_H
-#define BACKENDS_PLUGINS_PSP_PSP_PROVIDER_H
-
-#include "base/plugins.h"
-
#if defined(DYNAMIC_MODULES) && defined(__PSP__)
-class PSPPluginProvider : public FilePluginProvider {
-protected:
- Plugin* createPlugin(const Common::FSNode &node) const;
+#ifndef BACKENDS_PLUGINS_PSP_PSP_PROVIDER_H
+#define BACKENDS_PLUGINS_PSP_PSP_PROVIDER_H
- bool isPluginFilename(const Common::FSNode &node) const;
+#include "backends/plugins/elf/elf-provider.h"
+class PSPPluginProvider : public ELFPluginProvider {
+public:
+ Plugin *createPlugin(const Common::FSNode &node) const;
};
+#endif // BACKENDS_PLUGINS_PSP_PROVIDER_H
+
#endif // defined(DYNAMIC_MODULES) && defined(__PSP__)
-#endif /* BACKENDS_PLUGINS_PSP_PSP_PROVIDER_H */
diff --git a/backends/plugins/wii/plugin.ld b/backends/plugins/wii/plugin.ld
index 5692c8a07b..61b90d3394 100644
--- a/backends/plugins/wii/plugin.ld
+++ b/backends/plugins/wii/plugin.ld
@@ -1 +1,263 @@
-dummy
+/*
+ * Linkscript for Wii
+ */
+
+OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc");
+OUTPUT_ARCH(powerpc:common);
+
+PHDRS
+{
+ plugin PT_LOAD FLAGS(7);
+}
+
+SECTIONS
+{
+ . = 0x81000000;
+
+ /* Program */
+ .init :
+ {
+ KEEP (*crt0.o(*.init))
+ KEEP (*(.init))
+ } :plugin = 0
+ .plt : { *(.plt) }
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
+ .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
+ .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
+ .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
+ .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
+ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
+ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
+ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
+ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rela.got1 : { *(.rela.got1) }
+ .rela.got2 : { *(.rela.got2) }
+ .rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) }
+ .rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) }
+ .rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) }
+ .rela.sbss : { *(.rela.sbss .rela.sbss.* .rel.gnu.linkonce.sb.*) }
+ .rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) }
+ .rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) }
+ .rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) }
+ .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) }
+ .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
+ .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+
+ .text :
+ {
+ *(.text)
+ *(.text.*)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.gnu.linkonce.t.*)
+ . = ALIGN(32); /* REQUIRED. LD is flaky without it. */
+ } = 0
+
+ .fini :
+ {
+ KEEP (*(.fini))
+ . = ALIGN(32); /* REQUIRED. LD is flaky without it. */
+ } = 0
+
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+
+ .rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+ .sdata2 : { *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) }
+ .sbss2 : { *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) }
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ /* Ensure the __preinit_array_start label is properly aligned. We
+ could instead move the label definition inside the section, but
+ the linker would then create the section even if it turns out to
+ be empty, which isn't pretty. */
+ . = ALIGN(32 / 8);
+ PROVIDE (__preinit_array_start = .);
+ .preinit_array : { *(.preinit_array) }
+ PROVIDE (__preinit_array_end = .);
+ PROVIDE (__init_array_start = .);
+ .init_array : { *(.init_array) }
+ PROVIDE (__init_array_end = .);
+ PROVIDE (__fini_array_start = .);
+ .fini_array : { *(.fini_array) }
+ PROVIDE (__fini_array_end = .);
+ .data :
+ {
+ *(.data)
+ *(.data.*)
+ *(.gnu.linkonce.d.*)
+ SORT(CONSTRUCTORS)
+ . = ALIGN(32); /* REQUIRED. LD is flaky without it. */
+ }
+
+ .data1 : { *(.data1) }
+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+ .eh_frame : { KEEP (*(.eh_frame)) }
+ .gcc_except_table : { *(.gcc_except_table) }
+ .fixup : { *(.fixup) }
+ .got1 : { *(.got1) }
+ .got2 : { *(.got2) }
+ .dynamic : { *(.dynamic) }
+
+ .ctors :
+ {
+ ___plugin_ctors = .;
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ ___plugin_ctors_end = .;
+ . = ALIGN(32); /* REQUIRED. LD is flaky without it. */
+ }
+
+ .dtors :
+ {
+ ___plugin_dtors = .;
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ ___plugin_dtors_end = .;
+ . = ALIGN(32); /* REQUIRED. LD is flaky without it. */
+ }
+
+ .jcr : { KEEP (*(.jcr)) }
+ .got : { *(.got.plt) *(.got) }
+
+
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+
+ .sdata :
+ {
+ *(.sdata)
+ *(.sdata.*)
+ *(.gnu.linkonce.s.*)
+ . = ALIGN(32); /* REQUIRED. LD is flaky without it. */
+ }
+
+ _edata = .;
+ PROVIDE (edata = .);
+
+ .sbss :
+ {
+ __sbss_start = .;
+ PROVIDE (__sbss_start = .);
+ PROVIDE (___sbss_start = .);
+ *(.dynsbss)
+ *(.sbss)
+ *(.sbss.*)
+ *(.gnu.linkonce.sb.*)
+ *(.scommon)
+ PROVIDE (__sbss_end = .);
+ PROVIDE (___sbss_end = .);
+ . = ALIGN(32); /* REQUIRED. LD is flaky without it. */
+ __sbss_end = .;
+ }
+
+ .bss :
+ {
+ __bss_start = .;
+ PROVIDE (__bss_start = .);
+ *(.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. */
+
+ . = ALIGN(32);
+
+ PROVIDE (__bss_end = .);
+ __bss_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) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .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) }
+ /* These must appear regardless of . */
+}
+
+__isIPL = 0;
+__stack_addr = (__bss_start + SIZEOF(.bss) + 0x20000 + 7) & (-8);
+__stack_end = (__bss_start + SIZEOF(.bss));
+__intrstack_addr = (__stack_addr + 0x4000);
+__intrstack_end = (__stack_addr);
+__Arena1Lo = (__intrstack_addr + 31) & (-32);
+__Arena1Hi = (0x816ffff0);
+__Arena2Lo = (0x90002000);
+__Arena2Hi = (0x933E0000);
+
+__gxregs = (__Arena1Hi + 31) & (-32);
+__ipcbufferLo = (0x933e0000);
+__ipcbufferHi = (0x93400000);
+
+/* for backward compatibility with old crt0 */
+PROVIDE (__stack = (0x816ffff0));
+
+PROVIDE(__isIPL = __isIPL);
+PROVIDE(__stack_addr = __stack_addr);
+PROVIDE(__stack_end = __stack_end);
+PROVIDE(__intrstack_addr = __intrstack_addr);
+PROVIDE(__intrstack_end = __intrstack_end);
+PROVIDE(__Arena1Lo = __Arena1Lo);
+PROVIDE(__Arena1Hi = __Arena1Hi);
+PROVIDE(__Arena2Lo = __Arena2Lo);
+PROVIDE(__Arena2Hi = __Arena2Hi);
+PROVIDE(__ipcbufferLo = __ipcbufferLo);
+PROVIDE(__ipcbufferHi = __ipcbufferHi);
+PROVIDE(__gxregs = __gxregs);
diff --git a/backends/plugins/wii/wii-provider.cpp b/backends/plugins/wii/wii-provider.cpp
index 5692c8a07b..25f54f02de 100644
--- a/backends/plugins/wii/wii-provider.cpp
+++ b/backends/plugins/wii/wii-provider.cpp
@@ -1 +1,75 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(DYNAMIC_MODULES) && defined(__WII__)
+
+#include <malloc.h>
+#include <ogc/cache.h>
+
+#include "backends/plugins/wii/wii-provider.h"
+#include "backends/plugins/elf/ppc-loader.h"
+
+class WiiDLObject : public PPCDLObject {
+public:
+ WiiDLObject() :
+ PPCDLObject() {
+ }
+
+ virtual ~WiiDLObject() {
+ unload();
+ }
+
+protected:
+ virtual void *allocSegment(size_t boundary, size_t size) const {
+ return memalign(boundary, size);
+ }
+
+ virtual void freeSegment(void *segment) const {
+ free(segment);
+ }
+
+ virtual void flushDataCache(void *ptr, uint32 len) const {
+ DCFlushRange(ptr, len);
+ ICInvalidateRange(ptr, len);
+ }
+};
+
+class WiiPlugin : public ELFPlugin {
+public:
+ WiiPlugin(const Common::String &filename) :
+ ELFPlugin(filename) {
+ }
+
+ virtual DLObject *makeDLObject() {
+ return new WiiDLObject();
+ }
+};
+
+Plugin *WiiPluginProvider::createPlugin(const Common::FSNode &node) const {
+ return new WiiPlugin(node.getPath());
+}
+
+#endif // defined(DYNAMIC_MODULES) && defined(__WII__)
+
diff --git a/backends/plugins/wii/wii-provider.h b/backends/plugins/wii/wii-provider.h
index 5692c8a07b..4ec771490d 100644
--- a/backends/plugins/wii/wii-provider.h
+++ b/backends/plugins/wii/wii-provider.h
@@ -1 +1,41 @@
-dummy
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(DYNAMIC_MODULES) && defined(__WII__)
+
+#ifndef BACKENDS_PLUGINS_WII_PROVIDER_H
+#define BACKENDS_PLUGINS_WII_PROVIDER_H
+
+#include "backends/plugins/elf/elf-provider.h"
+
+class WiiPluginProvider : public ELFPluginProvider {
+public:
+ Plugin *createPlugin(const Common::FSNode &node) const;
+};
+
+#endif // BACKENDS_PLUGINS_WII_PROVIDER_H
+
+#endif // defined(DYNAMIC_MODULES) && defined(__WII__)
+