blocxx
StackTrace.cpp
Go to the documentation of this file.
1/*******************************************************************************
2* Copyright (C) 2005, Vintela, Inc. All rights reserved.
3* Copyright (C) 2006, Novell, Inc. All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7*
8* * Redistributions of source code must retain the above copyright notice,
9* this list of conditions and the following disclaimer.
10* * Redistributions in binary form must reproduce the above copyright
11* notice, this list of conditions and the following disclaimer in the
12* documentation and/or other materials provided with the distribution.
13* * Neither the name of
14* Vintela, Inc.,
15* nor Novell, Inc.,
16* nor the names of its contributors or employees may be used to
17* endorse or promote products derived from this software without
18* specific prior written permission.
19*
20* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30* POSSIBILITY OF SUCH DAMAGE.
31*******************************************************************************/
32
33
38#include "blocxx/BLOCXX_config.h"
39#include "blocxx/StackTrace.hpp"
40
41#ifdef BLOCXX_WIN32
42#include <iostream> // for cerr
43namespace BLOCXX_NAMESPACE
44{
45using std::cerr;
46using std::endl;
47void StackTrace::printStackTrace(EDoStackTraceFlag)
48{
49 cerr << "StackTrace::printStackTrace not implemented yet" << endl;
50}
51}
52#else
53
54#include "blocxx/Exec.hpp"
56#include "blocxx/Format.hpp"
57#include "blocxx/Array.hpp"
59
60#include <fstream>
61#include <iostream> // for cerr
62
63#if defined(BLOCXX_HAVE_BACKTRACE)
64#include <execinfo.h>
65#endif
66
67#if defined(BLOCXX_HAVE_CXXABI_H)
68#include <cxxabi.h>
69#endif
70
71#ifdef BLOCXX_HAVE_UNISTD_H
72extern "C"
73{
74#include <unistd.h> // for getpid()
75}
76#endif
77
78namespace BLOCXX_NAMESPACE
79{
80
81using std::ifstream;
82using std::ofstream;
83using std::flush;
84
85#ifndef BLOCXX_DEFAULT_GDB_PATH
86#define BLOCXX_DEFAULT_GDB_PATH "/usr/bin/gdb"
87#endif
88
89// static
91{
92 std::cerr << getStackTrace(doStackTrace);
93}
94
96{
97
98 if (doStackTrace == E_NO_CHECK_ENV_VAR || (doStackTrace == E_CHECK_ENV_VAR && getenv("BLOCXX_STACKTRACE")))
99 {
100 // if we have the GNU backtrace functions we use them. They don't give
101 // as good information as gdb does, but they are orders of magnitude
102 // faster!
103#ifdef BLOCXX_HAVE_BACKTRACE
104 void *array[200];
105
106 size_t size = backtrace (array, 200);
107 char **strings = backtrace_symbols (array, size);
108
109 StringBuffer bt;
110
111 size_t i;
112 for (i = 0; i < size; i++)
113 {
114#if defined(BLOCXX_HAVE_CXXABI_H)
115 bt += strings[i];
116 int status;
117 // extract the identifier from strings[i]. It's inside of parens.
118 char* firstparen = ::strchr(strings[i], '(');
119 char* lastparen = ::strchr(strings[i], '+');
120 if (firstparen != 0 && lastparen != 0 && firstparen < lastparen)
121 {
122 bt += ": ";
123 *lastparen = '\0';
124 char* realname = abi::__cxa_demangle(firstparen+1, 0, 0, &status);
125 bt += realname;
126 free(realname);
127 }
128#else
129 bt += strings[i];
130#endif
131 bt += "\n";
132 }
133
134 free (strings);
135
136 return bt.releaseString();
137#else
138 ifstream file(BLOCXX_DEFAULT_GDB_PATH);
139 if (file)
140 {
141 file.close();
142 String scriptName("/tmp/owgdb-");
143 String outputName("/tmp/owgdbout-");
144 // TODO: don't use getppid, get it from somewhere else!
145 outputName += String(UInt32(::getpid()));
146 scriptName += String(UInt32(::getpid())) + ".sh";
147 String exeName("/proc/");
148 exeName += String(UInt32(::getpid())) + "/exe";
149
150 ofstream scriptFile(scriptName.c_str(), std::ios::out);
151 scriptFile << "#!/bin/sh\n"
152 << "gdb " << exeName << " " << ::getpid() << " << EOS > " << outputName << " 2>&1\n"
153// doesn't work with gdb 5.1 << "thread apply all bt\n"
154 << "bt\n"
155 << "detach\n"
156 << "q\n"
157 << "EOS\n" << flush;
158 scriptFile.close();
159 Array<String> command;
160 command.push_back( "/bin/sh" );
161 command.push_back( scriptName );
162 Exec::system(command);
163 ifstream outputFile(outputName.c_str(), std::ios::in);
164 StringBuffer output;
165 while (outputFile)
166 {
167 output += String::getLine(outputFile);
168 output += "\n";
169 }
170 outputFile.close();
171 unlink(outputName.c_str());
172 unlink(scriptName.c_str());
173 return output.releaseString();
174 }
175#endif
176 }
177 return String();
178}
179
180} // end namespace BLOCXX_NAMESPACE
181
182#endif // ifdef BLOCXX_WIN32
#define BLOCXX_DEFAULT_GDB_PATH
Array<> wraps std::vector<> in COWReference<> adding ref counting and copy on write capability.
Definition ArrayFwd.hpp:46
void push_back(const T &x)
Append an element to the end of the Array.
This String class is an abstract data type that represents as NULL terminated string of characters.
Definition String.hpp:67
const char * c_str() const
Definition String.cpp:905
static String getLine(std::istream &istr)
Reads from in input stream until a newline is encountered.
Definition String.cpp:1505
Process::Status system(const Array< String > &command, const char *const envp[], const Timeout &timeout)
Execute a command.
Definition Exec.cpp:94
BLOCXX_COMMON_API String getStackTrace(EDoStackTraceFlag=E_NO_CHECK_ENV_VAR)
BLOCXX_COMMON_API void printStackTrace(EDoStackTraceFlag=E_CHECK_ENV_VAR)
Taken from RFC 1321.