From 49fd378a47184c99fdadf6f317e66cc780df36d0 Mon Sep 17 00:00:00 2001 From: Matthew Cline Date: Sun, 10 Jul 2011 02:16:28 -0700 Subject: [PATCH] incremental: deal with shifting Linux maps Issues #88: sometimes the end of the heap of the DF process will change between detaching and re-attaching to the process. To deal with this, /proc/PID/maps is re-read every time the process is attached. Also, made semgent finder give a little more info if there's an error doing a memory read. --- tools/supported/SegmentedFinder.h | 8 +- tools/supported/incrementalsearch.cpp | 129 ++++++++++++++++++++------ 2 files changed, 109 insertions(+), 28 deletions(-) diff --git a/tools/supported/SegmentedFinder.h b/tools/supported/SegmentedFinder.h index 052cab258..b3fe5aecf 100644 --- a/tools/supported/SegmentedFinder.h +++ b/tools/supported/SegmentedFinder.h @@ -27,7 +27,13 @@ class SegmentFinder free(mr_.buffer); valid = false; mr.valid = false; // mark the range passed in as bad - cout << "Range 0x" << hex << mr_.start << " - 0x" << mr_.end << dec << " not readable." << endl; + cout << "Range 0x" << hex << mr_.start << " - 0x" << mr_.end; + + if (strlen(mr_.name) != 0) + cout << " (" << mr_.name << ")"; + + cout << dec << " not readable." << endl; + cout << "Skipping this range on future scans." << endl; } } } diff --git a/tools/supported/incrementalsearch.cpp b/tools/supported/incrementalsearch.cpp index fc1568557..e70e09527 100644 --- a/tools/supported/incrementalsearch.cpp +++ b/tools/supported/incrementalsearch.cpp @@ -27,9 +27,17 @@ inline void printRange(DFHack::t_memrange * tpr) std::cout << std::hex << tpr->start << " - " << tpr->end << "|" << (tpr->read ? "r" : "-") << (tpr->write ? "w" : "-") << (tpr->execute ? "x" : "-") << "|" << tpr->name << std::endl; } -bool getRanges(DFHack::Process * p, vector & selected_ranges) +/* + * Since the start and/or end of a memory range can change each time we + * detach and re-attach to the DF process, we save the indexes of the + * memory ranges we want to look at, and re-read the ranges each time + * we re-attach. Hopefully we won't encounter any circumstances where + * entire new ranges are added or removed... + */ +bool getRanges(DFHack::Process * p, vector & selected_ranges) { vector ranges; + ranges.clear(); selected_ranges.clear(); p->getMemRanges(ranges); cout << "Which range to search? (default is 1-4)" << endl; @@ -46,8 +54,9 @@ bool getRanges(DFHack::Process * p, vector & selected_ranges std::getline(cin, select); if(select.empty()) { - // empty input, assume default. observe the length of the memory range vector - // these are hardcoded values, intended for my convenience only + // empty input, assume default. observe the length of the memory + // range vector these are hardcoded values, intended for my + // convenience only if(p->getDescriptor()->getOS() == DFHack::OS_WINDOWS) { start = min(11, (int)ranges.size()); @@ -78,20 +87,18 @@ bool getRanges(DFHack::Process * p, vector & selected_ranges } break; } - end++; cout << "selected ranges:" <::iterator it; - it = ranges.begin() + start; - while (it != ranges.begin() + end) + + for (int i = start; i <= end; i++) { // check if readable - if((*it).read) + if (ranges[i].read) { - selected_ranges.push_back(*it); - printRange(&*it); + selected_ranges.push_back(i); + printRange(&(ranges[i])); } - it++; } + return true; } @@ -139,6 +146,32 @@ bool getString (string prompt, string & output) } } +bool readRanges(DFHack::Context * DF, vector & selected_ranges, + vector & ranges) +{ + DFHack::Process * p = DF->getProcess(); + + vector new_ranges; + new_ranges.clear(); + p->getMemRanges(new_ranges); + + for (size_t i = 0; i < selected_ranges.size(); i++) + { + int idx = selected_ranges[i]; + + if (ranges.size() == i) + // First time ranges vector has been filled in. + ranges.push_back(new_ranges[idx]); + // If something was wrong with the range on one memory read, + // don't read it again. + else if(ranges[i].valid) + ranges[i] = new_ranges[idx]; + } + + return true; +} + + template bool Incremental ( vector &found, const char * what, T& output, const char *singular = "address", const char *plural = "addresses", bool numberz = false ) @@ -215,8 +248,11 @@ bool Incremental ( vector &found, const char * what, T& output, } } -void FindIntegers(DFHack::ContextManager & DFMgr, vector & ranges) +void FindIntegers(DFHack::ContextManager & DFMgr, + vector & selected_ranges) { + vector ranges; + // input / validation of variable size int size; do @@ -238,6 +274,7 @@ void FindIntegers(DFHack::ContextManager & DFMgr, vector & r DFMgr.Refresh(); DFHack::Context * DF = DFMgr.getSingleContext(); DF->Attach(); + readRanges(DF, selected_ranges, ranges); SegmentedFinder sf(ranges,DF); switch(size) { @@ -255,8 +292,11 @@ void FindIntegers(DFHack::ContextManager & DFMgr, vector & r } } -void FindVectorByLength(DFHack::ContextManager & DFMgr, vector & ranges ) +void FindVectorByLength(DFHack::ContextManager & DFMgr, + vector & selected_ranges ) { + vector ranges; + int element_size; do { @@ -271,6 +311,7 @@ void FindVectorByLength(DFHack::ContextManager & DFMgr, vector Attach(); + readRanges(DF, selected_ranges, ranges); SegmentedFinder sf(ranges,DF); //sf.Incremental(0,4,found,vectorAll); //sf.Filter(length * element_size,found,vectorLength); @@ -279,15 +320,19 @@ void FindVectorByLength(DFHack::ContextManager & DFMgr, vector & ranges) +void FindVectorByObjectRawname(DFHack::ContextManager & DFMgr, + vector & selected_ranges) { + vector ranges; vector found; string select; + while (Incremental(found, "raw name",select,"vector","vectors")) { DFMgr.Refresh(); DFHack::Context * DF = DFMgr.getSingleContext(); DF->Attach(); + readRanges(DF, selected_ranges, ranges); SegmentedFinder sf(ranges,DF); sf.Find(0,4,found, vectorAll); sf.Filter(select.c_str(),found, vectorString); @@ -295,8 +340,10 @@ void FindVectorByObjectRawname(DFHack::ContextManager & DFMgr, vector & ranges) +void FindVectorByFirstObjectRawname(DFHack::ContextManager & DFMgr, + vector & selected_ranges) { + vector ranges; vector found; string select; while (Incremental(found, "raw name",select,"vector","vectors")) @@ -304,6 +351,7 @@ void FindVectorByFirstObjectRawname(DFHack::ContextManager & DFMgr, vector Attach(); + readRanges(DF, selected_ranges, ranges); SegmentedFinder sf(ranges,DF); sf.Find(0,4,found, vectorAll); sf.Filter(select.c_str(),found, vectorStringFirst); @@ -323,8 +371,10 @@ struct VectorSizeFunctor : public binary_function SegmentedFinder & sf_; }; -void FindVectorByBounds(DFHack::ContextManager & DFMgr, vector & ranges) +void FindVectorByBounds(DFHack::ContextManager & DFMgr, + vector & selected_ranges) { + vector ranges; vector found; uint32_t select; while (Incremental(found, "address between vector.start and vector.end",select,"vector","vectors")) @@ -332,6 +382,7 @@ void FindVectorByBounds(DFHack::ContextManager & DFMgr, vector Attach(); + readRanges(DF, selected_ranges, ranges); SegmentedFinder sf(ranges,DF); sf.Find(0,4,found, vectorAll); sf.Filter(select,found, vectorAddrWithin); @@ -341,8 +392,10 @@ void FindVectorByBounds(DFHack::ContextManager & DFMgr, vector & ranges) +void FindPtrVectorsByObjectAddress(DFHack::ContextManager & DFMgr, + vector & selected_ranges) { + vector ranges; vector found; uint32_t select; while (Incremental(found, "object address",select,"vector","vectors")) @@ -350,6 +403,7 @@ void FindPtrVectorsByObjectAddress(DFHack::ContextManager & DFMgr, vector Attach(); + readRanges(DF, selected_ranges, ranges); SegmentedFinder sf(ranges,DF); sf.Find(0,4,found, vectorAll); sf.Filter(select,found, vectorOfPtrWithin); @@ -357,8 +411,10 @@ void FindPtrVectorsByObjectAddress(DFHack::ContextManager & DFMgr, vector & ranges) +void FindStrBufs(DFHack::ContextManager & DFMgr, + vector & selected_ranges) { + vector ranges; vector found; string select; while (Incremental(found,"buffer",select,"buffer","buffers")) @@ -366,6 +422,7 @@ void FindStrBufs(DFHack::ContextManager & DFMgr, vector & ra DFMgr.Refresh(); DFHack::Context * DF = DFMgr.getSingleContext(); DF->Attach(); + readRanges(DF, selected_ranges, ranges); SegmentedFinder sf(ranges,DF); sf.Find< const char * ,uint32_t>(select.c_str(),1,found, findStrBuffer); DF->Detach(); @@ -374,8 +431,10 @@ void FindStrBufs(DFHack::ContextManager & DFMgr, vector & ra -void FindStrings(DFHack::ContextManager & DFMgr, vector & ranges) +void FindStrings(DFHack::ContextManager & DFMgr, + vector & selected_ranges) { + vector ranges; vector found; string select; while (Incremental(found,"string",select,"string","strings")) @@ -383,14 +442,17 @@ void FindStrings(DFHack::ContextManager & DFMgr, vector & ra DFMgr.Refresh(); DFHack::Context * DF = DFMgr.getSingleContext(); DF->Attach(); + readRanges(DF, selected_ranges, ranges); SegmentedFinder sf(ranges,DF); sf.Incremental< const char * ,uint32_t>(select.c_str(),1,found, findString); DF->Detach(); } } -void FindData(DFHack::ContextManager & DFMgr, vector & ranges) +void FindData(DFHack::ContextManager & DFMgr, + vector & selected_ranges) { + vector ranges; vector found; Bytestream select; while (Incremental(found,"byte stream",select,"byte stream","byte streams")) @@ -398,6 +460,7 @@ void FindData(DFHack::ContextManager & DFMgr, vector & range DFMgr.Refresh(); DFHack::Context * DF = DFMgr.getSingleContext(); DF->Attach(); + readRanges(DF, selected_ranges, ranges); SegmentedFinder sf(ranges,DF); sf.Incremental< Bytestream ,uint32_t>(select,1,found, findBytestream); DF->Detach(); @@ -449,10 +512,11 @@ bool TriggerIncremental ( vector &found ) else return true; } - -void FindCoords(DFHack::ContextManager & DFMgr, vector & ranges) +void FindCoords(DFHack::ContextManager & DFMgr, vector & selected_ranges) { vector found; + vector ranges; + int size = 4; do { @@ -463,6 +527,7 @@ void FindCoords(DFHack::ContextManager & DFMgr, vector & ran DFMgr.Refresh(); DFHack::Context * DF = DFMgr.getSingleContext(); DF->Attach(); + readRanges(DF, selected_ranges, ranges); DFHack::Gui * pos = DF->getGui(); pos->Start(); int32_t x, y, z; @@ -488,8 +553,11 @@ void FindCoords(DFHack::ContextManager & DFMgr, vector & ran } } -void PtrTrace(DFHack::ContextManager & DFMgr, vector & ranges) +void PtrTrace(DFHack::ContextManager & DFMgr, + vector & selected_ranges) { + vector ranges; + int element_size; do { @@ -505,6 +573,7 @@ void PtrTrace(DFHack::ContextManager & DFMgr, vector & range found.clear(); DFHack::Context * DF = DFMgr.getSingleContext(); DF->Attach(); + readRanges(DF, selected_ranges, ranges); SegmentedFinder sf(ranges,DF); cout <<"Starting: 0x" << hex << select << endl; while(sf.getSegmentForAddress(select)) @@ -548,8 +617,10 @@ void PtrTrace(DFHack::ContextManager & DFMgr, vector & range } } */ -void DataPtrTrace(DFHack::ContextManager & DFMgr, vector & ranges) +void DataPtrTrace(DFHack::ContextManager & DFMgr, + vector & selected_ranges) { + vector ranges; int element_size; do { @@ -563,6 +634,7 @@ void DataPtrTrace(DFHack::ContextManager & DFMgr, vector & r DFHack::Context * DF = DFMgr.getSingleContext(); DF->Attach(); DFMgr.Refresh(); + readRanges(DF, selected_ranges, ranges); found.clear(); SegmentedFinder sf(ranges,DF); while(found.empty()) @@ -669,12 +741,15 @@ struct tilecolors }; #pragma pack() -void autoSearch(DFHack::Context * DF, vector & ranges) +void autoSearch(DFHack::Context * DF, vector & selected_ranges) { + vector ranges; vector allVectors; vector filtVectors; vector to_filter; + readRanges(DF, selected_ranges, ranges); + cout << "stealing memory..." << endl; SegmentedFinder sf(ranges, DF); cout << "looking for vectors..." << endl; @@ -906,8 +981,8 @@ int main (void) return 1; } DFHack::Process * p = DF->getProcess(); - vector selected_ranges; - getRanges(p,selected_ranges); + vector selected_ranges; + getRanges(p, selected_ranges); string prompt = "Select search type: 1=number(default), 2=vector by length, 3=vector>object>string,\n"