@ -23,31 +23,95 @@ distribution.
*/
# include "DFCommonInternal.h"
/*
# if !defined(NDEBUG)
# define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
# define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
# endif
# include <boost/multi_index_container.hpp>
# include <boost/multi_index/member.hpp>
# include <boost/multi_index/ordered_index.hpp>
# include <algorithm>
# include <iostream>
# include <iterator>
# include <string>
using boost : : multi_index_container ;
using namespace boost : : multi_index ;
*/
using namespace DFHack ;
/*
* Common data types
*/
struct t_class
{
string classname ;
uint32_t vtable ;
bool is_multiclass ;
uint32_t multi_index ;
uint32_t assign ; // index to typeclass array if multiclass. return value if not.
uint32_t type_offset ; // offset of type data for multiclass
} ;
struct t_type
{
string classname ;
uint32_t assign ;
uint32_t type ;
} ;
/*
* Private data
*/
class memory_info : : Private
{
public :
map < string , uint32_t > addresses ;
map < string , uint32_t > offsets ;
map < string , uint32_t > hexvals ;
map < string , string > strings ;
vector < string > professions ;
vector < string > jobs ;
vector < string > skills ;
vector < vector < string > > traits ;
map < uint32_t , string > labors ;
vector < t_class > classes ;
vector < vector < t_type > > classsubtypes ;
int32_t base ;
uint32_t classindex ;
string version ;
OSType OS ;
} ;
memory_info : : memory_info ( )
: d ( new Private )
{
base = 0 ;
classindex = 0 ;
d- > base = 0 ;
d- > classindex = 0 ;
}
void memory_info : : setVersion ( const char * v )
{
version = v ;
d- > version = v ;
}
void memory_info : : setVersion ( const string & v )
{
version = v ;
d- > version = v ;
}
string memory_info : : getVersion ( )
{
return version ;
return d- > version;
}
@ -55,22 +119,22 @@ void memory_info::setOS(const char *os)
{
string oss = os ;
if ( oss = = " windows " )
OS = OS_WINDOWS ;
d- > OS = OS_WINDOWS ;
else if ( oss = = " linux " )
OS = OS_LINUX ;
d- > OS = OS_LINUX ;
else
OS = OS_BAD ;
d- > OS = OS_BAD ;
}
void memory_info : : setOS ( const string & os )
{
if ( os = = " windows " )
OS = OS_WINDOWS ;
d- > OS = OS_WINDOWS ;
else if ( os = = " linux " )
OS = OS_LINUX ;
d- > OS = OS_LINUX ;
else
OS = OS_BAD ;
d- > OS = OS_BAD ;
}
@ -78,117 +142,118 @@ void memory_info::setOS(OSType os)
{
if ( os > = OS_WINDOWS & & os < OS_BAD )
{
OS = os ;
d- > OS = os ;
return ;
}
OS = OS_BAD ;
d- > OS = OS_BAD ;
}
memory_info : : OSType memory_info : : getOS ( ) const
{
return OS;
return d- > OS;
}
// copy constructor
memory_info : : memory_info ( const memory_info & old )
{
version = old . version ;
OS = old . OS ;
addresses = old . addresses ;
offsets = old . offsets ;
hexvals = old . hexvals ;
strings = old . strings ;
base = old . base ;
classes = old . classes ;
classsubtypes = old . classsubtypes ;
classindex = old . classindex ;
professions = old . professions ;
jobs = old . jobs ;
skills = old . skills ;
traits = old . traits ;
labors = old . labors ;
: 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 ;
d - > classes = old . d - > classes ;
d - > classsubtypes = old . d - > classsubtypes ;
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 ;
}
uint32_t memory_info : : getBase ( ) const
{
return base;
return d- > base;
}
void memory_info : : setBase ( const string & s )
{
base = strtol ( s . c_str ( ) , NULL , 16 ) ;
d- > base = strtol ( s . c_str ( ) , NULL , 16 ) ;
}
void memory_info : : setBase ( const uint32_t b )
{
base = b ;
d- > base = b ;
}
void memory_info : : setOffset ( const string & key , const string & value )
{
uint32_t offset = strtol ( value . c_str ( ) , NULL , 16 ) ;
offsets[ key ] = offset ;
d- > offsets[ key ] = offset ;
}
void memory_info : : setAddress ( const string & key , const string & value )
{
uint32_t address = strtol ( value . c_str ( ) , NULL , 16 ) ;
addresses[ key ] = address ;
d- > addresses[ key ] = address ;
}
void memory_info : : setHexValue ( const string & key , const string & value )
{
uint32_t hexval = strtol ( value . c_str ( ) , NULL , 16 ) ;
hexvals[ key ] = hexval ;
d- > hexvals[ key ] = hexval ;
}
void memory_info : : setString ( const string & key , const string & value )
{
strings[ key ] = value ;
d- > strings[ key ] = value ;
}
void memory_info : : setLabor ( const string & key , const string & value )
{
uint32_t keyInt = strtol ( key . c_str ( ) , NULL , 10 ) ;
labors[ keyInt ] = value ;
d- > labors[ keyInt ] = value ;
}
void memory_info : : setProfession ( const string & key , const string & value )
{
uint32_t keyInt = strtol ( key . c_str ( ) , NULL , 10 ) ;
if ( professions. size ( ) < = keyInt )
if ( d- > professions. size ( ) < = keyInt )
{
professions. resize ( keyInt + 1 ) ;
d- > professions. resize ( keyInt + 1 ) ;
}
professions[ keyInt ] = value ;
d- > professions[ keyInt ] = value ;
}
void memory_info : : setJob ( const string & key , const string & value )
{
uint32_t keyInt = strtol ( key . c_str ( ) , NULL , 10 ) ;
if ( jobs. size ( ) < = keyInt )
if ( d- > jobs. size ( ) < = keyInt )
{
jobs. resize ( keyInt + 1 ) ;
d- > jobs. resize ( keyInt + 1 ) ;
}
jobs[ keyInt ] = value ;
d- > jobs[ keyInt ] = value ;
}
void memory_info : : setSkill ( const string & key , const string & value )
{
uint32_t keyInt = strtol ( key . c_str ( ) , NULL , 10 ) ;
if ( skills. size ( ) < = keyInt ) {
skills. resize ( keyInt + 1 ) ;
if ( d- > skills. size ( ) < = keyInt ) {
d- > skills. resize ( keyInt + 1 ) ;
}
skills[ keyInt ] = value ;
d- > skills[ keyInt ] = value ;
}
void memory_info : : setTrait ( const string & key ,
@ -201,39 +266,39 @@ void memory_info::setTrait(const string & key,
const string & five )
{
uint32_t keyInt = strtol ( key . c_str ( ) , NULL , 10 ) ;
if ( traits. size ( ) < = keyInt )
if ( d- > traits. size ( ) < = keyInt )
{
traits. resize ( keyInt + 1 ) ;
d- > traits. resize ( keyInt + 1 ) ;
}
traits[ keyInt ] . push_back ( zero ) ;
traits[ keyInt ] . push_back ( one ) ;
traits[ keyInt ] . push_back ( two ) ;
traits[ keyInt ] . push_back ( three ) ;
traits[ keyInt ] . push_back ( four ) ;
traits[ keyInt ] . push_back ( five ) ;
traits[ keyInt ] . push_back ( value ) ;
d- > traits[ keyInt ] . push_back ( zero ) ;
d- > traits[ keyInt ] . push_back ( one ) ;
d- > traits[ keyInt ] . push_back ( two ) ;
d- > traits[ keyInt ] . push_back ( three ) ;
d- > traits[ keyInt ] . push_back ( four ) ;
d- > traits[ keyInt ] . push_back ( five ) ;
d- > traits[ keyInt ] . push_back ( value ) ;
}
// FIXME: next three methods should use some kind of custom container so it doesn't have to search so much.
void memory_info : : setClass ( const char * name , const char * vtable )
{
for ( uint32_t i = 0 ; i < classes. size ( ) ; i + + )
for ( uint32_t i = 0 ; i < d- > classes. size ( ) ; i + + )
{
if ( classes[ i ] . classname = = name )
if ( d- > classes[ i ] . classname = = name )
{
classes[ i ] . vtable = strtol ( vtable , NULL , 16 ) ;
d- > classes[ i ] . vtable = strtol ( vtable , NULL , 16 ) ;
return ;
}
}
t_class cls ;
cls . assign = classindex;
cls . assign = d- > classindex;
cls . classname = name ;
cls . is_multiclass = false ;
cls . type_offset = 0 ;
classindex+ + ;
d- > classindex+ + ;
cls . vtable = strtol ( vtable , NULL , 16 ) ;
classes. push_back ( cls ) ;
d- > classes. push_back ( cls ) ;
//cout << "class " << name << ", assign " << cls.assign << ", vtable " << cls.vtable << endl;
}
@ -241,40 +306,40 @@ void memory_info::setClass (const char * name, const char * vtable)
// find old entry by name, rewrite, return its multi index. otherwise make a new one, append an empty vector of t_type to classtypes, return its index.
uint32_t memory_info : : setMultiClass ( const char * name , const char * vtable , const char * typeoffset )
{
for ( uint32_t i = 0 ; i < classes. size ( ) ; i + + )
for ( uint32_t i = 0 ; i < d- > classes. size ( ) ; i + + )
{
if ( classes[ i ] . classname = = name )
if ( d- > classes[ i ] . classname = = name )
{
// vtable and typeoffset can be left out from the xml definition when there's already a named multiclass
if ( vtable ! = NULL )
classes[ i ] . vtable = strtol ( vtable , NULL , 16 ) ;
d- > classes[ i ] . vtable = strtol ( vtable , NULL , 16 ) ;
if ( typeoffset ! = NULL )
classes[ i ] . type_offset = strtol ( typeoffset , NULL , 16 ) ;
return classes[ i ] . multi_index ;
d- > classes[ i ] . type_offset = strtol ( typeoffset , NULL , 16 ) ;
return d- > classes[ i ] . multi_index ;
}
}
//FIXME: add checking for vtable and typeoffset here. they HAVE to be valid. maybe change the return value into a bool and pass in multi index by reference?
t_class cls ;
cls . assign = classindex;
cls . assign = d- > classindex;
cls . classname = name ;
cls . is_multiclass = true ;
cls . type_offset = strtol ( typeoffset , NULL , 16 ) ;
cls . vtable = strtol ( vtable , NULL , 16 ) ;
cls . multi_index = classsubtypes. size ( ) ;
classes. push_back ( cls ) ;
classindex+ + ;
cls . multi_index = d- > classsubtypes. size ( ) ;
d- > classes. push_back ( cls ) ;
d- > classindex+ + ;
vector < t_type > thistypes ;
classsubtypes. push_back ( thistypes ) ;
d- > classsubtypes. push_back ( thistypes ) ;
//cout << "multiclass " << name << ", assign " << cls.assign << ", vtable " << cls.vtable << endl;
return classsubtypes. size ( ) - 1 ;
return d- > classsubtypes. size ( ) - 1 ;
}
void memory_info : : setMultiClassChild ( uint32_t multi_index , const char * name , const char * type )
{
vector < t_type > & vec = classsubtypes[ multi_index ] ;
vector < t_type > & vec = d- > classsubtypes[ multi_index ] ;
for ( uint32_t i = 0 ; i < vec . size ( ) ; i + + )
{
if ( vec [ i ] . classname = = name )
@ -285,11 +350,11 @@ void memory_info::setMultiClassChild (uint32_t multi_index, const char * name, c
}
// new multiclass child
t_type mcc ;
mcc . assign = classindex;
mcc . assign = d- > classindex;
mcc . classname = name ;
mcc . type = strtol ( type , NULL , 16 ) ;
vec . push_back ( mcc ) ;
classindex+ + ;
d- > classindex+ + ;
//cout << " classtype " << name << ", assign " << mcc.assign << ", vtable " << mcc.type << endl;
}
@ -298,15 +363,15 @@ bool memory_info::resolveClassId(uint32_t address, int32_t & classid)
{
uint32_t vtable = g_pProcess - > readDWord ( address ) ;
// FIXME: stupid search. we need a better container
for ( uint32_t i = 0 ; i < classes. size ( ) ; i + + )
for ( uint32_t i = 0 ; i < d- > classes. size ( ) ; i + + )
{
if ( classes[ i ] . vtable = = vtable ) // got class
if ( d- > classes[ i ] . vtable = = vtable ) // got class
{
// if it is a multiclass, try resolving it
if ( classes[ i ] . is_multiclass )
if ( d- > classes[ i ] . is_multiclass )
{
vector < t_type > & vec = classsubtypes[ classes [ i ] . multi_index ] ;
uint32_t type = g_pProcess - > readWord ( address + classes[ i ] . type_offset ) ;
vector < t_type > & vec = d- > classsubtypes[ d - > classes [ i ] . multi_index ] ;
uint32_t type = g_pProcess - > readWord ( address + d- > classes[ i ] . type_offset ) ;
//printf ("class %d:%s offset 0x%x\n", i , classes[i].classname.c_str(), classes[i].type_offset);
// return typed building if successful
for ( uint32_t k = 0 ; k < vec . size ( ) ; k + + )
@ -320,7 +385,7 @@ bool memory_info::resolveClassId(uint32_t address, int32_t & classid)
}
}
// otherwise return the class we found
classid = classes[ i ] . assign ;
classid = d- > classes[ i ] . assign ;
return true ;
}
}
@ -332,12 +397,12 @@ bool memory_info::resolveClassId(uint32_t address, int32_t & classid)
uint32_t memory_info : : getClassVPtr ( string classname )
{
// FIXME: another stupid search.
for ( uint32_t i = 0 ; i < classes. size ( ) ; i + + )
for ( uint32_t i = 0 ; i < d- > classes. size ( ) ; i + + )
{
//if(classes[i].)
if ( classes[ i ] . classname = = classname ) // got class
if ( d- > classes[ i ] . classname = = classname ) // got class
{
return classes[ i ] . vtable ;
return d- > classes[ i ] . vtable ;
}
}
// we failed to find anything that would match
@ -347,14 +412,14 @@ uint32_t memory_info::getClassVPtr(string classname)
// Flatten vtables into a index<->name mapping
void memory_info : : getClassIDMapping ( vector < string > & v_ClassID2ObjName )
{
for ( uint32_t i = 0 ; i < classes. size ( ) ; i + + )
for ( uint32_t i = 0 ; i < d- > classes. size ( ) ; i + + )
{
v_ClassID2ObjName . push_back ( classes[ i ] . classname ) ;
if ( ! classes[ i ] . is_multiclass )
v_ClassID2ObjName . push_back ( d- > classes[ i ] . classname ) ;
if ( ! d- > classes[ i ] . is_multiclass )
{
continue ;
}
vector < t_type > & vec = classsubtypes[ classes [ i ] . multi_index ] ;
vector < t_type > & vec = d- > classsubtypes[ d - > classes [ i ] . multi_index ] ;
for ( uint32_t k = 0 ; k < vec . size ( ) ; k + + )
{
v_ClassID2ObjName . push_back ( vec [ k ] . classname ) ;
@ -367,10 +432,10 @@ void memory_info::getClassIDMapping(vector<string> & v_ClassID2ObjName)
void memory_info : : RebaseAddresses ( const int32_t new_base )
{
map < string , uint32_t > : : iterator iter ;
int32_t rebase = - ( int32_t ) base + new_base ;
for ( iter = addresses. begin ( ) ; iter ! = addresses . end ( ) ; iter + + )
int32_t rebase = - ( int32_t ) d- > base + new_base ;
for ( iter = d- > addresses. begin ( ) ; iter ! = d - > addresses . end ( ) ; iter + + )
{
addresses[ iter - > first ] = iter - > second + rebase ;
d- > addresses[ iter - > first ] = iter - > second + rebase ;
}
}
@ -379,10 +444,10 @@ void memory_info::RebaseAddresses(const int32_t new_base)
void memory_info : : RebaseAll ( int32_t new_base )
{
map < string , uint32_t > : : iterator iter ;
int32_t rebase = - ( int32_t ) base + new_base ;
for ( iter = addresses. begin ( ) ; iter ! = addresses . end ( ) ; iter + + )
int32_t rebase = - ( int32_t ) d- > base + new_base ;
for ( iter = d- > addresses. begin ( ) ; iter ! = d - > addresses . end ( ) ; iter + + )
{
addresses[ iter - > first ] = iter - > second + rebase ;
d- > addresses[ iter - > first ] = iter - > second + rebase ;
}
RebaseVTable ( rebase ) ;
}
@ -392,7 +457,7 @@ void memory_info::RebaseAll(int32_t new_base)
void memory_info : : RebaseVTable ( int32_t offset )
{
vector < t_class > : : iterator iter ;
for ( iter = classes. begin ( ) ; iter ! = classes . end ( ) ; iter + + )
for ( iter = d- > classes. begin ( ) ; iter ! = d - > classes . end ( ) ; iter + + )
{
iter - > vtable + = offset ;
}
@ -401,9 +466,9 @@ void memory_info::RebaseVTable(int32_t offset)
// Get named address
uint32_t memory_info : : getAddress ( const char * key )
{
map < string , uint32_t > : : iterator iter = addresses. find ( key ) ;
map < string , uint32_t > : : iterator iter = d- > addresses. find ( key ) ;
if ( iter ! = addresses. end ( ) )
if ( iter ! = d- > addresses. end ( ) )
{
return ( * iter ) . second ;
}
@ -414,8 +479,8 @@ uint32_t memory_info::getAddress (const char *key)
// Get named offset
uint32_t memory_info : : getOffset ( const char * key )
{
map < string , uint32_t > : : iterator iter = offsets. find ( key ) ;
if ( iter ! = offsets. end ( ) )
map < string , uint32_t > : : iterator iter = d- > offsets. find ( key ) ;
if ( iter ! = d- > offsets. end ( ) )
{
return ( * iter ) . second ;
}
@ -425,8 +490,8 @@ uint32_t memory_info::getOffset (const char *key)
// Get named numerical value
uint32_t memory_info : : getHexValue ( const char * key )
{
map < string , uint32_t > : : iterator iter = hexvals. find ( key ) ;
if ( iter ! = hexvals. end ( ) )
map < string , uint32_t > : : iterator iter = d- > hexvals. find ( key ) ;
if ( iter ! = d- > hexvals. end ( ) )
{
return ( * iter ) . second ;
}
@ -437,9 +502,9 @@ uint32_t memory_info::getHexValue (const char *key)
// Get named address
uint32_t memory_info : : getAddress ( const string & key )
{
map < string , uint32_t > : : iterator iter = addresses. find ( key ) ;
map < string , uint32_t > : : iterator iter = d- > addresses. find ( key ) ;
if ( iter ! = addresses. end ( ) )
if ( iter ! = d- > addresses. end ( ) )
{
return ( * iter ) . second ;
}
@ -450,8 +515,8 @@ uint32_t memory_info::getAddress (const string &key)
// Get named offset
uint32_t memory_info : : getOffset ( const string & key )
{
map < string , uint32_t > : : iterator iter = offsets. find ( key ) ;
if ( iter ! = offsets. end ( ) )
map < string , uint32_t > : : iterator iter = d- > offsets. find ( key ) ;
if ( iter ! = d- > offsets. end ( ) )
{
return ( * iter ) . second ;
}
@ -461,8 +526,8 @@ uint32_t memory_info::getOffset (const string &key)
// Get named numerical value
uint32_t memory_info : : getHexValue ( const string & key )
{
map < string , uint32_t > : : iterator iter = hexvals. find ( key ) ;
if ( iter ! = hexvals. end ( ) )
map < string , uint32_t > : : iterator iter = d- > hexvals. find ( key ) ;
if ( iter ! = d- > hexvals. end ( ) )
{
return ( * iter ) . second ;
}
@ -472,8 +537,8 @@ uint32_t memory_info::getHexValue (const string &key)
// Get named string
std : : string memory_info : : getString ( const string & key )
{
map < string , string > : : iterator iter = strings. find ( key ) ;
if ( iter ! = strings. end ( ) )
map < string , string > : : iterator iter = d- > strings. find ( key ) ;
if ( iter ! = d- > strings. end ( ) )
{
return ( * iter ) . second ;
}
@ -483,9 +548,9 @@ std::string memory_info::getString (const string &key)
// Get Profession
string memory_info : : getProfession ( const uint32_t key ) const
{
if ( professions. size ( ) > key )
if ( d- > professions. size ( ) > key )
{
return professions[ key ] ;
return d- > professions[ key ] ;
}
else
{
@ -496,18 +561,18 @@ string memory_info::getProfession (const uint32_t key) const
// Get Job
string memory_info : : getJob ( const uint32_t key ) const
{
if ( jobs. size ( ) > key )
if ( d- > jobs. size ( ) > key )
{
return jobs[ key ] ;
return d- > jobs[ key ] ;
}
return string ( " Job Does Not Exist " ) ;
}
string memory_info : : getSkill ( const uint32_t key ) const
{
if ( skills. size ( ) > key )
if ( d- > skills. size ( ) > key )
{
return skills[ key ] ;
return d- > skills[ key ] ;
}
return string ( " Skill is not Defined " ) ;
}
@ -522,7 +587,7 @@ int absolute (int number)
string memory_info : : getTrait ( const uint32_t traitIdx , const uint32_t traitValue ) const
{
if ( traits. size ( ) > traitIdx )
if ( d- > traits. size ( ) > traitIdx )
{
int diff = absolute ( traitValue - 50 ) ;
if ( diff < 10 )
@ -530,35 +595,35 @@ string memory_info::getTrait (const uint32_t traitIdx, const uint32_t traitValue
return string ( " " ) ;
}
if ( traitValue > = 91 )
return traits[ traitIdx ] [ 5 ] ;
return d- > traits[ traitIdx ] [ 5 ] ;
else if ( traitValue > = 76 )
return traits[ traitIdx ] [ 4 ] ;
return d- > traits[ traitIdx ] [ 4 ] ;
else if ( traitValue > = 61 )
return traits[ traitIdx ] [ 3 ] ;
return d- > traits[ traitIdx ] [ 3 ] ;
else if ( traitValue > = 25 )
return traits[ traitIdx ] [ 2 ] ;
return d- > traits[ traitIdx ] [ 2 ] ;
else if ( traitValue > = 10 )
return traits[ traitIdx ] [ 1 ] ;
return d- > traits[ traitIdx ] [ 1 ] ;
else
return traits[ traitIdx ] [ 0 ] ;
return d- > traits[ traitIdx ] [ 0 ] ;
}
return string ( " Trait is not Defined " ) ;
}
string memory_info : : getTraitName ( const uint32_t traitIdx ) const
{
if ( traits. size ( ) > traitIdx )
if ( d- > traits. size ( ) > traitIdx )
{
return traits[ traitIdx ] [ traits [ traitIdx ] . size ( ) - 1 ] ;
return d- > traits[ traitIdx ] [ d - > traits [ traitIdx ] . size ( ) - 1 ] ;
}
return string ( " Trait is not Defined " ) ;
}
string memory_info : : getLabor ( const uint32_t laborIdx )
{
if ( labors. count ( laborIdx ) )
if ( d- > labors. count ( laborIdx ) )
{
return labors[ laborIdx ] ;
return d- > labors[ laborIdx ] ;
}
return string ( " " ) ;
}
@ -566,14 +631,14 @@ string memory_info::getLabor (const uint32_t laborIdx)
// Reset everything
void memory_info : : flush ( )
{
base = 0 ;
addresses. clear ( ) ;
offsets. clear ( ) ;
strings. clear ( ) ;
hexvals. clear ( ) ;
classes. clear ( ) ;
classsubtypes. clear ( ) ;
classindex = 0 ;
version = " " ;
OS = OS_BAD ;
d- > base = 0 ;
d- > addresses. clear ( ) ;
d- > offsets. clear ( ) ;
d- > strings. clear ( ) ;
d- > hexvals. clear ( ) ;
d- > classes. clear ( ) ;
d- > classsubtypes. clear ( ) ;
d- > classindex = 0 ;
d- > version = " " ;
d- > OS = OS_BAD ;
}