#include "mipsobj.h" section::section(const String & _name, int _type) : name(_name), type(_type), datas(0), length(0) { } section::section() : name(""), type(-1), datas(0), length(0) { } section::~section() { if (datas) free(datas); } void section::setname(const String & _name) { name = _name; } void section::settype(int _type) { type = _type; } void section::putdatas(const Uint8 * _datas, int _length) { if (type != BSS) { datas = (Uint8 *) realloc(datas, length + _length); memcpy(datas + length, _datas, _length); } length += _length; } int section::gettype() { return type; } int section::getsize() { return length; } const Uint8 * section::getdatas() { return datas; } void section::putreloc(const String & _symbol, int _type, Uint32 _offset) { struct reloc_t r; r.symbol = _symbol; r.type = _type; r.offset = _offset; putreloc(r); } void section::putreloc(const struct reloc_t & r) { relocs.push_back(r); } mipsobj::mipsobj() : loaded(false) { } mipsobj::~mipsobj() { } void loadELF(Handle * elf) throw (GeneralException) { } #define OBJSIG 0x024b4e4c #define READNAME(_str, _file) { \ char _name[256]; \ int _len; \ \ _len = _file->readU8(); \ _file->read(_name, _len); \ _name[_len] = 0; \ _str = _name; \ } void mipsobj::loadOBJ(Handle * obj) throw (GeneralException) { int cursec, len, reloctype, relocexpr, id; bool eof = false; std::map secnames; std::map symbolnames; Uint8 * datas; struct reloc_t reloc; struct symbol_t symbol; String name; while (!eof) { int entryid = obj->readU8(); switch (entryid) { case 0x00: eof = true; break; case 0x02: len = obj->readU16(); datas = (Uint8 *) malloc(len); obj->read(datas, len); sections[secnames[cursec]].putdatas(datas, len); free(datas); break; case 0x06: cursec = obj->readU16(); break; case 0x08: len = obj->readU32(); sections[secnames[cursec]].putdatas(0, len); break; case 0x0a: reloctype = obj->readU8(); reloc.offset = obj->readU16(); switch (reloctype) { case 0x10: reloc.type = R_MIPS_32; break; case 0x4a: reloc.type = R_MIPS_26; break; case 0x52: reloc.type = R_MIPS_HI16; break; case 0x54: reloc.type = R_MIPS_LO16; break; case 0x0a: case 0x26: case 0x28: case 0x64: printm(M_ERROR, "Relocation type %02x not supported.\n", reloctype); exit(-1); break; default: printm(M_ERROR, "Relocation type %02x UNKNOWN! Please send the object to the author.\n", reloctype); exit(-1); } relocexpr = obj->readU8(); switch (relocexpr) { case 0x02: reloc.symbol = symbolnames[obj->readU16()]; break; case 0x04: reloc.symbol = secnames[obj->readU16()]; break; case 0x00: case 0x0c: case 0x16: case 0x2c: case 0x2e: case 0x30: case 0x32: case 0x36: printm(M_ERROR, "Relocation expression %02x not supported.\n", relocexpr); exit(-1); break; default: printm(M_ERROR, "Relocation expression %02x UNKNOWN! Please mail the author.\n", relocexpr); exit(-1); break; } sections[secnames[cursec]].relocs.push_back(reloc); break; case 0x0c: id = obj->readU16(); symbol.section = obj->readU16(); symbol.offset = obj->readU32(); READNAME(symbol.name, obj); symbol.type = GLOBAL; symbolnames[id] = symbol.name; break; case 0x0e: id = obj->readU16(); READNAME(symbol.name, obj); symbol.type = EXTERN; symbolnames[id] = symbol.name; break; case 0x10: id = obj->readU16(); obj->readU8(); obj->readU16(); READNAME(name, obj); secnames[id] = name; break; case 0x12: printm(M_WARNING, "Local symbol not supported.\n"); obj->readU16(); obj->readU32(); READNAME(name, obj); break; case 0x1c: printm(M_WARNING, "File number and name not supported.\n"); obj->readU16(); READNAME(name, obj); break; case 0x2e: if ((id = obj->readU8()) != 7) { printm(M_ERROR, "CPU type %i not supported.\n", id); exit(-1); } break; case 0x30: printm(M_ERROR, "Constant not supported.\n"); exit(-1); break; default: printm(M_ERROR, "Object entry type %i UNKNOWN! Please send the object to the author.\n", entryid); exit(-1); break; } } } #define LIBSIG 0x0142494c void mipsobj::loadLIB(Handle * lib, const String & objname) throw (GeneralException) { char _name[9]; String name; int hsize, size, ptr; bool found = false; lib->seek(0); if (lib->readU32() != LIBSIG) { throw GeneralException("Not a Psy-Q lib file"); } while (lib->tell() != lib->GetSize()) { ptr = lib->tell(); lib->read(_name, 8); name = _name; lib->seek(4, SEEK_CUR); hsize = lib->readU32(); size = lib->readU32(); if (objname == name.trim()) { lib->seek(ptr + hsize); found = true; break; } lib->seek(ptr + size); } if (!found) { throw GeneralException("Object `" + objname + "' not found in archive " + lib->GetName()); } loadOBJ(lib); }