Exception message format

From OC Systems Wiki!
Jump to: navigation, search

You can create a probe to register a callback with Aprobe to be called for each exception thrown/raised in an application. Use this interface found in aprobe.h:

/* The kinds of exceptions supported by Aprobe. */
typedef enum
{
   ap_NoException,
   ap_CppException,
   ap_WinNTVCppException,
   ap_GnatAdaException,
   ap_WinNTSEHException,
   ap_AixCppException,
   ap_Pa4AdaException
} ap_ExceptionKindT;

/* This is the information concerning an exception. */
/* The ExceptionData and Flags fields are internal to Aprobe. */
typedef struct
{
   ap_ExceptionKindT  Kind;
   ap_NameT           ExceptionName;
   void              *ExceptionData;
   int                Flags;
} ap_ExceptionT;


/* When an exception is raised, a handler can be called to log and / or */
/* print the exception. The following is the definition of the handler */
/* (note that Location is the location for the routine which raised the */
/* exception): */
typedef void ap_ExceptionHandlerProcT (ap_ExceptionT *Exception,
                                       ap_LocationT   Location);

/* Register the routine to be called when an exception occurs */
extern void ap_RegisterExceptionHandler (ap_ThreadContextPtrT    ThreadContext,
                                         ap_ExceptionHandlerProcT Handler);

The exception handler is passed the current exception and the location at which the exception was thrown/raised. The ExceptionName is the Ada exception name or the name of the C++ object thrown. The ExceptionData is generally the exception object or occurrence, but that is not guaranteed.

You can get the message associated with the Ada or C++ exception using:

/* Get the exception message (if any) for the given exception. The returned */
/* string must be freed by the caller. ap_NoName will be returned if there */
/* is no message for the exception. Note that it is expected that you call */
/* this within the exception handler procedure or immediately after calling */
/* ap_CurrentException. Any other usage has undefined behavior. */
extern ap_NameT ap_GetExceptionMessage (ap_ExceptionT *Exception);

Note that you can use exceptions.ual to log exception occurrences. This UAL will record the exception kind, name, message, and traceback.

Example

Putting it all together in some examples, this probe:

void HandlerRoutine (ap_ExceptionT *Exception,
                     ap_LocationT   Location)
{
   int   FmtLen = ap_FormatAddressSize(Location.CurrentAddress);
   char *Buffer = (char *)alloca(FmtLen);
   ap_FormatAddress(Buffer, Location.CurrentAddress);

   printf("Exception kind: %d\nException name: %s\nException  msg: %s\nException  loc: %s\n",
          Exception->Kind,
          Exception->ExceptionName,
          ap_GetExceptionMessage(Exception),
          Buffer);
}
   
probe thread
{
   on_entry
   {
      ap_RegisterExceptionHandler(ap_ThreadContextPtr, &HandlerRoutine);
   }
}

Produces this output for a C++ exception derived from std::exception using G++:

Exception kind: 1
Exception name: typeinfo for ooops
Exception  msg: Ooops!
Exception  loc: extern:"::work(void)" at line 17 (throwexc.cpp)

And this output for a C++ exception derived from std::exception using xlC:

Exception kind: 5
Exception name: 5ooops:0,Q2_3std9exception:0
Exception  msg: Ooops!
Exception  loc: extern:"::work(void)" at line 17 (throwexc.cpp)

And this output for an Ada Exception_Ocurrence using Gnat:

Exception kind: 3
Exception name: CONSTRAINT_ERROR
Exception  msg: t.adb:8 range check failed
Exception  loc: "t.adb":"t.q[4031]" at line 8 (t.adb)

And this for an Ada Exception using PowerAda:

Exception kind: 6
Exception name: CONSTRAINT_ERROR
Exception  msg: Value vs. Range Constraint (LRM 5.2:11)
Exception  loc: extern:"t.t.q[1b]" at line 8 (sec.t)