7 #include <fwCore/base.hpp> 12 #include "monitor/installSIGSEVBacktrace.hpp" 31 #if !defined(__APPLE__) || (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ - 1060) <= 0 34 #include <sys/ucontext.h> 46 #include <boost/lexical_cast.hpp> 57 char *p = (
char *)0xdeadbeef;
62 std::string demangle( std::string mangled )
64 char * c_demangled = abi::__cxa_demangle( mangled.c_str(), 0, 0, 0);
67 std::string res(c_demangled);
77 std::string decode(
char *message)
79 std::string msg(message);
80 std::string res(message);
82 std::string::size_type popen = msg.find(
'(');
83 if ( popen != std::string::npos )
85 std::string::size_type plus = msg.find(
'+');
86 res = std::string(message,popen+1) +
" ";
87 std::string mangled( message, popen+1, plus -popen -1 );
88 res += demangle(mangled) +
" ";
89 res += std::string( message + plus, message + strlen(message) );
94 void bt_sighandler(
int sig, siginfo_t *info,
99 char **messages = (
char **)NULL;
100 int i, trace_size = 0;
101 ucontext_t *uc = (ucontext_t *)secret;
103 std::stringstream ss;
104 ss <<
"Got signal " << sig;
109 ss <<
" faulty address is " << info->si_addr;
111 ss <<
" from " << uc->uc_mcontext.gregs[REG_EIP];
116 trace_size = backtrace(trace, 16);
119 trace[1] = (
void *) uc->uc_mcontext.gregs[REG_EIP];
122 messages = backtrace_symbols(trace, trace_size);
124 ss <<
" [bt] Execution path:" << std::endl;
125 for (i = 1; i<trace_size; ++i)
127 ss <<
" [bt] " << decode(messages[i]) << std::endl;
137 SLM_ERROR(
"SIGUSR1 signal " + ss.str() );
145 sa.sa_sigaction = bt_sighandler;
146 sigemptyset (&sa.sa_mask);
147 sa.sa_flags = SA_RESTART | SA_SIGINFO;
149 sigaction(SIGSEGV, &sa, NULL);
150 sigaction(SIGUSR1, &sa, NULL);
156 const size_t nbChar = 100;
157 #if _MSC_VER > 1499 // Visual C++ 2008 only 158 BOOL CALLBACK EnumerateLoadedModules(LPCSTR ModuleName, DWORD64 ModuleBase, ULONG ModuleSize, PVOID UserContext)
160 BOOL CALLBACK EnumerateLoadedModules(LPSTR ModuleName, DWORD64 ModuleBase, ULONG ModuleSize, PVOID UserContext)
163 std::list<std::string>* pLoadedModules =
reinterpret_cast<std::list<std::string>*
>(UserContext);
164 pLoadedModules->push_back(std::string((
char *)ModuleName) +
"\t" + ::boost::lexical_cast<std::string>(ModuleBase));
171 void printDump(std::list<std::string> &loadedModules, std::list<std::string> &callStack,
172 std::list<std::string> &fileStack)
174 std::stringstream stream;
177 stream <<
"-----------------------------------------" << std::endl;
178 stream <<
"\nLoaded Modules\n";
179 for(std::list<std::string>::const_iterator it = loadedModules.begin(); it != loadedModules.end(); ++it)
181 stream <<
"> " << *it << std::endl;
183 stream <<
"-----------------------------------------" << std::endl;
185 stream <<
"\nCallStack\n";
186 for(std::list<std::string>::const_iterator it = callStack.begin(), it2 = fileStack.begin();
187 it != callStack.end() && it2 != fileStack.end(); ++it, ++it2)
189 stream <<
"> " << *it << std::endl;
190 stream <<
" " << *it2 << std::endl;
192 stream <<
"-----------------------------------------" << std::endl;
201 void LoadCallStack(EXCEPTION_POINTERS* exceptionInfos, HANDLE &hProcess, std::list<std::string> &callStack,
202 std::list<std::string> &fileStack)
204 STACKFRAME64 tempStackFrame;
205 CONTEXT context = *(exceptionInfos->ContextRecord);
206 memset( &tempStackFrame, 0,
sizeof(STACKFRAME64) );
210 machineType = IMAGE_FILE_MACHINE_I386;
211 tempStackFrame.AddrPC.Offset = context.Eip;
212 tempStackFrame.AddrPC.Mode = AddrModeFlat;
213 tempStackFrame.AddrStack.Offset = context.Esp;
214 tempStackFrame.AddrStack.Mode = AddrModeFlat;
215 tempStackFrame.AddrFrame.Offset = context.Ebp;
216 tempStackFrame.AddrFrame.Mode = AddrModeFlat;
218 machineType = IMAGE_FILE_MACHINE_AMD64;
219 tempStackFrame.AddrPC.Offset = context.Rip;
220 tempStackFrame.AddrPC.Mode = AddrModeFlat;
221 tempStackFrame.AddrFrame.Offset = context.Rsp;
222 tempStackFrame.AddrFrame.Mode = AddrModeFlat;
223 tempStackFrame.AddrStack.Offset = context.Rsp;
224 tempStackFrame.AddrStack.Mode = AddrModeFlat;
226 machineType = IMAGE_FILE_MACHINE_IA64;
227 tempStackFrame.AddrPC.Offset = context.StIIP;
228 tempStackFrame.AddrPC.Mode = AddrModeFlat;
229 tempStackFrame.AddrFrame.Offset = context.IntSp;
230 tempStackFrame.AddrFrame.Mode = AddrModeFlat;
231 tempStackFrame.AddrBStore.Offset = context.RsBSP;
232 tempStackFrame.AddrBStore.Mode = AddrModeFlat;
233 tempStackFrame.AddrStack.Offset = context.IntSp;
234 tempStackFrame.AddrStack.Mode = AddrModeFlat;
236 #error "Platform not supported!" 239 ULONG64 buffer[(
sizeof(SYMBOL_INFO) + nbChar*
sizeof(TCHAR) +
sizeof(ULONG64) + 1) /
sizeof(ULONG64)];
240 PSYMBOL_INFO pSymbol =
reinterpret_cast<PSYMBOL_INFO
>(buffer);
241 PSTR undecoratedName = (PSTR)malloc(
sizeof(TCHAR) * nbChar);
243 pSymbol->SizeOfStruct =
sizeof(SYMBOL_INFO);
244 pSymbol->MaxNameLen = nbChar;
245 DWORD lineDisplacement;
246 IMAGEHLP_LINE64 lineInfo = {
sizeof(IMAGEHLP_LINE64) };
248 while(StackWalk64(machineType, hProcess, GetCurrentThread(), &tempStackFrame, &context, NULL,
249 SymFunctionTableAccess64, SymGetModuleBase64, NULL))
252 if(tempStackFrame.AddrPC.Offset == 0)
257 DWORD64 symDisplacement = 0;
259 if(SymFromAddr(hProcess, tempStackFrame.AddrPC.Offset, &symDisplacement, pSymbol))
261 UnDecorateSymbolName(pSymbol->Name, undecoratedName, MAX_SYM_NAME, UNDNAME_COMPLETE);
262 callStack.push_back(std::string((
char*)undecoratedName) +
"+" +
263 ::boost::lexical_cast<std::string>(symDisplacement));
265 if(SymGetLineFromAddr64(hProcess, tempStackFrame.AddrPC.Offset, &lineDisplacement, &lineInfo))
267 fileStack.push_back(std::string(lineInfo.FileName) +
"\tl:" +
268 ::boost::lexical_cast<std::string>(lineInfo.LineNumber));
272 fileStack.push_back(
"No info");
279 free(undecoratedName);
283 static LONG WINAPI UnhandledExpFilter(PEXCEPTION_POINTERS pExceptionInfo)
288 std::list<std::string> loadedModules;
290 std::list<std::string> callStack;
292 std::list<std::string> fileStack;
294 SymSetOptions(SYMOPT_UNDNAME|SYMOPT_DEFERRED_LOADS|SYMOPT_LOAD_LINES);
295 hProcess = GetCurrentProcess();
297 if(SymInitialize(hProcess, NULL, TRUE))
299 LoadCallStack(pExceptionInfo, hProcess, callStack, fileStack);
300 ::EnumerateLoadedModules64(hProcess, EnumerateLoadedModules, &loadedModules);
301 ::SymCleanup(hProcess);
304 printDump(loadedModules, callStack, fileStack);
306 return EXCEPTION_CONTINUE_SEARCH;
311 SetUnhandledExceptionFilter(UnhandledExpFilter);
MONITOR_API void installSIGSEVBacktrace()
Function installing a callback which print the backtrace on a SIGSEV and SIGUSR1 signal for posix onl...
#define SLM_ERROR(message)
#define SLM_FATAL(message)
The namespace monitor contains tools for monitoring an application built with FW4SPL.
MONITOR_API void generateSIGSEV()
Generates segmentation fault for test.