diff --git a/src/dmalloc.h b/src/dmalloc.h
index e88eafa38d90273087c9d6f37aa56e859578d443..15e3c699df64ca2c1a32fba7b693ea40f2ac5127 100644
--- a/src/dmalloc.h
+++ b/src/dmalloc.h
@@ -1,5 +1,5 @@
 /*
- * $Id: dmalloc.h,v 1.23 2000/03/27 06:34:05 hubbe Exp $
+ * $Id: dmalloc.h,v 1.24 2000/04/08 02:01:08 hubbe Exp $
  */
 
 extern char *debug_xalloc(long);
@@ -35,7 +35,8 @@ void search_all_memheaders_for_references(void);
 
 /* Beware! names of named memory regions are never ever freed!! /Hubbe */
 void *debug_malloc_name(void *p, char *fn, int line);
-void debug_malloc_copy_names(void *p, void *p2);
+int debug_malloc_copy_names(void *p, void *p2);
+char *dmalloc_find_name(void *p);
 
 /* glibc 2.1 defines this as a macro. */
 #ifdef strdup
@@ -63,6 +64,23 @@ void dmalloc_accept_leak(void *);
 #define dmalloc_touch_fd(X) debug_malloc_touch_fd((X),DMALLOC_LOCATION())
 #define dmalloc_register_fd(X) debug_malloc_register_fd((X),DMALLOC_LOCATION())
 #define dmalloc_close_fd(X) debug_malloc_close_fd((X),DMALLOC_LOCATION())
+
+/* Beware, these do not exist without DMALLOC */
+struct memory_map;
+void dmalloc_set_mmap(void *ptr, struct memory_map *m);
+void dmalloc_set_mmap_template(void *ptr, struct memory_map *m);
+void dmalloc_set_mmap_from_template(void *p, void *p2);
+void dmalloc_describe_location(void *p, int offset);
+struct memory_map *dmalloc_alloc_mmap(char *name, int line);
+void dmalloc_add_mmap_entry(struct memory_map *m,
+			    char *name,
+			    int offset,
+			    int size,
+			    int count,
+			    struct memory_map *recur,
+			    int recur_offset);
+
+
 #else
 #define dmalloc_touch_fd(X) (X)
 #define dmalloc_register_fd(X) (X)
@@ -85,6 +103,7 @@ void dmalloc_accept_leak(void *);
 #define dmalloc_unregister(X,Y)
 #define debug_free(X,Y,Z) free((X))
 #define debug_malloc_name(P,FN,LINE)
-#define debug_malloc_copy_names(p,p2)
+#define debug_malloc_copy_names(p,p2) 0
 #define search_all_memheaders_for_references()
+#define dmalloc_find_name(X) "unknown (no dmalloc)"
 #endif
diff --git a/src/encode.c b/src/encode.c
index 66b52b9781917e90e03285064df978cfc78c0a25..4b8797c78aefd9501056aa2f27c392ddf0662c70 100644
--- a/src/encode.c
+++ b/src/encode.c
@@ -25,7 +25,7 @@
 #include "version.h"
 #include "bignum.h"
 
-RCSID("$Id: encode.c,v 1.57 2000/04/06 09:03:29 hubbe Exp $");
+RCSID("$Id: encode.c,v 1.58 2000/04/08 02:01:08 hubbe Exp $");
 
 /* #define ENCODE_DEBUG */
 
@@ -573,7 +573,7 @@ static void encode_value2(struct svalue *val, struct encode_data *data)
       {
 	INT32 e;
 	struct program *p=val->u.program;
-	if(p->init || p->exit || p->gc_marked || p->gc_check ||
+	if(p->init || p->exit || p->gc_marked || p->gc_check_func ||
 	   (p->flags & PROGRAM_HAS_C_METHODS))
 	  error("Cannot encode C programs.\n");
 	code_entry(type_to_tag(val->type), 1,data);
diff --git a/src/gc.c b/src/gc.c
index c7e124730ad7813843107666f6f20a03ee4accde..1e8f63c72b9d40e4e9ba77409d07848c3942f953 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -29,7 +29,7 @@ struct callback *gc_evaluator_callback=0;
 
 #include "block_alloc.h"
 
-RCSID("$Id: gc.c,v 1.52 2000/03/07 23:51:29 hubbe Exp $");
+RCSID("$Id: gc.c,v 1.53 2000/04/08 02:01:08 hubbe Exp $");
 
 /* Run garbage collect approximate every time we have
  * 20 percent of all arrays, objects and programs is
@@ -131,23 +131,77 @@ void *gc_svalue_location=0;
 
 void describe_location(void *memblock, TYPE_T type, void *location)
 {
+  struct program *p;
   if(!location) return;
-  fprintf(stderr,"**Location of (short) svalue: %p\n",location);
+/*  fprintf(stderr,"**Location of (short) svalue: %p\n",location); */
 
+  if(type==T_UNKNOWN) type=attempt_to_identify(memblock);
+  fprintf(stderr,"  <from %s %p offset %ld>\n",
+	  get_name_of_type(type),
+	  memblock,
+	  ((long)location - (long)memblock));
+	  
   switch(type)
   {
+    case T_UNKNOWN:
+      for(p=first_program;p;p=p->next)
+      {
+	if(memblock == (void *)p->program)
+	{
+	  fprintf(stderr,"    **In memory block for program at %p\n",p);
+	  memblock=p;
+	  type=T_PROGRAM;
+	  goto describe_program_location;
+	}
+      }
+      break;
+      
     case T_PROGRAM:
+  describe_program_location:
     {
+      long e;
       struct program *p=(struct program *)memblock;
       char *ptr=(char *)location;
-      if(ptr >= (char *)p->inherits  && ptr<(char*)(p->inherits+p->num_inherits))
-	fprintf(stderr,"**In inherit block.\n");
 
-      if(ptr >= (char *)p->strings  && ptr<(char*)(p->strings+p->num_strings))
-	fprintf(stderr,"**In string block.\n");
+      if(location == (void *)&p->prev)
+	fprintf(stderr,"    **In p->prev\n");
+
+      if(location == (void *)&p->next)
+	fprintf(stderr,"    **In p->next\n");
+
+      if(ptr >= (char *)p->inherits  && ptr<(char*)(p->inherits+p->num_inherits)) 
+      {
+	e=((long)ptr - (long)(p->inherits)) / sizeof(struct inherit);
+	fprintf(stderr,"    **In p->inherits[%ld] (%s)\n",
+		e,
+		p->inherits[e].name ? p->inherits[e].name->str : "no name");
+	return;
+      }
+
+      if(ptr >= (char *)p->constants  && ptr<(char*)(p->constants+p->num_constants))
+      {
+	e=((long)ptr - (long)(p->constants)) / sizeof(struct program_constant);
+	fprintf(stderr,"    **In p->constants[%ld] (%s)\n",
+		e,
+		p->constants[e].name ? p->constants[e].name->str : "no name");
+	return;
+      }
+
 
       if(ptr >= (char *)p->identifiers  && ptr<(char*)(p->identifiers+p->num_identifiers))
-	fprintf(stderr,"**In identifier block.\n");
+      {
+	e=((long)ptr - (long)(p->identifiers)) / sizeof(struct identifier);
+	fprintf(stderr,"    **In p->identifiers[%ld] (%s)\n",
+		e,
+		p->identifiers[e].name ? p->constants[e].name->str : "no name");
+	return;
+      }
+
+#define FOO(NTYP,TYP,NAME) \
+    if(location == (void *)&p->NAME) fprintf(stderr,"    **In p->" #NAME "\n"); \
+    if(ptr >= (char *)p->NAME  && ptr<(char*)(p->NAME+p->PIKE_CONCAT(num_,NAME))) \
+      fprintf(stderr,"    **In p->" #NAME "[%ld]\n",((long)ptr - (long)(p->NAME)) / sizeof(TYP));
+#include "program_areas.h"
       
       return;
     }
@@ -155,12 +209,28 @@ void describe_location(void *memblock, TYPE_T type, void *location)
     case T_OBJECT:
     {
       struct object *o=(struct object *)memblock;
-      if(o->prog)
+      struct program *p;
+
+      if(location == (void *)&o->parent) fprintf(stderr,"    **In o->parent\n");
+      if(location == (void *)&o->prog)  fprintf(stderr,"    **In o->prog\n");
+      if(location == (void *)&o->next)  fprintf(stderr,"    **In o->next\n");
+      if(location == (void *)&o->prev)  fprintf(stderr,"    **In o->prev\n");
+
+      p=o->prog;
+
+      if(!o->prog)
+      {
+	p=id_to_program(o->program_id);
+	if(p)
+	  fprintf(stderr,"    **(We are lucky, found program for destructed object)\n");
+      }
+
+      if(p)
       {
 	INT32 e,d;
-	for(e=0;e<(INT32)o->prog->num_inherits;e++)
+	for(e=0;e<(INT32)p->num_inherits;e++)
 	{
-	  struct inherit tmp=o->prog->inherits[e];
+	  struct inherit tmp=p->inherits[e];
 	  char *base=o->storage + tmp.storage_offset;
 	  
 	  for(d=0;d<(INT32)tmp.prog->num_identifiers;d++)
@@ -170,9 +240,19 @@ void describe_location(void *memblock, TYPE_T type, void *location)
 	    
 	    if(location == (void *)(base + id->func.offset))
 	    {
-	      fprintf(stderr,"**In variable %s\n",id->name->str);
+	      fprintf(stderr,"    **In variable %s\n",id->name->str);
 	    }
 	  }
+
+	  if((char *)location >= base && (char *)location <= base +
+	     ( tmp.prog->storage_needed - tmp.prog->inherits[0].storage_offset ))
+	  {
+	    fprintf(stderr,"    **In storage for inherit %d",e);
+	    if(tmp.name)
+	      fprintf(stderr," (%s)",tmp.name->str);
+	    fprintf(stderr,"\n");
+	  }
+	     
 	}
       }
       return;
@@ -182,7 +262,7 @@ void describe_location(void *memblock, TYPE_T type, void *location)
     {
       struct array *a=(struct array *)memblock;
       struct svalue *s=(struct svalue *)location;
-      fprintf(stderr,"**In index %ld\n",(long)(s-ITEM(a)));
+      fprintf(stderr,"    **In index %ld\n",(long)(s-ITEM(a)));
       return;
     }
   }
@@ -252,6 +332,8 @@ void low_describe_something(void *a, int t, int dm)
     case T_OBJECT:
       p=((struct object *)a)->prog;
       fprintf(stderr,"**Parent identifier: %d\n",((struct object *)a)->parent_identifier);
+      fprintf(stderr,"**Program id: %ld\n",((struct object *)a)->program_id);
+
       if( ((struct object *)a)->parent)
       {
 	fprintf(stderr,"**Describing object's parent:\n");
@@ -262,7 +344,9 @@ void low_describe_something(void *a, int t, int dm)
       if(!p)
       {
 	fprintf(stderr,"**The object is destructed.\n");
-	break;
+	p=id_to_program(((struct object *)a)->program_id);
+
+	if(!p) break;
       }
       fprintf(stderr,"**Attempting to describe program object was instantiated from:\n");
       
@@ -313,6 +397,9 @@ void low_describe_something(void *a, int t, int dm)
 
 	fprintf(stderr,"**num inherits: %d\n",p->num_inherits);
       }
+#define FOO(NUMTYPE,TYPE,NAME) \
+      fprintf(stderr,"* " #NAME " %p[%d]\n",p->NAME,p->PIKE_CONCAT(num_,NAME));
+#include "program_areas.h"
 
       break;
     }
@@ -406,7 +493,13 @@ void debug_describe_svalue(struct svalue *s)
       }else{
 	if(!s->u.object->prog)
 	{
-	  fprintf(stderr,"    Function in destructed object.\n");
+	  struct program *p=id_to_program(s->u.object->program_id);
+	  if(p)
+	  {
+	    fprintf(stderr,"    Function (destructed) name: %s\n",ID_FROM_INT(p,s->subtype)->name->str);
+	  }else{
+	    fprintf(stderr,"    Function in destructed object.\n");
+	  }
 	}else{
 	  fprintf(stderr,"    Function name: %s\n",ID_FROM_INT(s->u.object->prog,s->subtype)->name->str);
 	}
@@ -417,7 +510,7 @@ void debug_describe_svalue(struct svalue *s)
 
 #endif
 
-INT32 gc_check(void *a)
+INT32 real_gc_check(void *a)
 {
 #ifdef PIKE_DEBUG
   if(check_for)
diff --git a/src/gc.h b/src/gc.h
index 988926ad759e4efa2f23f6598640f74b96a0dc12..718a25125dc6aefad5a1306a4c496f743d6d2b65 100644
--- a/src/gc.h
+++ b/src/gc.h
@@ -1,5 +1,5 @@
 /*
- * $Id: gc.h,v 1.23 2000/02/02 00:38:27 hubbe Exp $
+ * $Id: gc.h,v 1.24 2000/04/08 02:01:08 hubbe Exp $
  */
 #ifndef GC_H
 #define GC_H
@@ -55,7 +55,7 @@ int debug_gc_check(void *x, TYPE_T t, void *data);
 void describe_something(void *a, int t, int dm);
 void describe(void *x);
 void debug_describe_svalue(struct svalue *s);
-INT32 gc_check(void *a);
+INT32 real_gc_check(void *a);
 void locate_references(void *a);
 int debug_gc_is_referenced(void *a);
 int gc_external_mark(void *a);
@@ -65,13 +65,18 @@ void do_gc(void);
 void f__gc_status(INT32 args);
 /* Prototypes end here */
 
+#define gc_check_svalues(S,N) real_gc_check_svalues(debug_malloc_pass(S),N)
+#define gc_check_short_svalue(S,N) real_gc_check_short_svalue(debug_malloc_pass(S),N)
+#define gc_xmark_svalues(S,N) real_gc_xmark_svalues(debug_malloc_pass(S),N)
+#define gc_check(VP) real_gc_check(debug_malloc_pass(VP))
+
 #ifdef PIKE_DEBUG
 #define GC_FREE() do { num_objects-- ; if(num_objects < 0) fatal("Panic!! less than zero objects!\n"); }while(0)
 #else
-#define debug_gc_check_svalues(S,N,T,V) gc_check_svalues(S,N)
-#define debug_gc_check_short_svalue(S,N,T,V) gc_check_short_svalue(S,N)
-#define debug_gc_xmark_svalue(S,N,X) gc_xmark_svalue(S,N)
-#define debug_gc_check(VP,T,V) gc_check(VP)
+#define debug_gc_check_svalues(S,N,T,V) gc_check_svalues((S),N)
+#define debug_gc_check_short_svalue(S,N,T,V) gc_check_short_svalue((S),N)
+#define debug_gc_xmark_svalues(S,N,X) gc_xmark_svalues((S),N)
+#define debug_gc_check(VP,T,V) gc_check((VP))
 #define GC_FREE() do { num_objects-- ; }while(0)
 #endif
 
@@ -84,8 +89,8 @@ void f__gc_status(INT32 args);
 
 
 #ifdef PIKE_DEBUG
-#define gc_is_referenced debug_gc_is_referenced
-#define gc_do_free debug_gc_do_free
+#define gc_is_referenced(X) debug_gc_is_referenced(debug_malloc_pass(X))
+#define gc_do_free(X) debug_gc_do_free(debug_malloc_pass(X))
 #else
 #define gc_is_referenced(X) (get_marker(X)->refs < *(INT32 *)(X))
 #define gc_do_free(X) ( ! (get_marker(X)->flags & GC_REFERENCED ) )
diff --git a/src/interpret.c b/src/interpret.c
index 9cd971ad3de071578f25583889677030afd47759..cf3253e546db9ace468995f96c771772de20edbe 100644
--- a/src/interpret.c
+++ b/src/interpret.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: interpret.c,v 1.138 2000/04/04 00:26:09 hubbe Exp $");
+RCSID("$Id: interpret.c,v 1.139 2000/04/08 02:01:08 hubbe Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -620,8 +620,11 @@ static void do_trace_call(INT32 args)
   DO_IF_DMALLOC(					\
     X->context.prog=0;					\
     X->context.parent=0;				\
+    X->context.name=0;					\
     X->scope=0;						\
+    X->current_object=0;				\
     X->malloced_locals=0;				\
+    X->expendible=0;					\
     X->locals=0;					\
  )							\
 }while(0)
diff --git a/src/interpret.h b/src/interpret.h
index 90bf599eb7fb98c7de9059b1dbb38087d06e2631..d943d8636723023a309037094e1cdef11efd1763 100644
--- a/src/interpret.h
+++ b/src/interpret.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: interpret.h,v 1.39 2000/03/28 18:00:00 grubba Exp $
+ * $Id: interpret.h,v 1.40 2000/04/08 02:01:08 hubbe Exp $
  */
 #ifndef INTERPRET_H
 #define INTERPRET_H
@@ -20,7 +20,7 @@ struct pike_frame
 {
   INT32 refs; /* must be first */
   INT32 args;
-  INT16 fun;
+  unsigned INT16 fun;
   INT16 num_locals;
   INT16 num_args;
   INT16 malloced_locals;
diff --git a/src/language.yacc b/src/language.yacc
index e1dea41bc8814d205d6d08fd1ebaf9006ba6560a..17a7d2488b44fa395f9ca65244d0d33de4591e0a 100644
--- a/src/language.yacc
+++ b/src/language.yacc
@@ -188,7 +188,7 @@
 /* This is the grammar definition of Pike. */
 
 #include "global.h"
-RCSID("$Id: language.yacc,v 1.178 2000/04/07 19:59:40 grubba Exp $");
+RCSID("$Id: language.yacc,v 1.179 2000/04/08 02:01:08 hubbe Exp $");
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
@@ -1667,12 +1667,6 @@ local_function: F_IDENTIFIER push_compiler_frame1 func_args
     low_add_local_name(compiler_frame->previous,
 		       $1->u.sval.u.string, type, n);
 
-#ifdef LAMBDA_DEBUG
-    fprintf(stderr,"FNORD: ");
-    simple_describe_type(type);
-    fprintf(stderr,"\n");
-#endif /* LAMBDA_DEBUG */
-
     $<number>$=id;
     free_string(name);
   }
diff --git a/src/object.c b/src/object.c
index 42dcc63bccd5cb42468bd3e6e718979f6fcd50b6..62d8313c46e05ca7aaad09decedede27c7e0acd1 100644
--- a/src/object.c
+++ b/src/object.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: object.c,v 1.98 2000/04/06 21:07:58 hubbe Exp $");
+RCSID("$Id: object.c,v 1.99 2000/04/08 02:01:09 hubbe Exp $");
 #include "object.h"
 #include "dynamic_buffer.h"
 #include "interpret.h"
@@ -88,7 +88,28 @@ struct object *low_clone(struct program *p)
 
   o=(struct object *)xalloc( ((long)(((struct object *)0)->storage))+p->storage_needed);
 
-  debug_malloc_copy_names(o, p);
+#ifdef DEBUG_MALLOC
+  if(!debug_malloc_copy_names(o, p)) 
+  {
+    /* Didn't find a given name, revert to ad-hoc method */
+    char *tmp;
+    INT32 line,pos;
+
+    for(pos=0;pos<100;pos++)
+    {
+      tmp=get_line(p->program+pos, p, &line);
+      if(tmp && line)
+      {
+	debug_malloc_name(o, tmp, line);
+	break;
+      }
+      if(pos+1>=(long)p->num_program)
+	break;
+    }
+    
+  }
+  dmalloc_set_mmap_from_template(o,p);
+#endif
 
   o->prog=p;
   add_ref(p);
@@ -100,6 +121,11 @@ struct object *low_clone(struct program *p)
     first_object->prev=o;
   first_object=o;
   o->refs=1;
+
+#ifdef PIKE_DEBUG
+  o->program_id=p->id;
+#endif
+
   INITIALIZE_PROT(o);
   return o;
 }
@@ -481,6 +507,7 @@ void low_destruct(struct object *o,int do_free)
 	u=(union anything *)(pike_frame->current_storage +
 			     pike_frame->context.prog->identifiers[d].func.offset);
 	free_short_svalue(u, pike_frame->context.prog->identifiers[d].run_time_type);
+	DO_IF_DMALLOC(u->refs=(void *)-1);
       }
     }
   }
@@ -1190,8 +1217,8 @@ void gc_check_all_objects(void)
 	int q;
 	SET_FRAME_CONTEXT(p->inherits[e]);
 	
-	if(pike_frame->context.prog->gc_check)
-	  pike_frame->context.prog->gc_check(o);
+	if(pike_frame->context.prog->gc_check_func)
+	  pike_frame->context.prog->gc_check_func(o);
 
 	for(q=0;q<(int)pike_frame->context.prog->num_variable_index;q++)
 	{
diff --git a/src/object.h b/src/object.h
index c216ea74d7bc30df41ff7ce50c221bc085f1b353..d13a426d4c2119a239765597feb2025a617507d5 100644
--- a/src/object.h
+++ b/src/object.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: object.h,v 1.39 2000/03/28 17:59:14 grubba Exp $
+ * $Id: object.h,v 1.40 2000/04/08 02:01:09 hubbe Exp $
  */
 #ifndef OBJECT_H
 #define OBJECT_H
@@ -29,6 +29,9 @@ struct object
   INT16 parent_identifier;
   struct object *next;
   struct object *prev;
+#if PIKE_DEBUG
+  long program_id;
+#endif
   char storage[1];
 };
 
diff --git a/src/pike_memory.c b/src/pike_memory.c
index c1299a702dca5e70dca6556ed839fb510063688d..10e88b1e4402c366a25b8fa2b66ea9f790379599 100644
--- a/src/pike_memory.c
+++ b/src/pike_memory.c
@@ -10,7 +10,7 @@
 #include "pike_macros.h"
 #include "gc.h"
 
-RCSID("$Id: pike_memory.c,v 1.62 2000/04/06 21:00:20 hubbe Exp $");
+RCSID("$Id: pike_memory.c,v 1.63 2000/04/08 02:01:09 hubbe Exp $");
 
 /* strdup() is used by several modules, so let's provide it */
 #ifndef HAVE_STRDUP
@@ -1416,8 +1416,9 @@ void *__wrap_strdup(const char *s)
 #endif
 
 
-void dump_memhdr_locations(struct memhdr *from,
-			   struct memhdr *notfrom)
+void low_dump_memhdr_locations(struct memhdr *from,
+			   struct memhdr *notfrom,
+			   int indent)
 {
   struct memloc *l;
   if(!from) return;
@@ -1430,16 +1431,29 @@ void dump_memhdr_locations(struct memhdr *from,
     if(notfrom && find_location(notfrom, l->location))
       continue;
 
-    fprintf(stderr,"   %s %s (%d times) %s\n",
+    
+    fprintf(stderr,"%*s %s %s (%d times) %s\n",
+	    indent,"",
 	    LOCATION_IS_DYNAMIC(l->location) ? "-->" : "***",
 	    LOCATION_NAME(l->location),
 	    l->times,
 	    find_location(&no_leak_memlocs, l->location) ? "" :
 	    ( from->flags & MEM_REFERENCED ? "*" : "!*!")
 	    );
+
+    /* Allow linked memhdrs */
+/*    dump_memhdr_locations(my_find_memhdr(l,0),notfrom,indent+2); */
   }
 }
 
+void dump_memhdr_locations(struct memhdr *from,
+			   struct memhdr *notfrom)
+{
+  low_dump_memhdr_locations(from,notfrom, 2);
+}
+
+static void low_dmalloc_describe_location(struct memhdr *mh, int offset);
+
 static void find_references_to(void *block)
 {
   unsigned long h;
@@ -1461,7 +1475,11 @@ static void find_references_to(void *block)
 	  {
 	    if(p[e] == block)
 	    {
-	      fprintf(stderr,"  <from %p word %d>\n",p,e);
+/*	      fprintf(stderr,"  <from %p word %d>\n",p,e); */
+	      describe_location(p,T_UNKNOWN,p+e);
+
+	      low_dmalloc_describe_location(m, e * sizeof(void *));
+
 	      m->flags |= MEM_WARN_ON_FREE;
 	    }
 	  }
@@ -1722,7 +1740,7 @@ struct dmalloc_string
 
 static struct dmalloc_string *dstrhash[DSTRHSIZE];
 
-LOCATION dynamic_location(char *file, int line)
+static LOCATION low_dynamic_location(char type, char *file, int line)
 {
   struct dmalloc_string **prev, *str;
   int len=strlen(file);
@@ -1736,7 +1754,7 @@ LOCATION dynamic_location(char *file, int line)
     if(hval == str->hval &&
        str->str[len+1]==':' &&
        !MEMCMP(str->str+1, file, len) &&
-       str->str[0]=='D' &&
+       str->str[0]==type &&
        atoi(str->str+len+2) == line)
     {
       *prev=str->next;
@@ -1749,7 +1767,7 @@ LOCATION dynamic_location(char *file, int line)
   if(!str)
   {
     str=malloc( sizeof(struct dmalloc_string) + len + 20);
-    sprintf(str->str, "D%s:%d", file, line);
+    sprintf(str->str, "%c%s:%d", type, file, line);
     str->hval=hval;
     str->next=dstrhash[h];
     dstrhash[h]=str;
@@ -1760,6 +1778,11 @@ LOCATION dynamic_location(char *file, int line)
   return str->str;
 }
 
+LOCATION dynamic_location(char *file, int line)
+{
+  return low_dynamic_location('D',file,line);
+}
+
 
 void * debug_malloc_name(void *p,char *file, int line)
 {
@@ -1783,8 +1806,9 @@ void * debug_malloc_name(void *p,char *file, int line)
  * one pointer to another. Used by clone() to copy
  * the name(s) of the program.
  */
-void debug_malloc_copy_names(void *p, void *p2)
+int debug_malloc_copy_names(void *p, void *p2)
 {
+  int names=0;
   if(p)
   {
     struct memhdr *mh,*from;
@@ -1796,12 +1820,42 @@ void debug_malloc_copy_names(void *p, void *p2)
       for(l=from->locations;l;l=l->next)
       {
 	if(LOCATION_IS_DYNAMIC(l->location))
+	{
 	  add_location(mh, l->location);
+	  names++;
+	}
+      }
+    }
+
+    mt_unlock(&debug_malloc_mutex);
+  }
+  return names;
+}
+
+char *dmalloc_find_name(void *p)
+{
+  char *name=0;
+  if(p)
+  {
+    struct memhdr *mh;
+    mt_lock(&debug_malloc_mutex);
+
+    if((mh=my_find_memhdr(p,0)))
+    {
+      struct memloc *l;
+      for(l=mh->locations;l;l=l->next)
+      {
+	if(LOCATION_IS_DYNAMIC(l->location))
+	{
+	  name=LOCATION_NAME(l->location);
+	  break;
+	}
       }
     }
 
     mt_unlock(&debug_malloc_mutex);
   }
+  return name;
 }
 
 int debug_malloc_touch_fd(int fd, LOCATION location)
@@ -1842,4 +1896,153 @@ void reset_debug_malloc(void)
   }
 }
 
+struct memory_map
+{
+  char name[128];
+  struct memory_map *next;
+  struct memory_map_entry *entries;
+};
+
+struct memory_map_entry
+{
+  struct memory_map_entry *next;
+  char name[128];
+  int offset;
+  int size;
+  int count;
+  int recur_offset;
+  struct memory_map *recur;
+};
+
+BLOCK_ALLOC(memory_map, 255)
+BLOCK_ALLOC(memory_map_entry, 511)
+
+void dmalloc_set_mmap(void *ptr, struct memory_map *m)
+{
+  debug_malloc_update_location(ptr, m->name+1);
+}
+
+void dmalloc_set_mmap_template(void *ptr, struct memory_map *m)
+{
+  debug_malloc_update_location(ptr,m->name);
+}
+
+void dmalloc_set_mmap_from_template(void *p, void *p2)
+{
+  int names=0;
+  if(p)
+  {
+    struct memhdr *mh,*from;
+    mt_lock(&debug_malloc_mutex);
+
+    if((from=my_find_memhdr(p2,0)) && (mh=my_find_memhdr(p,0)))
+    {
+      struct memloc *l;
+      for(l=from->locations;l;l=l->next)
+      {
+	if(l->location[0]=='T')
+	{
+	  add_location(mh, l->location+1);
+	  names++;
+	}
+      }
+    }
+
+    mt_unlock(&debug_malloc_mutex);
+  }
+}
+
+static void very_low_dmalloc_describe_location(struct memory_map *m,
+					       int offset,
+					       int indent)
+{
+  struct memory_map_entry *e;
+  fprintf(stderr,"%*s ** In memory map %s:\n",indent,"",m->name+2);
+  for(e=m->entries;e;e=e->next)
+  {
+    if(e->offset <= offset && e->offset + e->size * e->count > offset)
+    {
+      int num=(offset - e->offset)/e->size;
+      int off=offset-e->size*num-e->offset;
+      fprintf(stderr,"%*s    Found in member: %s[%d] + %d (offset=%d size=%d)\n",
+	      off,
+	      indent,"",
+	      num,
+	      e->name,e->offset,e->size);
+
+      if(e->recur)
+      {
+	very_low_dmalloc_describe_location(e->recur,
+					   off-e->recur_offset,
+					   indent+2);
+      }
+    }
+  }
+}
+
+static void low_dmalloc_describe_location(struct memhdr *mh, int offset)
+{
+  struct memloc *l;
+  for(l=mh->locations;l;l=l->next)
+  {
+    if(l->location[0]=='M')
+    {
+      struct memory_map *m = (struct memory_map *)(l->location - 1);
+      very_low_dmalloc_describe_location(m, offset,4);
+    }
+  }
+}
+
+void dmalloc_describe_location(void *p, int offset)
+{
+  if(p)
+  {
+    struct memhdr *mh;
+    mt_lock(&debug_malloc_mutex);
+    if((mh=my_find_memhdr(p,0))) low_dmalloc_describe_location(mh, offset);
+    mt_unlock(&debug_malloc_mutex);
+  }
+}
+
+struct memory_map *dmalloc_alloc_mmap(char *name, int line)
+{
+  struct memory_map *m;
+  mt_lock(&debug_malloc_mutex);
+  m=alloc_memory_map();
+  strncpy(m->name+2,name,sizeof(m->name)-2);
+  m->name[sizeof(m->name)-1]=0;
+  m->name[0]='T';
+  m->name[1]='M';
+
+  if(strlen(m->name)+12<sizeof(m->name))
+    sprintf(m->name+strlen(m->name),":%d",line);
+
+  m->entries=0;
+  mt_unlock(&debug_malloc_mutex);
+  return m;
+}
+
+void dmalloc_add_mmap_entry(struct memory_map *m,
+			    char *name,
+			    int offset,
+			    int size,
+			    int count,
+			    struct memory_map *recur,
+			    int recur_offset)
+{
+  struct memory_map_entry *e;
+  mt_lock(&debug_malloc_mutex);
+  e=alloc_memory_map_entry();
+  strncpy(e->name,name,sizeof(e->name));
+  e->name[sizeof(e->name)-1]=0;
+  e->offset=offset;
+  e->size=size;
+  e->count=count?count:1;
+  e->next=m->entries;
+  e->recur=recur;
+  e->recur=recur_offset;
+  m->entries=e;
+  mt_unlock(&debug_malloc_mutex);
+}
+
 #endif
diff --git a/src/program.c b/src/program.c
index f9585993ea2827eb8e4c6c74884a103a95cd47de..68703e32b9bb30f1b65da1242f9df4359a6d1ad6 100644
--- a/src/program.c
+++ b/src/program.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: program.c,v 1.222 2000/04/06 21:00:20 hubbe Exp $");
+RCSID("$Id: program.c,v 1.223 2000/04/08 02:01:09 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -595,6 +595,62 @@ void fixate_program(void)
   }
 
   new_program->flags |= PROGRAM_FIXED;
+
+#ifdef DEBUG_MALLOC
+  {
+#define DBSTR(X) ((X)?(X)->str:"")
+    int e,v;
+    struct memory_map *m=dmalloc_alloc_mmap( DBSTR(lex.current_file),
+					     lex.current_line);
+    for(e=0;e<new_program->num_inherits;e++)
+    {
+      struct inherit *i=new_program->inherits+e;
+      char *tmp;
+      char buffer[50];
+
+      for(v=0;v<i->prog->num_variable_index;v++)
+      {
+	int d=i->prog->variable_index[v];
+	struct identifier *id=i->prog->identifiers+d;
+
+	dmalloc_add_mmap_entry(m,
+			       id->name->str,
+			       OFFSETOF(object,storage) + i->storage_offset + id->func.offset,
+			       sizeof_variable(id->run_time_type),
+			       1, /* count */
+			       0,0);
+      }
+
+      if(i->name)
+      {
+	tmp=i->name->str;
+      }else if(!(tmp=dmalloc_find_name(i->prog))){
+	/* Didn't find a given name, revert to ad-hoc method */
+	INT32 line,pos;
+	
+	for(pos=0;pos<100;pos++)
+	{
+	  tmp=get_line(i->prog->program+pos, i->prog, &line);
+	  if(tmp && line) break;
+	  if(pos+1>=(long)i->prog->num_program) break;
+	}
+	if(!(tmp && line))
+	{
+	  sprintf(buffer,"inherit[%d]",e);
+	  tmp=buffer;
+	}
+      }
+      dmalloc_add_mmap_entry(m,
+			     tmp,
+			     OFFSETOF(object, storage) + i->storage_offset,
+			     i->prog->storage_needed - i->prog->inherits[0].storage_offset,
+			     1, /* count */
+			     0,0);
+
+    }
+    dmalloc_set_mmap_template(new_program, m);
+  }
+#endif
 }
 
 struct program *low_allocate_program(void)
@@ -708,6 +764,11 @@ void low_start_new_program(struct program *p,
   fake_object->parent_identifier=0;
   fake_object->prog=p;
   add_ref(p);
+
+#ifdef PIKE_DEBUG
+  fake_object->program_id=p->id;
+#endif
+
 #ifdef PIKE_SECURITY
   fake_object->prot=0;
 #endif
@@ -1383,7 +1444,7 @@ void set_gc_mark_callback(void (*m)(struct object *))
  */
 void set_gc_check_callback(void (*m)(struct object *))
 {
-  new_program->gc_check=m;
+  new_program->gc_check_func=m;
 }
 
 int low_reference_inherited_identifier(struct program_state *q,
@@ -3074,7 +3135,11 @@ struct program *compile(struct pike_string *prog,
   if(lex.current_file)
   {
     store_linenumber(lex.current_line, lex.current_file);
-    debug_malloc_name(new_program, lex.current_file->str, lex.current_line);
+
+#ifdef DEBUG_MALLOC
+    if(strcmp(lex.current_file->str,"-") || lex.current_line!=1)
+      debug_malloc_name(new_program, lex.current_file->str, lex.current_line);
+#endif
   }
   compilation_depth=0;
 
@@ -3469,6 +3534,7 @@ void gc_free_all_unreferenced_programs(void)
       {
 	free_svalue(& p->constants[e].sval);
 	p->constants[e].sval.type=T_INT;
+	DO_IF_DMALLOC(p->constants[e].sval.u.refs=(void *)-1);
       }
 
       for(e=0;e<p->num_inherits;e++)
@@ -3483,6 +3549,16 @@ void gc_free_all_unreferenced_programs(void)
       /* FIXME: Is there anything else that needs to be freed here? */
       SET_NEXT_AND_FREE(p, free_program);
     }else{
+#ifdef PIKE_DEBUG
+      int e,tmp=0;
+      for(e=0;e<p->num_constants;e++)
+      {
+	if(p->constants[e].sval.type == T_PROGRAM && p->constants[e].sval.u.program == p)
+	  tmp++;
+      }
+      if(tmp >= p->refs)
+	fatal("garbage collector failed to free program!!!\n");
+#endif      
       next=p->next;
     }
   }
diff --git a/src/program.h b/src/program.h
index 54b71c2cdbe1581f7f910a34b79964fd2ace4314..ceb71467425c1744aa591a71a3e68776466fade4 100644
--- a/src/program.h
+++ b/src/program.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: program.h,v 1.85 2000/03/30 08:43:07 hubbe Exp $
+ * $Id: program.h,v 1.86 2000/04/08 02:01:09 hubbe Exp $
  */
 #ifndef PROGRAM_H
 #define PROGRAM_H
@@ -262,7 +262,7 @@ struct program
   void (*init)(struct object *);
   void (*exit)(struct object *);
   void (*gc_marked)(struct object *);
-  void (*gc_check)(struct object *);
+  void (*gc_check_func)(struct object *);
 #ifdef PIKE_DEBUG
   unsigned INT32 checksum;
 #endif
diff --git a/src/svalue.c b/src/svalue.c
index 7fb1643246000d91f47650d43a11af2989c82b03..962b50f556fa1305c5f0404de5afda2e8590ba1e 100644
--- a/src/svalue.c
+++ b/src/svalue.c
@@ -23,7 +23,7 @@
 #include "queue.h"
 #include "bignum.h"
 
-RCSID("$Id: svalue.c,v 1.64 2000/03/27 07:54:27 hubbe Exp $");
+RCSID("$Id: svalue.c,v 1.65 2000/04/08 02:01:09 hubbe Exp $");
 
 struct svalue dest_ob_zero = { T_INT, 0 };
 
@@ -153,7 +153,7 @@ void debug_free_svalues(struct svalue *s,INT32 num, INT32 type_hint DMALLOC_LINE
    while(--num>=0) {							\
     DO_IF_DMALLOC(debug_malloc_update_location(s->u.Z, dmalloc_location));	\
     Y(s->u.Z);								\
-    DO_IF_DMALLOC(s->u.Z=0);						\
+    DO_IF_DMALLOC(s->u.Z=(void *)-1);					\
     s++;								\
    }return
 
@@ -1204,7 +1204,7 @@ void check_svalue(struct svalue *s)
 
 #endif
 
-TYPE_FIELD gc_check_svalues(struct svalue *s, int num)
+TYPE_FIELD real_gc_check_svalues(struct svalue *s, int num)
 {
   INT32 e;
   TYPE_FIELD f;
@@ -1272,7 +1272,7 @@ TYPE_FIELD gc_check_svalues(struct svalue *s, int num)
 }
 
 #ifdef PIKE_DEBUG
-void gc_xmark_svalues(struct svalue *s, int num)
+void real_gc_xmark_svalues(struct svalue *s, int num)
 {
   INT32 e;
 
@@ -1298,7 +1298,7 @@ void gc_xmark_svalues(struct svalue *s, int num)
 }
 #endif
 
-void gc_check_short_svalue(union anything *u, TYPE_T type)
+void real_gc_check_short_svalue(union anything *u, TYPE_T type)
 {
 #ifdef PIKE_DEBUG
   gc_svalue_location=(void *)u;
diff --git a/src/svalue.h b/src/svalue.h
index a062913934e4a4a1290dd8b5222e346761f87592..d2d314c88f7102a2d3d4cb90edfbafdc35e742df 100644
--- a/src/svalue.h
+++ b/src/svalue.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: svalue.h,v 1.48 2000/03/20 21:00:04 hubbe Exp $
+ * $Id: svalue.h,v 1.49 2000/04/08 02:01:09 hubbe Exp $
  */
 #ifndef SVALUE_H
 #define SVALUE_H
@@ -270,8 +270,8 @@ do{ \
 
 #endif
 
-#define free_svalue(X) do { struct svalue *_s=(X); check_type(_s->type); check_refs(_s); if(_s->type<=MAX_REF_TYPE) { debug_malloc_touch(_s->u.refs); if(--*(_s->u.refs) <=0) { really_free_svalue(_s); DO_IF_DMALLOC(_s->u.refs=0;) }}}while(0)
-#define free_short_svalue(X,T) do { union anything *_s=(X); TYPE_T _t=(T); check_type(_t); check_refs2(_s,_t); if(_t<=MAX_REF_TYPE && _s->refs) if(--*(_s->refs) <= 0) { really_free_short_svalue(_s,_t); DO_IF_DMALLOC(_s->refs=0;)} }while(0)
+#define free_svalue(X) do { struct svalue *_s=(X); check_type(_s->type); check_refs(_s); if(_s->type<=MAX_REF_TYPE) { debug_malloc_touch(_s->u.refs); if(--*(_s->u.refs) <=0) { really_free_svalue(_s); } DO_IF_DMALLOC(_s->u.refs=(void *)-1;)  }}while(0)
+#define free_short_svalue(X,T) do { union anything *_s=(X); TYPE_T _t=(T); check_type(_t); check_refs2(_s,_t); if(_t<=MAX_REF_TYPE && _s->refs) if(--*(_s->refs) <= 0) { really_free_short_svalue(_s,_t); } DO_IF_DMALLOC(_s->refs=(void *)-1;) }while(0)
 #define add_ref_svalue(X) do { struct svalue *_tmp=(X); check_type(_tmp->type); check_refs(_tmp); if(_tmp->type <= MAX_REF_TYPE) { debug_malloc_touch(_tmp->u.refs); _tmp->u.refs[0]++; } }while(0)
 #define assign_svalue_no_free(X,Y) do { struct svalue _tmp, *_to=(X), *_from=(Y); check_type(_from->type); check_refs(_from);  *_to=_tmp=*_from; if(_tmp.type <= MAX_REF_TYPE) { debug_malloc_touch(_tmp.u.refs); _tmp.u.refs[0]++; } }while(0)
 #define assign_svalue(X,Y) do { struct svalue *_to2=(X), *_from2=(Y); free_svalue(_to2); assign_svalue_no_free(_to2, _from2);  }while(0)
@@ -335,9 +335,9 @@ void copy_svalues_recursively_no_free(struct svalue *to,
 				      struct processing *p);
 void check_short_svalue(union anything *u, TYPE_T type);
 void check_svalue(struct svalue *s);
-TYPE_FIELD gc_check_svalues(struct svalue *s, int num);
-void gc_xmark_svalues(struct svalue *s, int num);
-void gc_check_short_svalue(union anything *u, TYPE_T type);
+TYPE_FIELD real_gc_check_svalues(struct svalue *s, int num);
+void real_gc_xmark_svalues(struct svalue *s, int num);
+void real_gc_check_short_svalue(union anything *u, TYPE_T type);
 void gc_mark_svalues(struct svalue *s, int num);
 void gc_mark_short_svalue(union anything *u, TYPE_T type);
 INT32 pike_sizeof(struct svalue *s);