DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
ExceptionBase_stacktrace.cpp
Go to the documentation of this file.
2
3//Error string for stack string allocation error
4static const char stackError[] = "Stack allocation failed.\n";
5
6const char * BUException::exBase::StackTrace() const throw()
7{
8 if(stackBuffer == NULL)
9 return stackError;
10 return stackBuffer;
11}
12
13void BUException::exBase::AppendStackLine(const char * line) throw()
14{
15 //Check for NULL line
16 if(line == NULL)
17 return;
18
19 //get raw line size
20 size_t lineSize = strlen(line);
21 if(lineSize >= (stackSize - stackUsed))
22 lineSize = stackSize - stackUsed;
23 //copy string
24 strncpy(stackBuffer+stackUsed,line,lineSize);
25 //update size
26 stackUsed += lineSize;
27 //Add eol
28 if((stackSize - stackUsed) > 1)
29 {
30 stackBuffer[stackUsed] = '\n';
31 stackUsed++;
32 }
33 //add null terminator (there is always room for one(unless NULL))
34 if(stackBuffer != NULL)
35 {
36 stackBuffer[stackUsed] = '\0';
37 }
38}
39
41{
42 //Get the thread/process ID for this stack trace
43 PID = syscall(SYS_gettid);
44
45 //Get the stack trace (void *s)
46 const size_t maxStackSize = 20;
47 void * functionStack[maxStackSize];
48 size_t stackSize;
49
50 //Fill functionStack with void * pointers to return address of the corresponding stack frame
51 //filed up to maxStackSize with most recent calls
52 stackSize = backtrace(functionStack,maxStackSize);
53
54 //Get the stack trace strings (we have to free this)
55 char ** functionNames = backtrace_symbols(functionStack,stackSize);
56 if(functionNames == NULL)
57 {
58 fprintf(stderr,"Error in exBase::GenerateStackTrace(). backtrace_symbols failed\n");
59 return;
60 }
61
62 char * demangledName = NULL;
63 //Start stack trace from 3 to skip the exception class's functions
64 for(size_t iFunction = 3; iFunction < stackSize; iFunction++)
65 {
66 //based off of http://panthema.net/2008/0901-stacktrace-demangled/
67 //Be paranoid about these pointers and make sure they are valid
68 if(functionNames[iFunction] == NULL)
69 {
70 AppendStackLine("Unknown");
71 continue;
72 }
73
74 char * mangledStart = NULL;
75 char * offsetStart = NULL;
76 char * offsetEnd = NULL;
77
78 //Find mangled and offset start/ends
79 char * bufferEnd = functionNames[iFunction] + strlen(functionNames[iFunction]);
80 for(char * buffer = functionNames[iFunction];buffer != bufferEnd;buffer++)
81 {
82 //Look for function's opening '('
83 if(*buffer == '(')
84 mangledStart = buffer;
85 //Look for offset in function
86 else if(*buffer == '+')
87 offsetStart = buffer;
88 //Look for closing ')', but only if we've found an opening one
89 else if( (*buffer == ')') && (offsetStart != NULL))
90 {
91 offsetEnd = buffer;
92 break;
93 }
94 }
95
96 //if the parsing makes sense
97 if( (mangledStart != NULL) &&
98 (offsetStart != NULL) &&
99 (offsetEnd != NULL) &&
100 (mangledStart < offsetStart)
101 )
102 {
103 //Make manglesStart point to the beginning of the name
104 mangledStart++;
105 //put in a null terminator at offsetStart to end the mangled name
106 *offsetStart = '\0';
107
108 //Make offset start point to the beginning of the offset
109 offsetStart++;
110 //put a null terminator at the end of the offset
111 *offsetEnd = '\0';
112
113 //demangle
114 size_t demangledSize = 0;
115 int demangledRet = 0;
116 char * retName = abi::__cxa_demangle(mangledStart,
117 demangledName,
118 &demangledSize,
119 &demangledRet);
120 //Append demangled line
121 if((demangledRet == 0) && (retName != NULL))
122 {
123 //copy possibly reallocated c-string
124 demangledName = retName;
125 AppendStackLine(demangledName);
126 }
127 else //if ther was an error, append the mangled name
128 {
129 AppendStackLine(mangledStart);
130 }
131 }
132 else //Bad parse, just print the line
133 {
134 AppendStackLine(functionNames[iFunction]);
135 }
136 }
137
138 if(demangledName != NULL)
139 free(demangledName);
140 free(functionNames);
141
142}
static const char stackError[]
void AppendStackLine(const char *line)
const char * StackTrace() const