Invert Pan-Azimuth (up means left)
[ardour.git] / libs / pbd / stacktrace.cc
1 /*
2  * Copyright (C) 2000-2017 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2006-2007 Taybin Rutkin <taybin@taybin.com>
4  * Copyright (C) 2009-2010 Carl Hetherington <carl@carlh.net>
5  * Copyright (C) 2013-2015 John Emmas <john@creativepost.co.uk>
6  * Copyright (C) 2015-2019 Robin Gareus <robin@gareus.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #include "libpbd-config.h"
24
25 #include "pbd/stacktrace.h"
26 #include "pbd/debug.h"
27 #include "pbd/demangle.h"
28 #include "pbd/compose.h"
29 #include "pbd/pthread_utils.h"
30
31 #include <cstdio>
32 #include <iostream>
33 #include <string>
34
35 #ifdef PLATFORM_WINDOWS
36 #include <windows.h>
37 #include <dbghelp.h>
38 #endif
39
40 void
41 PBD::trace_twb ()
42 {
43 }
44
45 /* Obtain a backtrace and print it to stdout. */
46
47 #ifdef HAVE_EXECINFO
48
49 #include <execinfo.h>
50
51 void
52 PBD::stacktrace (std::ostream& out, int levels)
53 {
54         void *array[200];
55         size_t size;
56         char **strings;
57         size_t i;
58
59         size = backtrace (array, 200);
60
61         if (size) {
62                 strings = backtrace_symbols (array, size);
63
64                 if (strings) {
65
66                         for (i = 0; i < size && (levels == 0 || i < size_t(levels)); i++) {
67                                 out << "  " << demangle (strings[i]) << std::endl;
68                         }
69
70                         free (strings);
71                 }
72         } else {
73                 out << "no stacktrace available!" << std::endl;
74         }
75 }
76
77 #elif defined (PLATFORM_WINDOWS)
78
79 #if defined DEBUG && !defined CaptureStackBackTrace
80 #define CaptureStackBackTrace RtlCaptureStackBackTrace
81
82 extern "C" {
83         __declspec(dllimport) USHORT WINAPI CaptureStackBackTrace (
84                                      ULONG  FramesToSkip,
85                                      ULONG  FramesToCapture,
86                                      PVOID  *BackTrace,
87                                      PULONG BackTraceHash);
88 }
89 #endif
90
91 void
92 PBD::stacktrace (std::ostream& out, int)
93 {
94 #ifdef DEBUG
95         const size_t levels = 62; // does not support more then 62 levels of stacktrace
96         unsigned int   i;
97         void         * stack[ levels ];
98         unsigned short frames;
99         SYMBOL_INFO  * symbol;
100         HANDLE         process;
101
102         process = GetCurrentProcess();
103         out << "+++++Backtrace process: " <<  DEBUG_THREAD_SELF << std::endl;
104
105         SymInitialize (process, NULL, TRUE);
106
107         frames = CaptureStackBackTrace (0, levels, stack, NULL);
108
109         out << "+++++Backtrace frames: " << frames << std::endl;
110
111         symbol               = (SYMBOL_INFO*)calloc (sizeof (SYMBOL_INFO) + 256 * sizeof (char), 1);
112         symbol->MaxNameLen   = 255;
113         symbol->SizeOfStruct = sizeof (SYMBOL_INFO);
114
115         for (i = 0; i < frames; ++i) {
116                 SymFromAddr (process, (DWORD64)(stack[i]), 0, symbol);
117                 out << string_compose ("%1: %2 - %3\n", samples - i - 1, symbol->Name, symbol->Address);
118         }
119
120         out.flush ();
121
122         free (symbol);
123 #endif
124 }
125
126 #else
127
128 void
129 PBD::stacktrace (std::ostream& out, int /*levels*/)
130 {
131         out << "stack tracing is not enabled on this platform" << std::endl;
132 }
133
134 #endif
135
136 void
137 c_stacktrace ()
138 {
139         PBD::stacktrace (std::cout);
140 }