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] |
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] |