/**************************************************************************
*
- * Copyright 2011 Jose Fonseca
+ * Copyright 2011-2012 Jose Fonseca
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
#ifndef _RETRACE_HPP_
#define _RETRACE_HPP_
+#include <assert.h>
#include <string.h>
+#include <stdint.h>
#include <list>
#include <map>
};
+/**
+ * Similar to alloca(), but implemented with malloc.
+ */
+class ScopedAllocator
+{
+private:
+ uintptr_t next;
+
+public:
+ ScopedAllocator() :
+ next(0) {
+ }
+
+ inline void *
+ alloc(size_t size) {
+ if (!size) {
+ return NULL;
+ }
+
+ uintptr_t * buf = static_cast<uintptr_t *>(malloc(sizeof(uintptr_t) + size));
+ if (!buf) {
+ return NULL;
+ }
+
+ *buf = next;
+ next = reinterpret_cast<uintptr_t>(buf);
+ assert((next & 1) == 0);
+
+ return static_cast<void *>(&buf[1]);
+ }
+
+ template< class T >
+ inline T *
+ alloc(size_t n = 1) {
+ return static_cast<T *>(alloc(sizeof(T) * n));
+ }
+
+ /**
+ * Allocate an array with the same dimensions as the specified value.
+ */
+ template< class T >
+ inline T *
+ alloc(const trace::Value *value) {
+ const trace::Array *array = dynamic_cast<const trace::Array *>(value);
+ if (array) {
+ return alloc<T>(array->size());
+ }
+ const trace::Null *null = dynamic_cast<const trace::Null *>(value);
+ if (null) {
+ return NULL;
+ }
+ assert(0);
+ return NULL;
+ }
+
+ /**
+ * Prevent this pointer from being automatically freed.
+ */
+ template< class T >
+ inline void
+ bind(T *ptr) {
+ if (ptr) {
+ reinterpret_cast<uintptr_t *>(ptr)[-1] |= 1;
+ }
+ }
+
+ inline
+ ~ScopedAllocator() {
+ while (next) {
+ uintptr_t temp = *reinterpret_cast<uintptr_t *>(next);
+
+ bool bind = temp & 1;
+ temp &= ~1;
+
+ if (!bind) {
+ free(reinterpret_cast<void *>(next));
+ }
+
+ next = temp;
+ }
+ }
+};
+
+
void
addRegion(unsigned long long address, void *buffer, unsigned long long size);