summaryrefslogtreecommitdiff
path: root/lib/mipsobj.cpp
diff options
context:
space:
mode:
authorpixel <pixel>2004-01-26 15:31:54 +0000
committerpixel <pixel>2004-01-26 15:31:54 +0000
commitdd1a70b70cc5a4ab3a7dbeef2862d4a817fd91a7 (patch)
treec231980c6568c1a87412d6a7740025d7fce34742 /lib/mipsobj.cpp
parent3830a1a01fac86fea249fafc81f42b2f1e8ed1ae (diff)
Blah
Diffstat (limited to 'lib/mipsobj.cpp')
-rw-r--r--lib/mipsobj.cpp269
1 files changed, 269 insertions, 0 deletions
diff --git a/lib/mipsobj.cpp b/lib/mipsobj.cpp
new file mode 100644
index 0000000..97663e6
--- /dev/null
+++ b/lib/mipsobj.cpp
@@ -0,0 +1,269 @@
+#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<int, String> secnames;
+ std::map<int, String> 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);
+}