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 <map>
#include <fstream> #include <fstream>
#include <iostream>
using namespace std; using namespace std;
#include "integers.h" #include "integers.h"
#include <assert.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() memory_info API::getMemoryInfo()
{ {
return *d->offset_descriptor; return *d->offset_descriptor;
}
Process * API::getProcess()
{
return d->p;
} }

@ -33,6 +33,7 @@ distribution.
namespace DFHack namespace DFHack
{ {
class memory_info; class memory_info;
class Process;
enum VegetationType enum VegetationType
{ {
@ -178,6 +179,7 @@ namespace DFHack
void FinishReadNameTables(); void FinishReadNameTables();
memory_info getMemoryInfo(); memory_info getMemoryInfo();
Process * getProcess();
}; };
} // namespace DFHack } // namespace DFHack
#endif // SIMPLEAPI_H_INCLUDED #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) void memory_info::RebaseAddresses(int32_t new_base)
{ {
map<string, uint32_t>::iterator iter; 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) void memory_info::RebaseAll(int32_t new_base)
{ {
map<string, uint32_t>::iterator iter; 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 3. This notice may not be removed or altered from any source
distribution. distribution.
*/ */
#include "DFCommonInternal.h" #include "DFCommonInternal.h"
using namespace DFHack; using namespace DFHack;
@ -101,6 +100,33 @@ bool isStopped(pid_t pid)
return true; 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() bool Process::attach()
{ {
int status; int status;
@ -221,6 +247,7 @@ bool Process::detach()
} }
void Process::freeResources() void Process::freeResources()
{ {
// nil // nil
@ -271,6 +298,23 @@ bool Process::detach()
return false;*/ 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() void Process::freeResources()
{ {

@ -22,6 +22,7 @@ must not be misrepresented as being the original software.
distribution. distribution.
*/ */
//#define LINUX_BUILD
#include "DFCommonInternal.h" #include "DFCommonInternal.h"
using namespace DFHack; 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 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 int DFHack::g_ProcessMemFile; ///< opened /proc/PID/mem, valid when attached
#ifdef LINUX_BUILD #ifdef LINUX_BUILD
/* /*
* LINUX version of the process finder. * LINUX version of the process finder.

@ -25,6 +25,8 @@ distribution.
#ifndef PROCESSMANAGER_H_INCLUDED #ifndef PROCESSMANAGER_H_INCLUDED
#define PROCESSMANAGER_H_INCLUDED #define PROCESSMANAGER_H_INCLUDED
#include "Export.h"
class TiXmlElement; class TiXmlElement;
namespace DFHack namespace DFHack
@ -47,7 +49,31 @@ namespace DFHack
extern ProcessHandle g_ProcessHandle; ///< cache of handle to current process. used for speed reasons 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 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; friend class ProcessManager;
protected: protected:
@ -65,6 +91,7 @@ namespace DFHack
// Set up stuff so we can read memory // Set up stuff so we can read memory
bool attach(); bool attach();
bool detach(); bool detach();
void getMemRanges( vector<t_memrange> & ranges );
// is the process still there? // is the process still there?
memory_info *getDescriptor(); memory_info *getDescriptor();
DataModel *getDataModel(); DataModel *getDataModel();
@ -73,7 +100,7 @@ namespace DFHack
/* /*
* Process manager * Process manager
*/ */
class ProcessManager class DFHACK_EXPORT ProcessManager
{ {
public: public:
ProcessManager( string path_to_xml); ProcessManager( string path_to_xml);

@ -42,6 +42,10 @@ TARGET_LINK_LIBRARIES(dfmaterialtest dfhack)
ADD_EXECUTABLE(dfposition position.cpp) ADD_EXECUTABLE(dfposition position.cpp)
TARGET_LINK_LIBRARIES(dfposition dfhack) 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) IF(UNIX)
install(TARGETS install(TARGETS
dfexpbench dfexpbench
@ -54,6 +58,7 @@ dfattachtest
dfmaterialtest dfmaterialtest
dfbuildingsdump dfbuildingsdump
dfposition dfposition
dfincremental
RUNTIME DESTINATION bin 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;
}