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] |
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). */