--- ./gdb/breakpoint.c 2011-03-05 07:11:41.000000000 +0100 +++ ./gdb/breakpoint.c 2011-03-05 07:08:59.000000000 +0100 @@ -11730,6 +11730,7 @@ all_tracepoints () return tp_vec; } +#if 0 /* Call type_mark_used for any TYPEs referenced from this GDB source file. */ static void @@ -11745,6 +11746,7 @@ breakpoint_types_mark_used (void) type_mark_used (value_type (b->val)); } } +#endif /* This help string is used for the break, hbreak, tbreak and thbreak commands. @@ -12441,5 +12443,7 @@ inferior in all-stop mode, gdb behaves a automatic_hardware_breakpoints = 1; observer_attach_about_to_proceed (breakpoint_about_to_proceed); +#if 0 observer_attach_mark_used (breakpoint_types_mark_used); +#endif } --- ./gdb/doc/observer.texi 2011-03-05 07:11:40.000000000 +0100 +++ ./gdb/doc/observer.texi 2011-03-05 07:08:59.000000000 +0100 @@ -223,10 +223,10 @@ Bytes from @var{data} to @var{data} + @v to the current inferior at @var{addr}. @end deftypefun -@deftypefun void mark_used (void) -Mark any possibly reclaimable objects as used during a mark-and-sweep garbage -collector pass. Currently only @code{type_mark_used} marker is supported. -@end deftypefun +@c @deftypefun void mark_used (void) +@c Mark any possibly reclaimable objects as used during a mark-and-sweep garbage +@c collector pass. Currently only @code{type_mark_used} marker is supported. +@c @end deftypefun @deftypefun void test_notification (int @var{somearg}) This observer is used for internal testing. Do not use. --- ./gdb/gdbtypes.c 2011-03-05 07:11:41.000000000 +0100 +++ ./gdb/gdbtypes.c 2011-03-05 07:09:00.000000000 +0100 @@ -126,11 +126,13 @@ static void print_arg_types (struct fiel static void dump_fn_fieldlists (struct type *, int); static void print_cplus_stuff (struct type *, int); +#if 0 /* The hash table holding all discardable `struct type *' references. */ static htab_t type_discardable_table; /* Current type_discardable_check pass used for TYPE_DISCARDABLE_AGE. */ static int type_discardable_age_current; +#endif /* Allocate a new OBJFILE-associated type structure and fill it with some defaults. Space for the type structure is allocated @@ -161,6 +163,7 @@ alloc_type (struct objfile *objfile) return type; } +#if 0 /* Declare TYPE as discardable on next garbage collection by free_all_types. You must call type_mark_used during each free_all_types to protect TYPE from being deallocated. */ @@ -179,6 +182,7 @@ set_type_as_discardable (struct type *ty gdb_assert (!*slot); *slot = type; } +#endif /* Allocate a new type like alloc_type but preserve for it the discardability state of PARENT_TYPE. */ @@ -188,8 +192,10 @@ alloc_type_as_parent (struct type *paren { struct type *new_type = alloc_type_copy (parent_type); +#if 0 if (TYPE_DISCARDABLE (parent_type)) set_type_as_discardable (new_type); +#endif return new_type; } @@ -3219,11 +3225,13 @@ copy_type_recursive_1 (struct objfile *o TYPE_OBJFILE_OWNED (new_type) = 0; TYPE_OWNER (new_type).gdbarch = get_type_arch (type); +#if 0 /* TYPE_MAIN_TYPE memory copy above rewrote the TYPE_DISCARDABLE flag so we need to initialize it again. And even if TYPE was already discardable NEW_TYPE so far is not registered in TYPE_DISCARDABLE_TABLE. */ TYPE_DISCARDABLE (new_type) = 0; set_type_as_discardable (new_type); +#endif /* Pre-clear the fields processed by delete_main_type. If DWARF block evaluations below call error we would leave an unfreeable TYPE. */ @@ -3537,6 +3545,7 @@ copy_type (const struct type *type) return new_type; } +#if 0 /* Callback type for main_type_crawl. */ typedef int (*main_type_crawl_iter) (struct type *type, void *data); @@ -3730,6 +3739,7 @@ free_all_types (void) htab_traverse (type_discardable_table, type_discardable_remove, NULL); } +#endif /* Helper functions to initialize architecture-specific types. */ @@ -4261,9 +4271,11 @@ _initialize_gdbtypes (void) { gdbtypes_data = gdbarch_data_register_post_init (gdbtypes_post_init); +#if 0 type_discardable_table = htab_create_alloc (20, type_discardable_hash, type_discardable_equal, NULL, xcalloc, xfree); +#endif objfile_type_data = register_objfile_data (); --- ./gdb/gdbtypes.h 2011-03-05 07:11:41.000000000 +0100 +++ ./gdb/gdbtypes.h 2011-03-05 07:09:00.000000000 +0100 @@ -297,6 +297,7 @@ enum type_instance_flag_value #define TYPE_DECLARED_CLASS(t) (TYPE_MAIN_TYPE (t)->flag_declared_class) +#if 0 /* Define this type as being reclaimable during free_all_types. Type is required to be have TYPE_OBJFILE set to NULL. Setting this flag requires initializing TYPE_DISCARDABLE_AGE, see alloc_type_discardable. */ @@ -308,6 +309,7 @@ enum type_instance_flag_value by TYPE_DISCARDABLE_AGE_CURRENT. */ #define TYPE_DISCARDABLE_AGE(t) (TYPE_MAIN_TYPE (t)->flag_discardable_age) +#endif /* Is HIGH_BOUND a low-bound relative count (1) or the high bound itself (0)? */ @@ -450,8 +452,10 @@ struct main_type /* True if this type was declared with "class" rather than "struct". */ unsigned int flag_declared_class : 1; +#if 0 unsigned int flag_discardable : 1; unsigned int flag_discardable_age : 1; +#endif unsigned int flag_dynamic : 1; unsigned int flag_range_high_bound_is_count : 1; unsigned int flag_not_allocated : 1; @@ -1519,7 +1523,9 @@ extern int is_public_ancestor (struct ty extern int is_unique_ancestor (struct type *, struct value *); +#if 0 extern void type_mark_used (struct type *type); +#endif /* Overload resolution */ @@ -1588,6 +1594,8 @@ extern struct type *copy_type_recursive extern struct type *copy_type (const struct type *type); +#if 0 extern void free_all_types (void); +#endif #endif /* GDBTYPES_H */ --- ./gdb/parse.c 2011-03-05 07:11:41.000000000 +0100 +++ ./gdb/parse.c 2011-03-05 07:09:00.000000000 +0100 @@ -1584,6 +1584,7 @@ exp_uses_objfile (struct expression *exp /* Helper for exp_types_mark_used. */ +#if 0 static int exp_types_mark_used_iter (struct type *type, void *unused) { @@ -1600,6 +1601,7 @@ exp_types_mark_used (struct expression * { exp_iterate (exp, exp_types_mark_used_iter, NULL, NULL); } +#endif void _initialize_parse (void) --- ./gdb/parser-defs.h 2011-03-05 07:11:40.000000000 +0100 +++ ./gdb/parser-defs.h 2011-03-05 07:09:00.000000000 +0100 @@ -328,6 +328,8 @@ extern int exp_uses_objfile (struct expr extern int exp_uses_objfile (struct expression *exp, struct objfile *objfile); +#if 0 extern void exp_types_mark_used (struct expression *exp); +#endif #endif /* PARSER_DEFS_H */ --- ./gdb/printcmd.c 2011-03-05 07:11:40.000000000 +0100 +++ ./gdb/printcmd.c 2011-03-05 07:09:00.000000000 +0100 @@ -1485,6 +1485,7 @@ x_command (char *exp, int from_tty) } } +#if 0 /* Call type_mark_used for any TYPEs referenced from this GDB source file. */ static void @@ -1499,6 +1500,7 @@ print_types_mark_used (void) if (d->exp) exp_types_mark_used (d->exp); } +#endif @@ -2899,5 +2901,7 @@ Show printing of source filename and lin Convert \"printf format string\", arg1, arg2, arg3, ..., argn to\n\ a command line, and call it.")); +#if 0 observer_attach_mark_used (print_types_mark_used); +#endif } --- ./gdb/python/py-type.c 2011-03-05 07:11:40.000000000 +0100 +++ ./gdb/python/py-type.c 2011-03-05 07:09:00.000000000 +0100 @@ -45,8 +45,10 @@ typedef struct pyty_type_object struct pyty_type_object *next; } type_object; +#if 0 /* First element of a doubly-linked list of TYPE_DISCARDABLE Types. */ static type_object *pyty_objects_discardable; +#endif static PyTypeObject type_object_type; @@ -647,6 +649,7 @@ typy_link (type_object *type_obj) type_obj->next->prev = type_obj; set_objfile_data (objfile, typy_objfile_data_key, type_obj); } +#if 0 else if (type_obj->type && TYPE_DISCARDABLE (type_obj->type)) { type_obj->next = pyty_objects_discardable; @@ -654,6 +657,7 @@ typy_link (type_object *type_obj) type_obj->next->prev = type_obj; pyty_objects_discardable = type_obj; } +#endif else type_obj->next = NULL; } @@ -672,8 +676,10 @@ typy_unlink (type_object *type_obj) set_objfile_data (objfile, typy_objfile_data_key, type_obj->next); } +#if 0 else if (pyty_objects_discardable == type_obj) pyty_objects_discardable = type_obj->next; +#endif if (type_obj->next) type_obj->next->prev = type_obj->prev; @@ -722,6 +728,7 @@ typy_dealloc (PyObject *obj) type_obj->ob_type->tp_free (obj); } +#if 0 /* Call type_mark_used for any TYPEs referenced from this GDB source file. */ static void typy_types_mark_used (void) @@ -733,6 +740,7 @@ typy_types_mark_used (void) type_obj = type_obj->next) type_mark_used (type_obj->type); } +#endif /* Create a new Type referring to TYPE. */ PyObject * @@ -820,7 +828,9 @@ gdbpy_initialize_types (void) Py_INCREF (&field_object_type); PyModule_AddObject (gdb_module, "Field", (PyObject *) &field_object_type); +#if 0 observer_attach_mark_used (typy_types_mark_used); +#endif } --- ./gdb/python/py-value.c 2011-03-05 07:11:41.000000000 +0100 +++ ./gdb/python/py-value.c 2011-03-05 07:09:00.000000000 +0100 @@ -1071,6 +1071,7 @@ gdbpy_is_value_object (PyObject *obj) return PyObject_TypeCheck (obj, &value_object_type); } +#if 0 /* Call type_mark_used for any TYPEs referenced from this GDB source file. */ static void @@ -1081,6 +1082,7 @@ python_types_mark_used (void) for (iter = values_in_python; iter; iter = iter->next) type_mark_used (value_type (iter->value)); } +#endif void gdbpy_initialize_values (void) @@ -1093,7 +1095,9 @@ gdbpy_initialize_values (void) values_in_python = NULL; +#if 0 observer_attach_mark_used (python_types_mark_used); +#endif } --- ./gdb/top.c 2011-03-05 07:11:41.000000000 +0100 +++ ./gdb/top.c 2011-03-05 07:09:00.000000000 +0100 @@ -337,7 +337,9 @@ void prepare_execute_command (void) { free_all_values (); +#if 0 free_all_types (); +#endif /* With multiple threads running while the one we're examining is stopped, the dcache can get stale without us being able to detect it. --- ./gdb/value.c 2011-03-05 07:11:41.000000000 +0100 +++ ./gdb/value.c 2011-03-05 07:09:00.000000000 +0100 @@ -1004,7 +1004,9 @@ value_history_cleanup (void *unused) /* Free the unreferenced types above. */ free_all_values (); +#if 0 free_all_types (); +#endif } /* Internal variables. These are variables within the debugger @@ -1484,6 +1486,7 @@ call_internal_function (struct gdbarch * return (*ifn->handler) (gdbarch, language, ifn->cookie, argc, argv); } +#if 0 /* Call type_mark_used for any TYPEs referenced from this GDB source file. */ static void @@ -1517,6 +1520,7 @@ value_types_mark_used (void) type_mark_used (value_type (chunk->values[i])); } } +#endif /* The 'function' command. This does nothing -- it is just a placeholder to let "help function NAME" work. This is also used as @@ -2573,5 +2577,7 @@ Placeholder command for showing help on make_final_cleanup (value_history_cleanup, NULL); +#if 0 observer_attach_mark_used (value_types_mark_used); +#endif } commit b20c7d74a7e132186e7d80525eae8ed08ca4d5b8 Author: Jan Kratochvil Date: Tue Mar 8 08:50:33 2011 +0100 New testcase for the garbage collector MI incompleteness. diff --git a/gdb/testsuite/gdb.mi/mi2-var-stale-type.c b/gdb/testsuite/gdb.mi/mi2-var-stale-type.c new file mode 100644 index 0000000..ebced3c --- /dev/null +++ b/gdb/testsuite/gdb.mi/mi2-var-stale-type.c @@ -0,0 +1,26 @@ +/* Copyright 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +int +main (int argc, char **argv) +{ + char vla[argc]; + + vla[0] = 0; /* break-here */ + + return 0; +} diff --git a/gdb/testsuite/gdb.mi/mi2-var-stale-type.exp b/gdb/testsuite/gdb.mi/mi2-var-stale-type.exp new file mode 100644 index 0000000..74a104e --- /dev/null +++ b/gdb/testsuite/gdb.mi/mi2-var-stale-type.exp @@ -0,0 +1,57 @@ +# Copyright 2011 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +load_lib mi-support.exp +set MIFLAGS "-i=mi2" + +gdb_exit +if [mi_gdb_start] { + continue +} + +set testfile "mi2-var-stale-type" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if {[build_executable ${testfile}.exp $testfile $srcfile] == -1} { + return -1 +} + +mi_delete_breakpoints +mi_gdb_reinitialize_dir $srcdir/$subdir +mi_gdb_load ${binfile} + +mi_gdb_test {-interpreter-exec console "maintenance set internal-error quit yes"} \ + {\^done} \ + "maintenance set internal-error quit yes" + +mi_gdb_test {-interpreter-exec console "maintenance set internal-error corefile yes"} \ + {\^done} \ + "maintenance set internal-error corefile yes" + +set line [gdb_get_line_number "break-here"] +set func "main" + +mi_gdb_test "-break-insert -t $srcfile:$line" \ + "\\^done,bkpt=\{number=\"\[0-9\]+\",type=\"breakpoint\",disp=\"del\",enabled=\"y\",addr=\"$hex\",func=\"$func\(\\\(.*\\\)\)?\",file=\".*\",line=\"$line\",times=\"0\",original-location=\".*\"\}" \ + "breakpoint at $func" + +if { [mi_run_cmd] < 0 } { + return -1 +} +mi_expect_stop "breakpoint-hit" $func ".*" ".*" "\[0-9\]+" { "" "disp=\"del\"" } "stop after initializing vla" + +mi_create_varobj "vla" "vla" "create local variable vla" + +mi_gdb_test "-var-update *" "\\^done,changelist=.*" "-var-update *"