1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
27 #include "IStringStream.H"
28 #include "OStringStream.H"
29 #include "OSspecific.H"
31 #include "readHexLabel.H"
37 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
44 string pOpen(const string &cmd, label line=0)
48 FILE *cmdPipe = popen(cmd.c_str(), "r");
52 // Read line number of lines
53 for (label cnt = 0; cnt <= line; cnt++)
56 char* s = fgets(buffer, MAX-1, cmdPipe);
66 return str.substr(0, str.size()-1);
76 // use popen to call addr2line (using bfd.h directly would have
77 // meant relinking everything)
79 void printSourceFileAndLine
82 const HashTable<label, fileName>& addressMap,
83 const fileName& filename,
87 word myAddress = address;
89 if (filename.ext() == "so")
91 // Convert offset into .so into offset into executable.
94 sscanf(myAddress.c_str(), "%p",&addr);
100 unsigned long offset = ulong(info.dli_fbase);
102 IStringStream addressStr(address.substr(2));
103 label addressValue = readHexLabel(addressStr);
104 label relativeAddress = addressValue-offset;
106 // Reconstruct hex word from address
107 OStringStream nStream;
108 nStream << "0x" << hex << relativeAddress;
109 myAddress = nStream.str();
112 if (filename[0] == '/')
116 "addr2line -f --demangle=auto --exe "
125 os << " addr2line failed";
127 else if (line == "??:0")
129 os << " in " << filename;
133 string cwdLine(line.replaceAll(cwd() + '/', ""));
134 string homeLine(cwdLine.replaceAll(home(), '~'));
136 os << " at " << homeLine.c_str();
146 const fileName& filename,
150 if (filename.size() && filename[0] == '/')
154 "addr2line -f --demangle=auto --exe "
166 os << "Uninterpreted: " << raw.c_str();
170 void error::printStack(Ostream& os)
172 // Reads the starting addresses for the dynamically linked libraries
173 // from the /proc/pid/maps-file
174 // I'm afraid this works only for Linux 2.6-Kernels (may work on 2.4)
175 // Note2: the filenames in here will have softlinks resolved so will
176 // go wrong when having e.g. OpenFOAM installed under a softlink.
178 HashTable<label, fileName> addressMap;
180 IFstream is("/proc/" + name(pid()) + "/maps");
187 string::size_type space = line.rfind(' ') + 1;
188 fileName libPath = line.substr(space, line.size()-space);
190 if (libPath.size() && libPath[0] == '/')
192 string offsetString(line.substr(0, line.find('-')));
193 IStringStream offsetStr(offsetString);
194 addressMap.insert(libPath, readHexLabel(offsetStr));
199 // Get raw stack symbols
201 size_t size = backtrace(array, 100);
202 char **strings = backtrace_symbols(array, size);
204 // See if they contain function between () e.g. "(__libc_start_main+0xd0)"
205 // and see if cplus_demangle can make sense of part before +
206 for (size_t i = 0; i < size; i++)
208 string msg(strings[i]);
209 fileName programFile;
212 os << '#' << label(i) << " ";
213 //os << "Raw : " << msg << "\n\t";
215 string::size_type lPos = msg.find('[');
216 string::size_type rPos = msg.find(']');
218 if (lPos != string::npos && rPos != string::npos && lPos < rPos)
220 address = msg.substr(lPos+1, rPos-lPos-1);
221 msg = msg.substr(0, lPos);
224 string::size_type bracketPos = msg.find('(');
225 string::size_type spacePos = msg.find(' ');
226 if (bracketPos != string::npos || spacePos != string::npos)
228 programFile = msg.substr(0, min(spacePos, bracketPos));
230 // not an absolute path
231 if (programFile[0] != '/')
233 string tmp = pOpen("which " + programFile);
234 if (tmp[0] == '/' || tmp[0] == '~')
242 string::size_type bracketPos = msg.find('(');
244 if (bracketPos != string::npos)
246 string::size_type start = bracketPos+1;
248 string::size_type plusPos = msg.find('+', start);
250 if (plusPos != string::npos)
252 string cName(msg.substr(start, plusPos-start));
255 char* cplusNamePtr = abi::__cxa_demangle
258 NULL, // have it malloc itself
263 if (status == 0 && cplusNamePtr)
275 string::size_type endBracketPos = msg.find(')', start);
277 if (endBracketPos != string::npos)
279 string fullName(msg.substr(start, endBracketPos-start));
281 os << fullName.c_str() << nl;
286 getSymbolForRaw(os, msg, programFile, address);
293 getSymbolForRaw(os, msg, programFile, address);
296 printSourceFileAndLine(os, addressMap, programFile, address);
305 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
307 } // End namespace Foam
309 // ************************************************************************* //