From ae5a43e0c91c4be8e22492ad4c1407ac7b2fcb18 Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Wed, 1 Feb 2006 23:14:11 +0000 Subject: [PATCH] gdb/ * Makefile.in (gdbtypes_h, gdbtypes.o, utils.o): Update. * defs.h (hashtab_obstack_allocate, dummy_obstack_deallocate): Add prototypes. * dwarf2read.c (read_subroutine_type): Use TYPE_ZALLOC. (hashtab_obstack_allocate, dummy_obstack_deallocate): Moved to... * utils.c (hashtab_obstack_allocate, dummy_obstack_deallocate): ...here. * gdbtypes.c: Include "hashtab.h". (build_gdbtypes): Remove extra prototype. (struct type_pair, type_pair_hash, type_pair_eq) (create_copied_types_hash, copy_type_recursive): New. * gdbtypes.h: Include "hashtab.h". (TYPE_ZALLOC): New. (create_copied_types_hash, copy_type_recursive): New prototypes. * objfiles.c (free_objfile): Call preserve_values. * symfile.c (reread_symbols): Likewise. (clear_symtab_users): Remove calls to clear_value_history and clear_internalvars. * value.c (clear_value_history, clear_internalvars): Removed. (preserve_one_value, preserve_values): New functions. * value.h (clear_value_history, clear_internalvars): Removed. (preserve_values): New prototype. * tracepoint.c (_initialize_tracepoint): Do not initialize convenience variables here. gdb/doc/ * gdb.texinfo (Files): Remove obsolete bits from the description of "symbol-file". --- gdb/ChangeLog | 28 +++++++++ gdb/Makefile.in | 6 +- gdb/defs.h | 5 ++ gdb/doc/ChangeLog | 5 ++ gdb/doc/gdb.texinfo | 10 +-- gdb/dwarf2read.c | 28 +-------- gdb/gdbtypes.c | 145 +++++++++++++++++++++++++++++++++++++++++++- gdb/gdbtypes.h | 14 +++++ gdb/objfiles.c | 4 ++ gdb/symfile.c | 6 +- gdb/tracepoint.c | 5 -- gdb/utils.c | 24 ++++++++ gdb/value.c | 72 +++++++++++----------- gdb/value.h | 4 +- 14 files changed, 275 insertions(+), 81 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ec2c9d72111..6ac5565bcdf 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,31 @@ +2006-02-01 Daniel Jacobowitz + + * Makefile.in (gdbtypes_h, gdbtypes.o, utils.o): Update. + * defs.h (hashtab_obstack_allocate, dummy_obstack_deallocate): Add + prototypes. + * dwarf2read.c (read_subroutine_type): Use TYPE_ZALLOC. + (hashtab_obstack_allocate, dummy_obstack_deallocate): Moved to... + * utils.c (hashtab_obstack_allocate, dummy_obstack_deallocate): + ...here. + * gdbtypes.c: Include "hashtab.h". + (build_gdbtypes): Remove extra prototype. + (struct type_pair, type_pair_hash, type_pair_eq) + (create_copied_types_hash, copy_type_recursive): New. + * gdbtypes.h: Include "hashtab.h". + (TYPE_ZALLOC): New. + (create_copied_types_hash, copy_type_recursive): New prototypes. + * objfiles.c (free_objfile): Call preserve_values. + * symfile.c (reread_symbols): Likewise. + (clear_symtab_users): Remove calls to clear_value_history and + clear_internalvars. + * value.c (clear_value_history, clear_internalvars): Removed. + (preserve_one_value, preserve_values): New functions. + * value.h (clear_value_history, clear_internalvars): Removed. + (preserve_values): New prototype. + + * tracepoint.c (_initialize_tracepoint): Do not initialize convenience + variables here. + 2006-01-29 Mark Kettenis * amd64-tdep.c (amd64_classify): Handle TYPE_CODE_BOOL. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 3ac4697f477..932d724bf79 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -697,7 +697,7 @@ gdb_stat_h = gdb_stat.h gdb_string_h = gdb_string.h gdb_thread_db_h = gdb_thread_db.h gdbthread_h = gdbthread.h $(breakpoint_h) $(frame_h) -gdbtypes_h = gdbtypes.h +gdbtypes_h = gdbtypes.h $(hashtab_h) gdb_vfork_h = gdb_vfork.h gdb_wait_h = gdb_wait.h glibc_tdep_h = glibc-tdep.h @@ -1984,7 +1984,7 @@ gdb-events.o: gdb-events.c $(defs_h) $(gdb_events_h) $(gdbcmd_h) gdbtypes.o: gdbtypes.c $(defs_h) $(gdb_string_h) $(bfd_h) $(symtab_h) \ $(symfile_h) $(objfiles_h) $(gdbtypes_h) $(expression_h) \ $(language_h) $(target_h) $(value_h) $(demangle_h) $(complaints_h) \ - $(gdbcmd_h) $(wrapper_h) $(cp_abi_h) $(gdb_assert_h) + $(gdbcmd_h) $(wrapper_h) $(cp_abi_h) $(gdb_assert_h) $(hashtab_h) glibc-tdep.o: glibc-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(symfile_h) \ $(objfiles_h) $(glibc_tdep_h) gnu-nat.o: gnu-nat.c $(gdb_string_h) $(defs_h) $(inferior_h) $(symtab_h) \ @@ -2720,7 +2720,7 @@ utils.o: utils.c $(defs_h) $(gdb_assert_h) $(gdb_string_h) $(event_top_h) \ $(exceptions_h) $(tui_h) $(gdbcmd_h) $(serial_h) $(bfd_h) \ $(target_h) $(demangle_h) $(expression_h) $(language_h) $(charset_h) \ $(annotate_h) $(filenames_h) $(symfile_h) $(inferior_h) \ - $(gdb_curses_h) $(readline_h) + $(gdb_curses_h) $(readline_h) $(gdb_obstack_h) uw-thread.o: uw-thread.c $(defs_h) $(gdbthread_h) $(target_h) $(inferior_h) \ $(regcache_h) $(gregset_h) v850-tdep.o: v850-tdep.c $(defs_h) $(frame_h) $(frame_base_h) $(trad_frame_h) \ diff --git a/gdb/defs.h b/gdb/defs.h index 86a0b67832e..6d4e922b95e 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -1217,4 +1217,9 @@ extern int use_windows; extern ULONGEST align_up (ULONGEST v, int n); extern ULONGEST align_down (ULONGEST v, int n); +/* Allocation and deallocation functions for the libiberty hash table + which use obstacks. */ +void *hashtab_obstack_allocate (void *data, size_t size, size_t count); +void dummy_obstack_deallocate (void *object, void *data); + #endif /* #ifndef DEFS_H */ diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index a03ae63d761..530324c8879 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2006-02-01 Daniel Jacobowitz + + * gdb.texinfo (Files): Remove obsolete bits from the description + of "symbol-file". + 2006-01-25 Jim Blandy * gdbint.texinfo (Testsuite): Explain how to run selected tests. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index fd1a7ed2459..b2c5de62c76 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -11094,11 +11094,11 @@ table and program to run from the same file. @code{symbol-file} with no argument clears out @value{GDBN} information on your program's symbol table. -The @code{symbol-file} command causes @value{GDBN} to forget the contents -of its convenience variables, the value history, and all breakpoints and -auto-display expressions. This is because they may contain pointers to -the internal data recording symbols and data types, which are part of -the old symbol table data being discarded inside @value{GDBN}. +The @code{symbol-file} command causes @value{GDBN} to forget the contents of +some breakpoints and auto-display expressions. This is because they may +contain pointers to the internal data recording symbols and data types, +which are part of the old symbol table data being discarded inside +@value{GDBN}. @code{symbol-file} does not repeat if you press @key{RET} again after executing it once. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 943f30477f8..85152a34c88 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -1030,10 +1030,6 @@ static gdb_byte *skip_one_die (gdb_byte *info_ptr, struct abbrev_info *abbrev, static void free_stack_comp_unit (void *); -static void *hashtab_obstack_allocate (void *data, size_t size, size_t count); - -static void dummy_obstack_deallocate (void *object, void *data); - static hashval_t partial_die_hash (const void *item); static int partial_die_eq (const void *item_lhs, const void *item_rhs); @@ -4627,7 +4623,7 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu) /* Allocate storage for parameters and fill them in. */ TYPE_NFIELDS (ftype) = nparams; TYPE_FIELDS (ftype) = (struct field *) - TYPE_ALLOC (ftype, nparams * sizeof (struct field)); + TYPE_ZALLOC (ftype, nparams * sizeof (struct field)); child_die = die->child; while (child_die && child_die->tag) @@ -9622,28 +9618,6 @@ dwarf2_clear_marks (struct dwarf2_per_cu_data *per_cu) } } -/* Allocation function for the libiberty hash table which uses an - obstack. */ - -static void * -hashtab_obstack_allocate (void *data, size_t size, size_t count) -{ - unsigned int total = size * count; - void *ptr = obstack_alloc ((struct obstack *) data, total); - memset (ptr, 0, total); - return ptr; -} - -/* Trivial deallocation function for the libiberty splay tree and hash - table - don't deallocate anything. Rely on later deletion of the - obstack. */ - -static void -dummy_obstack_deallocate (void *object, void *data) -{ - return; -} - /* Trivial hash function for partial_die_info: the hash value of a DIE is its offset in .debug_info for this objfile. */ diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index b4062b7b5b2..dde327b5ab4 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -1,7 +1,7 @@ /* Support routines for manipulating internal types for GDB. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2006 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules. @@ -39,6 +39,7 @@ #include "wrapper.h" #include "cp-abi.h" #include "gdb_assert.h" +#include "hashtab.h" /* These variables point to the objects representing the predefined C data types. */ @@ -3152,7 +3153,147 @@ recursive_dump_type (struct type *type, int spaces) obstack_free (&dont_print_type_obstack, NULL); } -static void build_gdbtypes (void); +/* Trivial helpers for the libiberty hash table, for mapping one + type to another. */ + +struct type_pair +{ + struct type *old, *new; +}; + +static hashval_t +type_pair_hash (const void *item) +{ + const struct type_pair *pair = item; + return htab_hash_pointer (pair->old); +} + +static int +type_pair_eq (const void *item_lhs, const void *item_rhs) +{ + const struct type_pair *lhs = item_lhs, *rhs = item_rhs; + return lhs->old == rhs->old; +} + +/* Allocate the hash table used by copy_type_recursive to walk + types without duplicates. We use OBJFILE's obstack, because + OBJFILE is about to be deleted. */ + +htab_t +create_copied_types_hash (struct objfile *objfile) +{ + return htab_create_alloc_ex (1, type_pair_hash, type_pair_eq, + NULL, &objfile->objfile_obstack, + hashtab_obstack_allocate, + dummy_obstack_deallocate); +} + +/* Recursively copy (deep copy) TYPE, if it is associated with OBJFILE. + Return a new type allocated using malloc, a saved type if we have already + visited TYPE (using COPIED_TYPES), or TYPE if it is not associated with + OBJFILE. */ + +struct type * +copy_type_recursive (struct objfile *objfile, struct type *type, + htab_t copied_types) +{ + struct type_pair *stored, pair; + void **slot; + struct type *new_type; + + if (TYPE_OBJFILE (type) == NULL) + return type; + + /* This type shouldn't be pointing to any types in other objfiles; if + it did, the type might disappear unexpectedly. */ + gdb_assert (TYPE_OBJFILE (type) == objfile); + + pair.old = type; + slot = htab_find_slot (copied_types, &pair, INSERT); + if (*slot != NULL) + return ((struct type_pair *) *slot)->new; + + new_type = alloc_type (NULL); + + /* We must add the new type to the hash table immediately, in case + we encounter this type again during a recursive call below. */ + stored = xmalloc (sizeof (struct type_pair)); + stored->old = type; + stored->new = new_type; + *slot = stored; + + /* Copy the common fields of types. */ + TYPE_CODE (new_type) = TYPE_CODE (type); + TYPE_ARRAY_UPPER_BOUND_TYPE (new_type) = TYPE_ARRAY_UPPER_BOUND_TYPE (type); + TYPE_ARRAY_LOWER_BOUND_TYPE (new_type) = TYPE_ARRAY_LOWER_BOUND_TYPE (type); + if (TYPE_NAME (type)) + TYPE_NAME (new_type) = xstrdup (TYPE_NAME (type)); + if (TYPE_TAG_NAME (type)) + TYPE_TAG_NAME (new_type) = xstrdup (TYPE_TAG_NAME (type)); + TYPE_FLAGS (new_type) = TYPE_FLAGS (type); + TYPE_VPTR_FIELDNO (new_type) = TYPE_VPTR_FIELDNO (type); + + TYPE_INSTANCE_FLAGS (new_type) = TYPE_INSTANCE_FLAGS (type); + TYPE_LENGTH (new_type) = TYPE_LENGTH (type); + + /* Copy the fields. */ + TYPE_NFIELDS (new_type) = TYPE_NFIELDS (type); + if (TYPE_NFIELDS (type)) + { + int i, nfields; + + nfields = TYPE_NFIELDS (type); + TYPE_FIELDS (new_type) = xmalloc (sizeof (struct field) * nfields); + for (i = 0; i < nfields; i++) + { + TYPE_FIELD_ARTIFICIAL (new_type, i) = TYPE_FIELD_ARTIFICIAL (type, i); + TYPE_FIELD_BITSIZE (new_type, i) = TYPE_FIELD_BITSIZE (type, i); + if (TYPE_FIELD_TYPE (type, i)) + TYPE_FIELD_TYPE (new_type, i) + = copy_type_recursive (objfile, TYPE_FIELD_TYPE (type, i), + copied_types); + if (TYPE_FIELD_NAME (type, i)) + TYPE_FIELD_NAME (new_type, i) = xstrdup (TYPE_FIELD_NAME (type, i)); + if (TYPE_FIELD_STATIC_HAS_ADDR (type, i)) + SET_FIELD_PHYSADDR (TYPE_FIELD (new_type, i), + TYPE_FIELD_STATIC_PHYSADDR (type, i)); + else if (TYPE_FIELD_STATIC (type, i)) + SET_FIELD_PHYSNAME (TYPE_FIELD (new_type, i), + xstrdup (TYPE_FIELD_STATIC_PHYSNAME (type, i))); + else + { + TYPE_FIELD_BITPOS (new_type, i) = TYPE_FIELD_BITPOS (type, i); + TYPE_FIELD_STATIC_KIND (new_type, i) = 0; + } + } + } + + /* Copy pointers to other types. */ + if (TYPE_TARGET_TYPE (type)) + TYPE_TARGET_TYPE (new_type) = copy_type_recursive (objfile, + TYPE_TARGET_TYPE (type), + copied_types); + if (TYPE_VPTR_BASETYPE (type)) + TYPE_VPTR_BASETYPE (new_type) = copy_type_recursive (objfile, + TYPE_VPTR_BASETYPE (type), + copied_types); + /* Maybe copy the type_specific bits. + + NOTE drow/2005-12-09: We do not copy the C++-specific bits like + base classes and methods. There's no fundamental reason why we + can't, but at the moment it is not needed. */ + + if (TYPE_CODE (type) == TYPE_CODE_FLT) + TYPE_FLOATFORMAT (new_type) == TYPE_FLOATFORMAT (type); + else if (TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION + || TYPE_CODE (type) == TYPE_CODE_TEMPLATE + || TYPE_CODE (type) == TYPE_CODE_NAMESPACE) + INIT_CPLUS_SPECIFIC (new_type); + + return new_type; +} + static void build_gdbtypes (void) { diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index de451d5d99d..944e5f12bed 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -25,6 +25,8 @@ #if !defined (GDBTYPES_H) #define GDBTYPES_H 1 +#include "hashtab.h" + /* Forward declarations for prototypes. */ struct field; struct block; @@ -1176,6 +1178,12 @@ extern struct type *builtin_type_f_void; ? obstack_alloc (&TYPE_OBJFILE (t) -> objfile_obstack, size) \ : xmalloc (size)) +#define TYPE_ZALLOC(t,size) \ + (TYPE_OBJFILE (t) != NULL \ + ? memset (obstack_alloc (&TYPE_OBJFILE (t)->objfile_obstack, size), \ + 0, size) \ + : xzalloc (size)) + extern struct type *alloc_type (struct objfile *); extern struct type *init_type (enum type_code, int, int, char *, @@ -1371,4 +1379,10 @@ extern int is_integral_type (struct type *); extern void maintenance_print_type (char *, int); +extern htab_t create_copied_types_hash (struct objfile *objfile); + +extern struct type *copy_type_recursive (struct objfile *objfile, + struct type *type, + htab_t copied_types); + #endif /* GDBTYPES_H */ diff --git a/gdb/objfiles.c b/gdb/objfiles.c index 41aab64594a..3419c6dfa2d 100644 --- a/gdb/objfiles.c +++ b/gdb/objfiles.c @@ -393,6 +393,10 @@ free_objfile (struct objfile *objfile) objfile->separate_debug_objfile_backlink->separate_debug_objfile = NULL; } + /* Remove any references to this objfile in the global value + lists. */ + preserve_values (objfile); + /* First do any symbol file specific actions required when we are finished with a particular symbol file. Note that if the objfile is using reusable symbol information (via mmalloc) then each of diff --git a/gdb/symfile.c b/gdb/symfile.c index 63dd4b3ee00..93cb009e4fd 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -2013,6 +2013,10 @@ reread_symbols (void) memcpy (offsets, objfile->section_offsets, SIZEOF_N_SECTION_OFFSETS (num_offsets)); + /* Remove any references to this objfile in the global + value lists. */ + preserve_values (objfile); + /* Nuke all the state that we will re-read. Much of the following code which sets things to NULL really is necessary to tell other parts of GDB that there is nothing currently there. */ @@ -2485,9 +2489,7 @@ clear_symtab_users (void) breakpoint_re_set may try to access the current symtab. */ clear_current_source_symtab_and_line (); - clear_value_history (); clear_displays (); - clear_internalvars (); breakpoint_re_set (); set_default_breakpoint (0, 0, 0, 0); clear_pc_function_cache (); diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 0737e64daf9..c40b120e466 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -2694,11 +2694,6 @@ _initialize_tracepoint (void) traceframe_number = -1; tracepoint_number = -1; - set_internalvar (lookup_internalvar ("tpnum"), - value_from_longest (builtin_type_int, (LONGEST) 0)); - set_internalvar (lookup_internalvar ("trace_frame"), - value_from_longest (builtin_type_int, (LONGEST) - 1)); - if (tracepoint_list.list == NULL) { tracepoint_list.listsize = 128; diff --git a/gdb/utils.c b/gdb/utils.c index eb870ac92ef..fdebbdc3ea5 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -53,6 +53,7 @@ #include "annotate.h" #include "filenames.h" #include "symfile.h" +#include "gdb_obstack.h" #include "inferior.h" /* for signed_pointer_to_address */ @@ -3124,3 +3125,26 @@ align_down (ULONGEST v, int n) gdb_assert (n && (n & (n-1)) == 0); return (v & -n); } + +/* Allocation function for the libiberty hash table which uses an + obstack. The obstack is passed as DATA. */ + +void * +hashtab_obstack_allocate (void *data, size_t size, size_t count) +{ + unsigned int total = size * count; + void *ptr = obstack_alloc ((struct obstack *) data, total); + memset (ptr, 0, total); + return ptr; +} + +/* Trivial deallocation function for the libiberty splay tree and hash + table - don't deallocate anything. Rely on later deletion of the + obstack. DATA will be the obstack, although it is not needed + here. */ + +void +dummy_obstack_deallocate (void *object, void *data) +{ + return; +} diff --git a/gdb/value.c b/gdb/value.c index 801874b187d..2e304854bfa 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -653,29 +653,6 @@ access_value_history (int num) return value_copy (chunk->values[absnum % VALUE_HISTORY_CHUNK]); } -/* Clear the value history entirely. - Must be done when new symbol tables are loaded, - because the type pointers become invalid. */ - -void -clear_value_history (void) -{ - struct value_history_chunk *next; - int i; - struct value *val; - - while (value_history_chain) - { - for (i = 0; i < VALUE_HISTORY_CHUNK; i++) - if ((val = value_history_chain->values[i]) != NULL) - xfree (val); - next = value_history_chain->next; - xfree (value_history_chain); - value_history_chain = next; - } - value_history_count = 0; -} - static void show_values (char *num_exp, int from_tty) { @@ -842,22 +819,49 @@ internalvar_name (struct internalvar *var) return var->name; } -/* Free all internalvars. Done when new symtabs are loaded, - because that makes the values invalid. */ +/* Update VALUE before discarding OBJFILE. COPIED_TYPES is used to + prevent cycles / duplicates. */ + +static void +preserve_one_value (struct value *value, struct objfile *objfile, + htab_t copied_types) +{ + if (TYPE_OBJFILE (value->type) == objfile) + value->type = copy_type_recursive (objfile, value->type, copied_types); + + if (TYPE_OBJFILE (value->enclosing_type) == objfile) + value->enclosing_type = copy_type_recursive (objfile, + value->enclosing_type, + copied_types); +} + +/* Update the internal variables and value history when OBJFILE is + discarded; we must copy the types out of the objfile. New global types + will be created for every convenience variable which currently points to + this objfile's types, and the convenience variables will be adjusted to + use the new global types. */ void -clear_internalvars (void) +preserve_values (struct objfile *objfile) { + htab_t copied_types; + struct value_history_chunk *cur; struct internalvar *var; + int i; - while (internalvars) - { - var = internalvars; - internalvars = var->next; - xfree (var->name); - xfree (var->value); - xfree (var); - } + /* Create the hash table. We allocate on the objfile's obstack, since + it is soon to be deleted. */ + copied_types = create_copied_types_hash (objfile); + + for (cur = value_history_chain; cur; cur = cur->next) + for (i = 0; i < VALUE_HISTORY_CHUNK; i++) + if (cur->values[i]) + preserve_one_value (cur->values[i], objfile, copied_types); + + for (var = internalvars; var; var = var->next) + preserve_one_value (var->value, objfile, copied_types); + + htab_delete (copied_types); } static void diff --git a/gdb/value.h b/gdb/value.h index 6b2216bb726..e1972352270 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -502,9 +502,7 @@ extern void typedef_print (struct type *type, struct symbol *news, extern char *internalvar_name (struct internalvar *var); -extern void clear_value_history (void); - -extern void clear_internalvars (void); +extern void preserve_values (struct objfile *); /* From values.c */ -- 2.30.2