FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

printStack.C

Go to the documentation of this file.
00001 /*----------------------------------------------------------------------------*\
00002                 ______                _     ____          __  __
00003                |  ____|             _| |_  / __ \   /\   |  \/  |
00004                | |__ _ __ ___  ___ /     \| |  | | /  \  | \  / |
00005                |  __| '__/ _ \/ _ ( (| |) ) |  | |/ /\ \ | |\/| |
00006                | |  | | |  __/  __/\_   _/| |__| / ____ \| |  | |
00007                |_|  |_|  \___|\___|  |_|   \____/_/    \_\_|  |_|
00008 
00009                     FreeFOAM: The Cross-Platform CFD Toolkit
00010 
00011   Copyright (C) 2008-2012 Michael Wild <themiwi@users.sf.net>
00012                           Gerber van der Graaf <gerber_graaf@users.sf.net>
00013 --------------------------------------------------------------------------------
00014 License
00015     This file is part of FreeFOAM.
00016 
00017     FreeFOAM is free software: you can redistribute it and/or modify it
00018     under the terms of the GNU General Public License as published by
00019     the Free Software Foundation, either version 3 of the License, or
00020     (at your option) any later version.
00021 
00022     FreeFOAM is distributed in the hope that it will be useful, but WITHOUT
00023     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00024     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00025     for more details.
00026 
00027     You should have received a copy of the GNU General Public License
00028     along with FreeFOAM.  If not, see <http://www.gnu.org/licenses/>.
00029 
00030 \*----------------------------------------------------------------------------*/
00031 
00032 #include <OpenFOAM/error.H>
00033 #include <OpenFOAM/OStringStream.H>
00034 
00035 #include <cxxabi.h>
00036 #include <execinfo.h>
00037 
00038 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00039 
00040 // Local helper function
00041 void tokenizeSymbols( const Foam::string& symbols, Foam::string& module,
00042                       Foam::string& address, Foam::string& function,
00043                       Foam::string& offset )
00044 {
00045     size_t s(0), e;
00046     // Mac OS X uses a different output format for backtrac_symbols.
00047     // Thanks Apple, really.
00048 #ifdef darwin
00049     // this is for Mac OS X 10.5 Leopard and newer
00050     std::string blanks(" \t");
00051     // format: level module address function + offset
00052     // skip the stack level
00053     s = symbols.find_first_of(blanks,s);
00054     // find the module name
00055     s = symbols.find_first_not_of(blanks,s+1);
00056     e = symbols.find_first_of(blanks,s+1);
00057     module = symbols.substr(s,e-s);
00058     // find the address
00059     s = symbols.find_first_not_of(blanks,e+1);
00060     e = symbols.find_first_of(blanks,s+1);
00061     address = symbols.substr(s,e-s);
00062     // find the (mangled) function name
00063     s = symbols.find_first_not_of(blanks,e+1);
00064     e = symbols.find_first_of(blanks,s+1);
00065     function = symbols.substr(s,e-s);
00066     // skip the + sign
00067     s = symbols.find_first_not_of(blanks,e+1);
00068     e = symbols.find_first_of(blanks,s+1);
00069     // find the offset into the function
00070     s = symbols.find_first_not_of(blanks,e+1);
00071     e = symbols.find_first_of(blanks,s+1);
00072     offset = symbols.substr(s,e-s);
00073 #else
00074     // this is for GNU glibc (assumed)
00075     // format: module(function+offset) [address]
00076     // find the module name
00077     e = symbols.find('(',s);
00078     module = symbols.substr(s,e-s);
00079     // find the (mangled) function name
00080     s = e;
00081     e = symbols.find('+',s+1);
00082     function = symbols.substr(s+1,e-s-1);
00083     // find the offset
00084     s = e;
00085     e = symbols.find(')',s+1);
00086     offset = symbols.substr(s+1,e-s-1);
00087     // find the address
00088     s = symbols.find('[',s+1);
00089     e = symbols.find(']',s+2);
00090     address = symbols.substr(s+1,e-s-1);
00091 #endif
00092 }
00093 
00094 
00095 void Foam::error::printStack(Foam::Ostream& os)
00096 {
00097     os << "  Stack trace:\n";
00098 
00099     // storage array for stack trace address data
00100     const size_t max_frames = 100;
00101     void* addrlist[max_frames];
00102 
00103     // retrieve current stack addresses
00104     int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*));
00105 
00106     if (addrlen == 0) {
00107         os << "*        <EMPTY BACKTRACE, POSSIBLY CORRUPT STACK.>        *\n";
00108     } else {
00109         // resolve addresses into strings containing "filename(function+address)",
00110         // this array must be free()-ed
00111         char** symbollist = backtrace_symbols(addrlist, addrlen);
00112 
00113         // allocate string which will be filled with the demangled function name
00114         size_t funcnamesize = 256;
00115         char* funcname = new char[funcnamesize];
00116 
00117         // iterate over the returned symbol lines. skip the first two, it is the
00118         // address of this function and the sigSegvImpl::sigSegvHandler function.
00119         for (size_t i = 2; i < addrlen; i++)
00120         {
00121             // tokenize the symbols string
00122             string module, function, address, offset;
00123             tokenizeSymbols( symbollist[i], module, address, function, offset );
00124 
00125             if (! (module.empty() || address.empty() || function.empty() || offset.empty()) )
00126             {
00127                 // try to demangle
00128                 int status;
00129                 char* ret = abi::__cxa_demangle(function.c_str(), NULL, 0, &status);
00130                 if (status == 0) {
00131                     function.assign( ret );
00132                     free( ret );
00133                     os << "  " << int(i-2) << " " << module.c_str() << " [" << address.c_str() << "]: "
00134                         << function.c_str() << " + " << offset.c_str() << "\n";
00135                 }
00136                 else {
00137                     // demangling failed. Output function name as a C function with
00138                     // no arguments.
00139                     os << "  " << int(i-2) << " " << module.c_str() << " [" << address.c_str() << "]: "
00140                         << function.c_str() << " + " << offset.c_str() << "\n";
00141                 }
00142             }
00143             else
00144             {
00145                 // couldn't parse the line? print the whole line.
00146                 os << "  " << int(i-2) << " " << symbollist[i] << "\n";
00147             }
00148         }
00149 
00150         delete[] funcname;
00151         free(symbollist);
00152     }
00153 }
00154 
00155 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines