From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11279 invoked by alias); 9 Feb 2007 22:51:56 -0000 Received: (qmail 11258 invoked by uid 22791); 9 Feb 2007 22:51:52 -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; Fri, 09 Feb 2007 22:51:46 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-nile.gnat.com (Postfix) with ESMTP id CEF5648CC77 for ; Fri, 9 Feb 2007 17:51:44 -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 19584-01-2 for ; Fri, 9 Feb 2007 17:51:44 -0500 (EST) Received: from takamaka.act-europe.fr (unknown [70.71.0.212]) by nile.gnat.com (Postfix) with ESMTP id 4982648CC84 for ; Fri, 9 Feb 2007 17:51:44 -0500 (EST) Received: by takamaka.act-europe.fr (Postfix, from userid 1000) id 21FEB34C099; Fri, 9 Feb 2007 14:52:49 -0800 (PST) Date: Fri, 09 Feb 2007 22:51:00 -0000 From: Joel Brobecker To: gdb-patches@sourceware.org Subject: [RFA/stabs] 't' type declaration is equivalent to 'Tt' for Ada Message-ID: <20070209225249.GK3372@adacore.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="G4iJoqBmSsgzjUCe" Content-Disposition: inline User-Agent: Mutt/1.4.2.2i Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2007-02/txt/msg00152.txt.bz2 --G4iJoqBmSsgzjUCe Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 5522 Another case of a parameter reported as "undefined type". This time, it happens on pa-hpux and ppc-aix. We recently had to modify our runtime with respect to how exception breakpoints are handled. We now have a separate unit (s-except.adb) that contains simple hooks: . __gnat_debug_raise_exception: Called when an exception is raised . __gnat_unhandled_exception: Called when an unhandled exception is raised. If you remember my recent contribution in that area, to get the name of an unhandled exception, we had to go up the stack until we reached a specific frame, and extra the exception name from a local variable inside that frame. This stopped working with recent versions of GCC because the optimizer would simply optimize our variable away one way or the other no matter what we tried. So instead, we came up with the hooks in that new unit, and had that unit compiled at -O0 to prevent that optimization. As a bonus we avoid having to go up the stack. I hope to update GDB to support both old and new schemes pretty soon. In the meantime, the new scheme exposed a weakness in the stabs support. Consider any program that raises an exception: (gdb) b __gnat_debug_raise_exception Breakpoint 1 at 0xa514: file s-except.adb, line 44. (gdb) run Starting program: /[...]/a Breakpoint 1, <__gnat_debug_raise_exception> (e=0x40002fdc) at s-except.adb:44 44 s-except.adb: No such file or directory. in s-except.adb (gdb) p *e $1 = (gdb) ptype e type = access record end record Here is what the debugging info looks like: .stabs "e:p29=k23",160,0,51,-36 And type 23 is actually defined a bit earlier buried inside another type definition: .stabs "system__standard_library__exception_data:t22=s24not_handled_by_others:5,0,8;lang:6,8,8;name_length:7,32,32;full_name:20,64,32;htable_ptr:23=*24=xssystem__standard_library__exception_data:,96,32;import_code:21,128,32;raise_hook:25=*26=f27=27,160,32;;",128,0,153,0 (search for field htable_ptr). Type 23 is a pointer to type 24 which itself is a forward reference to system__standard_library__exception_data, which you might notice is actually the type we are currently defining :-). So at the time we try to build type 24, it is actually incomplete. So we push that type to the undef_types stack, and wait until the end to try to defined it properly. This is done in cleanup_undefined_types. For that, it goes through the list of symbols that have been created from reading the stabs of the current unit, and for each undefined type, if we find a symbol that has the same name, then we replace the undefined type with the symbol type: for (ppt = file_symbols; ppt; ppt = ppt->next) { for (i = 0; i < ppt->nsyms; i++) { struct symbol *sym = ppt->symbol[i]; if (SYMBOL_CLASS (sym) == LOC_TYPEDEF && SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN && (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE (*type)) && strcmp (DEPRECATED_SYMBOL_NAME (sym), typename) == 0) replace_type (*type, SYMBOL_TYPE (sym)); The problem is that we only match STRUCT_DOMAIN symbols. However, in our case, the actual type was declared: system__standard_library__exception_data:t22= This is different from: system__standard_library__exception_data:Tt22= When we have a 't', the debugger builds a VAR_DOMAIN symbol. When we have a 'T', the debugger also builds a STRUCT_DOMAIN symbol. In Ada, there is no equivalent of the distinction between typedef and non-typedef. So as a result, I modified the stabsreader such that, for Ada, a 't' symbol would be treated as if it was defined with 'Tt'. I don't particularly find the patch too eleguant. Perhaps it should have been better to group the 'T' case with the 't' one, and have a little check that check the character one after the other... Something like this: case 'T': case 't': int create_struct_domain_sym = (deftype == 'T' || *p == 'T'); int create_var_domain_sym = (deftype == 't' || *p == 't'); if (*p == 't' || *p == 'T') p++ if (language == language_ada) { /* For Ada, no distinction, bla bla bla, force the creation of both types of symbols, etc. */ create_struct_domain_sym = 1; create_var_domain_sym = 1; } SYMBOL_TYPE (sym) = read_type (&p, objfile) if (create_var_domain_sym) [create VAR_DOMAIN symbol - copied straight from what we have in the "case 't':"] if (create_struct_domain_sym) [create STRUCT_DOMAIN symbol - copied more or less straight from what we have in the "case 'T':"] The reason why I didn't pursue this idea was because it was a larger change, and with a slightly increased risk compared to what I did. In my change, if there is a bug, only Ada will get affected. In this case, it's going to be all languages. We're all hoping to get away from stabs as soon as we can, and in the meantime, I am hoping that the shortest route is good enough. 2007-02-07 Joel Brobecker * stabsread.c (define_symbol): Create an associated STRUCT_DOMAIN symbol for Ada units when the symbol is defined using 't' rather than 'Tt' as symbol descriptor. Tested on x86-linux (using -gstabs+) and pa-hpux, no regression. Fixes the problem described above. OK to apply? Thanks, -- Joel --G4iJoqBmSsgzjUCe Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="Tt.diff" Content-length: 2088 Index: stabsread.c =================================================================== --- stabsread.c (revision 6010) +++ stabsread.c (revision 6011) @@ -1102,6 +1102,22 @@ define_symbol (CORE_ADDR valu, char *str break; case 't': + /* In Ada, there is no distinction between typedef and non-typedef; + any type declaration implicitly has the equivalent of a typedef, + and thus 't' is in fact equivalent to 'Tt'. + + Therefore, for Ada units, we check the character immediately + before the 't', and if we do not find a 'T', then make sure to + create the associated symbol in the STRUCT_DOMAIN ('t' definitions + will be stored in the VAR_DOMAIN). If the symbol was indeed + defined as 'Tt' then the STRUCT_DOMAIN symbol will be created + elsewhere, so we don't need to take care of that. + + This is important to do, because of forward references: + The cleanup of undefined types stored in undef_types only uses + STRUCT_DOMAIN symbols to perform the replacement. */ + synonym = (SYMBOL_LANGUAGE (sym) == language_ada && p[-2] != 'T'); + /* Typedef */ SYMBOL_TYPE (sym) = read_type (&p, objfile); @@ -1185,6 +1201,24 @@ define_symbol (CORE_ADDR valu, char *str } add_symbol_to_list (sym, &file_symbols); + + if (synonym) + { + /* Create the STRUCT_DOMAIN clone. */ + struct symbol *struct_sym = (struct symbol *) + obstack_alloc (&objfile->objfile_obstack, sizeof (struct symbol)); + + *struct_sym = *sym; + SYMBOL_CLASS (struct_sym) = LOC_TYPEDEF; + SYMBOL_VALUE (struct_sym) = valu; + SYMBOL_DOMAIN (struct_sym) = STRUCT_DOMAIN; + if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0) + TYPE_NAME (SYMBOL_TYPE (sym)) + = obconcat (&objfile->objfile_obstack, "", "", + DEPRECATED_SYMBOL_NAME (sym)); + add_symbol_to_list (struct_sym, &file_symbols); + } + break; case 'T': --G4iJoqBmSsgzjUCe--