command clearvec: clear vector

Added command "clearvec" to plugin "vectors".  Takes a list of addresses
of vectors (or pointers to vectors), and sets each vector to zero length
by setting it's end to it's start.  Leaks memory, of course, but this
is just to poke at the game to see what happens when a vector's
contents disappear.
develop
Matthew Cline 2011-07-19 01:17:11 -07:00
parent 00cf7bc39e
commit 5bb6c3e037
1 changed files with 167 additions and 32 deletions

@ -24,7 +24,10 @@ struct t_vecTriplet
uint32_t alloc_end; uint32_t alloc_end;
}; };
DFhackCExport command_result df_vectors (Core * c, vector <string> & parameters); DFhackCExport command_result df_vectors (Core * c,
vector <string> & parameters);
DFhackCExport command_result df_clearvec (Core * c,
vector <string> & parameters);
DFhackCExport const char * plugin_name ( void ) DFhackCExport const char * plugin_name ( void )
{ {
@ -34,12 +37,17 @@ DFhackCExport const char * plugin_name ( void )
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands)
{ {
commands.clear(); commands.clear();
commands.push_back(PluginCommand("vectors", commands.push_back(PluginCommand("vectors",
"Scan memory for vectors.\ "Scan memory for vectors.\
\n 1st param: start of scan\ \n 1st param: start of scan\
\n 2nd param: number of bytes to scan", \n 2nd param: number of bytes to scan",
df_vectors)); df_vectors));
return CR_OK;
commands.push_back(PluginCommand("clearvec",
"Set list of vectors to zero length",
df_clearvec));
return CR_OK;
} }
DFhackCExport command_result plugin_shutdown ( Core * c ) DFhackCExport command_result plugin_shutdown ( Core * c )
@ -57,12 +65,6 @@ static bool hexOrDec(string &str, uint32_t &value)
return false; return false;
} }
static void usage(Console &con)
{
con << "Usage: vectors <start of scan address> <# bytes to scan>"
<< std::endl;
}
static bool mightBeVec(vector<t_memrange> &heap_ranges, static bool mightBeVec(vector<t_memrange> &heap_ranges,
t_vecTriplet *vec) t_vecTriplet *vec)
{ {
@ -94,6 +96,45 @@ static bool inAnyRange(vector<t_memrange> &ranges, uint32_t ptr)
return false; return false;
} }
static bool getHeapRanges(Core * c, std::vector<t_memrange> &heap_ranges)
{
std::vector<t_memrange> ranges;
c->p->getMemRanges(ranges);
for (size_t i = 0; i < ranges.size(); i++)
{
t_memrange &range = ranges[i];
// Some kernels don't report [heap], and the heap can consist of
// more segments than just the one labeled with [heap], so include
// all segments which *might* be part of the heap.
if (range.read && range.write && !range.shared)
{
if (strlen(range.name) == 0 || strcmp(range.name, "[heap]") == 0)
heap_ranges.push_back(range);
}
}
if (heap_ranges.empty())
{
c->con << "No possible heap segments." << std::endl;
return false;
}
return true;
}
////////////////////////////////////////
// COMMAND: vectors
////////////////////////////////////////
static void vectorsUsage(Console &con)
{
con << "Usage: vectors <start of scan address> <# bytes to scan>"
<< std::endl;
}
static void printVec(Console &con, const char* msg, t_vecTriplet *vec, static void printVec(Console &con, const char* msg, t_vecTriplet *vec,
uint32_t start, uint32_t pos) uint32_t start, uint32_t pos)
{ {
@ -110,7 +151,7 @@ DFhackCExport command_result df_vectors (Core * c, vector <string> & parameters)
if (parameters.size() != 2) if (parameters.size() != 2)
{ {
usage(con); vectorsUsage(con);
return CR_FAILURE; return CR_FAILURE;
} }
@ -118,13 +159,13 @@ DFhackCExport command_result df_vectors (Core * c, vector <string> & parameters)
if (!hexOrDec(parameters[0], start)) if (!hexOrDec(parameters[0], start))
{ {
usage(con); vectorsUsage(con);
return CR_FAILURE; return CR_FAILURE;
} }
if (!hexOrDec(parameters[1], bytes)) if (!hexOrDec(parameters[1], bytes))
{ {
usage(con); vectorsUsage(con);
return CR_FAILURE; return CR_FAILURE;
} }
@ -136,24 +177,18 @@ DFhackCExport command_result df_vectors (Core * c, vector <string> & parameters)
c->Suspend(); c->Suspend();
std::vector<t_memrange> ranges;
std::vector<t_memrange> heap_ranges; std::vector<t_memrange> heap_ranges;
c->p->getMemRanges(ranges);
bool startInRange = false; if (!getHeapRanges(c, heap_ranges))
for (size_t i = 0; i < ranges.size(); i++)
{ {
t_memrange &range = ranges[i]; return CR_FAILURE;
c->Resume();
}
// Some kernels don't report [heap], and the heap can consist of bool startInRange = false;
// more segments than just the one labeled with [heap], so include for (size_t i = 0; i < heap_ranges.size(); i++)
// all segments which *might* be part of the heap. {
if (range.read && range.write && !range.shared) t_memrange &range = heap_ranges[i];
{
if (strlen(range.name) == 0 || strcmp(range.name, "[heap]") == 0)
heap_ranges.push_back(range);
}
if (!range.isInRange(start)) if (!range.isInRange(start))
continue; continue;
@ -169,6 +204,7 @@ DFhackCExport command_result df_vectors (Core * c, vector <string> & parameters)
end = (uint32_t) range.end; end = (uint32_t) range.end;
} }
startInRange = true; startInRange = true;
break;
} // for (size_t i = 0; i < ranges.size(); i++) } // for (size_t i = 0; i < ranges.size(); i++)
if (!startInRange) if (!startInRange)
@ -178,13 +214,6 @@ DFhackCExport command_result df_vectors (Core * c, vector <string> & parameters)
return CR_FAILURE; return CR_FAILURE;
} }
if (heap_ranges.empty())
{
con << "No possible heap segments." << std::endl;
c->Resume();
return CR_FAILURE;
}
uint32_t pos = start; uint32_t pos = start;
const uint32_t ptr_size = sizeof(void*); const uint32_t ptr_size = sizeof(void*);
@ -226,3 +255,109 @@ DFhackCExport command_result df_vectors (Core * c, vector <string> & parameters)
c->Resume(); c->Resume();
return CR_OK; return CR_OK;
} }
////////////////////////////////////////
// COMMAND: clearvec
////////////////////////////////////////
static void clearUsage(Console &con)
{
con << "Usage: clearvec <vector1 addr> [vector2 addr] ..." << std::endl;
con << "Address can be either for vector or pointer to vector."
<< std::endl;
}
DFhackCExport command_result df_clearvec (Core * c, vector <string> & parameters)
{
Console & con = c->con;
if (parameters.size() == 0)
{
clearUsage(con);
return CR_FAILURE;
}
uint32_t start = 0, bytes = 0;
if (!hexOrDec(parameters[0], start))
{
vectorsUsage(con);
return CR_FAILURE;
}
if (!hexOrDec(parameters[1], bytes))
{
vectorsUsage(con);
return CR_FAILURE;
}
c->Suspend();
std::vector<t_memrange> heap_ranges;
if (!getHeapRanges(c, heap_ranges))
{
c->Resume();
return CR_FAILURE;
}
for (size_t i = 0; i < parameters.size(); i++)
{
std::string addr_str = parameters[i];
uint32_t addr;
if (!hexOrDec(addr_str, addr))
{
con << "'" << addr_str << "' not a number." << std::endl;
continue;
}
if (addr % 4 != 0)
{
con << addr_str << " not 4 byte aligned." << std::endl;
continue;
}
if (!inAnyRange(heap_ranges, addr))
{
con << addr_str << " not in any valid address range." << std::endl;
continue;
}
bool valid = false;
bool ptr = false;
t_vecTriplet* vec = (t_vecTriplet*) addr;
if (mightBeVec(heap_ranges, vec))
valid = true;
else
{
// Is it a pointer to a vector?
addr = * ( (uint32_t*) addr);
vec = (t_vecTriplet*) addr;
if (inAnyRange(heap_ranges, addr) && mightBeVec(heap_ranges, vec))
{
valid = true;
ptr = true;
}
}
if (!valid)
{
con << addr_str << " is not a vector." << std::endl;
continue;
}
vec->end = vec->start;
if (ptr)
con << "Vector pointer ";
else
con << "Vector ";
con << addr_str << " set to zero length." << std::endl;
} // for (size_t i = 0; i < parameters.size(); i++)
c->Resume();
return CR_OK;
}