Line data Source code
1 : #include "wibmod/WIB1/BUException/ExceptionBase.hh"
2 :
3 : // Error string for stack string allocation error
4 : static const char stackError[] = "Stack allocation failed.\n";
5 :
6 : const char*
7 0 : BUException::exBase::StackTrace() const throw()
8 : {
9 0 : if (stackBuffer == NULL)
10 0 : return stackError;
11 : return stackBuffer;
12 : }
13 :
14 : void
15 0 : BUException::exBase::AppendStackLine(const char* line) throw()
16 : {
17 : // Check for NULL line
18 0 : if (line == NULL)
19 : return;
20 :
21 : // get raw line size
22 0 : size_t lineSize = strlen(line);
23 0 : if (lineSize >= (stackSize - stackUsed))
24 : lineSize = stackSize - stackUsed;
25 : // copy string
26 0 : strncpy(stackBuffer + stackUsed, line, lineSize);
27 : // update size
28 0 : stackUsed += lineSize;
29 : // Add eol
30 0 : if ((stackSize - stackUsed) > 1) {
31 0 : stackBuffer[stackUsed] = '\n';
32 0 : stackUsed++;
33 : }
34 : // add null terminator (there is always room for one(unless NULL))
35 0 : if (stackBuffer != NULL) {
36 0 : stackBuffer[stackUsed] = '\0';
37 : }
38 : }
39 :
40 : void
41 0 : BUException::exBase::GenerateStackTrace() throw()
42 : {
43 : // Get the thread/process ID for this stack trace
44 0 : PID = syscall(SYS_gettid);
45 :
46 : // Get the stack trace (void *s)
47 0 : const size_t maxStackSize = 20;
48 0 : void* functionStack[maxStackSize];
49 0 : 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 0 : stackSize = backtrace(functionStack, maxStackSize);
54 :
55 : // Get the stack trace strings (we have to free this)
56 0 : char** functionNames = backtrace_symbols(functionStack, stackSize);
57 0 : if (functionNames == NULL) {
58 0 : fprintf(stderr, "Error in exBase::GenerateStackTrace(). backtrace_symbols failed\n");
59 0 : return;
60 : }
61 :
62 : char* demangledName = NULL;
63 : // Start stack trace from 3 to skip the exception class's functions
64 0 : 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 0 : if (functionNames[iFunction] == NULL) {
68 0 : AppendStackLine("Unknown");
69 0 : continue;
70 : }
71 :
72 0 : char* mangledStart = NULL;
73 0 : char* offsetStart = NULL;
74 0 : char* offsetEnd = NULL;
75 :
76 : // Find mangled and offset start/ends
77 0 : char* bufferEnd = functionNames[iFunction] + strlen(functionNames[iFunction]);
78 0 : for (char* buffer = functionNames[iFunction]; buffer != bufferEnd; buffer++) {
79 : // Look for function's opening '('
80 0 : if (*buffer == '(')
81 : mangledStart = buffer;
82 : // Look for offset in function
83 0 : else if (*buffer == '+')
84 : offsetStart = buffer;
85 : // Look for closing ')', but only if we've found an opening one
86 0 : else if ((*buffer == ')') && (offsetStart != NULL)) {
87 : offsetEnd = buffer;
88 : break;
89 : }
90 : }
91 :
92 : // if the parsing makes sense
93 0 : if ((mangledStart != NULL) && (offsetStart != NULL) && (offsetEnd != NULL) && (mangledStart < offsetStart)) {
94 : // Make manglesStart point to the beginning of the name
95 0 : mangledStart++;
96 : // put in a null terminator at offsetStart to end the mangled name
97 0 : *offsetStart = '\0';
98 :
99 : // Make offset start point to the beginning of the offset
100 0 : offsetStart++;
101 : // put a null terminator at the end of the offset
102 0 : *offsetEnd = '\0';
103 :
104 : // demangle
105 0 : size_t demangledSize = 0;
106 0 : int demangledRet = 0;
107 0 : char* retName = abi::__cxa_demangle(mangledStart, demangledName, &demangledSize, &demangledRet);
108 : // Append demangled line
109 0 : if ((demangledRet == 0) && (retName != NULL)) {
110 : // copy possibly reallocated c-string
111 0 : demangledName = retName;
112 0 : AppendStackLine(demangledName);
113 : } else // if ther was an error, append the mangled name
114 : {
115 0 : AppendStackLine(mangledStart);
116 : }
117 0 : } else // Bad parse, just print the line
118 : {
119 0 : AppendStackLine(functionNames[iFunction]);
120 : }
121 : }
122 :
123 0 : if (demangledName != NULL)
124 0 : free(demangledName);
125 0 : free(functionNames);
126 : }
|