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"
33 demangle (const char * mangled
) throw()
35 static char buf
[4096];
37 unsigned int length
= sizeof(buf
)-1;
39 memset (buf
, 0, sizeof(buf
));
44 char * demangled
= __cxxabiv1::__cxa_demangle(mangled
,
48 if (demangled
&& !status
)
55 printStackTrace (void **stackframes
,
62 // this might actually fail if memory is tight or we are in a
64 strings
= backtrace_symbols (stackframes
, stackframe_size
);
68 if (stackframe_size
== gltrace::MAX_STACKFRAMES
)
69 ss
<< "(possibly incomplete maximal number of frames exceeded):" << std::endl
;
75 // the first frame is the constructor of the exception
76 // the last frame always seem to be bogus?
77 for (int i
= 0; strings
&& i
< stackframe_size
-1; ++i
) {
78 char libname
[257], funcname
[2049];
79 unsigned int address
=0, funcoffset
= 0x0;
81 memset (libname
,0,sizeof(libname
));
82 memset (funcname
,0,sizeof(funcname
));
84 strcpy (funcname
,"??");
85 strcpy (libname
, "??");
87 int scanned
= sscanf (strings
[i
], "%256[^(] ( %2048[^+] + %x ) [ %x ]",
93 /* ok, so no function was mentioned in the backtrace */
95 scanned
= sscanf (strings
[i
], "%256[^([] [ %x ]",
100 if (funcname
[0] == '_') {
101 const char * demangled
;
102 if ((demangled
= demangle(funcname
) ) != funcname
) {
103 strncpy (funcname
, demangled
, sizeof(funcname
)-1);
107 strcat (funcname
," ()");
109 out
<< "\t#" << i
<< std::hex
<< " 0x" << address
<< " in " << funcname
110 << " at 0x" << funcoffset
<< " (from " << libname
<< ")" << std::endl
;
121 std::string
getStackTrace(int count
, int first
) {
123 std::stringstream ss
;
124 const int BA_MAX
= 1000;
125 assert(count
+ first
<= BA_MAX
);
127 int n
= backtrace(ba
, count
+first
);
129 printStackTrace( &ba
[first
], n
-first
, ss
);
134 std::ostream
&timeNow(std::ostream
&os
) {
138 static char *months
[12] =
140 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
141 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
144 gettimeofday (&now
, 0);
145 localtime_r ((time_t*) &now
.tv_sec
, &t
);
148 << months
[t
.tm_mon
] << " "
149 << std::setw(2) << t
.tm_mday
<< " "
150 << std::setw(2) << t
.tm_hour
<< ":"
151 << std::setw(2) << t
.tm_min
<< ":"
152 << std::setw(2) << t
.tm_sec
<< "."
153 << std::setw(3) << now
.tv_usec
/1000;
157 logstream::logstream(const char *filename
) {
159 init(std::cerr
.rdbuf());
161 file_os
.reset(new std::ofstream(filename
));
163 init(file_os
->rdbuf());
165 std::cerr
<< "ERROR: gltrace: Failed to open '" << filename
166 << "' for writing. Falling back to stderr." << std::endl
;
167 init(std::cerr
.rdbuf());
170 *this << std::setfill('0'); // setw used in timeNow
178 log(getenv("GLTRACE_LOGFILE")) {
179 if (const char *v
= getenv("GLTRACE_LOG_CALLS"))
180 logCalls
= strncmp("1", v
, 1) == 0;
181 if (const char *v
= getenv("GLTRACE_CHECK_ERRORS"))
182 checkErrors
= strncmp("1", v
, 1) == 0;
183 if (const char *v
= getenv("GLTRACE_LOG_TIME"))
184 logTime
= strncmp("1", v
, 1) == 0;
190 } // namespace gltrace