diff --git a/library/DFCommonInternal.h b/library/DFCommonInternal.h index a2fe35ad8..0477e2465 100644 --- a/library/DFCommonInternal.h +++ b/library/DFCommonInternal.h @@ -30,6 +30,7 @@ distribution. #include #include +#include using namespace std; #include "integers.h" #include diff --git a/library/DFHackAPI.cpp b/library/DFHackAPI.cpp index 155f35801..c4ae4da67 100644 --- a/library/DFHackAPI.cpp +++ b/library/DFHackAPI.cpp @@ -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; } \ No newline at end of file diff --git a/library/DFHackAPI.h b/library/DFHackAPI.h index e0b964b4a..5f76d5066 100644 --- a/library/DFHackAPI.h +++ b/library/DFHackAPI.h @@ -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 diff --git a/library/DFMemInfo.cpp b/library/DFMemInfo.cpp index 74d75baed..e48c14a1b 100644 --- a/library/DFMemInfo.cpp +++ b/library/DFMemInfo.cpp @@ -340,7 +340,7 @@ void memory_info::copyBuildings(vector & v_buildingtypes) } -// change base of all addresses/vtable entries +// change base of all addresses void memory_info::RebaseAddresses(int32_t new_base) { map::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::iterator iter; diff --git a/library/DFProcess.cpp b/library/DFProcess.cpp index 1c9e66106..7a8e9c187 100644 --- a/library/DFProcess.cpp +++ b/library/DFProcess.cpp @@ -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 & 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 & 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() { diff --git a/library/DFProcessManager.cpp b/library/DFProcessManager.cpp index d4a4c9155..73ca19058 100644 --- a/library/DFProcessManager.cpp +++ b/library/DFProcessManager.cpp @@ -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. diff --git a/library/DFProcessManager.h b/library/DFProcessManager.h index d5ef36326..b8ff9fd7b 100644 --- a/library/DFProcessManager.h +++ b/library/DFProcessManager.h @@ -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 & 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); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 9b1914a93..360ef25e7 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -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 ) diff --git a/tools/incrementalsearch.cpp b/tools/incrementalsearch.cpp new file mode 100644 index 000000000..3c226a1ce --- /dev/null +++ b/tools/incrementalsearch.cpp @@ -0,0 +1,47 @@ +// this will be an incremental search tool in the future. now it is just a memory region dump thing + +#include +#include +#include +#include +#include +#include +using namespace std; + +#ifndef LINUX_BUILD + #define WINVER 0x0500 + #define WIN32_LEAN_AND_MEAN + #include +#endif + +#include +#include +#include + +int main (void) +{ + DFHack::API DF("Memory.xml"); + if(!DF.Attach()) + { + cerr << "DF not found" << endl; + return 1; + } + DFHack::Process * p = DF.getProcess(); + vector 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; +} \ No newline at end of file