[commit/Ada] Special handling for predefined exceptions...

Joel Brobecker
2008-09-30T20:53:14Z

[-- Attachment #1: Type: text/plain, Size: 2335 bytes --]

Hello,

For Ada, we provide a command "catch exception [EXCEPTION_NAME]"
that stops the execution when an exception is raised. If an exception
name is specified in the command, then the debugger only stops when
a specific exception is raised. The matching of the exception is
performed through an internal condition that looks like this:

long_integer (e) = long_integer (&EXCEPTION_NAME)"

(where "e" is a parameter of the function where we inserted the
catchpoint that contains a pointer to the exception data). The way
it works is: For every EXCEPTION_NAME, the compiler defines an entity
whose name is EXCEPTION_NAME (fully qualified). So when we want to
verify whether we have raised a given exception, we just verify that
its address is the address of the symbol whose name is EXCEPTION_NAME.

Ada defines some standard exception names such as Constraint_Error
(used when using a value that's out of bounds, for instance),
Program_Error, Tasking_Error, etc. With GNAT, these exceptions are
defined inside runtime units which are not compiled with debugging info.

The situation that we ran into was a situation where the user defined
several enumerates whose name was Constraint_Error (there were several
enumeration types involved). As a result, the evaluation of the
condition above ends up finding the enumerates which had no relevance
whatsoever for our condition.

We dealt with the situation by taking a compromise: We believe that
this type of situation is not very common. In all my years at AdaCore,
we have only had one report of such issue. So what we did was make
the pre-defined exception names a little special, and assume that
"constraint_error" in the catch exception command means the pre-defined
exception. If the user ever happened to define his own exception
with a name identical to one of the pre-defined exception (which should
be very rare), and wants to break on his exception, then he'll have
to use the fully-qualified name of his exception.

2008-09-30 Joel Brobecker <brobecker@adacore.com>

* ada-lang.c (standard_exc): New static constant.
(ada_exception_catchpoint_cond_string): Add special handling
for the predefined exceptions.

Tested on x86-linux. Checked in.

I will see if I can add a note in our documentation about this
(as a separate patch).

--
Joel

[-- Attachment #2: std-exc.diff --]
[-- Type: text/plain, Size: 2248 bytes --]

Index: ada-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/ada-lang.c,v
retrieving revision 1.173
retrieving revision 1.174
diff -u -p -r1.173 -r1.174
--- ada-lang.c 30 Sep 2008 20:14:13 -0000 1.173
+++ ada-lang.c 30 Sep 2008 20:42:21 -0000 1.174
@@ -9650,6 +9650,15 @@ enum exception_catchpoint_kind
ex_catch_assert
};

+/* Ada's standard exceptions. */
+
+static char *standard_exc[] = {
+ "constraint_error",
+ "program_error",
+ "storage_error",
+ "tasking_error"
+};
+
typedef CORE_ADDR (ada_unhandled_exception_name_addr_ftype) (void);

/* A structure that describes how to support exception catchpoints
@@ -10334,6 +10343,35 @@ ada_exception_breakpoint_ops (enum excep
static char *
ada_exception_catchpoint_cond_string (const char *exp_string)
{
+ int i;
+
+ /* The standard exceptions are a special case. They are defined in
+ runtime units that have been compiled without debugging info; if
+ EXP_STRING is the not-fully-qualified name of a standard
+ exception (e.g. "constraint_error") then, during the evaluation
+ of the condition expression, the symbol lookup on this name would
+ *not* return this standard exception. The catchpoint condition
+ may then be set only on user-defined exceptions which have the
+ same not-fully-qualified name (e.g. my_package.constraint_error).
+
+ To avoid this unexcepted behavior, these standard exceptions are
+ systematically prefixed by "standard". This means that "catch
+ exception constraint_error" is rewritten into "catch exception
+ standard.constraint_error".
+
+ If an exception named contraint_error is defined in another package of
+ the inferior program, then the only way to specify this exception as a
+ breakpoint condition is to use its fully-qualified named:
+ e.g. my_package.constraint_error. */
+
+ for (i = 0; i < sizeof (standard_exc) / sizeof (char *); i++)
+ {
+ if (strcmp (standard_exc [i], exp_string) == 0)
+ {
+ return xstrprintf ("long_integer (e) = long_integer (&standard.%s)",
+ exp_string);
+ }
+ }
return xstrprintf ("long_integer (e) = long_integer (&%s)", exp_string);
}