2 * Copyright (C) 2006 Thomas Sondergaard All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 #include "gltrace_support.h"
34 demangle (const char * mangled
) throw()
36 static char buf
[4096];
38 size_t length
= sizeof(buf
)-1;
40 memset (buf
, 0, sizeof(buf
));
45 char * demangled
= __cxxabiv1::__cxa_demangle(mangled
,
49 if (demangled
&& !status
)
56 printStackTrace (void **stackframes
,
63 // this might actually fail if memory is tight or we are in a
65 strings
= backtrace_symbols (stackframes
, stackframe_size
);
69 if (stackframe_size
== gltrace::MAX_STACKFRAMES
)
70 ss
<< "(possibly incomplete maximal number of frames exceeded):" << std::endl
;
76 // the first frame is the constructor of the exception
77 // the last frame always seem to be bogus?
78 for (int i
= 0; strings
&& i
< stackframe_size
-1; ++i
) {
79 char libname
[257], funcname
[2049];
80 unsigned int address
=0, funcoffset
= 0x0;
82 memset (libname
,0,sizeof(libname
));
83 memset (funcname
,0,sizeof(funcname
));
85 strcpy (funcname
,"??");
86 strcpy (libname
, "??");
88 int scanned
= sscanf (strings
[i
], "%256[^(] ( %2048[^+] + %x ) [ %x ]",
94 /* ok, so no function was mentioned in the backtrace */
96 scanned
= sscanf (strings
[i
], "%256[^([] [ %x ]",
101 if (funcname
[0] == '_') {
102 const char * demangled
;
103 if ((demangled
= demangle(funcname
) ) != funcname
) {
104 strncpy (funcname
, demangled
, sizeof(funcname
)-1);
108 strcat (funcname
," ()");
110 out
<< "\t#" << i
<< std::hex
<< " 0x" << address
<< " in " << funcname
111 << " at 0x" << funcoffset
<< " (from " << libname
<< ")" << std::endl
;
122 std::string
getStackTrace(int count
, int first
) {
124 std::stringstream ss
;
125 const int BA_MAX
= 1000;
126 assert(count
+ first
<= BA_MAX
);
128 int n
= backtrace(ba
, count
+first
);
130 printStackTrace( &ba
[first
], n
-first
, ss
);
135 std::ostream
&timeNow(std::ostream
&os
) {
139 static char *months
[12] =
141 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
142 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
145 gettimeofday (&now
, 0);
146 localtime_r ((time_t*) &now
.tv_sec
, &t
);
149 << months
[t
.tm_mon
] << " "
150 << std::setw(2) << t
.tm_mday
<< " "
151 << std::setw(2) << t
.tm_hour
<< ":"
152 << std::setw(2) << t
.tm_min
<< ":"
153 << std::setw(2) << t
.tm_sec
<< "."
154 << std::setw(3) << now
.tv_usec
/1000;
158 logstream::logstream(const char *filename
) {
160 init(std::cerr
.rdbuf());
162 file_os
.reset(new std::ofstream(filename
));
164 init(file_os
->rdbuf());
166 std::cerr
<< "ERROR: gltrace: Failed to open '" << filename
167 << "' for writing. Falling back to stderr." << std::endl
;
168 init(std::cerr
.rdbuf());
171 *this << std::setfill('0'); // setw used in timeNow
179 log(getenv("GLTRACE_LOGFILE")) {
180 if (const char *v
= getenv("GLTRACE_LOG_CALLS"))
181 logCalls
= strncmp("1", v
, 1) == 0;
182 if (const char *v
= getenv("GLTRACE_CHECK_ERRORS"))
183 checkErrors
= strncmp("1", v
, 1) == 0;
184 if (const char *v
= getenv("GLTRACE_LOG_TIME"))
185 logTime
= strncmp("1", v
, 1) == 0;
191 } // namespace gltrace