From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jim Kingdon To: gdb-patches@sourceware.cygnus.com Subject: Problem with "next" in main on sparc Date: Mon, 01 Nov 1999 11:38:00 -0000 Message-id: <199911011938.OAA32716@devserv.devel.redhat.com> X-SW-Source: 1999-q4/msg00137.html Here is a bug in which GDB gets in an infinite loop. The problem was with the following change. I'm not sure what the rationale for this change was, and I will point out that the code which was checked in didn't match the ChangeLog entry. In fact the code would seem to disable most uses of the ->frame field, so it would look like it causes problems other than this one. 1998-09-08 Jason Molenda (jsm@bugshack.cygnus.com) * breakpoint.c (bpstat_stop_status): Declare a bp match if the current fp matches the bp->fp OR if the current fp is less than the bp->fp if we're looking at a bp_step_resume breakpoint. After the test case I have enclosed a patch to revert the 1998-09-08 change. [kingdon@bart jakub]$ cat try.c int foo = 1; int main(void) { foo = 2; } [kingdon@bart jakub]$ gcc -g try.c [kingdon@bart jakub]$ ./gdb-6 a.out GNU gdb 19991004 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 "sparc-redhat-linux"... (gdb) b main Breakpoint 1 at 0x103a8: file try.c, line 4. (gdb) run Starting program: /home/devel/kingdon/zwork/jakub/a.out Breakpoint 1, main () at try.c:4 4 foo = 2; (gdb) next 5 } (gdb) [infinite loop, hit ^C] Program received signal SIGINT, Interrupt. 0x70049f00 in __libc_start_main () at ../sysdeps/generic/libc-start.c:120 120 ../sysdeps/generic/libc-start.c: No such file or directory. (gdb) quit The program is running. Exit anyway? (y or n) y 1999-08-13 Jim Kingdon < http://developer.redhat.com/ > * breakpoint.c (bpstat_stop_status): Revert 1998-09-08 change to ->frame matching. The change did not match the ChangeLog entry, looked fishy, and caused infinite stepping when running "next" from main on sparc. Thanks to Jakub for the report. [kingdon@bart gdb]$ diff -u breakpoint.c.orig breakpoint.c --- breakpoint.c.orig Mon Oct 4 21:35:17 1999 +++ breakpoint.c Mon Nov 1 14:09:41 1999 @@ -2345,9 +2345,8 @@ real_breakpoint = 1; } - if (b->frame && b->frame != (get_current_frame ())->frame && - (b->type == bp_step_resume && - (INNER_THAN (get_current_frame ()->frame, b->frame)))) + if (b->frame && + b->frame != (get_current_frame ())->frame) bs->stop = 0; else { >From crash@cygnus.com Mon Nov 01 12:04:00 1999 From: Jason Molenda To: Jim Kingdon Cc: gdb-patches@sourceware.cygnus.com Subject: Re: Problem with "next" in main on sparc Date: Mon, 01 Nov 1999 12:04:00 -0000 Message-id: <19991101120357.B5862@cygnus.com> References: <199911011938.OAA32716@devserv.devel.redhat.com> X-SW-Source: 1999-q4/msg00138.html Content-length: 2978 On Mon, Nov 01, 1999 at 02:38:31PM -0500, Jim Kingdon wrote: > > 1998-09-08 Jason Molenda (jsm@bugshack.cygnus.com) > > * breakpoint.c (bpstat_stop_status): Declare a bp match if the > current fp matches the bp->fp OR if the current fp is less than > the bp->fp if we're looking at a bp_step_resume breakpoint. Ack, ill considered changes come back to haunt me. :-) Let me look this over later today so I can figure out if I'm a dork or not before I comment in depth. I'm fully prepared to admit a mistake, but I want to look it over a little more closely to figure out what I was doing. FWIW here in my original summary of the problem: When you do a 'step' on the last line in a function, the program runs without stopping. This is because Purify inserts calls to the Purify code right in the program epilogue. GDB detects these calls out to code with no line numbers, sets a step_resume_breakpoint on the instruction following the branch insn, and runs the inferior until it hits the breakpoint. The problem is where the FP has already been rolled back--we're right at the very end of the epilogue and we make one more call to the Purify code. When the breakpoint set after the branch is hit, bpstat_stop_status sees that there is a breakpoint at $pc, but bpstat_stop_status() checks the FP in the breakpoint (b->frame) against the current FP. The FP in the breakpoint is the correct one for our function, but the current FP has been rolled back to the caller function already--they do not match. w_f_i does not remove the gdb_step_resume breakpoint and does another PT_CONTINUE via ptrace() because it thinks it still has to hit the breakpoint. The program continues until it exits. Why did the frame address get set incorrectly in the breakpoint? We set the step_resume_breakpoint _after_ we find outself in the no-line-number code (see the code around "/* A subroutine call has happened. */" in w_f_i()). set_momentary_breakpoint() sets up the breakpoint for us at the SAVED_PC_AFTER_CALL address and we set the 'frame' member of the breakpoint to be step_frame_address. And here is the cvs log message I added when I checked this in: With a bp_step_resume type breakpoint, the frame pointer check exists in case we recurse and execute the same text section--we want to not stop there because it would confuse the user. So gdb checks to see that the frame pointer matches the one recorded in the breakpoint. If the current frame pointer is less than the frame pointer recorded in the breakpoint, then something odd is happened and we should declare that we're at the breakpoint so that we clear it out. This happens in Purify instrumented executables on PA systems, at least. They insert some calls out to Purify code in the function epilogue and it confuses GDB (which assumes that the frame pointer does not move around through the entire execution of a function). Jason >From guo@cup.hp.com Mon Nov 01 12:16:00 1999 From: Jimmy Guo To: gdb-patches@sourceware.cygnus.com Subject: (patch) hpjyg04: c-typeprint.c c-valprint.c Date: Mon, 01 Nov 1999 12:16:00 -0000 Message-id: X-SW-Source: 1999-q4/msg00139.html Content-length: 6308 Small patch for c-typeprint.c and c-typeprint.c -- see ChangeLog. - Jimmy Guo, guo@cup.hp.com Index: gdb/ChangeLog /opt/gnu/bin/diff -r -c -N /view/guo.wdb.c//CLO/Components/WDB/Src/gnu/gdb/ChangeLog gdb/ChangeLog *** /view/guo.wdb.c//CLO/Components/WDB/Src/gnu/gdb/ChangeLog Mon Nov 1 11:30:10 1999 --- gdb/ChangeLog Mon Nov 1 12:10:23 1999 *************** *** 1,4 **** --- 1,12 ---- 1999-11-01 Jimmy Guo + * c-typeprint.c + (c_type_print_varspec_prefix,c_type_print_varpsec_suffix): Add + TYPE_CODE_TEMPLATE case and default case. + (c_type_print_base): Revise how demangled_no_class is found; + print '}' before printing local file:line info. + * c-valprint.c (c_value_print): print reference type to class. + + 1999-11-01 Jimmy Guo * buildsym.h (add_free_pendings): Declare. Index: gdb/c-typeprint.c /opt/gnu/bin/diff -r -c -N /view/guo.wdb.c//CLO/Components/WDB/Src/gnu/gdb/c-typeprint.c gdb/c-typeprint.c *** /view/guo.wdb.c//CLO/Components/WDB/Src/gnu/gdb/c-typeprint.c Fri Oct 29 16:09:22 1999 --- gdb/c-typeprint.c Fri Oct 29 16:25:52 1999 *************** *** 338,346 **** --- 338,350 ---- case TYPE_CODE_BITSTRING: case TYPE_CODE_COMPLEX: case TYPE_CODE_TYPEDEF: + case TYPE_CODE_TEMPLATE: /* These types need no prefix. They are listed here so that gcc -Wall will reveal any types that haven't been handled. */ break; + default: + error ("type not handled in c_type_print_varspec_prefix()"); + break; } } *************** *** 530,538 **** --- 534,546 ---- case TYPE_CODE_BITSTRING: case TYPE_CODE_COMPLEX: case TYPE_CODE_TYPEDEF: + case TYPE_CODE_TEMPLATE: /* These types do not need a suffix. They are listed so that gcc -Wall will report types that may not have been considered. */ break; + default: + error ("type not handled in c_type_print_varspec_suffix()"); + break; } } *************** *** 766,772 **** if (TYPE_HAS_VTABLE (type) && (STREQN (TYPE_FIELD_NAME (type, i), "__vfp", 5))) continue; /* Other compilers */ - /* pai:: FIXME : check for has_vtable < 0 */ if (STREQN (TYPE_FIELD_NAME (type, i), "_vptr", 5) && is_cplus_marker ((TYPE_FIELD_NAME (type, i))[5])) continue; --- 774,779 ---- *************** *** 924,936 **** else { char *p; ! char *demangled_no_class = demangled_name; ! while ((p = strchr (demangled_no_class, ':'))) ! { ! demangled_no_class = p; ! if (*++demangled_no_class == ':') ! ++demangled_no_class; } /* get rid of the static word appended by the demangler */ p = strstr (demangled_no_class, " static"); --- 931,943 ---- else { char *p; ! char *demangled_no_class = strrchr (demangled_name, ':'); ! if (demangled_no_class == NULL) ! demangled_no_class = demangled_name; ! else ! { ! ++demangled_no_class; /* skip over last ':' */ } /* get rid of the static word appended by the demangler */ p = strstr (demangled_no_class, " static"); *************** *** 955,966 **** } } if (TYPE_LOCALTYPE_PTR (type) && show >= 0) fprintfi_filtered (level, stream, " (Local at %s:%d)\n", TYPE_LOCALTYPE_FILE (type), TYPE_LOCALTYPE_LINE (type)); - - fprintfi_filtered (level, stream, "}"); } if (TYPE_CODE (type) == TYPE_CODE_TEMPLATE) goto go_back; --- 962,973 ---- } } + fprintfi_filtered (level, stream, "}"); + if (TYPE_LOCALTYPE_PTR (type) && show >= 0) fprintfi_filtered (level, stream, " (Local at %s:%d)\n", TYPE_LOCALTYPE_FILE (type), TYPE_LOCALTYPE_LINE (type)); } if (TYPE_CODE (type) == TYPE_CODE_TEMPLATE) goto go_back; Index: gdb/c-valprint.c /opt/gnu/bin/diff -r -c -N /view/guo.wdb.c//CLO/Components/WDB/Src/gnu/gdb/c-valprint.c gdb/c-valprint.c *** /view/guo.wdb.c//CLO/Components/WDB/Src/gnu/gdb/c-valprint.c Fri Oct 29 15:49:26 1999 --- gdb/c-valprint.c Mon Nov 1 12:05:17 1999 *************** *** 483,502 **** { /* Pointer to class, check real type of object */ fprintf_filtered (stream, "("); ! type = value_rtti_target_type (val, &full, &top, &using_enc); ! if (type) { /* RTTI entry found */ ! type = lookup_pointer_type (type); ! type_print (type, "", stream, -1); ! } ! else ! { ! /* No RTTI fields, do whatever we can */ ! type = VALUE_ENCLOSING_TYPE (val); ! type_print (type, "", stream, -1); ! fprintf_filtered (stream, " ?"); ! } fprintf_filtered (stream, ") "); } else --- 483,506 ---- { /* Pointer to class, check real type of object */ fprintf_filtered (stream, "("); ! real_type = value_rtti_target_type (val, &full, &top, &using_enc); ! if (real_type) { /* RTTI entry found */ ! if (TYPE_CODE (type) == TYPE_CODE_PTR) ! { ! /* create a pointer type pointing to the real type */ ! type = lookup_pointer_type (real_type); ! } ! else ! { ! /* create a reference type referencing the real type */ ! type = lookup_reference_type (real_type); ! } ! /* Note: When we look up RTTI entries, we don't get any ! information on const or volatile attributes */ ! } ! type_print (type, "", stream, -1); fprintf_filtered (stream, ") "); } else *************** *** 521,526 **** --- 525,532 ---- /* Print out object: enclosing type is same as real_type if full */ return val_print (VALUE_ENCLOSING_TYPE (val), VALUE_CONTENTS_ALL (val), 0, VALUE_ADDRESS (val), stream, format, 1, 0, pretty); + /* Note: When we look up RTTI entries, we don't get any information on + const or volatile attributes */ } else if (type != VALUE_ENCLOSING_TYPE (val)) {