summaryrefslogtreecommitdiff
path: root/patches/gdb/6.3/740-debian_make-cv-type-crash.patch
blob: 4e0b8cd72a29a17bb58c01b8daffa409d00dd24b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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)