aboutsummaryrefslogtreecommitdiff
path: root/backends/dc/dcloader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'backends/dc/dcloader.cpp')
-rw-r--r--backends/dc/dcloader.cpp441
1 files changed, 0 insertions, 441 deletions
diff --git a/backends/dc/dcloader.cpp b/backends/dc/dcloader.cpp
deleted file mode 100644
index 2ce853c061..0000000000
--- a/backends/dc/dcloader.cpp
+++ /dev/null
@@ -1,441 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Dreamcast port
- * Copyright (C) 2002-2004 Marcus Comstedt
- *
- * 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$
- *
- */
-
-#include <common/stdafx.h>
-#include <ronin/ronin.h>
-#include <string.h>
-#include <stdarg.h>
-
-#include "dcloader.h"
-
-#ifdef DL_DEBUG
-#define DBG(...) reportf(__VA_ARGS__)
-#else
-#define DBG(...) 0
-#endif
-
-
-/* ELF stuff */
-
-typedef unsigned short Elf32_Half, Elf32_Section;
-typedef unsigned long Elf32_Word, Elf32_Addr, Elf32_Off;
-typedef signed long Elf32_Sword;
-typedef Elf32_Half Elf32_Versym;
-
-#define EI_NIDENT (16)
-#define ELFMAG "\177ELF\1\1"
-#define SELFMAG 6
-
-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;
-
-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;
-
-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;
-
-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;
-
-typedef struct
-{
- Elf32_Addr r_offset; /* Address */
- Elf32_Word r_info; /* Relocation type and symbol index */
- Elf32_Sword r_addend; /* Addend */
-} Elf32_Rela;
-
-
-
-extern "C" void flush_instruction_cache();
-
-static void purge_copyback()
-{
- int i;
- for(i=0; i!=(1<<14); i+=(1<<5))
- *(volatile unsigned int *)(0xf4000000+i) &= ~3;
-}
-
-
-void DLObject::seterror(const char *fmt, ...)
-{
- if(errbuf) {
- va_list va;
- va_start(va, fmt);
- vsnprintf(errbuf, MAXDLERRLEN, fmt, va);
- va_end(va);
- }
-}
-
-void DLObject::discard_symtab()
-{
- free(symtab);
- free(strtab);
- symtab = NULL;
- strtab = NULL;
- symbol_cnt = 0;
-}
-
-void DLObject::unload()
-{
- discard_symtab();
- free(segment);
- segment = NULL;
-}
-
-bool DLObject::relocate(int fd, unsigned long offset, unsigned long size)
-{
- Elf32_Rela *rela;
-
- if(!(rela = (Elf32_Rela *)malloc(size))) {
- seterror("Out of memory.");
- return false;
- }
-
- if(lseek(fd, offset, SEEK_SET)<0 ||
- read(fd, rela, size) != size) {
- seterror("Relocation table load failed.");
- free(rela);
- return false;
- }
-
- int cnt = size / sizeof(*rela);
- for(int i=0; i<cnt; i++) {
-
- Elf32_Sym *sym = (Elf32_Sym *)(((char *)symtab)+(rela[i].r_info>>4));
-
- void *target = ((char *)segment)+rela[i].r_offset;
-
- switch(rela[i].r_info & 0xf) {
- case 1: /* DIR32 */
- if(sym->st_shndx < 0xff00)
- *(unsigned long *)target += (unsigned long)segment;
- break;
- default:
- seterror("Unknown relocation type %d.", rela[i].r_info & 0xf);
- free(rela);
- return false;
- }
-
- }
-
- free(rela);
- return true;
-}
-
-
-bool DLObject::load(int fd)
-{
- Elf32_Ehdr ehdr;
- Elf32_Phdr phdr;
- Elf32_Shdr *shdr;
- int symtab_sect = -1;
-
- if(read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr) ||
- memcmp(ehdr.e_ident, ELFMAG, SELFMAG) ||
- ehdr.e_type != 2 || ehdr.e_machine != 42 ||
- ehdr.e_phentsize < sizeof(phdr) || ehdr.e_shentsize != sizeof(*shdr) ||
- ehdr.e_phnum != 1) {
- seterror("Invalid file type.");
- return false;
- }
-
- DBG("phoff = %d, phentsz = %d, phnum = %d\n",
- ehdr.e_phoff, ehdr.e_phentsize, ehdr.e_phnum);
-
- if(lseek(fd, ehdr.e_phoff, SEEK_SET)<0 ||
- read(fd, &phdr, sizeof(phdr)) != sizeof(phdr)) {
- seterror("Program header load failed.");
- return false;
- }
-
- if(phdr.p_type != 1 || phdr.p_vaddr != 0 || phdr.p_paddr != 0 ||
- phdr.p_filesz > phdr.p_memsz) {
- seterror("Invalid program header.");
- return false;
- }
-
- DBG("offs = %d, filesz = %d, memsz = %d, align = %d\n",
- phdr.p_offset, phdr.p_filesz, phdr.p_memsz, phdr.p_align);
-
- if(!(segment = memalign(phdr.p_align, phdr.p_memsz))) {
- seterror("Out of memory.");
- return false;
- }
-
- DBG("segment @ %p\n", segment);
-
- if(phdr.p_memsz > phdr.p_filesz)
- memset(((char *)segment) + phdr.p_filesz, 0, phdr.p_memsz - phdr.p_filesz);
-
- if(lseek(fd, phdr.p_offset, SEEK_SET)<0 ||
- read(fd, segment, phdr.p_filesz) != phdr.p_filesz) {
- seterror("Segment load failed.");
- return false;
- }
-
- DBG("shoff = %d, shentsz = %d, shnum = %d\n",
- ehdr.e_shoff, ehdr.e_shentsize, ehdr.e_shnum);
-
- if(!(shdr = (Elf32_Shdr *)malloc(ehdr.e_shnum * sizeof(*shdr)))) {
- seterror("Out of memory.");
- return false;
- }
-
- if(lseek(fd, ehdr.e_shoff, SEEK_SET)<0 ||
- read(fd, shdr, ehdr.e_shnum * sizeof(*shdr)) !=
- ehdr.e_shnum * sizeof(*shdr)) {
- seterror("Section headers load failed.");
- free(shdr);
- return false;
- }
-
- for(int i=0; i<ehdr.e_shnum; i++) {
- DBG("Section %d: type = %d, size = %d, entsize = %d, link = %d\n",
- i, shdr[i].sh_type, shdr[i].sh_size, shdr[i].sh_entsize, shdr[i].sh_link);
- if(shdr[i].sh_type == 2 && shdr[i].sh_entsize == sizeof(Elf32_Sym) &&
- shdr[i].sh_link < ehdr.e_shnum && shdr[shdr[i].sh_link].sh_type == 3 &&
- symtab_sect < 0)
- symtab_sect = i;
- }
-
- if(symtab_sect < 0) {
- seterror("No symbol table.");
- free(shdr);
- return false;
- }
-
- if(!(symtab = malloc(shdr[symtab_sect].sh_size))) {
- seterror("Out of memory.");
- free(shdr);
- return false;
- }
-
- if(lseek(fd, shdr[symtab_sect].sh_offset, SEEK_SET)<0 ||
- read(fd, symtab, shdr[symtab_sect].sh_size) != shdr[symtab_sect].sh_size){
- seterror("Symbol table load failed.");
- free(shdr);
- return false;
- }
-
- if(!(strtab = (char *)malloc(shdr[shdr[symtab_sect].sh_link].sh_size))) {
- seterror("Out of memory.");
- free(shdr);
- return false;
- }
-
- if(lseek(fd, shdr[shdr[symtab_sect].sh_link].sh_offset, SEEK_SET)<0 ||
- read(fd, strtab, shdr[shdr[symtab_sect].sh_link].sh_size) !=
- shdr[shdr[symtab_sect].sh_link].sh_size){
- seterror("Symbol table strings load failed.");
- free(shdr);
- return false;
- }
-
- symbol_cnt = shdr[symtab_sect].sh_size / sizeof(Elf32_Sym);
- DBG("Loaded %d symbols.\n", symbol_cnt);
-
- Elf32_Sym *s = (Elf32_Sym *)symtab;
- for(int c = symbol_cnt; c--; s++)
- if(s->st_shndx < 0xff00)
- s->st_value += (Elf32_Addr)segment;
-
- for(int i=0; i<ehdr.e_shnum; i++)
- if(shdr[i].sh_type == 4 && shdr[i].sh_entsize == sizeof(Elf32_Rela) &&
- shdr[i].sh_link == symtab_sect && shdr[i].sh_info < ehdr.e_shnum &&
- (shdr[shdr[i].sh_info].sh_flags & 2))
- if(!relocate(fd, shdr[i].sh_offset, shdr[i].sh_size)) {
- free(shdr);
- return false;
- }
-
- free(shdr);
-
- return true;
-}
-
-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;
- }
-
- if(!load(fd)) {
- ::close(fd);
- unload();
- return false;
- }
-
- ::close(fd);
-
- int oldmask = getimask();
- setimask(15);
- purge_copyback();
- flush_instruction_cache();
- setimask(oldmask);
-
- 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++)
- if((s->st_info>>4 == 1 || s->st_info>>4 == 2) &&
- strtab[s->st_name] == '_' && !strcmp(name, strtab+s->st_name+1)) {
- DBG("=> %p\n", (void*)s->st_value);
- return (void*)s->st_value;
- }
-
- 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();
-}