|
|
@ -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,11 +37,16 @@ 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));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
commands.push_back(PluginCommand("clearvec",
|
|
|
|
|
|
|
|
"Set list of vectors to zero length",
|
|
|
|
|
|
|
|
df_clearvec));
|
|
|
|
return CR_OK;
|
|
|
|
return CR_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -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;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < ranges.size(); i++)
|
|
|
|
if (!getHeapRanges(c, heap_ranges))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (strlen(range.name) == 0 || strcmp(range.name, "[heap]") == 0)
|
|
|
|
t_memrange &range = heap_ranges[i];
|
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
|
|
|