瀏覽代碼

added C stack trace report on Windows

Nicolas Cannasse 9 年之前
父節點
當前提交
c71e99623a
共有 4 個文件被更改,包括 81 次插入4 次删除
  1. 4 0
      hl.vcxproj
  2. 1 0
      src/hl.h
  3. 7 1
      src/main.c
  4. 69 3
      src/std/error.c

+ 4 - 0
hl.vcxproj

@@ -98,6 +98,7 @@
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalDependencies>std.lib;sdl.lib</AdditionalDependencies>
+      <StackReserveSize>0x200000</StackReserveSize>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -112,6 +113,7 @@
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalDependencies>std.lib;sdl.lib</AdditionalDependencies>
+      <StackReserveSize>0x200000</StackReserveSize>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -131,6 +133,7 @@
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <AdditionalDependencies>std.lib;sdl.lib</AdditionalDependencies>
+      <StackReserveSize>0x200000</StackReserveSize>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -149,6 +152,7 @@
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <AdditionalDependencies>std.lib;sdl.lib</AdditionalDependencies>
+      <StackReserveSize>0x200000</StackReserveSize>
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>

+ 1 - 0
src/hl.h

@@ -426,6 +426,7 @@ HL_API const uchar *hl_field_name( int hash );
 HL_API void hl_error_msg( const uchar *msg, ... );
 HL_API void hl_throw( vdynamic *v );
 HL_API void hl_rethrow( vdynamic *v );
+HL_API varray *hl_exception_stack();
 
 HL_API vvirtual *hl_to_virtual( hl_type *vt, vdynamic *obj );
 HL_API void hl_init_virtual( hl_type *vt, hl_module_context *ctx );

+ 7 - 1
src/main.c

@@ -44,7 +44,13 @@ int main(int argc, char *argv[]) {
 	hl_global_free();
 	return 0;
 on_exception:
-	uprintf(USTR("Uncaught exception: %s\n"), hl_to_string(exc));
+	{
+		varray *a = hl_exception_stack();
+		int i;
+		uprintf(USTR("Uncaught exception: %s\n"), hl_to_string(exc));
+		for(i=0;i<a->size;i++)
+			uprintf(USTR("Called from %s\n"), hl_aptr(a,uchar*)[i]);
+	}
 	hl_global_free();
 	return 1;
 }

+ 69 - 3
src/std/error.c

@@ -23,9 +23,22 @@
 #include <stdarg.h>
 #include <string.h>
 
+#ifdef _WIN32
+#	pragma warning(disable:4091)
+#	include <DbgHelp.h>
+#	pragma comment(lib, "Dbghelp.lib")
+#endif
+
 HL_PRIM hl_trap_ctx *hl_current_trap = NULL;
 HL_PRIM vdynamic *hl_current_exc = NULL;
 
+static vdynamic *stack_last_exc = NULL;
+static void *stack_trace[0x1000];
+static int stack_count = 0;
+#ifdef _WIN32
+static HANDLE stack_process_handle = NULL;
+#endif
+
 HL_PRIM void *hl_fatal_error( const char *msg, const char *file, int line ) {
 	printf("%s(%d) : FATAL ERROR : %s\n",file,line,msg);
 #ifdef _DEBUG
@@ -36,17 +49,68 @@ HL_PRIM void *hl_fatal_error( const char *msg, const char *file, int line ) {
 	return NULL;
 }
 
+static void hl_on_uncaught( const uchar *v ) {
+#	ifdef _DEBUG
+//	*(int*)0 = 0;
+#	endif
+}
+
 HL_PRIM void hl_throw( vdynamic *v ) {
 	hl_trap_ctx *t = hl_current_trap;
+#ifdef _WIN32
+	if( v != stack_last_exc ) {
+		stack_last_exc = v;
+		stack_count = CaptureStackBackTrace(1, 0x1000, stack_trace, NULL) - 8; // 8 startup
+	}
+#endif
 	hl_current_exc = v;
 	hl_current_trap = t->prev;
-#ifdef _DEBUG
-//	if( hl_current_trap == NULL ) *(int*)NULL = 0; // Uncaught exception
-#endif
+	if( hl_current_trap == NULL ) hl_on_uncaught((uchar*)v->v.bytes);
 	longjmp(t->buf,1);
 }
 
+static uchar *hl_resolve_symbol( void *addr ) {
+#ifdef _WIN32
+	DWORD64 index;
+	uchar tmp[256];
+	struct {
+		SYMBOL_INFOW sym;
+		uchar buffer[256];
+	} data;
+	data.sym.SizeOfStruct = sizeof(data.sym);
+	data.sym.MaxNameLen = 255;
+	if( SymFromAddrW(stack_process_handle,(DWORD64)addr,&index,&data.sym) ) {
+		int size = usprintf(tmp,256,USTR("%s at %d"),data.sym.Name,(int)index);
+		return (uchar*)hl_copy_bytes((vbyte*)tmp,sizeof(uchar)*(size+1));
+	}
+#endif
+	return NULL;
+}
+
+HL_PRIM varray *hl_exception_stack() {
+	varray *a = hl_alloc_array(&hlt_bytes, stack_count);
+	int i;
+	uchar tmp[32];
+#ifdef _WIN32
+	if( !stack_process_handle ) {
+		stack_process_handle = GetCurrentProcess();
+		SymInitialize(stack_process_handle,NULL,TRUE);
+	}
+#endif
+	for(i=0;i<stack_count;i++) {
+		void *addr = stack_trace[i];
+		uchar *str = hl_resolve_symbol(addr);
+		if( str == NULL ) {
+			int size = usprintf(tmp,32,USTR("@0x%X"),(int)addr);
+			str = (uchar*)hl_copy_bytes((vbyte*)tmp,sizeof(uchar)*(size+1));
+		}
+		hl_aptr(a,vbyte*)[i] = (vbyte*)str;
+	}
+	return a;
+}
+
 HL_PRIM void hl_rethrow( vdynamic *v ) {
+	stack_last_exc = v;
 	hl_throw(v);
 }
 
@@ -54,6 +118,7 @@ HL_PRIM void hl_error_msg( const uchar *fmt, ... ) {
 	uchar buf[256];
 	vdynamic *d;
 	int len;
+	if( !hl_current_trap->prev ) hl_on_uncaught(fmt);
 	va_list args;
 	va_start(args, fmt);
 	len = uvsprintf(buf,fmt,args);
@@ -65,6 +130,7 @@ HL_PRIM void hl_error_msg( const uchar *fmt, ... ) {
 
 HL_PRIM void hl_fatal_fmt(const char *fmt, ...) {
 	char buf[256];
+	if( !hl_current_trap->prev ) hl_on_uncaught(USTR(""));
 	va_list args;
 	va_start(args, fmt);
 	vsprintf(buf,fmt, args);