From: Daniel Karbach Date: Sun, 17 Mar 2013 18:48:40 +0000 (+0100) Subject: support for arrays containing (yet) undefined references X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=8ef435410d1f8aff339e4afef87a5757e77eba45;p=l2e.git support for arrays containing (yet) undefined references --- diff --git a/src/loader/Compiler.cpp b/src/loader/Compiler.cpp index 96c0cc1..b2d23be 100644 --- a/src/loader/Compiler.cpp +++ b/src/loader/Compiler.cpp @@ -194,6 +194,7 @@ void Compiler::PrepareExternal( const Interpreter::PostponedDefinition &def) { ext.nameOffset = addressMap[def.identifier.c_str()]; ext.referenceOffset = addressMap[def.object] + (def.dest - def.object); + ext.typeId = def.type; ext.inlined = 0; if (def.inlined) ext.inlined |= 1; if (def.aggregate) ext.inlined |= 2; @@ -258,6 +259,9 @@ void Compiler::RelocateArray(char *array, int size) { for (char *i = array, *end = array + size; i < end; i += sizeof(void *)) { char **dest = reinterpret_cast(i); + if (!*dest) { + continue; + } map::const_iterator entry(addressMap.find(*dest)); if (entry == addressMap.end()) { diff --git a/src/loader/Interpreter.cpp b/src/loader/Interpreter.cpp index ecbb076..3cb0d45 100644 --- a/src/loader/Interpreter.cpp +++ b/src/loader/Interpreter.cpp @@ -337,6 +337,7 @@ void Interpreter::ReadObject(int typeId, int id, char *object, const PropertyLis array.data = alloc.Alloc(array.size); array.ref = fd.IsReferenced(); arrays.push_back(array); + std::memset(array.data, 0, array.size); char *iter = reinterpret_cast(array.data); if (i->second->GetLiteral().GetType() == Literal::ARRAY_PROPS) { const vector &list(i->second->GetLiteral().GetPropertyLists()); diff --git a/src/loader/Loader.cpp b/src/loader/Loader.cpp index 961ec7c..ba5dcc0 100644 --- a/src/loader/Loader.cpp +++ b/src/loader/Loader.cpp @@ -3,12 +3,15 @@ #include #include #include +#include #include #include #include +using std::endl; using std::make_pair; using std::map; +using std::ostream; using std::string; using std::vector; @@ -73,6 +76,34 @@ void Loader::Load(const std::string &filePath) { throw; } objectFiles.insert(make_pair(filePath, block)); + + if (objectFiles.size() > 1) { + for (std::vector::iterator + i(unlinked.begin()); i != unlinked.end();) { + std::map::const_iterator + found(exports.find(i->identifier)); + if (found != exports.end()) { + LinkExternal(*i, found->second); + i = unlinked.erase(i); + } else { + ++i; + } + } + } +} + +void Loader::LinkExternal( + const MissingExternal &ext, + const LoadedExport &exp) { + if (ext.typeId != exp.typeId) { + throw std::runtime_error("casting not implemented in loader"); + } + const TypeDescription &td = TypeDescription::Get(ext.typeId); + if (ext.inlined) { + std::memcpy(ext.dest, exp.location, td.Size()); + } else { + std::memcpy(ext.dest, &exp.location, sizeof(void *)); + } } void Loader::LoadExports(char *src, Export *begin, Export *end) { @@ -88,18 +119,24 @@ void Loader::LoadExports(char *src, Export *begin, Export *end) { void Loader::LoadExternals(char *src, External *begin, External *end) { for (External *i = begin; i < end; ++i) { string identifier(src + i->nameOffset); + char *dest = src + i->referenceOffset; + map::const_iterator exp(exports.find(identifier)); if (exp == exports.end()) { - throw std::runtime_error("undefined reference to " - + identifier); - } - const TypeDescription &td(TypeDescription::Get(exp->second.typeId)); - char *dest = src + i->referenceOffset; - if (i->inlined) { - std::memcpy(dest, exp->second.location, td.Size()); + MissingExternal m; + m.identifier = identifier; + m.dest = dest; + m.typeId = i->typeId; + m.inlined = i->inlined; + unlinked.push_back(m); } else { - std::memcpy(dest, &exp->second.location, sizeof(char *)); + const TypeDescription &td(TypeDescription::Get(exp->second.typeId)); + if (i->inlined) { + std::memcpy(dest, exp->second.location, td.Size()); + } else { + std::memcpy(dest, &exp->second.location, sizeof(char *)); + } } } } @@ -204,4 +241,47 @@ void Loader::InitArrays(Array *begin, Array *end) { } } + +ostream &Loader::Dump(ostream &out) const { + out << "loaded objects" << endl; + out << "==============" << endl; + + out << objectFiles.size() << " object files" << endl; + for (std::map::const_iterator + i(objectFiles.begin()), end(objectFiles.end()); + i != end; ++i) { + out << " - " << i->first << endl; + } + + out << exports.size() << " exports" << endl; + for (std::map::const_iterator + i(exports.begin()), end(exports.end()); + i != end; ++i) { + const TypeDescription &td = TypeDescription::Get(i->second.typeId); + out << " - " << td.TypeName() << ' ' << i->first << endl; + } + + out << images.size() << " images" << endl; + for (std::map::const_iterator + i(images.begin()), end(images.end()); + i != end; ++i) { + out << " - " << i->first << endl; + } + + out << unlinked.size() << " missing objects" << endl; + for (std::vector::const_iterator + i(unlinked.begin()), end(unlinked.end()); + i != end; ++i) { + const TypeDescription &td = TypeDescription::Get( + i->typeId); + out << " - " << td.TypeName() << ' '; + if (!i->inlined) { + out << '*'; + } + out << i->identifier << endl; + } + + return out; +} + } diff --git a/src/loader/Loader.h b/src/loader/Loader.h index 5087638..c962f20 100644 --- a/src/loader/Loader.h +++ b/src/loader/Loader.h @@ -4,8 +4,10 @@ #include "ObjectFile.h" #include "TypeDescription.h" +#include #include #include +#include #include namespace loader { @@ -21,6 +23,8 @@ public: const std::map &Exports() const { return exports; } + std::ostream &Dump(std::ostream &) const; + private: void LoadExports(char *src, Export *begin, Export *end); void LoadExternals(char *src, External *begin, External *end); @@ -33,12 +37,31 @@ private: void InitObject(char *object, const TypeDescription &); void InitArrays(Array *begin, Array *end); + struct MissingExternal { + std::string identifier; + char *dest; + int typeId; + bool inlined; + }; + void LinkExternal(const MissingExternal &, const LoadedExport &); + private: std::map objectFiles; std::map exports; std::map images; + std::vector unlinked; }; } + + +namespace std { + +inline ostream &operator <<(ostream &o, const loader::Loader &l) { + return l.Dump(o); +} + +} + #endif diff --git a/src/loader/ObjectFile.cpp b/src/loader/ObjectFile.cpp index 7207eb0..b6ab2b7 100644 --- a/src/loader/ObjectFile.cpp +++ b/src/loader/ObjectFile.cpp @@ -64,7 +64,7 @@ bool ObjectFileHeader::CheckSection( unsigned int end, unsigned int fsize) const { return begin >= sizeof(ObjectFileHeader) - && begin < fsize + && (begin < fsize || begin == end) && end >= begin && end <= fsize; } diff --git a/src/loader/ObjectFile.h b/src/loader/ObjectFile.h index 98aff02..56319a4 100644 --- a/src/loader/ObjectFile.h +++ b/src/loader/ObjectFile.h @@ -11,7 +11,7 @@ struct Export { /// Offset of the identifier in the file. unsigned int nameOffset; /// Type ID of referenced object. - unsigned int typeId; + int typeId; /// File-offset of the object's actual data. unsigned int dataOffset; }; @@ -22,9 +22,11 @@ struct External { unsigned int nameOffset; /// Target position for linking/inlining. unsigned int referenceOffset; - /// Nonzero if the object should be copied rather that + /// Target type. + int typeId; + /// True if the object should be copied rather that /// just writing a reference. - unsigned int inlined; + bool inlined; }; struct Image { @@ -36,16 +38,18 @@ struct Image { }; struct Object { - unsigned int typeId; + int typeId; unsigned int size; + char *RawObject(); Object *Next(); }; struct Array { - unsigned int typeId; + int typeId; unsigned int size; bool ref; + char *Data(); Array *Next(); }; diff --git a/src/loader/ParsedSource.cpp b/src/loader/ParsedSource.cpp index 9059747..422c5a0 100644 --- a/src/loader/ParsedSource.cpp +++ b/src/loader/ParsedSource.cpp @@ -527,7 +527,8 @@ const Literal *ScriptToken::GetLiteral() const { namespace std { ostream &operator <<(ostream &out, const loader::ParsedSource &source) { - out << "parsed source file" << endl; + out << "parsed sources" << endl; + out << "==============" << endl; out << "declared objects: " << endl; for (map::const_iterator i(source.Declarations().begin()), end(source.Declarations().end()); i != end; ++i) { out << " - " << i->first << " of type " << i->second->TypeName() << endl; @@ -543,6 +544,7 @@ ostream &operator <<(ostream &out, const loader::ParsedSource &source) { for (set::const_iterator i(source.Exports().begin()), end(source.Exports().end()); i != end; ++i) { out << " - " << *i << endl; } + out << endl; return out; } diff --git a/src/main.cpp b/src/main.cpp index c01154e..672c41b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -189,7 +189,7 @@ int main(int argc, char **argv) { return 0; } case Arguments::DUMP: { - std::cout << source << std::endl; + std::cout << source << ld << std::endl; return 0; } case Arguments::SOURCE_WIKI: {