|
|
|
@ -33,28 +33,33 @@ DFhackCExport command_result plugin_init(color_ostream &, std::vector<PluginComm
|
|
|
|
|
return CR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool check_malloc_perturb()
|
|
|
|
|
// returns 0 if MALLOC_PERTURB_ is unset, or if set to 0, because 0 is not useful
|
|
|
|
|
uint8_t check_malloc_perturb()
|
|
|
|
|
{
|
|
|
|
|
struct T_test {
|
|
|
|
|
uint32_t data[1024];
|
|
|
|
|
};
|
|
|
|
|
auto test = new T_test;
|
|
|
|
|
bool ret = (test->data[0] == 0xd2d2d2d2);
|
|
|
|
|
delete test;
|
|
|
|
|
return ret;
|
|
|
|
|
const size_t TEST_DATA_LEN = 5000; // >1 4kb page
|
|
|
|
|
std::unique_ptr<uint8_t[]> test_data{new uint8_t[TEST_DATA_LEN]};
|
|
|
|
|
|
|
|
|
|
uint8_t expected_perturb = test_data[0];
|
|
|
|
|
if (getenv("MALLOC_PERTURB_"))
|
|
|
|
|
expected_perturb = 0xff ^ static_cast<uint8_t>(atoi(getenv("MALLOC_PERTURB_")));
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < TEST_DATA_LEN; i++)
|
|
|
|
|
if (expected_perturb != test_data[i])
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return expected_perturb;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static command_result command(color_ostream & out, std::vector<std::string> & parameters)
|
|
|
|
|
{
|
|
|
|
|
if (!check_malloc_perturb())
|
|
|
|
|
{
|
|
|
|
|
out.printerr("check-structures-sanity: MALLOC_PERTURB_ not set, cannot continue\n");
|
|
|
|
|
return CR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
uint8_t perturb_byte = check_malloc_perturb();
|
|
|
|
|
if (!perturb_byte)
|
|
|
|
|
out.printerr("check-structures-sanity: MALLOC_PERTURB_ not set. Some checks may be bypassed or fail.\n");
|
|
|
|
|
|
|
|
|
|
CoreSuspender suspend;
|
|
|
|
|
|
|
|
|
|
Checker checker(out);
|
|
|
|
|
checker.perturb_byte = perturb_byte;
|
|
|
|
|
|
|
|
|
|
// check parameters with values first
|
|
|
|
|
#define VAL_PARAM(name, expr_using_value) \
|
|
|
|
|