--- /home/rusty/devel/cvs/talloc/talloc.h	2005-12-31 15:30:25.000000000 +1100
+++ talloc.h	2006-01-17 09:44:41.000000000 +1100
@@ -115,6 +115,7 @@
 off_t talloc_total_size(const void *ptr);
 off_t talloc_total_blocks(const void *ptr);
 void talloc_report_full(const void *ptr, FILE *f);
+void talloc_report_dot(const void *ptr, FILE *f);
 void talloc_report(const void *ptr, FILE *f);
 void talloc_enable_null_tracking(void);
 void talloc_enable_leak_report(void);
--- /home/rusty/devel/cvs/talloc/talloc.c	2005-12-31 15:30:25.000000000 +1100
+++ talloc.c	2006-01-19 18:27:41.000000000 +1100
@@ -832,6 +868,80 @@
 	fflush(f);
 }
 
+static unsigned int hash_name(const char *name)
+{
+	unsigned value;	/* Used to compute the hash value.  */
+	unsigned   i;	/* Used to cycle through random values. */
+
+	/* Set the initial value from the key size. */
+	for (value = 0x238F13AF * strlen(name), i=0; i < strlen(name); i++)
+		value = (value + (name[i] << (i*5 % 24)));
+
+	return (1103515243 * value + 12345);
+}
+
+static unsigned int hash_chunk(struct talloc_chunk *c,
+			       struct talloc_chunk *parent)
+{
+	if (parent)
+		return hash_name(c->name) ^ hash_name(parent->name);
+	return hash_name(c->name);
+}
+
+static void talloc_report_dot_node(struct talloc_chunk *tc,
+				   struct talloc_chunk *parent,
+				   FILE *f)
+{
+	struct talloc_chunk *c;
+	const void *ptr = TC_PTR_FROM_CHUNK(tc);
+	unsigned hash = hash_chunk(tc, parent);
+
+	if (tc->flags & TALLOC_FLAG_LOOP)
+		return;
+
+	fprintf(f, "\tn%u [label=\"%.*s%s\\n(%zu bytes)\"]\n",
+		hash,
+		strlen(talloc_get_name(ptr)) > 20 ? 20 : 
+		strlen(talloc_get_name(ptr)),
+		ptr == null_context ? "NULL" : talloc_get_name(ptr),
+		strlen(talloc_get_name(ptr)) > 20 ? "..." : "",
+		talloc_chunk_from_ptr(ptr)->size);
+
+	tc->flags |= TALLOC_FLAG_LOOP;
+
+	for (c = tc->child; c; c = c->next) {
+		if (c->name == TALLOC_MAGIC_REFERENCE) {
+			struct talloc_reference_handle *handle =
+				TC_PTR_FROM_CHUNK(c);
+			fprintf(f, "\tn%u -> n%u [color=red,weight=0]\n",
+				hash,
+				hash_chunk(talloc_chunk_from_ptr(handle->ptr),
+					   tc));
+		} else {
+			fprintf(f, "\tn%u -> n%u\n",
+				hash, hash_chunk(c, tc));
+			talloc_report_dot_node(c, tc, f);
+		}
+	}
+
+	tc->flags &= ~TALLOC_FLAG_LOOP;
+}
+
+void talloc_report_dot(const void *ptr, FILE *f)
+{
+	if (ptr == NULL)
+		ptr = null_context;
+
+	if (ptr == NULL)
+		return;
+
+	fprintf(f, "digraph talloc {\n");
+	talloc_report_dot_node(talloc_chunk_from_ptr(ptr), NULL, f);
+	fprintf(f, "}\n");
+
+	fflush(f);
+}
+
 /*
   report on memory usage by all children of a pointer
 */
