/* Ada language support routines for GDB, the GNU debugger.
- Copyright (C) 1992-2013 Free Software Foundation, Inc.
+ Copyright (C) 1992-2014 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include <stdio.h>
-#include "gdb_string.h"
+#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include "demangle.h"
#include "expression.h"
#include "parser-defs.h"
#include "language.h"
+#include "varobj.h"
#include "c-lang.h"
#include "inferior.h"
#include "symfile.h"
#include "gdb_obstack.h"
#include "ada-lang.h"
#include "completer.h"
-#include "gdb_stat.h"
+#include <sys/stat.h>
#ifdef UI_OUT
#include "ui-out.h"
#endif
set_value_bitsize (result, value_bitsize (val));
set_value_bitpos (result, value_bitpos (val));
set_value_address (result, value_address (val));
- set_value_optimized_out (result, value_optimized_out (val));
+ set_value_optimized_out (result, value_optimized_out_const (val));
return result;
}
}
by run-time quantities other than discriminants. */
static LONGEST
-ada_array_bound_from_type (struct type * arr_type, int n, int which)
+ada_array_bound_from_type (struct type *arr_type, int n, int which)
{
- struct type *type, *elt_type, *index_type_desc, *index_type;
+ struct type *type, *index_type_desc, *index_type;
int i;
gdb_assert (which == 0 || which == 1);
else
type = arr_type;
- elt_type = type;
- for (i = n; i > 1; i--)
- elt_type = TYPE_TARGET_TYPE (type);
-
index_type_desc = ada_find_parallel_type (type, "___XA");
ada_fixup_array_indexes_type (index_type_desc);
if (index_type_desc != NULL)
index_type = to_fixed_range_type (TYPE_FIELD_TYPE (index_type_desc, n - 1),
NULL);
else
- index_type = TYPE_INDEX_TYPE (elt_type);
+ {
+ struct type *elt_type = check_typedef (type);
+
+ for (i = 1; i < n; i++)
+ elt_type = check_typedef (TYPE_TARGET_TYPE (elt_type));
+
+ index_type = TYPE_INDEX_TYPE (elt_type);
+ }
return
(LONGEST) (which == 0
return (struct ada_symbol_info *) obstack_base (obstackp);
}
-/* Return a minimal symbol matching NAME according to Ada decoding
- rules. Returns NULL if there is no such minimal symbol. Names
- prefixed with "standard__" are handled specially: "standard__" is
- first stripped off, and only static and global symbols are searched. */
+/* Return a bound minimal symbol matching NAME according to Ada
+ decoding rules. Returns an invalid symbol if there is no such
+ minimal symbol. Names prefixed with "standard__" are handled
+ specially: "standard__" is first stripped off, and only static and
+ global symbols are searched. */
-struct minimal_symbol *
+struct bound_minimal_symbol
ada_lookup_simple_minsym (const char *name)
{
+ struct bound_minimal_symbol result;
struct objfile *objfile;
struct minimal_symbol *msymbol;
const int wild_match_p = should_use_wild_match (name);
+ memset (&result, 0, sizeof (result));
+
/* Special case: If the user specifies a symbol name inside package
Standard, do a non-wild matching of the symbol name without
the "standard__" prefix. This was primarily introduced in order
{
if (match_name (SYMBOL_LINKAGE_NAME (msymbol), name, wild_match_p)
&& MSYMBOL_TYPE (msymbol) != mst_solib_trampoline)
- return msymbol;
+ {
+ result.minsym = msymbol;
+ result.objfile = objfile;
+ break;
+ }
}
- return NULL;
+ return result;
}
/* For all subprograms that statically enclose the subprogram of the
old_renaming_is_invisible (const struct symbol *sym, const char *function_name)
{
char *scope;
+ struct cleanup *old_chain;
if (SYMBOL_CLASS (sym) != LOC_TYPEDEF)
return 0;
scope = xget_renaming_scope (SYMBOL_TYPE (sym));
-
- make_cleanup (xfree, scope);
+ old_chain = make_cleanup (xfree, scope);
/* If the rename has been defined in a package, then it is visible. */
if (is_package_name (scope))
- return 0;
+ {
+ do_cleanups (old_chain);
+ return 0;
+ }
/* Check that the rename is in the current function scope by checking
that its name starts with SCOPE. */
if (strncmp (function_name, "_ada_", 5) == 0)
function_name += 5;
- return (strncmp (function_name, scope, strlen (scope)) != 0);
+ {
+ int is_invisible = strncmp (function_name, scope, strlen (scope)) != 0;
+
+ do_cleanups (old_chain);
+ return is_invisible;
+ }
}
/* Remove entries from SYMS that corresponds to a renaming entity that
return 0;
}
-/* Compare STRING1 to STRING2, with results as for strcmp.
- Compatible with strcmp_iw in that strcmp_iw (STRING1, STRING2) <= 0
- implies compare_names (STRING1, STRING2) (they may differ as to
- what symbols compare equal). */
+/* Implements compare_names, but only applying the comparision using
+ the given CASING. */
static int
-compare_names (const char *string1, const char *string2)
+compare_names_with_case (const char *string1, const char *string2,
+ enum case_sensitivity casing)
{
while (*string1 != '\0' && *string2 != '\0')
{
+ char c1, c2;
+
if (isspace (*string1) || isspace (*string2))
return strcmp_iw_ordered (string1, string2);
- if (*string1 != *string2)
+
+ if (casing == case_sensitive_off)
+ {
+ c1 = tolower (*string1);
+ c2 = tolower (*string2);
+ }
+ else
+ {
+ c1 = *string1;
+ c2 = *string2;
+ }
+ if (c1 != c2)
break;
+
string1 += 1;
string2 += 1;
}
+
switch (*string1)
{
case '(':
if (*string2 == '(')
return strcmp_iw_ordered (string1, string2);
else
- return *string1 - *string2;
+ {
+ if (casing == case_sensitive_off)
+ return tolower (*string1) - tolower (*string2);
+ else
+ return *string1 - *string2;
+ }
}
}
+/* Compare STRING1 to STRING2, with results as for strcmp.
+ Compatible with strcmp_iw_ordered in that...
+
+ strcmp_iw_ordered (STRING1, STRING2) <= 0
+
+ ... implies...
+
+ compare_names (STRING1, STRING2) <= 0
+
+ (they may differ as to what symbols compare equal). */
+
+static int
+compare_names (const char *string1, const char *string2)
+{
+ int result;
+
+ /* Similar to what strcmp_iw_ordered does, we need to perform
+ a case-insensitive comparison first, and only resort to
+ a second, case-sensitive, comparison if the first one was
+ not sufficient to differentiate the two strings. */
+
+ result = compare_names_with_case (string1, string2, case_sensitive_off);
+ if (result == 0)
+ result = compare_names_with_case (string1, string2, case_sensitive_on);
+
+ return result;
+}
+
/* Add to OBSTACKP all non-local symbols whose name and domain match
NAME and DOMAIN respectively. The search is performed on GLOBAL_BLOCK
symbols if GLOBAL is non-zero, or on STATIC_BLOCK symbols otherwise. */
data.objfile = objfile;
if (is_wild_match)
- objfile->sf->qf->map_matching_symbols (name, domain, objfile, global,
+ objfile->sf->qf->map_matching_symbols (objfile, name, domain, global,
aux_add_nonlocal_symbols, &data,
wild_match, NULL);
else
- objfile->sf->qf->map_matching_symbols (name, domain, objfile, global,
+ objfile->sf->qf->map_matching_symbols (objfile, name, domain, global,
aux_add_nonlocal_symbols, &data,
full_match, compare_names);
}
strcpy (name1, "_ada_");
strcpy (name1 + sizeof ("_ada_") - 1, name);
data.objfile = objfile;
- objfile->sf->qf->map_matching_symbols (name1, domain,
- objfile, global,
+ objfile->sf->qf->map_matching_symbols (objfile, name1, domain,
+ global,
aux_add_nonlocal_symbols,
&data,
full_match, compare_names);
variants of the runtime, we use a sniffer that will determine
the runtime variant used by the program being debugged. */
-/* The different types of catchpoints that we introduced for catching
- Ada exceptions. */
-
-enum exception_catchpoint_kind
-{
- ex_catch_exception,
- ex_catch_exception_unhandled,
- ex_catch_assert
-};
-
/* Ada's standard exceptions. */
static char *standard_exc[] = {
the name of the exception being raised (this name is printed in
the catchpoint message, and is also used when trying to catch
a specific exception). We do not handle this case for now. */
- if (lookup_minimal_symbol (einfo->catch_exception_sym, NULL, NULL))
+ struct minimal_symbol *msym
+ = lookup_minimal_symbol (einfo->catch_exception_sym, NULL, NULL);
+
+ if (msym && MSYMBOL_TYPE (msym) != mst_solib_trampoline)
error (_("Your Ada runtime appears to be missing some debugging "
"information.\nCannot insert Ada exception catchpoint "
"in this configuration."));
is_known_support_routine (struct frame_info *frame)
{
struct symtab_and_line sal;
- const char *func_name;
+ char *func_name;
enum language func_lang;
int i;
const char *fullname;
if (re_exec (lbasename (sal.symtab->filename)))
return 1;
if (sal.symtab->objfile != NULL
- && re_exec (sal.symtab->objfile->name))
+ && re_exec (objfile_name (sal.symtab->objfile)))
return 1;
}
{
re_comp (known_auxiliary_function_name_patterns[i]);
if (re_exec (func_name))
- return 1;
+ {
+ xfree (func_name);
+ return 1;
+ }
}
+ xfree (func_name);
return 0;
}
int frame_level;
struct frame_info *fi;
struct ada_inferior_data *data = get_ada_inferior_data (current_inferior ());
+ struct cleanup *old_chain;
/* To determine the name of this exception, we need to select
the frame corresponding to RAISE_SYM_NAME. This frame is
if (fi != NULL)
fi = get_prev_frame (fi);
+ old_chain = make_cleanup (null_cleanup, NULL);
while (fi != NULL)
{
- const char *func_name;
+ char *func_name;
enum language func_lang;
find_frame_funname (fi, &func_name, &func_lang, NULL);
- if (func_name != NULL
- && strcmp (func_name, data->exception_info->catch_exception_sym) == 0)
- break; /* We found the frame we were looking for... */
- fi = get_prev_frame (fi);
+ if (func_name != NULL)
+ {
+ make_cleanup (xfree, func_name);
+
+ if (strcmp (func_name,
+ data->exception_info->catch_exception_sym) == 0)
+ break; /* We found the frame we were looking for... */
+ fi = get_prev_frame (fi);
+ }
}
+ do_cleanups (old_chain);
if (fi == NULL)
return 0;
Return zero if the address could not be computed, or if not relevant. */
static CORE_ADDR
-ada_exception_name_addr_1 (enum exception_catchpoint_kind ex,
+ada_exception_name_addr_1 (enum ada_exception_catchpoint_kind ex,
struct breakpoint *b)
{
struct ada_inferior_data *data = get_ada_inferior_data (current_inferior ());
switch (ex)
{
- case ex_catch_exception:
+ case ada_catch_exception:
return (parse_and_eval_address ("e.full_name"));
break;
- case ex_catch_exception_unhandled:
+ case ada_catch_exception_unhandled:
return data->exception_info->unhandled_exception_name_addr ();
break;
- case ex_catch_assert:
+ case ada_catch_assert:
return 0; /* Exception name is not relevant in this case. */
break;
and zero is returned. */
static CORE_ADDR
-ada_exception_name_addr (enum exception_catchpoint_kind ex,
+ada_exception_name_addr (enum ada_exception_catchpoint_kind ex,
struct breakpoint *b)
{
volatile struct gdb_exception e;
return result;
}
-static struct symtab_and_line ada_exception_sal (enum exception_catchpoint_kind,
- char *, char **,
- const struct breakpoint_ops **);
static char *ada_exception_catchpoint_cond_string (const char *excep_string);
/* Ada catchpoints.
block_for_pc (bl->address), 0);
}
if (e.reason < 0)
- warning (_("failed to reevaluate internal exception condition "
- "for catchpoint %d: %s"),
- c->base.number, e.message);
+ {
+ warning (_("failed to reevaluate internal exception condition "
+ "for catchpoint %d: %s"),
+ c->base.number, e.message);
+ /* There is a bug in GCC on sparc-solaris when building with
+ optimization which causes EXP to change unexpectedly
+ (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56982).
+ The problem should be fixed starting with GCC 4.9.
+ In the meantime, work around it by forcing EXP back
+ to NULL. */
+ exp = NULL;
+ }
}
ada_loc->excep_cond_expr = exp;
exception catchpoint kinds. */
static void
-dtor_exception (enum exception_catchpoint_kind ex, struct breakpoint *b)
+dtor_exception (enum ada_exception_catchpoint_kind ex, struct breakpoint *b)
{
struct ada_catchpoint *c = (struct ada_catchpoint *) b;
structure for all exception catchpoint kinds. */
static struct bp_location *
-allocate_location_exception (enum exception_catchpoint_kind ex,
+allocate_location_exception (enum ada_exception_catchpoint_kind ex,
struct breakpoint *self)
{
struct ada_catchpoint_location *loc;
exception catchpoint kinds. */
static void
-re_set_exception (enum exception_catchpoint_kind ex, struct breakpoint *b)
+re_set_exception (enum ada_exception_catchpoint_kind ex, struct breakpoint *b)
{
struct ada_catchpoint *c = (struct ada_catchpoint *) b;
for all exception catchpoint kinds. */
static void
-check_status_exception (enum exception_catchpoint_kind ex, bpstat bs)
+check_status_exception (enum ada_exception_catchpoint_kind ex, bpstat bs)
{
bs->stop = should_stop_exception (bs->bp_location_at);
}
for all exception catchpoint kinds. */
static enum print_stop_action
-print_it_exception (enum exception_catchpoint_kind ex, bpstat bs)
+print_it_exception (enum ada_exception_catchpoint_kind ex, bpstat bs)
{
struct ui_out *uiout = current_uiout;
struct breakpoint *b = bs->breakpoint_at;
switch (ex)
{
- case ex_catch_exception:
- case ex_catch_exception_unhandled:
+ case ada_catch_exception:
+ case ada_catch_exception_unhandled:
{
const CORE_ADDR addr = ada_exception_name_addr (ex, b);
char exception_name[256];
it clearer to the user which kind of catchpoint just got
hit. We used ui_out_text to make sure that this extra
info does not pollute the exception name in the MI case. */
- if (ex == ex_catch_exception_unhandled)
+ if (ex == ada_catch_exception_unhandled)
ui_out_text (uiout, "unhandled ");
ui_out_field_string (uiout, "exception-name", exception_name);
}
break;
- case ex_catch_assert:
+ case ada_catch_assert:
/* In this case, the name of the exception is not really
important. Just print "failed assertion" to make it clearer
that his program just hit an assertion-failure catchpoint.
for all exception catchpoint kinds. */
static void
-print_one_exception (enum exception_catchpoint_kind ex,
+print_one_exception (enum ada_exception_catchpoint_kind ex,
struct breakpoint *b, struct bp_location **last_loc)
{
struct ui_out *uiout = current_uiout;
*last_loc = b->loc;
switch (ex)
{
- case ex_catch_exception:
+ case ada_catch_exception:
if (c->excep_string != NULL)
{
char *msg = xstrprintf (_("`%s' Ada exception"), c->excep_string);
break;
- case ex_catch_exception_unhandled:
+ case ada_catch_exception_unhandled:
ui_out_field_string (uiout, "what", "unhandled Ada exceptions");
break;
- case ex_catch_assert:
+ case ada_catch_assert:
ui_out_field_string (uiout, "what", "failed Ada assertions");
break;
for all exception catchpoint kinds. */
static void
-print_mention_exception (enum exception_catchpoint_kind ex,
+print_mention_exception (enum ada_exception_catchpoint_kind ex,
struct breakpoint *b)
{
struct ada_catchpoint *c = (struct ada_catchpoint *) b;
switch (ex)
{
- case ex_catch_exception:
+ case ada_catch_exception:
if (c->excep_string != NULL)
{
char *info = xstrprintf (_("`%s' Ada exception"), c->excep_string);
ui_out_text (uiout, _("all Ada exceptions"));
break;
- case ex_catch_exception_unhandled:
+ case ada_catch_exception_unhandled:
ui_out_text (uiout, _("unhandled Ada exceptions"));
break;
- case ex_catch_assert:
+ case ada_catch_assert:
ui_out_text (uiout, _("failed Ada assertions"));
break;
for all exception catchpoint kinds. */
static void
-print_recreate_exception (enum exception_catchpoint_kind ex,
+print_recreate_exception (enum ada_exception_catchpoint_kind ex,
struct breakpoint *b, struct ui_file *fp)
{
struct ada_catchpoint *c = (struct ada_catchpoint *) b;
switch (ex)
{
- case ex_catch_exception:
+ case ada_catch_exception:
fprintf_filtered (fp, "catch exception");
if (c->excep_string != NULL)
fprintf_filtered (fp, " %s", c->excep_string);
break;
- case ex_catch_exception_unhandled:
+ case ada_catch_exception_unhandled:
fprintf_filtered (fp, "catch exception unhandled");
break;
- case ex_catch_assert:
+ case ada_catch_assert:
fprintf_filtered (fp, "catch assert");
break;
static void
dtor_catch_exception (struct breakpoint *b)
{
- dtor_exception (ex_catch_exception, b);
+ dtor_exception (ada_catch_exception, b);
}
static struct bp_location *
allocate_location_catch_exception (struct breakpoint *self)
{
- return allocate_location_exception (ex_catch_exception, self);
+ return allocate_location_exception (ada_catch_exception, self);
}
static void
re_set_catch_exception (struct breakpoint *b)
{
- re_set_exception (ex_catch_exception, b);
+ re_set_exception (ada_catch_exception, b);
}
static void
check_status_catch_exception (bpstat bs)
{
- check_status_exception (ex_catch_exception, bs);
+ check_status_exception (ada_catch_exception, bs);
}
static enum print_stop_action
print_it_catch_exception (bpstat bs)
{
- return print_it_exception (ex_catch_exception, bs);
+ return print_it_exception (ada_catch_exception, bs);
}
static void
print_one_catch_exception (struct breakpoint *b, struct bp_location **last_loc)
{
- print_one_exception (ex_catch_exception, b, last_loc);
+ print_one_exception (ada_catch_exception, b, last_loc);
}
static void
print_mention_catch_exception (struct breakpoint *b)
{
- print_mention_exception (ex_catch_exception, b);
+ print_mention_exception (ada_catch_exception, b);
}
static void
print_recreate_catch_exception (struct breakpoint *b, struct ui_file *fp)
{
- print_recreate_exception (ex_catch_exception, b, fp);
+ print_recreate_exception (ada_catch_exception, b, fp);
}
static struct breakpoint_ops catch_exception_breakpoint_ops;
static void
dtor_catch_exception_unhandled (struct breakpoint *b)
{
- dtor_exception (ex_catch_exception_unhandled, b);
+ dtor_exception (ada_catch_exception_unhandled, b);
}
static struct bp_location *
allocate_location_catch_exception_unhandled (struct breakpoint *self)
{
- return allocate_location_exception (ex_catch_exception_unhandled, self);
+ return allocate_location_exception (ada_catch_exception_unhandled, self);
}
static void
re_set_catch_exception_unhandled (struct breakpoint *b)
{
- re_set_exception (ex_catch_exception_unhandled, b);
+ re_set_exception (ada_catch_exception_unhandled, b);
}
static void
check_status_catch_exception_unhandled (bpstat bs)
{
- check_status_exception (ex_catch_exception_unhandled, bs);
+ check_status_exception (ada_catch_exception_unhandled, bs);
}
static enum print_stop_action
print_it_catch_exception_unhandled (bpstat bs)
{
- return print_it_exception (ex_catch_exception_unhandled, bs);
+ return print_it_exception (ada_catch_exception_unhandled, bs);
}
static void
print_one_catch_exception_unhandled (struct breakpoint *b,
struct bp_location **last_loc)
{
- print_one_exception (ex_catch_exception_unhandled, b, last_loc);
+ print_one_exception (ada_catch_exception_unhandled, b, last_loc);
}
static void
print_mention_catch_exception_unhandled (struct breakpoint *b)
{
- print_mention_exception (ex_catch_exception_unhandled, b);
+ print_mention_exception (ada_catch_exception_unhandled, b);
}
static void
print_recreate_catch_exception_unhandled (struct breakpoint *b,
struct ui_file *fp)
{
- print_recreate_exception (ex_catch_exception_unhandled, b, fp);
+ print_recreate_exception (ada_catch_exception_unhandled, b, fp);
}
static struct breakpoint_ops catch_exception_unhandled_breakpoint_ops;
static void
dtor_catch_assert (struct breakpoint *b)
{
- dtor_exception (ex_catch_assert, b);
+ dtor_exception (ada_catch_assert, b);
}
static struct bp_location *
allocate_location_catch_assert (struct breakpoint *self)
{
- return allocate_location_exception (ex_catch_assert, self);
+ return allocate_location_exception (ada_catch_assert, self);
}
static void
re_set_catch_assert (struct breakpoint *b)
{
- re_set_exception (ex_catch_assert, b);
+ re_set_exception (ada_catch_assert, b);
}
static void
check_status_catch_assert (bpstat bs)
{
- check_status_exception (ex_catch_assert, bs);
+ check_status_exception (ada_catch_assert, bs);
}
static enum print_stop_action
print_it_catch_assert (bpstat bs)
{
- return print_it_exception (ex_catch_assert, bs);
+ return print_it_exception (ada_catch_assert, bs);
}
static void
print_one_catch_assert (struct breakpoint *b, struct bp_location **last_loc)
{
- print_one_exception (ex_catch_assert, b, last_loc);
+ print_one_exception (ada_catch_assert, b, last_loc);
}
static void
print_mention_catch_assert (struct breakpoint *b)
{
- print_mention_exception (ex_catch_assert, b);
+ print_mention_exception (ada_catch_assert, b);
}
static void
print_recreate_catch_assert (struct breakpoint *b, struct ui_file *fp)
{
- print_recreate_exception (ex_catch_assert, b, fp);
+ print_recreate_exception (ada_catch_assert, b, fp);
}
static struct breakpoint_ops catch_assert_breakpoint_ops;
static void
catch_ada_exception_command_split (char *args,
- enum exception_catchpoint_kind *ex,
+ enum ada_exception_catchpoint_kind *ex,
char **excep_string,
char **cond_string)
{
if (exception_name == NULL)
{
/* Catch all exceptions. */
- *ex = ex_catch_exception;
+ *ex = ada_catch_exception;
*excep_string = NULL;
}
else if (strcmp (exception_name, "unhandled") == 0)
{
/* Catch unhandled exceptions. */
- *ex = ex_catch_exception_unhandled;
+ *ex = ada_catch_exception_unhandled;
*excep_string = NULL;
}
else
{
/* Catch a specific exception. */
- *ex = ex_catch_exception;
+ *ex = ada_catch_exception;
*excep_string = exception_name;
}
*cond_string = cond;
implement a catchpoint of the EX kind. */
static const char *
-ada_exception_sym_name (enum exception_catchpoint_kind ex)
+ada_exception_sym_name (enum ada_exception_catchpoint_kind ex)
{
struct ada_inferior_data *data = get_ada_inferior_data (current_inferior ());
switch (ex)
{
- case ex_catch_exception:
+ case ada_catch_exception:
return (data->exception_info->catch_exception_sym);
break;
- case ex_catch_exception_unhandled:
+ case ada_catch_exception_unhandled:
return (data->exception_info->catch_exception_unhandled_sym);
break;
- case ex_catch_assert:
+ case ada_catch_assert:
return (data->exception_info->catch_assert_sym);
break;
default:
of the EX kind. */
static const struct breakpoint_ops *
-ada_exception_breakpoint_ops (enum exception_catchpoint_kind ex)
+ada_exception_breakpoint_ops (enum ada_exception_catchpoint_kind ex)
{
switch (ex)
{
- case ex_catch_exception:
+ case ada_catch_exception:
return (&catch_exception_breakpoint_ops);
break;
- case ex_catch_exception_unhandled:
+ case ada_catch_exception_unhandled:
return (&catch_exception_unhandled_breakpoint_ops);
break;
- case ex_catch_assert:
+ case ada_catch_assert:
return (&catch_assert_breakpoint_ops);
break;
default:
type of catchpoint we need to create. */
static struct symtab_and_line
-ada_exception_sal (enum exception_catchpoint_kind ex, char *excep_string,
+ada_exception_sal (enum ada_exception_catchpoint_kind ex, char *excep_string,
char **addr_string, const struct breakpoint_ops **ops)
{
const char *sym_name;
return find_function_start_sal (sym, 1);
}
-/* Parse the arguments (ARGS) of the "catch exception" command.
-
- If the user asked the catchpoint to catch only a specific
- exception, then save the exception name in ADDR_STRING.
+/* Create an Ada exception catchpoint.
- If the user provided a condition, then set COND_STRING to
- that condition expression (the memory must be deallocated
- after use). Otherwise, set COND_STRING to NULL.
+ EX_KIND is the kind of exception catchpoint to be created.
- See ada_exception_sal for a description of all the remaining
- function arguments of this function. */
+ If EXCEPT_STRING is NULL, this catchpoint is expected to trigger
+ for all exceptions. Otherwise, EXCEPT_STRING indicates the name
+ of the exception to which this catchpoint applies. When not NULL,
+ the string must be allocated on the heap, and its deallocation
+ is no longer the responsibility of the caller.
-static struct symtab_and_line
-ada_decode_exception_location (char *args, char **addr_string,
- char **excep_string,
- char **cond_string,
- const struct breakpoint_ops **ops)
-{
- enum exception_catchpoint_kind ex;
+ COND_STRING, if not NULL, is the catchpoint condition. This string
+ must be allocated on the heap, and its deallocation is no longer
+ the responsibility of the caller.
- catch_ada_exception_command_split (args, &ex, excep_string, cond_string);
- return ada_exception_sal (ex, *excep_string, addr_string, ops);
-}
+ TEMPFLAG, if nonzero, means that the underlying breakpoint
+ should be temporary.
-/* Create an Ada exception catchpoint. */
+ FROM_TTY is the usual argument passed to all commands implementations. */
-static void
+void
create_ada_exception_catchpoint (struct gdbarch *gdbarch,
- struct symtab_and_line sal,
- char *addr_string,
+ enum ada_exception_catchpoint_kind ex_kind,
char *excep_string,
char *cond_string,
- const struct breakpoint_ops *ops,
int tempflag,
+ int disabled,
int from_tty)
{
struct ada_catchpoint *c;
+ char *addr_string = NULL;
+ const struct breakpoint_ops *ops = NULL;
+ struct symtab_and_line sal
+ = ada_exception_sal (ex_kind, excep_string, &addr_string, &ops);
c = XNEW (struct ada_catchpoint);
init_ada_exception_breakpoint (&c->base, gdbarch, sal, addr_string,
- ops, tempflag, from_tty);
+ ops, tempflag, disabled, from_tty);
c->excep_string = excep_string;
create_excep_cond_exprs (c);
if (cond_string != NULL)
{
struct gdbarch *gdbarch = get_current_arch ();
int tempflag;
- struct symtab_and_line sal;
- char *addr_string = NULL;
+ enum ada_exception_catchpoint_kind ex_kind;
char *excep_string = NULL;
char *cond_string = NULL;
- const struct breakpoint_ops *ops = NULL;
tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
if (!arg)
arg = "";
- sal = ada_decode_exception_location (arg, &addr_string, &excep_string,
- &cond_string, &ops);
- create_ada_exception_catchpoint (gdbarch, sal, addr_string,
- excep_string, cond_string, ops,
- tempflag, from_tty);
+ catch_ada_exception_command_split (arg, &ex_kind, &excep_string,
+ &cond_string);
+ create_ada_exception_catchpoint (gdbarch, ex_kind,
+ excep_string, cond_string,
+ tempflag, 1 /* enabled */,
+ from_tty);
}
-/* Assuming that ARGS contains the arguments of a "catch assert"
- command, parse those arguments and return a symtab_and_line object
- for a failed assertion catchpoint.
+/* Split the arguments specified in a "catch assert" command.
- Set ADDR_STRING to the name of the function where the real
- breakpoint that implements the catchpoint is set.
+ ARGS contains the command's arguments (or the empty string if
+ no arguments were passed).
If ARGS contains a condition, set COND_STRING to that condition
- (the memory needs to be deallocated after use). Otherwise, set
- COND_STRING to NULL. */
+ (the memory needs to be deallocated after use). */
-static struct symtab_and_line
-ada_decode_assert_location (char *args, char **addr_string,
- char **cond_string,
- const struct breakpoint_ops **ops)
+static void
+catch_ada_assert_command_split (char *args, char **cond_string)
{
args = skip_spaces (args);
the command. */
else if (args[0] != '\0')
error (_("Junk at end of arguments."));
-
- return ada_exception_sal (ex_catch_assert, NULL, addr_string, ops);
}
/* Implement the "catch assert" command. */
{
struct gdbarch *gdbarch = get_current_arch ();
int tempflag;
- struct symtab_and_line sal;
- char *addr_string = NULL;
char *cond_string = NULL;
- const struct breakpoint_ops *ops = NULL;
tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
if (!arg)
arg = "";
- sal = ada_decode_assert_location (arg, &addr_string, &cond_string, &ops);
- create_ada_exception_catchpoint (gdbarch, sal, addr_string,
- NULL, cond_string, ops, tempflag,
+ catch_ada_assert_command_split (arg, &cond_string);
+ create_ada_exception_catchpoint (gdbarch, ada_catch_assert,
+ NULL, cond_string,
+ tempflag, 1 /* enabled */,
from_tty);
}
+
+/* Return non-zero if the symbol SYM is an Ada exception object. */
+
+static int
+ada_is_exception_sym (struct symbol *sym)
+{
+ const char *type_name = type_name_no_tag (SYMBOL_TYPE (sym));
+
+ return (SYMBOL_CLASS (sym) != LOC_TYPEDEF
+ && SYMBOL_CLASS (sym) != LOC_BLOCK
+ && SYMBOL_CLASS (sym) != LOC_CONST
+ && SYMBOL_CLASS (sym) != LOC_UNRESOLVED
+ && type_name != NULL && strcmp (type_name, "exception") == 0);
+}
+
+/* Given a global symbol SYM, return non-zero iff SYM is a non-standard
+ Ada exception object. This matches all exceptions except the ones
+ defined by the Ada language. */
+
+static int
+ada_is_non_standard_exception_sym (struct symbol *sym)
+{
+ int i;
+
+ if (!ada_is_exception_sym (sym))
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE (standard_exc); i++)
+ if (strcmp (SYMBOL_LINKAGE_NAME (sym), standard_exc[i]) == 0)
+ return 0; /* A standard exception. */
+
+ /* Numeric_Error is also a standard exception, so exclude it.
+ See the STANDARD_EXC description for more details as to why
+ this exception is not listed in that array. */
+ if (strcmp (SYMBOL_LINKAGE_NAME (sym), "numeric_error") == 0)
+ return 0;
+
+ return 1;
+}
+
+/* A helper function for qsort, comparing two struct ada_exc_info
+ objects.
+
+ The comparison is determined first by exception name, and then
+ by exception address. */
+
+static int
+compare_ada_exception_info (const void *a, const void *b)
+{
+ const struct ada_exc_info *exc_a = (struct ada_exc_info *) a;
+ const struct ada_exc_info *exc_b = (struct ada_exc_info *) b;
+ int result;
+
+ result = strcmp (exc_a->name, exc_b->name);
+ if (result != 0)
+ return result;
+
+ if (exc_a->addr < exc_b->addr)
+ return -1;
+ if (exc_a->addr > exc_b->addr)
+ return 1;
+
+ return 0;
+}
+
+/* Sort EXCEPTIONS using compare_ada_exception_info as the comparison
+ routine, but keeping the first SKIP elements untouched.
+
+ All duplicates are also removed. */
+
+static void
+sort_remove_dups_ada_exceptions_list (VEC(ada_exc_info) **exceptions,
+ int skip)
+{
+ struct ada_exc_info *to_sort
+ = VEC_address (ada_exc_info, *exceptions) + skip;
+ int to_sort_len
+ = VEC_length (ada_exc_info, *exceptions) - skip;
+ int i, j;
+
+ qsort (to_sort, to_sort_len, sizeof (struct ada_exc_info),
+ compare_ada_exception_info);
+
+ for (i = 1, j = 1; i < to_sort_len; i++)
+ if (compare_ada_exception_info (&to_sort[i], &to_sort[j - 1]) != 0)
+ to_sort[j++] = to_sort[i];
+ to_sort_len = j;
+ VEC_truncate(ada_exc_info, *exceptions, skip + to_sort_len);
+}
+
+/* A function intended as the "name_matcher" callback in the struct
+ quick_symbol_functions' expand_symtabs_matching method.
+
+ SEARCH_NAME is the symbol's search name.
+
+ If USER_DATA is not NULL, it is a pointer to a regext_t object
+ used to match the symbol (by natural name). Otherwise, when USER_DATA
+ is null, no filtering is performed, and all symbols are a positive
+ match. */
+
+static int
+ada_exc_search_name_matches (const char *search_name, void *user_data)
+{
+ regex_t *preg = user_data;
+
+ if (preg == NULL)
+ return 1;
+
+ /* In Ada, the symbol "search name" is a linkage name, whereas
+ the regular expression used to do the matching refers to
+ the natural name. So match against the decoded name. */
+ return (regexec (preg, ada_decode (search_name), 0, NULL, 0) == 0);
+}
+
+/* Add all exceptions defined by the Ada standard whose name match
+ a regular expression.
+
+ If PREG is not NULL, then this regexp_t object is used to
+ perform the symbol name matching. Otherwise, no name-based
+ filtering is performed.
+
+ EXCEPTIONS is a vector of exceptions to which matching exceptions
+ gets pushed. */
+
+static void
+ada_add_standard_exceptions (regex_t *preg, VEC(ada_exc_info) **exceptions)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE (standard_exc); i++)
+ {
+ if (preg == NULL
+ || regexec (preg, standard_exc[i], 0, NULL, 0) == 0)
+ {
+ struct bound_minimal_symbol msymbol
+ = ada_lookup_simple_minsym (standard_exc[i]);
+
+ if (msymbol.minsym != NULL)
+ {
+ struct ada_exc_info info
+ = {standard_exc[i], SYMBOL_VALUE_ADDRESS (msymbol.minsym)};
+
+ VEC_safe_push (ada_exc_info, *exceptions, &info);
+ }
+ }
+ }
+}
+
+/* Add all Ada exceptions defined locally and accessible from the given
+ FRAME.
+
+ If PREG is not NULL, then this regexp_t object is used to
+ perform the symbol name matching. Otherwise, no name-based
+ filtering is performed.
+
+ EXCEPTIONS is a vector of exceptions to which matching exceptions
+ gets pushed. */
+
+static void
+ada_add_exceptions_from_frame (regex_t *preg, struct frame_info *frame,
+ VEC(ada_exc_info) **exceptions)
+{
+ struct block *block = get_frame_block (frame, 0);
+
+ while (block != 0)
+ {
+ struct block_iterator iter;
+ struct symbol *sym;
+
+ ALL_BLOCK_SYMBOLS (block, iter, sym)
+ {
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_TYPEDEF:
+ case LOC_BLOCK:
+ case LOC_CONST:
+ break;
+ default:
+ if (ada_is_exception_sym (sym))
+ {
+ struct ada_exc_info info = {SYMBOL_PRINT_NAME (sym),
+ SYMBOL_VALUE_ADDRESS (sym)};
+
+ VEC_safe_push (ada_exc_info, *exceptions, &info);
+ }
+ }
+ }
+ if (BLOCK_FUNCTION (block) != NULL)
+ break;
+ block = BLOCK_SUPERBLOCK (block);
+ }
+}
+
+/* Add all exceptions defined globally whose name name match
+ a regular expression, excluding standard exceptions.
+
+ The reason we exclude standard exceptions is that they need
+ to be handled separately: Standard exceptions are defined inside
+ a runtime unit which is normally not compiled with debugging info,
+ and thus usually do not show up in our symbol search. However,
+ if the unit was in fact built with debugging info, we need to
+ exclude them because they would duplicate the entry we found
+ during the special loop that specifically searches for those
+ standard exceptions.
+
+ If PREG is not NULL, then this regexp_t object is used to
+ perform the symbol name matching. Otherwise, no name-based
+ filtering is performed.
+
+ EXCEPTIONS is a vector of exceptions to which matching exceptions
+ gets pushed. */
+
+static void
+ada_add_global_exceptions (regex_t *preg, VEC(ada_exc_info) **exceptions)
+{
+ struct objfile *objfile;
+ struct symtab *s;
+
+ ALL_OBJFILES (objfile)
+ if (objfile->sf)
+ objfile->sf->qf->expand_symtabs_matching
+ (objfile, NULL, ada_exc_search_name_matches,
+ VARIABLES_DOMAIN, preg);
+
+ ALL_PRIMARY_SYMTABS (objfile, s)
+ {
+ struct blockvector *bv = BLOCKVECTOR (s);
+ int i;
+
+ for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
+ {
+ struct block *b = BLOCKVECTOR_BLOCK (bv, i);
+ struct block_iterator iter;
+ struct symbol *sym;
+
+ ALL_BLOCK_SYMBOLS (b, iter, sym)
+ if (ada_is_non_standard_exception_sym (sym)
+ && (preg == NULL
+ || regexec (preg, SYMBOL_NATURAL_NAME (sym),
+ 0, NULL, 0) == 0))
+ {
+ struct ada_exc_info info
+ = {SYMBOL_PRINT_NAME (sym), SYMBOL_VALUE_ADDRESS (sym)};
+
+ VEC_safe_push (ada_exc_info, *exceptions, &info);
+ }
+ }
+ }
+}
+
+/* Implements ada_exceptions_list with the regular expression passed
+ as a regex_t, rather than a string.
+
+ If not NULL, PREG is used to filter out exceptions whose names
+ do not match. Otherwise, all exceptions are listed. */
+
+static VEC(ada_exc_info) *
+ada_exceptions_list_1 (regex_t *preg)
+{
+ VEC(ada_exc_info) *result = NULL;
+ struct cleanup *old_chain
+ = make_cleanup (VEC_cleanup (ada_exc_info), &result);
+ int prev_len;
+
+ /* First, list the known standard exceptions. These exceptions
+ need to be handled separately, as they are usually defined in
+ runtime units that have been compiled without debugging info. */
+
+ ada_add_standard_exceptions (preg, &result);
+
+ /* Next, find all exceptions whose scope is local and accessible
+ from the currently selected frame. */
+
+ if (has_stack_frames ())
+ {
+ prev_len = VEC_length (ada_exc_info, result);
+ ada_add_exceptions_from_frame (preg, get_selected_frame (NULL),
+ &result);
+ if (VEC_length (ada_exc_info, result) > prev_len)
+ sort_remove_dups_ada_exceptions_list (&result, prev_len);
+ }
+
+ /* Add all exceptions whose scope is global. */
+
+ prev_len = VEC_length (ada_exc_info, result);
+ ada_add_global_exceptions (preg, &result);
+ if (VEC_length (ada_exc_info, result) > prev_len)
+ sort_remove_dups_ada_exceptions_list (&result, prev_len);
+
+ discard_cleanups (old_chain);
+ return result;
+}
+
+/* Return a vector of ada_exc_info.
+
+ If REGEXP is NULL, all exceptions are included in the result.
+ Otherwise, it should contain a valid regular expression,
+ and only the exceptions whose names match that regular expression
+ are included in the result.
+
+ The exceptions are sorted in the following order:
+ - Standard exceptions (defined by the Ada language), in
+ alphabetical order;
+ - Exceptions only visible from the current frame, in
+ alphabetical order;
+ - Exceptions whose scope is global, in alphabetical order. */
+
+VEC(ada_exc_info) *
+ada_exceptions_list (const char *regexp)
+{
+ VEC(ada_exc_info) *result = NULL;
+ struct cleanup *old_chain = NULL;
+ regex_t reg;
+
+ if (regexp != NULL)
+ old_chain = compile_rx_or_error (®, regexp,
+ _("invalid regular expression"));
+
+ result = ada_exceptions_list_1 (regexp != NULL ? ® : NULL);
+
+ if (old_chain != NULL)
+ do_cleanups (old_chain);
+ return result;
+}
+
+/* Implement the "info exceptions" command. */
+
+static void
+info_exceptions_command (char *regexp, int from_tty)
+{
+ VEC(ada_exc_info) *exceptions;
+ struct cleanup *cleanup;
+ struct gdbarch *gdbarch = get_current_arch ();
+ int ix;
+ struct ada_exc_info *info;
+
+ exceptions = ada_exceptions_list (regexp);
+ cleanup = make_cleanup (VEC_cleanup (ada_exc_info), &exceptions);
+
+ if (regexp != NULL)
+ printf_filtered
+ (_("All Ada exceptions matching regular expression \"%s\":\n"), regexp);
+ else
+ printf_filtered (_("All defined Ada exceptions:\n"));
+
+ for (ix = 0; VEC_iterate(ada_exc_info, exceptions, ix, info); ix++)
+ printf_filtered ("%s: %s\n", info->name, paddress (gdbarch, info->addr));
+
+ do_cleanups (cleanup);
+}
+
/* Operators */
/* Information about operators given special treatment in functions
below. */
const struct language_defn ada_language_defn = {
"ada", /* Language name */
+ "Ada",
language_ada,
range_check_off,
case_sensitive_on, /* Yes, Ada is case-insensitive, but
c_get_string,
ada_get_symbol_name_cmp, /* la_get_symbol_name_cmp */
ada_iterate_over_symbols,
+ &ada_varobj_ops,
LANG_MAGIC
};
varsize_limit = 65536;
+ add_info ("exceptions", info_exceptions_command,
+ _("\
+List all Ada exception names.\n\
+If a regular expression is passed as an argument, only those matching\n\
+the regular expression are listed."));
+
obstack_init (&symbol_list_obstack);
decoded_names_store = htab_create_alloc