#include "macroscope.h"
#include "parser-defs.h"
+#include "completer.h"
/* Forward declarations for local functions. */
SYMBOL_SLOT_FOUND
};
+struct symbol_cache_slot
+{
+ enum symbol_cache_slot_state state;
+
+ /* The objfile that was current when the symbol was looked up.
+ This is only needed for global blocks, but for simplicity's sake
+ we allocate the space for both. If data shows the extra space used
+ for static blocks is a problem, we can split things up then.
+
+ Global blocks need cache lookup to include the objfile context because
+ we need to account for gdbarch_iterate_over_objfiles_in_search_order
+ which can traverse objfiles in, effectively, any order, depending on
+ the current objfile, thus affecting which symbol is found. Normally,
+ only the current objfile is searched first, and then the rest are
+ searched in recorded order; but putting cache lookup inside
+ gdbarch_iterate_over_objfiles_in_search_order would be awkward.
+ Instead we just make the current objfile part of the context of
+ cache lookup. This means we can record the same symbol multiple times,
+ each with a different "current objfile" that was in effect when the
+ lookup was saved in the cache, but cache space is pretty cheap. */
+ const struct objfile *objfile_context;
+
+ union
+ {
+ struct symbol *found;
+ struct
+ {
+ char *name;
+ domain_enum domain;
+ } not_found;
+ } value;
+};
+
/* Symbols don't specify global vs static block.
So keep them in separate caches. */
on which to decide. */
unsigned int size;
- struct symbol_cache_slot
- {
- enum symbol_cache_slot_state state;
-
- /* The objfile that was current when the symbol was looked up.
- This is only needed for global blocks, but for simplicity's sake
- we allocate the space for both. If data shows the extra space used
- for static blocks is a problem, we can split things up then.
-
- Global blocks need cache lookup to include the objfile context because
- we need to account for gdbarch_iterate_over_objfiles_in_search_order
- which can traverse objfiles in, effectively, any order, depending on
- the current objfile, thus affecting which symbol is found. Normally,
- only the current objfile is searched first, and then the rest are
- searched in recorded order; but putting cache lookup inside
- gdbarch_iterate_over_objfiles_in_search_order would be awkward.
- Instead we just make the current objfile part of the context of
- cache lookup. This means we can record the same symbol multiple times,
- each with a different "current objfile" that was in effect when the
- lookup was saved in the cache, but cache space is pretty cheap. */
- const struct objfile *objfile_context;
-
- union
- {
- struct symbol *found;
- struct
- {
- char *name;
- domain_enum domain;
- } not_found;
- } value;
- } symbols[1];
+ struct symbol_cache_slot symbols[1];
};
/* The symbol cache.
|| (newname && strcmp (field_name, newname) == 0);
if (!is_destructor)
- is_destructor = (strncmp (physname, "__dt", 4) == 0);
+ is_destructor = (startswith (physname, "__dt"));
if (is_destructor || is_full_physname_constructor)
{
if (name != NULL)
hash += htab_hash_string (name);
- hash += domain;
+ /* Because of symbol_matches_domain we need VAR_DOMAIN and STRUCT_DOMAIN
+ to map to the same slot. */
+ if (domain == STRUCT_DOMAIN)
+ hash += VAR_DOMAIN * 7;
+ else
+ hash += domain * 7;
return hash;
}
The result is the symbol if found, SYMBOL_LOOKUP_FAILED if a previous lookup
failed (and thus this one will too), or NULL if the symbol is not present
in the cache.
- *BSC_PTR, *SLOT_PTR are set to the cache and slot of the symbol, whether
- found or not found. */
+ If the symbol is not present in the cache, then *BSC_PTR and *SLOT_PTR are
+ set to the cache and slot of the symbol to save the result of a full lookup
+ attempt. */
static struct symbol *
symbol_cache_lookup (struct symbol_cache *cache,
hash = hash_symbol_entry (objfile_context, name, domain);
slot = bsc->symbols + hash % bsc->size;
- *bsc_ptr = bsc;
- *slot_ptr = slot;
if (eq_symbol_entry (slot, objfile_context, name, domain))
{
return slot->value.found;
}
+ /* Symbol is not present in the cache. */
+
+ *bsc_ptr = bsc;
+ *slot_ptr = slot;
+
if (symbol_lookup_debug)
{
fprintf_unfiltered (gdb_stdlog,
case SYMBOL_SLOT_UNUSED:
break;
case SYMBOL_SLOT_NOT_FOUND:
- printf_filtered (" [%-4u] = %s, %s (not found)\n", i,
+ printf_filtered (" [%4u] = %s, %s %s (not found)\n", i,
host_address_to_string (slot->objfile_context),
- slot->value.not_found.name);
+ slot->value.not_found.name,
+ domain_name (slot->value.not_found.domain));
break;
case SYMBOL_SLOT_FOUND:
- printf_filtered (" [%-4u] = %s, %s\n", i,
+ printf_filtered (" [%4u] = %s, %s %s\n", i,
host_address_to_string (slot->objfile_context),
- SYMBOL_PRINT_NAME (slot->value.found));
+ SYMBOL_PRINT_NAME (slot->value.found),
+ domain_name (SYMBOL_DOMAIN (slot->value.found)));
break;
}
}
int i;
/* The type may be a stub. */
- CHECK_TYPEDEF (type);
+ type = check_typedef (type);
for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
{
/* I'm not really sure that type of this can ever
be typedefed; just be safe. */
- CHECK_TYPEDEF (t);
+ t = check_typedef (t);
if (TYPE_CODE (t) == TYPE_CODE_PTR
|| TYPE_CODE (t) == TYPE_CODE_REF)
t = TYPE_TARGET_TYPE (t);
bv = COMPUNIT_BLOCKVECTOR (cust);
block = BLOCKVECTOR_BLOCK (bv, block_index);
- sym = block_lookup_symbol (block, name, STRUCT_DOMAIN);
- if (!sym)
+ sym = block_find_symbol (block, name, STRUCT_DOMAIN,
+ block_find_non_opaque_type, NULL);
+ if (sym == NULL)
error_in_psymtab_expansion (block_index, name, cust);
+ gdb_assert (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)));
+ return SYMBOL_TYPE (sym);
+}
- if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
- return SYMBOL_TYPE (sym);
+/* Subroutine of basic_lookup_transparent_type to simplify it.
+ Look up the non-opaque definition of NAME in BLOCK_INDEX of OBJFILE.
+ BLOCK_INDEX is either GLOBAL_BLOCK or STATIC_BLOCK. */
+
+static struct type *
+basic_lookup_transparent_type_1 (struct objfile *objfile, int block_index,
+ const char *name)
+{
+ const struct compunit_symtab *cust;
+ const struct blockvector *bv;
+ const struct block *block;
+ const struct symbol *sym;
+
+ ALL_OBJFILE_COMPUNITS (objfile, cust)
+ {
+ bv = COMPUNIT_BLOCKVECTOR (cust);
+ block = BLOCKVECTOR_BLOCK (bv, block_index);
+ sym = block_find_symbol (block, name, STRUCT_DOMAIN,
+ block_find_non_opaque_type, NULL);
+ if (sym != NULL)
+ {
+ gdb_assert (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)));
+ return SYMBOL_TYPE (sym);
+ }
+ }
return NULL;
}
ALL_OBJFILES (objfile)
{
- ALL_OBJFILE_COMPUNITS (objfile, cust)
- {
- bv = COMPUNIT_BLOCKVECTOR (cust);
- block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- sym = block_lookup_symbol (block, name, STRUCT_DOMAIN);
- if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
- {
- return SYMBOL_TYPE (sym);
- }
- }
+ t = basic_lookup_transparent_type_1 (objfile, GLOBAL_BLOCK, name);
+ if (t)
+ return t;
}
ALL_OBJFILES (objfile)
ALL_OBJFILES (objfile)
{
- ALL_OBJFILE_COMPUNITS (objfile, cust)
- {
- bv = COMPUNIT_BLOCKVECTOR (cust);
- block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- sym = block_lookup_symbol (block, name, STRUCT_DOMAIN);
- if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
- {
- return SYMBOL_TYPE (sym);
- }
- }
+ t = basic_lookup_transparent_type_1 (objfile, STATIC_BLOCK, name);
+ if (t)
+ return t;
}
ALL_OBJFILES (objfile)
/* Given a function symbol SYM, find the symtab and line for the start
of the function.
If the argument FUNFIRSTLINE is nonzero, we want the first line
- of real code inside the function. */
+ of real code inside the function.
+ This function should return SALs matching those from minsym_found,
+ otherwise false multiple-locations breakpoints could be placed. */
struct symtab_and_line
find_function_start_sal (struct symbol *sym, int funfirstline)
section = SYMBOL_OBJ_SECTION (symbol_objfile (sym), sym);
sal = find_pc_sect_line (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), section, 0);
+ if (funfirstline && sal.symtab != NULL
+ && (COMPUNIT_LOCATIONS_VALID (SYMTAB_COMPUNIT (sal.symtab))
+ || SYMTAB_LANGUAGE (sal.symtab) == language_asm))
+ {
+ sal.pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+ return sal;
+ }
+
/* We always should have a line for the function start address.
If we don't, something is odd. Create a plain SAL refering
just the PC and hope that skip_prologue_sal (if requested)
operator_chars (const char *p, const char **end)
{
*end = "";
- if (strncmp (p, "operator", 8))
+ if (!startswith (p, "operator"))
return *end;
p += 8;
completion_list_add_name \
(MSYMBOL_NATURAL_NAME (symbol), (sym_text), (len), (text), (word))
+/* Tracker for how many unique completions have been generated. Used
+ to terminate completion list generation early if the list has grown
+ to a size so large as to be useless. This helps avoid GDB seeming
+ to lock up in the event the user requests to complete on something
+ vague that necessitates the time consuming expansion of many symbol
+ tables. */
+
+static completion_tracker_t completion_tracker;
+
/* Test to see if the symbol specified by SYMNAME (which is already
demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN
characters. If so, add it to the current completion list. */
of matches. Note that the name is moved to freshly malloc'd space. */
{
- char *new;
+ char *newobj;
+ enum maybe_add_completion_enum add_status;
if (word == sym_text)
{
- new = xmalloc (strlen (symname) + 5);
- strcpy (new, symname);
+ newobj = xmalloc (strlen (symname) + 5);
+ strcpy (newobj, symname);
}
else if (word > sym_text)
{
/* Return some portion of symname. */
- new = xmalloc (strlen (symname) + 5);
- strcpy (new, symname + (word - sym_text));
+ newobj = xmalloc (strlen (symname) + 5);
+ strcpy (newobj, symname + (word - sym_text));
}
else
{
/* Return some of SYM_TEXT plus symname. */
- new = xmalloc (strlen (symname) + (sym_text - word) + 5);
- strncpy (new, word, sym_text - word);
- new[sym_text - word] = '\0';
- strcat (new, symname);
+ newobj = xmalloc (strlen (symname) + (sym_text - word) + 5);
+ strncpy (newobj, word, sym_text - word);
+ newobj[sym_text - word] = '\0';
+ strcat (newobj, symname);
}
- VEC_safe_push (char_ptr, return_val, new);
+ add_status = maybe_add_completion (completion_tracker, newobj);
+
+ switch (add_status)
+ {
+ case MAYBE_ADD_COMPLETION_OK:
+ VEC_safe_push (char_ptr, return_val, newobj);
+ break;
+ case MAYBE_ADD_COMPLETION_OK_MAX_REACHED:
+ VEC_safe_push (char_ptr, return_val, newobj);
+ throw_max_completions_reached_error ();
+ case MAYBE_ADD_COMPLETION_MAX_REACHED:
+ xfree (newobj);
+ throw_max_completions_reached_error ();
+ case MAYBE_ADD_COMPLETION_DUPLICATE:
+ xfree (newobj);
+ break;
+ }
}
}
datum->code);
}
-VEC (char_ptr) *
-default_make_symbol_completion_list_break_on (const char *text,
- const char *word,
- const char *break_on,
- enum type_code code)
+static void
+default_make_symbol_completion_list_break_on_1 (const char *text,
+ const char *word,
+ const char *break_on,
+ enum type_code code)
{
/* Problem: All of the symbols have to be copied because readline
frees them. I'm not going to worry about this; hopefully there
/* Length of sym_text. */
int sym_text_len;
struct add_name_data datum;
- struct cleanup *back_to;
+ struct cleanup *cleanups;
/* Now look for the symbol we are supposed to complete on. */
{
/* A double-quoted string is never a symbol, nor does it make sense
to complete it any other way. */
{
- return NULL;
+ return;
}
else
{
}
gdb_assert (sym_text[sym_text_len] == '\0' || sym_text[sym_text_len] == '(');
- return_val = NULL;
- back_to = make_cleanup (do_free_completion_list, &return_val);
+ completion_tracker = new_completion_tracker ();
+ cleanups = make_cleanup_free_completion_tracker (&completion_tracker);
datum.sym_text = sym_text;
datum.sym_text_len = sym_text_len;
macro_for_each (macro_user_macros, add_macro_name, &datum);
}
+ do_cleanups (cleanups);
+}
+
+VEC (char_ptr) *
+default_make_symbol_completion_list_break_on (const char *text,
+ const char *word,
+ const char *break_on,
+ enum type_code code)
+{
+ struct cleanup *back_to;
+
+ return_val = NULL;
+ back_to = make_cleanup (do_free_completion_list, &return_val);
+
+ TRY
+ {
+ default_make_symbol_completion_list_break_on_1 (text, word,
+ break_on, code);
+ }
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ if (except.error != MAX_COMPLETIONS_REACHED_ERROR)
+ throw_exception (except);
+ }
+ END_CATCH
+
discard_cleanups (back_to);
- return (return_val);
+ return return_val;
}
VEC (char_ptr) *
add_filename_to_list (const char *fname, const char *text, const char *word,
VEC (char_ptr) **list)
{
- char *new;
+ char *newobj;
size_t fnlen = strlen (fname);
if (word == text)
{
/* Return exactly fname. */
- new = xmalloc (fnlen + 5);
- strcpy (new, fname);
+ newobj = xmalloc (fnlen + 5);
+ strcpy (newobj, fname);
}
else if (word > text)
{
/* Return some portion of fname. */
- new = xmalloc (fnlen + 5);
- strcpy (new, fname + (word - text));
+ newobj = xmalloc (fnlen + 5);
+ strcpy (newobj, fname + (word - text));
}
else
{
/* Return some of TEXT plus fname. */
- new = xmalloc (fnlen + (text - word) + 5);
- strncpy (new, word, text - word);
- new[text - word] = '\0';
- strcat (new, fname);
+ newobj = xmalloc (fnlen + (text - word) + 5);
+ strncpy (newobj, word, text - word);
+ newobj[text - word] = '\0';
+ strcat (newobj, fname);
}
- VEC_safe_push (char_ptr, *list, new);
+ VEC_safe_push (char_ptr, *list, newobj);
}
static int
return 0;
for (i = 0; i < ARRAY_SIZE (arm_idents); i++)
- if (strncmp (producer, arm_idents[i], strlen (arm_idents[i])) == 0)
+ if (startswith (producer, arm_idents[i]))
return 1;
return 0;
add_com ("rbreak", class_breakpoint, rbreak_command,
_("Set a breakpoint for all functions matching REGEXP."));
- if (xdb_commands)
- {
- add_com ("lf", class_info, sources_info,
- _("Source files in the program"));
- add_com ("lg", class_info, variables_info, _("\
-All global and static variable names, or those matching REGEXP."));
- }
-
add_setshow_enum_cmd ("multiple-symbols", no_class,
multiple_symbols_modes, &multiple_symbols_mode,
_("\