mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-26 17:18:55 +00:00
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.
This commit is contained in:
145
gdb/parse.c
145
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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user