summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Schwartzmeyer <andrew@schwartzmeyer.com>2016-12-21 21:48:58 (GMT)
committerAndrew Schwartzmeyer <andrew@schwartzmeyer.com>2017-06-27 01:47:34 (GMT)
commite5d36443c6d03453f985721a6b16b4f1749846c4 (patch)
tree59e35706c2e297223399692a6dc3f280d41c0534 /src
parent9c1d0e6f6ed76da94c7a4a717e1405440a36be21 (diff)
downloadglog-e5d36443c6d03453f985721a6b16b4f1749846c4.zip
glog-e5d36443c6d03453f985721a6b16b4f1749846c4.tar.gz
glog-e5d36443c6d03453f985721a6b16b4f1749846c4.tar.bz2
Support stacktrace on Windows
Diffstat (limited to 'src')
-rw-r--r--src/stacktrace_windows-inl.h63
-rw-r--r--src/utilities.h7
2 files changed, 52 insertions, 18 deletions
diff --git a/src/stacktrace_windows-inl.h b/src/stacktrace_windows-inl.h
index fad81d3..5606408 100644
--- a/src/stacktrace_windows-inl.h
+++ b/src/stacktrace_windows-inl.h
@@ -27,33 +27,60 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
-// Portable implementation - just use glibc
+// Author: Andrew Schwartzmeyer
//
-// Note: The glibc implementation may cause a call to malloc.
-// This can cause a deadlock in HeapProfiler.
-#include <execinfo.h>
-#include <string.h>
+// Windows implementation - just use CaptureStackBackTrace
+
+#include "port.h"
#include "stacktrace.h"
+#include "Dbghelp.h"
+#include <vector>
_START_GOOGLE_NAMESPACE_
+static bool ready_to_run = false;
+class StackTraceInit {
+public:
+ HANDLE hProcess;
+ StackTraceInit() {
+ // Initialize the symbol handler
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680344(v=vs.85).aspx
+ hProcess = GetCurrentProcess();
+ SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
+ SymInitialize(hProcess, NULL, true);
+ ready_to_run = true;
+ }
+ ~StackTraceInit() {
+ SymCleanup(hProcess);
+ ready_to_run = false;
+ }
+};
+
+static const StackTraceInit module_initializer; // Force initialization
+
// If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) {
- static const int kStackLength = 64;
- void * stack[kStackLength];
- int size;
-
- size = backtrace(stack, kStackLength);
+ if (!ready_to_run) {
+ return 0;
+ }
skip_count++; // we want to skip the current frame as well
- int result_count = size - skip_count;
- if (result_count < 0)
- result_count = 0;
- if (result_count > max_depth)
- result_count = max_depth;
- for (int i = 0; i < result_count; i++)
- result[i] = stack[i + skip_count];
+ if (max_depth > 64) {
+ max_depth = 64;
+ }
+ std::vector<void*> stack(max_depth);
+ // This API is thread-safe (moreover it walks only the current thread).
+ int size = CaptureStackBackTrace(skip_count, max_depth, &stack[0], NULL);
+ for (int i = 0; i < size; ++i) {
+ // Resolve symbol information from address.
+ char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
+ SYMBOL_INFO* symbol = reinterpret_cast<SYMBOL_INFO*>(buffer);
+ symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+ symbol->MaxNameLen = MAX_SYM_NAME;
+ SymFromAddr(module_initializer.hProcess, reinterpret_cast<DWORD64>(stack[i]), 0, symbol);
+ result[i] = stack[i];
+ }
- return result_count;
+ return size;
}
_END_GOOGLE_NAMESPACE_
diff --git a/src/utilities.h b/src/utilities.h
index 101ca64..a10735b 100644
--- a/src/utilities.h
+++ b/src/utilities.h
@@ -99,6 +99,8 @@
// malloc() from the unwinder. This is a problem because we're
// trying to use the unwinder to instrument malloc().
//
+// 4) The Windows API CaptureStackTrace.
+//
// Note: if you add a new implementation here, make sure it works
// correctly when GetStackTrace() is called with max_depth == 0.
// Some code may do that.
@@ -112,6 +114,8 @@
# define STACKTRACE_H "stacktrace_x86_64-inl.h"
# elif (defined(__ppc__) || defined(__PPC__)) && __GNUC__ >= 2
# define STACKTRACE_H "stacktrace_powerpc-inl.h"
+# elif defined(OS_WINDOWS)
+# define STACKTRACE_H "stacktrace_windows-inl.h"
# endif
#endif
@@ -143,6 +147,9 @@ namespace glog_internal_namespace_ {
#ifdef HAVE___ATTRIBUTE__
# define ATTRIBUTE_NOINLINE __attribute__ ((noinline))
# define HAVE_ATTRIBUTE_NOINLINE
+#elif defined(OS_WINDOWS)
+# define ATTRIBUTE_NOINLINE __declspec(noinline)
+# define HAVE_ATTRIBUTE_NOINLINE
#else
# define ATTRIBUTE_NOINLINE
#endif