aboutsummaryrefslogtreecommitdiff
path: root/backends
diff options
context:
space:
mode:
authorAndre Heider2010-09-05 12:38:58 +0000
committerAndre Heider2010-09-05 12:38:58 +0000
commitc5a189f4d5f5a9f94b7e063077ba0ee5aaf1a788 (patch)
tree2d6038c0230e8a5ddb238bf61631aebbb726ee07 /backends
parentee2f4ef18963c4f3339a3cbdd5424fc0f36661c0 (diff)
downloadscummvm-rg350-c5a189f4d5f5a9f94b7e063077ba0ee5aaf1a788.tar.gz
scummvm-rg350-c5a189f4d5f5a9f94b7e063077ba0ee5aaf1a788.tar.bz2
scummvm-rg350-c5a189f4d5f5a9f94b7e063077ba0ee5aaf1a788.zip
PLUGINS: Respect the VMA when relocating.
Plugins do not have to be linked at 0x0. Some platforms have limited relocation jump offsets, which makes 0x0 unusable. svn-id: r52551
Diffstat (limited to 'backends')
-rw-r--r--backends/plugins/elf-loader.cpp25
-rw-r--r--backends/plugins/elf-loader.h10
2 files changed, 28 insertions, 7 deletions
diff --git a/backends/plugins/elf-loader.cpp b/backends/plugins/elf-loader.cpp
index b058f06e86..406f99913e 100644
--- a/backends/plugins/elf-loader.cpp
+++ b/backends/plugins/elf-loader.cpp
@@ -63,6 +63,22 @@ static void flushDataCache(void *ptr, uint32 len) {
#endif
}
+DLObject::DLObject() :
+ _segment(0),
+ _symtab(0),
+ _strtab(0),
+ _symbol_cnt(0),
+ _symtab_sect(-1),
+ _dtors_start(0),
+ _dtors_end(0),
+ _segmentSize(0),
+ _segmentOffset(0) {
+}
+
+DLObject::~DLObject() {
+ unload();
+}
+
// Expel the symbol table from memory
void DLObject::discard_symtab() {
free(_symtab);
@@ -276,7 +292,7 @@ bool DLObject::loadStringTable(Common::SeekableReadStream* DLFile, Elf32_Shdr *s
return true;
}
-void DLObject::relocateSymbols(Elf32_Addr offset) {
+void DLObject::relocateSymbols(ptrdiff_t offset) {
// Loop over symbols, add relocation offset
Elf32_Sym *s = (Elf32_Sym *)_symtab;
for (int c = _symbol_cnt; c--; s++) {
@@ -318,8 +334,11 @@ bool DLObject::load(Common::SeekableReadStream* DLFile) {
if (ret && (loadStringTable(DLFile, shdr) == false))
ret = false;
- if (ret)
- relocateSymbols((Elf32_Addr)_segment); // Offset by our segment allocated address
+ if (ret) {
+ // Offset by our segment allocated address
+ _segmentOffset = ptrdiff_t(_segment) - phdr.p_vaddr;
+ relocateSymbols(_segmentOffset);
+ }
if (ret && (relocateRels(DLFile, &ehdr, shdr) == false))
ret = false;
diff --git a/backends/plugins/elf-loader.h b/backends/plugins/elf-loader.h
index 93a6a15309..8d974eccb7 100644
--- a/backends/plugins/elf-loader.h
+++ b/backends/plugins/elf-loader.h
@@ -28,6 +28,8 @@
#ifndef ELF_LOADER_H
#define ELF_LOADER_H
+#include <stddef.h>
+
#include "backends/plugins/dynamic-plugin.h"
#include "backends/plugins/elf32.h"
@@ -49,6 +51,7 @@ protected:
void *_dtors_start, *_dtors_end;
uint32 _segmentSize;
+ ptrdiff_t _segmentOffset;
virtual void unload();
virtual bool relocate(Common::SeekableReadStream* DLFile, unsigned long offset, unsigned long size, void *relSegment) = 0;
@@ -60,7 +63,7 @@ protected:
Elf32_Shdr *loadSectionHeaders(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr);
int loadSymbolTable(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr);
bool loadStringTable(Common::SeekableReadStream* DLFile, Elf32_Shdr *shdr);
- virtual void relocateSymbols(Elf32_Addr offset);
+ virtual void relocateSymbols(ptrdiff_t offset);
virtual bool relocateRels(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) = 0;
public:
@@ -69,9 +72,8 @@ public:
void *symbol(const char *name);
void discard_symtab();
- DLObject() : _segment(NULL), _symtab(NULL), _strtab(NULL), _symbol_cnt(0),
- _symtab_sect(-1), _dtors_start(NULL), _dtors_end(NULL), _segmentSize(0) {}
- virtual ~DLObject() { unload(); }
+ DLObject();
+ virtual ~DLObject();
};
#endif /* ELF_LOADER_H */