From c0201579c8cd0c319fa851c98b0adf21ac013489 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Thu, 22 Apr 2010 23:15:43 +0000 Subject: gdb/ Fix crashes on dangling display expressions. * ada-lang.c (ada_operator_check): New function. (ada_exp_descriptor): Fill-in the field operator_check. * c-lang.c (exp_descriptor_c): Fill-in the field operator_check. * jv-lang.c (exp_descriptor_java): Likewise. * m2-lang.c (exp_descriptor_modula2): Likewise. * scm-lang.c (exp_descriptor_scm): Likewise. * parse.c (exp_descriptor_standard): Likewise. (operator_check_standard): New function. (exp_iterate, exp_uses_objfile_iter, exp_uses_objfile): New functions. * parser-defs.h (struct exp_descriptor): New field operator_check. (operator_check_standard, exp_uses_objfile): New declarations. * printcmd.c: Remove the inclusion of solib.h. (display_uses_solib_p): Remove the function. (clear_dangling_display_expressions): Call lookup_objfile_from_block and exp_uses_objfile instead of display_uses_solib_p. * solist.h (struct so_list) : New comment. * symtab.c (lookup_objfile_from_block): Remove the static qualifier. * symtab.h (lookup_objfile_from_block): New declaration. (struct general_symbol_info) : Extend the comment. gdb/testsuite/ Fix crashes on dangling display expressions. * gdb.base/solib-display.exp: Call gdb_gnu_strip_debug if LIBSEPDEBUG is SEP. (lib_flags): Remove the "debug" keyword. (libsepdebug): New variable for iterating new loop. (save_pf_prefix): New variable wrapping the loop. (sep_lib_flags): New variable derived from LIB_FLAGS. Use it. * lib/gdb.exp (gdb_gnu_strip_debug): Document the return code. --- gdb/parse.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) (limited to 'gdb/parse.c') diff --git a/gdb/parse.c b/gdb/parse.c index aabc461..51e1550 100644 --- a/gdb/parse.c +++ b/gdb/parse.c @@ -62,6 +62,7 @@ const struct exp_descriptor exp_descriptor_standard = { print_subexp_standard, operator_length_standard, + operator_check_standard, op_name_standard, dump_subexp_body_standard, evaluate_subexp_standard @@ -1373,6 +1374,150 @@ parser_fprintf (FILE *x, const char *y, ...) va_end (args); } +/* Implementation of the exp_descriptor method operator_check. */ + +int +operator_check_standard (struct expression *exp, int pos, + int (*objfile_func) (struct objfile *objfile, + void *data), + void *data) +{ + const union exp_element *const elts = exp->elts; + struct type *type = NULL; + struct objfile *objfile = NULL; + + /* Extended operators should have been already handled by exp_descriptor + iterate method of its specific language. */ + gdb_assert (elts[pos].opcode < OP_EXTENDED0); + + /* Track the callers of write_exp_elt_type for this table. */ + + switch (elts[pos].opcode) + { + case BINOP_VAL: + case OP_COMPLEX: + case OP_DECFLOAT: + case OP_DOUBLE: + case OP_LONG: + case OP_SCOPE: + case OP_TYPE: + case UNOP_CAST: + case UNOP_DYNAMIC_CAST: + case UNOP_REINTERPRET_CAST: + case UNOP_MAX: + case UNOP_MEMVAL: + case UNOP_MIN: + type = elts[pos + 1].type; + break; + + case TYPE_INSTANCE: + { + LONGEST arg, nargs = elts[pos + 1].longconst; + + for (arg = 0; arg < nargs; arg++) + { + struct type *type = elts[pos + 2 + arg].type; + struct objfile *objfile = TYPE_OBJFILE (type); + + if (objfile && (*objfile_func) (objfile, data)) + return 1; + } + } + break; + + case UNOP_MEMVAL_TLS: + objfile = elts[pos + 1].objfile; + type = elts[pos + 2].type; + break; + + case OP_VAR_VALUE: + { + const struct block *const block = elts[pos + 1].block; + const struct symbol *const symbol = elts[pos + 2].symbol; + + /* Check objfile where the variable itself is placed. + SYMBOL_OBJ_SECTION (symbol) may be NULL. */ + if ((*objfile_func) (SYMBOL_SYMTAB (symbol)->objfile, data)) + return 1; + + /* Check objfile where is placed the code touching the variable. */ + objfile = lookup_objfile_from_block (block); + + type = SYMBOL_TYPE (symbol); + } + break; + } + + /* Invoke callbacks for TYPE and OBJFILE if they were set as non-NULL. */ + + if (type && TYPE_OBJFILE (type) + && (*objfile_func) (TYPE_OBJFILE (type), data)) + return 1; + if (objfile && (*objfile_func) (objfile, data)) + return 1; + + return 0; +} + +/* Call OBJFILE_FUNC for any TYPE and OBJFILE found being referenced by EXP. + The functions are never called with NULL OBJFILE. Functions get passed an + arbitrary caller supplied DATA pointer. If any of the functions returns + non-zero value then (any other) non-zero value is immediately returned to + the caller. Otherwise zero is returned after iterating through whole EXP. + */ + +static int +exp_iterate (struct expression *exp, + int (*objfile_func) (struct objfile *objfile, void *data), + void *data) +{ + int endpos; + const union exp_element *const elts = exp->elts; + + for (endpos = exp->nelts; endpos > 0; ) + { + int pos, args, oplen = 0; + + exp->language_defn->la_exp_desc->operator_length (exp, endpos, + &oplen, &args); + gdb_assert (oplen > 0); + + pos = endpos - oplen; + if (exp->language_defn->la_exp_desc->operator_check (exp, pos, + objfile_func, data)) + return 1; + + endpos = pos; + } + + return 0; +} + +/* Helper for exp_uses_objfile. */ + +static int +exp_uses_objfile_iter (struct objfile *exp_objfile, void *objfile_voidp) +{ + struct objfile *objfile = objfile_voidp; + + if (exp_objfile->separate_debug_objfile_backlink) + exp_objfile = exp_objfile->separate_debug_objfile_backlink; + + return exp_objfile == objfile; +} + +/* Return 1 if EXP uses OBJFILE (and will become dangling when OBJFILE + is unloaded), otherwise return 0. OBJFILE must not be a separate debug info + file. */ + +int +exp_uses_objfile (struct expression *exp, struct objfile *objfile) +{ + gdb_assert (objfile->separate_debug_objfile_backlink == NULL); + + return exp_iterate (exp, exp_uses_objfile_iter, objfile); +} + void _initialize_parse (void) { -- cgit v1.1