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