More cleanup in the Process lands.

develop
Petr Mrázek 2011-02-24 11:43:33 +01:00
parent 79b78673e5
commit 97bfa32a82
13 changed files with 124 additions and 210 deletions

@ -31,12 +31,12 @@ distribution.
using namespace DFHack;
Process* DFHack::createSHMProcess(uint32_t pid, vector <VersionInfo *> & 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 <VersionInfo *> & 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 <VersionInfo *> & 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();
}

@ -216,7 +216,7 @@ bool SHMProcess::Private::AreLocksOk()
}
bool SHMProcess::Private::validate(vector <VersionInfo *> & 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 <VersionInfo *> & 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<VersionInfo *>::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;
}

@ -38,24 +38,22 @@ namespace {
private:
MicrosoftSTL stl;
public:
WineProcess(uint32_t pid, std::vector <VersionInfo *> & 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 <VersionInfo *> & known_versions);
};
}
Process* DFHack::createWineProcess(uint32_t pid, vector <VersionInfo *> & 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 <VersionInfo *> & 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 <VersionInfo *> & 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 <VersionInfo *> & 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 <VersionInfo *> & known_versions)
{
md5wrapper md5;
// get hash of the running DF process
string hash = md5.getHashFromFile(exe_file);
vector<VersionInfo *>::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);
}

@ -34,24 +34,22 @@ namespace {
class NormalProcess : public LinuxProcessBase
{
public:
NormalProcess(uint32_t pid, std::vector <VersionInfo *> & 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 <VersionInfo *> & known_versions);
};
}
Process* DFHack::createNormalProcess(uint32_t pid, vector <VersionInfo *> & known_versions)
Process* DFHack::createNormalProcess(uint32_t pid, VersionInfoFactory * known_versions)
{
return new NormalProcess(pid, known_versions);
}
NormalProcess::NormalProcess(uint32_t pid, vector <VersionInfo *> & 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 <VersionInfo *> & 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 <VersionInfo *> & 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 <VersionInfo *> & known_versions)
{
md5wrapper md5;
// get hash of the running DF process
string hash = md5.getHashFromFile(exe_file);
vector<VersionInfo *>::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

@ -216,7 +216,7 @@ bool SHMProcess::Private::AreLocksOk()
return false;
}
bool SHMProcess::Private::validate(vector <VersionInfo *> & 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 <VersionInfo *> & 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 *)&sections );
// iterate over the list of memory locations
vector<VersionInfo *>::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;
}

@ -47,7 +47,7 @@ namespace
uint32_t base;
MicrosoftSTL stl;
public:
NormalProcess(uint32_t pid, std::vector <VersionInfo *> & 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 <VersionInfo *> & 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 <VersionInfo *> & 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 <VersionInfo *> & known_versio
return;
}
// see if there's a version entry that matches this process
vector<VersionInfo*>::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<uint32_t> 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<uint32_t> 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()
{

@ -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

@ -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)
{

@ -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<VersionInfo*> versions;
private:
void ParseVTable(TiXmlElement* vtable, VersionInfo* mem);

@ -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?

@ -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

@ -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 <VersionInfo *> & known_versions);
Process* createSHMProcess(uint32_t pid, std::vector <VersionInfo *> & 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 <VersionInfo *> & known_versions);
Process* createWineProcess(uint32_t pid, VersionInfoFactory * factory);
#endif
}
#endif

@ -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 <VersionInfo *> & 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);