| 2004-11-04 Jim Blandy <jimb@redhat.com> |
| |
| * gdbtypes.c (make_qualified_type): Doc fix. Add assertion to |
| prevent cross-objfile references. |
| (make_cv_type): Doc fix. Don't create cross-objfile references, |
| even for stub types. |
| (replace_type): Add assertion to prevent cross-objfile references. |
| (check_typedef): Never resolve a stub type by copying over a type |
| from another file. |
| |
| Index: src/gdb/gdbtypes.c |
| =================================================================== |
| RCS file: /big/fsf/rsync/src-cvs/src/gdb/gdbtypes.c,v |
| retrieving revision 1.92 |
| retrieving revision 1.93 |
| diff -u -p -r1.92 -r1.93 |
| --- src/gdb/gdbtypes.c 8 Aug 2004 17:18:16 -0000 1.92 |
| +++ src/gdb/gdbtypes.c 4 Nov 2004 17:50:16 -0000 1.93 |
| @@ -433,7 +433,9 @@ address_space_int_to_name (int space_fla |
| } |
| |
| /* Create a new type with instance flags NEW_FLAGS, based on TYPE. |
| - If STORAGE is non-NULL, create the new type instance there. */ |
| + |
| + If STORAGE is non-NULL, create the new type instance there. |
| + STORAGE must be in the same obstack as TYPE. */ |
| |
| static struct type * |
| make_qualified_type (struct type *type, int new_flags, |
| @@ -453,6 +455,12 @@ make_qualified_type (struct type *type, |
| ntype = alloc_type_instance (type); |
| else |
| { |
| + /* If STORAGE was provided, it had better be in the same objfile as |
| + TYPE. Otherwise, we can't link it into TYPE's cv chain: if one |
| + objfile is freed and the other kept, we'd have dangling |
| + pointers. */ |
| + gdb_assert (TYPE_OBJFILE (type) == TYPE_OBJFILE (storage)); |
| + |
| ntype = storage; |
| TYPE_MAIN_TYPE (ntype) = TYPE_MAIN_TYPE (type); |
| TYPE_CHAIN (ntype) = ntype; |
| @@ -501,11 +509,12 @@ make_type_with_address_space (struct typ |
| CNST is a flag for setting the const attribute |
| VOLTL is a flag for setting the volatile attribute |
| TYPE is the base type whose variant we are creating. |
| - TYPEPTR, if nonzero, points |
| - to a pointer to memory where the reference type should be stored. |
| - If *TYPEPTR is zero, update it to point to the reference type we return. |
| - We allocate new memory if needed. */ |
| |
| + If TYPEPTR and *TYPEPTR are non-zero, then *TYPEPTR points to |
| + storage to hold the new qualified type; *TYPEPTR and TYPE must be |
| + in the same objfile. Otherwise, allocate fresh memory for the new |
| + type whereever TYPE lives. If TYPEPTR is non-zero, set it to the |
| + new type we construct. */ |
| struct type * |
| make_cv_type (int cnst, int voltl, struct type *type, struct type **typeptr) |
| { |
| @@ -524,20 +533,19 @@ make_cv_type (int cnst, int voltl, struc |
| |
| if (typeptr && *typeptr != NULL) |
| { |
| - /* Objfile is per-core-type. This const-qualified type had best |
| - belong to the same objfile as the type it is qualifying, unless |
| - we are overwriting a stub type, in which case the safest thing |
| - to do is to copy the core type into the new objfile. */ |
| - |
| - gdb_assert (TYPE_OBJFILE (*typeptr) == TYPE_OBJFILE (type) |
| - || TYPE_STUB (*typeptr)); |
| - if (TYPE_OBJFILE (*typeptr) != TYPE_OBJFILE (type)) |
| - { |
| - TYPE_MAIN_TYPE (*typeptr) |
| - = TYPE_ALLOC (*typeptr, sizeof (struct main_type)); |
| - *TYPE_MAIN_TYPE (*typeptr) |
| - = *TYPE_MAIN_TYPE (type); |
| - } |
| + /* TYPE and *TYPEPTR must be in the same objfile. We can't have |
| + a C-V variant chain that threads across objfiles: if one |
| + objfile gets freed, then the other has a broken C-V chain. |
| + |
| + This code used to try to copy over the main type from TYPE to |
| + *TYPEPTR if they were in different objfiles, but that's |
| + wrong, too: TYPE may have a field list or member function |
| + lists, which refer to types of their own, etc. etc. The |
| + whole shebang would need to be copied over recursively; you |
| + can't have inter-objfile pointers. The only thing to do is |
| + to leave stub types as stub types, and look them up afresh by |
| + name each time you encounter them. */ |
| + gdb_assert (TYPE_OBJFILE (*typeptr) == TYPE_OBJFILE (type)); |
| } |
| |
| ntype = make_qualified_type (type, new_flags, typeptr ? *typeptr : NULL); |
| @@ -562,6 +570,12 @@ replace_type (struct type *ntype, struct |
| { |
| struct type *chain; |
| |
| + /* These two types had better be in the same objfile. Otherwise, |
| + the assignment of one type's main type structure to the other |
| + will produce a type with references to objects (names; field |
| + lists; etc.) allocated on an objfile other than its own. */ |
| + gdb_assert (TYPE_OBJFILE (ntype) == TYPE_OBJFILE (ntype)); |
| + |
| *TYPE_MAIN_TYPE (ntype) = *TYPE_MAIN_TYPE (type); |
| |
| /* The type length is not a part of the main type. Update it for each |
| @@ -1416,8 +1430,24 @@ check_typedef (struct type *type) |
| return type; |
| } |
| newtype = lookup_transparent_type (name); |
| + |
| if (newtype) |
| - make_cv_type (is_const, is_volatile, newtype, &type); |
| + { |
| + /* If the resolved type and the stub are in the same objfile, |
| + then replace the stub type with the real deal. But if |
| + they're in separate objfiles, leave the stub alone; we'll |
| + just look up the transparent type every time we call |
| + check_typedef. We can't create pointers between types |
| + allocated to different objfiles, since they may have |
| + different lifetimes. Trying to copy NEWTYPE over to TYPE's |
| + objfile is pointless, too, since you'll have to move over any |
| + other types NEWTYPE refers to, which could be an unbounded |
| + amount of stuff. */ |
| + if (TYPE_OBJFILE (newtype) == TYPE_OBJFILE (type)) |
| + make_cv_type (is_const, is_volatile, newtype, &type); |
| + else |
| + type = newtype; |
| + } |
| } |
| /* Otherwise, rely on the stub flag being set for opaque/stubbed types */ |
| else if (TYPE_STUB (type) && !currently_reading_symtab) |