Skip to content

Commit c78c142

Browse files
committed
enable backtrace
1 parent d4641e9 commit c78c142

File tree

3 files changed

+146
-1
lines changed

3 files changed

+146
-1
lines changed

main/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ void funcAbort(int signal_number) {
5454
*/
5555
#if (defined(__GNUC__) || defined(__clang__)) && !defined(WIN32) && \
5656
!defined(WIN64) && !defined(__CYGWIN__)
57-
// print_stacktrace(cerr);
57+
print_backtrace(cerr);
5858
#endif
5959

6060
cerr << endl << "*** CMAPLE CRASHES WITH SIGNAL ";

utils/tools.cpp

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,3 +1663,138 @@ void cmaple::resetStream(std::istream& instream) {
16631663
instream.clear();
16641664
instream.seekg(0, ios::beg);
16651665
}
1666+
1667+
/** Print a demangled stack backtrace of the caller function to FILE* out. */
1668+
1669+
#if !defined(Backtrace_FOUND)
1670+
1671+
// donothing for WIN32
1672+
void cmaple::print_backtrace(ostream &out, unsigned int max_frames) {}
1673+
1674+
#else
1675+
1676+
void cmaple::print_backtrace(ostream &out, unsigned int max_frames)
1677+
{
1678+
#ifdef _OPENMP
1679+
#pragma omp master
1680+
{
1681+
#endif
1682+
out << "STACK TRACE FOR DEBUGGING:" << endl;
1683+
1684+
// storage array for stack trace address data
1685+
void* addrlist[max_frames+1];
1686+
1687+
// retrieve current stack addresses
1688+
int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*));
1689+
1690+
// if (addrlen == 0) {
1691+
// out << " <empty, possibly corrupt>" << endl;
1692+
// return;
1693+
// }
1694+
1695+
// resolve addresses into strings containing "filename(function+address)",
1696+
// this array must be free()-ed
1697+
char** symbollist = backtrace_symbols(addrlist, addrlen);
1698+
1699+
// allocate string which will be filled with the demangled function name
1700+
size_t funcnamesize = 256;
1701+
char* funcname = (char*)malloc(funcnamesize);
1702+
1703+
// iterate over the returned symbol lines. skip the first, it is the
1704+
// address of this function.
1705+
for (int i = 1; i < addrlen; i++)
1706+
{
1707+
char *begin_name = 0, *begin_offset = 0;
1708+
1709+
// find parentheses and +address offset surrounding the mangled name:
1710+
#ifdef __clang__
1711+
// OSX style stack trace
1712+
for ( char *p = symbollist[i]; *p; ++p )
1713+
{
1714+
if (( *p == '_' ) && ( *(p-1) == ' ' ))
1715+
begin_name = p-1;
1716+
else if ( *p == '+' )
1717+
begin_offset = p-1;
1718+
}
1719+
1720+
if ( begin_name && begin_offset && ( begin_name < begin_offset ))
1721+
{
1722+
*begin_name++ = '\0';
1723+
*begin_offset++ = '\0';
1724+
1725+
// mangled name is now in [begin_name, begin_offset) and caller
1726+
// offset in [begin_offset, end_offset). now apply
1727+
// __cxa_demangle():
1728+
int status;
1729+
char* ret = abi::__cxa_demangle( begin_name, &funcname[0],
1730+
&funcnamesize, &status );
1731+
if ( status == 0 )
1732+
{
1733+
funcname = ret; // use possibly realloc()-ed string
1734+
// out << " " << symbollist[i] << " : " << funcname << "+"<< begin_offset << endl;
1735+
out << i << " " << funcname << endl;
1736+
} else {
1737+
// demangling failed. Output function name as a C function with
1738+
// no arguments.
1739+
// out << " " << symbollist[i] << " : " << begin_name << "()+"<< begin_offset << endl;
1740+
out << i << " " << begin_name << "()" << endl;
1741+
}
1742+
1743+
#else // !DARWIN - but is posix
1744+
// ./module(function+0x15c) [0x8048a6d]
1745+
char *end_offset = 0;
1746+
for (char *p = symbollist[i]; *p; ++p)
1747+
{
1748+
if (*p == '(')
1749+
begin_name = p;
1750+
else if (*p == '+')
1751+
begin_offset = p;
1752+
else if (*p == ')' && begin_offset) {
1753+
end_offset = p;
1754+
break;
1755+
}
1756+
}
1757+
1758+
if (begin_name && begin_offset && end_offset
1759+
&& begin_name < begin_offset)
1760+
{
1761+
*begin_name++ = '\0';
1762+
*begin_offset++ = '\0';
1763+
*end_offset = '\0';
1764+
1765+
// mangled name is now in [begin_name, begin_offset) and caller
1766+
// offset in [begin_offset, end_offset). now apply
1767+
// __cxa_demangle():
1768+
1769+
int status;
1770+
char* ret = abi::__cxa_demangle(begin_name,
1771+
funcname, &funcnamesize, &status);
1772+
if (status == 0) {
1773+
funcname = ret; // use possibly realloc()-ed string
1774+
// out << " " << symbollist[i] << " : " << funcname << "+"<< begin_offset << endl;
1775+
out << i << " " << funcname << endl;
1776+
}
1777+
else {
1778+
// demangling failed. Output function name as a C function with
1779+
// no arguments.
1780+
// out << " " << symbollist[i] << " : " << begin_name << "()+"<< begin_offset << endl;
1781+
out << i << " " << begin_name << "()" << endl;
1782+
}
1783+
#endif
1784+
}
1785+
else
1786+
{
1787+
// couldn't parse the line? print the whole line.
1788+
// out << i << ". " << symbollist[i] << endl;
1789+
}
1790+
}
1791+
1792+
free(funcname);
1793+
free(symbollist);
1794+
#ifdef _OPENMP
1795+
}
1796+
#endif
1797+
1798+
}
1799+
1800+
#endif // Backtrace_FOUND

utils/tools.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@
5252
#include <omp.h> /* OpenMP */
5353
#endif
5454

55+
#if defined(Backtrace_FOUND)
56+
#include <execinfo.h>
57+
#include <cxxabi.h>
58+
#endif
59+
5560
/*#ifdef NDEBUG
5661
#define ASSERT(EXPRESSION) ((void)0)
5762
#else
@@ -1318,4 +1323,9 @@ std::unique_ptr<T> make_unique(Args&&... args) {
13181323
* @param instream the input stream
13191324
*/
13201325
void resetStream(std::istream& instream);
1326+
1327+
/**
1328+
* Print backtrace
1329+
*/
1330+
void print_backtrace(std::ostream &out, unsigned int max_frames = 63);
13211331
} // namespace cmaple

0 commit comments

Comments
 (0)