diff --git a/com32/include/sys/module.h b/com32/include/sys/module.h
index 64f1827..87440ab 100644
--- a/com32/include/sys/module.h
+++ b/com32/include/sys/module.h
@@ -11,9 +11,9 @@
 #include <stdio.h>
 #include <elf.h>
 #include <stdint.h>
+#include <setjmp.h>
 #include <linux/list.h>
 
-
 /*
  * The maximum length of the module file name (including path), stored
  * in the struct module descriptor.
@@ -77,6 +77,7 @@ typedef int (*module_main_t)(int, char**);
  *  predecessors and successors. There is also a global linked list containing all
  *  the modules currently loaded.
  */
+struct atexit;
 struct elf_module {
 	char				name[MODULE_NAME_SIZE]; 		// The module name
 
@@ -88,7 +89,7 @@ struct elf_module {
 
 	module_init_t		*init_func;	// The initialization entry point
 	module_exit_t		*exit_func;	// The module finalization code
-	module_main_t		*main_func; // The main function (for executable modules)
+        module_main_t		*main_func; // The main function (for executable modules)
 
 
 	void				*module_addr; // The module location in the memory
@@ -106,10 +107,19 @@ struct elf_module {
 	Elf32_Word			syment_size;	// The size of a symbol entry
 	Elf32_Word			symtable_size;	// The size of the symbol table
 
-
-	// Transient - Data available while the module is loading
-	FILE				*_file;	// The file object of the open file
-	Elf32_Off			_cr_offset; // The current offset in the open file
+	union {
+		// Transient - Data available while the module is loading
+		struct {
+			FILE		*_file;		// The file object of the open file
+			Elf32_Off	_cr_offset;	// The current offset in the open file
+		} l;
+
+		// Process execution data
+		struct {
+			jmp_buf		process_exit;	// Exit state
+			struct atexit  *atexit_list;	// atexit() chain
+		} x;
+	} u;
 };
 
 /**
@@ -312,6 +322,15 @@ static inline void *module_get_absolute(Elf32_Addr addr, struct elf_module *modu
 	return (void*)(module->base_addr + addr);
 }
 
+/**
+ * syslinux_current - get the current module process
+ */
+extern struct elf_module *__syslinux_current;
+static inline const struct elf_module *syslinux_current(void)
+{
+	return __syslinux_current;
+}
+
 #endif // DYNAMIC_MODULE
 
 #endif // MODULE_H_
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index 77bda08..fe2923d 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -67,8 +67,7 @@ LIBSYSLINUX_OBJS = \
 	syslinux/setadv.o
 
 DYNENTRY_OBJS = \
-	sys/entry.o atexit.o exit.o onexit.o	\
-	sys/exit.o abort.o 
+	atexit.o exit.o onexit.o abort.o 
 
 ## CORE OBJECTS, INCLUDED IN THE ROOT COM32 MODULE
 LIBENTRY_OBJS = \
diff --git a/com32/lib/exit.c b/com32/lib/exit.c
index ccd6f1e..a5aba18 100644
--- a/com32/lib/exit.c
+++ b/com32/lib/exit.c
@@ -31,11 +31,28 @@
  * The regular exit
  */
 
+#include <sys/module.h>
 #include <stdlib.h>
-
-extern __noreturn(*__exit_handler) (int);
+#include <unistd.h>
+#include "atexit.h"
 
 __noreturn exit(int rv)
 {
-    __exit_handler(rv);
+    struct atexit *ap;
+
+    for (ap = __syslinux_current->u.x.atexit_list; ap; ap = ap->next) {
+	ap->fctn(rv, ap->arg);	/* This assumes extra args are harmless */
+    }
+
+    _exit(rv);
+}    
+
+__noreturn _Exit(int rv)
+{
+    _exit(rv);
+}
+
+__noreturn _exit(int rv)
+{
+    longjmp(__syslinux_current->u.x.process_exit, rv+1);
 }
diff --git a/com32/lib/onexit.c b/com32/lib/onexit.c
index d409e82..8c45e3b 100644
--- a/com32/lib/onexit.c
+++ b/com32/lib/onexit.c
@@ -4,22 +4,9 @@
 
 #include <stdlib.h>
 #include <unistd.h>
+#include <sys/module.h>
 #include "atexit.h"
 
-extern __noreturn(*__exit_handler) (int);
-static struct atexit *__atexit_list;
-
-static __noreturn on_exit_exit(int rv)
-{
-    struct atexit *ap;
-
-    for (ap = __atexit_list; ap; ap = ap->next) {
-	ap->fctn(rv, ap->arg);	/* This assumes extra args are harmless */
-    }
-
-    _exit(rv);
-}
-
 int on_exit(void (*fctn) (int, void *), void *arg)
 {
     struct atexit *as = malloc(sizeof(struct atexit));
@@ -30,10 +17,8 @@ int on_exit(void (*fctn) (int, void *), void *arg)
     as->fctn = fctn;
     as->arg = arg;
 
-    as->next = __atexit_list;
-    __atexit_list = as;
-
-    __exit_handler = on_exit_exit;
+    as->next = __syslinux_current->u.x.atexit_list;
+    __syslinux_current->u.x.atexit_list = as;
 
     return 0;
 }
diff --git a/com32/lib/sys/entry.S b/com32/lib/sys/entry.S
deleted file mode 100644
index a3a1eaa..0000000
--- a/com32/lib/sys/entry.S
+++ /dev/null
@@ -1,118 +0,0 @@
-/* -----------------------------------------------------------------------
- *
- *   Copyright 2003-2008 H. Peter Anvin - All Rights Reserved
- *
- *   Permission is hereby granted, free of charge, to any person
- *   obtaining a copy of this software and associated documentation
- *   files (the "Software"), to deal in the Software without
- *   restriction, including without limitation the rights to use,
- *   copy, modify, merge, publish, distribute, sublicense, and/or
- *   sell copies of the Software, and to permit persons to whom
- *   the Software is furnished to do so, subject to the following
- *   conditions:
- *
- *   The above copyright notice and this permission notice shall
- *   be included in all copies or substantial portions of the Software.
- *
- *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *   OTHER DEALINGS IN THE SOFTWARE.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * COM32 start up code - must be linked first in the binary
- */
-
-/* Number of arguments in our version of the entry structure */
-#define COM32_ARGS 7
-
-		.section ".init","ax"
-		.globl _start
-		.type _start, @function
-_start:
-		/* This first instruction acts as COM32R magic number */
-		movl $0x21cd4cfe,%eax
-
-		/* Upwards string operations */
-		cld
-
-		/* Find our own location */
-		call 1f
-1:		popl %ebx
-		addl $_GLOBAL_OFFSET_TABLE_ + (. - 1b), %ebx
-	
-		/* Process relocations (which overlay the .bss segment) */
-		leal _edata@GOTOFF(%ebx),%esi
-		leal _start@GOTOFF(%ebx),%edx
-2:		lodsl
-		andl %eax,%eax
-		jz 3f
-		addl %edx,(%eax,%edx)
-		jmp 2b
-3:
-		/* Relocate the GOT (is this right?) */
-		leal __got_start@GOTOFF(%ebx),%esi
-		leal __got_end@GOTOFF(%ebx),%edi
-4:
-		addl %edx,(%esi)
-		addl $4,%esi
-		cmpl %edi,%esi
-		jb 4b
-	
-		/* Zero the .bss segment */
-		xorl %eax,%eax
-		leal __bss_start@GOTOFF(%ebx),%edi
-		leal _end+3@GOTOFF(%ebx),%ecx
-		subl %edi,%ecx
-		shrl $2,%ecx
-		rep ; stosl
-
-		/* Copy COM32 invocation parameters */
-		leal 4(%esp),%esi		# Argument list
-		leal __com32@GOTOFF(%ebx),%edi
-		movl $(COM32_ARGS),%ecx
-		movl %esp,-4(%edi)		# Save the initial stack ptr
-		cmpl (%esi),%ecx
-		jbe 5f
-		movl (%esi),%ecx
-5:		inc %ecx			# Copy the argument count, too
-		rep ; movsl
-
-		/* Parse the command line (assumes REGPARM) */
-		movl __com32+4@GOTOFF(%ebx),%edx	# Command line
-		pushl %edx				# Make space for argv
-		movl %esp,%eax
-		call __parse_argv
-		pushl %eax				# Save argc
-
-		/* Look for library initialization functions */
-		leal __ctors_start@GOTOFF(%ebx),%esi
-		leal __ctors_end@GOTOFF(%ebx),%edi
-6:
-		cmpl %edi,%esi
-		jae 7f
-		call *(%esi)
-		addl $4,%esi
-		jmp 6b
-/*
- * Actually run main.  This assumes REGPARM is used!!!!
- */
-7:
-		popl %eax			# argc
-		popl %edx			# argv
-		call main
-		call *__exit_handler@GOTOFF(%ebx)
-		hlt
-		.size _start, .-_start
-
-		.bss
-		.globl __entry_esp
-__entry_esp:	.space 4
-		.globl __com32
-__com32:	.space 4*(COM32_ARGS+1)
diff --git a/com32/lib/sys/exit.S b/com32/lib/sys/exit.S
deleted file mode 100644
index 2ab8012..0000000
--- a/com32/lib/sys/exit.S
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Implementation of _exit() for com32 based on c32entry.S
- */
-	.text
-
-	.globl _Exit
-	.type _Exit, @function
-_Exit:
-	/* Just fall through to _exit */
-	.size _Exit, .-_Exit
-
-	.globl _exit
-	.type _exit, @function
-_exit:
-#ifdef REGPARM
-	pushl %eax
-#endif
-
-	/* Run any destructors */
-	movl $__dtors_start, %esi
-2:
-	cmpl $__dtors_end, %esi
-	jae 1f
-	call *(%esi)
-	addl $4,%esi
-	jmp 2b
-
-1:
-#ifdef REGPARM
-	popl %eax
-#else
-	movl 4(%esp),%eax		# Exit code in %eax = return value
-#endif
-	movl (__entry_esp),%esp		# Return stack pointer to entry value
-	ret				# Return to termination address
-	.size _exit, .-_exit
-
-	.data
-__exit_handler:
-	.globl __exit_handler
-	.long _exit
diff --git a/com32/lib/sys/module/common.c b/com32/lib/sys/module/common.c
index ad17efa..5c8d34d 100644
--- a/com32/lib/sys/module/common.c
+++ b/com32/lib/sys/module/common.c
@@ -59,21 +59,21 @@ void print_elf_symbols(struct elf_module *module) {
  */
 
 int image_load(struct elf_module *module) {
-	module->_file = fopen(module->name, "rb");
+	module->u.l._file = fopen(module->name, "rb");
 
-	if (module->_file == NULL) {
+	if (module->u.l._file == NULL) {
 		DBG_PRINT("Could not open object file '%s'\n", module->name);
 		goto error;
 	}
 
-	module->_cr_offset = 0;
+	module->u.l._cr_offset = 0;
 
 	return 0;
 
 error:
-	if (module->_file != NULL) {
-		fclose(module->_file);
-		module->_file = NULL;
+	if (module->u.l._file != NULL) {
+		fclose(module->u.l._file);
+		module->u.l._file = NULL;
 	}
 
 	return -1;
@@ -81,22 +81,22 @@ error:
 
 
 int image_unload(struct elf_module *module) {
-	if (module->_file != NULL) {
-		fclose(module->_file);
-		module->_file = NULL;
+	if (module->u.l._file != NULL) {
+		fclose(module->u.l._file);
+		module->u.l._file = NULL;
 	}
-	module->_cr_offset = 0;
+	module->u.l._cr_offset = 0;
 
 	return 0;
 }
 
 int image_read(void *buff, size_t size, struct elf_module *module) {
-	size_t result = fread(buff, size, 1, module->_file);
+	size_t result = fread(buff, size, 1, module->u.l._file);
 
 	if (result < 1)
 		return -1;
 
-	module->_cr_offset += size;
+	module->u.l._cr_offset += size;
 	return 0;
 }
 
@@ -108,21 +108,21 @@ int image_skip(size_t size, struct elf_module *module) {
 		return 0;
 
 	skip_buff = malloc(size);
-	result = fread(skip_buff, size, 1, module->_file);
+	result = fread(skip_buff, size, 1, module->u.l._file);
 	free(skip_buff);
 
 	if (result < 1)
 		return -1;
 
-	module->_cr_offset += size;
+	module->u.l._cr_offset += size;
 	return 0;
 }
 
 int image_seek(Elf32_Off offset, struct elf_module *module) {
-	if (offset < module->_cr_offset) // Cannot seek backwards
+	if (offset < module->u.l._cr_offset) // Cannot seek backwards
 		return -1;
 
-	return image_skip(offset - module->_cr_offset, module);
+	return image_skip(offset - module->u.l._cr_offset, module);
 }
 
 
diff --git a/com32/lib/sys/module/elf_module.c b/com32/lib/sys/module/elf_module.c
index bf3e4a4..c5992fb 100644
--- a/com32/lib/sys/module/elf_module.c
+++ b/com32/lib/sys/module/elf_module.c
@@ -128,11 +128,12 @@ static int load_segments(struct elf_module *module, Elf32_Ehdr *elf_hdr) {
 
 		if (cr_pht->p_type == PT_LOAD) {
 			// Copy the segment at its destination
-			if (cr_pht->p_offset < module->_cr_offset) {
+			if (cr_pht->p_offset < module->u.l._cr_offset) {
 				// The segment contains data before the current offset
 				// It can be discarded without worry - it would contain only
 				// headers
-				Elf32_Off aux_off = module->_cr_offset - cr_pht->p_offset;
+				Elf32_Off aux_off = module->u.l._cr_offset
+					- cr_pht->p_offset;
 
 				if (image_read(module_get_absolute(cr_pht->p_vaddr, module) + aux_off,
 						cr_pht->p_filesz - aux_off, module) < 0) {
@@ -470,8 +471,6 @@ int module_load(struct elf_module *module) {
 	// Perform the relocations
 	resolve_symbols(module);
 
-
-
 	// The file image is no longer needed
 	image_unload(module);
 
@@ -494,5 +493,8 @@ error:
 
 	image_unload(module);
 
+	// Clear the execution part of the module buffer
+	memset(&module->u, 0, sizeof module->u);
+
 	return res;
 }
diff --git a/com32/lib/sys/module/exec.c b/com32/lib/sys/module/exec.c
index 34578ed..98c8ee6 100644
--- a/com32/lib/sys/module/exec.c
+++ b/com32/lib/sys/module/exec.c
@@ -8,8 +8,10 @@
 #include <sys/module.h>
 #include <sys/exec.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
+#include <setjmp.h>
 
 // The symbol declared in the linker script that indicates the loading point
 // of the COM32R module
@@ -56,7 +58,6 @@ int load_library(const char *name)
 
 	res = module_load(module);
 
-
 	if (res != 0) {
 		module_unload(module);
 		return res;
@@ -107,8 +108,11 @@ int unload_library(const char *name)
 int spawnv(const char *name, const char **argv)
 {
 	int res, ret_val = 0;
-
+	const char **arg;
+	int argc;
 	struct elf_module *module = module_alloc(name);
+	struct elf_module *previous;
+	void *prev_mem_tag;
 
 	if (module == NULL)
 		return -1;
@@ -120,28 +124,36 @@ int spawnv(const char *name, const char **argv)
 		return res;
 	}
 
-	if (module->main_func != NULL) {
-		const char **last_arg = argv;
-		void *old_tag;
-		while (*last_arg != NULL)
-			last_arg++;
-
-		// Setup the memory allocation context
-		old_tag = __mem_get_tag_global();
-		__mem_set_tag_global(module);
-
-		// Execute the program
-		ret_val = (*(module->main_func))(last_arg - argv, argv);
-
-		// Clean up the allocation context
-		__free_tagged(module);
-		// Restore the allocation context
-		__mem_set_tag_global(old_tag);
+	for (arg = argv; *arg; arg++)
+	    ;
+	argc = arg - argv;
+	
+	// Set up the process context
+	previous = __syslinux_current;
+	prev_mem_tag = __mem_get_tag_global();
+
+	// Setup the new process context
+	__syslinux_current = module;
+	__mem_set_tag_global(module);
+
+	// Execute the program
+	ret_val = setjmp(module->u.x.process_exit);
+
+	if (ret_val) {
+	    ret_val--;		/* Valid range is 0-255 */
 	} else {
-		// We can't execute without a main function
-		module_unload(module);
-		return -1;
+	    if (!module->main_func)
+		ret_val = -1;
+	    else
+		ret_val = (*module->main_func)(argc, argv);
 	}
+	
+	// Clean up the allocation context
+	__free_tagged(module);
+	// Restore the allocation context
+	__mem_set_tag_global(prev_mem_tag);
+	// Restore the process context
+	__syslinux_current = previous;
 
 	res = module_unload(module);
 
diff --git a/com32/lib/sys/module/shallow_module.c b/com32/lib/sys/module/shallow_module.c
index fdcb20f..3e14e5a 100644
--- a/com32/lib/sys/module/shallow_module.c
+++ b/com32/lib/sys/module/shallow_module.c
@@ -7,6 +7,7 @@
 
 
 
+#include <string.h>
 #include <sys/module.h>
 
 #include "common.h"
@@ -48,7 +49,7 @@ static int load_shallow_sections(struct elf_module *module, Elf32_Ehdr *elf_hdr)
 	char *sh_strtable;
 
 	// We buffer the data up to the SHT
-	buff_offset = module->_cr_offset;
+	buff_offset = module->u.l._cr_offset;
 
 	buffer = malloc(elf_hdr->e_shoff - buff_offset);
 	// Get to the SHT
