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