Difference between revisions of "Throw/Raise Exception From Probes"

From OC Systems Wiki!
Jump to: navigation, search
m (C/C++ Example)
m
 
Line 53: Line 53:
 
==C/C++ Example==
 
==C/C++ Example==
  
Throwing C++ exceptions is more complicated.  This example demonstrates some prototype macros to make the process simpler.
+
Throwing C++ exceptions is more complicated.  The file <code>aprobe.h</code> defines some macros to make the process easier:  <code>ap_ThrowwGccObject()</code> and <code>ap_ThrowGccString()</code>.  If the macros fail, you will have to extract the proper information yourself and call <code>ap_ThrowGccException()</code> directly.
Eventually, these macros may be migrated to <code>aprobe.h</code> as they prove their worth.  If the macros fail, you will have to extract the proper information yourself and call <code>ap_ThrowGccException()</code> directly.
 
  
 
  <source lang=c>
 
  <source lang=c>
// This macro can be used to throw a C++ exception. 
 
 
//
 
//
// You must provide the exception name, the exception object, and a module id. 
+
// The example probe which uses the helper macros.
//
 
// The macro will generate code to lookup the exception typeinfo and a constructor and destructor. 
 
// This is based on C++ mangled symbols and Aprobe demangled symbols and works for simple examples.
 
// If your exception is defined in your application module, pass <code>ap_ApplicationModuleId()</code>
 
// as the module parameter.  If your exception is defined in a shared library, you must provide
 
// the module id (ap_ModuleIdT) using <code>ap_ModuleNameToId()</code>.
 
//
 
#define THROW(exname, exobj, modid) \
 
{ \
 
  int len = ap_Strlen(exname); \
 
  ap_SymbolIdT tiSym; \
 
  ap_SymbolIdT ctorSym; \
 
  ap_SymbolIdT dtorSym; \
 
  char *tiptr = alloca(len + 5); \
 
  char *ctorptr = alloca(len * 2 + 5); \
 
  char *dtorptr = alloca(len * 2 + 5); \
 
\
 
  sprintf(tiptr, "_ZTI%d%s", len, exname); \
 
  sprintf(ctorptr, "%s::%s", exname, exname); \
 
  sprintf(dtorptr, "%s::~%s", exname, exname); \
 
\
 
  tiSym = \
 
        ap_SymbolNameToId( \
 
            modid, \
 
            tiptr, \
 
            ap_ExternSymbol, \
 
            ap_DataSymbol); \
 
  ctorSym = \
 
        ap_SymbolNameToId( \
 
            modid, \
 
            ctorptr, \
 
            ap_ExternSymbol, \
 
            ap_FunctionSymbol); \
 
  dtorSym = \
 
        ap_SymbolNameToId( \
 
            modid, \
 
            dtorptr, \
 
            ap_ExternSymbol, \
 
            ap_FunctionSymbol); \
 
\
 
  ap_ThrowCppException(exobj, sizeof(exobj), ap_SymbolAddress(tiSym), ap_SymbolAddress(ctorSym), ap_SymbolAddress(dtorSym)); \
 
}
 
 
 
// This macro can be used to throw a simple string object. 
 
// Just provide a string literal or a target-expression for the string object.
 
//
 
#define THROW_STRING(exobj) \
 
{ \
 
  ap_SymbolIdT tiSym = \
 
        ap_SymbolNameToId( \
 
            ap_ModuleNameToId("libstdc++.so"), \
 
            "_ZTIPKc", \
 
            ap_ExternSymbol, \
 
            ap_DataSymbol); \
 
  ap_ThrowCppException(exobj, sizeof(exobj), ap_SymbolAddress(tiSym), NULL, NULL); \
 
}
 
 
 
//
 
// The example probe which uses the above macros.
 
 
//
 
//
 
probe thread
 
probe thread
Line 133: Line 72:
 
             // throw E;
 
             // throw E;
 
             // E is the exception class and $e1 is the exception object declared in the application.
 
             // E is the exception class and $e1 is the exception object declared in the application.
             THROW("E", $e1, ap_ApplicationModuleId());
+
             ap_ThrowGccObject("E", $e1, ap_ApplicationModuleId());
 
         }
 
         }
 
         else if (count == 2)
 
         else if (count == 2)
Line 139: Line 78:
 
             // throw myexception;
 
             // throw myexception;
 
             // my exception is the exception class and $e2 is the exception object declared in the application.
 
             // my exception is the exception class and $e2 is the exception object declared in the application.
             THROW("myexception", $e2, ap_ApplicationModuleId());
+
             ap_ThrowGccObject("myexception", $e2, ap_ApplicationModuleId());
 
         }
 
         }
 
         else
 
         else
Line 145: Line 84:
 
             // throw "Exception";
 
             // throw "Exception";
 
             // throw a local string object.
 
             // throw a local string object.
             THROW_STRING("Exception");
+
             ap_ThrowGccString("Exception");
 
         }
 
         }
 
       }
 
       }

Latest revision as of 21:20, 10 September 2019

You can raise and Ada exception or throw a C++ exception from a probe.

In Ada you will need to know the name of the exception you want to raise. This can be as simple as constraint_error or a more complex fully-qualified name pkg.child.my_exception.

In C++ you will have to provide: the exception object (usually referenced in the application program using a target expression, for example $MyExceptionObject), the exception typeinfo, a constructor, and a destructor. Below are some prototype macros which make this a little bit easier.

If you raise/throw and exception in an on_entry action of a probe, the function call will be stubbed and the exception will be raised/thrown when the probed function exits.

If you raise/throw and exception in an on_line/offset action of a probe, the exception will be raised/thrown at that point.

If you raise/throw and exception in an on_exit action of a probe, the exception will be raised/thrown when the function returns.


Ada Example

The Ada example demonstrates how to raise an Ada exception from a probe on_entry/on_line/on_exit action. Note that #ifdef's are used to condition the Aprobe macro used to raise the exception depending on the target compiler (PowerAda or Gnat).

#ifdef _AIX
#define RAISE ap_RaisePowerAdaException
#else
#define RAISE ap_RaiseGnatException
#endif

probe thread
{
   probe "tmain.x1" 
   {
      on_entry 
      {
         RAISE("constraint_error");
      }
   }

   probe "tmain.x2" 
   {
      on_exit 
      {
         RAISE("ada.io_exceptions.status_error");
      }
   }

   probe "tmain.x3" 
   {
      on_line(27) 
      {
         RAISE("my_exception");
      }
   }
}

C/C++ Example

Throwing C++ exceptions is more complicated. The file aprobe.h defines some macros to make the process easier: ap_ThrowwGccObject() and ap_ThrowGccString(). If the macros fail, you will have to extract the proper information yourself and call ap_ThrowGccException() directly.

//
// The example probe which uses the helper macros.
//
probe thread
{
   int count = 0;

   probe "service(int, int)"
   {
      on_entry
      {
         count++;
         if (count == 1)
         {
            // throw E;
            // E is the exception class and $e1 is the exception object declared in the application.
            ap_ThrowGccObject("E", $e1, ap_ApplicationModuleId());
         }
         else if (count == 2)
         {
            // throw myexception;
            // my exception is the exception class and $e2 is the exception object declared in the application.
            ap_ThrowGccObject("myexception", $e2, ap_ApplicationModuleId());
         }
         else
         {
            // throw "Exception";
            // throw a local string object.
            ap_ThrowGccString("Exception");
         }
      }
   }
}