got rid of gp2xwiz loader (anything useful from it is already incorporated into the ARM loader in the plugins directory at this point) and implemented ARMDLObject as a subtype of DLObject

svn-id: r51813
This commit is contained in:
Tony Puccinelli 2010-08-06 23:30:27 +00:00
parent 66225374b2
commit 646587f79a
11 changed files with 22 additions and 1004 deletions

View file

@ -1,192 +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 BACKENDS_ELF_H
#define BACKENDS_ELF_H
/* ELF stuff */
typedef unsigned short Elf32_Half, Elf32_Section;
typedef unsigned int Elf32_Word, Elf32_Addr, Elf32_Off;
typedef signed int Elf32_Sword;
typedef Elf32_Half Elf32_Versym;
#define EI_NIDENT (16)
#define SELFMAG 6
/* ELF File format structures. Look up ELF structure for more details */
// ELF header (contains info about the file)
typedef struct {
unsigned char 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\1\1" /* ELF Magic number */
// 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_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_ARM_ARCHEXT 0x70000000 /* Platform architecture compatibility information */
#define PT_ARM_EXIDX 0x70000001 /* Exception unwind tables */
// 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_ARM_EXIDX 0x70000001 /* Exception Index table */
#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking pre-emption map */
#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility attributes */
// sh_flags values
#define SHF_WRITE 0 /* writable section */
#define SHF_ALLOC 2 /* section occupies memory */
#define SHF_EXECINSTR 4 /* machine instructions */
// 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 */
unsigned char st_info; /* Symbol type and binding */
unsigned char 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 (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) ((unsigned char) (x)) /* Extract relocation type */
#define REL_INDEX(x) ((x)>>8) /* Extract relocation index into symbol table */
// ARM relocation types
#define R_ARM_NONE 0
#define R_ARM_PC24 1
#define R_ARM_ABS32 2
#define R_ARM_COPY 20
#define R_ARM_GLOB_DAT 21
#define R_ARM_JUMP_SLOT 22
#define R_ARM_BASE_PREL 25
#define R_ARM_GOT_BREL 26
#define R_ARM_PLT32 27
#endif /* BACKENDS_ELF_H */

View file

@ -1,485 +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(GP2XWIZ)
#include <string.h>
#include <stdarg.h>
#include <stdarg.h>
#include <stdio.h>
#include <malloc.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include "backends/platform/gp2xwiz/gp2xwiz-loader.h"
#define __WIZ_DEBUG_PLUGINS__
#ifdef __WIZ_DEBUG_PLUGINS__
#define DBG(x,...) printf(x, ## __VA_ARGS__)
#else
#define DBG(x,...)
#endif
#define seterror(x,...) fprintf(stderr,x, ## __VA_ARGS__)
// Expel the symbol table from memory
void DLObject::discard_symtab() {
free(_symtab);
free(_strtab);
_symtab = NULL;
_strtab = NULL;
_symbol_cnt = 0;
}
// Unload all objects from memory
void DLObject::unload() {
discard_symtab();
free(_segment);
_segment = NULL;
}
/**
* Follow the instruction of a relocation section.
*
* @param fd File Descriptor
* @param offset Offset into the File
* @param size Size of relocation section
*
*/
bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void *relSegment) {
Elf32_Rela *rela; //relocation entry
// Allocate memory for relocation table
if (!(rela = (Elf32_Rela *)malloc(size))) {
seterror("Out of memory.");
return false;
}
// Read in our relocation table
if (lseek(fd, offset, SEEK_SET) < 0 ||
read(fd, rela, size) != (ssize_t)size) {
seterror("Relocation table load failed.");
free(rela);
return false;
}
// Treat each relocation entry. Loop over all of them
int cnt = size / sizeof(*rela);
// TODO: Loop over relocation entries
for (int i = 0; i < cnt; i++) {
DBG("attempting to relocate!");
//Elf32_Sym *sym = ???;
//void *target = ???;
/*switch (REL_TYPE()) {*/
//case ??? :
//TODO: Cases for each relocation type.
//break;
// default:
//seterror("Unknown relocation type %d.", ?? ?);
free(rela);
return false;
// }
}
free(rela);
return true;
}
bool DLObject::readElfHeader(int fd, Elf32_Ehdr *ehdr) {
// 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_ARM || // Check for ARM 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
seterror("Invalid file type.");
return false;
}
DBG("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) {
// Read program header
if (lseek(fd, ehdr->e_phoff + sizeof(*phdr)*num, SEEK_SET) < 0 ||
read(fd, phdr, sizeof(*phdr)) != sizeof(*phdr)) {
seterror("Program header load failed.");
return false;
}
// Check program header values
if (phdr->p_type != PT_LOAD || phdr->p_filesz > phdr->p_memsz) {
seterror("Invalid program header.");
return false;
}
DBG("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) {
char *baseAddress = 0;
// 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 (!(_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;
// 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);
}
// 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) {
seterror("Segment load failed.");
return false;
}
return true;
}
Elf32_Shdr * DLObject::loadSectionHeaders(int fd, Elf32_Ehdr *ehdr) {
Elf32_Shdr *shdr = NULL;
// Allocate memory for section headers
if (!(shdr = (Elf32_Shdr *)malloc(ehdr->e_shnum * sizeof(*shdr)))) {
seterror("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))) {
seterror("Section headers load failed.");
return NULL;
}
return shdr;
}
int DLObject::loadSymbolTable(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
// Loop over sections, looking for symbol table linked to a string table
for (int 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) {
seterror("No symbol table.");
return -1;
}
DBG("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))) {
seterror("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) {
seterror("Symbol table load failed.");
return -1;
}
// Set number of symbols
_symbol_cnt = shdr[_symtab_sect].sh_size / sizeof(Elf32_Sym);
DBG("Loaded %d symbols.\n", _symbol_cnt);
return _symtab_sect;
}
bool DLObject::loadStringTable(int fd, Elf32_Shdr *shdr) {
int string_sect = shdr[_symtab_sect].sh_link;
// Allocate memory for string table
if (!(_strtab = (char *)malloc(shdr[string_sect].sh_size))) {
seterror("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) {
seterror("Symbol table strings load failed.");
return false;
}
return true;
}
void DLObject::relocateSymbols(Elf32_Addr offset) {
int relocCount = 0;
DBG("Relocating symbols by %x\n", offset);
// 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) {
relocCount++;
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);
}
}
DBG("Relocated %d symbols.\n",relocCount);
}
bool DLObject::relocateRels(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
// 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_Rela) && // 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 (!relocate(fd, curShdr->sh_offset, curShdr->sh_size, _segment)) {
return false;
}
}
}
return true;
}
bool DLObject::load(int fd) {
Elf32_Ehdr ehdr;
Elf32_Phdr phdr;
Elf32_Shdr *shdr;
bool ret = true;
//int symtab_sect = -1;
if (readElfHeader(fd, &ehdr) == false) {
return false;
}
for (int i = 0; i < ehdr.e_phnum; i++) { // Load our 2 segments
fprintf(stderr, "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); // 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) {
int fd;
void *ctors_start, *ctors_end;
DBG(("open(\"%s\")\n", path));
if ((fd = ::open(path, O_RDONLY)) < 0) {
seterror("%s not found.", path);
return false;
}
// Try to load and relocate
if (!load(fd)) {
::close(fd);
unload();
return false;
}
::close(fd);
//TODO: flush data cache
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) {
seterror("Missing ctors/dtors.");
_dtors_start = _dtors_end = NULL;
unload();
return false;
}
DBG(("Calling constructors.\n"));
for (void (**f)(void) = (void (**)(void))ctors_start; f != ctors_end; f++)
(**f)();
DBG(("%s opened ok.\n", path));
return true;
}
bool DLObject::close() {
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) {
DBG(("symbol(\"%s\")\n", name));
if (_symtab == NULL || _strtab == NULL || _symbol_cnt < 1) {
seterror("No symbol table loaded.");
return NULL;
}
Elf32_Sym *s = (Elf32_Sym *)_symtab;
for (int c = _symbol_cnt; c--; s++)
//TODO: Figure out which symbols should be detected here
if ((s->st_info >> 4 == 1 || s->st_info >> 4 == 2) &&
_strtab[s->st_name] == '_' && !strcmp(name, _strtab + s->st_name + 1)) {
// We found the symbol
DBG("=> %p\n", (void*)s->st_value);
return (void*)s->st_value;
}
// We didn't find the symbol
seterror("Symbol \"%s\" not found.", name);
return NULL;
}
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 && GP2XWIZ */

View file

@ -1,79 +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 GP2XWIZ_LOADER_H
#define GP2XWIZ_LOADER_H
#include "elf32.h"
#define MAXDLERRLEN 80
class DLObject {
protected:
char *_errbuf; /* For error messages, at least MAXDLERRLEN in size */
void *_segment, *_symtab;
char *_strtab;
int _symbol_cnt;
int _symtab_sect;
void *_dtors_start, *_dtors_end;
int _segmentSize;
void seterror(const char *fmt, ...);
void unload();
bool relocate(int fd, unsigned long offset, unsigned long size, void *relSegment);
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);
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), _segment(NULL),_symtab(NULL),
_strtab(NULL), _symbol_cnt(0), _dtors_start(NULL), _dtors_end(NULL) {}
};
#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 /* GP2XWIZ_LOADER_H */

View file

@ -1,182 +0,0 @@
/* Script for -z combreloc: combine and sort reloc sections */
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm",
"elf32-littlearm")
OUTPUT_ARCH(arm)
PHDRS
{
plugin PT_LOAD ;
}
/* Do we need any of these for elf?
__DYNAMIC = 0; */
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0;
.interp : { *(.interp) } : plugin
.hash : { *(.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.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.*)
}
.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.*)
}
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init :
{
KEEP (*(.init))
} =0
.plt : { *(.plt) }
.text :
{
*(.text .stub .text.* .gnu.linkonce.t.*)
KEEP (*(.text.*personality*))
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.glue_7t) *(.glue_7)
} =0
.fini :
{
KEEP (*(.fini))
} =0
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.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 (0x8000) - ((0x8000 - .) & (0x8000 - 1)); . = DATA_SEGMENT_ALIGN (0x8000, 0x1000);
/* 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*) }
.dynamic : { *(.dynamic) }
. = DATA_SEGMENT_RELRO_END (0, .);
.got : { *(.got.plt) *(.got) }
.data :
{
__data_start = . ;
*(.data .data.* .gnu.linkonce.d.*)
KEEP (*(.gnu.linkonce.d.*personality*))
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. */
. = ALIGN(32 / 8);
}
. = ALIGN(32 / 8);
_end = .;
_bss_end__ = . ; __bss_end__ = . ; __end__ = . ;
PROVIDE (end = .);
. = DATA_SEGMENT_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) }
.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }
/DISCARD/ : { *(.note.GNU-stack) }
}

View file

@ -1,8 +0,0 @@
PLUGIN_getVersion
PLUGIN_getType
PLUGIN_getTypeVersion
PLUGIN_getObject
___plugin_ctors
___plugin_ctors_end
___plugin_dtors
___plugin_dtors_end

View file

@ -23,9 +23,12 @@
*
*/
#if defined(DYNAMIC_MODULES) && defined(ARM)
#include "backends/fs/ds/ds-fs.h"
#include "elf-loader.h"
#include "dsmain.h"
#include "arm-loader.h"
#define __DEBUG_PLUGINS__
@ -45,7 +48,7 @@
* @param size Size of relocation section
*
*/
bool DLObject::relocate(Common::SeekableReadStream* DLFile, unsigned long offset, unsigned long size, void *relSegment) {
bool ARMDLObject::relocate(Common::SeekableReadStream* DLFile, unsigned long offset, unsigned long size, void *relSegment) {
Elf32_Rel *rel = NULL; //relocation entry
// Allocate memory for relocation table
@ -135,7 +138,7 @@ bool DLObject::relocate(Common::SeekableReadStream* DLFile, unsigned long offset
return true;
}
bool DLObject::relocateRels(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
bool ARMDLObject::relocateRels(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
// Loop over sections, finding relocation sections
for (int i = 0; i < ehdr->e_shnum; i++) {
@ -162,3 +165,5 @@ bool DLObject::relocateRels(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr
return true;
}
#endif /* defined(DYNAMIC_MODULES) && defined(ARM) */

View file

@ -23,15 +23,18 @@
*
*/
#if defined(DYNAMIC_MODULES) && defined(__DS__)
/*#include "base/plugins.h"
#include "backends/plugins/dynamic-plugin.h"
#include "common/fs.h"
#include "backends/plugins/elf-loader.h"*/
#include "backends/plugins/arm-loader.h"
#include "backends/plugins/elf-provider.h"
#include "backends/plugins/ds/ds-provider.h"
#if defined(DYNAMIC_MODULES) && defined(__DS__)
class DSPlugin : public ELFPlugin {
public:
@ -50,7 +53,7 @@ public:
bool DSPlugin::loadPlugin() {
assert(!_dlHandle);
DLObject *obj = new DLObject(NULL);
DLObject *obj = new ARMDLObject();
if (obj->open(_filename.c_str())) {
_dlHandle = obj;
} else {

View file

@ -25,11 +25,8 @@
#include "backends/plugins/elf-provider.h"
#if defined(DYNAMIC_MODULES) && defined(ELF_LOADER_TARGET)
class DSPluginProvider : public ELFPluginProvider {
Plugin* createPlugin(const Common::FSNode &node) const;
};
#endif // defined(DYNAMIC_MODULES) && defined(ELF_LOADER_TARGET)

View file

@ -28,6 +28,7 @@
#include "elf32.h"
#include "common/stream.h"
#include "backends/plugins/dynamic-plugin.h"
#if defined(__PLAYSTATION2__) || defined(__PSP__)
#define MIPS_TARGET
@ -38,12 +39,8 @@
#define ARM_TARGET
#endif
#define MAXDLERRLEN 80
class DLObject {
protected:
char *_errbuf; /* For error messages, at least MAXDLERRLEN in size */
void *_segment, *_symtab;
char *_strtab;
int _symbol_cnt;
@ -57,9 +54,9 @@ protected:
unsigned int _gpVal; // Value of Global Pointer
#endif
void seterror(const char *fmt, ...);
//void seterror(const char *fmt, ...);
void unload();
virtual bool relocate(Common::SeekableReadStream* DLFile, unsigned long offset, unsigned long size, void *relSegment);
virtual bool relocate(Common::SeekableReadStream* DLFile, unsigned long offset, unsigned long size, void *relSegment) = 0;
bool load(Common::SeekableReadStream* DLFile);
bool readElfHeader(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr);
@ -69,7 +66,7 @@ protected:
int loadSymbolTable(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr);
bool loadStringTable(Common::SeekableReadStream* DLFile, Elf32_Shdr *shdr);
void relocateSymbols(Elf32_Addr offset);
virtual bool relocateRels(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr);
virtual bool relocateRels(Common::SeekableReadStream* DLFile, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) = 0;
public:
bool open(const char *path);
@ -77,15 +74,6 @@ public:
void *symbol(const char *name);
void discard_symtab();
DLObject(char *errbuf = NULL) : _errbuf(errbuf), _segment(NULL), _symtab(NULL),
_strtab(NULL), _symbol_cnt(0), _symtab_sect(-1), _dtors_start(NULL), _dtors_end(NULL),
_segmentSize(0) {
#ifdef MIPS_TARGET
_shortsSegment = NULL;
_gpVal = 0;
#endif
}
};
#endif /* LOADER_H */
#endif /* ELF_LOADER_H */

View file

@ -23,14 +23,14 @@
*
*/
#if defined(DYNAMIC_MODULES) && defined(ELF_LOADER_TARGET)
#include "backends/plugins/elf-provider.h"
#include "backends/plugins/dynamic-plugin.h"
#include "common/fs.h"
#include "backends/plugins/elf-loader.h"
#if defined(DYNAMIC_MODULES) && defined(ELF_LOADER_TARGET)
DynamicPlugin::VoidFunc ELFPlugin::findSymbol(const char *symbol) {
void *func;
bool handleNull;
@ -58,30 +58,6 @@ DynamicPlugin::VoidFunc ELFPlugin::findSymbol(const char *symbol) {
return tmp;
}
bool ELFPlugin::loadPlugin() {
assert(!_dlHandle);
DLObject *obj = new DLObject(NULL);
if (obj->open(_filename.c_str())) {
_dlHandle = obj;
} else {
delete obj;
_dlHandle = NULL;
}
if (!_dlHandle) {
warning("Failed loading plugin '%s'", _filename.c_str());
return false;
}
bool ret = DynamicPlugin::loadPlugin();
if (ret && _dlHandle) {
_dlHandle->discard_symtab();
}
return ret;
}
void ELFPlugin::unloadPlugin() {
DynamicPlugin::unloadPlugin();
if (_dlHandle) {
@ -93,11 +69,6 @@ void ELFPlugin::unloadPlugin() {
}
}
Plugin* ELFPluginProvider::createPlugin(const Common::FSNode &node) const {
return new ELFPlugin(node.getPath());
}
bool ELFPluginProvider::isPluginFilename(const Common::FSNode &node) const {
// Check the plugin suffix
Common::String filename = node.getName();

View file

@ -53,14 +53,14 @@ public:
unloadPlugin();
}
virtual bool loadPlugin();
virtual void unloadPlugin();
virtual bool loadPlugin() = 0;
void unloadPlugin();
};
class ELFPluginProvider : public FilePluginProvider {
protected:
virtual Plugin* createPlugin(const Common::FSNode &node) const;
virtual Plugin* createPlugin(const Common::FSNode &node) const = 0;
bool isPluginFilename(const Common::FSNode &node) const;