/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA \*---------------------------------------------------------------------------*/ #include "error.H" #include "IStringStream.H" #include "OStringStream.H" #include "OSspecific.H" #include "IFstream.H" #include "readHexLabel.H" #include #include #include // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam { // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // string pOpen(const string &cmd, label line=0) { const int MAX = 1000; FILE *cmdPipe = popen(cmd.c_str(), "r"); if (cmdPipe) { // Read line number of lines for (label cnt = 0; cnt <= line; cnt++) { char buffer[MAX]; char* s = fgets(buffer, MAX-1, cmdPipe); if (s == NULL) { return ""; } if (cnt == line) { string str(buffer); return str.substr(0, str.size()-1); } } pclose(cmdPipe); } return ""; } // use popen to call addr2line (using bfd.h directly would have // meant relinking everything) void printSourceFileAndLine ( Ostream& os, const HashTable& addressMap, const fileName& filename, const word& address ) { word myAddress = address; if (filename.ext() == "so") { // Convert offset into .so into offset into executable. void *addr; sscanf(myAddress.c_str(), "%p",&addr); Dl_info info; dladdr(addr, &info); unsigned long offset = ulong(info.dli_fbase); IStringStream addressStr(address.substr(2)); label addressValue = readHexLabel(addressStr); label relativeAddress = addressValue-offset; // Reconstruct hex word from address OStringStream nStream; nStream << "0x" << hex << relativeAddress; myAddress = nStream.str(); } if (filename[0] == '/') { string line = pOpen ( "addr2line -f --demangle=auto --exe " + filename + " " + myAddress, 1 ); if (line == "") { os << " addr2line failed"; } else if (line == "??:0") { os << " in " << filename; } else { string cwdLine(line.replaceAll(cwd() + '/', "")); string homeLine(cwdLine.replaceAll(home(), '~')); os << " at " << homeLine.c_str(); } } } void getSymbolForRaw ( Ostream& os, const string& raw, const fileName& filename, const word& address ) { if (filename[0] == '/') { string fcnt = pOpen ( "addr2line -f --demangle=auto --exe " + filename + " " + address ); if (fcnt != "") { os << fcnt.c_str(); return; } } os << "Uninterpreted: " << raw.c_str(); } void error::printStack(Ostream& os) { // Reads the starting addresses for the dynamically linked libraries // from the /proc/pid/maps-file // I'm afraid this works only for Linux 2.6-Kernels (may work on 2.4) // Note2: the filenames in here will have softlinks resolved so will // go wrong when having e.g. OpenFOAM installed under a softlink. HashTable addressMap; { IFstream is("/proc/" + name(pid()) + "/maps"); while(is.good()) { string line; is.getLine(line); string::size_type space = line.rfind(' ') + 1; fileName libPath = line.substr(space, line.size()-space); if (libPath.size() > 0 && libPath[0] == '/') { string offsetString(line.substr(0, line.find('-'))); IStringStream offsetStr(offsetString); addressMap.insert(libPath, readHexLabel(offsetStr)); } } } // Get raw stack symbols void *array[100]; size_t size = backtrace(array, 100); char **strings = backtrace_symbols(array, size); // See if they contain function between () e.g. "(__libc_start_main+0xd0)" // and see if cplus_demangle can make sense of part before + for (size_t i = 0; i < size; i++) { string msg(strings[i]); fileName programFile; word address; os << '#' << label(i) << " "; //os << "Raw : " << msg << "\n\t"; { string::size_type lPos = msg.find('['); string::size_type rPos = msg.find(']'); if (lPos != string::npos && rPos != string::npos && lPos