#include "valprint.h"
#include "source.h"
#include "observable.h"
-#include "common/vec.h"
+#include "gdbsupport/vec.h"
#include "stack.h"
-#include "common/gdb_vecs.h"
+#include "gdbsupport/gdb_vecs.h"
#include "typeprint.h"
#include "namespace.h"
#include "mi/mi-common.h"
#include "arch-utils.h"
#include "cli/cli-utils.h"
-#include "common/function-view.h"
-#include "common/byte-vector.h"
+#include "gdbsupport/function-view.h"
+#include "gdbsupport/byte-vector.h"
#include <algorithm>
+#include <map>
/* Define whether or not the C operator '/' truncates towards zero for
differently signed operands (truncation direction is undefined in C).
static int discrete_type_p (struct type *);
-static enum ada_renaming_category parse_old_style_renaming (struct type *,
- const char **,
- int *,
- const char **);
-
-static struct symbol *find_old_style_renaming_symbol (const char *,
- const struct block *);
-
static struct type *ada_lookup_struct_elt_type (struct type *, const char *,
int, int);
tagged types. With older versions of GNAT, this type was directly
accessible through a component ("tsd") in the object tag. But this
is no longer the case, so we cache it for each inferior. */
- struct type *tsd_type;
+ struct type *tsd_type = nullptr;
/* The exception_support_info data. This data is used to determine
how to implement support for Ada exception catchpoints in a given
inferior. */
- const struct exception_support_info *exception_info;
+ const struct exception_support_info *exception_info = nullptr;
};
/* Our key to this module's inferior data. */
-static const struct inferior_data *ada_inferior_data;
-
-/* A cleanup routine for our inferior data. */
-static void
-ada_inferior_data_cleanup (struct inferior *inf, void *arg)
-{
- struct ada_inferior_data *data;
-
- data = (struct ada_inferior_data *) inferior_data (inf, ada_inferior_data);
- if (data != NULL)
- xfree (data);
-}
+static const struct inferior_key<ada_inferior_data> ada_inferior_data;
/* Return our inferior data for the given inferior (INF).
{
struct ada_inferior_data *data;
- data = (struct ada_inferior_data *) inferior_data (inf, ada_inferior_data);
+ data = ada_inferior_data.get (inf);
if (data == NULL)
- {
- data = XCNEW (struct ada_inferior_data);
- set_inferior_data (inf, ada_inferior_data, data);
- }
+ data = ada_inferior_data.emplace (inf);
return data;
}
static void
ada_inferior_exit (struct inferior *inf)
{
- ada_inferior_data_cleanup (inf, NULL);
- set_inferior_data (inf, ada_inferior_data, NULL);
+ ada_inferior_data.clear (inf);
}
/* This module's per-program-space data. */
struct ada_pspace_data
{
+ ~ada_pspace_data ()
+ {
+ if (sym_cache != NULL)
+ ada_free_symbol_cache (sym_cache);
+ }
+
/* The Ada symbol cache. */
- struct ada_symbol_cache *sym_cache;
+ struct ada_symbol_cache *sym_cache = nullptr;
};
/* Key to our per-program-space data. */
-static const struct program_space_data *ada_pspace_data_handle;
+static const struct program_space_key<ada_pspace_data> ada_pspace_data_handle;
/* Return this module's data for the given program space (PSPACE).
If not is found, add a zero'ed one now.
{
struct ada_pspace_data *data;
- data = ((struct ada_pspace_data *)
- program_space_data (pspace, ada_pspace_data_handle));
+ data = ada_pspace_data_handle.get (pspace);
if (data == NULL)
- {
- data = XCNEW (struct ada_pspace_data);
- set_program_space_data (pspace, ada_pspace_data_handle, data);
- }
+ data = ada_pspace_data_handle.emplace (pspace);
return data;
}
-/* The cleanup callback for this module's per-program-space data. */
-
-static void
-ada_pspace_data_cleanup (struct program_space *pspace, void *data)
-{
- struct ada_pspace_data *pspace_data = (struct ada_pspace_data *) data;
-
- if (pspace_data->sym_cache != NULL)
- ada_free_symbol_cache (pspace_data->sym_cache);
- xfree (pspace_data);
-}
-
/* Utilities */
/* If TYPE is a TYPE_CODE_TYPEDEF type, return the target type after
set_value_component_location (result, val);
set_value_bitsize (result, value_bitsize (val));
set_value_bitpos (result, value_bitpos (val));
- set_value_address (result, value_address (val));
+ if (VALUE_LVAL (result) == lval_memory)
+ set_value_address (result, value_address (val));
return result;
}
}
enum language
ada_update_initial_language (enum language lang)
{
- if (lookup_minimal_symbol ("adainit", (const char *) NULL,
- (struct objfile *) NULL).minsym != NULL)
+ if (lookup_minimal_symbol ("adainit", NULL, NULL).minsym != NULL)
return language_ada;
return lang;
*len = *len - 1;
}
-/* Remove trailing X[bn]* suffixes (indicating names in package bodies). */
-
-static void
-ada_remove_Xbn_suffix (const char *encoded, int *len)
-{
- int i = *len - 1;
-
- while (i > 0 && (encoded[i] == 'b' || encoded[i] == 'n'))
- i--;
-
- if (encoded[i] != 'X')
- return;
-
- if (i == 0)
- return;
-
- if (isalnum (encoded[i-1]))
- *len = i;
-}
-
/* If ENCODED follows the GNAT entity encoding conventions, then return
the decoded form of ENCODED. Otherwise, return "<%s>" where "%s" is
replaced by ENCODED.
from_size = value_bitsize (fromval);
if (from_size == 0)
from_size = TYPE_LENGTH (value_type (fromval)) * TARGET_CHAR_BIT;
- if (gdbarch_bits_big_endian (get_type_arch (type)))
- copy_bitwise (buffer, value_bitpos (toval),
- value_contents (fromval), from_size - bits, bits, 1);
- else
- copy_bitwise (buffer, value_bitpos (toval),
- value_contents (fromval), 0, bits, 0);
+
+ const int is_big_endian = gdbarch_bits_big_endian (get_type_arch (type));
+ ULONGEST from_offset = 0;
+ if (is_big_endian && is_scalar_type (value_type (fromval)))
+ from_offset = from_size - bits;
+ copy_bitwise (buffer, value_bitpos (toval),
+ value_contents (fromval), from_offset,
+ bits, is_big_endian);
write_memory_with_notification (to_addr, buffer, len);
val = value_copy (toval);
{
default:
return ADA_NOT_RENAMING;
- case LOC_TYPEDEF:
- return parse_old_style_renaming (SYMBOL_TYPE (sym),
- renamed_entity, len, renaming_expr);
case LOC_LOCAL:
case LOC_STATIC:
case LOC_COMPUTED:
return kind;
}
-/* Assuming TYPE encodes a renaming according to the old encoding in
- exp_dbug.ads, returns details of that renaming in *RENAMED_ENTITY,
- *LEN, and *RENAMING_EXPR, as for ada_parse_renaming, above. Returns
- ADA_NOT_RENAMING otherwise. */
-static enum ada_renaming_category
-parse_old_style_renaming (struct type *type,
- const char **renamed_entity, int *len,
- const char **renaming_expr)
-{
- enum ada_renaming_category kind;
- const char *name;
- const char *info;
- const char *suffix;
-
- if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM
- || TYPE_NFIELDS (type) != 1)
- return ADA_NOT_RENAMING;
-
- name = TYPE_NAME (type);
- if (name == NULL)
- return ADA_NOT_RENAMING;
-
- name = strstr (name, "___XR");
- if (name == NULL)
- return ADA_NOT_RENAMING;
- switch (name[5])
- {
- case '\0':
- case '_':
- kind = ADA_OBJECT_RENAMING;
- break;
- case 'E':
- kind = ADA_EXCEPTION_RENAMING;
- break;
- case 'P':
- kind = ADA_PACKAGE_RENAMING;
- break;
- case 'S':
- kind = ADA_SUBPROGRAM_RENAMING;
- break;
- default:
- return ADA_NOT_RENAMING;
- }
-
- info = TYPE_FIELD_NAME (type, 0);
- if (info == NULL)
- return ADA_NOT_RENAMING;
- if (renamed_entity != NULL)
- *renamed_entity = info;
- suffix = strstr (info, "___XE");
- if (renaming_expr != NULL)
- *renaming_expr = suffix + 5;
- if (suffix == NULL || suffix == info)
- return ADA_NOT_RENAMING;
- if (len != NULL)
- *len = suffix - info;
- return kind;
-}
-
/* Compute the value of the given RENAMING_SYM, which is expected to
be a symbol encoding a renaming expression. BLOCK is the block
used to evaluate the renaming. */
return result;
}
+/* Return all the bound minimal symbols matching NAME according to Ada
+ decoding rules. Returns an empty vector 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. */
+
+static std::vector<struct bound_minimal_symbol>
+ada_lookup_simple_minsyms (const char *name)
+{
+ std::vector<struct bound_minimal_symbol> result;
+
+ symbol_name_match_type match_type = name_match_type_from_name (name);
+ lookup_name_info lookup_name (name, match_type);
+
+ symbol_name_matcher_ftype *match_name
+ = ada_get_symbol_name_matcher (lookup_name);
+
+ for (objfile *objfile : current_program_space->objfiles ())
+ {
+ for (minimal_symbol *msymbol : objfile->msymbols ())
+ {
+ if (match_name (MSYMBOL_LINKAGE_NAME (msymbol), lookup_name, NULL)
+ && MSYMBOL_TYPE (msymbol) != mst_solib_trampoline)
+ result.push_back ({msymbol, objfile});
+ }
+ }
+
+ return result;
+}
+
/* For all subprograms that statically enclose the subprogram of the
selected frame, add symbols matching identifier NAME in DOMAIN
and their blocks to the list of data in OBSTACKP, as for
std::string verbatim = std::string ("<") + name + '>';
gdb_assert (info != NULL);
- *info = ada_lookup_symbol (verbatim.c_str (), block, domain, NULL);
+ *info = ada_lookup_symbol (verbatim.c_str (), block, domain);
}
/* Return a symbol in DOMAIN matching NAME, in BLOCK0 and enclosing
scope and in global scopes, or NULL if none. NAME is folded and
encoded first. Otherwise, the result is as for ada_lookup_symbol_list,
- choosing the first symbol if there are multiple choices.
- If IS_A_FIELD_OF_THIS is not NULL, it is set to zero. */
+ choosing the first symbol if there are multiple choices. */
struct block_symbol
ada_lookup_symbol (const char *name, const struct block *block0,
- domain_enum domain, int *is_a_field_of_this)
+ domain_enum domain)
{
- if (is_a_field_of_this != NULL)
- *is_a_field_of_this = 0;
-
std::vector<struct block_symbol> candidates;
int n_candidates;
{
struct block_symbol sym;
- sym = ada_lookup_symbol (name, block_static_block (block), domain, NULL);
+ sym = ada_lookup_symbol (name, block_static_block (block), domain);
if (sym.symbol != NULL)
return sym;
arg_type = ada_check_typedef (arg_type);
type = TYPE_FIELD_TYPE (arg_type, fieldno);
- /* Handle packed fields. */
-
- if (TYPE_FIELD_BITSIZE (arg_type, fieldno) != 0)
+ /* Handle packed fields. It might be that the field is not packed
+ relative to its containing structure, but the structure itself is
+ packed; in this case we must take the bit-field path. */
+ if (TYPE_FIELD_BITSIZE (arg_type, fieldno) != 0 || value_bitpos (arg1) != 0)
{
int bit_pos = TYPE_FIELD_BITPOS (arg_type, fieldno);
int bit_size = TYPE_FIELD_BITSIZE (arg_type, fieldno);
symbols whose name is that of NAME_SYM suffixed with "___XR".
Return symbol if found, and NULL otherwise. */
-struct symbol *
-ada_find_renaming_symbol (struct symbol *name_sym, const struct block *block)
+static bool
+ada_is_renaming_symbol (struct symbol *name_sym)
{
const char *name = SYMBOL_LINKAGE_NAME (name_sym);
- struct symbol *sym;
-
- if (strstr (name, "___XR") != NULL)
- return name_sym;
-
- sym = find_old_style_renaming_symbol (name, block);
-
- if (sym != NULL)
- return sym;
-
- /* Not right yet. FIXME pnh 7/20/2007. */
- sym = ada_find_any_type_symbol (name);
- if (sym != NULL && strstr (SYMBOL_LINKAGE_NAME (sym), "___XR") != NULL)
- return sym;
- else
- return NULL;
-}
-
-static struct symbol *
-find_old_style_renaming_symbol (const char *name, const struct block *block)
-{
- const struct symbol *function_sym = block_linkage_function (block);
- char *rename;
-
- if (function_sym != NULL)
- {
- /* If the symbol is defined inside a function, NAME is not fully
- qualified. This means we need to prepend the function name
- as well as adding the ``___XR'' suffix to build the name of
- the associated renaming symbol. */
- const char *function_name = SYMBOL_LINKAGE_NAME (function_sym);
- /* Function names sometimes contain suffixes used
- for instance to qualify nested subprograms. When building
- the XR type name, we need to make sure that this suffix is
- not included. So do not include any suffix in the function
- name length below. */
- int function_name_len = ada_name_prefix_len (function_name);
- const int rename_len = function_name_len + 2 /* "__" */
- + strlen (name) + 6 /* "___XR\0" */ ;
-
- /* Strip the suffix if necessary. */
- ada_remove_trailing_digits (function_name, &function_name_len);
- ada_remove_po_subprogram_suffix (function_name, &function_name_len);
- ada_remove_Xbn_suffix (function_name, &function_name_len);
-
- /* Library-level functions are a special case, as GNAT adds
- a ``_ada_'' prefix to the function name to avoid namespace
- pollution. However, the renaming symbols themselves do not
- have this prefix, so we need to skip this prefix if present. */
- if (function_name_len > 5 /* "_ada_" */
- && strstr (function_name, "_ada_") == function_name)
- {
- function_name += 5;
- function_name_len -= 5;
- }
-
- rename = (char *) alloca (rename_len * sizeof (char));
- strncpy (rename, function_name, function_name_len);
- xsnprintf (rename + function_name_len, rename_len - function_name_len,
- "__%s___XR", name);
- }
- else
- {
- const int rename_len = strlen (name) + 6;
-
- rename = (char *) alloca (rename_len * sizeof (char));
- xsnprintf (rename, rename_len * sizeof (char), "%s___XR", name);
- }
-
- return ada_find_any_type_symbol (rename);
+ return strstr (name, "___XR") != NULL;
}
/* Because of GNAT encoding conventions, several GDB symbols may match a
[At the moment, this is true only for Character and Wide_Character;
It is a heuristic test that could stand improvement]. */
-int
+bool
ada_is_character_type (struct type *type)
{
const char *name;
/* If the type code says it's a character, then assume it really is,
and don't check any further. */
if (TYPE_CODE (type) == TYPE_CODE_CHAR)
- return 1;
+ return true;
/* Otherwise, assume it's a character type iff it is a discrete type
with a known character type name. */
/* True if TYPE appears to be an Ada string type. */
-int
+bool
ada_is_string_type (struct type *type)
{
type = ada_check_typedef (type);
return ada_is_character_type (elttype);
}
else
- return 0;
+ return false;
}
/* The compiler sometimes provides a parallel XVS type for a given
arg2 = evaluate_subexp (type, exp, pos, noside);
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
return arg1;
- if (ada_is_fixed_point_type (value_type (arg1)))
+ if (VALUE_LVAL (arg1) == lval_internalvar)
+ {
+ /* Nothing. */
+ }
+ else if (ada_is_fixed_point_type (value_type (arg1)))
arg2 = cast_to_fixed (value_type (arg1), arg2);
else if (ada_is_fixed_point_type (value_type (arg2)))
error
if (noside == EVAL_SKIP)
goto nosideret;
+ else if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ if (type_arg == NULL)
+ type_arg = value_type (arg1);
+
+ if (ada_is_constrained_packed_array_type (type_arg))
+ type_arg = decode_constrained_packed_array_type (type_arg);
+
+ if (!discrete_type_p (type_arg))
+ {
+ switch (op)
+ {
+ default: /* Should never happen. */
+ error (_("unexpected attribute encountered"));
+ case OP_ATR_FIRST:
+ case OP_ATR_LAST:
+ type_arg = ada_index_type (type_arg, tem,
+ ada_attribute_name (op));
+ break;
+ case OP_ATR_LENGTH:
+ type_arg = builtin_type (exp->gdbarch)->builtin_int;
+ break;
+ }
+ }
- if (type_arg == NULL)
+ return value_zero (type_arg, not_lval);
+ }
+ else if (type_arg == NULL)
{
arg1 = ada_coerce_ref (arg1);
type = builtin_type (exp->gdbarch)->builtin_int;
}
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return allocate_value (type);
-
switch (op)
{
default: /* Should never happen. */
type = builtin_type (exp->gdbarch)->builtin_int;
}
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return allocate_value (type);
-
switch (op)
{
default:
/* The following exception support info structure describes how to
implement exception catchpoints with the latest version of the
- Ada runtime (as of 2007-03-06). */
+ Ada runtime (as of 2019-08-??). */
static const struct exception_support_info default_exception_support_info =
+{
+ "__gnat_debug_raise_exception", /* catch_exception_sym */
+ "__gnat_unhandled_exception", /* catch_exception_unhandled_sym */
+ "__gnat_debug_raise_assert_failure", /* catch_assert_sym */
+ "__gnat_begin_handler_v1", /* catch_handlers_sym */
+ ada_unhandled_exception_name_addr
+};
+
+/* The following exception support info structure describes how to
+ implement exception catchpoints with an earlier version of the
+ Ada runtime (as of 2007-03-06) using v0 of the EH ABI. */
+
+static const struct exception_support_info exception_support_info_v0 =
{
"__gnat_debug_raise_exception", /* catch_exception_sym */
"__gnat_unhandled_exception", /* catch_exception_unhandled_sym */
/* Make sure that the symbol we found corresponds to a function. */
if (SYMBOL_CLASS (sym) != LOC_BLOCK)
- error (_("Symbol \"%s\" is not a function (class = %d)"),
- SYMBOL_LINKAGE_NAME (sym), SYMBOL_CLASS (sym));
+ {
+ error (_("Symbol \"%s\" is not a function (class = %d)"),
+ SYMBOL_LINKAGE_NAME (sym), SYMBOL_CLASS (sym));
+ return 0;
+ }
+
+ sym = standard_lookup (einfo->catch_handlers_sym, NULL, VAR_DOMAIN);
+ if (sym == NULL)
+ {
+ struct bound_minimal_symbol msym
+ = lookup_minimal_symbol (einfo->catch_handlers_sym, NULL, NULL);
+
+ if (msym.minsym && MSYMBOL_TYPE (msym.minsym) != mst_solib_trampoline)
+ error (_("Your Ada runtime appears to be missing some debugging "
+ "information.\nCannot insert Ada exception catchpoint "
+ "in this configuration."));
+
+ return 0;
+ }
+
+ /* Make sure that the symbol we found corresponds to a function. */
+
+ if (SYMBOL_CLASS (sym) != LOC_BLOCK)
+ {
+ error (_("Symbol \"%s\" is not a function (class = %d)"),
+ SYMBOL_LINKAGE_NAME (sym), SYMBOL_CLASS (sym));
+ return 0;
+ }
return 1;
}
return;
}
+ /* Try the v0 exception suport info. */
+ if (ada_has_this_exception_support (&exception_support_info_v0))
+ {
+ data->exception_info = &exception_support_info_v0;
+ return;
+ }
+
/* Try our fallback exception suport info. */
if (ada_has_this_exception_support (&exception_support_info_fallback))
{
{
public:
ada_catchpoint_location (breakpoint *owner)
- : bp_location (owner)
+ : bp_location (owner, bp_loc_software_breakpoint)
{}
/* The condition that checks whether the exception that was raised
create_excep_cond_exprs (struct ada_catchpoint *c,
enum ada_exception_catchpoint_kind ex)
{
- struct bp_location *bl;
-
/* Nothing to do if there's no specific exception to catch. */
if (c->excep_string.empty ())
return;
if (c->loc == NULL)
return;
- /* Compute the condition expression in text form, from the specific
- expection we want to catch. */
- std::string cond_string
- = ada_exception_catchpoint_cond_string (c->excep_string.c_str (), ex);
+ /* We have to compute the expression once for each program space,
+ because the expression may hold the addresses of multiple symbols
+ in some cases. */
+ std::multimap<program_space *, struct bp_location *> loc_map;
+ for (bp_location *bl = c->loc; bl != NULL; bl = bl->next)
+ loc_map.emplace (bl->pspace, bl);
+
+ scoped_restore_current_program_space save_pspace;
- /* Iterate over all the catchpoint's locations, and parse an
- expression for each. */
- for (bl = c->loc; bl != NULL; bl = bl->next)
+ std::string cond_string;
+ program_space *last_ps = nullptr;
+ for (auto iter : loc_map)
{
struct ada_catchpoint_location *ada_loc
- = (struct ada_catchpoint_location *) bl;
+ = (struct ada_catchpoint_location *) iter.second;
+
+ if (ada_loc->pspace != last_ps)
+ {
+ last_ps = ada_loc->pspace;
+ set_current_program_space (last_ps);
+
+ /* Compute the condition expression in text form, from the
+ specific expection we want to catch. */
+ cond_string
+ = ada_exception_catchpoint_cond_string (c->excep_string.c_str (),
+ ex);
+ }
+
expression_up exp;
- if (!bl->shlib_disabled)
+ if (!ada_loc->shlib_disabled)
{
const char *s;
s = cond_string.c_str ();
try
{
- exp = parse_exp_1 (&s, bl->address,
- block_for_pc (bl->address),
+ exp = parse_exp_1 (&s, ada_loc->address,
+ block_for_pc (ada_loc->address),
0);
}
catch (const gdb_exception_error &e)
uiout->text (b->disposition == disp_del
? "\nTemporary catchpoint " : "\nCatchpoint ");
- uiout->field_int ("bkptno", b->number);
+ uiout->field_signed ("bkptno", b->number);
uiout->text (", ");
/* ada_exception_name_addr relies on the selected frame being the
struct value_print_options opts;
get_user_print_options (&opts);
+
if (opts.addressprint)
- {
- annotate_field (4);
- uiout->field_core_addr ("addr", b->loc->gdbarch, b->loc->address);
- }
+ uiout->field_skip ("addr");
annotate_field (5);
- *last_loc = b->loc;
switch (ex)
{
case ada_catch_exception:
uiout->text (b->disposition == disp_del ? _("Temporary catchpoint ")
: _("Catchpoint "));
- uiout->field_int ("bkptno", b->number);
+ uiout->field_signed ("bkptno", b->number);
uiout->text (": ");
switch (ex)
static struct breakpoint_ops catch_handlers_breakpoint_ops;
+/* See ada-lang.h. */
+
+bool
+is_ada_exception_catchpoint (breakpoint *bp)
+{
+ return (bp->ops == &catch_exception_breakpoint_ops
+ || bp->ops == &catch_exception_unhandled_breakpoint_ops
+ || bp->ops == &catch_assert_breakpoint_ops
+ || bp->ops == &catch_handlers_breakpoint_ops);
+}
+
/* Split the arguments specified in a "catch exception" command.
Set EX to the appropriate catchpoint type.
Set EXCEP_STRING to the name of the specific exception if
enum ada_exception_catchpoint_kind ex)
{
int i;
- bool is_standard_exc = false;
std::string result;
+ const char *name;
if (ex == ada_catch_handlers)
{
/* For exception handlers catchpoints, the condition string does
not use the same parameter as for the other exceptions. */
- result = ("long_integer (GNAT_GCC_exception_Access"
- "(gcc_exception).all.occurrence.id)");
+ name = ("long_integer (GNAT_GCC_exception_Access"
+ "(gcc_exception).all.occurrence.id)");
}
else
- result = "long_integer (e)";
+ name = "long_integer (e)";
/* The standard exceptions are a special case. They are defined in
runtime units that have been compiled without debugging info; if
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. */
+ e.g. my_package.constraint_error.
+
+ Furthermore, in some situations a standard exception's symbol may
+ be present in more than one objfile, because the compiler may
+ choose to emit copy relocations for them. So, we have to compare
+ against all the possible addresses. */
+ /* Storage for a rewritten symbol name. */
+ std::string std_name;
for (i = 0; i < sizeof (standard_exc) / sizeof (char *); i++)
{
if (strcmp (standard_exc [i], excep_string) == 0)
{
- is_standard_exc = true;
+ std_name = std::string ("standard.") + excep_string;
+ excep_string = std_name.c_str ();
break;
}
}
- result += " = ";
-
- if (is_standard_exc)
- string_appendf (result, "long_integer (&standard.%s)", excep_string);
- else
- string_appendf (result, "long_integer (&%s)", excep_string);
+ excep_string = ada_encode (excep_string);
+ std::vector<struct bound_minimal_symbol> symbols
+ = ada_lookup_simple_minsyms (excep_string);
+ for (const bound_minimal_symbol &msym : symbols)
+ {
+ if (!result.empty ())
+ result += " or ";
+ string_appendf (result, "%s = %s", name,
+ pulongest (BMSYMBOL_VALUE_ADDRESS (msym)));
+ }
return result;
}
from_tty);
}
+/* Completion function for the Ada "catch" commands. */
+
+static void
+catch_ada_completer (struct cmd_list_element *cmd, completion_tracker &tracker,
+ const char *text, const char *word)
+{
+ std::vector<ada_exc_info> exceptions = ada_exceptions_list (NULL);
+
+ for (const ada_exc_info &info : exceptions)
+ {
+ if (startswith (info.name, word))
+ tracker.add_completion (make_unique_xstrdup (info.name));
+ }
+}
+
/* Split the arguments specified in a "catch assert" command.
ARGS contains the command's arguments (or the empty string if
ada_read_var_value (struct symbol *var, const struct block *var_block,
struct frame_info *frame)
{
- const struct block *frame_block = NULL;
- struct symbol *renaming_sym = NULL;
-
/* The only case where default_read_var_value is not sufficient
is when VAR is a renaming... */
- if (frame)
- frame_block = get_frame_block (frame, NULL);
- if (frame_block)
- renaming_sym = ada_find_renaming_symbol (var, frame_block);
- if (renaming_sym != NULL)
- return ada_read_renaming_var_value (renaming_sym, frame_block);
+ if (frame != nullptr)
+ {
+ const struct block *frame_block = get_frame_block (frame, NULL);
+ if (frame_block != nullptr && ada_is_renaming_symbol (var))
+ return ada_read_renaming_var_value (var, frame_block);
+ }
/* This is a typical case where we expect the default_read_var_value
function to work. */
default_search_name_hash,
&ada_varobj_ops,
NULL,
- NULL
+ NULL,
+ ada_is_string_type,
+ "(...)" /* la_struct_too_deep_ellipsis */
};
/* Command-list for the "set/show ada" prefix command. */
initialize_ada_catchpoint_ops ();
add_prefix_cmd ("ada", no_class, set_ada_command,
- _("Prefix command for changing Ada-specific settings"),
+ _("Prefix command for changing Ada-specific settings."),
&set_ada_list, "set ada ", 0, &setlist);
add_prefix_cmd ("ada", no_class, show_ada_command,
add_setshow_boolean_cmd ("trust-PAD-over-XVS", class_obscure,
&trust_pad_over_xvs, _("\
-Enable or disable an optimization trusting PAD types over XVS types"), _("\
-Show whether an optimization trusting PAD types over XVS types is activated"),
+Enable or disable an optimization trusting PAD types over XVS types."), _("\
+Show whether an optimization trusting PAD types over XVS types is activated."),
_("\
This is related to the encoding used by the GNAT compiler. The debugger\n\
should normally trust the contents of PAD types, but certain older versions\n\
add_setshow_boolean_cmd ("print-signatures", class_vars,
&print_signatures, _("\
Enable or disable the output of formal and return types for functions in the \
-overloads selection menu"), _("\
+overloads selection menu."), _("\
Show whether the output of formal and return types for functions in the \
-overloads selection menu is activated"),
+overloads selection menu is activated."),
NULL, NULL, NULL, &set_ada_list, &show_ada_list);
add_catch_command ("exception", _("\
Catch Ada exceptions, when raised.\n\
-Usage: catch exception [ ARG ]\n\
-\n\
+Usage: catch exception [ARG] [if CONDITION]\n\
Without any argument, stop when any Ada exception is raised.\n\
If ARG is \"unhandled\" (without the quotes), only stop when the exception\n\
being raised does not have a handler (and will therefore lead to the task's\n\
termination).\n\
Otherwise, the catchpoint only stops when the name of the exception being\n\
-raised is the same as ARG."),
+raised is the same as ARG.\n\
+CONDITION is a boolean expression that is evaluated to see whether the\n\
+exception should cause a stop."),
catch_ada_exception_command,
- NULL,
+ catch_ada_completer,
CATCH_PERMANENT,
CATCH_TEMPORARY);
add_catch_command ("handlers", _("\
Catch Ada exceptions, when handled.\n\
-With an argument, catch only exceptions with the given name."),
+Usage: catch handlers [ARG] [if CONDITION]\n\
+Without any argument, stop when any Ada exception is handled.\n\
+With an argument, catch only exceptions with the given name.\n\
+CONDITION is a boolean expression that is evaluated to see whether the\n\
+exception should cause a stop."),
catch_ada_handlers_command,
- NULL,
+ catch_ada_completer,
CATCH_PERMANENT,
CATCH_TEMPORARY);
add_catch_command ("assert", _("\
Catch failed Ada assertions, when raised.\n\
-With an argument, catch only exceptions with the given name."),
+Usage: catch assert [if CONDITION]\n\
+CONDITION is a boolean expression that is evaluated to see whether the\n\
+exception should cause a stop."),
catch_assert_command,
NULL,
CATCH_PERMANENT,
add_info ("exceptions", info_exceptions_command,
_("\
List all Ada exception names.\n\
+Usage: info exceptions [REGEXP]\n\
If a regular expression is passed as an argument, only those matching\n\
the regular expression are listed."));
0/*allow-unknown*/, &maintenance_set_cmdlist);
add_prefix_cmd ("ada", class_maintenance, maint_show_ada_cmd,
- _("Show Ada maintenance-related variables"),
+ _("Show Ada maintenance-related variables."),
&maint_show_ada_cmdlist, "maintenance show ada ",
0/*allow-unknown*/, &maintenance_show_cmdlist);
gdb::observers::new_objfile.attach (ada_new_objfile_observer);
gdb::observers::free_objfile.attach (ada_free_objfile_observer);
gdb::observers::inferior_exit.attach (ada_inferior_exit);
-
- /* Setup various context-specific data. */
- ada_inferior_data
- = register_inferior_data_with_cleanup (NULL, ada_inferior_data_cleanup);
- ada_pspace_data_handle
- = register_program_space_data_with_cleanup (NULL, ada_pspace_data_cleanup);
}