From 368de864a1723df3ece4c58968036e76c8035e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Mon, 23 Aug 2010 01:29:55 +0200 Subject: [PATCH] Sync --- library/DFProcessEnumerator.cpp | 6 +- library/VersionInfo.cpp | 77 ++++-- library/VersionInfoFactory.cpp | 363 ++++++++++++++++++++------- library/include/dfhack/VersionInfo.h | 23 +- library/private/VersionInfoFactory.h | 13 +- 5 files changed, 361 insertions(+), 121 deletions(-) diff --git a/library/DFProcessEnumerator.cpp b/library/DFProcessEnumerator.cpp index b43139965..19164be88 100644 --- a/library/DFProcessEnumerator.cpp +++ b/library/DFProcessEnumerator.cpp @@ -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 diff --git a/library/VersionInfo.cpp b/library/VersionInfo.cpp index 7d55daaba..ea743e209 100644 --- a/library/VersionInfo.cpp +++ b/library/VersionInfo.cpp @@ -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::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); } diff --git a/library/VersionInfoFactory.cpp b/library/VersionInfoFactory.cpp index 6f2e6a32b..002b9ae4f 100644 --- a/library/VersionInfoFactory.cpp +++ b/library/VersionInfoFactory.cpp @@ -32,18 +32,19 @@ using namespace DFHack; VersionInfoFactory::~VersionInfoFactory() { - // for each in std::vector 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 & 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 map_pNamedEntries; - vector v_pEntries; - for( ; pMemInfo; pMemInfo=pMemInfo->NextSiblingElement("Entry")) + vector 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; diff --git a/library/include/dfhack/VersionInfo.h b/library/include/dfhack/VersionInfo.h index ed6404792..1bdb4a794 100644 --- a/library/include/dfhack/VersionInfo.h +++ b/library/include/dfhack/VersionInfo.h @@ -28,6 +28,7 @@ distribution. #include "DFPragma.h" #include "DFExport.h" #include "dfhack/DFTypes.h" +#include 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 &, diff --git a/library/private/VersionInfoFactory.h b/library/private/VersionInfoFactory.h index 9b5a40e51..36c1cbd78 100644 --- a/library/private/VersionInfoFactory.h +++ b/library/private/VersionInfoFactory.h @@ -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 meminfo; + std::vector versions; private: void ParseVTable(TiXmlElement* vtable, VersionInfo* mem); - void ParseEntry (TiXmlElement* entry, VersionInfo* mem, map & 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 knownVersions; }; }