1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
28 #include "IStringStream.H"
29 #include "OStringStream.H"
30 #include "OSspecific.H"
32 #include "readHexLabel.H"
38 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
43 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
45 string pOpen(const string &cmd, label line=0)
49 FILE *cmdPipe = popen(cmd.c_str(), "r");
53 // Read line number of lines
54 for (label cnt = 0; cnt <= line; cnt++)
57 char* s = fgets(buffer, MAX-1, cmdPipe);
67 return str.substr(0, str.size()-1);
77 // use popen to call addr2line (using bfd.h directly would have
78 // meant relinking everything)
80 void printSourceFileAndLine
83 const HashTable<label, fileName>& addressMap,
84 const fileName& filename,
88 word myAddress = address;
90 if (filename.ext() == "so")
92 // Convert offset into .so into offset into executable.
95 sscanf(myAddress.c_str(), "%p",&addr);
101 unsigned long offset = ulong(info.dli_fbase);
103 IStringStream addressStr(address.substr(2));
104 label addressValue = readHexLabel(addressStr);
105 label relativeAddress = addressValue-offset;
107 // Reconstruct hex word from address
108 OStringStream nStream;
109 nStream << "0x" << hex << relativeAddress;
110 myAddress = nStream.str();
113 if (filename[0] == '/')
117 "addr2line -f --demangle=auto --exe "
126 os << " addr2line failed";
128 else if (line == "??:0")
130 os << " in " << filename;
134 string cwdLine(line.replaceAll(cwd() + '/', ""));
136 string homeLine(cwdLine.replaceAll(home(), '~'));
138 os << " at " << homeLine.c_str();
148 const fileName& filename,
152 if (filename.size() > 0 && filename[0] == '/')
156 "addr2line -f --demangle=auto --exe "
168 os << "Uninterpreted: " << raw.c_str();
172 void error::printStack(Ostream& os)
174 // Reads the starting addresses for the dynamically linked libraries
175 // from the /proc/pid/maps-file
176 // I'm afraid this works only for Linux 2.6-Kernels (may work on 2.4)
177 // Note2: the filenames in here will have softlinks resolved so will
178 // go wrong when having e.g. OpenFOAM installed under a softlink.
180 HashTable<label, fileName> addressMap;
182 IFstream is("/proc/" + name(pid()) + "/maps");
189 string::size_type space = line.rfind(' ') + 1;
190 fileName libPath = line.substr(space, line.size()-space);
192 if (libPath.size() > 0 && libPath[0] == '/')
194 string offsetString(line.substr(0, line.find('-')));
195 IStringStream offsetStr(offsetString);
196 addressMap.insert(libPath, readHexLabel(offsetStr));
201 // Get raw stack symbols
203 size_t size = backtrace(array, 100);
204 char **strings = backtrace_symbols(array, size);
206 // See if they contain function between () e.g. "(__libc_start_main+0xd0)"
207 // and see if cplus_demangle can make sense of part before +
208 for (size_t i = 0; i < size; i++)
210 string msg(strings[i]);
211 fileName programFile;
214 os << '#' << label(i) << " ";
215 //os << "Raw : " << msg << "\n\t";
217 string::size_type lPos = msg.find('[');
218 string::size_type rPos = msg.find(']');
220 if (lPos != string::npos && rPos != string::npos && lPos<rPos)
222 address = msg.substr(lPos+1, rPos-lPos-1);
223 msg = msg.substr(0, lPos);
226 string::size_type bracketPos = msg.find('(');
227 string::size_type spacePos = msg.find(' ');
228 if (bracketPos != string::npos || spacePos != string::npos)
230 programFile = msg.substr(0, min(spacePos, bracketPos));
232 // not an absolute path
233 if (programFile[0] != '/')
235 string tmp = pOpen("which "+programFile);
236 if (tmp[0] == '/' || tmp[0] == '~')
244 string::size_type bracketPos = msg.find('(');
246 if (bracketPos != string::size_type(string::npos))
248 string::size_type start = bracketPos+1;
250 string::size_type plusPos = msg.find('+', start);
252 if (plusPos != string::size_type(string::npos))
254 string cName(msg.substr(start, plusPos-start));
257 char* cplusNamePtr = abi::__cxa_demangle
260 NULL, // have it malloc itself
265 if (status == 0 && cplusNamePtr)
277 string::size_type endBracketPos = msg.find(')', start);
279 if (endBracketPos != string::size_type(string::npos))
281 string fullName(msg.substr(start, endBracketPos-start));
283 os << fullName.c_str() << nl;
288 getSymbolForRaw(os, msg, programFile, address);
295 getSymbolForRaw(os, msg, programFile, address);
298 printSourceFileAndLine(os, addressMap, programFile, address);
307 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
309 } // End namespace Foam
311 // ************************************************************************* //