diff --git a/src/backend.c b/src/backend.c
index 14b36774a147f971ffbfeaa030b02b70cc6698ce..3a8faae1e65e897de98de57ec89b48c798db1435 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: backend.c,v 1.40 1998/11/22 11:02:33 hubbe Exp $");
+RCSID("$Id: backend.c,v 1.41 1999/05/02 08:11:28 hubbe Exp $");
 #include "fdlib.h"
 #include "backend.h"
 #include <errno.h>
@@ -184,7 +184,7 @@ static int may_need_wakeup=0;
 
 static struct callback_list backend_callbacks;
 
-struct callback *add_backend_callback(callback_func call,
+struct callback *debug_add_backend_callback(callback_func call,
 				      void *arg,
 				      callback_func free_func)
 {
diff --git a/src/backend.h b/src/backend.h
index b72d32fd3ad6823af71c1ec83600d23541b4cc89..09011754e6019ac4129dfd03a689f3ccce34f204 100644
--- a/src/backend.h
+++ b/src/backend.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: backend.h,v 1.6 1998/03/28 15:39:44 grubba Exp $
+ * $Id: backend.h,v 1.7 1999/05/02 08:11:29 hubbe Exp $
  */
 #ifndef BACKEND_H
 #define BACKEND_H
@@ -21,7 +21,7 @@ extern struct callback_list do_debug_callbacks;
 
 /* Prototypes begin here */
 struct selectors;
-struct callback *add_backend_callback(callback_func call,
+struct callback *debug_add_backend_callback(callback_func call,
 				      void *arg,
 				      callback_func free_func);
 void wake_up_backend(void);
@@ -49,4 +49,7 @@ void backend(void);
 int write_to_stderr(char *a, INT32 len);
 /* Prototypes end here */
 
+#define add_backend_callback(X,Y,Z) \
+  dmalloc_touch(struct callback *,debug_add_backend_callback((X),(Y),(Z)))
+
 #endif
diff --git a/src/block_alloc.h b/src/block_alloc.h
index 2862f71e835e02fa9d5a8806f8f3ba02b0b02dc5..517a35dbda1c22796aa098c261c951e93448f6dc 100644
--- a/src/block_alloc.h
+++ b/src/block_alloc.h
@@ -1,4 +1,4 @@
-/* $Id: block_alloc.h,v 1.10 1999/04/08 22:27:06 hubbe Exp $ */
+/* $Id: block_alloc.h,v 1.11 1999/05/02 08:11:30 hubbe Exp $ */
 #undef PRE_INIT_BLOCK
 #undef INIT_BLOCK
 #undef EXIT_BLOCK
@@ -47,6 +47,7 @@ struct DATA *PIKE_CONCAT(alloc_,DATA)(void)				\
 									\
   tmp=PIKE_CONCAT3(free_,DATA,s);					\
   PIKE_CONCAT3(free_,DATA,s)=tmp->next;					\
+  DO_IF_DMALLOC( dmalloc_register(tmp,0, __FILE__, __LINE__);  )        \
   INIT_BLOCK(tmp);							\
   return tmp;								\
 }									\
@@ -54,6 +55,7 @@ struct DATA *PIKE_CONCAT(alloc_,DATA)(void)				\
 void PIKE_CONCAT(really_free_,DATA)(struct DATA *d)			\
 {									\
   EXIT_BLOCK(d);							\
+  DO_IF_DMALLOC( dmalloc_unregister(d, 1);  )                           \
   d->next=PIKE_CONCAT3(free_,DATA,s);					\
   PRE_INIT_BLOCK(d);							\
   PIKE_CONCAT3(free_,DATA,s)=d;						\
@@ -70,6 +72,22 @@ void PIKE_CONCAT3(free_all_,DATA,_blocks)(void)				\
   PIKE_CONCAT(DATA,_blocks)=0;						\
   PIKE_CONCAT3(free_,DATA,s)=0;						\
 }									\
+									\
+									\
+void PIKE_CONCAT3(count_memory_in_,DATA,s)(INT32 *num_, INT32 *size_)	\
+{									\
+  INT32 num=0, size=0;							\
+  struct PIKE_CONCAT(DATA,_block) *tmp;					\
+  struct DATA *tmp2;							\
+  for(tmp=PIKE_CONCAT(DATA,_blocks);tmp;tmp=tmp->next)			\
+  {									\
+    num+=BSIZE;								\
+    size+=sizeof(struct PIKE_CONCAT(DATA,_block));			\
+  }									\
+  for(tmp2=PIKE_CONCAT3(free_,DATA,s);tmp2;tmp2=tmp2->next) num--;	\
+  *num_=num;								\
+  *size_=size;								\
+}
 
 
 
@@ -108,52 +126,59 @@ struct DATA *PIKE_CONCAT(find_,DATA)(void *ptr)				\
 }									\
 									\
 									\
+static void PIKE_CONCAT(DATA,_rehash)()					\
+{									\
+  /* Time to re-hash */							\
+  struct DATA **old_hash= PIKE_CONCAT(DATA,_hash_table);		\
+  struct DATA *p;                                                       \
+  int hval;                                                             \
+  int e=PIKE_CONCAT(DATA,_hash_table_size);				\
+  									\
+  PIKE_CONCAT(DATA,_hash_table_size)*=2;				\
+  PIKE_CONCAT(DATA,_hash_table_size)++;					\
+  if((PIKE_CONCAT(DATA,_hash_table)=(struct DATA **)			\
+      malloc(PIKE_CONCAT(DATA,_hash_table_size)*			\
+	     sizeof(struct DATA *))))					\
+  {									\
+    MEMSET(PIKE_CONCAT(DATA,_hash_table),0,				\
+	   sizeof(struct DATA *)*PIKE_CONCAT(DATA,_hash_table_size));	\
+    while(--e >=0)							\
+    {									\
+      while((p=old_hash[e]))						\
+      {									\
+	old_hash[e]=p->next;						\
+	hval=(long)(p-> data);						\
+	hval%=PIKE_CONCAT(DATA,_hash_table_size);			\
+	p->next=PIKE_CONCAT(DATA,_hash_table)[hval];			\
+	PIKE_CONCAT(DATA,_hash_table)[hval]=p;				\
+      }									\
+    }									\
+    free((char *)old_hash);						\
+  }else{								\
+    PIKE_CONCAT(DATA,_hash_table)=old_hash;				\
+    PIKE_CONCAT(DATA,_hash_table_size)=e;				\
+  }									\
+}                                            				\
+									\
 									\
-struct DATA *PIKE_CONCAT(make_,DATA)(void *ptr, int hval)	        \
+struct DATA *PIKE_CONCAT(make_,DATA)(void *ptr, int hval)		\
 {									\
   struct DATA *p;							\
 									\
-  DO_IF_DEBUG( if(!PIKE_CONCAT(DATA,_hash_table))                       \
-    fatal("Hash table error!\n"); )                                     \
+  DO_IF_DEBUG( if(!PIKE_CONCAT(DATA,_hash_table))			\
+    fatal("Hash table error!\n"); )					\
   PIKE_CONCAT(num_,DATA)++;						\
 									\
   if(( PIKE_CONCAT(num_,DATA)>>2 ) >=					\
      PIKE_CONCAT(DATA,_hash_table_size))				\
   {									\
-    /* Time to re-hash */						\
-    struct DATA **old_hash= PIKE_CONCAT(DATA,_hash_table);		\
-    int e=PIKE_CONCAT(DATA,_hash_table_size);				\
-									\
-    PIKE_CONCAT(DATA,_hash_table_size)*=2;				\
-    PIKE_CONCAT(DATA,_hash_table_size)++;				\
-    if((PIKE_CONCAT(DATA,_hash_table)=(struct DATA **)			\
-	malloc(PIKE_CONCAT(DATA,_hash_table_size)*			\
-	       sizeof(struct DATA *))))					\
-    {									\
-      MEMSET(PIKE_CONCAT(DATA,_hash_table),0,				\
-	 sizeof(struct DATA *)*PIKE_CONCAT(DATA,_hash_table_size));	\
-      while(e-- >=0)							\
-      {									\
-	while((p=old_hash[e]))		                                \
-	{								\
-	  old_hash[e]=p->next;                                          \
-	  hval=(long)(p-> data);					\
-	  hval%=PIKE_CONCAT(DATA,_hash_table_size);			\
-	  p->next=PIKE_CONCAT(DATA,_hash_table)[hval];			\
-	  PIKE_CONCAT(DATA,_hash_table)[hval]=p;			\
-	}								\
-      }									\
-      hval=(long)ptr;							\
-      hval%=PIKE_CONCAT(DATA,_hash_table_size);				\
-      free((char *)old_hash);                                           \
-    }else{								\
-      PIKE_CONCAT(DATA,_hash_table)=old_hash;	                        \
-      PIKE_CONCAT(DATA,_hash_table_size)=e;				\
-    }									\
+    PIKE_CONCAT(DATA,_rehash)();					\
+    hval=(long)ptr;							\
+    hval%=PIKE_CONCAT(DATA,_hash_table_size);				\
   }									\
 									\
-  p=PIKE_CONCAT(alloc_,DATA)();	        				\
-  p->data=ptr;                                                          \
+  p=PIKE_CONCAT(alloc_,DATA)();						\
+  p->data=ptr;								\
   p->next=PIKE_CONCAT(DATA,_hash_table)[hval];				\
   PIKE_CONCAT(DATA,_hash_table)[hval]=p;				\
   return p;								\
@@ -186,12 +211,12 @@ int PIKE_CONCAT(remove_,DATA)(void *ptr)				\
 {									\
   struct DATA *p;							\
   int hval=(long)ptr;							\
-  if(!PIKE_CONCAT(DATA,_hash_table)) return 0;                          \
+  if(!PIKE_CONCAT(DATA,_hash_table)) return 0;				\
   hval%=PIKE_CONCAT(DATA,_hash_table_size);				\
   if((p=PIKE_CONCAT(really_low_find_,DATA)(ptr, hval)))			\
   {									\
     PIKE_CONCAT(num_,DATA)--;						\
-    if(PIKE_CONCAT(DATA,_hash_table)[hval]!=p) fatal("GAOssdf\n");      \
+    if(PIKE_CONCAT(DATA,_hash_table)[hval]!=p) fatal("GAOssdf\n");	\
     PIKE_CONCAT(DATA,_hash_table)[hval]=p->next;			\
     PIKE_CONCAT(really_free_,DATA)(p);					\
     return 1;								\
@@ -206,7 +231,12 @@ void PIKE_CONCAT3(init_,DATA,_hash)(void)				\
   PIKE_CONCAT(DATA,_hash_table_size)=hashprimes[my_log2(BSIZE)];	\
 									\
   PIKE_CONCAT(DATA,_hash_table)=(struct DATA **)			\
-    xalloc(sizeof(struct DATA *)*PIKE_CONCAT(DATA,_hash_table_size));	\
+    malloc(sizeof(struct DATA *)*PIKE_CONCAT(DATA,_hash_table_size));	\
+  if(!PIKE_CONCAT(DATA,_hash_table))                                    \
+  {									\
+    fprintf(stderr,"Fatal: out of memory.\n");			        \
+    exit(17);								\
+  }									\
   MEMSET(PIKE_CONCAT(DATA,_hash_table),0,				\
 	 sizeof(struct DATA *)*PIKE_CONCAT(DATA,_hash_table_size));	\
 }									\
@@ -216,5 +246,5 @@ void PIKE_CONCAT3(exit_,DATA,_hash)(void)				\
   PIKE_CONCAT3(free_all_,DATA,_blocks)();				\
   free(PIKE_CONCAT(DATA,_hash_table));					\
   PIKE_CONCAT(DATA,_hash_table)=0;					\
-}									\
+}
 
diff --git a/src/block_alloc_h.h b/src/block_alloc_h.h
index a3c47e0a63639f2dc860bb4906e0f12f281a16d5..39432dd8d87ab8f9da96ee1b8045f31b880e8064 100644
--- a/src/block_alloc_h.h
+++ b/src/block_alloc_h.h
@@ -5,6 +5,7 @@
 struct DATA *PIKE_CONCAT(alloc_,DATA)(void);			\
 void PIKE_CONCAT(really_free_,DATA)(struct DATA *d);	\
 void PIKE_CONCAT3(free_all_,DATA,_blocks)(void);
+void PIKE_CONCAT3(count_memory_in_,DATA,s)(INT32 *, INT32 *);	\
 
 
 #define PTR_HASH_ALLOC(DATA,BSIZE)				\
diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index 8f020bf12fe1bb3640703c3724d240e260550fdf..d3f691b795b44944ee1aba9f6a4340e5710ad490 100644
--- a/src/builtin_functions.c
+++ b/src/builtin_functions.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: builtin_functions.c,v 1.167 1999/04/17 13:45:52 grubba Exp $");
+RCSID("$Id: builtin_functions.c,v 1.168 1999/05/02 08:11:32 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "pike_macros.h"
@@ -3506,6 +3506,12 @@ void f__memory_usage(INT32 args)
   push_text("callable_bytes");
   push_int(size);
 
+  count_memory_in_pike_frames(&num, &size);
+  push_text("num_frames");
+  push_int(num);
+  push_text("frame_bytes");
+  push_int(size);
+
   call_callback(&memory_usage_callback, (void *)0);
 
   f_aggregate_mapping(sp-ss);
diff --git a/src/callback.c b/src/callback.c
index 53cb8a6ae8b6aa51c9f164a8b3ff83b62ea74366..a371ab50bb9fefd77b9fad177edeeb7c6ea9b748 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -9,7 +9,7 @@
 #include "error.h"
 #include "block_alloc.h"
 
-RCSID("$Id: callback.c,v 1.16 1999/01/31 09:01:41 hubbe Exp $");
+RCSID("$Id: callback.c,v 1.17 1999/05/02 08:11:33 hubbe Exp $");
 
 struct callback_list fork_child_callback;
 
@@ -172,10 +172,10 @@ void call_callback(struct callback_list *lst, void *arg)
 }
 
 /* Add a callback to the linked list pointed to by ptr. */
-struct callback *add_to_callback(struct callback_list *lst,
-				 callback_func call,
-				 void *arg,
-				 callback_func free_func)
+struct callback *debug_add_to_callback(struct callback_list *lst,
+				       callback_func call,
+				       void *arg,
+				       callback_func free_func)
 {
   struct callback *l;
   l=alloc_callback();
@@ -183,6 +183,8 @@ struct callback *add_to_callback(struct callback_list *lst,
   l->arg=arg;
   l->free_func=free_func;
 
+  DO_IF_DMALLOC( if(l->free_func == free) l->free_func=dmalloc_free; )
+
   l->next=lst->callbacks;
   lst->callbacks=l;
 
@@ -196,6 +198,7 @@ struct callback *add_to_callback(struct callback_list *lst,
  */
 void *remove_callback(struct callback *l)
 {
+  dmalloc_unregister(l,1);
   l->call=0;
   l->free_func=0;
   return l->arg;
@@ -221,18 +224,3 @@ void cleanup_callbacks(void)
   free_all_callback_blocks();
 }
 
-
-void count_memory_in_callbacks(INT32 *num_, INT32 *size_)
-{
-  INT32 num=0, size=0;
-  struct callback_block *tmp;
-  struct callback *tmp2;
-  for(tmp=callback_blocks;tmp;tmp=tmp->next)
-  {
-    num+=CALLBACK_CHUNK;
-    size+=sizeof(struct callback_block);
-  }
-  for(tmp2=free_callbacks;tmp2;tmp2=tmp2->next) num--;
-  *num_=num;
-  *size_=size;
-}
diff --git a/src/callback.h b/src/callback.h
index 9a6c241e9612ec3f6a129fab64aaaf584247227d..850cdfc0ce79d5d386790591c67668e1d3dfd8dd 100644
--- a/src/callback.h
+++ b/src/callback.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: callback.h,v 1.7 1998/03/28 15:38:18 grubba Exp $
+ * $Id: callback.h,v 1.8 1999/05/02 08:11:34 hubbe Exp $
  */
 #ifndef CALLBACK_H
 #define CALLBACK_H
@@ -26,16 +26,17 @@ typedef void (*callback_func)(struct callback *, void *,void *);
 
 /* Prototypes begin here */
 struct callback;
-struct callback_block;
 void call_callback(struct callback_list *lst, void *arg);
-struct callback *add_to_callback(struct callback_list *lst,
-				 callback_func call,
-				 void *arg,
-				 callback_func free_func);
+struct callback *debug_add_to_callback(struct callback_list *lst,
+				       callback_func call,
+				       void *arg,
+				       callback_func free_func);
 void *remove_callback(struct callback *l);
 void free_callback_list(struct callback_list *lst);
 void cleanup_callbacks(void);
-void count_memory_in_callbacks(INT32 *num_, INT32 *size_);
 /* Prototypes end here */
 
+#define add_to_callback(LST,CALL,ARG,FF) \
+  dmalloc_touch(struct callback *,debug_add_to_callback((LST),(CALL),(ARG),(FF)))
+
 #endif
diff --git a/src/configure.in b/src/configure.in
index 8cb57974ad0d31ceca2db74be6f6f3b096c6e7c7..f3a2dd4498fdaef22eb8ad383099360cda67376f 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -1,4 +1,4 @@
-AC_REVISION("$Id: configure.in,v 1.280 1999/04/30 07:22:17 hubbe Exp $")
+AC_REVISION("$Id: configure.in,v 1.281 1999/05/02 08:11:35 hubbe Exp $")
 AC_INIT(interpret.c)
 AC_CONFIG_HEADER(machine.h)
 
@@ -161,7 +161,8 @@ fi
 CC="$SMARTLINK $REALCC"
 pike_cv_prog_CC="$CC"
 
-AC_SUBST(SMARTLINK REALCC)
+AC_SUBST(SMARTLINK)
+AC_SUBST(REALCC)
 export REALCC SMARTLINK
 
 #############################################################################
diff --git a/src/constants.c b/src/constants.c
index 7aaac6f47b94013c36375b8da73d8a173498c1e5..e5f405df4ad32702c0f858a4e930f6b655835bfc 100644
--- a/src/constants.c
+++ b/src/constants.c
@@ -15,9 +15,8 @@
 #include "error.h"
 #include "block_alloc.h"
 
-RCSID("$Id: constants.c,v 1.17 1999/04/15 04:08:09 hubbe Exp $");
+RCSID("$Id: constants.c,v 1.18 1999/05/02 08:11:37 hubbe Exp $");
 
-static INT32 num_callable=0;
 static struct mapping *builtin_constants = 0;
 
 struct mapping *get_builtin_constants(void)
@@ -64,13 +63,10 @@ void add_global_program(char *name, struct program *p)
   low_add_constant(name, &s);
 }
 
-#undef INIT_BLOCK
-#define INIT_BLOCK(X) num_callable++
 #undef EXIT_BLOCK
 #define EXIT_BLOCK(X) do {		\
   free_string(X->type);			\
   free_string(X->name);			\
-  num_callable--;			\
 }while(0)
 BLOCK_ALLOC(callable,128)
 
@@ -169,8 +165,3 @@ void cleanup_added_efuns(void)
   }
 #endif
 }
-void count_memory_in_callables(INT32 *num_, INT32 *size_)
-{
-  *num_=num_callable;
-  *size_=num_callable*sizeof(struct callable);
-}
diff --git a/src/dmalloc.h b/src/dmalloc.h
index 5d0626b43e62a7f89b87ee6f1b3f0335f4a3612f..b2e42439e23bd79fec13ffd2d2b6da90f8727221 100644
--- a/src/dmalloc.h
+++ b/src/dmalloc.h
@@ -1,5 +1,5 @@
 /*
- * $Id: dmalloc.h,v 1.10 1999/03/19 11:39:29 hubbe Exp $
+ * $Id: dmalloc.h,v 1.11 1999/05/02 08:11:38 hubbe Exp $
  */
 
 extern char *debug_xalloc(long);
@@ -16,17 +16,21 @@ void low_add_marks_to_memhdr(struct memhdr *to,
 
 extern int verbose_debug_malloc;
 extern int verbose_debug_exit;
+extern void dmalloc_register(void *, int,char *, int);
+extern int dmalloc_unregister(void *, int);
 extern void *debug_malloc(size_t, const char *, int);
 extern void *debug_calloc(size_t, size_t, const char *, int);
 extern void *debug_realloc(void *, size_t, const char *, int);
-extern void debug_free(void *, const char *, int);
+extern void debug_free(void *, const char *, int,int);
 extern char *debug_strdup(const char *, const char *, int);
 extern void reset_debug_malloc(void);
+extern void dmalloc_free(void *p);
 void *debug_malloc_update_location(void *,const char *, int);
 #define malloc(x) debug_malloc((x), __FILE__, __LINE__)
 #define calloc(x, y) debug_calloc((x), (y), __FILE__, __LINE__)
 #define realloc(x, y) debug_realloc((x), (y), __FILE__, __LINE__)
-#define free(x) debug_free((x), __FILE__, __LINE__)
+#define free(x) debug_free((x), __FILE__, __LINE__,0)
+#define dmfree(x) debug_free((x),__FILE__,__LINE__,1)
 #define strdup(x) debug_strdup((x), __FILE__, __LINE__)
 #define DO_IF_DMALLOC(X) X
 #define debug_malloc_touch(X) debug_malloc_update_location((X),__FILE__,__LINE__)
@@ -34,7 +38,17 @@ void *debug_malloc_update_location(void *,const char *, int);
 #define xalloc(X) ((char *)debug_malloc_touch(debug_xalloc(X)))
 void debug_malloc_dump_references(void *x);
 #define dmalloc_touch(TYPE,X) ((TYPE)debug_malloc_update_location((X),__FILE__,__LINE__))
+
+#define DMALLOC_LINE_ARGS ,char * dmalloc_file, int dmalloc_line
+#define DMALLOC_POS ,__FILE__,__LINE__
+#define DMALLOC_PROXY_ARGS ,dmalloc_file,dmalloc_line
+void *dmalloc_accept_leak(void *);
 #else
+#define dmfree(X) free((X))
+#define dmalloc_accept_leak(X) (X)
+#define DMALLOC_LINE_ARGS 
+#define DMALLOC_POS 
+#define DMALLOC_PROXY_ARGS
 #define debug_malloc_dump_references(X)
 #define xalloc debug_xalloc
 #define dbm_main main
@@ -43,4 +57,7 @@ void debug_malloc_dump_references(void *x);
 #define debug_malloc_touch(X)
 #define debug_malloc_pass(X) (X)
 #define dmalloc_touch(TYPE,X) (X)
+#define dmalloc_register(X,Y,Z)
+#define dmalloc_unregister(X,Y)
+#define debug_free(X,Y,Z,Q) free((X))
 #endif
diff --git a/src/error.c b/src/error.c
index bf52817b66187598f656e5834b3fa55dd21d53ef..a98e5315552e905ef732fac2a26ddd1dede557f9 100644
--- a/src/error.c
+++ b/src/error.c
@@ -19,7 +19,7 @@
 #include "module_support.h"
 #include "threads.h"
 
-RCSID("$Id: error.c,v 1.34 1999/04/17 13:47:16 grubba Exp $");
+RCSID("$Id: error.c,v 1.35 1999/05/02 08:11:39 hubbe Exp $");
 
 #undef ATTRIBUTE
 #define ATTRIBUTE(X)
@@ -80,14 +80,11 @@ void pike_throw(void) ATTRIBUTE((noreturn))
 
   while(fp != recoveries->fp)
   {
-    struct pike_frame *tmp=fp;
 #ifdef PIKE_DEBUG
     if(!fp)
       fatal("Popped out of stack frames.\n");
 #endif
-    fp = tmp->next;
-    tmp->next=0;
-    free_pike_frame(tmp);
+    POP_PIKE_FRAME();
   }
 
   pop_n_elems(sp - evaluator_stack - recoveries->sp);
@@ -483,7 +480,7 @@ void permission_error(
   char *func,
   struct svalue *base_sp, int args,
   char *permission_type,
-  char *desc, ...) ATTRIBUTE((noreturn, format(printf, 2, 3)))
+  char *desc, ...) ATTRIBUTE((noreturn, format(printf, 5, 6)))
 {
   INIT_ERROR(permission);
   ERROR_STRUCT(permission,o)->permission_type=
diff --git a/src/error.h b/src/error.h
index a6de3eb4b57bb1c213d05ea32a9d3c6433a14935..75c59a77c598654fbc4fa385e415fc65ebddc5bd 100644
--- a/src/error.h
+++ b/src/error.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: error.h,v 1.35 1999/04/10 00:42:00 hubbe Exp $
+ * $Id: error.h,v 1.36 1999/05/02 08:11:40 hubbe Exp $
  */
 #ifndef ERROR_H
 #define ERROR_H
@@ -103,6 +103,7 @@ extern int throw_severity;
      OED_FPRINTF((stderr, "SET_ONERROR(%p, %p, %p) %s:%d\n", \
                   &(X), (Y), (void *)(Z), __FILE__, __LINE__)); \
      X.func=(error_call)(Y); \
+     DO_IF_DMALLOC( if( X.func == free ) X.func=dmalloc_free;) \
      X.arg=(void *)(Z); \
      if(!recoveries) break; \
      X.previous=recoveries->onerror; \
@@ -172,6 +173,7 @@ void check_recovery_context(void);
 JMP_BUF *init_recovery(JMP_BUF *r DEBUG_LINE_ARGS);
 void pike_throw(void) ATTRIBUTE((noreturn));
 void push_error(char *description);
+void low_error(char *buf);
 void va_error(const char *fmt, va_list args) ATTRIBUTE((noreturn));
 void new_error(const char *name, const char *text, struct svalue *oldsp,
 	       INT32 args, const char *file, int line) ATTRIBUTE((noreturn));
@@ -217,6 +219,11 @@ void resource_error(
   char *resource_type,
   long howmuch,
   char *desc, ...) ATTRIBUTE((noreturn,format (printf, 6, 7)));
+void permission_error(
+  char *func,
+  struct svalue *base_sp, int args,
+  char *permission_type,
+  char *desc, ...) ATTRIBUTE((noreturn, format(printf, 5, 6)));
 void init_error(void);
 void cleanup_error(void);
 /* Prototypes end here */
diff --git a/src/gc.c b/src/gc.c
index 36a3886dc17981f65d229ffaeb270fac858ebd7a..a51d490ada4335d0a63bc062abec0ffb9776e662 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -21,12 +21,13 @@ struct callback *gc_evaluator_callback=0;
 #include "pike_types.h"
 #include "time_stuff.h"
 #include "constants.h"
+#include "block_alloc.h"
 
 #include "gc.h"
 #include "main.h"
 #include <math.h>
 
-RCSID("$Id: gc.c,v 1.41 1999/03/17 21:49:24 hubbe Exp $");
+RCSID("$Id: gc.c,v 1.42 1999/05/02 08:11:41 hubbe Exp $");
 
 /* Run garbage collect approximate every time we have
  * 20 percent of all arrays, objects and programs is
@@ -50,7 +51,7 @@ static double objects_freed = 0.0;
 
 struct callback_list gc_callbacks;
 
-struct callback *add_gc_callback(callback_func call,
+struct callback *debug_add_gc_callback(callback_func call,
 				 void *arg,
 				 callback_func free_func)
 {
@@ -68,65 +69,17 @@ struct marker
 #endif
   INT32 flags;
   struct marker *next;
-  void *marked;
+  void *data;
 };
 
-struct marker_chunk
-{
-  struct marker_chunk *next;
-  struct marker markers[MARKER_CHUNK_SIZE];
-};
-
-static struct marker_chunk *chunk=0;
-static int markers_left_in_chunk=0;
-
-static struct marker *new_marker(void)
-{
-  if(!markers_left_in_chunk)
-  {
-    struct marker_chunk *m;
-    m=(struct marker_chunk *)xalloc(sizeof(struct marker_chunk));
-    m->next=chunk;
-    chunk=m;
-    markers_left_in_chunk=MARKER_CHUNK_SIZE;
-  }
-  markers_left_in_chunk--;
-
-  return chunk->markers + markers_left_in_chunk;
-}
-
-static struct marker **hash=0;
-static unsigned long hashsize=0;
-
-static struct marker *getmark(void *a)
-{
-  unsigned long hashval;
-  struct marker *m;
-
-  hashval=(unsigned long)a;
-  hashval%=hashsize;
-
+#undef INIT_BLOCK
 #ifdef PIKE_DEBUG
-  if(hashval >= hashsize)
-    fatal("Compiler has buggy modulo operator.\n");
-#endif
-
-  for(m=hash[hashval];m;m=m->next)
-    if(m->marked == a)
-      return m;
-
-  m=new_marker();
-  m->marked=a;
-  m->refs=0;
-#ifdef PIKE_DEBUG
-  m->xrefs=0;
+#define INIT_BLOCK(X) (X)->flags=(X)->refs=(X)->xrefs=0
+#else
+#define INIT_BLOCK(X) (X)->flags=(X)->refs=0
 #endif
-  m->flags=0;
-  m->next=hash[hashval];
-  hash[hashval]=m;
 
-  return m;
-}
+PTR_HASH_ALLOC(marker,MARKER_CHUNK_SIZE)
 
 #ifdef PIKE_DEBUG
 
@@ -465,11 +418,12 @@ INT32 gc_check(void *a)
     return 0;
   }
 #endif
-  return add_ref(getmark(a));
+  return add_ref(get_marker(a));
 }
 
 static void init_gc(void)
 {
+#if 0
   INT32 tmp3;
   /* init hash , hashsize will be a prime between num_objects/8 and
    * num_objects/4, this will assure that no re-hashing is needed.
@@ -484,10 +438,14 @@ static void init_gc(void)
   hash=(struct marker **)xalloc(sizeof(struct marker **)*hashsize);
   MEMSET((char *)hash,0,sizeof(struct marker **)*hashsize);
   markers_left_in_chunk=0;
+#else
+  init_marker_hash();
+#endif
 }
 
 static void exit_gc(void)
 {
+#if 0
   struct marker_chunk *m;
   /* Free hash table */
   free((char *)hash);
@@ -496,6 +454,16 @@ static void exit_gc(void)
     chunk=m->next;
     free((char *)m);
   }
+#else
+#ifdef DO_PIKE_CLEANUP
+  int e=0;
+  struct marker *h;
+  for(e=0;e<marker_hash_table_size;e++)
+    while(marker_hash_table[e])
+      remove_marker(marker_hash_table[e]->data);
+#endif
+  exit_marker_hash();
+#endif
 }
 
 #ifdef PIKE_DEBUG
@@ -537,7 +505,7 @@ void locate_references(void *a)
 int gc_is_referenced(void *a)
 {
   struct marker *m;
-  m=getmark(a);
+  m=get_marker(a);
 #ifdef PIKE_DEBUG
   if(m->refs + m->xrefs > *(INT32 *)a ||
      (!(m->refs < *(INT32 *)a) && m->xrefs) )
@@ -577,7 +545,7 @@ int gc_external_mark(void *a)
     }
     return 0;
   }
-  m=getmark(a);
+  m=get_marker(a);
   m->xrefs++;
   m->flags|=GC_XREFERENCED;
   gc_is_referenced(a);
@@ -588,7 +556,7 @@ int gc_external_mark(void *a)
 int gc_mark(void *a)
 {
   struct marker *m;
-  m=getmark(a);
+  m=get_marker(a);
 
   if(m->flags & GC_REFERENCED)
   {
@@ -602,7 +570,7 @@ int gc_mark(void *a)
 int gc_do_free(void *a)
 {
   struct marker *m;
-  m=getmark(a);
+  m=get_marker(a);
 #ifdef PIKE_DEBUG
   if( !(m->flags & GC_REFERENCED)  && m->flags & GC_XREFERENCED )
   {
diff --git a/src/gc.h b/src/gc.h
index e29ecfee223d87700450e52321f233e522e98987..a879ae136f9d04b9c05d6a5be2b5b28ef06b88fb 100644
--- a/src/gc.h
+++ b/src/gc.h
@@ -1,5 +1,5 @@
 /*
- * $Id: gc.h,v 1.21 1998/12/16 07:49:36 hubbe Exp $
+ * $Id: gc.h,v 1.22 1999/05/02 08:11:42 hubbe Exp $
  */
 #ifndef GC_H
 #define GC_H
@@ -28,7 +28,7 @@ extern void *gc_svalue_location;
 #endif
 
 /* Prototypes begin here */
-struct callback *add_gc_callback(callback_func call,
+struct callback *debug_add_gc_callback(callback_func call,
 				 void *arg,
 				 callback_func free_func);
 struct marker;
@@ -63,4 +63,7 @@ void do_gc(void);
 #endif
 
 
+#define add_gc_callback(X,Y,Z) \
+  dmalloc_touch(struct callback *,debug_add_gc_callback((X),(Y),(Z)))
+
 #endif
diff --git a/src/interpret.c b/src/interpret.c
index e59bfe2349b2a5252bd275c3bb6b162d8a50e1a2..2d9fa132df0e928e30650aade1726c85a902de19 100644
--- a/src/interpret.c
+++ b/src/interpret.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: interpret.c,v 1.121 1999/04/17 13:48:47 grubba Exp $");
+RCSID("$Id: interpret.c,v 1.122 1999/05/02 08:11:43 hubbe Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -186,6 +186,7 @@ use_malloc:
     if(!spcb)
     {
       spcb=add_gc_callback(gc_check_stack_callback,0,0);
+      dmalloc_accept_leak(spcb);
     }
   }
 #endif
@@ -790,7 +791,7 @@ void mega_apply2(enum apply_type type, INT32 args, void *arg1, void *arg2)
     {
       struct program *p;
       struct reference *ref;
-      struct pike_frame *new_frame=alloc_pike_frame();
+      struct pike_frame *new_frame;
       struct identifier *function;
       
       if(fun<0)
@@ -804,6 +805,9 @@ void mega_apply2(enum apply_type type, INT32 args, void *arg1, void *arg2)
       check_mark_stack(256);
       check_c_stack(8192);
 
+      new_frame=alloc_pike_frame();
+      debug_malloc_touch(new_frame);
+
 #ifdef PIKE_DEBUG
       if(d_flag>2) do_debug();
 #endif
@@ -914,6 +918,7 @@ void mega_apply2(enum apply_type type, INT32 args, void *arg1, void *arg2)
       switch(function->identifier_flags & (IDENTIFIER_FUNCTION | IDENTIFIER_CONSTANT))
       {
       case IDENTIFIER_C_FUNCTION:
+	debug_malloc_touch(fp);
 	fp->num_args=args;
 	new_frame->num_locals=args;
 	check_threads_etc();
@@ -923,6 +928,7 @@ void mega_apply2(enum apply_type type, INT32 args, void *arg1, void *arg2)
       case IDENTIFIER_CONSTANT:
       {
 	struct svalue *s=fp->context.prog->constants+function->func.offset;
+	debug_malloc_touch(fp);
 	if(s->type == T_PROGRAM)
 	{
 	  struct object *tmp;
@@ -939,6 +945,7 @@ void mega_apply2(enum apply_type type, INT32 args, void *arg1, void *arg2)
       
       case 0:
       {
+	debug_malloc_touch(fp);
 	if(sp-save_sp-args<=0)
 	{
 	  /* Create an extra svalue for tail recursion style call */
@@ -1109,6 +1116,7 @@ static int o_catch(unsigned char *pc)
 {
   JMP_BUF tmp;
   struct svalue *expendible=fp->expendible;
+  debug_malloc_touch(fp);
   if(SETJMP(tmp))
   {
     *sp=throw_value;
@@ -1328,12 +1336,7 @@ void cleanup_interpret(void)
 #endif
 
   while(fp)
-  {
-    struct pike_frame *tmp=fp;
-    fp=tmp->next;
-    tmp->next=0;
-    free_pike_frame(tmp);
-  }
+    POP_PIKE_FRAME();
 
 #ifdef PIKE_DEBUG
   for(e=0;e<BACKLOG;e++)
@@ -1372,6 +1375,13 @@ void cleanup_interpret(void)
 void really_clean_up_interpret(void)
 {
 #ifdef DO_PIKE_CLEANUP
+#if 0
+  struct pike_frame_block *p;
+  int e;
+  for(p=pike_frame_blocks;p;p=p->next)
+    for(e=0;e<128;e++)
+      debug_malloc_dump_references( p->x + e);
+#endif
   free_all_pike_frame_blocks();
 #endif
 }
diff --git a/src/interpret.h b/src/interpret.h
index cd6454a1217ebed91a427403b825ca957d68ceb4..1a9af86c62b303fbd53583535a9a01aa975e28f8 100644
--- a/src/interpret.h
+++ b/src/interpret.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: interpret.h,v 1.30 1999/04/15 19:12:50 hubbe Exp $
+ * $Id: interpret.h,v 1.31 1999/05/02 08:11:44 hubbe Exp $
  */
 #ifndef INTERPRET_H
 #define INTERPRET_H
@@ -102,6 +102,7 @@ struct pike_frame
     really_free_pike_frame(fp);						\
   }else{								\
     DO_IF_DEBUG(if( fp->locals+fp->num_locals>sp) fatal("Stack failure in POP_PIKE_FRAME!\n"));                                                      \
+    debug_malloc_touch(fp); \
     if(fp->num_locals)							\
     {									\
       struct svalue *s=(struct svalue *)xalloc(sizeof(struct svalue)*	\
diff --git a/src/interpreter.h b/src/interpreter.h
index 156f287a1b783a09674b639a777d664784b3e528..566d522fd469c3b87b82d2030df2a7f37bc13e13 100644
--- a/src/interpreter.h
+++ b/src/interpreter.h
@@ -22,6 +22,7 @@
 static int eval_instruction(unsigned char *pc)
 {
   unsigned INT32 accumulator=0,instr, prefix=0;
+  debug_malloc_touch(fp);
   while(1)
   {
     fp->pc = pc;
diff --git a/src/modules/call_out/call_out.c b/src/modules/call_out/call_out.c
index 0a6bfbd53dd556e53199d09412dd01df303f3471..63f6b48c268f58992c1f33429c4f389397121800 100644
--- a/src/modules/call_out/call_out.c
+++ b/src/modules/call_out/call_out.c
@@ -6,7 +6,7 @@
 /**/
 #include "global.h"
 #include "config.h"
-RCSID("$Id: call_out.c,v 1.26 1999/04/24 13:43:28 grubba Exp $");
+RCSID("$Id: call_out.c,v 1.27 1999/05/02 08:12:32 hubbe Exp $");
 #include "array.h"
 #include "dynamic_buffer.h"
 #include "object.h"
@@ -453,13 +453,15 @@ void f_call_out(INT32 args)
 
   if(!mem_callback)
     mem_callback=add_memory_usage_callback(count_memory_in_call_outs,0,0);
+    
 
 #ifdef PIKE_DEBUG
   if(!verify_call_out_callback)
   {
     verify_call_out_callback=add_to_callback(& do_debug_callbacks,
 					     do_verify_call_outs, 0, 0);
-    add_gc_callback(mark_call_outs, 0, 0);
+    dmalloc_accept_leak(verify_call_out_callback);
+    dmalloc_accept_leak(add_gc_callback(mark_call_outs, 0, 0));
   }
 #endif
 
@@ -730,4 +732,21 @@ void pike_module_init(void)
 void pike_module_exit(void)
 {
   free_all_call_outs();
+#ifdef DO_PIKE_CLEANUP
+  if(mem_callback)
+  {
+    remove_callback(mem_callback);
+    mem_callback=0;
+  }
+  if(verify_call_out_callback)
+  {
+    remove_callback(verify_call_out_callback);
+    verify_call_out_callback=0;
+  }
+  if(call_out_backend_callback)
+  {
+    remove_callback(call_out_backend_callback);
+    call_out_backend_callback=0;
+  }
+#endif
 }
diff --git a/src/modules/files/file.c b/src/modules/files/file.c
index 345a0c46a95866bc98a584e63d8a42ed9a639639..271d07c52ff747323113e6c5306a71197d1b358d 100644
--- a/src/modules/files/file.c
+++ b/src/modules/files/file.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: file.c,v 1.151 1999/04/20 20:35:01 grubba Exp $");
+RCSID("$Id: file.c,v 1.152 1999/05/02 08:12:48 hubbe Exp $");
 #include "fdlib.h"
 #include "interpret.h"
 #include "svalue.h"
@@ -2627,10 +2627,10 @@ void pike_module_init(void)
 #endif
 
 #ifdef PIKE_DEBUG
-  add_to_callback(&do_debug_callbacks,
-		  check_static_file_data,
-		  0,
-		  0);
+  dmalloc_accept_leak(add_to_callback(&do_debug_callbacks,
+				      check_static_file_data,
+				      0,
+				      0));
 #endif
 }
 
diff --git a/src/modules/system/system.c b/src/modules/system/system.c
index 293bd47aae6cd60e321e5178c129d267d63222e4..c5dc632b90b10dc6bbc8e1cc55873c28f2e6d402 100644
--- a/src/modules/system/system.c
+++ b/src/modules/system/system.c
@@ -1,5 +1,5 @@
 /*
- * $Id: system.c,v 1.69 1999/04/16 20:40:57 grubba Exp $
+ * $Id: system.c,v 1.70 1999/05/02 08:13:05 hubbe Exp $
  *
  * System-call module for Pike
  *
@@ -15,7 +15,7 @@
 #include "system_machine.h"
 #include "system.h"
 
-RCSID("$Id: system.c,v 1.69 1999/04/16 20:40:57 grubba Exp $");
+RCSID("$Id: system.c,v 1.70 1999/05/02 08:13:05 hubbe Exp $");
 #ifdef HAVE_WINSOCK_H
 #include <winsock.h>
 #endif
@@ -1186,7 +1186,8 @@ void pike_module_init(void)
   init_passwd();
 
 #ifdef GETHOSTBYNAME_MUTEX_EXISTS
-  add_to_callback(& fork_child_callback, cleanup_after_fork, 0, 0);
+  dmalloc_accept_leak(add_to_callback(& fork_child_callback,
+				      cleanup_after_fork, 0, 0));
 #endif
 
 #ifdef __NT__
diff --git a/src/pike_memory.c b/src/pike_memory.c
index f5bb736d8043a341b933f3da1ac8a76d2f0cb636..a4c00de80b1526a76432709b1414ec8b55178dcf 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.36 1999/04/01 17:21:07 hubbe Exp $");
+RCSID("$Id: pike_memory.c,v 1.37 1999/05/02 08:11:46 hubbe Exp $");
 
 /* strdup() is used by several modules, so let's provide it */
 #ifndef HAVE_STRDUP
@@ -622,7 +622,7 @@ static MUTEX_T debug_malloc_mutex;
 #undef main
 
 static void add_location(struct memhdr *mh, int locnum);
-static struct memhdr *find_memhdr(void *p);
+static struct memhdr *my_find_memhdr(void *, int);
 
 #include "block_alloc.h"
 
@@ -630,10 +630,9 @@ int verbose_debug_malloc = 0;
 int verbose_debug_exit = 1;
 int debug_malloc_check_all = 0;
 
-#define HSIZE 1109891
 #define LHSIZE 1109891
 #define FLSIZE 8803
-#define DEBUG_MALLOC_PAD 8
+#define DEBUG_MALLOC_PAD 32
 #define FREE_DELAY 4096
 #define MAX_UNFREE_MEM 1024*1024*32
 
@@ -650,6 +649,11 @@ struct fileloc
   int number;
 };
 
+
+/* Hepp, we cannot do dmalloc on dmalloc structures... */
+#undef DO_IF_DMALLOC
+#define DO_IF_DMALLOC(X)
+
 BLOCK_ALLOC(fileloc, 4090)
 
 struct memloc
@@ -660,22 +664,24 @@ struct memloc
   int times;
 };
 
+#define MEM_PADDED 1
+
 BLOCK_ALLOC(memloc, 16382)
 
 struct memhdr
 {
   struct memhdr *next;
   long size;
+  int flags;
   void *data;
   struct memloc *locations;
 };
 
 static struct fileloc *flhash[FLSIZE];
 static struct memloc *mlhash[LHSIZE];
-static struct memhdr *hash[HSIZE];
 
 static struct memhdr no_leak_memlocs;
-static int file_location_number=0;
+static int file_location_number=1;
 
 #if DEBUG_MALLOC_PAD - 0 > 0
 char *do_pad(char *mem, long size)
@@ -686,12 +692,20 @@ char *do_pad(char *mem, long size)
   
 /*  fprintf(stderr,"Padding  %p(%d) %ld\n",mem, size, q); */
 #if 1
-  for(e=0;e< DEBUG_MALLOC_PAD; e++)
+  for(e=0;e< DEBUG_MALLOC_PAD; e+=4)
   {
-    char tmp=q|1;
+    char tmp;
     q=(q<<13) ^ ~(q>>5);
-    mem[e-DEBUG_MALLOC_PAD] = tmp;
-    mem[size+e] = tmp;
+
+#define BLORG(X,Y)				\
+    tmp=(Y);					\
+    mem[e+(X)-DEBUG_MALLOC_PAD] = tmp;		\
+    mem[size+e+(X)] = tmp;
+
+    BLORG(0, (q) | 1)
+    BLORG(1, (q >> 5) | 1)
+    BLORG(2, (q >> 10) | 1)
+    BLORG(3, (q >> 15) | 1)
   }
 #endif
   return mem;
@@ -705,6 +719,7 @@ void check_pad(struct memhdr *mh, int freeok)
   long size=mh->size;
   if(out_biking) return;
 
+  if(!(mh->flags & MEM_PADDED)) return;
   if(size < 0)
   {
     if(!freeok)
@@ -720,24 +735,37 @@ void check_pad(struct memhdr *mh, int freeok)
 
 /*  fprintf(stderr,"Checking %p(%d) %ld\n",mem, size, q);  */
 #if 1
-  for(e=0;e< DEBUG_MALLOC_PAD; e++)
+  for(e=0;e< DEBUG_MALLOC_PAD; e+=4)
   {
-    char tmp=q|1;
+    char tmp;
     q=(q<<13) ^ ~(q>>5);
-    if(mem[e-DEBUG_MALLOC_PAD] != tmp)
-    {
-      out_biking=1;
-      fprintf(stderr,"Pre-padding overwritten for block at %p (size %ld) (e=%ld %d!=%d)!\n",mem, size, e, tmp, mem[e-DEBUG_MALLOC_PAD]);
-      describe(mem);
-      abort();
-    }
-    if(mem[size+e] != tmp)
-    {
-      out_biking=1;
-      fprintf(stderr,"Post-padding overwritten for block at %p (size %ld) (e=%ld %d!=%d)!\n",mem, size, e, tmp, mem[size+e]);
-      describe(mem);
-      abort();
+
+#undef BLORG
+#define BLORG(X,Y) 						\
+    tmp=(Y);                                                    \
+    if(mem[e+(X)-DEBUG_MALLOC_PAD] != tmp)			\
+    {								\
+      out_biking=1;						\
+      fprintf(stderr,"Pre-padding overwritten for "		\
+	      "block at %p (size %ld) (e=%ld %d!=%d)!\n",	\
+	      mem, size, e, tmp, mem[e-DEBUG_MALLOC_PAD]);	\
+      describe(mem);						\
+      abort();							\
+    }								\
+    if(mem[size+e+(X)] != tmp)					\
+    {								\
+      out_biking=1;						\
+      fprintf(stderr,"Post-padding overwritten for "		\
+	      "block at %p (size %ld) (e=%ld %d!=%d)!\n",	\
+	      mem, size, e, tmp, mem[size+e]);			\
+      describe(mem);						\
+      abort();							\
     }
+
+    BLORG(0, (q) | 1)
+    BLORG(1, (q >> 5) | 1)
+    BLORG(2, (q >> 10) | 1)
+    BLORG(3, (q >> 15) | 1)
   }
 #endif
 }
@@ -796,7 +824,7 @@ void low_add_marks_to_memhdr(struct memhdr *to,
 
 void add_marks_to_memhdr(struct memhdr *to, void *ptr)
 {
-  low_add_marks_to_memhdr(to,find_memhdr(ptr));
+  low_add_marks_to_memhdr(to,my_find_memhdr(ptr,0));
 }
 
 static inline unsigned long lhash(struct memhdr *m, int locnum)
@@ -812,7 +840,7 @@ static inline unsigned long lhash(struct memhdr *m, int locnum)
 #undef INIT_BLOCK
 #undef EXIT_BLOCK
 
-#define INIT_BLOCK(X) X->locations=0
+#define INIT_BLOCK(X) X->locations=0; X->flags=0;
 #define EXIT_BLOCK(X) do {				\
   struct memloc *ml;					\
   while((ml=X->locations))				\
@@ -825,7 +853,7 @@ static inline unsigned long lhash(struct memhdr *m, int locnum)
   }							\
 }while(0)
 
-BLOCK_ALLOC(memhdr,16382)
+PTR_HASH_ALLOC(memhdr,16382)
 
 #undef INIT_BLOCK
 #undef EXIT_BLOCK
@@ -834,17 +862,18 @@ BLOCK_ALLOC(memhdr,16382)
 #define EXIT_BLOCK(X)
 
 
-static struct memhdr *find_memhdr(void *p)
+
+static struct memhdr *my_find_memhdr(void *p, int already_gone)
 {
-  struct memhdr *mh,**prev;
-  unsigned long h;
+  struct memhdr *mh;
 
 #if DEBUG_MALLOC_PAD - 0 > 0
   if(debug_malloc_check_all)
   {
-    for(h=0;h<HSIZE;h++)
+    long h;
+    for(h=0;h<memhdr_hash_table_size;h++)
     {
-      for(mh=hash[h]; mh; mh=mh->next)
+      for(mh=memhdr_hash_table[h]; mh; mh=mh->next)
       {
 	check_pad(mh,1);
       }
@@ -852,20 +881,11 @@ static struct memhdr *find_memhdr(void *p)
   }
 #endif
 
-  h=(long)p;
-  h%=HSIZE;
-  for(prev=hash+h; (mh=*prev); prev=&mh->next)
-  {
-    if(mh->data==p)
-    {
-      *prev=mh->next;
-      mh->next=hash[h];
-      hash[h]=mh;
+  if((mh=find_memhdr(p)))
+    if(!already_gone)
       check_pad(mh,0);
-      return mh;
-    }
-  }
-  return NULL;
+
+  return mh;
 }
 
 
@@ -924,43 +944,47 @@ static void add_location(struct memhdr *mh, int locnum)
   mlhash[l]=ml;
 }
 
-static void make_memhdr(void *p, int s, int locnum)
+static struct memhdr *low_make_memhdr(void *p, int s, int locnum)
 {
-  struct memhdr *mh=alloc_memhdr();
+  struct memhdr *mh=get_memhdr(p);
   struct memloc *ml=alloc_memloc();
   unsigned long l=lhash(mh,locnum);
-  unsigned long h=(long)p;
-  h%=HSIZE;
-  
-  mh->next=hash[h];
-  mh->data=p;
+
   mh->size=s;
   mh->locations=ml;
   ml->locnum=locnum;
   ml->next=0;
   ml->times=1;
-  hash[h]=mh;
   mlhash[l]=ml;
+
+  return mh;
+}
+
+void dmalloc_register(void *p, int s, char *file, int line)
+{
+  low_make_memhdr(p,s,location_number(file, line));
 }
 
-static int remove_memhdr(void *p, int already_gone)
+void *dmalloc_accept_leak(void *p)
 {
-  struct memhdr **prev,*mh;
-  unsigned long h=(long)p;
-  h%=HSIZE;
-  for(prev=hash+h;(mh=*prev);prev=&(mh->next))
+  if(p)
   {
-    if(mh->data==p)
-    {
-      if(mh->size < 0) mh->size=~mh->size;
-      if(!already_gone) check_pad(mh,0);
+    struct memhdr *mh;
+    if((mh=my_find_memhdr(p,0))) add_location(mh, 0);
+  }
+  return p;
+}
 
-      *prev=mh->next;
-      low_add_marks_to_memhdr(&no_leak_memlocs, mh);
-      really_free_memhdr(mh);
-      
-      return 1;
-    }
+int dmalloc_unregister(void *p, int already_gone)
+{
+  struct memhdr *mh=find_memhdr(p);
+  if(mh)
+  {
+    if(mh->size < 0) mh->size=~mh->size;
+    if(!already_gone) check_pad(mh,0);
+    low_add_marks_to_memhdr(&no_leak_memlocs, mh);
+    remove_memhdr(p);
+    return 1;
   }
   return 0;
 }
@@ -975,7 +999,7 @@ void *debug_malloc(size_t s, const char *fn, int line)
   if(m)
   {
     m=do_pad(m, s);
-    make_memhdr(m, s, location_number(fn,line));
+    low_make_memhdr(m, s, location_number(fn,line))->flags|=MEM_PADDED;
   }
 
   if(verbose_debug_malloc)
@@ -1003,16 +1027,13 @@ void *debug_realloc(void *p, size_t s, const char *fn, int line)
   char *m,*base;
   mt_lock(&debug_malloc_mutex);
 
-  base=find_memhdr(p) ?  (void *)(((char *)p)-DEBUG_MALLOC_PAD): p;
+  base=my_find_memhdr(p,0) ?  (void *)(((char *)p)-DEBUG_MALLOC_PAD): p;
   m=realloc(base, s+DEBUG_MALLOC_PAD*2);
 
   if(m) {
     m=do_pad(m, s);
-    if(m != base)
-    {
-      if(p) remove_memhdr(p,1);
-      make_memhdr(m, s, location_number(fn,line));
-    }
+    if(p) dmalloc_unregister(p,1);
+    low_make_memhdr(m, s, location_number(fn,line))->flags|=MEM_PADDED;
   }
   if(verbose_debug_malloc)
     fprintf(stderr, "realloc(%p,%d) => %p  (%s:%d)\n", p, s, m, fn,line);
@@ -1020,14 +1041,22 @@ void *debug_realloc(void *p, size_t s, const char *fn, int line)
   return m;
 }
 
-void debug_free(void *p, const char *fn, int line)
+void debug_free(void *p, const char *fn, int line, int mustfind)
 {
   struct memhdr *mh;
   if(!p) return;
   mt_lock(&debug_malloc_mutex);
   if(verbose_debug_malloc)
     fprintf(stderr, "free(%p) (%s:%d)\n", p, fn,line);
-  if(!exiting && (mh=find_memhdr(p)))
+  mh=my_find_memhdr(p,0);
+
+  if(!mh && mustfind && p)
+  {
+    fprintf(stderr,"Lost track of a mustfind memory block: %p!\n",p);
+    abort();
+  }
+
+  if(!exiting && mh)
   {
     void *p2;
     MEMSET(p, 0x55, mh->size);
@@ -1039,14 +1068,41 @@ void debug_free(void *p, const char *fn, int line)
       blocks_to_free_ptr%=FREE_DELAY;
       p2=blocks_to_free[blocks_to_free_ptr];
       blocks_to_free[blocks_to_free_ptr]=p;
-      p=p2;
+      if((p=p2))
+      {
+	mh=my_find_memhdr(p,1);
+	if(!mh)
+	{
+	  fprintf(stderr,"Lost track of a freed memory block: %p!\n",p);
+	  abort();
+	}
+      }else{
+	mh=0;
+      }
     }
   }
-  if(remove_memhdr(p,0))  p=((char *)p) - DEBUG_MALLOC_PAD;
-  free(p);
+  
+  if(mh)
+  {
+    free( ((char *)p) - DEBUG_MALLOC_PAD );
+    if(!dmalloc_unregister(p,1))
+    {
+      fprintf(stderr,"Lost track of a memory block (2): %p!\n",p);
+      abort();
+    }
+  }
+  else
+  {
+    free(p);
+  }
   mt_unlock(&debug_malloc_mutex);
 }
 
+void dmalloc_free(void *p)
+{
+  debug_free(p, __FILE__, __LINE__, 0);
+}
+
 char *debug_strdup(const char *s, const char *fn, int line)
 {
   char *m;
@@ -1080,7 +1136,7 @@ void dump_memhdr_locations(struct memhdr *from,
 
 void debug_malloc_dump_references(void *x)
 {
-  dump_memhdr_locations(find_memhdr(x),0);
+  dump_memhdr_locations(my_find_memhdr(x,0),0);
 }
 
 void cleanup_memhdrs()
@@ -1092,7 +1148,7 @@ void cleanup_memhdrs()
     void *p;
     if((p=blocks_to_free[h]))
     {
-      if(remove_memhdr(p,0))  p=((char *)p) - DEBUG_MALLOC_PAD;
+      if(dmalloc_unregister(p,0))  p=((char *)p) - DEBUG_MALLOC_PAD;
       free(p);
       blocks_to_free[h]=0;
     }
@@ -1102,15 +1158,20 @@ void cleanup_memhdrs()
   if(verbose_debug_exit)
   {
     int first=1;
-    for(h=0;h<HSIZE;h++)
+    for(h=0;h<memhdr_hash_table_size;h++)
     {
       struct memhdr *m;
-      for(m=hash[h];m;m=m->next)
+      for(m=memhdr_hash_table[h];m;m=m->next)
       {
 	struct memhdr *tmp;
 	struct memloc *l;
 	void *p=m->data;
 
+	for(l=m->locations;l;l=l->next)
+          if(!l->locnum)
+            break;
+	if(l) continue; /* acceptable leak */
+
 	mt_unlock(&debug_malloc_mutex);
 	if(first)
 	{
@@ -1126,7 +1187,7 @@ void cleanup_memhdrs()
 	mt_lock(&debug_malloc_mutex);
 
 	/* Now we must reassure 'm' */
-	for(tmp=hash[h];tmp;tmp=tmp->next)
+	for(tmp=memhdr_hash_table[h];tmp;tmp=tmp->next)
 	  if(m==tmp)
 	    break;
 
@@ -1157,7 +1218,14 @@ void cleanup_memhdrs()
 int main(int argc, char *argv[])
 {
   extern int dbm_main(int, char **);
+
+#if DEBUG_MALLOC_PAD & 3
+  fprintf(stderr,"DEBUG_MALLOC_PAD not dividable by four!\n");
+  exit(99);
+#endif
+    
   mt_init(&debug_malloc_mutex);
+  init_memhdr_hash();
   return dbm_main(argc, argv);
 }
 
@@ -1166,7 +1234,7 @@ void * debug_malloc_update_location(void *p,const char *fn, int line)
   if(p)
   {
     struct memhdr *mh;
-    if((mh=find_memhdr(p)))
+    if((mh=my_find_memhdr(p,0)))
       add_location(mh, location_number(fn,line));
   }
   return p;
@@ -1175,10 +1243,10 @@ void * debug_malloc_update_location(void *p,const char *fn, int line)
 void reset_debug_malloc(void)
 {
   INT32 h;
-  for(h=0;h<HSIZE;h++)
+  for(h=0;h<memhdr_hash_table_size;h++)
   {
     struct memhdr *m;
-    for(m=hash[h];m;m=m->next)
+    for(m=memhdr_hash_table[h];m;m=m->next)
     {
       struct memloc *l;
       for(l=m->locations;l;l=l->next)
diff --git a/src/program.c b/src/program.c
index e03168d6d037a2124008fb6baff8297c2fc76e1b..c03b2aaac7a6fb15d7ed15300b86f5afa027a72c 100644
--- a/src/program.c
+++ b/src/program.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: program.c,v 1.122 1999/05/01 16:33:11 grubba Exp $");
+RCSID("$Id: program.c,v 1.123 1999/05/02 08:11:47 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -418,7 +418,7 @@ void optimize_program(struct program *p)
 #define FOO(NUMTYPE,TYPE,NAME) \
   size=DO_ALIGN(size, ALIGNOF(TYPE)); \
   MEMCPY(data+size,p->NAME,p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0])); \
-  free((char *)p->NAME); \
+  dmfree((char *)p->NAME); \
   p->NAME=(TYPE *)(data+size); \
   size+=p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0]);
 #include "program_areas.h"
@@ -682,17 +682,17 @@ void really_free_program(struct program *p)
   if(p->flags & PROGRAM_OPTIMIZED)
   {
     if(p->program)
-      free(p->program);
+      dmfree(p->program);
 #define FOO(NUMTYPE,TYPE,NAME) p->NAME=0;
 #include "program_areas.h"
   }else{
 #define FOO(NUMTYPE,TYPE,NAME) \
-    if(p->NAME) { free((char *)p->NAME); p->NAME=0; }
+    if(p->NAME) { dmfree((char *)p->NAME); p->NAME=0; }
 #include "program_areas.h"
   }
   
   FREE_PROT(p);
-  free((char *)p);
+  dmfree((char *)p);
   
   GC_FREE();
 }
@@ -746,7 +746,7 @@ static void toss_compilation_resources(void)
 
   if(malloc_size_program)
     {
-      free((char *)malloc_size_program);
+      dmfree((char *)malloc_size_program);
       malloc_size_program=0;
     }
 
@@ -2801,7 +2801,7 @@ void pop_compiler_frame(void)
     free_string(f->current_return_type);
 
   compiler_frame=f->previous;
-  free((char *)f);
+  dmfree((char *)f);
 }
 
 
diff --git a/src/signal_handler.c b/src/signal_handler.c
index ccb59789944673ef254ee2fa84530662f33e26fc..427a2a371318613587341f65e642f3319c3dc991 100644
--- a/src/signal_handler.c
+++ b/src/signal_handler.c
@@ -25,7 +25,7 @@
 #include "main.h"
 #include <signal.h>
 
-RCSID("$Id: signal_handler.c,v 1.128 1999/05/01 13:37:08 grubba Exp $");
+RCSID("$Id: signal_handler.c,v 1.129 1999/05/02 08:11:48 hubbe Exp $");
 
 #ifdef HAVE_PASSWD_H
 # include <passwd.h>
@@ -530,6 +530,7 @@ static void f_signal(int args)
     signal_evaluator_callback=add_to_callback(&evaluator_callbacks,
 					      check_signals,
 					      0,0);
+    dmalloc_accept_leak(signal_evaluator_callback);
   }
 
   if(args == 1)
@@ -2208,6 +2209,7 @@ void f_create_process(INT32 args)
 	signal_evaluator_callback=add_to_callback(&evaluator_callbacks,
 						  check_signals,
 						  0,0);
+	dmalloc_accept_leak(signal_evaluator_callback);
       }
 #endif
 
@@ -2542,6 +2544,7 @@ void f_fork(INT32 args)
       signal_evaluator_callback=add_to_callback(&evaluator_callbacks,
 						check_signals,
 						0,0);
+      dmalloc_accept_leak(signal_evaluator_callback);
     }
 #endif
 
@@ -2860,6 +2863,7 @@ void init_signals(void)
     signal_evaluator_callback=add_to_callback(&evaluator_callbacks,
 					      check_signals,
 					      0,0);
+    dmalloc_accept_leak(signal_evaluator_callback);
   }
 
 #ifdef USE_PID_MAPPING
diff --git a/src/stralloc.c b/src/stralloc.c
index ef6af50733bf08916d0e37558d07f20628e67b7a..d07f13d955890b9d4f320c89775a736d8183e139 100644
--- a/src/stralloc.c
+++ b/src/stralloc.c
@@ -23,7 +23,7 @@
 #define HUGE HUGE_VAL
 #endif /*!HUGE*/
 
-RCSID("$Id: stralloc.c,v 1.58 1999/04/01 17:20:17 hubbe Exp $");
+RCSID("$Id: stralloc.c,v 1.59 1999/05/02 08:11:49 hubbe Exp $");
 
 #define BEGIN_HASH_SIZE 997
 #define MAX_AVG_LINK_LENGTH 3
@@ -638,7 +638,7 @@ void really_free_string(struct pike_string *s)
   }
 #endif
   unlink_pike_string(s);
-  free((char *)s);
+  debug_free((char *)s,__FILE__,__LINE__,1);
 }
 
 void debug_free_string(struct pike_string *s)
diff --git a/src/threads.c b/src/threads.c
index 48c21667649db81e61a3cc4de039a0e013f96a6e..71ebc4a70ec5f26dd00ad12613c2468cd61f7ac4 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -1,5 +1,5 @@
 #include "global.h"
-RCSID("$Id: threads.c,v 1.92 1999/04/02 23:23:47 hubbe Exp $");
+RCSID("$Id: threads.c,v 1.93 1999/05/02 08:11:50 hubbe Exp $");
 
 int num_threads = 1;
 int threads_disabled = 0;
@@ -560,6 +560,7 @@ void f_thread_create(INT32 args)
     {
       threads_evaluator_callback=add_to_callback(&evaluator_callbacks,
 						 check_threads, 0,0);
+      dmalloc_accept_leak(threads_evaluator_callback);
     }
     ref_push_object(arg->id);
     THREADS_FPRINTF(0, (stderr, "THREAD_CREATE -> t:%08x\n",