This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
RFA: avoid creating inter-objfile type pointers
- From: Jim Blandy <jimb at redhat dot com>
- To: gdb-patches at sources dot redhat dot com
- Date: 04 Nov 2004 02:12:19 -0500
- Subject: RFA: avoid creating inter-objfile type pointers
This fixes a bug that causes incorrect output and crashes, and which
is not caught by the current test suite. A test could be easily added
to shlib-call.exp to catch this; I'll try to give that a shot in a
bit.
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: gdb/gdbtypes.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.c,v
retrieving revision 1.82
diff -c -r1.82 gdbtypes.c
*** gdb/gdbtypes.c 9 Mar 2004 17:08:25 -0000 1.82
--- gdb/gdbtypes.c 4 Nov 2004 05:32:44 -0000
***************
*** 428,434 ****
}
/* Create a new type with instance flags NEW_FLAGS, based on TYPE.
! If STORAGE is non-NULL, create the new type instance there. */
static struct type *
make_qualified_type (struct type *type, int new_flags,
--- 428,436 ----
}
/* Create a new type with instance flags NEW_FLAGS, based on TYPE.
!
! 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,
***************
*** 448,453 ****
--- 450,461 ----
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;
***************
*** 496,506 ****
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. */
struct type *
make_cv_type (int cnst, int voltl, struct type *type, struct type **typeptr)
{
--- 504,515 ----
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.
+ 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)
{
***************
*** 519,538 ****
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);
! }
}
ntype = make_qualified_type (type, new_flags, typeptr ? *typeptr : NULL);
--- 528,546 ----
if (typeptr && *typeptr != NULL)
{
! /* 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);
***************
*** 557,562 ****
--- 565,576 ----
{
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
***************
*** 1423,1430 ****
return type;
}
newtype = lookup_transparent_type (name);
if (newtype)
! make_cv_type (is_const, is_volatile, newtype, &type);
}
/* Otherwise, rely on the stub flag being set for opaque/stubbed types */
else if (TYPE_STUB (type) && !currently_reading_symtab)
--- 1437,1460 ----
return type;
}
newtype = lookup_transparent_type (name);
+
if (newtype)
! {
! /* 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)