From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19576 invoked by alias); 9 Feb 2007 19:40:15 -0000 Received: (qmail 19563 invoked by uid 22791); 9 Feb 2007 19:40:13 -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 19:40:06 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-nile.gnat.com (Postfix) with ESMTP id 2E6FD48CC63 for ; Fri, 9 Feb 2007 14:40:03 -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 05969-01-8 for ; Fri, 9 Feb 2007 14:40:03 -0500 (EST) Received: from takamaka.act-europe.fr (unknown [70.71.0.212]) by nile.gnat.com (Postfix) with ESMTP id 7C45C48CBF7 for ; Fri, 9 Feb 2007 14:40:02 -0500 (EST) Received: by takamaka.act-europe.fr (Postfix, from userid 1000) id A237E34C099; Fri, 9 Feb 2007 11:41:07 -0800 (PST) Date: Fri, 09 Feb 2007 19:40:00 -0000 From: Joel Brobecker To: gdb-patches@sourceware.org Subject: [RFA] Enhance stabs reader to better deal with forward references Message-ID: <20070209194107.GA3365@adacore.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="/9DWx/yDrRhgMJTb" 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/msg00139.txt.bz2 --/9DWx/yDrRhgMJTb Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 3485 Hello, Yep, you read right, some of us are still stuck with stabs. This is still being used on pa32-hpux and ppc-aix. The case that concerns us, this time, is on ppc-aix. Incidentally, we're trying to add support for DWARF on AIX, and we actually managed to get a first prototype going, but there are still many many details we need to iron out before we declare success. In the meantime, I had this curious failure. We hit this problem only with an old testcase that uses some code that was given to us by a customer, so I cannot send you the entire code. What's interesting, however, is that we're dealing with procedure parameter of type float. The debugging info looks like this: .stabx "float:t243=r8;4;0;",0,140,0 [...FOLLOWED by...] .stabx "incomplete:p268=k243",100,130,0 However, the fun starts after the assembler (we use the native assembler) actually swaps the two stabs. So we end up seeing in the object file the stabs for incomplete BEFORE the stabs for type float. The current stabs reader is not really designed to handle this case, and one could also argue that this is an assembler bug, since we could argue that stabs assumes that the entries should be ordered properly. Nonetheless, it turned out that adding support for misordered entries was relatively easy, at the cost of an extra table. That's not where the fun stops, however. The code handling const types looks like this: case 'k': /* Const qualifier on some type (Sun) */ type = read_type (pp, objfile); type = make_cv_type (1, TYPE_VOLATILE (type), type, dbx_lookup_type (typenums)); break; In our case, the "make_type" call ended up returning an undefined type, and then we end up making a "const" copy of that undefined type when calling "make_cv_type". The problem is that type 268 (our const type) is "complete", and no future stabs entry will ammend it. So even though I some handling for forward references of the kind above, this was not sufficient because the type attached to our parameter was still an undefined type. That's why I modified this part of the code to make the cv type only when the target type was already defined. Otherwise, we give up the "const" qualifier and reuse the target type instead. We know that this target type will be fixed up later, so our parameter will have a defined type, and we'll be able to print it. We end up losing the "const" qualifier, but this is still way better than not having any type at all. 2007-02-08 Joel Brobecker * stabsread.c (add_undefined_type): Add extra parameter. Now handles nameless types separately. (struct nat): New type. (noname_undefs, noname_undefs_allocated, noname_undefs_length): New static variables. (read_type): Update calls to add_undefined_type. Do not create an equivalent cv type if the type referenced has not been defined yet. (add_undefined_type_noname): New function. (add_undefined_type_1): Renames from add_undefined_type. (cleanup_undefined_types_noname): New function. (cleanup_undefined_types_1): Renames cleanup_undefined_types. (cleanup_undefined_types): New handles nameless types separately. (_initialize_stabsread): Initialize our new static constants. Tested on ppc-aix and x86-linux, no regression. Fixes the problem at hand. OK to apply? Thanks, -- Joel --/9DWx/yDrRhgMJTb Content-Type: text/plain; charset=us-ascii Content-Description: incomplete.diff Content-Disposition: attachment; filename="stabs-public3.diff" Content-length: 7308 Index: stabsread.c =================================================================== RCS file: /cvs/src/src/gdb/stabsread.c,v retrieving revision 1.86 diff -u -p -r1.86 stabsread.c --- stabsread.c 9 Jan 2007 17:58:58 -0000 1.86 +++ stabsread.c 9 Feb 2007 02:30:58 -0000 @@ -147,7 +147,7 @@ static struct type *read_array_type (cha static struct field *read_args (char **, int, struct objfile *, int *, int *); -static void add_undefined_type (struct type *); +static void add_undefined_type (struct type *, int[2]); static int read_cpp_abbrev (struct field_info *, char **, struct type *, @@ -198,6 +198,20 @@ static int undef_types_allocated; static int undef_types_length; static struct symbol *current_symbol = NULL; +/* Make a list of nameless type that are undefined. + This happens when another type is referenced by its number + before this type is actually defined. For instance "t(0,1)=k(0,2)" + and type (0,2) is defined only later. */ + +struct nat +{ + int typenums[2]; + struct type *type; +}; +static struct nat *noname_undefs; +static int noname_undefs_allocated; +static int noname_undefs_length; + /* Check for and handle cretinous stabs symbol name continuation! */ #define STABS_CONTINUE(pp,objfile) \ do { \ @@ -1413,7 +1427,7 @@ read_type (char **pp, struct objfile *ob doesn't get patched up by the time we're done reading. */ if (TYPE_CODE (type) == TYPE_CODE_UNDEF) - add_undefined_type (type); + add_undefined_type (type, typenums); return type; } @@ -1539,7 +1553,7 @@ again: INIT_CPLUS_SPECIFIC (type); TYPE_FLAGS (type) |= TYPE_FLAG_STUB; - add_undefined_type (type); + add_undefined_type (type, typenums); return type; } @@ -1706,14 +1720,31 @@ again: case 'k': /* Const qualifier on some type (Sun) */ type = read_type (pp, objfile); - type = make_cv_type (1, TYPE_VOLATILE (type), type, - dbx_lookup_type (typenums)); + /* If the referenced type has not been defined yet, we cannot + make a const copy of it. Otherwise, we would make a const + copy of an undefined type, which would be an undefined type. + Instead, we discard the constant type qualifier and use the + referenced type instead. We know that the referenced type + will be fixed up later (when it is actually defined), whereas + the constant type copy won't. We end up losing the "constant" + qualifier but that is still better than ending up with an + undefined type. */ + if (TYPE_CODE (type) != TYPE_CODE_UNDEF) + type = make_cv_type (1, TYPE_VOLATILE (type), type, + dbx_lookup_type (typenums)); + else + *dbx_lookup_type (typenums) = type; break; case 'B': /* Volatile qual on some type (Sun) */ type = read_type (pp, objfile); - type = make_cv_type (TYPE_CONST (type), 1, type, - dbx_lookup_type (typenums)); + /* Same as above for const types: We create the volatile type + only if the type being referenced has already been defined. */ + if (TYPE_CODE (type) != TYPE_CODE_UNDEF) + type = make_cv_type (TYPE_CONST (type), 1, type, + dbx_lookup_type (typenums)); + else + *dbx_lookup_type (typenums) = type; break; case '@': @@ -4136,13 +4167,33 @@ fix_common_block (struct symbol *sym, in -/* What about types defined as forward references inside of a small lexical - scope? */ -/* Add a type to the list of undefined types to be checked through - once this file has been read in. */ +/* Add {TYPE, TYPENUMS} to the NONAME_UNDEFS vector. + See add_undefined_type for more details. */ + +static void +add_undefined_type_noname (struct type *type, int typenums[2]) +{ + struct nat nat; + + nat.typenums[0] = typenums [0]; + nat.typenums[1] = typenums [1]; + nat.type = type; + + if (noname_undefs_length == noname_undefs_allocated) + { + noname_undefs_allocated *= 2; + noname_undefs = (struct nat *) + xrealloc ((char *) noname_undefs, + noname_undefs_allocated * sizeof (struct nat)); + } + noname_undefs[noname_undefs_length++] = nat; +} + +/* Add TYPE to the UNDEF_TYPES vector. + See add_undefined_type for more details. */ static void -add_undefined_type (struct type *type) +add_undefined_type_1 (struct type *type) { if (undef_types_length == undef_types_allocated) { @@ -4154,6 +4205,48 @@ add_undefined_type (struct type *type) undef_types[undef_types_length++] = type; } +/* What about types defined as forward references inside of a small lexical + scope? */ +/* Add a type to the list of undefined types to be checked through + once this file has been read in. + + In practice, we actually maintain two such list: The first list + (UNDEF_TYPES) is used for types whose name has been provided, and + concerns forward references (eg 'xs' or 'xu' forward references); + the second list (NONAME_UNDEFS) is used for types whose name is + unknown at creation time, because they were referenced through + their type number before the actual type was declared. + This function actually adds the given type to the proper list. */ + +static void +add_undefined_type (struct type *type, int typenums[2]) +{ + if (TYPE_TAG_NAME (type) == NULL) + add_undefined_type_noname (type, typenums); + else + add_undefined_type_1 (type); +} + +/* Try to fix all undefined types pushed on the UNDEF_TYPES vector. */ + +void +cleanup_undefined_types_noname (void) +{ + int i; + + for (i = 0; i < noname_undefs_length; i++) + { + struct nat nat = noname_undefs[i]; + struct type **type; + + type = dbx_lookup_type (nat.typenums); + if (nat.type != *type && TYPE_CODE (*type) != TYPE_CODE_UNDEF) + replace_type (nat.type, *type); + } + + noname_undefs_length = 0; +} + /* Go through each undefined type, see if it's still undefined, and fix it up if possible. We have two kinds of undefined types: @@ -4163,8 +4256,9 @@ add_undefined_type (struct type *type) TYPE_CODE_STRUCT, TYPE_CODE_UNION: Structure whose fields were not yet defined at the time a pointer to it was made. Fix: Do a full lookup on the struct/union tag. */ + void -cleanup_undefined_types (void) +cleanup_undefined_types_1 (void) { struct type **type; @@ -4225,6 +4319,16 @@ cleanup_undefined_types (void) undef_types_length = 0; } +/* Try to fix all the undefined types we ecountered while processing + this unit. */ + +void +cleanup_undefined_types (void) +{ + cleanup_undefined_types_1 (); + cleanup_undefined_types_noname (); +} + /* Scan through all of the global symbols defined in the object file, assigning values to the debugging symbols that need to be assigned to. Get these symbols from the minimal symbol table. */ @@ -4460,4 +4564,9 @@ _initialize_stabsread (void) undef_types_length = 0; undef_types = (struct type **) xmalloc (undef_types_allocated * sizeof (struct type *)); + + noname_undefs_allocated = 20; + noname_undefs_length = 0; + noname_undefs = (struct nat *) + xmalloc (noname_undefs_allocated * sizeof (struct nat)); } --/9DWx/yDrRhgMJTb--