This is the mail archive of the gdb-patches@sourceware.cygnus.com mailing list for the GDB project. See the GDB home page for more information.


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

Third segmentation fault in GDB 4.17 and comments on previous patch


Hello again,

While looking into GDB 4.17 for Fortran debugging information I have now
encountered the third (different) GDB segmentation fault in a week.
Before going into the new one, let me comment first on Peter Schauer's
comments to my patch from yesterday:

Peter Schauer wrote:

> Sorry, I do not intend to spend time on any F77 support fixes, as I am lacking
> the required Fortran expertise.

I have the impression that GDB really needs someone for F77 support and
that the GDB project needs better communication with the G77 project.
(I did not mean me. I just wanted to use gdb under the surface of ddd.)
The same appears to apply to other non-C/C++ languages like Pascal.

> I have a few objections to the proposed patches however:
> 
> > In fact, the second part of his patch isn't needed and the first part 
> > needs a little modification to avoid junk output. My suggested solution
> > (appended below) is to fix the length of these character strings to 1.
> 
> This might work for Fortran, but it will break C and C++, where
> dynamic arrays are represented with a type length of zero.
> Perhaps the proper fix is to remove the arbitrary output of one element
> for Fortran assumed size arrays in f-valprint.c, which will get rid of
> the junk output when printing an assumed size array.

Possible side-effects can be easily avoided by restricting the length of 1
to the Fortran language (see also complete patch below):
      if ( current_subfile->language == language_fortran )
      	 TYPE_LENGTH (result_type) = 1;
      else
      	 TYPE_LENGTH (result_type) = 0;
There are no dynamic arrays in Fortran and the actual size of an array
is never passed to a subroutine. Instead of declaring a subroutine argument
      REAL MATRIX(9,*)
you can always use (except for readability)
      REAL MATRIX(9,1)
(and many legacy Fortran programs actually do just that).
Only for character strings is the length passed to a subroutine.
Perhaps the proper treatment would be the job of function
f77_get_dynamic_length_of_aggregate function in gdb/f-valprint.c.
But I don't see how it could be done there.

> > both strings. I modified the STREQ, STREQN, and STRCMP macros in gdb/defs.h
> > to catch such things in general (without too much tradeoff in speed, I hope).
> 
> These macros are used in inner loops, so I think that we should not
> do the extra test, and the calling code in f-typeprint.c should get fixed.

Ok, if that is really so important, I redraw yesterdays suggested patch to
gdb/defs.h and suggest one for gdb/f_typeprint.f (see below). 
The return values 999 for STREQ and STREQN would be wrong anyway (should be 0).
(I still think that gdb needs some action to become more robust.)

> Perhaps g77 should output the type of __g77_length_* as `integer*4', to
> avoid an `Invalid type code' message from GDB, but I don't know.

That is probably true but I am not involved in the g77 development and perhaps
the g77 developers should comment on that point.

> > +   /* Fortran character strings were told by g77 to be character arrays */
> > +   /* which can be fixed here. */
> > +   if ( TYPE_NAME(element_type) != NULL && 
> > +        current_subfile->language == language_fortran )
> > +      if ( STRCMP(TYPE_NAME(element_type),"char") == 0 )
> > +         TYPE_CODE (result_type) = TYPE_CODE_STRING;
> 
> If we really want to do this, then it should be done in the symbol reader.
> A cleaner solution might be to handle character arrays explicitly
> in f-valprint.c:f77_print_array_1.

Since the variable type TYPE_CODE_STRING is already known by GDB and is properly 
treated in f-valprint.c, I don't see a need to change something there.
But I admit that it might perhaps be appropriate to make this change of
the result type in the symbol reader. However, calling create_string_type()
instead of create_array_type() doesn't do anything else than first call
create_array_type() and then setting the type to TYPE_CODE_STRING.
Perhaps g77 should (in future) better emit the right debugging information.

To demonstrate that character arrays and character strings mean something
different in Fortran and that my patch treats both properly, I changed my 
example program a little bit.
I also included a REAL array to show the effect leading to the third
segmentation fault with a non-character variable:

      Program xyz
      Character c*30
      Character d(5)
      Real z(3,4)
      c = 'This is only a test'
      d(1) = 'a'
      d(2) = 'b'
      d(3) = 'c'
      Call sub1(c,z,d)
      End
      
      Subroutine sub1 ( c, z, d )
      Character c*(*)
      Character d(*)
      Real z(3,*)
      Write(*,*) 'C=''',c,''''
      Write(*,*) 'LEN(C)=',Len(c)
      Write(*,*) 'D(1...3)=',(d(i),i=1,3)
      End

Note that 'd' now is not a character string but an array of characters,
which actually means an array of five CHARACTER*1 strings (and therefore
'__g77_length_d' below is correctly 1 and not 5).

Example debugging session (with original gdb 4.17 or with yesterday's patch):
   (gdb) break t.f:16
   Breakpoint 1 at 0x8048e32: file t.f, line 16.
   (gdb) run
   Starting program: /home/users/bernlohr/t 

   Breakpoint 1, sub1_ (c=0xbffff928, z=0xbffff8f0, d=0xbffff920, 
       __g77_length_c=30, __g77_length_d=1) at t.f:16
   16            Write(*,*) 'C=''',c,''''
   Current language:  auto; currently fortran
   (gdb) whatis z
   type = PTR TO -> ( real*4 (3,2147483647))
   (gdb) whatis *z
   Segmentation fault (core dumped)
Second attempt (with yesterdays patch but the same segmentation fault
happens with the original gdb 4.17, just 'whatis d' is different):
   (gdb) break t.f:16
   Breakpoint 1 at 0x8048e32: file t.f, line 16.
   (gdb) run
   Starting program: /home/users/bernlohr/t 

   Breakpoint 1, sub1_ (c=0xbffff928, z=0xbffff8f0, d=0xbffff920, 
       __g77_length_c=30, __g77_length_d=1) at t.f:16
   16            Write(*,*) 'C=''',c,''''
   Current language:  auto; currently fortran
   (gdb) whatis d
   type = PTR TO -> ( character*1 (2147483647))
   (gdb) whatis *d
   Segmentation fault (core dumped)

The second core dump says:
#0  0x8176470 in memset ()
#1  0x2 in ?? ()
#2  0x8060fc6 in evaluate_subexp_standard (expect_type=0x0, exp=0x8344920, 
    pos=0xbffff800, noside=EVAL_AVOID_SIDE_EFFECTS) at eval.c:1475
#3  0x8062199 in evaluate_subexp (expect_type=0x0, exp=0x8344920, 
    pos=0xbffff800, noside=EVAL_AVOID_SIDE_EFFECTS) at eval.c:64
#4  0x8059f3e in evaluate_type (exp=0x8344920) at eval.c:154
#5  0x80e89ed in whatis_exp (exp=0x81e19c7 "*d", show=-1) at typeprint.c:82
#6  0x80e8a6e in whatis_command (exp=0x81e19c7 "*d", from_tty=1)
    at typeprint.c:104
#7  0x80fe643 in execute_command (p=0x81e19c8 "d", from_tty=1) at top.c:1259
#8  0x80fe826 in command_loop () at top.c:1339
#9  0x8107505 in main (argc=2, argv=0xbffff9dc) at main.c:554

The function not shown (#1) for unknown reason is value_zero() in gdb/valops.c.
value_zero() first calls allocate_type to allocate 2^31-1 bytes (which went
surprisingly smooth on my little Linux PC). One surprising thing there was
that for that purpose first xmalloc is called (in gdb/utils.c, with
argument type: 'size_t') which calls xmmalloc (argument type: 'long') which 
calls mmalloc (argument type: 'size_t'). What about machines where the length 
of 'size_t' is different from that of 'long' ???
The really bad thing happens when value_zero() calls memset to initialize
these 2^31-1 bytes to zero.
Apart from the resulting segmentation fault I was surprised to see that one
has to initialize two gigabytes of memory to zero to see what type of
variable '*d' is.

My suggested fix for that new segmentation fault goes again in gdb/gdbtypes.c
(and is for Fortran only to avoid side-effects on other languages although
I cannot imagine that INT_MAX (because type->fields[...].loc.bitpos is 'int')
would be a good size of an array in any language).

    Kind regards,
    Konrad Bernloehr

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       Dr. Konrad Bernloehr,  Institut fuer Kernphysik III
     Forschungszentrum Karlsruhe,  76021 Karlsruhe,  Germany
                   E-mail: bernlohr@ik3.fzk.de

The following patch prevents all three segmentation faults and includes
the second part of Peter Schauer's patch to gdb/gdbtypes.c (which is not 
needed for the segmentation faults that I encountered):

*** gdb/gdbtypes.c.orig Mon Jun 29 12:05:04 1998
--- gdb/gdbtypes.c      Thu Jul  2 14:55:27 1998
***************
*** 31,36 ****
--- 31,37 ----
  #include "value.h"
  #include "demangle.h"
  #include "complaints.h"
+ #include "buildsym.h"
  
  /* These variables point to the objects
     representing the predefined C data types.  */
***************
*** 436,447 ****
--- 437,476 ----
        result_type = alloc_type (TYPE_OBJFILE (range_type));
      }
    TYPE_CODE (result_type) = TYPE_CODE_ARRAY;
+   /* Fortran character strings were told by g77 to be character arrays */
+   /* which can be fixed here. */
+   if ( TYPE_NAME(element_type) != NULL && 
+        current_subfile->language == language_fortran )
+      if ( STRCMP(TYPE_NAME(element_type),"char") == 0 )
+         TYPE_CODE (result_type) = TYPE_CODE_STRING;
    TYPE_TARGET_TYPE (result_type) = element_type;
    if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
      low_bound = high_bound = 0;
    CHECK_TYPEDEF (element_type);
+ 
+   /* Fix to avoid segmentation fault for 'whatis *var' where 'var' */
+   /* is for example a Fortran subroutine argument declared as an */
+   /* array with its last dimension undetermined, like 'REAL VAR(3,*)'. */
+   if ( high_bound == INT_MAX &&
+        current_subfile->language == language_fortran )
+     high_bound = TYPE_HIGH_BOUND(range_type) = 1;
+ 
    TYPE_LENGTH (result_type) =
      TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
+ 
+   /* Fix to avoid segmentation faults when printing for example */
+   /* Fortran variables passed as CHARACTER*(*). */
+   if (low_bound > high_bound)
+     {
+       /* A minimum length of 1 is needed for Fortran to avoid chunk output */
+       if ( current_subfile->language == language_fortran )
+                TYPE_LENGTH (result_type) = 1;
+       else
+                TYPE_LENGTH (result_type) = 0;
+       if (high_bound == -1)
+         TYPE_ARRAY_UPPER_BOUND_TYPE(result_type) = BOUND_CANNOT_BE_DETERMINED;
+     }
+ 
    TYPE_NFIELDS (result_type) = 1;
    TYPE_FIELDS (result_type) =
      (struct field *) TYPE_ALLOC (result_type, sizeof (struct field));
***************
*** 996,1008 ****
               && (TYPE_CODE (range_type = TYPE_FIELD_TYPE (type, 0))
                   == TYPE_CODE_RANGE))
        {
!         /* Now recompute the length of the array type, based on its
             number of elements and the target type's length.  */
!         TYPE_LENGTH (type) =
!           ((TYPE_FIELD_BITPOS (range_type, 1)
!             - TYPE_FIELD_BITPOS (range_type, 0)
!             + 1)
!            * TYPE_LENGTH (target_type));
          TYPE_FLAGS (type) &= ~TYPE_FLAG_TARGET_STUB;
        }
        else if (TYPE_CODE (type) == TYPE_CODE_RANGE)
--- 1025,1048 ----
               && (TYPE_CODE (range_type = TYPE_FIELD_TYPE (type, 0))
                   == TYPE_CODE_RANGE))
        {
! 
!           LONGEST low_bound, high_bound;
! 
!         /* Now recompute the length of the array type, based on its
             number of elements and the target type's length.  */
!           low_bound = TYPE_FIELD_BITPOS (range_type, 0);
!           high_bound = TYPE_FIELD_BITPOS (range_type, 1);
! 
!           if (low_bound > high_bound)
!             {
!             TYPE_LENGTH (type) = 1;
!             if (high_bound == -1)
!               TYPE_ARRAY_UPPER_BOUND_TYPE(type)
!                 = BOUND_CANNOT_BE_DETERMINED;
!             }
!           else
!             TYPE_LENGTH (type) =
!               (high_bound - low_bound + 1) * TYPE_LENGTH (target_type);
          TYPE_FLAGS (type) &= ~TYPE_FLAG_TARGET_STUB;
        }
        else if (TYPE_CODE (type) == TYPE_CODE_RANGE)
*** gdb/f-typeprint.c.orig      Thu Jul  2 09:12:34 1998
--- gdb/f-typeprint.c   Thu Jul  2 09:12:34 1998
***************
*** 411,417 ****
           through as TYPE_CODE_INT since dbxstclass.h is so
           C-oriented, we must change these to "character" from "char".  */
  
!       if (STREQ (TYPE_NAME (type), "char"))
        fprintf_filtered (stream, "character");
        else
        goto default_case;
--- 411,419 ----
           through as TYPE_CODE_INT since dbxstclass.h is so
           C-oriented, we must change these to "character" from "char".  */
  
!       if ( TYPE_NAME (type) == NULL )
!          goto default_case;
!       else if (STREQ (TYPE_NAME (type), "char"))
        fprintf_filtered (stream, "character");
        else
        goto default_case;