diff --git a/src/object.c b/src/object.c
index 9994d09e4e7acb818aa18364eea0adb23fbef866..2d5ea75b0c5f2322f1fd330f28303456cf3565ff 100644
--- a/src/object.c
+++ b/src/object.c
@@ -3259,6 +3259,97 @@ void init_object(void)
   exit_compiler();
 }
 
+static struct program *shm_program, *sbuf_program, *iobuf_program;
+
+struct sysmem {
+  unsigned char *p;
+  size_t size;
+};
+
+static struct sysmem *system_memory(struct object *o)
+{
+  if( !shm_program )
+  {
+    push_text("System.Memory");
+    SAFE_APPLY_MASTER("resolv", 1);
+    shm_program = program_from_svalue(Pike_sp - 1);
+    if (!shm_program)
+      return 0;
+    Pike_sp--;
+  }
+  return get_storage( o, shm_program );
+}
+
+static struct string_builder *string_buffer(struct object *o)
+{
+  if( !sbuf_program )
+  {
+    push_text("String.Buffer");
+    SAFE_APPLY_MASTER("resolv", 1);
+    sbuf_program = program_from_svalue(Pike_sp - 1);
+    if (!sbuf_program)
+      return 0;
+    Pike_sp--;
+  }
+  return get_storage( o, sbuf_program );
+}
+
+#include "modules/_Stdio/iobuffer.h"
+
+static IOBuffer *io_buffer(struct object *o)
+{
+  if( !iobuf_program )
+  {
+    push_text("Stdio.IOBuffer");
+    SAFE_APPLY_MASTER("resolv", 1);
+    iobuf_program = program_from_svalue(Pike_sp - 1);
+    if (!iobuf_program)
+      return 0;
+    Pike_sp--;
+  }
+  return get_storage( o, iobuf_program );
+}
+
+PMOD_EXPORT enum memobj_type get_memory_object_memory( struct object *o, void **ptr, size_t *len, int *shift )
+{
+  union {
+    struct string_builder *b;
+    struct sysmem *s;
+    IOBuffer *io;
+  } src;
+
+  if( (src.b = string_buffer(o)) )
+  {
+    if( src.b->s->size_shift )
+    {
+      if( shift )
+        *shift = src.b->s->size_shift;
+      else
+        return MEMOBJ_NONE;
+    }
+    if( len ) *len = src.b->s->len;
+    if( ptr ) *ptr = src.b->s->str;
+    return MEMOBJ_STRING_BUFFER;
+  }
+
+  if( (src.io = io_buffer( o )) )
+  {
+    if( shift ) *shift=0;
+    if( len ) *len = src.io->len-src.io->offset;
+    if( ptr ) *ptr=src.io->buffer+src.io->offset;
+    return MEMOBJ_STDIO_IOBUFFER;
+  }
+
+  if( (src.s = system_memory(o)) )
+  {
+    if( shift ) *shift=0;
+    if( len ) *len = src.s->size;
+    if( ptr ) *ptr= src.s->p;
+    return MEMOBJ_SYSTEM_MEMORY;
+  }
+  return MEMOBJ_NONE;
+}
+
 void exit_object(void)
 {
   if (destruct_object_evaluator_callback) {
@@ -3281,6 +3372,23 @@ void exit_object(void)
 
   destruct_objects_to_destruct();
 
+  if( shm_program )
+  {
+      free_program( shm_program );
+      shm_program = 0;
+  }
+  if( sbuf_program )
+  {
+      free_program( sbuf_program );
+      sbuf_program = 0;
+  }
+
+  if( iobuf_program )
+  {
+      free_program( iobuf_program );
+      iobuf_program = 0;
+  }
+
   if(magic_index_program)
   {
     free_program(magic_index_program);
diff --git a/src/object.h b/src/object.h
index 4e3f6d91d2fb795d90bcba3db6791f0d8918bd6e..4d584093e57470414c124de9caea1b6e88689fd7 100644
--- a/src/object.h
+++ b/src/object.h
@@ -142,6 +142,17 @@ PMOD_EXPORT void visit_function (const struct svalue *s, int ref_type,
 				 void *extra);
 PMOD_EXPORT void gc_mark_object_as_referenced(struct object *o);
 PMOD_EXPORT void real_gc_cycle_check_object(struct object *o, int weak);
+
+enum memobj_type{
+    MEMOBJ_NONE,
+    MEMOBJ_SYSTEM_MEMORY,
+    MEMOBJ_STRING_BUFFER,
+    MEMOBJ_STDIO_IOBUFFER,
+};
+
+PMOD_EXPORT enum memobj_type get_memory_object_memory( struct object *o, void **ptr, size_t *len, int *shift );
+
+
 unsigned gc_touch_all_objects(void);
 void gc_check_all_objects(void);
 void gc_mark_all_objects(void);