This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]