/* Helper routines for C++ support in GDB.
- Copyright (C) 2002-2013 Free Software Foundation, Inc.
+ Copyright (C) 2002-2015 Free Software Foundation, Inc.
Contributed by MontaVista Software.
#include "defs.h"
#include "cp-support.h"
-#include "gdb_string.h"
#include "demangle.h"
-#include "gdb_assert.h"
#include "gdbcmd.h"
#include "dictionary.h"
#include "objfiles.h"
#include "block.h"
#include "complaints.h"
#include "gdbtypes.h"
-#include "exceptions.h"
#include "expression.h"
#include "value.h"
#include "cp-abi.h"
+#include "namespace.h"
+#include <signal.h>
#include "safe-ctype.h"
const char *oload_name);
static void make_symbol_overload_list_using (const char *func_name,
- const char *namespace);
+ const char *the_namespace);
static void make_symbol_overload_list_qualified (const char *func_name);
long *len)
{
*len = strlen (string);
- return obstack_copy (obstack, string, *len);
+ return (char *) obstack_copy (obstack, string, *len);
}
/* A cleanup wrapper for cp_demangled_name_parse_free. */
int i;
char *name;
struct symbol *sym;
- volatile struct gdb_exception except;
/* Copy the symbol's name from RET_COMP and look it up
in the symbol table. */
}
sym = NULL;
- TRY_CATCH (except, RETURN_MASK_ALL)
- {
- sym = lookup_symbol (name, 0, VAR_DOMAIN, 0);
- }
- if (except.reason >= 0 && sym != NULL)
+ TRY
+ {
+ sym = lookup_symbol (name, 0, VAR_DOMAIN, 0).symbol;
+ }
+ CATCH (except, RETURN_MASK_ALL)
+ {
+ return 0;
+ }
+ END_CATCH
+
+ if (sym != NULL)
{
struct type *otype = SYMBOL_TYPE (sym);
return 0;
}
- /* If the type is a typedef, replace it. */
- if (TYPE_CODE (otype) == TYPE_CODE_TYPEDEF)
+ /* If the type is a typedef or namespace alias, replace it. */
+ if (TYPE_CODE (otype) == TYPE_CODE_TYPEDEF
+ || TYPE_CODE (otype) == TYPE_CODE_NAMESPACE)
{
long len;
int is_anon;
/* Get the real type of the typedef. */
type = check_typedef (otype);
+ /* If the symbol is a namespace and its type name is no different
+ than the name we looked up, this symbol is not a namespace
+ alias and does not need to be substituted. */
+ if (TYPE_CODE (otype) == TYPE_CODE_NAMESPACE
+ && strcmp (TYPE_NAME (type), name) == 0)
+ return 0;
+
is_anon = (TYPE_TAG_NAME (type) == NULL
&& (TYPE_CODE (type) == TYPE_CODE_ENUM
|| TYPE_CODE (type) == TYPE_CODE_STRUCT
}
buf = mem_fileopen ();
- TRY_CATCH (except, RETURN_MASK_ERROR)
+ TRY
{
type_print (type, "", buf, -1);
}
/* If type_print threw an exception, there is little point
in continuing, so just bow out gracefully. */
- if (except.reason < 0)
+ CATCH (except, RETURN_MASK_ERROR)
{
ui_file_delete (buf);
return 0;
}
+ END_CATCH
name = ui_file_obsavestring (buf, &info->obstack, &len);
ui_file_delete (buf);
{
if (d_left (comp)->type == DEMANGLE_COMPONENT_NAME)
{
- struct demangle_component new;
+ struct demangle_component newobj;
ui_file_write (buf, d_left (comp)->u.s_name.s,
d_left (comp)->u.s_name.len);
name = ui_file_obsavestring (buf, &info->obstack, &len);
- new.type = DEMANGLE_COMPONENT_NAME;
- new.u.s_name.s = name;
- new.u.s_name.len = len;
- if (inspect_type (info, &new, finder, data))
+ newobj.type = DEMANGLE_COMPONENT_NAME;
+ newobj.u.s_name.s = name;
+ newobj.u.s_name.len = len;
+ if (inspect_type (info, &newobj, finder, data))
{
char *n, *s;
long slen;
node. */
ui_file_rewind (buf);
- n = cp_comp_to_string (&new, 100);
+ n = cp_comp_to_string (&newobj, 100);
if (n == NULL)
{
/* If something went astray, abort typedef substitutions. */
if (local_name != NULL)
{
- struct symbol *sym;
- volatile struct gdb_exception except;
+ struct symbol *sym = NULL;
sym = NULL;
- TRY_CATCH (except, RETURN_MASK_ALL)
+ TRY
+ {
+ sym = lookup_symbol (local_name, 0, VAR_DOMAIN, 0).symbol;
+ }
+ CATCH (except, RETURN_MASK_ALL)
{
- sym = lookup_symbol (local_name, 0, VAR_DOMAIN, 0);
}
+ END_CATCH
+
xfree (local_name);
- if (except.reason >= 0 && sym != NULL)
+ if (sym != NULL)
{
struct type *otype = SYMBOL_TYPE (sym);
const char *new_name = (*finder) (otype, data);
struct symbol **
make_symbol_overload_list (const char *func_name,
- const char *namespace)
+ const char *the_namespace)
{
struct cleanup *old_cleanups;
const char *name;
sym_return_val_size = 100;
sym_return_val_index = 0;
- sym_return_val = xmalloc ((sym_return_val_size + 1) *
- sizeof (struct symbol *));
+ sym_return_val = XNEWVEC (struct symbol *, sym_return_val_size + 1);
sym_return_val[0] = NULL;
old_cleanups = make_cleanup (xfree, sym_return_val);
- make_symbol_overload_list_using (func_name, namespace);
+ make_symbol_overload_list_using (func_name, the_namespace);
- if (namespace[0] == '\0')
+ if (the_namespace[0] == '\0')
name = func_name;
else
{
char *concatenated_name
- = alloca (strlen (namespace) + 2 + strlen (func_name) + 1);
- strcpy (concatenated_name, namespace);
+ = (char *) alloca (strlen (the_namespace) + 2 + strlen (func_name) + 1);
+ strcpy (concatenated_name, the_namespace);
strcat (concatenated_name, "::");
strcat (concatenated_name, func_name);
name = concatenated_name;
struct block_iterator iter;
struct symbol *sym;
- for (sym = block_iter_name_first (block, name, &iter);
- sym != NULL;
- sym = block_iter_name_next (name, &iter))
+ ALL_BLOCK_SYMBOLS_WITH_NAME (block, name, iter, sym)
overload_list_add_symbol (sym, name);
}
static void
make_symbol_overload_list_namespace (const char *func_name,
- const char *namespace)
+ const char *the_namespace)
{
const char *name;
const struct block *block = NULL;
- if (namespace[0] == '\0')
+ if (the_namespace[0] == '\0')
name = func_name;
else
{
char *concatenated_name
- = alloca (strlen (namespace) + 2 + strlen (func_name) + 1);
+ = (char *) alloca (strlen (the_namespace) + 2 + strlen (func_name) + 1);
- strcpy (concatenated_name, namespace);
+ strcpy (concatenated_name, the_namespace);
strcat (concatenated_name, "::");
strcat (concatenated_name, func_name);
name = concatenated_name;
make_symbol_overload_list_adl_namespace (struct type *type,
const char *func_name)
{
- char *namespace;
+ char *the_namespace;
const char *type_name;
int i, prefix_len;
if (prefix_len != 0)
{
- namespace = alloca (prefix_len + 1);
- strncpy (namespace, type_name, prefix_len);
- namespace[prefix_len] = '\0';
+ the_namespace = (char *) alloca (prefix_len + 1);
+ strncpy (the_namespace, type_name, prefix_len);
+ the_namespace[prefix_len] = '\0';
- make_symbol_overload_list_namespace (func_name, namespace);
+ make_symbol_overload_list_namespace (func_name, the_namespace);
}
/* Check public base type */
- if (TYPE_CODE (type) == TYPE_CODE_CLASS)
+ if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
for (i = 0; i < TYPE_N_BASECLASSES (type); i++)
{
if (BASETYPE_VIA_PUBLIC (type, i))
static void
reset_directive_searched (void *data)
{
- struct using_direct *direct = data;
+ struct using_direct *direct = (struct using_direct *) data;
direct->searched = 0;
}
static void
make_symbol_overload_list_using (const char *func_name,
- const char *namespace)
+ const char *the_namespace)
{
struct using_direct *current;
const struct block *block;
if (current->alias != NULL || current->declaration != NULL)
continue;
- if (strcmp (namespace, current->import_dest) == 0)
+ if (strcmp (the_namespace, current->import_dest) == 0)
{
/* Mark this import as searched so that the recursive call
does not search it again. */
}
/* Now, add names for this namespace. */
- make_symbol_overload_list_namespace (func_name, namespace);
+ make_symbol_overload_list_namespace (func_name, the_namespace);
}
/* This does the bulk of the work of finding overloaded symbols.
static void
make_symbol_overload_list_qualified (const char *func_name)
{
- struct symtab *s;
+ struct compunit_symtab *cust;
struct objfile *objfile;
const struct block *b, *surrounding_static_block = 0;
/* Go through the symtabs and check the externs and statics for
symbols which match. */
- ALL_PRIMARY_SYMTABS (objfile, s)
+ ALL_COMPUNITS (objfile, cust)
{
QUIT;
- b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
+ b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), GLOBAL_BLOCK);
make_symbol_overload_list_block (func_name, b);
}
- ALL_PRIMARY_SYMTABS (objfile, s)
+ ALL_COMPUNITS (objfile, cust)
{
QUIT;
- b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
+ b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), STATIC_BLOCK);
/* Don't do this block twice. */
if (b == surrounding_static_block)
continue;
struct symbol * rtti_sym;
struct type * rtti_type;
- rtti_sym = lookup_symbol (name, block, STRUCT_DOMAIN, NULL);
+ /* Use VAR_DOMAIN here as NAME may be a typedef. PR 18141, 18417.
+ Classes "live" in both STRUCT_DOMAIN and VAR_DOMAIN. */
+ rtti_sym = lookup_symbol (name, block, VAR_DOMAIN, NULL).symbol;
if (rtti_sym == NULL)
{
return NULL;
}
- rtti_type = SYMBOL_TYPE (rtti_sym);
+ rtti_type = check_typedef (SYMBOL_TYPE (rtti_sym));
switch (TYPE_CODE (rtti_type))
{
- case TYPE_CODE_CLASS:
+ case TYPE_CODE_STRUCT:
break;
case TYPE_CODE_NAMESPACE:
/* chastain/2003-11-26: the symbol tables often contain fake
return rtti_type;
}
+#ifdef HAVE_WORKING_FORK
+
+/* If nonzero, attempt to catch crashes in the demangler and print
+ useful debugging information. */
+
+static int catch_demangler_crashes = 1;
+
+/* Stack context and environment for demangler crash recovery. */
+
+static SIGJMP_BUF gdb_demangle_jmp_buf;
+
+/* If nonzero, attempt to dump core from the signal handler. */
+
+static int gdb_demangle_attempt_core_dump = 1;
+
+/* Signal handler for gdb_demangle. */
+
+static void
+gdb_demangle_signal_handler (int signo)
+{
+ if (gdb_demangle_attempt_core_dump)
+ {
+ if (fork () == 0)
+ dump_core ();
+
+ gdb_demangle_attempt_core_dump = 0;
+ }
+
+ SIGLONGJMP (gdb_demangle_jmp_buf, signo);
+}
+
+#endif
+
/* A wrapper for bfd_demangle. */
char *
gdb_demangle (const char *name, int options)
{
- return bfd_demangle (NULL, name, options);
+ char *result = NULL;
+ int crash_signal = 0;
+
+#ifdef HAVE_WORKING_FORK
+#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
+ struct sigaction sa, old_sa;
+#else
+ sighandler_t ofunc;
+#endif
+ static int core_dump_allowed = -1;
+
+ if (core_dump_allowed == -1)
+ {
+ core_dump_allowed = can_dump_core (LIMIT_CUR);
+
+ if (!core_dump_allowed)
+ gdb_demangle_attempt_core_dump = 0;
+ }
+
+ if (catch_demangler_crashes)
+ {
+#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
+ sa.sa_handler = gdb_demangle_signal_handler;
+ sigemptyset (&sa.sa_mask);
+#ifdef HAVE_SIGALTSTACK
+ sa.sa_flags = SA_ONSTACK;
+#else
+ sa.sa_flags = 0;
+#endif
+ sigaction (SIGSEGV, &sa, &old_sa);
+#else
+ ofunc = signal (SIGSEGV, gdb_demangle_signal_handler);
+#endif
+
+ crash_signal = SIGSETJMP (gdb_demangle_jmp_buf);
+ }
+#endif
+
+ if (crash_signal == 0)
+ result = bfd_demangle (NULL, name, options);
+
+#ifdef HAVE_WORKING_FORK
+ if (catch_demangler_crashes)
+ {
+#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
+ sigaction (SIGSEGV, &old_sa, NULL);
+#else
+ signal (SIGSEGV, ofunc);
+#endif
+
+ if (crash_signal != 0)
+ {
+ static int error_reported = 0;
+
+ if (!error_reported)
+ {
+ char *short_msg, *long_msg;
+ struct cleanup *back_to;
+
+ short_msg = xstrprintf (_("unable to demangle '%s' "
+ "(demangler failed with signal %d)"),
+ name, crash_signal);
+ back_to = make_cleanup (xfree, short_msg);
+
+ long_msg = xstrprintf ("%s:%d: %s: %s", __FILE__, __LINE__,
+ "demangler-warning", short_msg);
+ make_cleanup (xfree, long_msg);
+
+ target_terminal_ours ();
+ begin_line ();
+ if (core_dump_allowed)
+ fprintf_unfiltered (gdb_stderr,
+ _("%s\nAttempting to dump core.\n"),
+ long_msg);
+ else
+ warn_cant_dump_core (long_msg);
+
+ demangler_warning (__FILE__, __LINE__, "%s", short_msg);
+
+ do_cleanups (back_to);
+
+ error_reported = 1;
+ }
+
+ result = NULL;
+ }
+ }
+#endif
+
+ return result;
}
/* Don't allow just "maintenance cplus". */
"by the name of a command.\n"));
help_list (maint_cplus_cmd_list,
"maintenance cplus ",
- -1, gdb_stdout);
+ all_commands, gdb_stdout);
}
/* This is a front end for cp_find_first_component, for unit testing.
return;
len = cp_find_first_component (arg);
- prefix = alloca (len + 1);
+ prefix = (char *) alloca (len + 1);
memcpy (prefix, arg, len);
prefix[len] = '\0';
Usage: info vtbl EXPRESSION\n\
Evaluate EXPRESSION and display the virtual function table for the\n\
resulting object."));
+
+#ifdef HAVE_WORKING_FORK
+ add_setshow_boolean_cmd ("catch-demangler-crashes", class_maintenance,
+ &catch_demangler_crashes, _("\
+Set whether to attempt to catch demangler crashes."), _("\
+Show whether to attempt to catch demangler crashes."), _("\
+If enabled GDB will attempt to catch demangler crashes and\n\
+display the offending symbol."),
+ NULL,
+ NULL,
+ &maintenance_set_cmdlist,
+ &maintenance_show_cmdlist);
+#endif
}