diff options
author | Jan Kratochvil <jan.kratochvil@redhat.com> | 2010-04-22 23:15:43 +0000 |
---|---|---|
committer | Jan Kratochvil <jan.kratochvil@redhat.com> | 2010-04-22 23:15:43 +0000 |
commit | c0201579c8cd0c319fa851c98b0adf21ac013489 (patch) | |
tree | 16da9856639cf50456ca57f90fa738059ead5304 /gdb/parse.c | |
parent | 793b0ff8d7126cf5ec1631fc07ffec5b5664b226 (diff) | |
download | gdb-c0201579c8cd0c319fa851c98b0adf21ac013489.zip gdb-c0201579c8cd0c319fa851c98b0adf21ac013489.tar.gz gdb-c0201579c8cd0c319fa851c98b0adf21ac013489.tar.bz2 |
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) <objfile>: New comment.
* symtab.c (lookup_objfile_from_block): Remove the static qualifier.
* symtab.h (lookup_objfile_from_block): New declaration.
(struct general_symbol_info) <obj_section>: 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.
Diffstat (limited to 'gdb/parse.c')
-rw-r--r-- | gdb/parse.c | 145 |
1 files changed, 145 insertions, 0 deletions
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) { |