From 7c8484437d88ff4e4ed708e5d2787b1e5e90f698 Mon Sep 17 00:00:00 2001
From: moko256 <koutaro.mo@gmail.com>
Date: Fri, 21 Oct 2022 05:10:25 +0900
Subject: [PATCH] Add Windows support for `//flutter/fml/backtrace.h` (#36202)

---
 fml/BUILD.gn     |  4 +--
 fml/backtrace.cc | 74 +++++++++++++++++++++---------------------------
 fml/backtrace.h  |  3 ++
 3 files changed, 38 insertions(+), 43 deletions(-)

diff --git a/fml/BUILD.gn b/fml/BUILD.gn
index 3caa047f4b30c..2656313e03764 100644
--- a/fml/BUILD.gn
+++ b/fml/BUILD.gn
@@ -96,7 +96,7 @@ source_set("fml") {
     "wakeable.h",
   ]
 
-  if (is_mac || is_linux || (is_ios && is_debug)) {
+  if (is_mac || is_linux || is_win || (is_ios && is_debug)) {
     sources += [ "backtrace.cc" ]
   } else {
     sources += [ "backtrace_stub.cc" ]
@@ -115,7 +115,7 @@ source_set("fml") {
     "//third_party/icu",
   ]
 
-  if (is_mac || is_linux || (is_ios && is_debug)) {
+  if (is_mac || is_linux || is_win || (is_ios && is_debug)) {
     # This abseil dependency is only used by backtrace.cc.
     deps += [ "//third_party/abseil-cpp/absl/debugging:symbolize" ]
   }
diff --git a/fml/backtrace.cc b/fml/backtrace.cc
index 34b0ef06b146b..264fa7d0bcda5 100644
--- a/fml/backtrace.cc
+++ b/fml/backtrace.cc
@@ -4,68 +4,56 @@
 
 #include "flutter/fml/backtrace.h"
 
-#include <cxxabi.h>
-#include <dlfcn.h>
-#include <execinfo.h>
-
 #include <csignal>
 #include <sstream>
 
-#if FML_OS_WIN
-#include <crtdbg.h>
-#include <debugapi.h>
-#endif
-
+#include "flutter/fml/build_config.h"
 #include "flutter/fml/logging.h"
 #include "flutter/fml/paths.h"
 #include "third_party/abseil-cpp/absl/debugging/symbolize.h"
 
+#ifdef FML_OS_WIN
+#include <Windows.h>
+#include <crtdbg.h>
+#include <debugapi.h>
+#else  // FML_OS_WIN
+#include <execinfo.h>
+#endif  // FML_OS_WIN
+
 namespace fml {
 
 static std::string kKUnknownFrameName = "Unknown";
 
-static std::string DemangleSymbolName(const std::string& mangled) {
-  if (mangled == kKUnknownFrameName) {
-    return kKUnknownFrameName;
-  }
-
-  int status = 0;
-  size_t length = 0;
-  char* demangled = __cxxabiv1::__cxa_demangle(
-      mangled.data(),  // mangled name
-      nullptr,         // output buffer (malloc-ed if nullptr)
-      &length,         // demangled length
-      &status);
-
-  if (demangled == nullptr || status != 0) {
-    return mangled;
-  }
-
-  auto demangled_string = std::string{demangled, length};
-  free(demangled);
-  return demangled_string;
-}
-
 static std::string GetSymbolName(void* symbol) {
   char name[1024];
   if (!absl::Symbolize(symbol, name, sizeof(name))) {
     return kKUnknownFrameName;
   }
+  return name;
+}
 
-  return DemangleSymbolName({name});
+static int Backtrace(void** symbols, int size) {
+#if FML_OS_WIN
+  return CaptureStackBackTrace(0, size, symbols, NULL);
+#else
+  return ::backtrace(symbols, size);
+#endif  // FML_OS_WIN
 }
 
 std::string BacktraceHere(size_t offset) {
   constexpr size_t kMaxFrames = 256;
   void* symbols[kMaxFrames];
-  const auto available_frames = ::backtrace(symbols, kMaxFrames);
+  const auto available_frames = Backtrace(symbols, kMaxFrames);
   if (available_frames <= 0) {
     return "";
   }
 
+  // Exclude here.
+  offset += 2;
+
   std::stringstream stream;
-  for (int i = 1 + offset; i < available_frames; ++i) {
-    stream << "Frame " << i - 1 - offset << ": " << symbols[i] << " "
+  for (int i = offset; i < available_frames; ++i) {
+    stream << "Frame " << i - offset << ": " << symbols[i] << " "
            << GetSymbolName(symbols[i]) << std::endl;
   }
   return stream.str();
@@ -74,12 +62,14 @@ std::string BacktraceHere(size_t offset) {
 static size_t kKnownSignalHandlers[] = {
     SIGABRT,  // abort program
     SIGFPE,   // floating-point exception
-    SIGBUS,   // bus error
+    SIGTERM,  // software termination signal
     SIGSEGV,  // segmentation violation
+#if !FML_OS_WIN
+    SIGBUS,   // bus error
     SIGSYS,   // non-existent system call invoked
     SIGPIPE,  // write on a pipe with no reader
     SIGALRM,  // real-time timer expired
-    SIGTERM,  // software termination signal
+#endif        // !FML_OS_WIN
 };
 
 static std::string SignalNameToString(int signal) {
@@ -88,18 +78,20 @@ static std::string SignalNameToString(int signal) {
       return "SIGABRT";
     case SIGFPE:
       return "SIGFPE";
-    case SIGBUS:
-      return "SIGBUS";
     case SIGSEGV:
       return "SIGSEGV";
+    case SIGTERM:
+      return "SIGTERM";
+#if !FML_OS_WIN
+    case SIGBUS:
+      return "SIGBUS";
     case SIGSYS:
       return "SIGSYS";
     case SIGPIPE:
       return "SIGPIPE";
     case SIGALRM:
       return "SIGALRM";
-    case SIGTERM:
-      return "SIGTERM";
+#endif  // !FML_OS_WIN
   };
   return std::to_string(signal);
 }
diff --git a/fml/backtrace.h b/fml/backtrace.h
index 18f17933b355b..167ce956206f6 100644
--- a/fml/backtrace.h
+++ b/fml/backtrace.h
@@ -11,6 +11,9 @@
 
 namespace fml {
 
+// Retrieve the backtrace, for debugging.
+//
+// If the |offset| is 0, the backtrace is included caller function.
 std::string BacktraceHere(size_t offset = 0);
 
 void InstallCrashHandler();