Exception message format
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)