ソースを参照

Use addr2line

Daniele Bartolini 10 年 前
コミット
e93fa52f1e
1 ファイル変更35 行追加7 行削除
  1. 35 7
      src/core/error/stacktrace_linux.cpp

+ 35 - 7
src/core/error/stacktrace_linux.cpp

@@ -13,15 +13,30 @@
 #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[strlen(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)
@@ -30,25 +45,38 @@ void print_callstack()
 		char* msg = messages[i];
 		char* mangled_name = strchr(msg, '(');
 		char* offset_begin = strchr(msg, '+');
-		char* offset_end = 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';
+			*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));
 
-			int status;
-			char* real_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);
+			printf("\t[%d] %s: (%s)+%s in %s\n"
+				, i
+				, msg
+				, (demangle_ok == 0 ? real_name : mangled_name)
+				, offset_begin
+				, addr2line(addr_begin, line, sizeof(line))
+				);
 
-			printf("\t[%d] %s: (%s)+%s %s\n", i, messages[i], (status == 0 ? real_name : mangled_name), offset_begin, offset_end);
 			free(real_name);
 		}
 		// otherwise, print the whole line
 		else
 		{
-			printf("\t[%d] %s\n", i, messages[i]);
+			printf("\t[%d] %s\n", i, msg);
 		}
 	}
 	free(messages);