1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend 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 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. 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"
39 #include <mach-o/dyld.h>
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
47 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
49 string pOpen(const string &cmd, label line=0)
53 FILE *cmdPipe = popen(cmd.c_str(), "r");
57 // Read line number of lines
58 for (label cnt = 0; cnt <= line; cnt++)
62 char* s = fgets(buffer, MAX-1, cmdPipe);
67 // workaround for the Python-Script
68 for(int i=0;i<MAX;i++) {
82 return str.substr(0, str.size()-1);
92 // use popen to call addr2line (using bfd.h directly would have
93 // meant relinking everything)
95 void printSourceFileAndLine
98 const HashTable<label, fileName>& addressMap,
99 const fileName& filename,
103 word myAddress = address;
106 if (filename.ext() == "so")
108 if (filename.ext() == "dylib")
111 // Convert offset into .so into offset into executable.
114 sscanf(myAddress.c_str(), "%p",&addr);
120 unsigned long offset = reinterpret_cast<unsigned long>(info.dli_fbase);
122 IStringStream addressStr(address.substr(2));
123 label addressValue = readHexLabel(addressStr);
124 label relativeAddress = addressValue-offset;
126 // Reconstruct hex word from address
127 OStringStream nStream;
128 nStream << "0x" << hex << relativeAddress;
129 myAddress = nStream.str();
133 if (filename[0] == '/')
141 "addr2line -f --demangle=auto --exe "
153 os << " addr2line failed";
155 else if (line == "??:0")
157 os << " in " << filename;
161 string cwdLine(line.replaceAll(cwd() + '/', ""));
162 string homeLine(cwdLine.replaceAll(home(), '~'));
164 os << " at " << homeLine.c_str();
174 const fileName& filename,
178 if (filename.size() && filename[0] == '/')
183 "addr2line -f --demangle=auto --exe "
198 os << "Uninterpreted: " << raw.c_str();
201 void error::printStack(Ostream& os)
203 // Do not print anything if FOAM_ABORT is not set
204 if (!env("FOAM_ABORT"))
209 // Reads the starting addresses for the dynamically linked libraries
210 // from the /proc/pid/maps-file
211 // I'm afraid this works only for Linux 2.6-Kernels (may work on 2.4)
212 // Note2: the filenames in here will have softlinks resolved so will
213 // go wrong when having e.g. FOAM installed under a softlink.
215 HashTable<label, fileName> addressMap;
217 IFstream is("/proc/" + name(pid()) + "/maps");
224 string::size_type space = line.rfind(' ') + 1;
225 fileName libPath = line.substr(space, line.size()-space);
227 if (libPath.size() && libPath[0] == '/')
229 string offsetString(line.substr(0, line.find('-')));
230 IStringStream offsetStr(offsetString);
231 addressMap.insert(libPath, readHexLabel(offsetStr));
236 // Get raw stack symbols
238 size_t size = backtrace(array, 100);
239 char **strings = backtrace_symbols(array, size);
241 // See if they contain function between () e.g. "(__libc_start_main+0xd0)"
242 // and see if cplus_demangle can make sense of part before +
243 // HJ, formatting of stack backtrace. 17/Dec/2008
245 for (size_t i = 0; i < size; i++)
247 string msg(strings[i]);
248 fileName programFile;
251 os << '#' << label(i) << " ";
252 //os << "Raw : " << msg << "\n\t";
255 string::size_type lPos = msg.find('[');
256 string::size_type rPos = msg.find(']');
258 if (lPos != string::npos && rPos != string::npos && lPos < rPos)
260 address = msg.substr(lPos+1, rPos-lPos-1);
261 msg = msg.substr(0, lPos);
264 string::size_type bracketPos = msg.find('(');
265 string::size_type spacePos = msg.find(' ');
266 if (bracketPos != string::npos || spacePos != string::npos)
268 programFile = msg.substr(0, min(spacePos, bracketPos));
270 // not an absolute path
271 if (programFile[0] != '/')
273 string tmp = pOpen("which " + programFile);
274 if (tmp[0] == '/' || tmp[0] == '~')
282 string::size_type bracketPos = msg.find('(');
284 string::size_type counter=0;
285 while(msg[counter]!=' ') {
288 while(msg[counter]==' ') {
291 string::size_type fileStart=counter;
292 while(msg[counter]!=' ') {
295 programFile = msg.substr(fileStart,counter-fileStart);
296 if(programFile=="???") {
298 uint32_t size = sizeof(path);
299 if (_NSGetExecutablePath(path, &size) == 0) {
302 programFile="unknownFile";
305 while(msg[counter]==' ') {
308 string::size_type addrStart=counter;
309 while(msg[counter]!=' ') {
312 address = msg.substr(addrStart,counter-addrStart);
315 if (bracketPos != string::npos)
317 string::size_type start = bracketPos+1;
319 string::size_type plusPos = msg.find('+', start);
321 if (plusPos != string::npos)
323 string cName(msg.substr(start, plusPos-start));
326 while(msg[counter]==' ') {
329 string::size_type nameStart=counter;
330 while(msg[counter]!=' ') {
334 string::size_type start = counter;
337 string cName(msg.substr(nameStart,counter-nameStart));
340 char* cplusNamePtr = abi::__cxa_demangle
343 NULL, // have it malloc itself
348 if (status == 0 && cplusNamePtr)
360 string::size_type endBracketPos = msg.find(')', start);
362 if (endBracketPos != string::npos)
364 string fullName(msg.substr(start, endBracketPos-start));
366 os << fullName.c_str() << nl;
371 getSymbolForRaw(os, msg, programFile, address);
378 getSymbolForRaw(os, msg, programFile, address);
381 printSourceFileAndLine(os, addressMap, programFile, address);
390 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
392 } // End namespace Foam
394 // ************************************************************************* //