[llvm] r231382 - [Windows] Implement PrintStackTrace(FILE*)

Zachary Turner zturner at google.com
Thu Mar 5 09:47:52 PST 2015


Author: zturner
Date: Thu Mar  5 11:47:52 2015
New Revision: 231382

URL: http://llvm.org/viewvc/llvm-project?rev=231382&view=rev
Log:
[Windows] Implement PrintStackTrace(FILE*)

llvm::sys::PrintBacktrace(FILE*) is supposed to print a backtrace
of the current thread given the current PC.  This function was
unimplemented on Windows, and instead the only time we could
print a backtrace was as the result of an exception through
LLVMUnhandledExceptionFilter.

This patch implements backtracing of self by using
RtlCaptureContext to get a CONTEXT for the current thread, and
moving the printing and StackWalk64 code to a common method that
printing own stack trace and printing stack trace of an exception
can use.

Differential Revision: http://reviews.llvm.org/D8068
Reviewed by: Reid Kleckner

Modified:
    llvm/trunk/lib/Support/Windows/Signals.inc

Modified: llvm/trunk/lib/Support/Windows/Signals.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/Signals.inc?rev=231382&r1=231381&r2=231382&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Windows/Signals.inc (original)
+++ llvm/trunk/lib/Support/Windows/Signals.inc Thu Mar  5 11:47:52 2015
@@ -10,7 +10,6 @@
 // This file provides the Win32 specific implementation of the Signals class.
 //
 //===----------------------------------------------------------------------===//
-
 #include "llvm/Support/FileSystem.h"
 #include <algorithm>
 #include <signal.h>
@@ -173,6 +172,89 @@ static PTOP_LEVEL_EXCEPTION_FILTER OldFi
 // globals which this critical section addresses.
 static CRITICAL_SECTION CriticalSection;
 
+static void PrintStackTraceForThread(FILE *File, HANDLE hProcess,
+                                     HANDLE hThread, STACKFRAME64 &StackFrame,
+                                     CONTEXT *Context) {
+  DWORD machineType;
+#if defined(_M_X64)
+  machineType = IMAGE_FILE_MACHINE_AMD64;
+#else
+  machineType = IMAGE_FILE_MACHINE_I386;
+#endif
+
+  // Initialize the symbol handler.
+  SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES);
+  SymInitialize(hProcess, NULL, TRUE);
+
+  while (true) {
+    if (!StackWalk64(machineType, hProcess, hThread, &StackFrame, Context, NULL,
+                     SymFunctionTableAccess64, SymGetModuleBase64, NULL)) {
+      break;
+    }
+
+    if (StackFrame.AddrFrame.Offset == 0)
+      break;
+
+    // Print the PC in hexadecimal.
+    DWORD64 PC = StackFrame.AddrPC.Offset;
+#if defined(_M_X64)
+    fprintf(File, "0x%016llX", PC);
+#elif defined(_M_IX86)
+    fprintf(File, "0x%08lX", static_cast<DWORD>(PC));
+#endif
+
+// Print the parameters.  Assume there are four.
+#if defined(_M_X64)
+    fprintf(File, " (0x%016llX 0x%016llX 0x%016llX 0x%016llX)",
+            StackFrame.Params[0], StackFrame.Params[1], StackFrame.Params[2],
+            StackFrame.Params[3]);
+#elif defined(_M_IX86)
+    fprintf(File, " (0x%08lX 0x%08lX 0x%08lX 0x%08lX)",
+            static_cast<DWORD>(StackFrame.Params[0]),
+            static_cast<DWORD>(StackFrame.Params[1]),
+            static_cast<DWORD>(StackFrame.Params[2]),
+            static_cast<DWORD>(StackFrame.Params[3]));
+#endif
+    // Verify the PC belongs to a module in this process.
+    if (!SymGetModuleBase64(hProcess, PC)) {
+      fputs(" <unknown module>\n", File);
+      continue;
+    }
+
+    // Print the symbol name.
+    char buffer[512];
+    IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer);
+    memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64));
+    symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
+    symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64);
+
+    DWORD64 dwDisp;
+    if (!SymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) {
+      fputc('\n', File);
+      continue;
+    }
+
+    buffer[511] = 0;
+    if (dwDisp > 0)
+      fprintf(File, ", %s() + 0x%llX bytes(s)", symbol->Name, dwDisp);
+    else
+      fprintf(File, ", %s", symbol->Name);
+
+    // Print the source file and line number information.
+    IMAGEHLP_LINE64 line;
+    DWORD dwLineDisp;
+    memset(&line, 0, sizeof(line));
+    line.SizeOfStruct = sizeof(line);
+    if (SymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) {
+      fprintf(File, ", %s, line %lu", line.FileName, line.LineNumber);
+      if (dwLineDisp > 0)
+        fprintf(File, " + 0x%lX byte(s)", dwLineDisp);
+    }
+
+    fputc('\n', File);
+  }
+}
+
 namespace llvm {
 
 //===----------------------------------------------------------------------===//
@@ -299,8 +381,25 @@ void sys::PrintStackTraceOnErrorSignal()
   LeaveCriticalSection(&CriticalSection);
 }
 
-void llvm::sys::PrintStackTrace(FILE *) {
-  // FIXME: Implement.
+void llvm::sys::PrintStackTrace(FILE *File) {
+
+  STACKFRAME64 StackFrame = {0};
+  CONTEXT Context = {0};
+  ::RtlCaptureContext(&Context);
+#if defined(_M_X64)
+  StackFrame.AddrPC.Offset = Context.Rip;
+  StackFrame.AddrStack.Offset = Context.Rsp;
+  StackFrame.AddrFrame.Offset = Context.Rbp;
+#else
+  StackFrame.AddrPC.Offset = Context.Eip;
+  StackFrame.AddrStack.Offset = Context.Esp;
+  StackFrame.AddrFrame.Offset = Context.Ebp;
+#endif
+  StackFrame.AddrPC.Mode = AddrModeFlat;
+  StackFrame.AddrStack.Mode = AddrModeFlat;
+  StackFrame.AddrFrame.Mode = AddrModeFlat;
+  PrintStackTraceForThread(File, GetCurrentProcess(), GetCurrentThread(),
+                           StackFrame, &Context);
 }
 
 
@@ -356,9 +455,7 @@ static LONG WINAPI LLVMUnhandledExceptio
   STACKFRAME64 StackFrame;
   memset(&StackFrame, 0, sizeof(StackFrame));
 
-  DWORD machineType;
 #if defined(_M_X64)
-  machineType = IMAGE_FILE_MACHINE_AMD64;
   StackFrame.AddrPC.Offset = ep->ContextRecord->Rip;
   StackFrame.AddrPC.Mode = AddrModeFlat;
   StackFrame.AddrStack.Offset = ep->ContextRecord->Rsp;
@@ -366,7 +463,6 @@ static LONG WINAPI LLVMUnhandledExceptio
   StackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp;
   StackFrame.AddrFrame.Mode = AddrModeFlat;
 #elif defined(_M_IX86)
-  machineType = IMAGE_FILE_MACHINE_I386;
   StackFrame.AddrPC.Offset = ep->ContextRecord->Eip;
   StackFrame.AddrPC.Mode = AddrModeFlat;
   StackFrame.AddrStack.Offset = ep->ContextRecord->Esp;
@@ -377,81 +473,8 @@ static LONG WINAPI LLVMUnhandledExceptio
 
   HANDLE hProcess = GetCurrentProcess();
   HANDLE hThread = GetCurrentThread();
-
-  // Initialize the symbol handler.
-  SymSetOptions(SYMOPT_DEFERRED_LOADS|SYMOPT_LOAD_LINES);
-  SymInitialize(hProcess, NULL, TRUE);
-
-  while (true) {
-    if (!StackWalk64(machineType, hProcess, hThread, &StackFrame,
-                   ep->ContextRecord, NULL, SymFunctionTableAccess64,
-                   SymGetModuleBase64, NULL)) {
-      break;
-    }
-
-    if (StackFrame.AddrFrame.Offset == 0)
-      break;
-
-    // Print the PC in hexadecimal.
-    DWORD64 PC = StackFrame.AddrPC.Offset;
-#if defined(_M_X64)
-    fprintf(stderr, "0x%016llX", PC);
-#elif defined(_M_IX86)
-    fprintf(stderr, "0x%08lX", static_cast<DWORD>(PC));
-#endif
-
-    // Print the parameters.  Assume there are four.
-#if defined(_M_X64)
-    fprintf(stderr, " (0x%016llX 0x%016llX 0x%016llX 0x%016llX)",
-                StackFrame.Params[0],
-                StackFrame.Params[1],
-                StackFrame.Params[2],
-                StackFrame.Params[3]);
-#elif defined(_M_IX86)
-    fprintf(stderr, " (0x%08lX 0x%08lX 0x%08lX 0x%08lX)",
-                static_cast<DWORD>(StackFrame.Params[0]),
-                static_cast<DWORD>(StackFrame.Params[1]),
-                static_cast<DWORD>(StackFrame.Params[2]),
-                static_cast<DWORD>(StackFrame.Params[3]));
-#endif
-    // Verify the PC belongs to a module in this process.
-    if (!SymGetModuleBase64(hProcess, PC)) {
-      fputs(" <unknown module>\n", stderr);
-      continue;
-    }
-
-    // Print the symbol name.
-    char buffer[512];
-    IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer);
-    memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64));
-    symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
-    symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64);
-
-    DWORD64 dwDisp;
-    if (!SymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) {
-      fputc('\n', stderr);
-      continue;
-    }
-
-    buffer[511] = 0;
-    if (dwDisp > 0)
-      fprintf(stderr, ", %s() + 0x%llX bytes(s)", symbol->Name, dwDisp);
-    else
-      fprintf(stderr, ", %s", symbol->Name);
-
-    // Print the source file and line number information.
-    IMAGEHLP_LINE64 line;
-    DWORD dwLineDisp;
-    memset(&line, 0, sizeof(line));
-    line.SizeOfStruct = sizeof(line);
-    if (SymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) {
-      fprintf(stderr, ", %s, line %lu", line.FileName, line.LineNumber);
-      if (dwLineDisp > 0)
-        fprintf(stderr, " + 0x%lX byte(s)", dwLineDisp);
-    }
-
-    fputc('\n', stderr);
-  }
+  PrintStackTraceForThread(stderr, hProcess, hThread, StackFrame,
+                           ep->ContextRecord);
 
   _exit(ep->ExceptionRecord->ExceptionCode);
 }





More information about the llvm-commits mailing list