From 97bfa32a82d02eba4db792ecc59af0f400348b05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Thu, 24 Feb 2011 11:43:33 +0100 Subject: [PATCH] More cleanup in the Process lands. --- library/DFProcess-SHM.cpp | 8 +-- library/DFProcess-linux-SHM.cpp | 32 ++++------ library/DFProcess-linux-wine.cpp | 63 +++++-------------- library/DFProcess-linux.cpp | 51 ++++----------- library/DFProcess-windows-SHM.cpp | 34 +++------- library/DFProcess-windows.cpp | 70 +++++++-------------- library/DFProcessEnumerator.cpp | 6 +- library/VersionInfoFactory.cpp | 41 ++++++++++-- library/include/dfhack/VersionInfoFactory.h | 2 + library/include/dfhack/modules/Maps.h | 10 +-- library/private/LinuxProcess.h | 5 -- library/private/ProcessFactory.h | 7 ++- library/private/SHMProcess.h | 5 +- 13 files changed, 124 insertions(+), 210 deletions(-) diff --git a/library/DFProcess-SHM.cpp b/library/DFProcess-SHM.cpp index 3246e567e..2d907c32b 100644 --- a/library/DFProcess-SHM.cpp +++ b/library/DFProcess-SHM.cpp @@ -31,12 +31,12 @@ distribution. using namespace DFHack; -Process* DFHack::createSHMProcess(uint32_t pid, vector & known_versions) +Process* DFHack::createSHMProcess(uint32_t pid, VersionInfoFactory * factory) { - return new SHMProcess(pid, known_versions); + return new SHMProcess(pid, factory); } -SHMProcess::SHMProcess(uint32_t PID, vector & known_versions) +SHMProcess::SHMProcess(uint32_t PID, VersionInfoFactory * factory) : d(new Private(this)) { d->process_ID = PID; @@ -59,7 +59,7 @@ SHMProcess::SHMProcess(uint32_t PID, vector & known_versions) } // try to identify the DF version (md5 the binary, compare with known versions) - d->validate(known_versions); + d->validate(factory); // at this point, DF is attached and suspended, make it run detach(); } diff --git a/library/DFProcess-linux-SHM.cpp b/library/DFProcess-linux-SHM.cpp index 8229b6adb..2f5889908 100644 --- a/library/DFProcess-linux-SHM.cpp +++ b/library/DFProcess-linux-SHM.cpp @@ -216,7 +216,7 @@ bool SHMProcess::Private::AreLocksOk() } -bool SHMProcess::Private::validate(vector & known_versions) +bool SHMProcess::Private::validate(VersionInfoFactory * factory) { char exe_link_name [256]; char target_name[1024]; @@ -233,29 +233,19 @@ bool SHMProcess::Private::validate(vector & known_versions) // see http://www.opengroup.org/onlinepubs/000095399/functions/readlink.html target_name[target_result] = 0; - md5wrapper md5; // get hash of the running DF process + md5wrapper md5; string hash = md5.getHashFromFile(target_name); - vector::iterator it; - // cerr << exe_file << " " << hash << endl; - // iterate over the list of memory locations - for ( it=known_versions.begin() ; it < known_versions.end(); it++ ) + + // create linux process, add it to the vector + VersionInfo * vinfo = factory->getVersionInfoByMD5(hash); + if(vinfo) { - try{ - if(hash == (*it)->getMD5()) // are the md5 hashes the same? - { - VersionInfo *m = new VersionInfo(**it); - memdescriptor = m; - m->setParentProcess(self); - identified = true; - // cerr << "identified " << m->getVersion() << endl; - return true; - } - } - catch (Error::AllMemdef&) - { - continue; - } + memdescriptor = vinfo; + // FIXME: BIG BAD BUG RIGHT HERE!!!! + memdescriptor->setParentProcess(self); + identified = true; + return true; } return false; } diff --git a/library/DFProcess-linux-wine.cpp b/library/DFProcess-linux-wine.cpp index 7f28f8d9e..073efcaa2 100644 --- a/library/DFProcess-linux-wine.cpp +++ b/library/DFProcess-linux-wine.cpp @@ -38,24 +38,22 @@ namespace { private: MicrosoftSTL stl; public: - WineProcess(uint32_t pid, std::vector & known_versions); + WineProcess(uint32_t pid, VersionInfoFactory * factory); const std::string readSTLString (uint32_t offset); size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity); void writeSTLString(const uint32_t address, const std::string writeString){}; // get class name of an object with rtti/type info std::string readClassName(uint32_t vptr); - private: - bool validate(char * exe_file,uint32_t pid, char * memFile, vector & known_versions); }; } -Process* DFHack::createWineProcess(uint32_t pid, vector & known_versions) +Process* DFHack::createWineProcess(uint32_t pid, VersionInfoFactory * factory) { - return new WineProcess(pid, known_versions); + return new WineProcess(pid, factory); } -WineProcess::WineProcess(uint32_t pid, vector & known_versions) : LinuxProcessBase(pid) +WineProcess::WineProcess(uint32_t pid, VersionInfoFactory * factory) : LinuxProcessBase(pid) { char dir_name [256]; char exe_link_name [256]; @@ -71,6 +69,7 @@ WineProcess::WineProcess(uint32_t pid, vector & known_versions) sprintf(dir_name,"/proc/%d/", pid); sprintf(exe_link_name,"/proc/%d/exe", pid); sprintf(mem_name,"/proc/%d/mem", pid); + memFile = mem_name; sprintf(cwd_name,"/proc/%d/cwd", pid); sprintf(cmdline_name,"/proc/%d/cmdline", pid); @@ -101,51 +100,23 @@ WineProcess::WineProcess(uint32_t pid, vector & known_versions) // put executable name and path together sprintf(exe_link,"%s/%s",target_name,cmdline.c_str()); - // create wine process, add it to the vector - identified = validate(exe_link,pid,mem_name,known_versions); - return; - } - } -} - - -bool WineProcess::validate(char * exe_file,uint32_t pid, char * memFile, vector & known_versions) -{ - md5wrapper md5; - // get hash of the running DF process - string hash = md5.getHashFromFile(exe_file); - vector::iterator it; - - // iterate over the list of memory locations - for ( it=known_versions.begin() ; it < known_versions.end(); it++ ) - { - try - { - if (hash == (*it)->getMD5()) // are the md5 hashes the same? + md5wrapper md5; + // get hash of the running DF process + string hash = md5.getHashFromFile(exe_link); + // create linux process, add it to the vector + VersionInfo * vinfo = factory->getVersionInfoByMD5(hash); + if(vinfo) { - if (OS_WINDOWS == (*it)->getOS()) - { - // keep track of created memory_info object so we can destroy it later - my_descriptor = new VersionInfo(**it); - my_descriptor->setParentProcess(this); - // tell Process about the /proc/PID/mem file - memFile = memFile; - identified = true; - - stl.init(this); - return true; - } + my_descriptor = new VersionInfo(*vinfo); + my_descriptor->setParentProcess(this); + stl.init(this); + identified = true; } - } - catch (Error::AllMemdef&) - { - continue; + return; } } - return false; } - size_t WineProcess::readSTLString (uint32_t offset, char * buffer, size_t bufcapacity) { return stl.readSTLString(offset, buffer, bufcapacity); @@ -158,5 +129,5 @@ const string WineProcess::readSTLString (uint32_t offset) string WineProcess::readClassName (uint32_t vptr) { - stl.readClassName(vptr); + return stl.readClassName(vptr); } diff --git a/library/DFProcess-linux.cpp b/library/DFProcess-linux.cpp index dda919663..216f4babe 100644 --- a/library/DFProcess-linux.cpp +++ b/library/DFProcess-linux.cpp @@ -34,24 +34,22 @@ namespace { class NormalProcess : public LinuxProcessBase { public: - NormalProcess(uint32_t pid, std::vector & known_versions); + NormalProcess(uint32_t pid, VersionInfoFactory * known_versions); const std::string readSTLString (uint32_t offset); size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity); void writeSTLString(const uint32_t address, const std::string writeString){}; // get class name of an object with rtti/type info std::string readClassName(uint32_t vptr); - private: - bool validate(char * exe_file,uint32_t pid, char * memFile, vector & known_versions); }; } -Process* DFHack::createNormalProcess(uint32_t pid, vector & known_versions) +Process* DFHack::createNormalProcess(uint32_t pid, VersionInfoFactory * known_versions) { return new NormalProcess(pid, known_versions); } -NormalProcess::NormalProcess(uint32_t pid, vector & known_versions) : LinuxProcessBase(pid) +NormalProcess::NormalProcess(uint32_t pid, VersionInfoFactory * known_versions) : LinuxProcessBase(pid) { char dir_name [256]; char exe_link_name [256]; @@ -67,6 +65,7 @@ NormalProcess::NormalProcess(uint32_t pid, vector & known_versio sprintf(dir_name,"/proc/%d/", pid); sprintf(exe_link_name,"/proc/%d/exe", pid); sprintf(mem_name,"/proc/%d/mem", pid); + memFile = mem_name; sprintf(cwd_name,"/proc/%d/cwd", pid); sprintf(cmdline_name,"/proc/%d/cmdline", pid); @@ -82,44 +81,18 @@ NormalProcess::NormalProcess(uint32_t pid, vector & known_versio // is this the regular linux DF? if (strstr(target_name, "dwarfort.exe") != 0 || strstr(target_name,"Dwarf_Fortress") != 0) { + md5wrapper md5; + // get hash of the running DF process + string hash = md5.getHashFromFile(target_name); // create linux process, add it to the vector - identified = validate(target_name,pid,mem_name,known_versions); - return; - } -} - -bool NormalProcess::validate(char * exe_file,uint32_t pid, char * memFile, vector & known_versions) -{ - md5wrapper md5; - // get hash of the running DF process - string hash = md5.getHashFromFile(exe_file); - vector::iterator it; - - // iterate over the list of memory locations - for ( it=known_versions.begin() ; it < known_versions.end(); it++ ) - { - try - { - if (hash == (*it)->getMD5()) // are the md5 hashes the same? - { - if (OS_LINUX == (*it)->getOS()) - { - // keep track of created memory_info object so we can destroy it later - my_descriptor = new VersionInfo(**it); - my_descriptor->setParentProcess(this); - // tell Process about the /proc/PID/mem file - memFile = memFile; - identified = true; - return true; - } - } - } - catch (Error::AllMemdef&) + VersionInfo * vinfo = known_versions->getVersionInfoByMD5(hash); + if(vinfo) { - continue; + my_descriptor = new VersionInfo(*vinfo); + my_descriptor->setParentProcess(this); + identified = true; } } - return false; } struct _Rep_base diff --git a/library/DFProcess-windows-SHM.cpp b/library/DFProcess-windows-SHM.cpp index 37d74697a..50c410b39 100644 --- a/library/DFProcess-windows-SHM.cpp +++ b/library/DFProcess-windows-SHM.cpp @@ -216,7 +216,7 @@ bool SHMProcess::Private::AreLocksOk() return false; } -bool SHMProcess::Private::validate(vector & known_versions) +bool SHMProcess::Private::validate(VersionInfoFactory * factory) { // try to identify the DF version IMAGE_NT_HEADERS pe_header; @@ -246,30 +246,16 @@ bool SHMProcess::Private::validate(vector & known_versions) self->read(base + pe_offset , sizeof(pe_header), (uint8_t *)&pe_header); self->read(base + pe_offset+ sizeof(pe_header), sizeof(sections) , (uint8_t *)§ions ); - // iterate over the list of memory locations - vector::iterator it; - for ( it=known_versions.begin() ; it < known_versions.end(); it++ ) + VersionInfo* vinfo = factory->getVersionInfoByPETimestamp(pe_header.FileHeader.TimeDateStamp); + if(vinfo) { - uint32_t pe_timestamp; - try - { - pe_timestamp = (*it)->getPE(); - } - catch(Error::AllMemdef&) - { - continue; - } - if (pe_timestamp == pe_header.FileHeader.TimeDateStamp) - { - VersionInfo *m = new VersionInfo(**it); - m->RebaseAll(base); - memdescriptor = m; - m->setParentProcess(self); - identified = true; - cerr << "identified " << m->getVersion() << endl; - CloseHandle(hProcess); - return true; - } + VersionInfo *m = new VersionInfo(*vinfo); + m->RebaseAll(base); + memdescriptor = m; + m->setParentProcess(self); + identified = true; + CloseHandle(hProcess); + return true; } return false; } diff --git a/library/DFProcess-windows.cpp b/library/DFProcess-windows.cpp index 9f637e944..77ac2c3a0 100644 --- a/library/DFProcess-windows.cpp +++ b/library/DFProcess-windows.cpp @@ -47,7 +47,7 @@ namespace uint32_t base; MicrosoftSTL stl; public: - NormalProcess(uint32_t pid, std::vector & known_versions); + NormalProcess(uint32_t pid, VersionInfoFactory * factory); ~NormalProcess(); bool attach(); bool detach(); @@ -101,12 +101,12 @@ namespace } -Process* DFHack::createNormalProcess(uint32_t pid, vector & known_versions) +Process* DFHack::createNormalProcess(uint32_t pid, VersionInfoFactory * factory) { - return new NormalProcess(pid, known_versions); + return new NormalProcess(pid, factory); } -NormalProcess::NormalProcess(uint32_t pid, vector & known_versions) +NormalProcess::NormalProcess(uint32_t pid, VersionInfoFactory * factory) : my_pid(pid) { my_descriptor = NULL; @@ -155,56 +155,30 @@ NormalProcess::NormalProcess(uint32_t pid, vector & known_versio return; } - // see if there's a version entry that matches this process - vector::iterator it; - for ( it=known_versions.begin() ; it < known_versions.end(); it++ ) + VersionInfo* vinfo = factory->getVersionInfoByPETimestamp(pe_header.FileHeader.TimeDateStamp); + if(vinfo) { - // filter by OS - if(OS_WINDOWS != (*it)->getOS()) - continue; - uint32_t pe_timestamp; - // filter by timestamp, skip entries without a timestamp - try - { - pe_timestamp = (*it)->getPE(); - } - catch(Error::AllMemdef&) - { - continue; - } - if (pe_timestamp != pe_header.FileHeader.TimeDateStamp) - continue; - - // all went well - { - printf("Match found! Using version %s.\n", (*it)->getVersion().c_str()); - identified = true; - // give the process a data model and memory layout fixed for the base of first module - my_descriptor = new VersionInfo(**it); - my_descriptor->RebaseAll(base); - // keep track of created memory_info object so we can destroy it later - my_descriptor->setParentProcess(this); - // process is responsible for destroying its data model - my_handle = my_handle; - identified = true; - - // TODO: detect errors in thread enumeration - vector threads; - getThreadIDs( threads ); - my_main_thread = OpenThread(THREAD_ALL_ACCESS, FALSE, (DWORD) threads[0]); - stl.init(this); - found = true; - break; // break the iterator loop - } + identified = true; + // give the process a data model and memory layout fixed for the base of first module + my_descriptor = new VersionInfo(*vinfo); + my_descriptor->RebaseAll(base); + // keep track of created memory_info object so we can destroy it later + my_descriptor->setParentProcess(this); + // process is responsible for destroying its data model + my_handle = my_handle; + + // TODO: detect errors in thread enumeration + vector threads; + getThreadIDs( threads ); + my_main_thread = OpenThread(THREAD_ALL_ACCESS, FALSE, (DWORD) threads[0]); + stl.init(this); } - // close handle of processes that aren't DF - if(!found) + else { + // close handles of processes that aren't DF CloseHandle(my_handle); } } -/* -*/ NormalProcess::~NormalProcess() { diff --git a/library/DFProcessEnumerator.cpp b/library/DFProcessEnumerator.cpp index be33d41fd..94e40450a 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 = createSHMProcess(ID.pid,meminfo->versions); + Process *p1 = createSHMProcess(ID.pid, meminfo); if(p1->isIdentified()) return p1; else delete p1; - Process *p2 = createNormalProcess(ID.pid,meminfo->versions); + Process *p2 = createNormalProcess(ID.pid, meminfo); if(p2->isIdentified()) return p2; else delete p2; #ifdef LINUX_BUILD - Process *p3 = createWineProcess(ID.pid,meminfo->versions); + Process *p3 = createWineProcess(ID.pid, meminfo); if(p3->isIdentified()) return p3; else diff --git a/library/VersionInfoFactory.cpp b/library/VersionInfoFactory.cpp index e41923f4a..72aa982be 100644 --- a/library/VersionInfoFactory.cpp +++ b/library/VersionInfoFactory.cpp @@ -90,6 +90,12 @@ inline bool operator>=(const triple<_T1, _T2, _T3>& __x, const triple<_T1, _T2, return !(__x < __y); } +VersionInfoFactory::VersionInfoFactory(string path_to_xml) +{ + error = false; + loadFile(path_to_xml); +} + VersionInfoFactory::~VersionInfoFactory() { // for each stored version, delete @@ -100,6 +106,35 @@ VersionInfoFactory::~VersionInfoFactory() versions.clear(); } +VersionInfo * VersionInfoFactory::getVersionInfoByMD5(string hash) +{ + VersionInfo * vinfo; + for(uint32_t i = 0; i < versions.size();i++) + { + vinfo = versions[i]; + if(vinfo->getMD5() == hash) + { + return vinfo; + } + } + return NULL; +} + +VersionInfo * VersionInfoFactory::getVersionInfoByPETimestamp(uint32_t timestamp) +{ + VersionInfo * vinfo; + for(uint32_t i = 0; i < versions.size();i++) + { + vinfo = versions[i]; + if(vinfo->getPE() == timestamp) + { + return vinfo; + } + } + return NULL; +} + + void VersionInfoFactory::ParseVTable(TiXmlElement* vtable, VersionInfo* mem) { TiXmlElement* pClassEntry; @@ -628,12 +663,6 @@ void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem) } // for } // method -VersionInfoFactory::VersionInfoFactory(string path_to_xml) -{ - error = false; - loadFile(path_to_xml); -} - // load the XML file with offsets bool VersionInfoFactory::loadFile(string path_to_xml) { diff --git a/library/include/dfhack/VersionInfoFactory.h b/library/include/dfhack/VersionInfoFactory.h index 7f811f588..76fe7ad21 100644 --- a/library/include/dfhack/VersionInfoFactory.h +++ b/library/include/dfhack/VersionInfoFactory.h @@ -41,6 +41,8 @@ namespace DFHack // 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 versions; private: void ParseVTable(TiXmlElement* vtable, VersionInfo* mem); diff --git a/library/include/dfhack/modules/Maps.h b/library/include/dfhack/modules/Maps.h index 110877c62..942219591 100644 --- a/library/include/dfhack/modules/Maps.h +++ b/library/include/dfhack/modules/Maps.h @@ -158,15 +158,7 @@ namespace DFHack liquid_water, liquid_magma }; - /* - enum e_liquidcharacter - { - liquid_fresh, - liquid_unk1, - liquid_salt, - liquid_unk2, - }; - */ + struct naked_designation { unsigned int flow_size : 3; // how much liquid is here? diff --git a/library/private/LinuxProcess.h b/library/private/LinuxProcess.h index cc9df1a05..e3e04cb35 100644 --- a/library/private/LinuxProcess.h +++ b/library/private/LinuxProcess.h @@ -25,8 +25,6 @@ distribution. #ifndef LINUX_PROCESS_H_INCLUDED #define LINUX_PROCESS_H_INCLUDED -#ifdef LINUX_BUILD - #include "dfhack/DFProcess.h" namespace DFHack @@ -89,8 +87,5 @@ namespace DFHack // set a SHM command and wait for a response bool SetAndWait (uint32_t state){return false;}; }; - } - -#endif #endif diff --git a/library/private/ProcessFactory.h b/library/private/ProcessFactory.h index 217dbe839..ed697d570 100644 --- a/library/private/ProcessFactory.h +++ b/library/private/ProcessFactory.h @@ -26,13 +26,14 @@ distribution. #define PROCESS_FACTORY_H_INCLUDED #include "dfhack/DFProcess.h" +#include "dfhack/VersionInfoFactory.h" namespace DFHack { - Process* createNormalProcess(uint32_t pid, std::vector & known_versions); - Process* createSHMProcess(uint32_t pid, std::vector & known_versions); + Process* createNormalProcess(uint32_t pid, VersionInfoFactory * factory); + Process* createSHMProcess(uint32_t pid, VersionInfoFactory * factory); #ifdef LINUX_BUILD - Process* createWineProcess(uint32_t pid, std::vector & known_versions); + Process* createWineProcess(uint32_t pid, VersionInfoFactory * factory); #endif } #endif diff --git a/library/private/SHMProcess.h b/library/private/SHMProcess.h index 3f8a8f75c..e10476aad 100644 --- a/library/private/SHMProcess.h +++ b/library/private/SHMProcess.h @@ -27,6 +27,7 @@ distribution. #include "dfhack/DFProcess.h" #include "dfhack/DFIntegers.h" +#include "dfhack/VersionInfoFactory.h" namespace DFHack { @@ -37,7 +38,7 @@ namespace DFHack Private * const d; public: - SHMProcess(uint32_t PID, std::vector & known_versions); + SHMProcess(uint32_t PID, VersionInfoFactory * factory); ~SHMProcess(); // Set up stuff so we can read memory bool attach(); @@ -121,7 +122,7 @@ namespace DFHack HANDLE DFCLSuspendMutex; #endif - bool validate(std::vector< VersionInfo* >& known_versions); + bool validate(VersionInfoFactory * factory); bool Aux_Core_Attach(bool & versionOK, pid_t& PID); bool SetAndWait (uint32_t state);