diff options
Diffstat (limited to 'backends/platform')
-rw-r--r-- | backends/platform/psp/psploader.cpp | 141 |
1 files changed, 76 insertions, 65 deletions
diff --git a/backends/platform/psp/psploader.cpp b/backends/platform/psp/psploader.cpp index 68e51c1a50..464e20770c 100644 --- a/backends/platform/psp/psploader.cpp +++ b/backends/platform/psp/psploader.cpp @@ -37,24 +37,20 @@ #include "backends/platform/psp/psploader.h" #include "backends/platform/psp/powerman.h" -//#define __PSP_DEBUG_PLUGINS__ +//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ +//#define __PSP_DEBUG_PRINT__ -#ifdef __PSP_DEBUG_PLUGINS__ -#define DBG(x,...) fprintf(stderr,x, ## __VA_ARGS__) -#else -#define DBG(x,...) -#endif - -#define seterror(x,...) fprintf(stderr,x, ## __VA_ARGS__) +#include "backends/platform/psp/trace.h" extern char __plugin_hole_start; // Indicates start of hole in program file for shorts extern char __plugin_hole_end; // Indicates end of hole in program file -extern char _gp[]; // Value of gp register +extern char _gp[]; // Value of gp register DECLARE_SINGLETON(ShortSegmentManager) // For singleton // Get rid of symbol table in memory void DLObject::discard_symtab() { + DEBUG_ENTER_FUNC(); free(_symtab); free(_strtab); _symtab = NULL; @@ -64,6 +60,7 @@ void DLObject::discard_symtab() { // Unload all objects from memory void DLObject::unload() { + DEBUG_ENTER_FUNC(); discard_symtab(); free(_segment); _segment = NULL; @@ -84,18 +81,19 @@ void DLObject::unload() { * */ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void *relSegment) { + DEBUG_ENTER_FUNC(); Elf32_Rel *rel = NULL; // relocation entry // Allocate memory for relocation table if (!(rel = (Elf32_Rel *)malloc(size))) { - seterror("Out of memory."); + PSP_ERROR("Out of memory."); return false; } // Read in our relocation table if (lseek(fd, offset, SEEK_SET) < 0 || read(fd, rel, size) != (ssize_t)size) { - seterror("Relocation table load failed."); + PSP_ERROR("Relocation table load failed."); free(rel); return false; } @@ -103,7 +101,7 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void * // Treat each relocation entry. Loop over all of them int cnt = size / sizeof(*rel); - DBG("Loaded relocation table. %d entries. base address=%p\n", cnt, relSegment); + PSP_DEBUG_PRINT("Loaded relocation table. %d entries. base address=%p\n", cnt, relSegment); bool seenHi16 = false; // For treating HI/LO16 commands int firstHi16 = -1; // Mark the point of the first hi16 seen @@ -127,7 +125,7 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void * // Get the target instruction in the code unsigned int *target = (unsigned int *)((char *)relSegment + rel[i].r_offset); - unsigned int origTarget = *target; // Save for debugging + PSP_DEBUG_DO(unsigned int origTarget = *target); // Save for debugging // Act differently based on the type of relocation switch (REL_TYPE(rel[i].r_info)) { @@ -142,7 +140,7 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void * lastHiSymVal = sym->st_value; hi16InShorts = (ShortsMan.inGeneralSegment((char *)sym->st_value)); // Fix for problem with switching btw segments if (debugRelocs[0]++ < DEBUG_NUM) // Print only a set number - DBG("R_MIPS_HI16: i=%d, offset=%x, ahl = %x, target = %x\n", + PSP_DEBUG_PRINT("R_MIPS_HI16: i=%d, offset=%x, ahl = %x, target = %x\n", i, rel[i].r_offset, ahl, *target); } break; @@ -150,7 +148,7 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void * case R_MIPS_LO16: // Absolute addressing. Needs a HI16 to come before it if (sym->st_shndx < SHN_LOPROC) { // Only shift for plugin section. (ie. has a real section index) if (!seenHi16) { // We MUST have seen HI16 first - seterror("R_MIPS_LO16 w/o preceding R_MIPS_HI16 at relocation %d!\n", i); + PSP_ERROR("R_MIPS_LO16 w/o preceding R_MIPS_HI16 at relocation %d!\n", i); free(rel); return false; } @@ -195,10 +193,10 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void * *target |= relocation & 0xffff; // Take the lower 16 bits of the relocation if (debugRelocs[1]++ < DEBUG_NUM) - DBG("R_MIPS_LO16: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n", + PSP_DEBUG_PRINT("R_MIPS_LO16: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n", i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target); if (lo16InShorts && debugRelocs[2]++ < DEBUG_NUM) - DBG("R_MIPS_LO16s: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n", + PSP_DEBUG_PRINT("R_MIPS_LO16s: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n", i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target); } break; @@ -212,11 +210,11 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void * *target |= (relocation & 0x03ffffff); if (debugRelocs[3]++ < DEBUG_NUM) - DBG("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n", + PSP_DEBUG_PRINT("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n", i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target); } else { if (debugRelocs[4]++ < DEBUG_NUM) - DBG("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n", + PSP_DEBUG_PRINT("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n", i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target); } break; @@ -233,7 +231,7 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void * *target |= relocation & 0xffff; if (debugRelocs[5]++ < DEBUG_NUM) - DBG("R_MIPS_GPREL16: i=%d, a=%x, gpVal=%x, origTarget=%x, target=%x, offset=%x\n", + PSP_DEBUG_PRINT("R_MIPS_GPREL16: i=%d, a=%x, gpVal=%x, origTarget=%x, target=%x, offset=%x\n", i, a, _gpVal, origTarget, *target, _shortsSegment->getOffset()); } @@ -250,24 +248,25 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void * *target = relocation; if (debugRelocs[6]++ < DEBUG_NUM) - DBG("R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x\n", i, a, origTarget, *target); + PSP_DEBUG_PRINT("R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x\n", i, a, origTarget, *target); } break; default: - seterror("Unknown relocation type %x at relocation %d.\n", REL_TYPE(rel[i].r_info), i); + PSP_ERROR("Unknown relocation type %x at relocation %d.\n", REL_TYPE(rel[i].r_info), i); free(rel); return false; } } - DBG("Done with relocation. extendedHi16=%d\n\n", extendedHi16); + PSP_DEBUG_PRINT("Done with relocation. extendedHi16=%d\n\n", extendedHi16); free(rel); return true; } bool DLObject::readElfHeader(int fd, Elf32_Ehdr *ehdr) { + DEBUG_ENTER_FUNC(); // Start reading the elf header. Check for errors if (read(fd, ehdr, sizeof(*ehdr)) != sizeof(*ehdr) || memcmp(ehdr->e_ident, ELFMAG, SELFMAG) || // Check MAGIC @@ -275,31 +274,32 @@ bool DLObject::readElfHeader(int fd, Elf32_Ehdr *ehdr) { ehdr->e_machine != EM_MIPS || // Check for MIPS 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."); + PSP_ERROR("Invalid file type."); return false; } - DBG("phoff = %d, phentsz = %d, phnum = %d\n", + PSP_DEBUG_PRINT("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) { + DEBUG_ENTER_FUNC(); // 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."); + PSP_ERROR("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."); + PSP_ERROR("Invalid program header."); return false; } - DBG("offs = %x, filesz = %x, memsz = %x, align = %x\n", + PSP_DEBUG_PRINT("offs = %x, filesz = %x, memsz = %x, align = %x\n", phdr->p_offset, phdr->p_filesz, phdr->p_memsz, phdr->p_align); return true; @@ -307,6 +307,7 @@ bool DLObject::readProgramHeaders(int fd, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, in } bool DLObject::loadSegment(int fd, Elf32_Phdr *phdr) { + DEBUG_ENTER_FUNC(); char *baseAddress = 0; @@ -315,15 +316,15 @@ bool DLObject::loadSegment(int fd, Elf32_Phdr *phdr) { // 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); + PSP_DEBUG_PRINT("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"); + PSP_ERROR("Out of memory.\n"); return false; } - DBG("allocated segment @ %p\n", _segment); + PSP_DEBUG_PRINT("allocated segment @ %p\n", _segment); // Get offset to load segment into baseAddress = (char *)_segment + phdr->p_vaddr; @@ -332,20 +333,20 @@ bool DLObject::loadSegment(int fd, Elf32_Phdr *phdr) { _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", + PSP_DEBUG_PRINT("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); + PSP_DEBUG_PRINT("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."); + PSP_ERROR("Segment load failed."); return false; } @@ -354,12 +355,13 @@ bool DLObject::loadSegment(int fd, Elf32_Phdr *phdr) { Elf32_Shdr * DLObject::loadSectionHeaders(int fd, Elf32_Ehdr *ehdr) { + DEBUG_ENTER_FUNC(); Elf32_Shdr *shdr = NULL; // Allocate memory for section headers if (!(shdr = (Elf32_Shdr *)malloc(ehdr->e_shnum * sizeof(*shdr)))) { - seterror("Out of memory."); + PSP_ERROR("Out of memory."); return NULL; } @@ -367,7 +369,7 @@ Elf32_Shdr * DLObject::loadSectionHeaders(int fd, Elf32_Ehdr *ehdr) { 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."); + PSP_ERROR("Section headers load failed."); return NULL; } @@ -375,11 +377,12 @@ Elf32_Shdr * DLObject::loadSectionHeaders(int fd, Elf32_Ehdr *ehdr) { } int DLObject::loadSymbolTable(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { + DEBUG_ENTER_FUNC(); // Loop over sections, looking for symbol table linked to a string table for (int i = 0; i < ehdr->e_shnum; i++) { - //DBG("Section %d: type = %x, size = %x, entsize = %x, link = %x\n", - // i, shdr[i].sh_type, shdr[i].sh_size, shdr[i].sh_entsize, shdr[i].sh_link); + PSP_DEBUG_PRINT("Section %d: type = %x, size = %x, entsize = %x, link = %x\n", + i, shdr[i].sh_type, shdr[i].sh_size, shdr[i].sh_entsize, shdr[i].sh_link); if (shdr[i].sh_type == SHT_SYMTAB && shdr[i].sh_entsize == sizeof(Elf32_Sym) && @@ -392,15 +395,15 @@ int DLObject::loadSymbolTable(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { // Check for no symbol table if (_symtab_sect < 0) { - seterror("No symbol table."); + PSP_ERROR("No symbol table."); return -1; } - DBG("Symbol section at section %d, size %x\n", _symtab_sect, shdr[_symtab_sect].sh_size); + PSP_DEBUG_PRINT("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."); + PSP_ERROR("Out of memory."); return -1; } @@ -408,25 +411,26 @@ int DLObject::loadSymbolTable(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { 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."); + PSP_ERROR("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); + PSP_DEBUG_PRINT("Loaded %d symbols.\n", _symbol_cnt); return _symtab_sect; } bool DLObject::loadStringTable(int fd, Elf32_Shdr *shdr) { + DEBUG_ENTER_FUNC(); 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."); + PSP_ERROR("Out of memory."); return false; } @@ -434,16 +438,17 @@ bool DLObject::loadStringTable(int fd, Elf32_Shdr *shdr) { 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."); + PSP_ERROR("Symbol table strings load failed."); return false; } return true; } void DLObject::relocateSymbols(Elf32_Addr offset, Elf32_Addr shortsOffset) { + DEBUG_ENTER_FUNC(); int shortsCount = 0, othersCount = 0; - DBG("Relocating symbols by %x. Shorts offset=%x\n", offset, shortsOffset); + PSP_DEBUG_PRINT("Relocating symbols by %x. Shorts offset=%x\n", offset, shortsOffset); // Loop over symbols, add relocation offset Elf32_Sym *s = (Elf32_Sym *)_symtab; @@ -454,22 +459,23 @@ void DLObject::relocateSymbols(Elf32_Addr offset, Elf32_Addr shortsOffset) { othersCount++; 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); + PSP_ERROR("Symbol out of bounds! st_value = %x\n", s->st_value); } else { // shorts section shortsCount++; s->st_value += shortsOffset; if (!_shortsSegment->inSegment((char *)s->st_value)) - seterror("Symbol out of bounds! st_value = %x\n", s->st_value); + PSP_ERROR("Symbol out of bounds! st_value = %x\n", s->st_value); } } } - DBG("Relocated %d short symbols, %d others.\n", shortsCount, othersCount); + PSP_DEBUG_PRINT("Relocated %d short symbols, %d others.\n", shortsCount, othersCount); } bool DLObject::relocateRels(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { + DEBUG_ENTER_FUNC(); // Loop over sections, finding relocation sections for (int i = 0; i < ehdr->e_shnum; i++) { @@ -500,7 +506,7 @@ bool DLObject::relocateRels(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { bool DLObject::load(int fd) { - fprintf(stderr, "In DLObject::load\n"); + DEBUG_ENTER_FUNC(); Elf32_Ehdr ehdr; // ELF header Elf32_Phdr phdr; // Program header @@ -512,8 +518,7 @@ bool DLObject::load(int fd) { } for (int i = 0; i < ehdr.e_phnum; i++) { // Load our 2 segments - - fprintf(stderr, "Loading segment %d\n", i); + PSP_DEBUG_PRINT("Loading segment %d\n", i); if (readProgramHeaders(fd, &ehdr, &phdr, i) == false) return false; @@ -543,19 +548,20 @@ bool DLObject::load(int fd) { } bool DLObject::open(const char *path) { + DEBUG_ENTER_FUNC(); int fd; void *ctors_start, *ctors_end; - DBG("open(\"%s\")\n", path); + PSP_DEBUG_PRINT("open(\"%s\")\n", path); // Get the address of the global pointer _gpVal = (unsigned int) & _gp; - DBG("_gpVal is %x\n", _gpVal); + PSP_DEBUG_PRINT("_gpVal is %x\n", _gpVal); PowerMan.beginCriticalSection(); if ((fd = ::open(path, O_RDONLY)) < 0) { - seterror("%s not found.", path); + PSP_ERROR("%s not found.", path); return false; } @@ -581,21 +587,22 @@ bool DLObject::open(const char *path) { if (ctors_start == NULL || ctors_end == NULL || _dtors_start == NULL || _dtors_end == NULL) { - seterror("Missing ctors/dtors."); + PSP_ERROR("Missing ctors/dtors."); _dtors_start = _dtors_end = NULL; unload(); return false; } - DBG("Calling constructors.\n"); + PSP_DEBUG_PRINT("Calling constructors.\n"); for (void (**f)(void) = (void (**)(void))ctors_start; f != ctors_end; f++) (**f)(); - DBG("%s opened ok.\n", path); + PSP_DEBUG_PRINT("%s opened ok.\n", path); return true; } bool DLObject::close() { + DEBUG_ENTER_FUNC(); if (_dtors_start != NULL && _dtors_end != NULL) for (void (**f)(void) = (void (**)(void))_dtors_start; f != _dtors_end; f++) (**f)(); @@ -605,10 +612,11 @@ bool DLObject::close() { } void *DLObject::symbol(const char *name) { - DBG("symbol(\"%s\")\n", name); + DEBUG_ENTER_FUNC(); + PSP_DEBUG_PRINT("symbol(\"%s\")\n", name); if (_symtab == NULL || _strtab == NULL || _symbol_cnt < 1) { - seterror("No symbol table loaded."); + PSP_ERROR("No symbol table loaded."); return NULL; } @@ -621,23 +629,25 @@ void *DLObject::symbol(const char *name) { !strcmp(name, _strtab + s->st_name)) { // We found the symbol - DBG("=> %p\n", (void*)s->st_value); + PSP_DEBUG_PRINT("=> %p\n", (void*)s->st_value); return (void*)s->st_value; } } - seterror("Symbol \"%s\" not found.", name); + PSP_ERROR("Symbol \"%s\" not found.", name); return NULL; } ShortSegmentManager::ShortSegmentManager() { + DEBUG_ENTER_FUNC(); _shortsStart = &__plugin_hole_start ; _shortsEnd = &__plugin_hole_end; } ShortSegmentManager::Segment *ShortSegmentManager::newSegment(int size, char *origAddr) { + DEBUG_ENTER_FUNC(); char *lastAddress = origAddr; Common::List<Segment *>::iterator i; @@ -654,7 +664,7 @@ ShortSegmentManager::Segment *ShortSegmentManager::newSegment(int size, char *or lastAddress += 4 - ((Elf32_Addr)lastAddress & 3); // Round up to multiple of 4 if (lastAddress + size > _shortsEnd) { - seterror("Error. No space in shorts segment for %x bytes. Last address is %p, max address is %p.\n", + PSP_ERROR("No space in shorts segment for %x bytes. Last address is %p, max address is %p.\n", size, lastAddress, _shortsEnd); return NULL; } @@ -665,14 +675,15 @@ ShortSegmentManager::Segment *ShortSegmentManager::newSegment(int size, char *or _list.insert(i, seg); - DBG("Shorts segment size %x allocated. End = %p. Remaining space = %x. Highest so far is %p.\n", + PSP_DEBUG_PRINT("Shorts segment size %x allocated. End = %p. Remaining space = %x. Highest so far is %p.\n", size, lastAddress + size, _shortsEnd - _list.back()->getEnd(), _highestAddress); return seg; } void ShortSegmentManager::deleteSegment(ShortSegmentManager::Segment *seg) { - DBG("Deleting shorts segment from %p to %p.\n\n", seg->getStart(), seg->getEnd()); + DEBUG_ENTER_FUNC(); + PSP_DEBUG_PRINT("Deleting shorts segment from %p to %p.\n\n", seg->getStart(), seg->getEnd()); _list.remove(seg); delete seg; } |