node/lib/metasm/samples/dbg-plugins/heapscan/heapscan.rb
def each_heap
		if not @cp.toplevel.struct['malloc_state']
			@cp.parse <<EOS
// TODO autotune these 2 defines..
#define THREAD_STATS 0
//#define PER_THREAD

#define NFASTBINS 10
#define NBINS 128
#define BINMAPSIZE (NBINS/32)

struct malloc_state {
	int mutex;
	int flags;
#if THREAD_STATS
	long stat_lock_direct, stat_lock_loop, stat_lock_wait;
#endif
	void *fastbinsY[NFASTBINS];
	void *top;
	void *last_remainder;
	void *bins[NBINS * 2 - 2];	// *2: double-linked list
	unsigned int binmap[BINMAPSIZE];
	struct malloc_state *next;
#ifdef PER_THREAD
	struct malloc_state *next_free;
#endif
	uintptr_t system_mem;	// XXX int32?
	uintptr_t max_system_mem;
};

struct heap_info {
	struct malloc_state *ar_ptr; // Arena for this heap.
	struct _heap_info *prev; // Previous heap.
	uintptr_t size;   // Current size in bytes. XXX int32?
	uintptr_t mprotect_size; // Size in bytes that has been mprotected
};
EOS
		end

		ptr = @main_arena_ptr
		loop do
			ar = @cp.decode_c_struct('malloc_state', @dbg.memory, ptr)
			if ptr == @main_arena_ptr
				# main arena: find start from top.end - system_mem
				toplen = chunkdata(ar.top)[1] & -8
				yield ar.top + toplen - ar.system_mem, ar.system_mem, ar
			else
				# non-main arena: find heap_info for top, follow list
				iptr = ar.top & -0x10_0000	# XXX
				while iptr
					hi = @cp.decode_c_struct('heap_info', @dbg.memory, iptr)
					off = hi.sizeof
					off += ar.sizeof if iptr+off == hi.ar_ptr
					yield iptr+off, hi.size-off, ar

					iptr = hi.prev
				end
			end

			ptr = ar.next
			break if ptr == @main_arena_ptr
		end
	end
# find all chunks in the memory address space
find all chunks in the memory address space
find all chunks in the memory address space
def each_heap
		if not @cp.toplevel.struct['malloc_state']
			@cp.parse <<EOS
// TODO autotune these 2 defines..
#define THREAD_STATS 0
//#define PER_THREAD
#define NFASTBINS 10
#define NBINS 128
#define BINMAPSIZE (NBINS/32)
struct malloc_state {
	int mutex;
	int flags;
#if THREAD_STATS
	long stat_lock_direct, stat_lock_loop, stat_lock_wait;
#endif
	void *fastbinsY[NFASTBINS];
	void *top;
	void *last_remainder;
	void *bins[NBINS * 2 - 2];	// *2: double-linked list
	unsigned int binmap[BINMAPSIZE];
	struct malloc_state *next;
#ifdef PER_THREAD
	struct malloc_state *next_free;
#endif
	uintptr_t system_mem;	// XXX int32?
	uintptr_t max_system_mem;
};
struct heap_info {
	struct malloc_state *ar_ptr; // Arena for this heap.
	struct _heap_info *prev; // Previous heap.
	uintptr_t size;   // Current size in bytes. XXX int32?
	uintptr_t mprotect_size; // Size in bytes that has been mprotected
};
EOS
		end
		ptr = @main_arena_ptr
		loop do
			ar = @cp.decode_c_struct('malloc_state', @dbg.memory, ptr)
			if ptr == @main_arena_ptr
				toplen = chunkdata(ar.top)[1] & -8
				yield ar.top + toplen - ar.system_mem, ar.system_mem, ar
			else
				iptr = ar.top & -0x10_0000	
				while iptr
					hi = @cp.decode_c_struct('heap_info', @dbg.memory, iptr)
					off = hi.sizeof
					off += ar.sizeof if iptr+off == hi.ar_ptr
					yield iptr+off, hi.size-off, ar
					iptr = hi.prev
				end
			end
			ptr = ar.next
			break if ptr == @main_arena_ptr
		end
	end
def each_heap if not @cp . toplevel . struct [ 'malloc_state' ] @cp . parse <<EOS 
// TODO autotune these 2 defines..
#define THREAD_STATS 0
//#define PER_THREAD

#define NFASTBINS 10
#define NBINS 128
#define BINMAPSIZE (NBINS/32)

struct malloc_state {
	int mutex;
	int flags;
#if THREAD_STATS
	long stat_lock_direct, stat_lock_loop, stat_lock_wait;
#endif
	void *fastbinsY[NFASTBINS];
	void *top;
	void *last_remainder;
	void *bins[NBINS * 2 - 2];	// *2: double-linked list
	unsigned int binmap[BINMAPSIZE];
	struct malloc_state *next;
#ifdef PER_THREAD
	struct malloc_state *next_free;
#endif
	uintptr_t system_mem;	// XXX int32?
	uintptr_t max_system_mem;
};

struct heap_info {
	struct malloc_state *ar_ptr; // Arena for this heap.
	struct _heap_info *prev; // Previous heap.
	uintptr_t size;   // Current size in bytes. XXX int32?
	uintptr_t mprotect_size; // Size in bytes that has been mprotected
};
 EOS end ptr = @main_arena_ptr loop do ar = @cp . decode_c_struct ( 'malloc_state' , @dbg . memory , ptr ) if ptr == @main_arena_ptr toplen = chunkdata ( ar . top ) [ 1 ] & - 8 yield ar . top + toplen - ar . system_mem , ar . system_mem , ar else iptr = ar . top & - 0x10_0000 while iptr hi = @cp . decode_c_struct ( 'heap_info' , @dbg . memory , iptr ) off = hi . sizeof off += ar . sizeof if iptr + off == hi . ar_ptr yield iptr + off , hi . size - off , ar iptr = hi . prev end end ptr = ar . next break if ptr == @main_arena_ptr end end
find all chunks in the memory address space
find all chunks in the memory address space
# main arena: find start from top.end - system_mem # non-main arena: find heap_info for top, follow list # XXX