#include "source.h"
#include "observer.h"
#include "vec.h"
+#include "stack.h"
+
+#include "psymtab.h"
/* Define whether or not the C operator '/' truncates towards zero for
differently signed operands (truncation direction is undefined in C).
static struct ada_symbol_info *defns_collected (struct obstack *, int);
-static struct partial_symbol *ada_lookup_partial_symbol (struct partial_symtab
- *, const char *, int,
- domain_enum, int);
-
static struct value *resolve_subexp (struct expression **, int *, int,
struct type *);
/* Language Selection */
/* If the main program is in Ada, return language_ada, otherwise return LANG
- (the main program is in Ada iif the adainit symbol is found).
-
- MAIN_PST is not used. */
+ (the main program is in Ada iif the adainit symbol is found). */
enum language
-ada_update_initial_language (enum language lang,
- struct partial_symtab *main_pst)
+ada_update_initial_language (enum language lang)
{
if (lookup_minimal_symbol ("adainit", (const char *) NULL,
(struct objfile *) NULL) != NULL)
return (struct ada_symbol_info *) obstack_base (obstackp);
}
-/* Look, in partial_symtab PST, for symbol NAME in given namespace.
- Check the global symbols if GLOBAL, the static symbols if not.
- Do wild-card match if WILD. */
-
-static struct partial_symbol *
-ada_lookup_partial_symbol (struct partial_symtab *pst, const char *name,
- int global, domain_enum namespace, int wild)
-{
- struct partial_symbol **start;
- int name_len = strlen (name);
- int length = (global ? pst->n_global_syms : pst->n_static_syms);
- int i;
-
- if (length == 0)
- {
- return (NULL);
- }
-
- start = (global ?
- pst->objfile->global_psymbols.list + pst->globals_offset :
- pst->objfile->static_psymbols.list + pst->statics_offset);
-
- if (wild)
- {
- for (i = 0; i < length; i += 1)
- {
- struct partial_symbol *psym = start[i];
-
- if (symbol_matches_domain (SYMBOL_LANGUAGE (psym),
- SYMBOL_DOMAIN (psym), namespace)
- && wild_match (name, name_len, SYMBOL_LINKAGE_NAME (psym)))
- return psym;
- }
- return NULL;
- }
- else
- {
- if (global)
- {
- int U;
- i = 0;
- U = length - 1;
- while (U - i > 4)
- {
- int M = (U + i) >> 1;
- struct partial_symbol *psym = start[M];
- if (SYMBOL_LINKAGE_NAME (psym)[0] < name[0])
- i = M + 1;
- else if (SYMBOL_LINKAGE_NAME (psym)[0] > name[0])
- U = M - 1;
- else if (strcmp (SYMBOL_LINKAGE_NAME (psym), name) < 0)
- i = M + 1;
- else
- U = M;
- }
- }
- else
- i = 0;
-
- while (i < length)
- {
- struct partial_symbol *psym = start[i];
-
- if (symbol_matches_domain (SYMBOL_LANGUAGE (psym),
- SYMBOL_DOMAIN (psym), namespace))
- {
- int cmp = strncmp (name, SYMBOL_LINKAGE_NAME (psym), name_len);
-
- if (cmp < 0)
- {
- if (global)
- break;
- }
- else if (cmp == 0
- && is_name_suffix (SYMBOL_LINKAGE_NAME (psym)
- + name_len))
- return psym;
- }
- i += 1;
- }
-
- if (global)
- {
- int U;
- i = 0;
- U = length - 1;
- while (U - i > 4)
- {
- int M = (U + i) >> 1;
- struct partial_symbol *psym = start[M];
- if (SYMBOL_LINKAGE_NAME (psym)[0] < '_')
- i = M + 1;
- else if (SYMBOL_LINKAGE_NAME (psym)[0] > '_')
- U = M - 1;
- else if (strcmp (SYMBOL_LINKAGE_NAME (psym), "_ada_") < 0)
- i = M + 1;
- else
- U = M;
- }
- }
- else
- i = 0;
-
- while (i < length)
- {
- struct partial_symbol *psym = start[i];
-
- if (symbol_matches_domain (SYMBOL_LANGUAGE (psym),
- SYMBOL_DOMAIN (psym), namespace))
- {
- int cmp;
-
- cmp = (int) '_' - (int) SYMBOL_LINKAGE_NAME (psym)[0];
- if (cmp == 0)
- {
- cmp = strncmp ("_ada_", SYMBOL_LINKAGE_NAME (psym), 5);
- if (cmp == 0)
- cmp = strncmp (name, SYMBOL_LINKAGE_NAME (psym) + 5,
- name_len);
- }
-
- if (cmp < 0)
- {
- if (global)
- break;
- }
- else if (cmp == 0
- && is_name_suffix (SYMBOL_LINKAGE_NAME (psym)
- + name_len + 5))
- return psym;
- }
- i += 1;
- }
- }
- return NULL;
-}
-
/* 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
add_symbols_from_enclosing_procs (obstackp, name, domain, wild_match);
}
+/* An object of this type is used as the user_data argument when
+ calling the map_ada_symtabs method. */
+
+struct ada_psym_data
+{
+ struct obstack *obstackp;
+ const char *name;
+ domain_enum domain;
+ int global;
+ int wild_match;
+};
+
+/* Callback function for map_ada_symtabs. */
+
+static void
+ada_add_psyms (struct objfile *objfile, struct symtab *s, void *user_data)
+{
+ struct ada_psym_data *data = user_data;
+ const int block_kind = data->global ? GLOBAL_BLOCK : STATIC_BLOCK;
+ ada_add_block_symbols (data->obstackp,
+ BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), block_kind),
+ data->name, data->domain, objfile, data->wild_match);
+}
+
/* 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. */
static void
ada_add_non_local_symbols (struct obstack *obstackp, const char *name,
domain_enum domain, int global,
- int wild_match)
+ int is_wild_match)
{
struct objfile *objfile;
- struct partial_symtab *ps;
+ struct ada_psym_data data;
- ALL_PSYMTABS (objfile, ps)
- {
- QUIT;
- if (ps->readin
- || ada_lookup_partial_symbol (ps, name, global, domain, wild_match))
- {
- struct symtab *s = PSYMTAB_TO_SYMTAB (ps);
- const int block_kind = global ? GLOBAL_BLOCK : STATIC_BLOCK;
+ data.obstackp = obstackp;
+ data.name = name;
+ data.domain = domain;
+ data.global = global;
+ data.wild_match = is_wild_match;
- if (s == NULL || !s->primary)
- continue;
- ada_add_block_symbols (obstackp,
- BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), block_kind),
- name, domain, objfile, wild_match);
- }
+ ALL_OBJFILES (objfile)
+ {
+ if (objfile->sf)
+ objfile->sf->qf->map_ada_symtabs (objfile, wild_match, is_name_suffix,
+ ada_add_psyms, name,
+ global, domain,
+ is_wild_match, &data);
}
}
static struct symbol *
ada_lookup_symbol_nonlocal (const char *name,
- const char *linkage_name,
const struct block *block,
const domain_enum domain)
{
- if (linkage_name == NULL)
- linkage_name = name;
- return ada_lookup_symbol (linkage_name, block_static_block (block), domain,
- NULL);
+ return ada_lookup_symbol (name, block_static_block (block), domain, NULL);
}
VEC_safe_push (char_ptr, *sv, completion);
}
+/* An object of this type is passed as the user_data argument to the
+ map_partial_symbol_names method. */
+struct add_partial_datum
+{
+ VEC(char_ptr) **completions;
+ char *text;
+ int text_len;
+ char *text0;
+ char *word;
+ int wild_match;
+ int encoded;
+};
+
+/* A callback for map_partial_symbol_names. */
+static void
+ada_add_partial_symbol_completions (const char *name, void *user_data)
+{
+ struct add_partial_datum *data = user_data;
+ symbol_completion_add (data->completions, name,
+ data->text, data->text_len, data->text0, data->word,
+ data->wild_match, data->encoded);
+}
+
/* Return a list of possible symbol names completing TEXT0. The list
is NULL terminated. WORD is the entire command on which completion
is made. */
VEC(char_ptr) *completions = VEC_alloc (char_ptr, 128);
struct symbol *sym;
struct symtab *s;
- struct partial_symtab *ps;
struct minimal_symbol *msymbol;
struct objfile *objfile;
struct block *b, *surrounding_static_block = 0;
}
/* First, look at the partial symtab symbols. */
- ALL_PSYMTABS (objfile, ps)
{
- struct partial_symbol **psym;
-
- /* If the psymtab's been read in we'll get it when we search
- through the blockvector. */
- if (ps->readin)
- continue;
-
- for (psym = objfile->global_psymbols.list + ps->globals_offset;
- psym < (objfile->global_psymbols.list + ps->globals_offset
- + ps->n_global_syms); psym++)
- {
- QUIT;
- symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (*psym),
- text, text_len, text0, word,
- wild_match, encoded);
- }
-
- for (psym = objfile->static_psymbols.list + ps->statics_offset;
- psym < (objfile->static_psymbols.list + ps->statics_offset
- + ps->n_static_syms); psym++)
- {
- QUIT;
- symbol_completion_add (&completions, SYMBOL_LINKAGE_NAME (*psym),
- text, text_len, text0, word,
- wild_match, encoded);
- }
+ struct add_partial_datum data;
+
+ data.completions = &completions;
+ data.text = text;
+ data.text_len = text_len;
+ data.text0 = text0;
+ data.word = word;
+ data.wild_match = wild_match;
+ data.encoded = encoded;
+ map_partial_symbol_names (ada_add_partial_symbol_completions, &data);
}
/* At this point scan through the misc symbol vectors and add each
}
else
{
- TYPE_FIELD_TYPE (rtype, f) = TYPE_FIELD_TYPE (type, f);
+ struct type *field_type = TYPE_FIELD_TYPE (type, f);
+
+ TYPE_FIELD_TYPE (rtype, f) = field_type;
TYPE_FIELD_NAME (rtype, f) = TYPE_FIELD_NAME (type, f);
if (TYPE_FIELD_BITSIZE (type, f) > 0)
bit_incr = fld_bit_len =
TYPE_FIELD_BITSIZE (rtype, f) = TYPE_FIELD_BITSIZE (type, f);
else
bit_incr = fld_bit_len =
- TYPE_LENGTH (TYPE_FIELD_TYPE (type, f)) * TARGET_CHAR_BIT;
+ TYPE_LENGTH (ada_check_typedef (field_type)) * TARGET_CHAR_BIT;
}
if (off + fld_bit_len > bit_len)
bit_len = off + fld_bit_len;
value_address (val),
val);
}
-
-/* A value representing VAL, but with a standard (static-sized) type
- chosen to approximate the real type of VAL as well as possible, but
- without consulting any runtime values. For Ada dynamic-sized
- types, therefore, the type of the result is likely to be inaccurate. */
-
-static struct value *
-ada_to_static_fixed_value (struct value *val)
-{
- struct type *type =
- to_static_fixed_type (static_unwrap_type (value_type (val)));
- if (type == value_type (val))
- return val;
- else
- return coerce_unspec_val_to_type (val, type);
-}
\f
/* Attributes */
return 0;
}
+/* The compiler sometimes provides a parallel XVS type for a given
+ PAD type. Normally, it is safe to follow the PAD type directly,
+ but older versions of the compiler have a bug that causes the offset
+ of its "F" field to be wrong. Following that field in that case
+ would lead to incorrect results, but this can be worked around
+ by ignoring the PAD type and using the associated XVS type instead.
+
+ Set to True if the debugger should trust the contents of PAD types.
+ Otherwise, ignore the PAD type if there is a parallel XVS type. */
+static int trust_pad_over_xvs = 1;
/* True if TYPE is a struct type introduced by the compiler to force the
alignment of a value. Such types have a single field with a
{
type = ada_check_typedef (type);
- /* If we can find a parallel XVS type, then the XVS type should
- be used instead of this type. And hence, this is not an aligner
- type. */
- if (ada_find_parallel_type (type, "___XVS") != NULL)
+ if (!trust_pad_over_xvs && ada_find_parallel_type (type, "___XVS") != NULL)
return 0;
return (TYPE_CODE (type) == TYPE_CODE_STRUCT
|| TYPE_NFIELDS (real_type_namer) != 1)
return raw_type;
- raw_real_type = ada_find_any_type (TYPE_FIELD_NAME (real_type_namer, 0));
- if (raw_real_type == NULL)
- return raw_type;
- else
- return raw_real_type;
+ if (TYPE_CODE (TYPE_FIELD_TYPE (real_type_namer, 0)) != TYPE_CODE_REF)
+ {
+ /* This is an older encoding form where the base type needs to be
+ looked up by name. We prefer the newer enconding because it is
+ more efficient. */
+ raw_real_type = ada_find_any_type (TYPE_FIELD_NAME (real_type_namer, 0));
+ if (raw_real_type == NULL)
+ return raw_type;
+ else
+ return raw_real_type;
+ }
+
+ /* The field in our XVS type is a reference to the base type. */
+ return TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (real_type_namer, 0));
}
/* The type of value designated by TYPE, with all aligners removed. */
struct type *raw_real_type =
ada_check_typedef (ada_get_base_type (type));
- if (type == raw_real_type)
- return val;
+ /* If there is no parallel XVS or XVE type, then the value is
+ already unwrapped. Return it without further modification. */
+ if ((type == raw_real_type)
+ && ada_find_parallel_type (type, "___XVE") == NULL)
+ return val;
return
coerce_unspec_val_to_type
else if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
type = static_unwrap_type (SYMBOL_TYPE (exp->elts[pc + 2].symbol));
- if (ada_is_tagged_type (type, 0))
+ /* Check to see if this is a tagged type. We also need to handle
+ the case where the type is a reference to a tagged type, but
+ we have to be careful to exclude pointers to tagged types.
+ The latter should be shown as usual (as a pointer), whereas
+ a reference should mostly be transparent to the user. */
+ if (ada_is_tagged_type (type, 0)
+ || (TYPE_CODE(type) == TYPE_CODE_REF
+ && ada_is_tagged_type (TYPE_TARGET_TYPE (type), 0)))
{
/* Tagged types are a little special in the fact that the real
type is dynamic and can only be determined by inspecting the
started yet. Inform the user of these two possible causes if
applicable. */
- if (ada_update_initial_language (language_unknown, NULL) != language_ada)
+ if (ada_update_initial_language (language_unknown) != language_ada)
error (_("Unable to insert catchpoint. Is this an Ada main program?"));
/* If the symbol does not exist, then check that the program is
exception_info = NULL;
}
-/* Return the name of the function at PC, NULL if could not find it.
- This function only checks the debugging information, not the symbol
- table. */
-
-static char *
-function_name_from_pc (CORE_ADDR pc)
-{
- char *func_name;
-
- if (!find_pc_partial_function (pc, &func_name, NULL, NULL))
- return NULL;
-
- return func_name;
-}
-
/* True iff FRAME is very likely to be that of a function that is
part of the runtime system. This is all very heuristic, but is
intended to be used as advice as to what frames are uninteresting
{
struct symtab_and_line sal;
char *func_name;
+ enum language func_lang;
int i;
/* If this code does not have any debugging information (no symtab),
/* Check whether the function is a GNAT-generated entity. */
- func_name = function_name_from_pc (get_frame_address_in_block (frame));
+ find_frame_funname (frame, &func_name, &func_lang);
if (func_name == NULL)
return 1;
while (fi != NULL)
{
- const char *func_name =
- function_name_from_pc (get_frame_address_in_block (fi));
+ char *func_name;
+ enum language func_lang;
+
+ find_frame_funname (fi, &func_name, &func_lang);
if (func_name != NULL
&& strcmp (func_name, exception_info->catch_exception_sym) == 0)
break; /* We found the frame we were looking for... */
/* Provide a prototype to silence -Wmissing-prototypes. */
extern initialize_file_ftype _initialize_ada_language;
+/* Command-list for the "set/show ada" prefix command. */
+static struct cmd_list_element *set_ada_list;
+static struct cmd_list_element *show_ada_list;
+
+/* Implement the "set ada" prefix command. */
+
+static void
+set_ada_command (char *arg, int from_tty)
+{
+ printf_unfiltered (_(\
+"\"set ada\" must be followed by the name of a setting.\n"));
+ help_list (set_ada_list, "set ada ", -1, gdb_stdout);
+}
+
+/* Implement the "show ada" prefix command. */
+
+static void
+show_ada_command (char *args, int from_tty)
+{
+ cmd_show_list (show_ada_list, from_tty, "");
+}
+
void
_initialize_ada_language (void)
{
add_language (&ada_language_defn);
+ add_prefix_cmd ("ada", no_class, set_ada_command,
+ _("Prefix command for changing Ada-specfic settings"),
+ &set_ada_list, "set ada ", 0, &setlist);
+
+ add_prefix_cmd ("ada", no_class, show_ada_command,
+ _("Generic command for showing Ada-specific settings."),
+ &show_ada_list, "show ada ", 0, &showlist);
+
+ 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"),
+ _("\
+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\
+of GNAT have a bug that sometimes causes the information in the PAD type\n\
+to be incorrect. Turning this setting \"off\" allows the debugger to\n\
+work around this bug. It is always safe to turn this option \"off\", but\n\
+this incurs a slight performance penalty, so it is recommended to NOT change\n\
+this option to \"off\" unless necessary."),
+ NULL, NULL, &set_ada_list, &show_ada_list);
+
varsize_limit = 65536;
obstack_init (&symbol_list_obstack);