develop
Petr Mrázek 2010-08-23 01:29:55 +02:00
parent 1bceac2343
commit 368de864a1
5 changed files with 361 additions and 121 deletions

@ -120,19 +120,19 @@ Process * BadProcesses::operator[](uint32_t index)
Process *ProcessEnumerator::Private::GetProcessObject(ProcessID ID)
{
Process *p1 = new SHMProcess(ID.pid,meminfo->meminfo);
Process *p1 = new SHMProcess(ID.pid,meminfo->versions);
if(p1->isIdentified())
return p1;
else
delete p1;
Process *p2 = new NormalProcess(ID.pid,meminfo->meminfo);
Process *p2 = new NormalProcess(ID.pid,meminfo->versions);
if(p2->isIdentified())
return p2;
else
delete p2;
#ifdef LINUX_BUILD
Process *p3 = new WineProcess(ID.pid,meminfo->meminfo);
Process *p3 = new WineProcess(ID.pid,meminfo->versions);
if(p3->isIdentified())
return p3;
else

@ -118,6 +118,8 @@ class VersionInfo::Private
string version;
OSType OS;
std::string md5;
uint32_t PE_timestamp;
};
@ -130,6 +132,8 @@ VersionInfo::VersionInfo()
d->classindex = 0;
d->levels.reserve(NUM_RESERVE_LVLS);
d->moods.reserve(NUM_RESERVE_MOODS);
d->md5 = "invalid";
d->PE_timestamp = 0;
}
@ -137,31 +141,37 @@ VersionInfo::VersionInfo()
VersionInfo::VersionInfo(const VersionInfo &old)
:d(new Private)
{
d->version = old.d->version;
d->OS = old.d->OS;
d->addresses = old.d->addresses;
d->offsets = old.d->offsets;
d->hexvals = old.d->hexvals;
d->strings = old.d->strings;
d->base = old.d->base;
copy(&old);
}
void VersionInfo::copy(const VersionInfo * old)
{
d->version = old->d->version;
d->OS = old->d->OS;
d->md5 = old->d->md5;
d->PE_timestamp = old->d->PE_timestamp;
d->addresses = old->d->addresses;
d->offsets = old->d->offsets;
d->hexvals = old->d->hexvals;
d->strings = old->d->strings;
d->base = old->d->base;
//d->classes = old.d->classes;
for(uint32_t i = 0; i < old.d->classes.size(); i++)
for(uint32_t i = 0; i < old->d->classes.size(); i++)
{
t_class * copy = new t_class(*old.d->classes[i]);
t_class * copy = new t_class(*old->d->classes[i]);
d->classes.push_back(copy);
}
d->classnames = old.d->classnames;
d->classindex = old.d->classindex;
d->professions = old.d->professions;
d->jobs = old.d->jobs;
d->skills = old.d->skills;
d->traits = old.d->traits;
d->labors = old.d->labors;
d->levels = old.d->levels;
d->moods = old.d->moods;
d->classnames = old->d->classnames;
d->classindex = old->d->classindex;
d->professions = old->d->professions;
d->jobs = old->d->jobs;
d->skills = old->d->skills;
d->traits = old->d->traits;
d->labors = old->d->labors;
d->levels = old->d->levels;
d->moods = old->d->moods;
}
void VersionInfo::setParentProcess(Process * _p)
{
d->p = _p;
@ -198,6 +208,25 @@ string VersionInfo::getVersion()
return d->version;
}
void VersionInfo::setMD5(const string &v)
{
d->md5 = v;
}
string VersionInfo::getMD5()
{
return d->md5;
}
void VersionInfo::setPE(uint32_t v)
{
d->PE_timestamp = v;
}
uint32_t VersionInfo::getPE()
{
return d->PE_timestamp;
}
void VersionInfo::setOS(const char *os)
{
@ -206,6 +235,8 @@ void VersionInfo::setOS(const char *os)
d->OS = OS_WINDOWS;
else if(oss == "linux")
d->OS = OS_LINUX;
else if(oss == "apple")
d->OS = OS_APPLE;
else
d->OS = OS_BAD;
}
@ -217,6 +248,8 @@ void VersionInfo::setOS(const string &os)
d->OS = OS_WINDOWS;
else if(os == "linux")
d->OS = OS_LINUX;
else if(os == "apple")
d->OS = OS_APPLE;
else
d->OS = OS_BAD;
}
@ -550,12 +583,8 @@ void VersionInfo::RebaseAddresses(const int32_t new_base)
// change base of all addresses *and* vtable entries
void VersionInfo::RebaseAll(int32_t new_base)
{
map<string, uint32_t>::iterator iter;
RebaseAddresses(new_base);
int32_t rebase = - (int32_t)d->base + new_base;
for(iter = d->addresses.begin(); iter != d->addresses.end(); iter++)
{
d->addresses[iter->first] = iter->second + rebase;
}
RebaseVTable(rebase);
}

@ -32,18 +32,19 @@ using namespace DFHack;
VersionInfoFactory::~VersionInfoFactory()
{
// for each in std::vector<memory_info*> meminfo;, delete
for(uint32_t i = 0; i < meminfo.size();i++)
// for each stored version, delete
for(uint32_t i = 0; i < versions.size();i++)
{
delete meminfo[i];
delete versions[i];
}
meminfo.clear();
versions.clear();
}
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)
@ -51,6 +52,7 @@ void VersionInfoFactory::ParseVTable(TiXmlElement* vtable, VersionInfo* mem)
int32_t rebase_offset = strtol(rebase, NULL, 16);
mem->RebaseVTable(rebase_offset);
}
*/
// parse vtable entries
pClassEntry = vtable->FirstChildElement();
for(;pClassEntry;pClassEntry=pClassEntry->NextSiblingElement())
@ -92,26 +94,214 @@ void VersionInfoFactory::ParseVTable(TiXmlElement* vtable, VersionInfo* mem)
}
}
void VersionInfoFactory::ParseEntry (TiXmlElement* entry, VersionInfo* mem, map <string ,TiXmlElement *>& knownEntries)
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(VersionInfo::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
//ParseBaseOffsets(pMemEntry, mem);
continue;
}
else if (type == "Professions")
{
pElement2nd = entry->FirstChildElement("Profession")->ToElement();
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 = entry->FirstChildElement("Job")->ToElement();
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 = entry->FirstChildElement("Skill")->ToElement();
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 = entry->FirstChildElement("Trait")->ToElement();
for(;pElement2nd;pElement2nd=pElement2nd->NextSiblingElement("Trait"))
{
const char * id = pElement2nd->Attribute("id");
const char * name = pElement2nd->Attribute("name");
const char * lvl0 = pElement->Attribute("level_0");
const char * lvl1 = pElement->Attribute("level_1");
const char * lvl2 = pElement->Attribute("level_2");
const char * lvl3 = pElement->Attribute("level_3");
const char * lvl4 = pElement->Attribute("level_4");
const char * lvl5 = pElement->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 = entry->FirstChildElement("Labor")->ToElement();
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 = entry->FirstChildElement("Level")->ToElement();
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 = entry->FirstChildElement("Mood")->ToElement();
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 * newmem = new VersionInfo();
ParseVersion(desc.first, newmem);
desc.second = newmem;
versions.push_back(newmem);
}
mem->copy(desc.second);
}
}
void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem)
{
TiXmlElement* pMemEntry;
const char *cstr_version = entry->Attribute("version");
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;
ParseEntry(knownEntries[base], mem, knownEntries);
EvalVersion(base, mem);
}
if (!cstr_version)
throw Error::MemoryXmlBadAttribute("version");
if (!cstr_name)
throw Error::MemoryXmlBadAttribute("name");
if (!cstr_os)
throw Error::MemoryXmlBadAttribute("os");
string os = cstr_os;
mem->setVersion(cstr_version);
mem->setVersion(cstr_name);
mem->setOS(cstr_os);
// offset inherited addresses by 'rebase'.
@ -134,10 +324,6 @@ void VersionInfoFactory::ParseEntry (TiXmlElement* entry, VersionInfo* mem, map
// users are free to use a sane kernel that doesn't do this kind of **** by default
mem->setBase(0x0);
}
else if ( os == "all")
{
// yay
}
else
{
throw Error::MemoryXmlBadAttribute("os");
@ -148,75 +334,55 @@ void VersionInfoFactory::ParseEntry (TiXmlElement* entry, VersionInfo* mem, map
pMemEntry = entry->FirstChildElement()->ToElement();
for(;pMemEntry;pMemEntry=pMemEntry->NextSiblingElement())
{
// only elements get processed
const char *cstr_type = pMemEntry->Value();
const char *cstr_name = pMemEntry->Attribute("name");
const char *cstr_value = pMemEntry->GetText();
if(!cstr_value)
cstr_value = pMemEntry->Attribute("id");
// check for missing parts
string type, name, value;
const char *cstr_type = pMemEntry->Value();
type = cstr_type;
// check for missing parts
if(type == "VTable")
{
ParseVTable(pMemEntry, mem);
continue;
}
if(!(cstr_name && cstr_value))
{
throw Error::MemoryXmlUnderspecifiedEntry(cstr_version);
}
name = cstr_name;
value = cstr_value;
if (type == "HexValue")
{
mem->setHexValue(name, value);
}
else if (type == "Address")
{
mem->setAddress(name, value);
}
else if (type == "Offset")
{
mem->setOffset(name, value);
}
else if (type == "String")
{
mem->setString(name, value);
}
else if (type == "Profession")
{
mem->setProfession(value,name);
}
else if (type == "Job")
{
mem->setJob(value,name);
}
else if (type == "Skill")
{
mem->setSkill(value,name);
}
else if (type == "Trait")
else if(type == "Offsets")
{
mem->setTrait(value, name,pMemEntry->Attribute("level_0"),pMemEntry->Attribute("level_1"),pMemEntry->Attribute("level_2"),pMemEntry->Attribute("level_3"),pMemEntry->Attribute("level_4"),pMemEntry->Attribute("level_5"));
}
else if (type == "Labor")
{
mem->setLabor(value,name);
}
else if (type == "Level")
{
mem->setLevel(value, name, pMemEntry->Attribute("xpNxtLvl"));
/*
if (type == "HexValue")
{
mem->setHexValue(name, value);
}
else if (type == "Address")
{
mem->setAddress(name, value);
}
else if (type == "Offset")
{
mem->setOffset(name, value);
}
else if (type == "String")
{
mem->setString(name, value);
}
else
{
throw Error::MemoryXmlUnknownType(type.c_str());
}
*/
//ParseOffsets(pMemEntry, mem);
continue;
}
else if (type == "Mood")
else if (type == "MD5")
{
mem->setMood(value, name);
const char *cstr_value = pMemEntry->Attribute("value");
if(!cstr_value)
throw Error::MemoryXmlUnderspecifiedEntry(cstr_name);
mem->setMD5(cstr_value);
}
else
else if (type == "PETimeStamp")
{
throw Error::MemoryXmlUnknownType(type.c_str());
const char *cstr_value = pMemEntry->Attribute("value");
if(!cstr_value)
throw Error::MemoryXmlUnderspecifiedEntry(cstr_name);
mem->setPE(atol(cstr_value));
}
} // for
} // method
@ -240,7 +406,7 @@ bool VersionInfoFactory::loadFile(string path_to_xml)
TiXmlHandle hDoc(&doc);
TiXmlElement* pElem;
TiXmlHandle hRoot(0);
VersionInfo mem;
VersionInfo *mem;
// block: name
{
@ -263,31 +429,54 @@ bool VersionInfoFactory::loadFile(string path_to_xml)
// transform elements
{
// trash existing list
for(uint32_t i = 0; i < meminfo.size(); i++)
for(uint32_t i = 0; i < versions.size(); i++)
{
delete meminfo[i];
delete versions[i];
}
meminfo.clear();
TiXmlElement* pMemInfo=hRoot.FirstChild( "MemoryDescriptors" ).FirstChild( "Entry" ).Element();
versions.clear();
// For each base version
TiXmlElement* pMemInfo=hRoot.FirstChild( "Base" ).Element();
map <string ,TiXmlElement *> map_pNamedEntries;
vector <TiXmlElement *> v_pEntries;
for( ; pMemInfo; pMemInfo=pMemInfo->NextSiblingElement("Entry"))
vector <string> v_sEntries;
for( ; pMemInfo; pMemInfo=pMemInfo->NextSiblingElement("Base"))
{
v_pEntries.push_back(pMemInfo);
const char *id = pMemInfo->Attribute("id");
if(id)
const char *name = pMemInfo->Attribute("name");
if(name)
{
string str_id = id;
map_pNamedEntries[str_id] = pMemInfo;
string str_name = name;
VersionInfo *base = new VersionInfo();
ParseBase( pMemInfo , mem );
knownVersions[str_name] = v_descr (pMemInfo, mem);
}
}
for(uint32_t i = 0; i< v_pEntries.size();i++)
// For each derivative 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, NULL);
v_sEntries.push_back(str_name);
}
}
// Parse the versions
for(uint32_t i = 0; i< v_sEntries.size();i++)
{
VersionInfo *mem = new VersionInfo();
//FIXME: add a set of entries processed in a step of this cycle, use it to check for infinite loops
/* recursive */ParseEntry( v_pEntries[i] , mem , map_pNamedEntries);
meminfo.push_back(mem);
string & name = v_sEntries[i];
v_descr & desc = knownVersions[name];
if(!desc.second)
{
VersionInfo *version = new VersionInfo();
ParseVersion( desc.first , version );
versions.push_back(version);
}
}
// process found things here
}
error = false;

@ -28,6 +28,7 @@ distribution.
#include "DFPragma.h"
#include "DFExport.h"
#include "dfhack/DFTypes.h"
#include <sys/types.h>
namespace DFHack
{
@ -36,21 +37,31 @@ namespace DFHack
*/
class Process;
struct t_class;
class VersionInfoPrivate;
class OffsetGroupPrivate;
class DFHACK_EXPORT OffsetGroup
{
private:
OffsetGroupPrivate * d;
public:
};
class DFHACK_EXPORT VersionInfo
{
private:
class Private;
Private * d;
VersionInfoPrivate * d;
public:
enum OSType
{
OS_WINDOWS,
OS_LINUX,
OS_APPLE,
OS_BAD
};
VersionInfo();
VersionInfo(const VersionInfo&);
void copy(const DFHack::VersionInfo* old);
~VersionInfo();
void RebaseAddresses(const int32_t new_base);
@ -59,6 +70,12 @@ namespace DFHack
void setBase (const std::string&);
void setBase (const uint32_t);
void setMD5 (const std::string & _md5);
std::string getMD5();
void setPE (uint32_t PE_);
uint getPE();
int32_t getOffset (const std::string&);
uint32_t getAddress (const std::string&);
uint32_t getHexValue (const std::string&);
@ -101,7 +118,7 @@ namespace DFHack
void setHexValue (const std::string &, const std::string &);
void setString (const std::string &, const std::string &);
void setProfession(const std::string &, const std::string &);
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 &,

@ -35,16 +35,21 @@ namespace DFHack
{
friend class ProcessEnumerator;
public:
VersionInfoFactory(string path_to_xml);
VersionInfoFactory(std::string path_to_xml);
~VersionInfoFactory();
// memory info entries loaded from a file
bool loadFile( string path_to_xml);
bool loadFile( std::string path_to_xml);
bool isInErrorState() const {return error;};
std::vector<VersionInfo*> meminfo;
std::vector<VersionInfo*> versions;
private:
void ParseVTable(TiXmlElement* vtable, VersionInfo* mem);
void ParseEntry (TiXmlElement* entry, VersionInfo* mem, map <string ,TiXmlElement *>& knownEntries);
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);
bool error;
typedef std::pair < TiXmlElement *, VersionInfo *> v_descr;
std::map <std::string , v_descr > knownVersions;
};
}