vectors: attempt to identify instances of virtual classes

Also:
- don't restrict to heap ranges (e.g. allow globals)
- stylistic cleanup
develop
lethosor 2016-04-03 20:47:21 -04:00
parent 37c81df21c
commit f5d10ecf61
1 changed files with 44 additions and 35 deletions

@ -1,18 +1,20 @@
// Lists embeded STL vectors and pointers to STL vectors found in the given // Lists embeded STL vectors and pointers to STL vectors found in the given
// memory range. // memory range.
// //
// Linux only, enabled with BUILD_VECTORS cmake option. // Linux and OS X only
#include "Core.h"
#include <Console.h>
#include <Export.h>
#include <PluginManager.h>
#include <MemAccess.h>
#include <vector> #include <vector>
#include <string> #include <string>
#include <stdio.h> #include <stdio.h>
#include "Core.h"
#include "Console.h"
#include "Export.h"
#include "PluginManager.h"
#include "MemAccess.h"
#include "VersionInfo.h"
using std::vector; using std::vector;
using std::string; using std::string;
using namespace DFHack; using namespace DFHack;
@ -58,7 +60,7 @@ static bool hexOrDec(string &str, uint32_t &value)
return false; return false;
} }
static bool mightBeVec(vector<t_memrange> &heap_ranges, static bool mightBeVec(vector<t_memrange> &ranges,
t_vecTriplet *vec) t_vecTriplet *vec)
{ {
if ((vec->start > vec->end) || (vec->end > vec->alloc_end)) if ((vec->start > vec->end) || (vec->end > vec->alloc_end))
@ -70,9 +72,9 @@ static bool mightBeVec(vector<t_memrange> &heap_ranges,
if (((int)vec->start % 4 != 0) || ((int)vec->alloc_end % 4 != 0)) if (((int)vec->start % 4 != 0) || ((int)vec->alloc_end % 4 != 0))
return false; return false;
for (size_t i = 0; i < heap_ranges.size(); i++) for (size_t i = 0; i < ranges.size(); i++)
{ {
t_memrange &range = heap_ranges[i]; t_memrange &range = ranges[i];
if (range.isInRange(vec->start) && range.isInRange(vec->alloc_end)) if (range.isInRange(vec->start) && range.isInRange(vec->alloc_end))
return true; return true;
@ -92,7 +94,7 @@ static bool inAnyRange(vector<t_memrange> &ranges, void * ptr)
return false; return false;
} }
static bool getHeapRanges(color_ostream &out, std::vector<t_memrange> &heap_ranges) static bool getRanges(color_ostream &out, std::vector<t_memrange> &out_ranges)
{ {
std::vector<t_memrange> ranges; std::vector<t_memrange> ranges;
@ -102,19 +104,13 @@ static bool getHeapRanges(color_ostream &out, std::vector<t_memrange> &heap_rang
{ {
t_memrange &range = ranges[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 (range.read && range.write && !range.shared)
{ out_ranges.push_back(range);
if (strlen(range.name) == 0 || strcmp(range.name, "[heap]") == 0)
heap_ranges.push_back(range);
}
} }
if (heap_ranges.empty()) if (out_ranges.empty())
{ {
out << "No possible heap segments." << std::endl; out << "No readable segments." << std::endl;
return false; return false;
} }
@ -132,13 +128,26 @@ static void vectorsUsage(color_ostream &con)
} }
static void printVec(color_ostream &con, const char* msg, t_vecTriplet *vec, static void printVec(color_ostream &con, const char* msg, t_vecTriplet *vec,
uint32_t start, uint32_t pos) uint32_t start, uint32_t pos, std::vector<t_memrange> &ranges)
{ {
uint32_t length = (int)vec->end - (int)vec->start; uint32_t length = (int)vec->end - (int)vec->start;
uint32_t offset = pos - start; uint32_t offset = pos - start;
con.print("%8s offset %06p, addr %010p, start %010p, length %u\n", con.print("%8s offset %06p, addr %010p, start %010p, length %u",
msg, offset, pos, vec->start, length); msg, offset, pos, vec->start, length);
if (length >= 4 && length % 4 == 0)
{
void *ptr = vec->start;
for (int level = 0; level < 2; level++)
{
if (inAnyRange(ranges, ptr))
ptr = *(void**)ptr;
}
std::string classname;
if (Core::getInstance().vinfo->getVTableName(ptr, classname))
con.print(", 1st item: %s", classname.c_str());
}
con.print("\n");
} }
command_result df_vectors (color_ostream &con, vector <string> & parameters) command_result df_vectors (color_ostream &con, vector <string> & parameters)
@ -171,17 +180,17 @@ command_result df_vectors (color_ostream &con, vector <string> & parameters)
CoreSuspender suspend; CoreSuspender suspend;
std::vector<t_memrange> heap_ranges; std::vector<t_memrange> ranges;
if (!getHeapRanges(con, heap_ranges)) if (!getRanges(con, ranges))
{ {
return CR_FAILURE; return CR_FAILURE;
} }
bool startInRange = false; bool startInRange = false;
for (size_t i = 0; i < heap_ranges.size(); i++) for (size_t i = 0; i < ranges.size(); i++)
{ {
t_memrange &range = heap_ranges[i]; t_memrange &range = ranges[i];
if (!range.isInRange((void *)start)) if (!range.isInRange((void *)start))
continue; continue;
@ -217,9 +226,9 @@ command_result df_vectors (color_ostream &con, vector <string> & parameters)
{ {
t_vecTriplet* vec = (t_vecTriplet*) pos; t_vecTriplet* vec = (t_vecTriplet*) pos;
if (mightBeVec(heap_ranges, vec)) if (mightBeVec(ranges, vec))
{ {
printVec(con, "VEC:", vec, start, pos); printVec(con, "VEC:", vec, start, pos, ranges);
// Skip over rest of vector. // Skip over rest of vector.
pos += sizeof(t_vecTriplet) - ptr_size; pos += sizeof(t_vecTriplet) - ptr_size;
continue; continue;
@ -231,13 +240,13 @@ command_result df_vectors (color_ostream &con, vector <string> & parameters)
{ {
uint32_t ptr = * ( (uint32_t*) pos); uint32_t ptr = * ( (uint32_t*) pos);
if (inAnyRange(heap_ranges, (void *) ptr)) if (inAnyRange(ranges, (void *) ptr))
{ {
t_vecTriplet* vec = (t_vecTriplet*) ptr; t_vecTriplet* vec = (t_vecTriplet*) ptr;
if (mightBeVec(heap_ranges, vec)) if (mightBeVec(ranges, vec))
{ {
printVec(con, "VEC PTR:", vec, start, pos); printVec(con, "VEC PTR:", vec, start, pos, ranges);
continue; continue;
} }
} }
@ -282,9 +291,9 @@ command_result df_clearvec (color_ostream &con, vector <string> & parameters)
CoreSuspender suspend; CoreSuspender suspend;
std::vector<t_memrange> heap_ranges; std::vector<t_memrange> ranges;
if (!getHeapRanges(con, heap_ranges)) if (!getRanges(con, ranges))
{ {
return CR_FAILURE; return CR_FAILURE;
} }
@ -305,7 +314,7 @@ command_result df_clearvec (color_ostream &con, vector <string> & parameters)
continue; continue;
} }
if (!inAnyRange(heap_ranges, (void *) addr)) if (!inAnyRange(ranges, (void *) addr))
{ {
con << addr_str << " not in any valid address range." << std::endl; con << addr_str << " not in any valid address range." << std::endl;
continue; continue;
@ -315,7 +324,7 @@ command_result df_clearvec (color_ostream &con, vector <string> & parameters)
bool ptr = false; bool ptr = false;
t_vecTriplet* vec = (t_vecTriplet*) addr; t_vecTriplet* vec = (t_vecTriplet*) addr;
if (mightBeVec(heap_ranges, vec)) if (mightBeVec(ranges, vec))
valid = true; valid = true;
else else
{ {
@ -323,7 +332,7 @@ command_result df_clearvec (color_ostream &con, vector <string> & parameters)
addr = * ( (uint32_t*) addr); addr = * ( (uint32_t*) addr);
vec = (t_vecTriplet*) addr; vec = (t_vecTriplet*) addr;
if (inAnyRange(heap_ranges, (void *) addr) && mightBeVec(heap_ranges, vec)) if (inAnyRange(ranges, (void *) addr) && mightBeVec(ranges, vec))
{ {
valid = true; valid = true;
ptr = true; ptr = true;