Daniele Bartolini 10 лет назад
Родитель
Сommit
3a72816145

+ 5 - 2
src/core/error/stacktrace_android.cpp → src/core/error/callstack_android.cpp

@@ -9,9 +9,12 @@
 
 namespace crown
 {
-void print_callstack()
+namespace error
 {
-}
+	void print_callstack()
+	{
+	}
+} // namespace error
 
 } // namespace crown
 

+ 90 - 0
src/core/error/callstack_linux.cpp

@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2012-2016 Daniele Bartolini and individual contributors.
+ * License: https://github.com/taylor001/crown/blob/master/LICENSE
+ */
+
+#include "config.h"
+
+#if CROWN_PLATFORM_LINUX && CROWN_COMPILER_GCC
+
+#include "log.h"
+#include "macros.h"
+#include "string_utils.h"
+#include <cxxabi.h>
+#include <execinfo.h>
+#include <stdlib.h>
+#include <string.h> // strchr
+#include <unistd.h> // getpid
+
+namespace crown
+{
+namespace error
+{
+	static const char* addr2line(const char* addr, char* line, int len)
+	{
+		char buf[256];
+		snprintf(buf, sizeof(buf), "addr2line -e /proc/%u/exe %s", getpid(), addr);
+		FILE* f = popen(buf, "r");
+		if (f)
+		{
+			fgets(line, len, f);
+			line[strlen32(line) - 1] = '\0';
+			pclose(f);
+			return line;
+		}
+		return "<addr2line missing>";
+	}
+
+	void print_callstack()
+	{
+		void* array[64];
+		int size = backtrace(array, CE_COUNTOF(array));
+		char** messages = backtrace_symbols(array, size);
+
+		// skip first stack frame (points here)
+		for (int i = 1; i < size && messages != NULL; ++i)
+		{
+			char* msg = messages[i];
+			char* mangled_name = strchr(msg, '(');
+			char* offset_begin = strchr(msg, '+');
+			char* offset_end   = strchr(msg, ')');
+			char* addr_begin   = strchr(msg, '[');
+			char* addr_end     = strchr(msg, ']');
+
+			// if the line could be processed, attempt to demangle the symbol
+			if (mangled_name && offset_begin && offset_end && mangled_name < offset_begin)
+			{
+				*mangled_name++ = '\0';
+				*offset_begin++ = '\0';
+				*offset_end++   = '\0';
+				*addr_begin++   = '\0';
+				*addr_end++     = '\0';
+
+				int demangle_ok;
+				char* real_name = abi::__cxa_demangle(mangled_name, 0, 0, &demangle_ok);
+				char line[256];
+				memset(line, 0, sizeof(line));
+
+				CE_LOGE("\t[%2d] %s: (%s)+%s in %s"
+					, i
+					, msg
+					, (demangle_ok == 0 ? real_name : mangled_name)
+					, offset_begin
+					, addr2line(addr_begin, line, sizeof(line))
+					);
+
+				free(real_name);
+			}
+			// otherwise, print the whole line
+			else
+			{
+				CE_LOGE("\t[%2d] %s", i, msg);
+			}
+		}
+		free(messages);
+	}
+} // namespace error
+
+} // namespace crown
+
+#endif // CROWN_PLATFORM_LINUX && CROWN_COMPILER_GCC

+ 94 - 0
src/core/error/callstack_windows.cpp

@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2012-2016 Daniele Bartolini and individual contributors.
+ * License: https://github.com/taylor001/crown/blob/master/LICENSE
+ */
+
+#include "config.h"
+
+#if CROWN_PLATFORM_WINDOWS
+
+#include "log.h"
+#include "win_headers.h"
+#include <dbghelp.h>
+
+namespace crown
+{
+namespace error
+{
+	void print_callstack()
+	{
+		SymInitialize(GetCurrentProcess(), NULL, TRUE);
+		SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
+		DWORD mtype;
+		CONTEXT ctx;
+		ZeroMemory(&ctx, sizeof(CONTEXT));
+		ctx.ContextFlags = CONTEXT_CONTROL;
+		RtlCaptureContext(&ctx);
+
+		STACKFRAME64 stack;
+		ZeroMemory(&stack, sizeof(STACKFRAME64));
+	#ifdef _M_IX86
+		mtype = IMAGE_FILE_MACHINE_I386;
+		stack.AddrPC.Offset = ctx.Eip;
+		stack.AddrPC.Mode = AddrModeFlat;
+		stack.AddrFrame.Offset = ctx.Ebp;
+		stack.AddrFrame.Mode = AddrModeFlat;
+		stack.AddrStack.Offset = ctx.Esp;
+		stack.AddrStack.Mode = AddrModeFlat;
+	#elif _M_X64
+		mtype = IMAGE_FILE_MACHINE_AMD64;
+		stack.AddrPC.Offset = ctx.Rip;
+		stack.AddrPC.Mode = AddrModeFlat;
+		stack.AddrFrame.Offset = ctx.Rsp;
+		stack.AddrFrame.Mode = AddrModeFlat;
+		stack.AddrStack.Offset = ctx.Rsp;
+		stack.AddrStack.Mode = AddrModeFlat;
+	#endif
+
+		DWORD ldsp = 0;
+		IMAGEHLP_LINE64 line;
+		ZeroMemory(&line, sizeof(IMAGEHLP_LINE64));
+		line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+
+		char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
+		PSYMBOL_INFO sym = (PSYMBOL_INFO)buf;
+		sym->SizeOfStruct = sizeof(SYMBOL_INFO);
+		sym->MaxNameLen = MAX_SYM_NAME;
+
+		UINT num = 0;
+		while (StackWalk64(mtype
+				, GetCurrentProcess()
+				, GetCurrentThread()
+				, &stack
+				, &ctx
+				, NULL
+				, SymFunctionTableAccess64
+				, SymGetModuleBase64
+				, NULL
+				))
+		{
+			if (stack.AddrPC.Offset == 0)
+				break;
+
+			++num;
+
+			BOOL res = SymGetLineFromAddr64(GetCurrentProcess()
+						, stack.AddrPC.Offset
+						, &ldsp
+						, &line
+						);
+			res = res && SymFromAddr(GetCurrentProcess(), stack.AddrPC.Offset, 0, sym);
+
+			if (res == TRUE)
+				CE_LOGE("\t[%2i] %s in %s:%d", num, sym->Name, line.FileName, line.LineNumber);
+			else
+				CE_LOGE("\t[%2i] 0x%p", num, stack.AddrPC.Offset);
+		}
+
+		SymCleanup(GetCurrentProcess());
+	}
+} // namespace error
+
+} // namespace crown
+
+#endif // CROWN_PLATFORM_WINDOWS

+ 2 - 4
src/core/error/error.cpp

@@ -4,10 +4,9 @@
  */
 
 #include "error.h"
-#include "stacktrace.h"
 #include "log.h"
-#include <stdlib.h>
 #include <stdarg.h>
+#include <stdlib.h> // exit
 
 namespace crown
 {
@@ -16,8 +15,7 @@ namespace error
 	static void abort(const char* file, int line, const char* format, va_list args)
 	{
 		CE_LOGEV(format, args);
-		CE_LOGE("\tIn: %s:%d", file, line);
-		CE_LOGE("Stacktrace:");
+		CE_LOGE("\tIn: %s:%d\n\nStacktrace:", file, line);
 		print_callstack();
 		exit(EXIT_FAILURE);
 	}

+ 7 - 0
src/core/error/error.h

@@ -7,13 +7,20 @@
 
 #include "config.h"
 
+/// @defgroup Error Error
 namespace crown
 {
+/// Error management.
+///
+/// @ingroup Error
 namespace error
 {
 	/// Aborts the program execution logging an error message and the stacktrace if
 	/// the platform supports it.
 	void abort(const char* file, int line, const char* format, ...);
+
+	/// Prints the current call stack.
+	void print_callstack();
 } // namespace error
 } // namespace crown
 

+ 0 - 13
src/core/error/stacktrace.h

@@ -1,13 +0,0 @@
-/*
- * Copyright (c) 2012-2016 Daniele Bartolini and individual contributors.
- * License: https://github.com/taylor001/crown/blob/master/LICENSE
- */
-
-#pragma once
-
-namespace crown
-{
-/// Prints the current call stack.
-void print_callstack();
-
-} // namespace crown

+ 0 - 87
src/core/error/stacktrace_linux.cpp

@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2012-2016 Daniele Bartolini and individual contributors.
- * License: https://github.com/taylor001/crown/blob/master/LICENSE
- */
-
-#include "config.h"
-
-#if CROWN_PLATFORM_LINUX && CROWN_COMPILER_GCC
-
-#include "macros.h"
-#include "string_utils.h"
-#include "log.h"
-#include <stdlib.h>
-#include <cxxabi.h>
-#include <execinfo.h>
-#include <string.h> // strchr
-#include <unistd.h> // getpid
-
-namespace crown
-{
-const char* addr2line(const char* addr, char* line, int len)
-{
-	char buf[256];
-	snprintf(buf, sizeof(buf), "addr2line -e /proc/%u/exe %s", getpid(), addr);
-	FILE* f = popen(buf, "r");
-	if (f)
-	{
-		fgets(line, len, f);
-		line[strlen32(line) - 1] = '\0';
-		pclose(f);
-		return line;
-	}
-	return "<addr2line missing>";
-}
-
-void print_callstack()
-{
-	void* array[64];
-	int size = backtrace(array, CE_COUNTOF(array));
-	char** messages = backtrace_symbols(array, size);
-
-	// skip first stack frame (points here)
-	for (int i = 1; i < size && messages != NULL; ++i)
-	{
-		char* msg = messages[i];
-		char* mangled_name = strchr(msg, '(');
-		char* offset_begin = strchr(msg, '+');
-		char* offset_end   = strchr(msg, ')');
-		char* addr_begin   = strchr(msg, '[');
-		char* addr_end     = strchr(msg, ']');
-
-		// if the line could be processed, attempt to demangle the symbol
-		if (mangled_name && offset_begin && offset_end && mangled_name < offset_begin)
-		{
-			*mangled_name++ = '\0';
-			*offset_begin++ = '\0';
-			*offset_end++   = '\0';
-			*addr_begin++   = '\0';
-			*addr_end++     = '\0';
-
-			int demangle_ok;
-			char* real_name = abi::__cxa_demangle(mangled_name, 0, 0, &demangle_ok);
-			char line[256];
-			memset(line, 0, sizeof(line));
-
-			CE_LOGE("\t[%2d] %s: (%s)+%s in %s"
-				, i
-				, msg
-				, (demangle_ok == 0 ? real_name : mangled_name)
-				, offset_begin
-				, addr2line(addr_begin, line, sizeof(line))
-				);
-
-			free(real_name);
-		}
-		// otherwise, print the whole line
-		else
-		{
-			CE_LOGE("\t[%2d] %s", i, msg);
-		}
-	}
-	free(messages);
-}
-
-} // namespace crown
-
-#endif // CROWN_PLATFORM_LINUX && CROWN_COMPILER_GCC

+ 0 - 90
src/core/error/stacktrace_windows.cpp

@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2012-2016 Daniele Bartolini and individual contributors.
- * License: https://github.com/taylor001/crown/blob/master/LICENSE
- */
-
-#include "config.h"
-
-#if CROWN_PLATFORM_WINDOWS
-
-#include "log.h"
-#include "win_headers.h"
-#include <dbghelp.h>
-
-namespace crown
-{
-void print_callstack()
-{
-	SymInitialize(GetCurrentProcess(), NULL, TRUE);
-	SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
-	DWORD mtype;
-	CONTEXT ctx;
-	ZeroMemory(&ctx, sizeof(CONTEXT));
-	ctx.ContextFlags = CONTEXT_CONTROL;
-	RtlCaptureContext(&ctx);
-
-	STACKFRAME64 stack;
-	ZeroMemory(&stack, sizeof(STACKFRAME64));
-#ifdef _M_IX86
-	mtype = IMAGE_FILE_MACHINE_I386;
-	stack.AddrPC.Offset = ctx.Eip;
-	stack.AddrPC.Mode = AddrModeFlat;
-	stack.AddrFrame.Offset = ctx.Ebp;
-	stack.AddrFrame.Mode = AddrModeFlat;
-	stack.AddrStack.Offset = ctx.Esp;
-	stack.AddrStack.Mode = AddrModeFlat;
-#elif _M_X64
-	mtype = IMAGE_FILE_MACHINE_AMD64;
-	stack.AddrPC.Offset = ctx.Rip;
-	stack.AddrPC.Mode = AddrModeFlat;
-	stack.AddrFrame.Offset = ctx.Rsp;
-	stack.AddrFrame.Mode = AddrModeFlat;
-	stack.AddrStack.Offset = ctx.Rsp;
-	stack.AddrStack.Mode = AddrModeFlat;
-#endif
-
-	DWORD ldsp = 0;
-	IMAGEHLP_LINE64 line;
-	ZeroMemory(&line, sizeof(IMAGEHLP_LINE64));
-	line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
-
-	char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
-	PSYMBOL_INFO sym = (PSYMBOL_INFO)buf;
-	sym->SizeOfStruct = sizeof(SYMBOL_INFO);
-	sym->MaxNameLen = MAX_SYM_NAME;
-
-	UINT num = 0;
-	while (StackWalk64(mtype
-			, GetCurrentProcess()
-			, GetCurrentThread()
-			, &stack
-			, &ctx
-			, NULL
-			, SymFunctionTableAccess64
-			, SymGetModuleBase64
-			, NULL
-			))
-	{
-		if (stack.AddrPC.Offset == 0)
-			break;
-
-		++num;
-
-		BOOL res = SymGetLineFromAddr64(GetCurrentProcess()
-					, stack.AddrPC.Offset
-					, &ldsp
-					, &line
-					);
-		res = res && SymFromAddr(GetCurrentProcess(), stack.AddrPC.Offset, 0, sym);
-
-		if (res == TRUE)
-			CE_LOGE("\t[%2i] %s in %s:%d", num, sym->Name, line.FileName, line.LineNumber);
-		else
-			CE_LOGE("\t[%2i] 0x%p", num, stack.AddrPC.Offset);
-	}
-
-	SymCleanup(GetCurrentProcess());
-}
-} // namespace crown
-
-#endif // CROWN_PLATFORM_WINDOWS