took out hacky 'ifdef MIPS_TARGET' statements in DLObject's methods and instead overrode those methods in MIPSDLObject
svn-id: r51827
This commit is contained in:
parent
0712d41870
commit
d6adeb9ccf
3 changed files with 109 additions and 68 deletions
|
@ -37,6 +37,11 @@
|
||||||
#include "common/fs.h"
|
#include "common/fs.h"
|
||||||
#include "elf-loader.h"
|
#include "elf-loader.h"
|
||||||
|
|
||||||
|
#ifdef __PSP__
|
||||||
|
#include "backends/platform/psp/powerman.h"
|
||||||
|
#include "psputils.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __DS__
|
#ifdef __DS__
|
||||||
#include <nds.h>
|
#include <nds.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -62,6 +67,9 @@ static void flushDataCache() {
|
||||||
FlushCache(0);
|
FlushCache(0);
|
||||||
FlushCache(2);
|
FlushCache(2);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef __PSP__
|
||||||
|
sceKernelDcacheWritebackAll();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expel the symbol table from memory
|
// Expel the symbol table from memory
|
||||||
|
@ -78,13 +86,6 @@ void DLObject::unload() {
|
||||||
discard_symtab();
|
discard_symtab();
|
||||||
free(_segment);
|
free(_segment);
|
||||||
_segment = NULL;
|
_segment = NULL;
|
||||||
|
|
||||||
#ifdef MIPS_TARGET
|
|
||||||
if (_shortsSegment) {
|
|
||||||
ShortsMan.deleteSegment(_shortsSegment);
|
|
||||||
_shortsSegment = NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DLObject::readElfHeader(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr) {
|
bool DLObject::readElfHeader(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr) {
|
||||||
|
@ -97,7 +98,7 @@ bool DLObject::readElfHeader(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehd
|
||||||
ehdr->e_machine != EM_ARM || // Check for ARM machine type
|
ehdr->e_machine != EM_ARM || // Check for ARM machine type
|
||||||
#endif
|
#endif
|
||||||
#ifdef MIPS_TARGET
|
#ifdef MIPS_TARGET
|
||||||
ehdr->e_machine != EM_MIPS ||
|
ehdr->e_machine != EM_MIPS || // Check for MIPS machine type
|
||||||
#endif
|
#endif
|
||||||
ehdr->e_phentsize < sizeof(Elf32_Phdr) || // Check for size of program header
|
ehdr->e_phentsize < sizeof(Elf32_Phdr) || // Check for size of program header
|
||||||
ehdr->e_shentsize != sizeof(Elf32_Shdr)) { // Check for size of section header
|
ehdr->e_shentsize != sizeof(Elf32_Shdr)) { // Check for size of section header
|
||||||
|
@ -137,33 +138,6 @@ bool DLObject::loadSegment(Common::SeekableReadStream* DLFile, Elf32_Phdr *phdr)
|
||||||
|
|
||||||
char *baseAddress = 0;
|
char *baseAddress = 0;
|
||||||
|
|
||||||
#ifdef MIPS_TARGET
|
|
||||||
// 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
|
|
||||||
DBG("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))) {
|
|
||||||
seterror("Out of memory.\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
DBG("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();
|
|
||||||
DBG("shorts segment @ %p to %p. Segment wants to be at %x. Offset=%x\n",
|
|
||||||
_shortsSegment->getStart(), _shortsSegment->getEnd(), phdr->p_vaddr, _shortsSegment->getOffset());
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// Attempt to allocate memory for segment
|
// Attempt to allocate memory for segment
|
||||||
int extra = phdr->p_vaddr % phdr->p_align; // Get extra length TODO: check logic here
|
int extra = phdr->p_vaddr % phdr->p_align; // Get extra length TODO: check logic here
|
||||||
DBG("extra mem is %x\n", extra);
|
DBG("extra mem is %x\n", extra);
|
||||||
|
@ -178,7 +152,6 @@ bool DLObject::loadSegment(Common::SeekableReadStream* DLFile, Elf32_Phdr *phdr)
|
||||||
// Get offset to load segment into
|
// Get offset to load segment into
|
||||||
baseAddress = (char *)_segment + phdr->p_vaddr;
|
baseAddress = (char *)_segment + phdr->p_vaddr;
|
||||||
_segmentSize = phdr->p_memsz + extra;
|
_segmentSize = phdr->p_memsz + extra;
|
||||||
#endif
|
|
||||||
|
|
||||||
// Set bss segment to 0 if necessary (assumes bss is at the end)
|
// Set bss segment to 0 if necessary (assumes bss is at the end)
|
||||||
if (phdr->p_memsz > phdr->p_filesz) {
|
if (phdr->p_memsz > phdr->p_filesz) {
|
||||||
|
@ -294,33 +267,13 @@ void DLObject::relocateSymbols(Elf32_Addr offset) {
|
||||||
Elf32_Sym *s = (Elf32_Sym *)_symtab;
|
Elf32_Sym *s = (Elf32_Sym *)_symtab;
|
||||||
for (int c = _symbol_cnt; c--; s++) {
|
for (int c = _symbol_cnt; c--; s++) {
|
||||||
|
|
||||||
#ifdef MIPS_TARGET
|
|
||||||
// Make sure we don't relocate special valued symbols
|
|
||||||
if (s->st_shndx < SHN_LOPROC) {
|
|
||||||
if (!ShortsMan.inGeneralSegment((char *)s->st_value)) {
|
|
||||||
mainCount++;
|
|
||||||
s->st_value += offset;
|
|
||||||
if (s->st_value < (Elf32_Addr)_segment || s->st_value > (Elf32_Addr)_segment + _segmentSize)
|
|
||||||
seterror("Symbol out of bounds! st_value = %x\n", s->st_value);
|
|
||||||
} else { // shorts section
|
|
||||||
shortsCount++;
|
|
||||||
s->st_value += _shortsSegment->getOffset();
|
|
||||||
if (!_shortsSegment->inSegment((char *)s->st_value))
|
|
||||||
seterror("Symbol out of bounds! st_value = %x\n", s->st_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// Make sure we don't relocate special valued symbols
|
// Make sure we don't relocate special valued symbols
|
||||||
if (s->st_shndx < SHN_LOPROC) {
|
if (s->st_shndx < SHN_LOPROC) {
|
||||||
mainCount++;
|
mainCount++;
|
||||||
s->st_value += offset;
|
s->st_value += offset;
|
||||||
if (s->st_value < (Elf32_Addr)_segment || s->st_value > (Elf32_Addr)_segment + _segmentSize)
|
if (s->st_value < (Elf32_Addr)_segment || s->st_value > (Elf32_Addr)_segment + _segmentSize)
|
||||||
seterror("Symbol out of bounds! st_value = %x\n", s->st_value);
|
seterror("Symbol out of bounds! st_value = %x\n", s->st_value);
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,6 +324,10 @@ bool DLObject::open(const char *path) {
|
||||||
Common::SeekableReadStream* DLFile;
|
Common::SeekableReadStream* DLFile;
|
||||||
void *ctors_start, *ctors_end;
|
void *ctors_start, *ctors_end;
|
||||||
|
|
||||||
|
#ifdef __PSP__
|
||||||
|
PowerMan.beginCriticalSection();
|
||||||
|
#endif
|
||||||
|
|
||||||
DBG("open(\"%s\")\n", path);
|
DBG("open(\"%s\")\n", path);
|
||||||
|
|
||||||
Common::FSNode file(path);
|
Common::FSNode file(path);
|
||||||
|
@ -390,6 +347,10 @@ bool DLObject::open(const char *path) {
|
||||||
|
|
||||||
DBG("loaded!/n");
|
DBG("loaded!/n");
|
||||||
|
|
||||||
|
#ifdef __PSP__
|
||||||
|
PowerMan.endCriticalSection();
|
||||||
|
#endif
|
||||||
|
|
||||||
flushDataCache();
|
flushDataCache();
|
||||||
|
|
||||||
ctors_start = symbol("___plugin_ctors");
|
ctors_start = symbol("___plugin_ctors");
|
||||||
|
|
|
@ -30,10 +30,6 @@
|
||||||
#include "common/stream.h"
|
#include "common/stream.h"
|
||||||
#include "backends/plugins/dynamic-plugin.h"
|
#include "backends/plugins/dynamic-plugin.h"
|
||||||
|
|
||||||
#if defined(MIPS_TARGET)
|
|
||||||
#include "shorts-segment-manager.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class DLObject {
|
class DLObject {
|
||||||
protected:
|
protected:
|
||||||
void *_segment, *_symtab;
|
void *_segment, *_symtab;
|
||||||
|
@ -44,23 +40,18 @@ protected:
|
||||||
|
|
||||||
int _segmentSize;
|
int _segmentSize;
|
||||||
|
|
||||||
#ifdef MIPS_TARGET
|
|
||||||
ShortSegmentManager::Segment *_shortsSegment; // For assigning shorts ranges
|
|
||||||
unsigned int _gpVal; // Value of Global Pointer
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//void seterror(const char *fmt, ...);
|
//void seterror(const char *fmt, ...);
|
||||||
void unload();
|
virtual void unload();
|
||||||
virtual bool relocate(Common::SeekableReadStream* DLFile, unsigned long offset, unsigned long size, void *relSegment) = 0;
|
virtual bool relocate(Common::SeekableReadStream* DLFile, unsigned long offset, unsigned long size, void *relSegment) = 0;
|
||||||
bool load(Common::SeekableReadStream* DLFile);
|
bool load(Common::SeekableReadStream* DLFile);
|
||||||
|
|
||||||
bool readElfHeader(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr);
|
bool readElfHeader(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr);
|
||||||
bool readProgramHeaders(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, int num);
|
bool readProgramHeaders(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, int num);
|
||||||
bool loadSegment(Common::SeekableReadStream* DLFile, Elf32_Phdr *phdr);
|
virtual bool loadSegment(Common::SeekableReadStream* DLFile, Elf32_Phdr *phdr);
|
||||||
Elf32_Shdr *loadSectionHeaders(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr);
|
Elf32_Shdr *loadSectionHeaders(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr);
|
||||||
int loadSymbolTable(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr);
|
int loadSymbolTable(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr);
|
||||||
bool loadStringTable(Common::SeekableReadStream* DLFile, Elf32_Shdr *shdr);
|
bool loadStringTable(Common::SeekableReadStream* DLFile, Elf32_Shdr *shdr);
|
||||||
void relocateSymbols(Elf32_Addr offset);
|
virtual void relocateSymbols(Elf32_Addr offset);
|
||||||
virtual bool relocateRels(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) = 0;
|
virtual bool relocateRels(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -259,4 +259,93 @@ bool MIPSDLObject::relocateRels(Common::SeekableReadStream* DLFile, Elf32_Ehdr *
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MIPSDLObject::relocateSymbols(Elf32_Addr offset) {
|
||||||
|
|
||||||
|
int mainCount = 0;
|
||||||
|
int shortsCount= 0;
|
||||||
|
|
||||||
|
// 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)) {
|
||||||
|
mainCount++;
|
||||||
|
s->st_value += offset;
|
||||||
|
if (s->st_value < (Elf32_Addr)_segment || s->st_value > (Elf32_Addr)_segment + _segmentSize)
|
||||||
|
seterror("Symbol out of bounds! st_value = %x\n", s->st_value);
|
||||||
|
} else { // shorts section
|
||||||
|
shortsCount++;
|
||||||
|
s->st_value += _shortsSegment->getOffset();
|
||||||
|
if (!_shortsSegment->inSegment((char *)s->st_value))
|
||||||
|
seterror("Symbol out of bounds! st_value = %x\n", s->st_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MIPSDLObject::loadSegment(Common::SeekableReadStream* DLFile, Elf32_Phdr *phdr) {
|
||||||
|
|
||||||
|
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
|
||||||
|
DBG("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))) {
|
||||||
|
seterror("Out of memory.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DBG("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();
|
||||||
|
DBG("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) {
|
||||||
|
DBG("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);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG("Reading the segment into memory\n");
|
||||||
|
|
||||||
|
// Read the segment into memory
|
||||||
|
if (DLFile->seek(phdr->p_offset, SEEK_SET) < 0 ||
|
||||||
|
DLFile->read(baseAddress, phdr->p_filesz) != (ssize_t)phdr->p_filesz) {
|
||||||
|
seterror("Segment load failed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG("Segment has been read into memory\n");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unload all objects from memory
|
||||||
|
void MIPSDLObject::unload() {
|
||||||
|
discard_symtab();
|
||||||
|
free(_segment);
|
||||||
|
_segment = NULL;
|
||||||
|
|
||||||
|
if (_shortsSegment) {
|
||||||
|
ShortsMan.deleteSegment(_shortsSegment);
|
||||||
|
_shortsSegment = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* defined(DYNAMIC_MODULES) && defined(MIPS_TARGET) */
|
#endif /* defined(DYNAMIC_MODULES) && defined(MIPS_TARGET) */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue