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:
parent
66225374b2
commit
646587f79a
11 changed files with 22 additions and 1004 deletions
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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) }
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
PLUGIN_getVersion
|
||||
PLUGIN_getType
|
||||
PLUGIN_getTypeVersion
|
||||
PLUGIN_getObject
|
||||
___plugin_ctors
|
||||
___plugin_ctors_end
|
||||
___plugin_dtors
|
||||
___plugin_dtors_end
|
|
@ -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) */
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue