diff --git a/tools/playground/SegmentedFinder.h b/tools/playground/SegmentedFinder.h index f16152997..dfe365490 100644 --- a/tools/playground/SegmentedFinder.h +++ b/tools/playground/SegmentedFinder.h @@ -151,7 +151,7 @@ bool vectorString (SegmentedFinder* s, vecTriplet *x, const char *y) { uint32_t object_ptr; uint32_t idx = x->start; - // iterato over vector of pointers + // iterate over vector of pointers for(uint32_t idx = x->start; idx < x->finish; idx += sizeof(uint32_t)) { // deref ptr idx, get ptr to object @@ -173,7 +173,31 @@ bool vectorString (SegmentedFinder* s, vecTriplet *x, const char *y) return false; } -// test if the address is within a vector's array +// find a vector of 32bit pointers, where the first object pointed to has a string 'y' as the first member +bool vectorStringFirst (SegmentedFinder* s, vecTriplet *x, const char *y) +{ + uint32_t object_ptr; + uint32_t idx = x->start; + // deref ptr idx, get ptr to object + if(!s->Read(idx,object_ptr)) + { + return false; + } + // deref ptr to first object, get ptr to string + uint32_t string_ptr; + if(!s->Read(object_ptr,string_ptr)) + return false; + // get string location in our local cache + char * str = s->Translate(string_ptr); + if(!str) + return false; + if(strcmp(y, str) == 0) + return true; + return false; +} + +// test if the address is between vector.start and vector.finish +// not very useful alone, but could be a good step to filter some things bool vectorAddrWithin (SegmentedFinder* s, vecTriplet *x, uint32_t address) { if(address < x->finish && address >= x->start) @@ -182,6 +206,7 @@ bool vectorAddrWithin (SegmentedFinder* s, vecTriplet *x, uint32_t address) } // test if an object address is within the vector of pointers +// bool vectorOfPtrWithin (SegmentedFinder* s, vecTriplet *x, uint32_t address) { uint32_t object_ptr; diff --git a/tools/playground/incrementalsearch.cpp b/tools/playground/incrementalsearch.cpp index 083597ba3..1207464e9 100644 --- a/tools/playground/incrementalsearch.cpp +++ b/tools/playground/incrementalsearch.cpp @@ -137,11 +137,11 @@ bool Incremental ( vector &found, const char * what, T& output, string select; if(found.empty()) { - cout << "search ready - insert " << what << ", 'p' for results" << endl; + cout << "search ready - insert " << what << ", 'p' for results, 'p #' to limit number of results" << endl; } else if( found.size() == 1) { - cout << "Found an "<< singular <<"!" << endl; + cout << "Found single "<< singular <<"!" << endl; cout << hex << "0x" << found[0] << endl; } else @@ -151,7 +151,17 @@ bool Incremental ( vector &found, const char * what, T& output, incremental_more: cout << ">>"; std::getline(cin, select); - if(select == "p") + size_t num = 0; + if( sscanf(select.c_str(),"p %d", &num) && num > 0) + { + cout << "Found "<< plural <<":" << endl; + for(int i = 0; i < min(found.size(), num);i++) + { + cout << hex << "0x" << found[i] << endl; + } + goto incremental_more; + } + else if(select == "p") { cout << "Found "<< plural <<":" << endl; for(int i = 0; i < found.size();i++) @@ -168,18 +178,21 @@ bool Incremental ( vector &found, const char * what, T& output, { stringstream ss (stringstream::in | stringstream::out); ss << select; - ss >> output; + ss >> hex >> output; if(ss.fail()) { - cout << "not a valid value for type: " << what << endl; - goto incremental_more; + ss >> dec >> output; + if(ss.fail()) + { + cout << "not a valid value for type: " << what << endl; + goto incremental_more; + } } return true; } } -//TODO: lots of optimization -void searchLoop(DFHack::ContextManager & DFMgr, vector & ranges) +void FindIntegers(DFHack::ContextManager & DFMgr, vector & ranges) { // input / validation of variable size int size; @@ -219,7 +232,7 @@ void searchLoop(DFHack::ContextManager & DFMgr, vector & ran } } -void searchLoopVector(DFHack::ContextManager & DFMgr, vector & ranges ) +void FindVectorByLength(DFHack::ContextManager & DFMgr, vector & ranges ) { int element_size; do @@ -242,7 +255,7 @@ void searchLoopVector(DFHack::ContextManager & DFMgr, vector & ranges) +void FindVectorByObjectRawname(DFHack::ContextManager & DFMgr, vector & ranges) { vector found; string select; @@ -260,7 +273,76 @@ void searchLoopStrObjVector(DFHack::ContextManager & DFMgr, vector & ranges) +void FindVectorByFirstObjectRawname(DFHack::ContextManager & DFMgr, vector & ranges) +{ + vector found; + string select; + while (Incremental(found, "raw name",select,"vector","vectors")) + { + // clear the list of found addresses -- this is a one-shot + found.clear(); + DFMgr.Refresh(); + DFHack::Context * DF = DFMgr.getSingleContext(); + DF->Attach(); + SegmentedFinder sf(ranges,DF); + sf.Find(0,4,found, vectorAll); + sf.Find(select.c_str(),4,found, vectorStringFirst); + DF->Detach(); + } +} + +struct VectorSizeFunctor : public binary_function +{ + VectorSizeFunctor(SegmentedFinder & sf):sf_(sf){} + bool operator()( uint64_t lhs, uint64_t rhs) + { + vecTriplet* left = sf_.Translate(lhs); + vecTriplet* right = sf_.Translate(rhs); + return ((left->finish - left->start) < (right->finish - right->start)); + } + SegmentedFinder & sf_; +}; + +void FindVectorByBounds(DFHack::ContextManager & DFMgr, vector & ranges) +{ + vector found; + uint32_t select; + while (Incremental(found, "address between vector.start and vector.end",select,"vector","vectors")) + { + // clear the list of found addresses -- this is a one-shot + found.clear(); + DFMgr.Refresh(); + DFHack::Context * DF = DFMgr.getSingleContext(); + DF->Attach(); + SegmentedFinder sf(ranges,DF); + sf.Find(0,4,found, vectorAll); + sf.Find(select,4,found, vectorAddrWithin); + // sort by size of vector + std::sort(found.begin(), found.end(), VectorSizeFunctor(sf)); + DF->Detach(); + } +} + +void FindPtrVectorsByObjectAddress(DFHack::ContextManager & DFMgr, vector & ranges) +{ + vector found; + uint32_t select; + while (Incremental(found, "object address",select,"vector","vectors")) + { + // clear the list of found addresses -- this is a one-shot + found.clear(); + DFMgr.Refresh(); + DFHack::Context * DF = DFMgr.getSingleContext(); + DF->Attach(); + SegmentedFinder sf(ranges,DF); + sf.Find(0,4,found, vectorAll); + sf.Find(select,4,found, vectorOfPtrWithin); + DF->Detach(); + } +} + + +void FindStrings(DFHack::ContextManager & DFMgr, vector & ranges) { vector found; string select; @@ -290,17 +372,17 @@ void automatedLangtables(DFHack::Context * DF, vector & rang // find lang vector (neutral word table) to_filter = allVectors; - sf.Find("ABBEY",4,to_filter, vectorString); + sf.Find("ABBEY",4,to_filter, vectorStringFirst); uint64_t lang_addr = to_filter[0]; // find dwarven language word table to_filter = allVectors; - sf.Find("kulet",4,to_filter, vectorString); + sf.Find("kulet",4,to_filter, vectorStringFirst); kulet_vector = to_filter[0]; // find vector of languages to_filter = allVectors; - sf.Find("DWARF",4,to_filter, vectorString); + sf.Find("DWARF",4,to_filter, vectorStringFirst); // verify for(int i = 0; i < to_filter.size(); i++) @@ -352,24 +434,30 @@ int main (void) } while (mode < 1 || mode > 8 ); switch (mode) { - case 1:// integers - searchLoop(DFMgr, selected_ranges); + case 1: + FindIntegers(DFMgr, selected_ranges); break; - case 2:// vector by length and item size - searchLoopVector(DFMgr, selected_ranges); + case 2: + FindVectorByLength(DFMgr, selected_ranges); break; - case 3:// vector>object>string - searchLoopStrObjVector(DFMgr, selected_ranges); + case 3: + FindVectorByObjectRawname(DFMgr, selected_ranges); break; - case 4:// string - searchLoopStr(DFMgr, selected_ranges); + case 4: + FindStrings(DFMgr, selected_ranges); break; case 5: automatedLangtables(DF,selected_ranges); break; case 6: + FindVectorByBounds(DFMgr,selected_ranges); + break; case 7: + FindPtrVectorsByObjectAddress(DFMgr,selected_ranges); + break; case 8: + FindVectorByFirstObjectRawname(DFMgr, selected_ranges); + break; default: cout << "not implemented :(" << endl; }