This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA/stabs] 't' type declaration is equivalent to 'Tt' for Ada


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 = <incomplete type>
   (gdb) ptype e
   type = access record <incomplete type> 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  <brobecker@adacore.com>

        * 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

Attachment: Tt.diff
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]