BUG: radialActuactionDiskSource: corrected maxR calculation.
[OpenFOAM-2.0.x.git] / src / OSspecific / POSIX / printStack.C
blobdf31b35f7b37c149444daa8294eb5368e34543c3
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
19     for more details.
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 \*---------------------------------------------------------------------------*/
26 #include "error.H"
27 #include "IStringStream.H"
28 #include "OStringStream.H"
29 #include "OSspecific.H"
30 #include "IFstream.H"
31 #include "readHexLabel.H"
33 #include <cxxabi.h>
34 #include <execinfo.h>
35 #include <dlfcn.h>
37 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
39 namespace Foam
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
44 string pOpen(const string &cmd, label line=0)
46     const int MAX = 1000;
48     FILE *cmdPipe = popen(cmd.c_str(), "r");
50     if (cmdPipe)
51     {
52         // Read line number of lines
53         for (label cnt = 0; cnt <= line; cnt++)
54         {
55             char buffer[MAX];
56             char* s = fgets(buffer, MAX-1, cmdPipe);
58             if (s == NULL)
59             {
60                 return "";
61             }
63             if (cnt == line)
64             {
65                 string str(buffer);
66                 return str.substr(0, str.size()-1);
67             }
68         }
69         pclose(cmdPipe);
70     }
72     return "";
76 // use popen to call addr2line (using bfd.h directly would have
77 // meant relinking everything)
79 void printSourceFileAndLine
81     Ostream& os,
82     const HashTable<label, fileName>& addressMap,
83     const fileName& filename,
84     const word& address
87     word myAddress = address;
89     if (filename.ext() == "so")
90     {
91         // Convert offset into .so into offset into executable.
93         void *addr;
94         sscanf(myAddress.c_str(), "%p",&addr);
96         Dl_info info;
98         dladdr(addr, &info);
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();
110     }
112     if (filename[0] == '/')
113     {
114         string line = pOpen
115         (
116             "addr2line -f --demangle=auto --exe "
117           + filename
118           + " "
119           + myAddress,
120             1
121         );
123         if (line == "")
124         {
125             os  << " addr2line failed";
126         }
127         else if (line == "??:0")
128         {
129             os  << " in " << filename;
130         }
131         else
132         {
133             string cwdLine(line.replaceAll(cwd() + '/', ""));
134             string homeLine(cwdLine.replaceAll(home(), '~'));
136             os  << " at " << homeLine.c_str();
137         }
138     }
142 void getSymbolForRaw
144     Ostream& os,
145     const string& raw,
146     const fileName& filename,
147     const word& address
150     if (filename.size() && filename[0] == '/')
151     {
152         string fcnt = pOpen
153         (
154             "addr2line -f --demangle=auto --exe "
155           + filename
156           + " "
157           + address
158         );
160         if (fcnt != "")
161         {
162             os  << fcnt.c_str();
163             return;
164         }
165     }
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;
179     {
180         IFstream is("/proc/" + name(pid()) + "/maps");
182         while (is.good())
183         {
184             string line;
185             is.getLine(line);
187             string::size_type space = line.rfind(' ') + 1;
188             fileName libPath = line.substr(space, line.size()-space);
190             if (libPath.size() && libPath[0] == '/')
191             {
192                 string offsetString(line.substr(0, line.find('-')));
193                 IStringStream offsetStr(offsetString);
194                 addressMap.insert(libPath, readHexLabel(offsetStr));
195             }
196         }
197     }
199     // Get raw stack symbols
200     void *array[100];
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++)
207     {
208         string msg(strings[i]);
209         fileName programFile;
210         word address;
212         os  << '#' << label(i) << "  ";
213         //os  << "Raw   : " << msg << "\n\t";
214         {
215             string::size_type lPos = msg.find('[');
216             string::size_type rPos = msg.find(']');
218             if (lPos != string::npos && rPos != string::npos && lPos < rPos)
219             {
220                 address = msg.substr(lPos+1, rPos-lPos-1);
221                 msg = msg.substr(0, lPos);
222             }
224             string::size_type bracketPos = msg.find('(');
225             string::size_type spacePos = msg.find(' ');
226             if (bracketPos != string::npos || spacePos != string::npos)
227             {
228                 programFile = msg.substr(0, min(spacePos, bracketPos));
230                 // not an absolute path
231                 if (programFile[0] != '/')
232                 {
233                     string tmp = pOpen("which " + programFile);
234                     if (tmp[0] == '/' || tmp[0] == '~')
235                     {
236                         programFile = tmp;
237                     }
238                 }
239             }
240         }
242         string::size_type bracketPos = msg.find('(');
244         if (bracketPos != string::npos)
245         {
246             string::size_type start = bracketPos+1;
248             string::size_type plusPos = msg.find('+', start);
250             if (plusPos != string::npos)
251             {
252                 string cName(msg.substr(start, plusPos-start));
254                 int status;
255                 char* cplusNamePtr = abi::__cxa_demangle
256                 (
257                     cName.c_str(),
258                     NULL,                   // have it malloc itself
259                     0,
260                     &status
261                 );
263                 if (status == 0 && cplusNamePtr)
264                 {
265                     os  << cplusNamePtr;
266                     free(cplusNamePtr);
267                 }
268                 else
269                 {
270                     os  << cName.c_str();
271                 }
272             }
273             else
274             {
275                 string::size_type endBracketPos = msg.find(')', start);
277                 if (endBracketPos != string::npos)
278                 {
279                     string fullName(msg.substr(start, endBracketPos-start));
281                     os  << fullName.c_str() << nl;
282                 }
283                 else
284                 {
285                     // Print raw message
286                     getSymbolForRaw(os, msg, programFile, address);
287                 }
288             }
289         }
290         else
291         {
292             // Print raw message
293             getSymbolForRaw(os, msg, programFile, address);
294         }
296         printSourceFileAndLine(os, addressMap, programFile, address);
298         os  << nl;
299     }
301     free(strings);
305 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
307 } // End namespace Foam
309 // ************************************************************************* //