diff -urN /usr/local/dmd/src/phobos/internal/backtrace_win32.d phobos/internal/backtrace_win32.d
--- /usr/local/dmd/src/phobos/internal/backtrace_win32.d	1970-01-01 09:00:00.000000000 +0900
+++ phobos/internal/backtrace_win32.d	2006-12-09 23:56:23.000000000 +0900
@@ -0,0 +1,20 @@
+private void _d_save_backtrace_ebp(Exception e, void** p) {
+    while (p) {
+        e.backtrace ~= *(cast(void**)p+1);
+        p = cast(void**)*cast(void**)p;
+        if (e.backtrace.length > 100) break;
+    }
+}
+
+extern (C) void _d_save_backtrace(Object o, void** p) {
+    Exception e = cast(Exception)o;
+    if (!e) return;
+    _d_save_backtrace_ebp(e, p);
+}
+
+extern (C) void _d_save_backtrace_se(Object o, void* eip, void* ebp) {
+    Exception e = cast(Exception)o;
+    if (!e) return;
+    e.backtrace ~= eip;
+    _d_save_backtrace_ebp(e, cast(void**)ebp);
+}
diff -urN /usr/local/dmd/src/phobos/internal/deh.c phobos/internal/deh.c
--- /usr/local/dmd/src/phobos/internal/deh.c	2006-12-03 17:19:34.000000000 +0900
+++ phobos/internal/deh.c	2006-12-10 00:38:14.000000000 +0900
@@ -87,9 +87,40 @@
 
 #define STATUS_DIGITAL_MARS_D_EXCEPTION		MAKE_EXCEPTION_CODE(3,'D',1)
 
-Object *_d_translate_se_to_d_exception(EXCEPTION_RECORD *exception_record);
+
+typedef struct {
+    DWORD ContextFlags;
+    DWORD   Dr0;
+    DWORD   Dr1;
+    DWORD   Dr2;
+    DWORD   Dr3;
+    DWORD   Dr6;
+    DWORD   Dr7;
+    FLOATING_SAVE_AREA FloatSave;
+    DWORD   SegGs;
+    DWORD   SegFs;
+    DWORD   SegEs;
+    DWORD   SegDs;
+    DWORD   Edi;
+    DWORD   Esi;
+    DWORD   Ebx;
+    DWORD   Edx;
+    DWORD   Ecx;
+    DWORD   Eax;
+    DWORD   Ebp;
+    DWORD   Eip;
+    DWORD   SegCs;              // MUST BE SANITIZED
+    DWORD   EFlags;             // MUST BE SANITIZED
+    DWORD   Esp;
+    DWORD   SegSs;
+//    BYTE    ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
+} CONTEXT_X86;
+
+Object *_d_translate_se_to_d_exception(EXCEPTION_RECORD *exception_record, CONTEXT_X86 *context);
 void __cdecl _d_local_unwind(struct DHandlerTable *handler_table, struct DEstablisherFrame *frame, int stop_index);
 
+void _d_save_backtrace(Object *h, DWORD ebp);
+void _d_save_backtrace_se(Object *h, DWORD eip, DWORD ebp);
 
 /***********************************
  * The frame handler, this is called for each frame that has been registered
@@ -158,7 +189,7 @@
 		    {   // Matched the catch type, so we've found the handler.
 			int regebp;
 
-			pti = _d_translate_se_to_d_exception(exception_record);
+			pti = _d_translate_se_to_d_exception(exception_record, *(CONTEXT_X86 **)&context);
 
 			// Initialize catch variable
 			regebp = (int)&frame->ebp;		// EBP for this frame
@@ -206,7 +237,7 @@
 			int retval,
 			Object **exception_object) 
 {
-    *exception_object = _d_translate_se_to_d_exception(eptrs->ExceptionRecord);
+    *exception_object = _d_translate_se_to_d_exception(eptrs->ExceptionRecord, NULL);
     return retval;
 }
 
@@ -216,8 +247,10 @@
 
 void __stdcall _d_throw(Object *h)
 {
-    //printf("_d_throw(h = %p, &h = %p)\n", h, &h);
-    //printf("\tvptr = %p\n", *(void **)h);
+    DWORD ebp;
+    ebp = _EBP;
+    _d_save_backtrace(h, ebp);
+
     RaiseException(STATUS_DIGITAL_MARS_D_EXCEPTION,
 		   EXCEPTION_NONCONTINUABLE,
 		   1, (DWORD *)&h);
@@ -246,7 +279,7 @@
  * Converts a Windows Structured Exception code to a D Exception Object.
  */
 
-Object *_d_translate_se_to_d_exception(EXCEPTION_RECORD *exception_record)
+Object *_d_translate_se_to_d_exception(EXCEPTION_RECORD *exception_record, CONTEXT_X86 *context)
 {
     Object *pti;
 
@@ -258,23 +291,28 @@
 
         case STATUS_INTEGER_DIVIDE_BY_ZERO:
             pti = _d_create_exception_object(&_Class_9Exception, "Integer Divide by Zero");
+            if (context) _d_save_backtrace_se(pti, context->Eip, context->Ebp);
             break;
 
         case STATUS_FLOAT_DIVIDE_BY_ZERO:
             pti = _d_create_exception_object(&_Class_9Exception, "Float Divide by Zero");
+            if (context) _d_save_backtrace_se(pti, context->Eip, context->Ebp);
             break;
 
         case STATUS_ACCESS_VIOLATION:
             pti = _d_create_exception_object(&_Class_9Exception, "Access Violation");
+            if (context) _d_save_backtrace_se(pti, context->Eip, context->Ebp);
             break;
 
         case STATUS_STACK_OVERFLOW:
             pti = _d_create_exception_object(&_Class_9Exception, "Stack Overflow");
+            if (context) _d_save_backtrace_se(pti, context->Eip, context->Ebp);
             break;
 
         // convert all other exception codes into a Win32Exception
         default:
             pti = _d_create_exception_object(&_Class_9Exception, "Win32 Exception");
+            if (context) _d_save_backtrace_se(pti, context->Eip, context->Ebp);
             break;
     }
 
diff -urN /usr/local/dmd/src/phobos/internal/deh2.d phobos/internal/deh2.d
--- /usr/local/dmd/src/phobos/internal/deh2.d	2006-12-03 17:19:34.000000000 +0900
+++ phobos/internal/deh2.d	2006-12-09 21:03:31.000000000 +0900
@@ -26,6 +26,7 @@
 //debug=1;
 
 import std.c.linux.linuxextern;
+import std.string;
 
 extern (C) int _d_isbaseof(ClassInfo oc, ClassInfo c);
 
@@ -83,6 +84,64 @@
     }
 }
 
+extern (C) {
+    struct sigval_t {
+	int sigval_int;
+	void *sigval_ptr;
+    }
+    struct siginfo_t {
+	int      si_signo;  /* Signal number */
+	int      si_errno;  /* An errno value */
+	int      si_code;   /* Signal code */
+	int      si_pid;    /* Sending process ID */
+	uint     si_uid;    /* Real user ID of sending process */
+	int      si_status; /* Exit value or signal */
+	int      si_utime;  /* User time consumed */
+	int      si_stime;  /* System time consumed */
+	sigval_t si_value;  /* Signal value */
+	int      si_int;    /* POSIX.1b signal */
+	void *   si_ptr;    /* POSIX.1b signal */
+	void *   si_addr;   /* Memory location which caused fault */
+	int      si_band;   /* Band event */
+	int      si_fd;     /* File descriptor */
+    }
+    struct mcontext_t {
+	uint[19] gregs;
+	/* Due to Linux's history we have to use a pointer here.  The SysV/i386
+	   ABI requires a struct with the values.  */
+	/*
+	  fpregset_t fpregs;
+	  uint oldmask;
+	  uint cr2;
+	*/
+     }
+    struct stack_t {
+	void *ss_sp;
+	int ss_flags;
+	uint ss_size;
+    }
+    struct ucontext_t {
+	uint uc_flags;
+	ucontext_t *uc_link;
+	stack_t uc_stack;
+	mcontext_t uc_mcontext;
+	// __sigset_t uc_sigmask;
+	// struct _libc_fpstate __fpregs_mem;
+    }
+    enum REG {
+	GS, FS, ES, DS, EDI, ESI, EBP, ESP,
+	EBX, EDX, ECX, EAX, TRAPNO, ERR, EIP, CS, EFL, UESP, SS
+    }
+
+    char *strsignal(int id);
+    void __backtrace_handler(int id, siginfo_t *si, ucontext_t *uc) {
+	char *signame = strsignal(id);
+	Exception e = new Exception(toString(signame));
+	e.backtrace ~= cast(void*)uc.uc_mcontext.gregs[REG.EIP];
+	throw e;
+    }
+}
+
 /*******************************************
  * Given address that is inside a function,
  * figure out which function it is in.
@@ -161,6 +220,13 @@
 	mov regebp,EBP	;
     }
 
+    Exception exception = cast(Exception)h;
+    int ignore_count;
+    // dirty, it seems to be from signal handler
+    if (exception && exception.backtrace) {
+	ignore_count = 2;
+    }
+
 //static uint abc;
 //if (++abc == 2) *(char *)0=0;
 
@@ -179,6 +245,15 @@
 	int ndx;
 	int prev_ndx;
 
+	if (exception) {
+	    if (!ignore_count) {
+		exception.backtrace ~= *(cast(void**)regebp+1);
+	    }
+	    else {
+		ignore_count--;
+	    }
+	}
+
         regebp = __eh_find_caller(regebp,&retaddr);
         if (!regebp)
 	{   // if end of call chain
diff -urN /usr/local/dmd/src/phobos/internal/dmain2.d phobos/internal/dmain2.d
--- /usr/local/dmd/src/phobos/internal/dmain2.d	2006-12-03 17:19:34.000000000 +0900
+++ phobos/internal/dmain2.d	2006-12-09 22:59:47.000000000 +0900
@@ -9,6 +9,9 @@
 import std.c.string;
 import std.c.stdlib;
 import std.string;
+import std.file;
+import std.path;
+import std.symtable;
 
 extern (C) void _STI_monitor_staticctor();
 extern (C) void _STD_monitor_staticdtor();
@@ -23,6 +26,30 @@
 
 extern (C) bool no_catch_exceptions;
 
+version (linux) {
+    extern (C) {
+	struct sigaction_t {
+	    union {
+		void *sa_handler;
+		void *sa_sigaction;
+	    }
+	    uint[32] sa_mask;
+	    int sa_flags;
+	    void *sa_restorer;
+	}
+	int sigaction(int signum, sigaction_t *act, sigaction_t *oldact);
+	extern (C) void __backtrace_handler(int id, void *si, void *uc);
+	const int SA_NOCLDSTOP = 1;
+	const int SA_NOCLDWAIT = 2;
+	const int SA_SIGINFO = 4;
+	const int SA_ONSTACK = 0x08000000;
+	const int SA_RESTART = 0x10000000;
+	const int SA_NODEFER = 0x40000000;
+	const int SA_RESETHAND = 0x80000000;
+	const int SA_INTERRUPT = 0x20000000;
+    }
+}
+
 /***********************************
  * The D main() function supplied by the user's program
  */
@@ -51,13 +78,26 @@
 	am = cast(char[] *) malloc(argc * (char[]).sizeof);
 	// BUG: alloca() conflicts with try-catch-finally stack unwinding
 	//am = (char[] *) alloca(argc * (char[]).sizeof);
+
+	sigaction_t sa;
+	sa.sa_sigaction = &__backtrace_handler;
+	sa.sa_flags = SA_SIGINFO;
+	sigaction(1, &sa, null);
+	sigaction(2, &sa, null);
+	sigaction(3, &sa, null);
+	sigaction(4, &sa, null);
+	sigaction(6, &sa, null);
+	sigaction(8, &sa, null);
+	sigaction(11, &sa, null);
+	sigaction(13, &sa, null);
+	sigaction(15, &sa, null);
     }
     version (Win32)
     {
 	gc_init();
 	_minit();
-	am = cast(char[] *) alloca(argc * (char[]).sizeof);
-    }
+	am = cast(char[] *) malloc(argc * (char[]).sizeof);
+     }
 
     if (no_catch_exceptions)
     {
@@ -98,7 +138,37 @@
 	catch (Object o)
 	{
 	    printf("Error: ");
-	    o.print();
+	    Exception e = cast(Exception)o;
+	    if (e) {
+		if (Symtable.getDefaultSymtable()) {
+		    e.print(Symtable.getDefaultSymtable());
+		    exit(EXIT_FAILURE);
+		}
+		version (linux) {
+		    char[] nmfile = addExt(args[0], "nm");
+		    if (exists(nmfile)) {
+			Symtable st =
+			    new Symtable(nmfile, SymtableType.BINUTILS_NM);
+			e.print(st);
+			exit(EXIT_FAILURE);
+		    }
+		}
+		version (Win32) {
+		    char[] mapfile = addExt(args[0], "map");
+		    if (exists(mapfile)) {
+			Symtable st =
+			    new Symtable(mapfile, SymtableType.DMC_MAP);
+			e.print(st);
+			exit(EXIT_FAILURE);
+		    }
+		}
+		Symtable st = new Symtable("", SymtableType.NONE);
+		e.print(st);
+		exit(EXIT_FAILURE);
+	    }
+	    else {
+		o.print();
+	    }
 	    exit(EXIT_FAILURE);
 	}
     }
diff -urN /usr/local/dmd/src/phobos/internal/object.d phobos/internal/object.d
--- /usr/local/dmd/src/phobos/internal/object.d	2006-12-03 17:19:34.000000000 +0900
+++ phobos/internal/object.d	2006-12-09 22:19:57.000000000 +0900
@@ -880,12 +880,15 @@
     }
 }
 
+import std.symtable;
+
 /**
  * All recoverable exceptions should be derived from class Exception.
  */
 class Exception : Object
 {
     char[] msg;
+    void*[] backtrace;
 
     /**
      * Constructor; msg is a descriptive message for the exception.
@@ -900,7 +903,26 @@
 	printf("%.*s\n", toString());
     }
 
-    char[] toString() { return msg; }
+    void print(Object sto) {
+	Symtable st = cast(Symtable)sto;
+	print();
+	if (st && backtrace) {
+	    printf("Backtrace:\n");
+	    foreach (addr; backtrace) {
+		char[] name = st.lookupName(cast(uint)addr);
+		if (name) {
+		    printf("%08x %.*s\n", addr, name);
+		}
+		else {
+		    printf("%08x ???\n", addr, name);
+		}
+	    }
+	}
+    }
+
+    char[] toString() {
+	return msg;
+    }
 }
 
 /**
diff -urN /usr/local/dmd/src/phobos/linux.mak phobos/linux.mak
--- /usr/local/dmd/src/phobos/linux.mak	2006-12-03 17:19:34.000000000 +0900
+++ phobos/linux.mak	2006-12-09 19:49:26.000000000 +0900
@@ -58,7 +58,7 @@
 	socket.o socketstream.o stdarg.o stdio.o format.o \
 	perf.o openrj.o uni.o trace.o boxer.o \
 	demangle.o cover.o bitarray.o bind.o aApplyR.o \
-	signals.o cpuid.o traits.o typetuple.o \
+	signals.o symtable.o cpuid.o traits.o typetuple.o \
 	ti_wchar.o ti_uint.o ti_short.o ti_ushort.o \
 	ti_byte.o ti_ubyte.o ti_long.o ti_ulong.o ti_ptr.o \
 	ti_float.o ti_double.o ti_real.o ti_delegate.o \
@@ -94,7 +94,8 @@
 	std/socket.d std/socketstream.d std/loader.d std/stdarg.d \
 	std/stdio.d std/format.d std/perf.d std/openrj.d std/uni.d \
 	std/boxer.d std/cstream.d std/demangle.d std/cover.d std/bitarray.d \
-	std/signals.d std/cpuid.d std/typetuple.d std/traits.d std/bind.d
+	std/signals.d std/cpuid.d std/typetuple.d std/traits.d std/bind.d \
+    std/symtable.d
 
 SRC_STD_C= std/c/process.d std/c/stdlib.d std/c/time.d std/c/stdio.d \
 	std/c/math.d std/c/stdarg.d std/c/stddef.d std/c/fenv.d std/c/string.d \
@@ -418,6 +419,9 @@
 syserror.o : std/syserror.d
 	$(DMD) -c $(DFLAGS) std/syserror.d
 
+symtable.o : std/symtable.d
+	$(DMD) -c $(DFLAGS) std/symtable.d
+
 thread.o : std/thread.d
 	$(DMD) -c $(DFLAGS) std/thread.d
 
diff -urN /usr/local/dmd/src/phobos/object.d phobos/object.d
--- /usr/local/dmd/src/phobos/object.d	2006-12-03 17:19:34.000000000 +0900
+++ phobos/object.d	2006-12-09 19:47:17.000000000 +0900
@@ -129,9 +129,11 @@
 class Exception : Object
 {
     char[] msg;
+    void*[] backtrace;
 
     this(char[] msg);
     void print();
+    void print(Object st);
     char[] toString();
 }
 
diff -urN /usr/local/dmd/src/phobos/std/symtable.d phobos/std/symtable.d
--- /usr/local/dmd/src/phobos/std/symtable.d	1970-01-01 09:00:00.000000000 +0900
+++ phobos/std/symtable.d	2006-12-09 22:42:59.000000000 +0900
@@ -0,0 +1,89 @@
+module std.symtable;
+
+import std.string;
+import std.demangle;
+import std.file;
+import std.regexp;
+
+private {
+    extern (C) int strtol(char* ptr, char** eptr, int base);
+}
+
+enum SymtableType {
+    NONE, BINUTILS_NM, DMC_MAP
+}
+
+class Symtable {
+    class Sym {
+        uint addr;
+        char[] name;
+        this(uint a, char[] n) {
+            addr = a;
+            name = n;
+        }
+        int opCmp(Object o) {
+            return addr - (cast(Sym)o).addr;
+        }
+    }
+
+    this(char[] filename, SymtableType st) {
+        switch (st) {
+        case SymtableType.BINUTILS_NM:
+            char[] cont = cast(char[])std.file.read(filename);
+            foreach (char[] line; std.string.split(cont, "\n")) {
+                char[][] toks = std.string.split(line, " ");
+                if (toks.length != 3) continue;
+                uint addr = strtol(toStringz(toks[0]), null, 16);
+                char[] name = demangle(toks[2]);
+                syms ~= new Sym(addr, name);
+            }
+            syms.sort;
+            break;
+        case SymtableType.DMC_MAP:
+            char[] cont = cast(char[])std.file.read(filename);
+            RegExp reg =
+                new RegExp(` [\dABCDEF]{4}:[\dABCDEF]{8}\s{7}(.*)`, ``);
+            foreach (char[] line; std.string.split(cont, "\n")) {
+                if (reg.test(line) == 0) continue;
+                line = reg.replace(`$1`);
+                char[][] toks = std.string.split(line);
+                if (toks.length != 2) continue;
+                uint addr = strtol(toStringz(toks[1]), null, 16);
+                char[] name = demangle(toks[0]);
+                syms ~= new Sym(addr, name);
+            }
+            syms.sort;
+            break;
+        case SymtableType.NONE:
+            break;
+        default:
+            throw new Error("unknown symtable type");
+        }
+    }
+
+    char[] lookupName(uint addr) {
+        for (int i = 0; i < syms.length; i++) {
+            if (syms[i].addr > addr) {
+                if (i == 0) return null;
+                else return syms[i-1].name;
+            }
+        }
+        return null;
+    }
+
+    Sym[] getAllSymbol() { return syms; }
+
+    static void setDefaultSymtable(Symtable st) {
+        default_symtable = st;
+    }
+    static Symtable getDefaultSymtable() {
+        return default_symtable;
+    }
+
+protected:
+    this() {}
+
+private:
+    Sym[] syms;
+    static Symtable default_symtable;
+}
