Toggle navigation
Documentation
Big picture
The finite element method
The data structure
Not-so-quick guide
Optimisation
Order of action functions
Example codes and tutorials
List of example codes and tutorials
Meshing
Solvers
MPI parallel processing
Post-processing/visualisation
Other
Change log
Creating documentation
Coding conventions
Index
FAQ
Get it
Installation guide
Get code from subversion repository
Get code as tar file
Copyright
About
People
Contact/Get involved
Publications
Acknowledgements
Picture show
Go
src
generic
stacktrace.h
Go to the documentation of this file.
1
//LIC// ====================================================================
2
//LIC// This file forms part of oomph-lib, the object-oriented,
3
//LIC// multi-physics finite-element library, available
4
//LIC// at http://www.oomph-lib.org.
5
//LIC//
6
//LIC// Version 1.0; svn revision $LastChangedRevision$
7
//LIC//
8
//LIC// $LastChangedDate$
9
//LIC//
10
//LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11
//LIC//
12
//LIC// This library is free software; you can redistribute it and/or
13
//LIC// modify it under the terms of the GNU Lesser General Public
14
//LIC// License as published by the Free Software Foundation; either
15
//LIC// version 2.1 of the License, or (at your option) any later version.
16
//LIC//
17
//LIC// This library is distributed in the hope that it will be useful,
18
//LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19
//LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20
//LIC// Lesser General Public License for more details.
21
//LIC//
22
//LIC// You should have received a copy of the GNU Lesser General Public
23
//LIC// License along with this library; if not, write to the Free Software
24
//LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25
//LIC// 02110-1301 USA.
26
//LIC//
27
//LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28
//LIC//
29
//LIC//====================================================================
30
//====================================================================
31
// stacktrace.h (c) 2008, Timo Bingmann from http://idlebox.net/
32
// published under the WTFPL v2.0
33
34
// Modified by MH to take proper C++ output stream and to produce
35
// code for retrieval of line numbers. Also obtains name of
36
// executable from oomph-lib CommandLineArgs namespace (if it's been
37
// set up)
38
//====================================================================
39
#ifndef _STACKTRACE_H_
40
#define _STACKTRACE_H_
41
42
#include <stdio.h>
43
#include <stdlib.h>
44
#include <execinfo.h>
45
#include <cxxabi.h>
46
47
// Include oomph-utilities to be able to obtain name of executable
48
#include "
oomph_utilities.h
"
49
50
/** Print a demangled stack backtrace of the caller function */
51
static
inline
void
print_stacktrace
(std::ostream &exception_stream,
52
unsigned
int
max_frames = 63)
53
{
54
55
exception_stream <<
"\nStack trace:\n"
;
56
exception_stream <<
"------------\n"
;
57
58
// storage array for stack trace address data
59
void
* addrlist[max_frames+1];
60
61
// retrieve current stack addresses
62
int
addrlen = backtrace(addrlist,
sizeof
(addrlist) /
sizeof
(
void
*));
63
64
if
(addrlen == 0)
65
{
66
exception_stream <<
"\n<empty stack trace, possibly corrupt>\n"
;
67
return
;
68
}
69
70
// resolve addresses into strings containing "filename(function+address)",
71
// this array must be free()-ed
72
char
** symbollist = backtrace_symbols(addrlist, addrlen);
73
74
// allocate string which will be filled with the demangled function name
75
size_t
funcnamesize = 256;
76
char
* funcname = (
char
*)malloc(funcnamesize);
77
78
// Stream to collect information that allows retrieval of line numbers
79
std::stringstream address_stream;
80
81
// iterate over the returned symbol lines. skip the first, it is the
82
// address of this function.
83
for
(
int
i
= 1;
i
< addrlen;
i
++)
84
{
85
86
// ------------- begin mh addition ---------------
87
char
* begin_absolute=0, *end_absolute=0;
88
89
// find absolute address (in square brackets)
90
// ./module(function+0x15c) [0x8048a6d]
91
for
(
char
*p = symbollist[
i
]; *p; ++p)
92
{
93
if
(*p ==
'['
)
94
begin_absolute = p;
95
else
if
(*p ==
']'
&& begin_absolute) {
96
end_absolute = p;
97
break
;
98
}
99
}
100
101
if
(begin_absolute)
102
{
103
*begin_absolute++ =
'\0'
;
104
*end_absolute =
'\0'
;
105
if
(
oomph::CommandLineArgs::Argc
!=0)
106
{
107
address_stream <<
"addr2line -e "
108
<<
oomph::CommandLineArgs::Argv
[0] <<
" "
109
<< begin_absolute <<
"\n"
;
110
}
111
else
112
{
113
address_stream <<
"addr2line -e [name_of_executable] "
114
<< begin_absolute <<
"\n"
;
115
}
116
}
117
118
// ------------- end mh addition ---------------
119
120
char
*begin_name = 0, *begin_offset = 0, *end_offset = 0;
121
122
// find parentheses and +address offset surrounding the mangled name:
123
// ./module(function+0x15c) [0x8048a6d]
124
for
(
char
*p = symbollist[
i
]; *p; ++p)
125
{
126
if
(*p ==
'('
)
127
begin_name = p;
128
else
if
(*p ==
'+'
)
129
begin_offset = p;
130
else
if
(*p ==
')'
&& begin_offset) {
131
end_offset = p;
132
break
;
133
}
134
}
135
136
if
(begin_name && begin_offset && end_offset
137
&& begin_name < begin_offset)
138
{
139
*begin_name++ =
'\0'
;
140
*begin_offset++ =
'\0'
;
141
*end_offset =
'\0'
;
142
143
// mangled name is now in [begin_name, begin_offset) and caller
144
// offset in [begin_offset, end_offset). now apply
145
// __cxa_demangle():
146
147
int
status;
148
char
* ret = abi::__cxa_demangle(begin_name,
149
funcname, &funcnamesize, &status);
150
if
(status == 0) {
151
funcname = ret;
// use possibly realloc()-ed string
152
/* fprintf(out, " %s : %s+%s\n", */
153
/* symbollist[i], funcname, begin_offset); */
154
exception_stream << symbollist[
i
] <<
" : "
<< funcname <<
"+"
155
<< begin_offset << std::endl;
156
157
}
158
else
{
159
// demangling failed. Output function name as a C function with
160
// no arguments.
161
/* fprintf(out, " %s : %s()+%s\n", */
162
/* symbollist[i], begin_name, begin_offset); */
163
164
exception_stream << symbollist[
i
] <<
" : "
<< begin_name <<
"+"
165
<< begin_offset << std::endl;
166
}
167
}
168
else
169
{
170
// couldn't parse the line? print the whole line.
171
//fprintf(out, " %s\n", symbollist[i]);
172
exception_stream << symbollist[
i
]<< std::endl;
173
174
}
175
176
}
177
178
exception_stream
179
<<
"\nHere are the commmands to obtain the line numbers:\n"
;
180
181
exception_stream
182
<<
"--------------------------------------------------\n"
;
183
exception_stream << address_stream.str() << std::endl;
184
185
186
if
(
oomph::CommandLineArgs::Argc
==0)
187
{
188
exception_stream <<
"\nNOTE: Replace [name_of_executable] by the actual\n"
189
<<
" name of the executable. I would have inserted\n"
190
<<
" this for you if you had called \n\n"
191
<<
" CommandLineArgs::setup(argc,argv);\n\n"
192
<<
" in your driver code...\n\n"
;
193
}
194
195
free(funcname);
196
free(symbollist);
197
}
198
199
#endif // _STACKTRACE_H_
oomph::CommandLineArgs::Argv
char ** Argv
Arguments themselves.
Definition:
oomph_utilities.cc:635
i
cstr elem_len * i
Definition:
cfortran.h:607
oomph_utilities.h
print_stacktrace
static void print_stacktrace(std::ostream &exception_stream, unsigned int max_frames=63)
Definition:
stacktrace.h:51
oomph::CommandLineArgs::Argc
int Argc
Number of arguments + 1.
Definition:
oomph_utilities.cc:632