add support for enumerating process memory ranges. full of fail on windows.

develop
Petr Mrázek 2009-11-15 04:25:00 +00:00
parent 37d08a05ca
commit 7e3af38941
9 changed files with 136 additions and 6 deletions

@ -30,6 +30,7 @@ distribution.
#include <map>
#include <fstream>
#include <iostream>
using namespace std;
#include "integers.h"
#include <assert.h>

@ -1170,4 +1170,8 @@ bool API::setCursorCoords (const int32_t &x, const int32_t &y, const int32_t &z)
memory_info API::getMemoryInfo()
{
return *d->offset_descriptor;
}
Process * API::getProcess()
{
return d->p;
}

@ -33,6 +33,7 @@ distribution.
namespace DFHack
{
class memory_info;
class Process;
enum VegetationType
{
@ -178,6 +179,7 @@ namespace DFHack
void FinishReadNameTables();
memory_info getMemoryInfo();
Process * getProcess();
};
} // namespace DFHack
#endif // SIMPLEAPI_H_INCLUDED

@ -340,7 +340,7 @@ void memory_info::copyBuildings(vector<string> & v_buildingtypes)
}
// change base of all addresses/vtable entries
// change base of all addresses
void memory_info::RebaseAddresses(int32_t new_base)
{
map<string, uint32_t>::iterator iter;
@ -352,7 +352,7 @@ void memory_info::RebaseAddresses(int32_t new_base)
}
// change base of all addresses/vtable entries
// change base of all addresses *and* vtable entries
void memory_info::RebaseAll(int32_t new_base)
{
map<string, uint32_t>::iterator iter;

@ -21,7 +21,6 @@ must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "DFCommonInternal.h"
using namespace DFHack;
@ -101,6 +100,33 @@ bool isStopped(pid_t pid)
return true;
}
*/
void Process::getMemRanges( vector<t_memrange> & ranges )
{
char buffer[1024];
char name[1024];
char permissions[5]; // r/-, w/-, x/-, p/s, 0
sprintf(buffer, "/proc/%lu/maps", my_pid);
FILE *mapFile = ::fopen(buffer, "r");
uint64_t begin, end, offset, device1, device2, node;
while (fgets(buffer, 1024, mapFile))
{
t_memrange temp;
sscanf(buffer, "%llx-%llx %s %llx %2llu:%2llu %llu %s",
&temp.start,
&temp.end,
(char*)&permissions,
&offset, &device1, &device2, &node,
(char*)&temp.name);
temp.read = permissions[0] == 'r';
temp.write = permissions[1] == 'w';
temp.execute = permissions[2] == 'x';
ranges.push_back(temp);
}
}
bool Process::attach()
{
int status;
@ -221,6 +247,7 @@ bool Process::detach()
}
void Process::freeResources()
{
// nil
@ -271,6 +298,23 @@ bool Process::detach()
return false;*/
}
void Process::getMemRanges( vector<t_memrange> & ranges )
{
// code here is taken from hexsearch by Silas Dunmore.
// As this IMHO isn't a 'sunstantial portion' of anything, I'm not including the MIT license here
// I'm faking this, because there's no way I'm using VirtualQuery
t_memrange temp;
uint32_t base = this->my_descriptor->getBase();
temp.start = base + 0x1000; // more fakery.
temp.end = base + MreadDWord(base+MreadDWord(base+0x3C)+0x50)-1; // yay for magic.
temp.read = 1;
temp.write = 1;
temp.execute = 0; // fake
strcpy(temp.name,"pants");// that's right. I'm calling it pants. Windows can go to HELL
ranges.push_back(temp);
}
void Process::freeResources()
{

@ -22,6 +22,7 @@ must not be misrepresented as being the original software.
distribution.
*/
//#define LINUX_BUILD
#include "DFCommonInternal.h"
using namespace DFHack;
@ -30,7 +31,6 @@ Process * DFHack::g_pProcess; ///< current process. non-NULL when picked
ProcessHandle DFHack::g_ProcessHandle; ///< cache of handle to current process. used for speed reasons
int DFHack::g_ProcessMemFile; ///< opened /proc/PID/mem, valid when attached
#ifdef LINUX_BUILD
/*
* LINUX version of the process finder.

@ -25,6 +25,8 @@ distribution.
#ifndef PROCESSMANAGER_H_INCLUDED
#define PROCESSMANAGER_H_INCLUDED
#include "Export.h"
class TiXmlElement;
namespace DFHack
@ -47,7 +49,31 @@ namespace DFHack
extern ProcessHandle g_ProcessHandle; ///< cache of handle to current process. used for speed reasons
extern int g_ProcessMemFile; ///< opened /proc/PID/mem, valid when attached
class Process
// structure describing a memory range
struct DFHACK_EXPORT t_memrange
{
uint64_t start;
uint64_t end;
// memory range name (if any)
char name[1024];
// permission to read
bool read;
// permission to write
bool write;
// permission to execute
bool execute;
inline bool isInRange( uint64_t address)
{
if (address >= start && address <= end) return true;
return false;
}
inline void print()
{
cout << hex << start << " - " << end << "|" << (read ? "r" : "-") << (write ? "w" : "-") << (execute ? "x" : "-") << "|" << name << endl;
}
};
class DFHACK_EXPORT Process
{
friend class ProcessManager;
protected:
@ -65,6 +91,7 @@ namespace DFHack
// Set up stuff so we can read memory
bool attach();
bool detach();
void getMemRanges( vector<t_memrange> & ranges );
// is the process still there?
memory_info *getDescriptor();
DataModel *getDataModel();
@ -73,7 +100,7 @@ namespace DFHack
/*
* Process manager
*/
class ProcessManager
class DFHACK_EXPORT ProcessManager
{
public:
ProcessManager( string path_to_xml);

@ -42,6 +42,10 @@ TARGET_LINK_LIBRARIES(dfmaterialtest dfhack)
ADD_EXECUTABLE(dfposition position.cpp)
TARGET_LINK_LIBRARIES(dfposition dfhack)
# materialtest - just list the first material of each type
ADD_EXECUTABLE(dfincremental incrementalsearch.cpp)
TARGET_LINK_LIBRARIES(dfincremental dfhack)
IF(UNIX)
install(TARGETS
dfexpbench
@ -54,6 +58,7 @@ dfattachtest
dfmaterialtest
dfbuildingsdump
dfposition
dfincremental
RUNTIME DESTINATION bin
)

@ -0,0 +1,47 @@
// this will be an incremental search tool in the future. now it is just a memory region dump thing
#include <iostream>
#include <climits>
#include <integers.h>
#include <vector>
#include <map>
#include <ctime>
using namespace std;
#ifndef LINUX_BUILD
#define WINVER 0x0500
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include <DFTypes.h>
#include <DFHackAPI.h>
#include <DFProcessManager.h>
int main (void)
{
DFHack::API DF("Memory.xml");
if(!DF.Attach())
{
cerr << "DF not found" << endl;
return 1;
}
DFHack::Process * p = DF.getProcess();
vector <DFHack::t_memrange> ranges;
p->getMemRanges(ranges);
for(int i = 0; i< ranges.size();i++)
{
ranges[i].print();
}
if(!DF.Detach())
{
cerr << "Can't detach from DF" << endl;
return 1;
}
#ifndef LINUX_BUILD
cout << "Done. Press any key to continue" << endl;
cin.ignore();
#endif
return 0;
}