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