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.
develop
Matthew Cline 2011-07-10 02:16:28 -07:00
parent 488322cb0d
commit 49fd378a47
2 changed files with 109 additions and 28 deletions

@ -27,7 +27,13 @@ class SegmentFinder
free(mr_.buffer); free(mr_.buffer);
valid = false; valid = false;
mr.valid = false; // mark the range passed in as bad 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;
} }
} }
} }

@ -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; 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 <DFHack::t_memrange>& 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 <int>& selected_ranges)
{ {
vector <DFHack::t_memrange> ranges; vector <DFHack::t_memrange> ranges;
ranges.clear();
selected_ranges.clear(); selected_ranges.clear();
p->getMemRanges(ranges); p->getMemRanges(ranges);
cout << "Which range to search? (default is 1-4)" << endl; cout << "Which range to search? (default is 1-4)" << endl;
@ -46,8 +54,9 @@ bool getRanges(DFHack::Process * p, vector <DFHack::t_memrange>& selected_ranges
std::getline(cin, select); std::getline(cin, select);
if(select.empty()) if(select.empty())
{ {
// empty input, assume default. observe the length of the memory range vector // empty input, assume default. observe the length of the memory
// these are hardcoded values, intended for my convenience only // range vector these are hardcoded values, intended for my
// convenience only
if(p->getDescriptor()->getOS() == DFHack::OS_WINDOWS) if(p->getDescriptor()->getOS() == DFHack::OS_WINDOWS)
{ {
start = min(11, (int)ranges.size()); start = min(11, (int)ranges.size());
@ -78,20 +87,18 @@ bool getRanges(DFHack::Process * p, vector <DFHack::t_memrange>& selected_ranges
} }
break; break;
} }
end++;
cout << "selected ranges:" <<endl; cout << "selected ranges:" <<endl;
vector <DFHack::t_memrange>::iterator it;
it = ranges.begin() + start; for (int i = start; i <= end; i++)
while (it != ranges.begin() + end)
{ {
// check if readable // check if readable
if((*it).read) if (ranges[i].read)
{ {
selected_ranges.push_back(*it); selected_ranges.push_back(i);
printRange(&*it); printRange(&(ranges[i]));
} }
it++;
} }
return true; return true;
} }
@ -139,6 +146,32 @@ bool getString (string prompt, string & output)
} }
} }
bool readRanges(DFHack::Context * DF, vector <int>& selected_ranges,
vector <DFHack::t_memrange>& ranges)
{
DFHack::Process * p = DF->getProcess();
vector <DFHack::t_memrange> 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 <class T> template <class T>
bool Incremental ( vector <uint64_t> &found, const char * what, T& output, bool Incremental ( vector <uint64_t> &found, const char * what, T& output,
const char *singular = "address", const char *plural = "addresses", bool numberz = false ) const char *singular = "address", const char *plural = "addresses", bool numberz = false )
@ -215,8 +248,11 @@ bool Incremental ( vector <uint64_t> &found, const char * what, T& output,
} }
} }
void FindIntegers(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ranges) void FindIntegers(DFHack::ContextManager & DFMgr,
vector <int>& selected_ranges)
{ {
vector <DFHack::t_memrange> ranges;
// input / validation of variable size // input / validation of variable size
int size; int size;
do do
@ -238,6 +274,7 @@ void FindIntegers(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& r
DFMgr.Refresh(); DFMgr.Refresh();
DFHack::Context * DF = DFMgr.getSingleContext(); DFHack::Context * DF = DFMgr.getSingleContext();
DF->Attach(); DF->Attach();
readRanges(DF, selected_ranges, ranges);
SegmentedFinder sf(ranges,DF); SegmentedFinder sf(ranges,DF);
switch(size) switch(size)
{ {
@ -255,8 +292,11 @@ void FindIntegers(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& r
} }
} }
void FindVectorByLength(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ranges ) void FindVectorByLength(DFHack::ContextManager & DFMgr,
vector <int>& selected_ranges )
{ {
vector <DFHack::t_memrange> ranges;
int element_size; int element_size;
do do
{ {
@ -271,6 +311,7 @@ void FindVectorByLength(DFHack::ContextManager & DFMgr, vector <DFHack::t_memran
DFMgr.Refresh(); DFMgr.Refresh();
DFHack::Context * DF = DFMgr.getSingleContext(); DFHack::Context * DF = DFMgr.getSingleContext();
DF->Attach(); DF->Attach();
readRanges(DF, selected_ranges, ranges);
SegmentedFinder sf(ranges,DF); SegmentedFinder sf(ranges,DF);
//sf.Incremental<int ,vecTriplet>(0,4,found,vectorAll); //sf.Incremental<int ,vecTriplet>(0,4,found,vectorAll);
//sf.Filter<uint32_t,vecTriplet>(length * element_size,found,vectorLength<uint32_t>); //sf.Filter<uint32_t,vecTriplet>(length * element_size,found,vectorLength<uint32_t>);
@ -279,15 +320,19 @@ void FindVectorByLength(DFHack::ContextManager & DFMgr, vector <DFHack::t_memran
} }
} }
void FindVectorByObjectRawname(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ranges) void FindVectorByObjectRawname(DFHack::ContextManager & DFMgr,
vector <int>& selected_ranges)
{ {
vector <DFHack::t_memrange> ranges;
vector <uint64_t> found; vector <uint64_t> found;
string select; string select;
while (Incremental(found, "raw name",select,"vector","vectors")) while (Incremental(found, "raw name",select,"vector","vectors"))
{ {
DFMgr.Refresh(); DFMgr.Refresh();
DFHack::Context * DF = DFMgr.getSingleContext(); DFHack::Context * DF = DFMgr.getSingleContext();
DF->Attach(); DF->Attach();
readRanges(DF, selected_ranges, ranges);
SegmentedFinder sf(ranges,DF); SegmentedFinder sf(ranges,DF);
sf.Find<int ,vecTriplet>(0,4,found, vectorAll); sf.Find<int ,vecTriplet>(0,4,found, vectorAll);
sf.Filter<const char * ,vecTriplet>(select.c_str(),found, vectorString); sf.Filter<const char * ,vecTriplet>(select.c_str(),found, vectorString);
@ -295,8 +340,10 @@ void FindVectorByObjectRawname(DFHack::ContextManager & DFMgr, vector <DFHack::t
} }
} }
void FindVectorByFirstObjectRawname(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ranges) void FindVectorByFirstObjectRawname(DFHack::ContextManager & DFMgr,
vector <int>& selected_ranges)
{ {
vector <DFHack::t_memrange> ranges;
vector <uint64_t> found; vector <uint64_t> found;
string select; string select;
while (Incremental(found, "raw name",select,"vector","vectors")) while (Incremental(found, "raw name",select,"vector","vectors"))
@ -304,6 +351,7 @@ void FindVectorByFirstObjectRawname(DFHack::ContextManager & DFMgr, vector <DFHa
DFMgr.Refresh(); DFMgr.Refresh();
DFHack::Context * DF = DFMgr.getSingleContext(); DFHack::Context * DF = DFMgr.getSingleContext();
DF->Attach(); DF->Attach();
readRanges(DF, selected_ranges, ranges);
SegmentedFinder sf(ranges,DF); SegmentedFinder sf(ranges,DF);
sf.Find<int ,vecTriplet>(0,4,found, vectorAll); sf.Find<int ,vecTriplet>(0,4,found, vectorAll);
sf.Filter<const char * ,vecTriplet>(select.c_str(),found, vectorStringFirst); sf.Filter<const char * ,vecTriplet>(select.c_str(),found, vectorStringFirst);
@ -323,8 +371,10 @@ struct VectorSizeFunctor : public binary_function<uint64_t, uint64_t, bool>
SegmentedFinder & sf_; SegmentedFinder & sf_;
}; };
void FindVectorByBounds(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ranges) void FindVectorByBounds(DFHack::ContextManager & DFMgr,
vector <int>& selected_ranges)
{ {
vector <DFHack::t_memrange> ranges;
vector <uint64_t> found; vector <uint64_t> found;
uint32_t select; uint32_t select;
while (Incremental(found, "address between vector.start and vector.end",select,"vector","vectors")) while (Incremental(found, "address between vector.start and vector.end",select,"vector","vectors"))
@ -332,6 +382,7 @@ void FindVectorByBounds(DFHack::ContextManager & DFMgr, vector <DFHack::t_memran
DFMgr.Refresh(); DFMgr.Refresh();
DFHack::Context * DF = DFMgr.getSingleContext(); DFHack::Context * DF = DFMgr.getSingleContext();
DF->Attach(); DF->Attach();
readRanges(DF, selected_ranges, ranges);
SegmentedFinder sf(ranges,DF); SegmentedFinder sf(ranges,DF);
sf.Find<int ,vecTriplet>(0,4,found, vectorAll); sf.Find<int ,vecTriplet>(0,4,found, vectorAll);
sf.Filter<uint32_t ,vecTriplet>(select,found, vectorAddrWithin); sf.Filter<uint32_t ,vecTriplet>(select,found, vectorAddrWithin);
@ -341,8 +392,10 @@ void FindVectorByBounds(DFHack::ContextManager & DFMgr, vector <DFHack::t_memran
} }
} }
void FindPtrVectorsByObjectAddress(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ranges) void FindPtrVectorsByObjectAddress(DFHack::ContextManager & DFMgr,
vector <int>& selected_ranges)
{ {
vector <DFHack::t_memrange> ranges;
vector <uint64_t> found; vector <uint64_t> found;
uint32_t select; uint32_t select;
while (Incremental(found, "object address",select,"vector","vectors")) while (Incremental(found, "object address",select,"vector","vectors"))
@ -350,6 +403,7 @@ void FindPtrVectorsByObjectAddress(DFHack::ContextManager & DFMgr, vector <DFHac
DFMgr.Refresh(); DFMgr.Refresh();
DFHack::Context * DF = DFMgr.getSingleContext(); DFHack::Context * DF = DFMgr.getSingleContext();
DF->Attach(); DF->Attach();
readRanges(DF, selected_ranges, ranges);
SegmentedFinder sf(ranges,DF); SegmentedFinder sf(ranges,DF);
sf.Find<int ,vecTriplet>(0,4,found, vectorAll); sf.Find<int ,vecTriplet>(0,4,found, vectorAll);
sf.Filter<uint32_t ,vecTriplet>(select,found, vectorOfPtrWithin); sf.Filter<uint32_t ,vecTriplet>(select,found, vectorOfPtrWithin);
@ -357,8 +411,10 @@ void FindPtrVectorsByObjectAddress(DFHack::ContextManager & DFMgr, vector <DFHac
} }
} }
void FindStrBufs(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ranges) void FindStrBufs(DFHack::ContextManager & DFMgr,
vector <int>& selected_ranges)
{ {
vector <DFHack::t_memrange> ranges;
vector <uint64_t> found; vector <uint64_t> found;
string select; string select;
while (Incremental(found,"buffer",select,"buffer","buffers")) while (Incremental(found,"buffer",select,"buffer","buffers"))
@ -366,6 +422,7 @@ void FindStrBufs(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ra
DFMgr.Refresh(); DFMgr.Refresh();
DFHack::Context * DF = DFMgr.getSingleContext(); DFHack::Context * DF = DFMgr.getSingleContext();
DF->Attach(); DF->Attach();
readRanges(DF, selected_ranges, ranges);
SegmentedFinder sf(ranges,DF); SegmentedFinder sf(ranges,DF);
sf.Find< const char * ,uint32_t>(select.c_str(),1,found, findStrBuffer); sf.Find< const char * ,uint32_t>(select.c_str(),1,found, findStrBuffer);
DF->Detach(); DF->Detach();
@ -374,8 +431,10 @@ void FindStrBufs(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ra
void FindStrings(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ranges) void FindStrings(DFHack::ContextManager & DFMgr,
vector <int>& selected_ranges)
{ {
vector <DFHack::t_memrange> ranges;
vector <uint64_t> found; vector <uint64_t> found;
string select; string select;
while (Incremental(found,"string",select,"string","strings")) while (Incremental(found,"string",select,"string","strings"))
@ -383,14 +442,17 @@ void FindStrings(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ra
DFMgr.Refresh(); DFMgr.Refresh();
DFHack::Context * DF = DFMgr.getSingleContext(); DFHack::Context * DF = DFMgr.getSingleContext();
DF->Attach(); DF->Attach();
readRanges(DF, selected_ranges, ranges);
SegmentedFinder sf(ranges,DF); SegmentedFinder sf(ranges,DF);
sf.Incremental< const char * ,uint32_t>(select.c_str(),1,found, findString); sf.Incremental< const char * ,uint32_t>(select.c_str(),1,found, findString);
DF->Detach(); DF->Detach();
} }
} }
void FindData(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ranges) void FindData(DFHack::ContextManager & DFMgr,
vector <int>& selected_ranges)
{ {
vector <DFHack::t_memrange> ranges;
vector <uint64_t> found; vector <uint64_t> found;
Bytestream select; Bytestream select;
while (Incremental(found,"byte stream",select,"byte stream","byte streams")) while (Incremental(found,"byte stream",select,"byte stream","byte streams"))
@ -398,6 +460,7 @@ void FindData(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& range
DFMgr.Refresh(); DFMgr.Refresh();
DFHack::Context * DF = DFMgr.getSingleContext(); DFHack::Context * DF = DFMgr.getSingleContext();
DF->Attach(); DF->Attach();
readRanges(DF, selected_ranges, ranges);
SegmentedFinder sf(ranges,DF); SegmentedFinder sf(ranges,DF);
sf.Incremental< Bytestream ,uint32_t>(select,1,found, findBytestream); sf.Incremental< Bytestream ,uint32_t>(select,1,found, findBytestream);
DF->Detach(); DF->Detach();
@ -449,10 +512,11 @@ bool TriggerIncremental ( vector <uint64_t> &found )
else return true; else return true;
} }
void FindCoords(DFHack::ContextManager & DFMgr, vector <int>& selected_ranges)
void FindCoords(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ranges)
{ {
vector <uint64_t> found; vector <uint64_t> found;
vector <DFHack::t_memrange> ranges;
int size = 4; int size = 4;
do do
{ {
@ -463,6 +527,7 @@ void FindCoords(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ran
DFMgr.Refresh(); DFMgr.Refresh();
DFHack::Context * DF = DFMgr.getSingleContext(); DFHack::Context * DF = DFMgr.getSingleContext();
DF->Attach(); DF->Attach();
readRanges(DF, selected_ranges, ranges);
DFHack::Gui * pos = DF->getGui(); DFHack::Gui * pos = DF->getGui();
pos->Start(); pos->Start();
int32_t x, y, z; int32_t x, y, z;
@ -488,8 +553,11 @@ void FindCoords(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ran
} }
} }
void PtrTrace(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ranges) void PtrTrace(DFHack::ContextManager & DFMgr,
vector <int>& selected_ranges)
{ {
vector <DFHack::t_memrange> ranges;
int element_size; int element_size;
do do
{ {
@ -505,6 +573,7 @@ void PtrTrace(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& range
found.clear(); found.clear();
DFHack::Context * DF = DFMgr.getSingleContext(); DFHack::Context * DF = DFMgr.getSingleContext();
DF->Attach(); DF->Attach();
readRanges(DF, selected_ranges, ranges);
SegmentedFinder sf(ranges,DF); SegmentedFinder sf(ranges,DF);
cout <<"Starting: 0x" << hex << select << endl; cout <<"Starting: 0x" << hex << select << endl;
while(sf.getSegmentForAddress(select)) while(sf.getSegmentForAddress(select))
@ -548,8 +617,10 @@ void PtrTrace(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& range
} }
} }
*/ */
void DataPtrTrace(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& ranges) void DataPtrTrace(DFHack::ContextManager & DFMgr,
vector <int>& selected_ranges)
{ {
vector <DFHack::t_memrange> ranges;
int element_size; int element_size;
do do
{ {
@ -563,6 +634,7 @@ void DataPtrTrace(DFHack::ContextManager & DFMgr, vector <DFHack::t_memrange>& r
DFHack::Context * DF = DFMgr.getSingleContext(); DFHack::Context * DF = DFMgr.getSingleContext();
DF->Attach(); DF->Attach();
DFMgr.Refresh(); DFMgr.Refresh();
readRanges(DF, selected_ranges, ranges);
found.clear(); found.clear();
SegmentedFinder sf(ranges,DF); SegmentedFinder sf(ranges,DF);
while(found.empty()) while(found.empty())
@ -669,12 +741,15 @@ struct tilecolors
}; };
#pragma pack() #pragma pack()
void autoSearch(DFHack::Context * DF, vector <DFHack::t_memrange>& ranges) void autoSearch(DFHack::Context * DF, vector <int>& selected_ranges)
{ {
vector <DFHack::t_memrange> ranges;
vector <uint64_t> allVectors; vector <uint64_t> allVectors;
vector <uint64_t> filtVectors; vector <uint64_t> filtVectors;
vector <uint64_t> to_filter; vector <uint64_t> to_filter;
readRanges(DF, selected_ranges, ranges);
cout << "stealing memory..." << endl; cout << "stealing memory..." << endl;
SegmentedFinder sf(ranges, DF); SegmentedFinder sf(ranges, DF);
cout << "looking for vectors..." << endl; cout << "looking for vectors..." << endl;
@ -906,7 +981,7 @@ int main (void)
return 1; return 1;
} }
DFHack::Process * p = DF->getProcess(); DFHack::Process * p = DF->getProcess();
vector <DFHack::t_memrange> selected_ranges; vector <int> selected_ranges;
getRanges(p, selected_ranges); getRanges(p, selected_ranges);
string prompt = string prompt =