diff --git a/library/DataDefs.cpp b/library/DataDefs.cpp index c9586fcc0..ab50eb942 100644 --- a/library/DataDefs.cpp +++ b/library/DataDefs.cpp @@ -36,6 +36,7 @@ distribution. #include "DataDefs.h" #include "DataIdentity.h" #include "VTableInterpose.h" +#include "Error.h" #include "MiscUtils.h" @@ -310,7 +311,7 @@ void virtual_identity::adjust_vtable(virtual_ptr obj, virtual_identity *main) return; std::cerr << "Attempt to create class '" << getName() << "' without known vtable." << std::endl; - abort(); + throw DFHack::Error::VTableMissing(getName()); } virtual_ptr virtual_identity::clone(virtual_ptr obj) diff --git a/library/LuaTypes.cpp b/library/LuaTypes.cpp index 6e3c5d5cf..f30a1878e 100644 --- a/library/LuaTypes.cpp +++ b/library/LuaTypes.cpp @@ -1086,6 +1086,11 @@ int LuaWrapper::method_wrapper_core(lua_State *state, function_identity_base *id std::string tmp = stl_sprintf("Invalid argument; expected: %s", vn ? vn : "?"); field_error(state, UPVAL_METHOD_NAME, tmp.c_str(), "invoke"); } + catch (Error::VTableMissing &e) { + const char *cn = e.name(); + std::string tmp = stl_sprintf("Missing vtable address: %s", cn ? cn : "?"); + field_error(state, UPVAL_METHOD_NAME, tmp.c_str(), "invoke"); + } catch (std::exception &e) { std::string tmp = stl_sprintf("C++ exception: %s", e.what()); field_error(state, UPVAL_METHOD_NAME, tmp.c_str(), "invoke"); @@ -1110,6 +1115,10 @@ int Lua::CallWithCatch(lua_State *state, int (*fn)(lua_State*), const char *cont const char *vn = e.expr(); return luaL_error(state, "%s: Invalid argument; expected: %s", context, vn ? vn : "?"); } + catch (Error::VTableMissing &e) { + const char *cn = e.name(); + return luaL_error(state, "%s: Missing vtable address: %s", context, cn ? cn : "?"); + } catch (std::exception &e) { return luaL_error(state, "%s: C++ exception: %s", context, e.what()); } diff --git a/library/MiscUtils.cpp b/library/MiscUtils.cpp index a6bb4b412..bff7f07e1 100644 --- a/library/MiscUtils.cpp +++ b/library/MiscUtils.cpp @@ -49,6 +49,10 @@ const char *DFHack::Error::InvalidArgument::what() const throw() { return "DFHack::Error::InvalidArgument"; } +const char *DFHack::Error::VTableMissing::what() const throw() { + return "DFHack::Error::VTableMissing"; +} + std::string stl_sprintf(const char *fmt, ...) { va_list lst; va_start(lst, fmt); diff --git a/library/include/Error.h b/library/include/Error.h index 6b4781028..2d0baadfc 100644 --- a/library/include/Error.h +++ b/library/include/Error.h @@ -75,6 +75,14 @@ namespace DFHack #define CHECK_INVALID_ARGUMENT(expr) \ { if (!(expr)) throw DFHack::Error::InvalidArgument(#expr); } + class DFHACK_EXPORT VTableMissing : public All { + const char *name_; + public: + VTableMissing(const char *name_ = NULL) : name_(name_) {} + const char *name() const { return name_; } + virtual const char *what() const throw(); + }; + class DFHACK_EXPORT AllSymbols : public All{}; // Syntax errors and whatnot, the xml can't be read