LCOV - code coverage report
Current view: top level - wibmod/src/WIB1/BUException - ExceptionBase_stacktrace.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 56 0
Test Date: 2025-12-21 13:07:08 Functions: 0.0 % 3 0

            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              : }
        

Generated by: LCOV version 2.0-1