diff options
author | Andre Heider | 2010-09-05 12:38:58 +0000 |
---|---|---|
committer | Andre Heider | 2010-09-05 12:38:58 +0000 |
commit | c5a189f4d5f5a9f94b7e063077ba0ee5aaf1a788 (patch) | |
tree | 2d6038c0230e8a5ddb238bf61631aebbb726ee07 /backends | |
parent | ee2f4ef18963c4f3339a3cbdd5424fc0f36661c0 (diff) | |
download | scummvm-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.cpp | 25 | ||||
-rw-r--r-- | backends/plugins/elf-loader.h | 10 |
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 */ |