]> git.localhorst.tv Git - l2e.git/commitdiff
relocate scripts linker
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 19 Mar 2013 17:53:42 +0000 (18:53 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 19 Mar 2013 17:53:42 +0000 (18:53 +0100)
it totally works, yay \o/
well, except for referencing unavailable symbols in scripts

src/common/Script.cpp
src/common/Script.h
src/loader/Compiler.cpp
src/loader/Compiler.h
src/loader/Interpreter.cpp
src/loader/Loader.cpp
src/loader/Loader.h
src/loader/ObjectFile.cpp
src/loader/ObjectFile.h

index 05dd8194d8a6a78249c66add98618f72e9d8edd7..c5caf579a3d817b70a59b0198d3eaa57d1987443 100644 (file)
@@ -1,5 +1,7 @@
 #include "Script.h"
 
+#include "../math/Vector.h"
+
 namespace common {
 
 Script::Script()
@@ -12,4 +14,41 @@ Script::~Script() {
 
 }
 
+
+unsigned int Script::Code::Size() const {
+       unsigned int size = sizeof(Code);
+       if (numParams == 0) {
+               return size;
+       }
+       unsigned int argSize = 0;
+       switch (type) {
+               default:
+                       argSize = 0;
+                       break;
+               case TYPE_ADDRESS:
+                       argSize = sizeof(void *);
+                       break;
+               case TYPE_INTEGER:
+                       argSize = sizeof(int);
+                       break;
+               case TYPE_VECTOR:
+                       argSize = sizeof(math::Vector<int>);
+                       break;
+       }
+       switch (numParams) {
+               case 3:
+               case 2:
+                       if (reg2 == 7) {
+                               size += argSize;
+                       }
+               case 1:
+                       if (reg1 == 7) {
+                               size += argSize;
+                       }
+               default:
+                       break;
+       }
+       return size;
+}
+
 }
index c3f483826c5618b6d238aea0b08d172ad51b7bf4..be15a5e9777bc7e408d74570aeb73d2d8a3aa6a0 100644 (file)
@@ -41,6 +41,8 @@ public:
                Type type : 2;
                unsigned int reg1 : 3;
                unsigned int reg2 : 3;
+
+               unsigned int Size() const;
        };
 
 public:
index b2d23be9c5cb984ee969ae3402706fbe02cf6289..13f3dfc24ba0b1416ef87bfdd2976b9f9c8003dd 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "Interpreter.h"
 #include "TypeDescription.h"
+#include "../common/Script.h"
 
 #include <climits>
 #include <cstring>
@@ -18,6 +19,7 @@ using std::iostream;
 using std::make_pair;
 using std::map;
 using std::ostream;
+using std::pair;
 using std::runtime_error;
 using std::set;
 using std::string;
@@ -51,6 +53,9 @@ void Compiler::Write(iostream &out) {
        fileHeader.arraysBegin = out.tellp();
        WriteArrays(out);
        fileHeader.arraysEnd = out.tellp();
+       fileHeader.scriptsBegin = out.tellp();
+       WriteScripts(out);
+       fileHeader.scriptsEnd = out.tellp();
        out.seekp(0);
        WriteHeader(out);
        WriteExports(out);
@@ -148,6 +153,11 @@ void Compiler::WriteObjects(ostream &out) {
                        Write(out, &object, sizeof(Object));
                        addressMap.insert(make_pair(*j, out.tellp()));
                        Write(out, *j, object.size);
+
+                       if (td.TypeId() == Interpreter::SCRIPT_ID) {
+                               common::Script *script = reinterpret_cast<common::Script *>(*j);
+                               scripts.push_back(make_pair(const_cast<char *>(script->text), script->textlen));
+                       }
                }
        }
 }
@@ -180,6 +190,18 @@ void Compiler::WriteImages(ostream &out) {
        }
 }
 
+void Compiler::WriteScripts(ostream &out) {
+       for (vector<pair<const char *, unsigned int> >::const_iterator
+                       i(scripts.begin()), end(scripts.end());
+                       i != end; ++i) {
+               Script s;
+               s.size = i->second;
+               Write(out, &s, sizeof(Script));
+               addressMap.insert(make_pair(i->first, out.tellp()));
+               Write(out, i->first, s.size);
+       }
+}
+
 
 void Compiler::PrepareExport(Export &exp, const string &str) {
        const Interpreter::ParsedDefinition &dfn
@@ -253,6 +275,18 @@ void Compiler::Relocate(iostream &out) {
                out.seekg(out.tellp());
                delete[] buffer;
        }
+       Script script;
+       for (; out && out.tellg() < fileHeader.scriptsEnd;) {
+               out.read(reinterpret_cast<char *>(&script), sizeof(Script));
+               buffer = new char[script.size];
+               unsigned int pos = out.tellg();
+               out.read(buffer, script.size);
+               RelocateScript(buffer, script.size);
+               out.seekp(pos);
+               out.write(buffer, script.size);
+               out.seekg(out.tellp());
+               delete[] buffer;
+       }
 }
 
 void Compiler::RelocateArray(char *array, int size) {
@@ -306,6 +340,38 @@ void Compiler::Relocate(
        }
 }
 
+void Compiler::RelocateScript(char *text, unsigned int textlen) {
+       for (char *i = text, *end = text + textlen; i < end;) {
+               common::Script::Code *code =
+                               reinterpret_cast<common::Script::Code *>(i);
+               if (code->type == common::Script::TYPE_ADDRESS && code->numParams > 0) {
+                       if (code->reg1 == 7) {
+                               char *addr = i + sizeof(common::Script::Code);
+                               std::map<const void *, unsigned int>::const_iterator
+                                               found(addressMap.find(*reinterpret_cast<void **>(addr)));
+                               if (found == addressMap.end()) {
+                                       throw std::runtime_error("unable to relocate script code");
+                               }
+                               *reinterpret_cast<unsigned int *>(addr) = found->second;
+                       }
+
+                       if (code->numParams > 1 && code->reg2 == 7) {
+                               char *addr = i + sizeof(common::Script::Code);
+                               if (code->reg1 == 7) {
+                                       addr += sizeof(void *);
+                               }
+                               std::map<const void *, unsigned int>::const_iterator
+                                               found(addressMap.find(*reinterpret_cast<void **>(addr)));
+                               if (found == addressMap.end()) {
+                                       throw std::runtime_error("unable to relocate script code");
+                               }
+                               *reinterpret_cast<unsigned int *>(addr) = found->second;
+                       }
+               }
+               i += code->Size();
+       }
+}
+
 
 void Compiler::Write(ostream &out, const void *data, int amount) {
        out.write(reinterpret_cast<const char *>(data), amount);
index 2f89752690664d3a33426621cc33a3a4f8c92a30..d406bbf2c8cbf016873472941c333e961ac65812 100644 (file)
@@ -8,6 +8,8 @@
 #include <iosfwd>
 #include <map>
 #include <memory>
+#include <utility>
+#include <vector>
 #include <SDL.h>
 
 namespace loader {
@@ -33,10 +35,12 @@ private:
        void WriteExports(std::ostream &);
        void WriteExternals(std::ostream &);
        void WriteImages(std::ostream &);
+       void WriteScripts(std::ostream &);
 
        void Relocate(std::iostream &);
        void RelocateArray(char *, int size);
        void Relocate(unsigned int pos, char *dest, const TypeDescription &);
+       void RelocateScript(char *, unsigned int);
 
        void PrepareExport(Export &, const std::string &);
        void PrepareExternal(External &, const Interpreter::PostponedDefinition &);
@@ -54,6 +58,7 @@ private:
 
        std::map<const void *, unsigned int> addressMap;
        std::map<unsigned int, void *> images;
+       std::vector<std::pair<const char *, unsigned int> > scripts;
 
 };
 
index 3cb0d452a755b4f36b0345912026564e310b395c..d13c3c6424bfbdd60ccc5cefd19d96f85a56440a 100644 (file)
@@ -959,16 +959,18 @@ void Interpreter::CreateTypeDescriptions() {
                td.SetDescription("A signed integer.");
                td.SetSize(sizeof(int));
        }
-       {;
+       {
                TypeDescription &td(TypeDescription::Create(PATH_ID, "Path"));
                td.SetDescription("A path in the filesystem which is interpreted relative to the source file's location.");
                td.SetSize(1);
                td.AddSupertype(STRING_ID, 0);
        }
        {
+               Script s;
                TypeDescription &td(TypeDescription::Create(SCRIPT_ID, "Script"));
                td.SetDescription("Collection of commands that define a behaviour.");
                td.SetSize(sizeof(Script));
+               td.AddField("text", FieldDescription(((char *)&s.text) - ((char *)&s), STRING_ID).SetAggregate());
        }
        {
                TypeDescription &td(TypeDescription::Create(STRING_ID, "String"));
index ba5dcc066d2b6c941534eb1160f57ded7106b74a..3c7f2bd5b3005611e6c41d93f0fc5f7b2895b96b 100644 (file)
@@ -1,5 +1,7 @@
 #include "Loader.h"
 
+#include "../common/Script.h"
+
 #include <climits>
 #include <cstring>
 #include <fstream>
@@ -64,6 +66,9 @@ void Loader::Load(const std::string &filePath) {
                LoadImages(header->ident,
                                header->ImagesBegin(),
                                header->ImagesEnd());
+               LoadScripts(header->ident,
+                               header->ScriptsBegin(),
+                               header->ScriptsEnd());
 
                InitObjects(
                                header->ObjectsBegin(),
@@ -203,6 +208,36 @@ void Loader::LoadArrays(char *src, Array *begin, Array *end) {
        }
 }
 
+void Loader::LoadScripts(char *src, Script *begin, Script *end) {
+       for (Script *s = begin; s < end; s = s->Next()) {
+               for (char *i = s->Text(), *end = s->Text() + s->size; i < end;) {
+                       common::Script::Code *code =
+                                       reinterpret_cast<common::Script::Code *>(i);
+                       if (code->type == common::Script::TYPE_ADDRESS && code->numParams > 0) {
+                               if (code->reg1 == 7) {
+                                       char *addr = i + sizeof(common::Script::Code);
+                                       unsigned int offset = *reinterpret_cast<unsigned int *>(addr);
+                                       if (offset) {
+                                               *reinterpret_cast<const char **>(addr) = src + offset;
+                                       }
+                               }
+       
+                               if (code->numParams > 1 && code->reg2 == 7) {
+                                       char *addr = i + sizeof(common::Script::Code);
+                                       if (code->reg1 == 7) {
+                                               addr += sizeof(void *);
+                                       }
+                                       unsigned int offset = *reinterpret_cast<unsigned int *>(addr);
+                                       if (offset) {
+                                               *reinterpret_cast<const char **>(addr) = src + offset;
+                                       }
+                               }
+                       }
+                       i += code->Size();
+               }
+       }
+}
+
 
 void Loader::InitObjects(Object *begin, Object *end) {
        for (Object *i = begin; i < end; i = i->Next()) {
index c962f206119a9b67f22d11d52b9b58b806004b2e..17f637ad22ef07bda40cab79a6f59b3e810c73c2 100644 (file)
@@ -32,6 +32,7 @@ private:
        void LoadObjects(char *src, Object *begin, Object *end);
        void LoadObject(char *src, char *dest, const TypeDescription &);
        void LoadArrays(char *src, Array *begin, Array *end);
+       void LoadScripts(char *src, Script *begin, Script *end);
 
        void InitObjects(Object *begin, Object *end);
        void InitObject(char *object, const TypeDescription &);
index b6ab2b71c57e3724a93b0a5d987ad6ccf9fc1f32..76cc98266c1214b31395a419db68700cea97285a 100644 (file)
@@ -13,10 +13,14 @@ ObjectFileHeader::ObjectFileHeader()
 , exportsEnd(0)
 , externalsBegin(0)
 , externalsEnd(0)
+, imagesBegin(0)
+, imagesEnd(0)
 , objectsBegin(0)
 , objectsEnd(0)
 , arraysBegin(0)
-, arraysEnd(0) {
+, arraysEnd(0)
+, scriptsBegin(0)
+, scriptsEnd(0) {
        ident[0] = 'L';
        ident[1] = '2';
        ident[2] = 'E';
@@ -119,6 +123,16 @@ Array *ObjectFileHeader::ArraysEnd() {
        return reinterpret_cast<Array *>(data + arraysEnd);
 }
 
+Script *ObjectFileHeader::ScriptsBegin() {
+       char *data = reinterpret_cast<char *>(this);
+       return reinterpret_cast<Script *>(data + scriptsBegin);
+}
+
+Script *ObjectFileHeader::ScriptsEnd() {
+       char *data = reinterpret_cast<char *>(this);
+       return reinterpret_cast<Script *>(data + scriptsEnd);
+}
+
 
 char *Object::RawObject() {
        return reinterpret_cast<char *>(this) + sizeof(Object);
@@ -137,4 +151,12 @@ Array *Array::Next() {
        return reinterpret_cast<Array *>(Data() + size);
 }
 
+char *Script::Text() {
+       return reinterpret_cast<char *>(this) + sizeof(Script);
+}
+
+Script *Script::Next() {
+       return reinterpret_cast<Script *>(Text() + size);
+}
+
 }
index 56319a4dd444050681fb0aef7a8886893e91c3d6..2bdcb125c63aa5ec2c3a57b5c79fc8126776e669 100644 (file)
@@ -54,6 +54,13 @@ struct Array {
        Array *Next();
 };
 
+struct Script {
+       unsigned int size;
+
+       char *Text();
+       Script *Next();
+};
+
 struct ObjectFileHeader {
        /// Has to be "L2E\n"
        char ident[4];
@@ -109,6 +116,13 @@ struct ObjectFileHeader {
        unsigned int arraysBegin;
        unsigned int arraysEnd;
 
+       /// File-relative offsets of the script section's begin
+       /// and end respectively.
+       /// Each script is an unsigned int with the length in
+       /// bytes followed by the script text.
+       unsigned int scriptsBegin;
+       unsigned int scriptsEnd;
+
        ObjectFileHeader();
 
        /// Check if there are any problems with the file header.
@@ -124,6 +138,8 @@ struct ObjectFileHeader {
        Object *ObjectsEnd();
        Array *ArraysBegin();
        Array *ArraysEnd();
+       Script *ScriptsBegin();
+       Script *ScriptsEnd();
 
 private:
        bool CheckSection(