Remove fat from memory.xml, simplify memory.xml loading, break

everything.
develop
Petr Mrázek 2012-02-08 13:17:47 +01:00 committed by Mrazek Petr
parent 1ae1549513
commit f7d8635be1
5 changed files with 163 additions and 5297 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -38,65 +38,6 @@ using namespace DFHack;
#include <tinyxml.h>
template<class _T1, class _T2, class _T3>
struct triple
{
typedef _T1 first_type;
typedef _T2 second_type;
typedef _T3 third_type;
_T1 first;
_T2 second;
_T3 third;
triple() : first(), second(), third() { }
triple(const _T1& __a, const _T2& __b, const _T3& __c) : first(__a), second(__b), third(__c) { }
template<class _U1, class _U2, class _U3>
triple(const triple<_U1, _U2, _U3>& __p) : first(__p.first), second(__p.second), third(__p.third) { }
};
template<class _T1, class _T2, class _T3>
inline bool operator==(const triple<_T1, _T2, _T3>& __x, const triple<_T1, _T2, _T3>& __y)
{
return __x.first == __y.first && __x.second == __y.second && __x.third == __y.third;
}
template<class _T1, class _T2, class _T3>
inline bool operator<(const triple<_T1, _T2, _T3>& __x, const triple<_T1, _T2, _T3>& __y)
{
return
__x.first < __y.first ||
(!(__y.first < __x.first) && __x.second < __y.second) ||
(!(__y.first < __x.first) && !(__x.second < __y.second) && (__x.third < __y.third));
}
template<class _T1, class _T2, class _T3>
inline bool operator!=(const triple<_T1, _T2, _T3>& __x, const triple<_T1, _T2, _T3>& __y)
{
return !(__x == __y);
}
template<class _T1, class _T2, class _T3>
inline bool operator>(const triple<_T1, _T2, _T3>& __x, const triple<_T1, _T2, _T3>& __y)
{
return __y < __x;
}
template<class _T1, class _T2, class _T3>
inline bool operator<=(const triple<_T1, _T2, _T3>& __x, const triple<_T1, _T2, _T3>& __y)
{
return !(__y < __x);
}
template<class _T1, class _T2, class _T3>
inline bool operator>=(const triple<_T1, _T2, _T3>& __x, const triple<_T1, _T2, _T3>& __y)
{
return !(__x < __y);
}
VersionInfoFactory::VersionInfoFactory()
{
error = false;
@ -106,7 +47,7 @@ VersionInfoFactory::~VersionInfoFactory()
{
clear();
}
void VersionInfoFactory::clear(void)
void VersionInfoFactory::clear()
{
// for each stored version, delete
for(size_t i = 0; i < versions.size();i++)
@ -114,7 +55,6 @@ void VersionInfoFactory::clear(void)
delete versions[i];
}
versions.clear();
knownVersions.clear();
error = false;
}
@ -123,522 +63,46 @@ VersionInfo * VersionInfoFactory::getVersionInfoByMD5(string hash)
VersionInfo * vinfo;
for(size_t i = 0; i < versions.size();i++)
{
vinfo = versions[i];
string test_hash;
if(vinfo->getMD5(test_hash) && hash == test_hash)
{
return vinfo;
}
if(versions[i]->hasMD5(hash))
return versions[i];
}
return 0;
}
VersionInfo * VersionInfoFactory::getVersionInfoByPETimestamp(uint32_t timestamp)
{
VersionInfo * vinfo;
//cout << "lookup size:" << versions.size() << endl;
for(size_t i = 0; i < versions.size();i++)
{
vinfo = versions[i];
uint32_t test_PE;
//cout << "Testing version: " << hex << vinfo <<" No:" << dec << i << endl;
//cout << vinfo->getName() << endl;
if(vinfo->getPE(test_PE) && test_PE == timestamp)
{
return vinfo;
}
//cout << "LOOP ENDS" << endl;
if(versions[i]->hasPE(timestamp))
return versions[i];
}
//cout << "NOTHING!" << endl;
return 0;
}
void VersionInfoFactory::ParseVTable(TiXmlElement* vtable, VersionInfo* mem)
{
TiXmlElement* pClassEntry;
TiXmlElement* pClassSubEntry;
/*
// check for rebase, do rebase if check positive
const char * rebase = vtable->Attribute("rebase");
if(rebase)
{
int32_t rebase_offset = strtol(rebase, NULL, 16);
mem->RebaseVTable(rebase_offset);
}
*/
// parse vtable entries
pClassEntry = vtable->FirstChildElement();
for(;pClassEntry;pClassEntry=pClassEntry->NextSiblingElement())
{
string type = pClassEntry->Value();
const char *cstr_name = pClassEntry->Attribute("name");
const char *cstr_vtable = pClassEntry->Attribute("vtable");
uint32_t vtable_num = 0;
if(cstr_vtable)
vtable_num = strtol(cstr_vtable, NULL, 16);
// it's a simple class
if(type== "class")
{
mem->setClass(cstr_name, vtable_num);
}
// it's a multi-type class
else if (type == "multiclass")
{
// get offset of the type variable
const char *cstr_typeoffset = pClassEntry->Attribute("typeoffset");
uint32_t typeoffset = 0;
if(cstr_typeoffset)
typeoffset = strtol(cstr_typeoffset, NULL, 16);
t_class * mclass = mem->setClass(cstr_name, vtable_num, typeoffset);
// parse class sub-entries
pClassSubEntry = pClassEntry->FirstChildElement();
for(;pClassSubEntry;pClassSubEntry=pClassSubEntry->NextSiblingElement())
{
type = pClassSubEntry->Value();
if(type== "class")
{
// type is a value loaded from type offset
cstr_name = pClassSubEntry->Attribute("name");
const char *cstr_value = pClassSubEntry->Attribute("type");
mem->setClassChild(mclass,cstr_name,cstr_value);
}
}
}
}
}
struct breadcrumb
{
TiXmlElement * first;
OffsetGroup * second;
};
void VersionInfoFactory::ParseOffsets(TiXmlElement * parent, VersionInfo* target, bool initial)
{
// we parse the groups iteratively instead of recursively
// breadcrubs acts like a makeshift stack
// first pair entry stores the current element of that level
// second pair entry the group object from OffsetGroup
typedef triple< TiXmlElement *, OffsetGroup *, INVAL_TYPE> groupTriple;
vector< groupTriple > breadcrumbs;
{
TiXmlElement* pEntry;
// we get the <Offsets>, look at the children
pEntry = parent->FirstChildElement();
const char *cstr_invalid = parent->Attribute("valid");
INVAL_TYPE parent_inval = NOT_SET;
if(cstr_invalid)
{
if(strcmp(cstr_invalid,"false") == 0)
parent_inval = IS_INVALID;
else if(strcmp(cstr_invalid,"true") == 0)
parent_inval = IS_VALID;
}
OffsetGroup * currentGroup = reinterpret_cast<OffsetGroup *> (target);
currentGroup->setInvalid(parent_inval);
// we end here if there are no child tags.
if(!pEntry)
return;
breadcrumbs.push_back(groupTriple(pEntry,currentGroup, parent_inval));
}
// work variables
OffsetGroup * currentGroup = 0;
TiXmlElement * currentElem = 0;
INVAL_TYPE parent_inval = NOT_SET;
//cerr << "<Offsets>"<< endl;
while(1)
{
// get current work variables
currentElem = breadcrumbs.back().first;
currentGroup = breadcrumbs.back().second;
parent_inval = breadcrumbs.back().third;
// we reached the end of the current group?
if(!currentElem)
{
// go one level up
breadcrumbs.pop_back();
// exit if no more work
if(breadcrumbs.empty())
{
break;
}
else
{
//cerr << "</group>" << endl;
continue;
}
}
if(!currentGroup)
{
groupTriple & gp = breadcrumbs.back();
gp.first = gp.first->NextSiblingElement();
continue;
}
// skip non-elements
if (currentElem->Type() != TiXmlNode::ELEMENT)
{
groupTriple & gp = breadcrumbs.back();
gp.first = gp.first->NextSiblingElement();
continue;
}
// we have a valid current element and current group
// get properties
string type = currentElem->Value();
std::transform(type.begin(), type.end(), type.begin(), ::tolower);
const char *cstr_name = currentElem->Attribute("name");
if(!cstr_name)
{
// ERROR, missing attribute
}
// evaluate elements
const char *cstr_value = currentElem->Attribute("value");
const char *cstr_invalid = currentElem->Attribute("valid");
INVAL_TYPE child_inval = parent_inval;
if(cstr_invalid)
{
if(strcmp(cstr_invalid,"false") == 0)
child_inval = IS_INVALID;
else if(strcmp(cstr_invalid,"true") == 0)
child_inval = IS_VALID;
}
if(type == "group")
{
// create or get group
OffsetGroup * og;
if(initial)
og = currentGroup->createGroup(cstr_name);
else
og = currentGroup->getGroup(cstr_name);
// advance this level to the next element
groupTriple & gp = breadcrumbs.back();
gp.first = currentElem->NextSiblingElement();
if(!og)
{
string fullname = currentGroup->getFullName() + cstr_name;
throw Error::MissingMemoryDefinition("group", fullname);
}
// add a new level that will be processed in the next step
breadcrumbs.push_back(groupTriple(currentElem->FirstChildElement(), og, child_inval));
og->setInvalid(child_inval);
continue;
}
else if(type == "address")
{
if(child_inval == NOT_SET)
child_inval = IS_VALID;
if(initial)
{
currentGroup->createAddress(cstr_name);
}
else if(cstr_value)
{
currentGroup->setAddress(cstr_name, cstr_value, child_inval);
}
else
{
currentGroup->setAddressValidity(cstr_name, child_inval);
}
}
else if(type == "offset")
{
if(child_inval == NOT_SET)
child_inval = IS_VALID;
if(initial)
{
currentGroup->createOffset(cstr_name);
}
else if(cstr_value)
{
currentGroup->setOffset(cstr_name, cstr_value, child_inval);
}
else
{
currentGroup->setOffsetValidity(cstr_name, child_inval);
}
}
else if(type == "string")
{
if(child_inval == NOT_SET)
child_inval = IS_VALID;
if(initial)
{
currentGroup->createString(cstr_name);
}
else if(cstr_value)
{
currentGroup->setString(cstr_name, cstr_value, child_inval);
}
else
{
currentGroup->setStringValidity(cstr_name, child_inval);
}
}
else if(type == "hexvalue")
{
if(child_inval == NOT_SET)
child_inval = IS_VALID;
if(initial)
{
currentGroup->createHexValue(cstr_name);
}
else if(cstr_value)
{
currentGroup->setHexValue(cstr_name, cstr_value, child_inval);
}
else
{
currentGroup->setHexValueValidity(cstr_name, child_inval);
}
}
// advance to next element
groupTriple & gp = breadcrumbs.back();
gp.first = currentElem->NextSiblingElement();
continue;
}
//cerr << "</Offsets>"<< endl;
}
void VersionInfoFactory::ParseBase (TiXmlElement* entry, VersionInfo* mem)
{
TiXmlElement* pElement;
TiXmlElement* pElement2nd;
const char *cstr_version = entry->Attribute("name");
if (!cstr_version)
throw Error::MemoryXmlBadAttribute("name");
mem->setVersion(cstr_version);
mem->setOS(OS_BAD);
// process additional entries
pElement = entry->FirstChildElement()->ToElement();
for(;pElement;pElement=pElement->NextSiblingElement())
{
// only elements get processed
const char *cstr_type = pElement->Value();
std::string type = cstr_type;
if(type == "VTable")
{
ParseVTable(pElement, mem);
continue;
}
else if(type == "Offsets")
{
// we don't care about the descriptions here, do nothing
ParseOffsets(pElement, mem, true);
continue;
}
else if (type == "Professions")
{
pElement2nd = pElement->FirstChildElement("Profession");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Profession"))
{
const char * id = pElement2nd->Attribute("id");
const char * name = pElement2nd->Attribute("name");
// FIXME: missing some attributes here
if(id && name)
{
mem->setProfession(id,name);
}
else
{
// FIXME: this is crap, doesn't tell anything about the error
throw Error::MemoryXmlUnderspecifiedEntry(name);
}
}
}
else if (type == "Jobs")
{
pElement2nd = pElement->FirstChildElement("Job");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Job"))
{
const char * id = pElement2nd->Attribute("id");
const char * name = pElement2nd->Attribute("name");
if(id && name)
{
mem->setJob(id,name);
}
else
{
// FIXME: this is crap, doesn't tell anything about the error
throw Error::MemoryXmlUnderspecifiedEntry(name);
}
}
}
else if (type == "Skills")
{
pElement2nd = pElement->FirstChildElement("Skill");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Skill"))
{
const char * id = pElement2nd->Attribute("id");
const char * name = pElement2nd->Attribute("name");
if(id && name)
{
mem->setSkill(id,name);
}
else
{
// FIXME: this is crap, doesn't tell anything about the error
throw Error::MemoryXmlUnderspecifiedEntry(name);
}
}
}
else if (type == "Traits")
{
pElement2nd = pElement->FirstChildElement("Trait");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Trait"))
{
const char * id = pElement2nd->Attribute("id");
const char * name = pElement2nd->Attribute("name");
const char * lvl0 = pElement2nd->Attribute("level_0");
const char * lvl1 = pElement2nd->Attribute("level_1");
const char * lvl2 = pElement2nd->Attribute("level_2");
const char * lvl3 = pElement2nd->Attribute("level_3");
const char * lvl4 = pElement2nd->Attribute("level_4");
const char * lvl5 = pElement2nd->Attribute("level_5");
if(id && name && lvl0 && lvl1 && lvl2 && lvl3 && lvl4 && lvl5)
{
mem->setTrait(id, name, lvl0, lvl1, lvl2, lvl3, lvl4, lvl5);
}
else
{
// FIXME: this is crap, doesn't tell anything about the error
throw Error::MemoryXmlUnderspecifiedEntry(name);
}
}
}
else if (type == "Labors")
{
pElement2nd = pElement->FirstChildElement("Labor");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Labor"))
{
const char * id = pElement2nd->Attribute("id");
const char * name = pElement2nd->Attribute("name");
if(id && name)
{
mem->setLabor(id,name);
}
else
{
// FIXME: this is crap, doesn't tell anything about the error
throw Error::MemoryXmlUnderspecifiedEntry(name);
}
}
}
else if (type == "Levels")
{
pElement2nd = pElement->FirstChildElement("Level");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Level"))
{
const char * id = pElement2nd->Attribute("id");
const char * name = pElement2nd->Attribute("name");
const char * nextlvl = pElement2nd->Attribute("xpNxtLvl");
if(id && name && nextlvl)
{
mem->setLevel(id, name, nextlvl);
}
else
{
// FIXME: this is crap, doesn't tell anything about the error
throw Error::MemoryXmlUnderspecifiedEntry(name);
}
}
}
else if (type == "Moods")
{
pElement2nd = pElement->FirstChildElement("Mood");
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Mood"))
{
const char * id = pElement2nd->Attribute("id");
const char * name = pElement2nd->Attribute("name");
if(id && name)
{
mem->setMood(id, name);
}
else
{
// FIXME: this is crap, doesn't tell anything about the error
throw Error::MemoryXmlUnderspecifiedEntry(name);
}
}
}
else
{
//FIXME: only log, not hard error
//throw Error::MemoryXmlUnknownType(type.c_str());
}
} // for
} // method
void VersionInfoFactory::EvalVersion(string base, VersionInfo * mem)
{
if(knownVersions.find(base) != knownVersions.end())
{
v_descr & desc = knownVersions[base];
if (!desc.second)
{
VersionInfo * basemem = new VersionInfo();
ParseVersion(desc.first, basemem);
desc.second = basemem;
}
mem->copy(desc.second);
}
}
void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem)
{
TiXmlElement* pMemEntry;
const char *cstr_name = entry->Attribute("name");
const char *cstr_os = entry->Attribute("os");
const char *cstr_base = entry->Attribute("base");
const char *cstr_rebase = entry->Attribute("rebase");
if(cstr_base)
{
string base = cstr_base;
EvalVersion(base, mem);
}
if (!cstr_name)
throw Error::MemoryXmlBadAttribute("name");
const char *cstr_os = entry->Attribute("os");
if (!cstr_os)
throw Error::MemoryXmlBadAttribute("os");
string os = cstr_os;
mem->setVersion(cstr_name);
mem->setOS(cstr_os);
// offset inherited addresses by 'rebase'.
int32_t rebase = 0;
if(cstr_rebase)
{
rebase = mem->getBase() + strtol(cstr_rebase, NULL, 16);
mem->RebaseAddresses(rebase);
}
//set base to default, we're overwriting this because the previous rebase could cause havoc on Vista/7
if(os == "windows")
{
mem->setOS(OS_WINDOWS);
// set default image base. this is fixed for base relocation later
mem->setBase(0x400000);
}
else if(os == "linux")
{
mem->setOS(OS_LINUX);
// this is wrong... I'm not going to do base image relocation on linux though.
// users are free to use a sane kernel that doesn't do this kind of **** by default
mem->setBase(0x0);
}
else
@ -654,30 +118,29 @@ void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem)
string type, name, value;
const char *cstr_type = pMemEntry->Value();
type = cstr_type;
// check for missing parts
if(type == "VTable")
{
ParseVTable(pMemEntry, mem);
continue;
}
else if(type == "Offsets")
if(type == "Address")
{
ParseOffsets(pMemEntry, mem);
continue;
const char *cstr_key = currentElem->Attribute("name");
if(!cstr_key)
throw Error::MemoryXmlUnderspecifiedEntry(cstr_key);
const char *cstr_value = pMemEntry->Attribute("value");
if(!cstr_value)
throw Error::MemoryXmlUnderspecifiedEntry(cstr_name);
mem->setAddress(cstr_key, strtol(cstr_value, 0, 0));
}
else if (type == "MD5")
{
const char *cstr_value = pMemEntry->Attribute("value");
if(!cstr_value)
throw Error::MemoryXmlUnderspecifiedEntry(cstr_name);
mem->setMD5(cstr_value);
mem->addMD5(cstr_value);
}
else if (type == "PETimeStamp")
{
const char *cstr_value = pMemEntry->Attribute("value");
if(!cstr_value)
throw Error::MemoryXmlUnderspecifiedEntry(cstr_name);
mem->setPE(strtol(cstr_value, 0, 16));
mem->addPE(strtol(cstr_value, 0, 16));
}
} // for
} // method
@ -723,51 +186,16 @@ bool VersionInfoFactory::loadFile(string path_to_xml)
}
// transform elements
{
// trash existing list
for(size_t i = 0; i < versions.size(); i++)
{
delete versions[i];
}
versions.clear();
// For each base version
TiXmlElement* pMemInfo=hRoot.FirstChild( "Base" ).Element();
map <string ,TiXmlElement *> map_pNamedEntries;
vector <string> v_sEntries;
for( ; pMemInfo; pMemInfo=pMemInfo->NextSiblingElement("Base"))
{
const char *name = pMemInfo->Attribute("name");
if(name)
{
string str_name = name;
mem = new VersionInfo();
ParseBase( pMemInfo , mem );
knownVersions[str_name] = v_descr (pMemInfo, mem);
}
}
// For each derivative version
clear();
// For each version
pMemInfo=hRoot.FirstChild( "Version" ).Element();
for( ; pMemInfo; pMemInfo=pMemInfo->NextSiblingElement("Version"))
{
const char *name = pMemInfo->Attribute("name");
if(name)
{
string str_name = name;
knownVersions[str_name] = v_descr (pMemInfo, (VersionInfo *) NULL);
v_sEntries.push_back(str_name);
}
}
// Parse the versions
for(size_t i = 0; i< v_sEntries.size();i++)
{
//FIXME: add a set of entries processed in a step of this cycle, use it to check for infinite loops
string & name = v_sEntries[i];
v_descr & desc = knownVersions[name];
if(!desc.second)
{
VersionInfo *version = new VersionInfo();
ParseVersion( desc.first , version );
ParseVersion( pMemInfo , version );
versions.push_back(version);
}
}

@ -25,9 +25,6 @@ distribution.
#pragma once
#ifndef MEMINFO_H_INCLUDED
#define MEMINFO_H_INCLUDED
#include "Pragma.h"
#include "Export.h"
#include "Types.h"
@ -37,82 +34,6 @@ distribution.
namespace DFHack
{
/*
* Stubs
*/
class Process;
class XMLPP;
struct t_class;
class VersionInfoPrivate;
class OffsetGroupPrivate;
enum INVAL_TYPE
{
NOT_SET,
IS_INVALID,
IS_VALID
};
enum KEY_TYPE
{
IS_OFFSET,
IS_ADDRESS,
IS_HEX_VAL,
IS_STRING,
IS_GROUP
};
struct OffsetKey
{
std::string key;
INVAL_TYPE inval;
KEY_TYPE keytype;
};
/*
* Offset Group
*/
class DFHACK_EXPORT OffsetGroup
{
protected:
OffsetGroupPrivate * OGd;
public:
OffsetGroup();
OffsetGroup(const std::string & _name, OffsetGroup * parent = 0);
~OffsetGroup();
void copy(const OffsetGroup * old); // recursive
void RebaseAddresses( int32_t offset ); // recursive
void createOffset (const std::string & key);
void createAddress (const std::string & key);
void createHexValue (const std::string & key);
void createString (const std::string & key);
OffsetGroup * createGroup ( const std::string & name );
int32_t getOffset (const std::string & key);
char * getAddress (const std::string & key);
uint32_t getHexValue (const std::string & key);
std::string getString (const std::string & key);
OffsetGroup * getGroup ( const std::string & name );
bool getSafeOffset (const std::string & key, int32_t & out);
bool getSafeAddress (const std::string & key, void * & out);
void setOffset (const std::string& key, const std::string& value, const DFHack::INVAL_TYPE inval = IS_VALID);
void setOffsetValidity(const std::string& key, const DFHack::INVAL_TYPE inval = IS_VALID);
void setAddress (const std::string& key, const std::string& value, const DFHack::INVAL_TYPE inval = IS_VALID);
void setAddressValidity(const std::string& key, const DFHack::INVAL_TYPE inval = IS_VALID);
void setHexValue (const std::string& key, const std::string& value, const DFHack::INVAL_TYPE inval = IS_VALID);
void setHexValueValidity(const std::string& key, const DFHack::INVAL_TYPE inval = IS_VALID);
void setString (const std::string& key, const std::string& value, const DFHack::INVAL_TYPE inval = IS_VALID);
void setStringValidity(const std::string& key, const DFHack::INVAL_TYPE inval = IS_VALID);
std::string PrintOffsets(int indentation);
std::string getName();
std::string getFullName();
OffsetGroup * getParent();
void setInvalid(INVAL_TYPE arg1);
std::vector<OffsetKey> getKeys() const;
};
/*
* Version Info
*/
@ -123,99 +44,92 @@ namespace DFHack
OS_APPLE,
OS_BAD
};
class DFHACK_EXPORT VersionInfo : public OffsetGroup
struct DFHACK_EXPORT VersionInfo
{
private:
VersionInfoPrivate * d;
std::vector <std::string> md5_list;
std::vector <uint32_t> PE_list;
map <std::string, uint32_t> Addresses;
uint32_t base;
std::string version;
OSType OS;
public:
VersionInfo();
VersionInfo(const VersionInfo&);
void copy(const DFHack::VersionInfo* old);
~VersionInfo();
void RebaseAddresses(const int32_t new_base);
void RebaseAll(const int32_t new_base);
uint32_t getBase () const;
void setBase (const std::string&);
void setBase (const uint32_t);
void setMD5 (const std::string & _md5);
bool getMD5(std::string & output);
void setPE (uint32_t PE_);
bool getPE(uint32_t & output);
std::string getMood(const uint32_t moodID);
std::string getString (const std::string&);
std::string getProfession(const uint32_t) const;
std::string getJob(const uint32_t) const;
std::string getSkill (const uint32_t) const;
std::string getTrait (const uint32_t, const uint32_t) const;
std::string getTraitName(const uint32_t) const;
std::string getLabor (const uint32_t);
std::vector< std::vector<std::string> > const& getAllTraits();
std::map<uint32_t, std::string> const& getAllLabours();
DFHack::t_level getLevelInfo(const uint32_t level) const;
void setVersion(const char *);
void setVersion(const std::string&);
std::string getVersion();
void setOS(const char *);
void setOS(const std::string&);
void setOS(const OSType);
OSType getOS() const;
void setProfession(const std::string & id, const std::string & name);
void setJob(const std::string &, const std::string &);
void setSkill(const std::string &, const std::string &);
void setTrait(const std::string &, const std::string &, const std::string &,
const std::string &, const std::string &,
const std::string &, const std::string &, const std::string &);
void setLabor(const std::string &, const std::string &);
void setLevel(const std::string &nLevel, const std::string &nName,
const std::string &nXp);
void setMood(const std::string &id, const std::string &mood);
void RebaseVTable(const int32_t offset);
void setParentProcess(Process * _p);
t_class * setClass (const char * classname, uint32_t vptr = 0, uint32_t typeoffset = 0);
void setClassChild (t_class * parent, const char * classname, const char * type);
/**
* Get a classID from an address. The address has to point to the start of a virtual object (one with a virtual base class)
* uses memory reading directly, needs suspend. input = address of the object
* fails if it's unable to read from memory
*/
bool resolveObjectToClassID (const char * address, int32_t & classID);
/**
* Get a ClassID when you know the classname. can fail if the class is not in the cache
*/
bool resolveClassnameToClassID (const std::string classname, int32_t & classID);
/**
* Get a vptr from a classname. Can fail if the type is not in the cache
* limited to normal classes, variable-dependent types will resolve to the base class
*/
bool resolveClassnameToVPtr ( const std::string classname, void * & vptr );
/**
* Get a classname from a previous classID. Can fail if the type is not in the cache (you use bogus classID)
*/
bool resolveClassIDToClassname (const int32_t classID, std::string & classname);
/**
* Get the internal classID->classname mapping (for speed). DO NOT MANIPULATE THE VECTOR!
*/
const std::vector<std::string> * getClassIDMapping();
/**
* Get a string with all addresses and offsets
*/
std::string PrintOffsets();
VersionInfo()
{
base = 0;
version = "invalid";
OS = OS_BAD;
};
VersionInfo(const VersionInfo& rhs)
{
md5_list = rhs.md5_list;
PE_list = rhs.PE_list;
Addresses = rhs.Addresses;
base = rhs.base;
version = rhs.version;
OS = rhs.OS;
};
uint32_t getBase () const { return base; };
void setBase (const uint32_t _base) { base = _base; };
void rebaseTo(const uint32_t new_base)
{
int64_t old = base;
int64_t new = new_base;
int64_t rebase = new - old;
base = new_base;
auto iter = Addresses.start();
while (iter != Addresses.end())
{
uint32_t & ref = *iter.second;
ref += rebase;
iter ++;
}
};
void addMD5 (const std::string & _md5)
{
md5_list.push_back(_md5);
};
bool hasMD5 (const std::string & _md5) const
{
return find(md5_list.begin(), md5_list.end(), PE_) != md5_list.end();
};
void addPE (uint32_t PE_)
{
PE_list.push_back(PE_);
};
bool hasPE (uint32_t PE_) const
{
return find(PE_list.begin(), PE_list.end(), PE_) != PE_list.end();
};
void setVersion(const std::string& v)
{
version = v;
};
std::string getVersion() const { return version; };
void setAddress (const std::string& key, const uint32_t value)
{
Addresses[key] = value;
};
uint32_t getAddress (const std::string& key) const;
{
iter i = Addresses.find(key);
if(i == Addresses.end())
return 0;
return *i.second;
}
void setOS(const OSType os)
{
OS = os;
};
OSType getOS() const
{
return OS;
};
};
}
#endif // MEMINFO_H_INCLUDED

@ -25,9 +25,6 @@ distribution.
#pragma once
#ifndef MEMINFO_MANAGER_H_INCLUDED
#define MEMINFO_MANAGER_H_INCLUDED
#include "Pragma.h"
#include "Export.h"
@ -37,29 +34,18 @@ namespace DFHack
class VersionInfo;
class DFHACK_EXPORT VersionInfoFactory
{
friend class ProcessEnumerator;
public:
VersionInfoFactory();
~VersionInfoFactory();
// memory info entries loaded from a file
bool loadFile( std::string path_to_xml);
bool isInErrorState() const {return error;};
VersionInfo * getVersionInfoByMD5(std::string md5string);
VersionInfo * getVersionInfoByPETimestamp(uint32_t timestamp);
std::vector<VersionInfo*> versions;
void clear( void );
// trash existing list
void clear();
private:
void ParseVTable(TiXmlElement* vtable, VersionInfo* mem);
void ParseBase (TiXmlElement* base, VersionInfo* mem);
void ParseVersion (TiXmlElement* version, VersionInfo* mem);
// copy version 'base' to 'target' or throw
void EvalVersion(std::string base, VersionInfo* target);
void ParseOffsets(TiXmlElement* elem, VersionInfo* target, bool initial = false);
bool error;
typedef std::pair < TiXmlElement *, VersionInfo *> v_descr;
std::map <std::string , v_descr > knownVersions;
};
}
#endif