From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13405 invoked by alias); 27 Feb 2007 07:17:03 -0000 Received: (qmail 13393 invoked by uid 22791); 27 Feb 2007 07:17:02 -0000 X-Spam-Check-By: sourceware.org Received: from nile.gnat.com (HELO nile.gnat.com) (205.232.38.5) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 27 Feb 2007 07:16:57 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-nile.gnat.com (Postfix) with ESMTP id B108348D1AC for ; Tue, 27 Feb 2007 02:16:55 -0500 (EST) Received: from nile.gnat.com ([127.0.0.1]) by localhost (nile.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id 00708-01-5 for ; Tue, 27 Feb 2007 02:16:55 -0500 (EST) Received: from takamaka.act-europe.fr (unknown [70.71.0.212]) by nile.gnat.com (Postfix) with ESMTP id 332D648CEF2 for ; Tue, 27 Feb 2007 02:16:55 -0500 (EST) Received: by takamaka.act-europe.fr (Postfix, from userid 1000) id 8C08BE7B41; Mon, 26 Feb 2007 23:16:58 -0800 (PST) Date: Tue, 27 Feb 2007 11:02:00 -0000 From: Joel Brobecker To: gdb@sourceware.org Subject: failed assertion hit in check_typedef Message-ID: <20070227071658.GB13159@adacore.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.2.2i Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org X-SW-Source: 2007-02/txt/msg00266.txt.bz2 Hello, I just hit that assertion when working on the mips-irix port of GDB, in order to bring that port back in shape. Here is what happens: > (gdb) catch exception Constraint_Error > Breakpoint 2 at 0x9947200: file s-except.adb, line 44. > (gdb) n > gdbtypes.c:567: internal-error: make_cv_type: Assertion `TYPE_OBJFILE (*typeptr) == TYPE_OBJFILE (type)' failed. Here, the "next" steps over a call that leads to an exception being raised. And during the course of handling that exception, GDB hits that assertion. To refresh your memory on how Ada exception catchpoints are implemented, it's a simple breakpoint on a specific function, and the exception name is extracted from the addressed returned by the evaluation of the following expression: "e.full_name". "e" here is the name of the parameter of our function. This function is part of the Ada runtime, and in the case of mips-irix, the default runtime used is the shared GNAT runtime. Thus, our function and its parameter are defined in a DSO, not in the main executable. As as result, when we lookup "e", the symbol we get refers to the objfile of that DSO, not the one of the main executable. "E" is described as a ptr to a struct. However, the struct type is a STUB (flags = 4): $18 = {code = TYPE_CODE_STRUCT, upper_bound_type = BOUND_SIMPLE, lower_bound_type = BOUND_SIMPLE, name = 0x0, tag_name = 0x105dd636 "system__standard_library__exception_data", objfile = 0x1059b4d0, target_type = 0x0, flags = 4, nfields = 0, vptr_fieldno = -1, fields = 0x0, vptr_basetype = 0x0, type_specific = { cplus_stuff = 0x104c8480, floatformat = 0x104c8480, gnat_stuff = 0x104c8480}} So at some point, we do a "check_typedef" on it to resolve it to the complete type. This is where the fun begins: GCC, or maybe it is just GNAT, has the little habit of duplicating the definition of all the types it uses in all the compilation units that use them. So one of the unfortunate effects is that we end up in a situation when we have a copy of that type definition in our DSO, and also another copy in the main executable (more than one actually, but one is already too many). As a result, we have a problem there (gdbtypes.c:check_typedef): else if (TYPE_STUB (type) && !currently_reading_symtab) { char *name = type_name_no_tag (type); [...] sym = lookup_symbol (name, 0, STRUCT_DOMAIN, 0, (struct symtab **) NULL); if (sym) make_cv_type (is_const, is_volatile, SYMBOL_TYPE (sym), &type); } the lookup_symbol routine finds the first one which, bad luck, just happens to be the definition from the main exectuable. As a result, the following assertion in make_cv_type breaks: /* 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)); I'm not exactly too sure at this point on how to fix this problem. Maybe we should just change the call to make_cv_type to: type = make_cv_type (is_const, is_volatile, SYMBOL_TYPE (sym), type); But I think this would be bad, because that would leave the incomplete type as is, instead of replacing it by the complete definition. So instead, I suggest the following: Remove the assertion, and turn it into a check. Something like this: /* [repeat the comment already there (the one just above), and explain that we avoid the overwrite if the two types are not stored in the same obstack. Add explanation as to when this can happen]. */ if (typeptr && *typeptr != NULL && TYPE_OBJFILE (*typeptr) != TYPE_OBJFILE (type)) typeptr = NULL; It takes quite a long while to run the testsuite on mips-irix, so I was wondering if I could get some feedback before I go too far into this route... Thanks, -- Joel