Another segmentation fault in GDB 4.17 (and a patch for it)
Peter.Schauer
Peter.Schauer@regent.e-technik.tu-muenchen.de
Wed Jul 1 02:39:00 GMT 1998
Sorry, I do not intend to spend time on any F77 support fixes, as I am lacking
the required Fortran expertise.
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.
> 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.
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.
> + /* 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.
> Hello again,
>
> Peter Schauer kindly provided a fix to the gdb segmentation fault
> which I reported recently (g77 compiled Fortran functions passing
> character strings as CHARACTER*(*) arguments).
> 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.
> By default then, only the first character is displayed but the '@'
> modifier to the print command can of course be used to show more.
> The actual length of the character string is passed in an additional
> variable '__g77_length_something' for a string named 'something'.
>
> This variable caused another gdb segmentation fault with the same
> example program:
>
> Program xyz
> Character c*30
> c = 'This is only a test'
> Call sub(c)
> End
>
> Subroutine sub ( c )
> Character c*(*)
> Write(*,*) 'C=''',c,''''
> Write(*,*) 'LEN(C)=',Len(c)
> End
>
> Example session:
> (gdb) break x.f:4
> Breakpoint 1 at 0x8048dcb: file x.f, line 4.
> (gdb) run
> Starting program: /home/users/bernlohr/x
>
> Breakpoint 1, MAIN__ () at x.f:4
> 4 Call sub(c)
> Current language: auto; currently fortran
> (gdb) print c
> $1 = (84 'T', 104 'h', 105 'i', 115 's', 32 ' ', 105 'i', 115 's', 32 ' ', 111 'o', 110 'n', 108 'l', 121 'y', 32 ' ', 97 'a', 32 ' ', 116 't', 101 'e', 115 's', 116 't', 32 ' ', 32 ' ', 32 ' ', 32 ' ', 32 ' ', 32 ' ', 32 ' ', 32 ' ', 32 ' ', 32 ' ', 32 ' ')
> (gdb) step
> sub_ (c=0xbffff8c8, __g77_length_c=30) at x.f:9
> 9 Write(*,*) 'C=''',c,''''
> (gdb) print c
> $2 = (PTR TO -> ( char (*))) 0xbffff8c8
> (gdb) print *c
> $3 = (<assumed size array> 84 'T')
> (gdb) whatis c
> type = PTR TO -> ( char (*))
> (gdb) whatis __g77_length_c
> Segmentation fault
>
> That's what gdb's core dump tells:
> GNU gdb 4.17
> Copyright 1998 Free Software Foundation, Inc.
> GDB is free software, covered by the GNU General Public License, and you are
> welcome to change it and/or distribute copies of it under certain conditions.
> Type "show copying" to see the conditions.
> There is absolutely no warranty for GDB. Type "show warranty" for details.
> This GDB was configured as "i586-pc-linux-gnu"...
> Core was generated by `gdb/gdb /home/users/bernlohr/t'.
> Program terminated with signal 11, Segmentation fault.
> find_solib: Can't read pathname for load map: Input/output error
>
> #0 0x80ee366 in f_type_print_base (type=0x81c9d64, stream=0x819da68, show=-1,
> level=0) at f-typeprint.c:414
> 414 if (STREQ (TYPE_NAME (type), "char"))
> (gdb) where
> #0 0x80ee366 in f_type_print_base (type=0x81c9d64, stream=0x819da68, show=-1,
> level=0) at f-typeprint.c:414
> #1 0x80edb7c in f_print_type (type=0x81c9d64, varstring=0x818626c "",
> stream=0x819da68, show=-1, level=0) at f-typeprint.c:69
> #2 0x80eae00 in type_print (type=0x81c9d64, varstring=0x818626c "",
> stream=0x819da68, show=-1) at typeprint.c:63
> #3 0x80eae90 in whatis_exp (exp=0x81b1ccf "__g77_length_c", show=-1)
> at typeprint.c:88
> #4 0x80eaece in whatis_command (exp=0x81b1ccf "__g77_length_c", from_tty=1)
> at typeprint.c:104
> #5 0x8100b23 in execute_command (p=0x81b1cdc "c", from_tty=1) at top.c:1259
> #6 0x8100d06 in command_loop () at top.c:1339
> #7 0x81099e5 in main (argc=2, argv=0xbffff910) at main.c:554
>
> The fatal problem was that a NULL pointer was passed to the STREQ macro
> which tries to optimize for speed and compares first the first character of
> 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).
> Well, after that fix the 'whatis __g77_length_c' still shows a wrong type
> (apparently due to incorrect debugging info from g77) but at least gdb
> doesn't die anymore.
>
> Once being at it, I noticed that g77 declares character strings as
> arrays of characters in the debugging info. That is the reason why
> the first 'print c' above results in such an ugly output. Therefore,
> I decided that (at least for the present g77) characters of arrays
> should instead be declared as character strings (TYPE_CODE_STRING
> instead of TYPE_CODE_ARRAY). See the patch below.
>
> With the final patched gdb the above gdb session again:
> (gdb) break x.f:4
> Breakpoint 1 at 0x8048dcb: file x.f, line 4.
> (gdb) run
> Starting program: /home/users/bernlohr/x
>
> Breakpoint 1, MAIN__ () at x.f:4
> 4 Call sub(c)
> Current language: auto; currently fortran
> (gdb) print c
> $1 = 'This is only a test', ' ' <repeats 11 times>
> (gdb) step
> sub_ (c=0xbffff8b0, __g77_length_c=30) at x.f:9
> 9 Write(*,*) 'C=''',c,''''
> (gdb) print c
> $2 = (PTR TO -> ( character*(*) )) 0xbffff8b0
> (gdb) print *c
> $3 = 'T'
> (gdb) whatis c
> type = PTR TO -> ( character*(*) )
> (gdb) whatis __g77_length_c
> type = character
> (gdb) print __g77_length_c
> $4 = 30
> (gdb) print *c@30
> $5 = ('T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'o', 'n', 'l', 'y', ' ', 'a', ' ', 't', 'e', 's', 't', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ')
>
> By the way, I would also like to 'print' a substring as a Fortran expression, e.g.
> 'print C(5:20)', but I can only 'print *(c+4)@16'. I will leave that as an
> exercise.
>
> Kind regards,
> Konrad Bernloehr
>
> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
> Dr. Konrad Bernloehr, Institut fuer Kernphysik III
> Forschungszentrum Karlsruhe, 76021 Karlsruhe, Germany
> E-mail: bernlohr@ik3.fzk.de
>
>
> *** gdb/gdbtypes.c.orig Mon Jun 29 12:05:04 1998
> --- gdb/gdbtypes.c Tue Jun 30 18:10:17 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,465 ----
> 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);
> 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 to avoid chunk output */
> + TYPE_LENGTH (result_type) = 1;
> + 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));
> *** gdb/defs.h.orig Tue Jun 30 13:16:27 1998
> --- gdb/defs.h Tue Jun 30 13:16:27 1998
> ***************
> *** 77,85 ****
> /* Gdb does *lots* of string compares. Use macros to speed them up by
> avoiding function calls if the first characters are not the same. */
>
> ! #define STRCMP(a,b) (*(a) == *(b) ? strcmp ((a), (b)) : (int)*(a) - (int)*(b))
> ! #define STREQ(a,b) (*(a) == *(b) ? !strcmp ((a), (b)) : 0)
> ! #define STREQN(a,b,c) (*(a) == *(b) ? !strncmp ((a), (b), (c)) : 0)
>
> /* The character GNU C++ uses to build identifiers that must be unique from
> the program's identifiers (such as $this and $$vptr). */
> --- 77,85 ----
> /* Gdb does *lots* of string compares. Use macros to speed them up by
> avoiding function calls if the first characters are not the same. */
>
> ! #define STRCMP(a,b) ((a)!=NULL && (b)!=NULL ? (*(a) == *(b) ? strcmp ((a), (b)) : (int)*(a) - (int)*(b)) : 999)
> ! #define STREQ(a,b) ((a)!=NULL && (b)!=NULL ? (*(a) == *(b) ? !strcmp ((a), (b)) : 0) : 999)
> ! #define STREQN(a,b,c) ((a)!=NULL && (b)!=NULL ? (*(a) == *(b) ? !strncmp ((a), (b), (c)) : 0) : 999)
>
> /* The character GNU C++ uses to build identifiers that must be unique from
> the program's identifiers (such as $this and $$vptr). */
>
>
--
Peter Schauer pes@regent.e-technik.tu-muenchen.de
More information about the Gdb
mailing list