AutoReferenceRecorder.h [plain text]
#pragma once
#ifndef __AUTO_INTERFACE__
#define __AUTO_INTERFACE__
#include <sys/types.h>
#include <malloc/malloc.h>
#include "AutoZone.h"
#include "AutoInUseEnumerator.h"
#include "AutoMemoryScanner.h"
namespace Auto {
struct ReferenceRecorder : public MemoryScanner {
auto_reference_recorder_t _callback; void *_callback_ctx; void *_block; Thread *_thread; int _first_register; Range _thread_range;
ReferenceRecorder(Zone *zone, void *block, auto_reference_recorder_t callback, void *stack_bottom, void *ctx)
: MemoryScanner(zone, stack_bottom, true)
, _callback(callback)
, _callback_ctx(ctx)
, _block(block)
, _thread(NULL)
, _first_register(-1)
, _thread_range()
{}
void check_block(void **reference, void *block) {
if (block == _block) {
if (_thread) {
intptr_t offset = (intptr_t)reference - (intptr_t)_thread_range.end();
auto_reference_t ref = { (vm_address_t)block, (vm_address_t)_thread_range.end(), offset };
_callback((auto_zone_t *)_zone, _callback_ctx, ref);
} else if (!reference) {
} else {
void *owner = zone()->block_start((void*)reference);
if (owner) {
intptr_t offset = (intptr_t)reference - (intptr_t)owner;
auto_reference_t ref = { (vm_address_t)block, (vm_address_t)owner, offset };
_callback((auto_zone_t *)_zone, _callback_ctx, ref);
} else {
auto_reference_t ref = { (vm_address_t)block, (vm_address_t)reference, 0 };
_callback((auto_zone_t *)_zone, _callback_ctx, ref);
}
}
}
MemoryScanner::check_block(reference, block);
}
void scan_range_from_thread(Range &range, Thread &thread) {
_thread = &thread;
_thread_range = range;
MemoryScanner::scan_range_from_thread(range, thread);
_thread = NULL;
}
void scan_range_from_registers(Range &range, Thread &thread, int first_register) {
_thread = &thread;
_first_register = first_register;
_thread_range = range;
MemoryScanner::scan_range_from_registers(range, thread, first_register);
_thread = NULL;
_first_register = -1;
}
};
};
#endif // __AUTO_INTERFACE__