From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 2829 invoked by alias); 4 Nov 2004 07:13:23 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 2813 invoked from network); 4 Nov 2004 07:13:20 -0000 Received: from unknown (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org with SMTP; 4 Nov 2004 07:13:20 -0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.12.11/8.12.11) with ESMTP id iA47DEtV026418 for ; Thu, 4 Nov 2004 02:13:19 -0500 Received: from zenia.home.redhat.com (sebastian-int.corp.redhat.com [172.16.52.221]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id iA47DDr05210; Thu, 4 Nov 2004 02:13:13 -0500 To: gdb-patches@sources.redhat.com Subject: RFA: avoid creating inter-objfile type pointers From: Jim Blandy Date: Thu, 04 Nov 2004 07:13:00 -0000 Message-ID: User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-SW-Source: 2004-11/txt/msg00059.txt.bz2 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 * 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)