瀏覽代碼

Alter linux debug stacktraces handling to support more environments

- Use -gdwarf-4 to support both LLVM and GCC when calling addr2line
- Subtract position-independant execuable relocation when passing the
  address to addr2line

(cherry picked from commit 5e041eee11e611bc2c89dd54b1dad28d0660f335)
Ekaterina Vaartis 2 年之前
父節點
當前提交
8bc325d991
共有 3 個文件被更改,包括 32 次插入19 次删除
  1. 5 1
      platform/server/detect.py
  2. 22 18
      platform/x11/crash_handler_x11.cpp
  3. 5 0
      platform/x11/detect.py

+ 5 - 1
platform/server/detect.py

@@ -51,7 +51,6 @@ def get_flags():
 
 
 def configure(env):
-
     ## Build type
 
     if env["target"] == "release":
@@ -76,6 +75,11 @@ def configure(env):
         env.Prepend(CCFLAGS=["-g3"])
         env.Append(LINKFLAGS=["-rdynamic"])
 
+    if env["debug_symbols"]:
+        # Adding dwarf-4 explicitly makes stacktraces work with clang builds,
+        # otherwise addr2line doesn't understand them
+        env.Append(CCFLAGS=["-gdwarf-4"])
+
     ## Architecture
 
     is64 = sys.maxsize > 2**32

+ 22 - 18
platform/x11/crash_handler_x11.cpp

@@ -44,6 +44,7 @@
 #include <cxxabi.h>
 #include <dlfcn.h>
 #include <execinfo.h>
+#include <link.h>
 #include <signal.h>
 #include <stdlib.h>
 
@@ -79,7 +80,27 @@ static void handle_crash(int sig) {
 	}
 	print_error(vformat("Dumping the backtrace. %s", msg));
 	char **strings = backtrace_symbols(bt_buffer, size);
+	// PIE executable relocation, zero for non-PIE executables
+	uintptr_t relocation = _r_debug.r_map->l_addr;
 	if (strings) {
+		List<String> args;
+		for (size_t i = 0; i < size; i++) {
+			char str[1024];
+			snprintf(str, 1024, "%p", (void *)((uintptr_t)bt_buffer[i] - relocation));
+			args.push_back(str);
+		}
+		args.push_back("-e");
+		args.push_back(_execpath);
+
+		// Try to get the file/line number using addr2line
+		int ret;
+		String output = "";
+		Error err = OS::get_singleton()->execute(String("addr2line"), args, true, nullptr, &output, &ret);
+		Vector<String> addr2line_results;
+		if (err == OK) {
+			addr2line_results = output.substr(0, output.length() - 1).split("\n", false);
+		}
+
 		for (size_t i = 1; i < size; i++) {
 			char fname[1024];
 			Dl_info info;
@@ -102,24 +123,7 @@ static void handle_crash(int sig) {
 				}
 			}
 
-			List<String> args;
-
-			char str[1024];
-			snprintf(str, 1024, "%p", bt_buffer[i]);
-			args.push_back(str);
-			args.push_back("-e");
-			args.push_back(_execpath);
-
-			String output = "";
-
-			// Try to get the file/line number using addr2line
-			int ret;
-			Error err = OS::get_singleton()->execute(String("addr2line"), args, true, nullptr, &output, &ret);
-			if (err == OK) {
-				output.erase(output.length() - 1, 1);
-			}
-
-			print_error(vformat("[%d] %s (%s)", (int64_t)i, fname, output));
+			print_error(vformat("[%d] %s (%s)", (int64_t)i, fname, err == OK ? addr2line_results[i] : ""));
 		}
 
 		free(strings);

+ 5 - 0
platform/x11/detect.py

@@ -112,6 +112,11 @@ def configure(env):
         env.Prepend(CCFLAGS=["-g3"])
         env.Append(LINKFLAGS=["-rdynamic"])
 
+    if env["debug_symbols"]:
+        # Adding dwarf-4 explicitly makes stacktraces work with clang builds,
+        # otherwise addr2line doesn't understand them
+        env.Append(CCFLAGS=["-gdwarf-4"])
+
     ## Architecture
 
     is64 = sys.maxsize > 2**32