Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [patch] infcall: Remove gdb_assert ($sp overflow)
@ 2010-02-19 22:48 Jan Kratochvil
  2010-02-26 22:45 ` Tom Tromey
  2010-02-26 22:53 ` Daniel Jacobowitz
  0 siblings, 2 replies; 8+ messages in thread
From: Jan Kratochvil @ 2010-02-19 22:48 UTC (permalink / raw)
  To: gdb-patches

Hi,

set $sp=0
call something()
->
../../gdb/infcall.c:521: internal-error: call_function_by_hand: Assertion
`(gdbarch_inner_than (gdbarch, 1, 2) && sp <= old_sp) || (gdbarch_inner_than
(gdbarch, 2, 1) && sp >= old_sp)' failed.

as $sp - frame == 0xffffsmth which is not lower than $sp.

It must not be gdb_assert().  It can be an error() but I left it just to do:
	(gdb) set $sp=0
	(gdb) call doubleit (1)
	Cannot access memory at address 0xffffffffffffff78
	(gdb) set $sp=-1
	(gdb) call doubleit (1)
	Cannot access memory at address 0xffffffffffffff68

Unaware how inconvenient is an intentional crash of the testcase on some
embedded/non-MMU systems.
No regressions on {x86_64,x86_64-m32,i686}-fedora12-linux-gnu.


Thanks,
Jan


gdb/
2010-02-19  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* infcall.c (call_function_by_hand): Remove gdb_assert on sp and old_sp.
	New comment.

gdb/testsuite/
2010-02-19  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.base/callfuncs.exp: New tests for $spval 0 and -1.  Remove return.

--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -518,10 +518,9 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
 	      /* Stack grows up.  */
 	      sp = gdbarch_frame_align (gdbarch, old_sp + 1);
 	  }
-	gdb_assert ((gdbarch_inner_than (gdbarch, 1, 2)
-		    && sp <= old_sp)
-		    || (gdbarch_inner_than (gdbarch, 2, 1)
-		       && sp >= old_sp));
+	/* SP may have overflown address zero here from OLD_SP.  Memory access
+	   functions will probably fail in such case but that is a target's
+	   problem.  */
       }
     else
       /* FIXME: cagney/2002-09-18: Hey, you loose!
--- a/gdb/testsuite/gdb.base/callfuncs.exp
+++ b/gdb/testsuite/gdb.base/callfuncs.exp
@@ -469,5 +469,18 @@ if {$old_reg_content == $new_reg_content} then {
     fail "nested call dummies preserve register contents"
 }
 
-return 0
+# GDB should not crash by internal error on $sp overflow during the inferior
+# call.  It is OK it will stop on some: Cannot access memory at address 0x$hex.
 
+foreach spval {0 -1} {
+    set old_ldprefix $pf_prefix
+    lappend pf_prefix "sp=$spval:"
+
+    gdb_test {set $old_sp = $sp}
+    gdb_test "set \$sp = $spval"
+
+    gdb_test "call doubleit (1)"
+
+    gdb_test {set $sp = $old_sp}
+    set pf_prefix $old_ldprefix
+}


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch] infcall: Remove gdb_assert ($sp overflow)
  2010-02-19 22:48 [patch] infcall: Remove gdb_assert ($sp overflow) Jan Kratochvil
@ 2010-02-26 22:45 ` Tom Tromey
  2010-02-27  1:19   ` [patch] infcall: Remove gdb_assert ($sp underflow) Jan Kratochvil
  2010-02-28 10:53   ` [patch] infcall: Remove gdb_assert ($sp overflow) Joel Brobecker
  2010-02-26 22:53 ` Daniel Jacobowitz
  1 sibling, 2 replies; 8+ messages in thread
From: Tom Tromey @ 2010-02-26 22:45 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:

Jan> set $sp=0
Jan> call something()

I don't really have much problem with this patch, I guess, but do people
really do this sort of thing?  Or is this a reduced case of some other
scenario that actually does happen?

Tom


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch] infcall: Remove gdb_assert ($sp overflow)
  2010-02-19 22:48 [patch] infcall: Remove gdb_assert ($sp overflow) Jan Kratochvil
  2010-02-26 22:45 ` Tom Tromey
@ 2010-02-26 22:53 ` Daniel Jacobowitz
  2010-02-27  0:46   ` [patch] infcall: Remove gdb_assert ($sp underflow) Jan Kratochvil
  1 sibling, 1 reply; 8+ messages in thread
From: Daniel Jacobowitz @ 2010-02-26 22:53 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On Fri, Feb 19, 2010 at 11:48:05PM +0100, Jan Kratochvil wrote:
> Unaware how inconvenient is an intentional crash of the testcase on some
> embedded/non-MMU systems.

Maybe limit it at least by nosignals?  It might still blow up uClinux
testing, I don't know offhand if there are other crashy tests.

> +foreach spval {0 -1} {
> +    set old_ldprefix $pf_prefix
> +    lappend pf_prefix "sp=$spval:"
> +
> +    gdb_test {set $old_sp = $sp}
> +    gdb_test "set \$sp = $spval"
> +
> +    gdb_test "call doubleit (1)"
> +
> +    gdb_test {set $sp = $old_sp}
> +    set pf_prefix $old_ldprefix
> +}

Because these tests run more than once, please give them unique names.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch] infcall: Remove gdb_assert ($sp underflow)
  2010-02-26 22:53 ` Daniel Jacobowitz
@ 2010-02-27  0:46   ` Jan Kratochvil
  2010-02-28 14:35     ` Daniel Jacobowitz
  0 siblings, 1 reply; 8+ messages in thread
From: Jan Kratochvil @ 2010-02-27  0:46 UTC (permalink / raw)
  To: gdb-patches

On Fri, 26 Feb 2010 23:52:52 +0100, Daniel Jacobowitz wrote:
> On Fri, Feb 19, 2010 at 11:48:05PM +0100, Jan Kratochvil wrote:
> > Unaware how inconvenient is an intentional crash of the testcase on some
> > embedded/non-MMU systems.
> 
> Maybe limit it at least by nosignals?  It might still blow up uClinux
> testing, I don't know offhand if there are other crashy tests.

OK, used:
	if {![target_info exists gdb,nosignals] && ![istarget "*-*-uclinux*"]} {


> > +foreach spval {0 -1} {
> > +    set old_ldprefix $pf_prefix
> > +    lappend pf_prefix "sp=$spval:"
> > +
> > +    gdb_test {set $old_sp = $sp}
> > +    gdb_test "set \$sp = $spval"
> > +
> > +    gdb_test "call doubleit (1)"
> > +
> > +    gdb_test {set $sp = $old_sp}
> > +    set pf_prefix $old_ldprefix
> > +}
> 
> Because these tests run more than once, please give them unique names.

The tests have been already producing:

PASS: gdb.base/callfuncs.exp: sp=0: set $old_sp = $sp
PASS: gdb.base/callfuncs.exp: sp=0: set $sp = 0
PASS: gdb.base/callfuncs.exp: sp=0: call doubleit (1)
PASS: gdb.base/callfuncs.exp: sp=0: set $sp = $old_sp
PASS: gdb.base/callfuncs.exp: sp=-1: set $old_sp = $sp
PASS: gdb.base/callfuncs.exp: sp=-1: set $sp = -1
PASS: gdb.base/callfuncs.exp: sp=-1: call doubleit (1)
PASS: gdb.base/callfuncs.exp: sp=-1: set $sp = $old_sp

But OK, made now the tests code more obvious:

PASS: gdb.base/callfuncs.exp: set $old_sp = $sp
PASS: gdb.base/callfuncs.exp: set $sp = 0
PASS: gdb.base/callfuncs.exp: sp == 0: call doubleit (1)
PASS: gdb.base/callfuncs.exp: set $sp = -1
PASS: gdb.base/callfuncs.exp: sp == -1: call doubleit (1)
PASS: gdb.base/callfuncs.exp: set $sp = $old_sp


Thanks,
Jan


gdb/
2010-02-27  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* infcall.c (call_function_by_hand): Remove gdb_assert on sp and old_sp.
	New comment.

gdb/testsuite/
2010-02-27  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.base/callfuncs.exp: New tests for $spval 0 and -1.  Remove return.

--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -518,10 +518,9 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
 	      /* Stack grows up.  */
 	      sp = gdbarch_frame_align (gdbarch, old_sp + 1);
 	  }
-	gdb_assert ((gdbarch_inner_than (gdbarch, 1, 2)
-		    && sp <= old_sp)
-		    || (gdbarch_inner_than (gdbarch, 2, 1)
-		       && sp >= old_sp));
+	/* SP may have underflown address zero here from OLD_SP.  Memory access
+	   functions will probably fail in such case but that is a target's
+	   problem.  */
       }
     else
       /* FIXME: cagney/2002-09-18: Hey, you loose!
--- a/gdb/testsuite/gdb.base/callfuncs.exp
+++ b/gdb/testsuite/gdb.base/callfuncs.exp
@@ -469,5 +469,17 @@ if {$old_reg_content == $new_reg_content} then {
     fail "nested call dummies preserve register contents"
 }
 
-return 0
+# GDB should not crash by internal error on $sp underflow during the inferior
+# call.  It is OK it will stop on some: Cannot access memory at address 0x$hex.
 
+if {![target_info exists gdb,nosignals] && ![istarget "*-*-uclinux*"]} {
+    gdb_test {set $old_sp = $sp}
+
+    gdb_test {set $sp = 0}
+    gdb_test {sp == 0: call doubleit (1)}
+
+    gdb_test {set $sp = -1}
+    gdb_test {sp == -1: call doubleit (1)}
+
+    gdb_test {set $sp = $old_sp}
+}


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch] infcall: Remove gdb_assert ($sp underflow)
  2010-02-26 22:45 ` Tom Tromey
@ 2010-02-27  1:19   ` Jan Kratochvil
  2010-02-28 10:53   ` [patch] infcall: Remove gdb_assert ($sp overflow) Joel Brobecker
  1 sibling, 0 replies; 8+ messages in thread
From: Jan Kratochvil @ 2010-02-27  1:19 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Fri, 26 Feb 2010 23:45:10 +0100, Tom Tromey wrote:
> >>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:
> 
> Jan> set $sp=0
> Jan> call something()
[...]
> do people really do this sort of thing?  Or is this a reduced case of some
> other scenario that actually does happen?

$sp=0 is a perfectly valid 16bit embedded device initialization with ROM 0..16KB
and RAM 16KB..64KB address range with normal PUSH as *--$sp (and POP as *sp++).


But it is true I have met this case as a consequence of a different problem.
Assuming it is a bug in the ia64 part of the subsystem in Linux kernel for
ptrace emulated on top of utrace (that is RHEL-5, such as RHEL-5.4).

Reproducer instructions:
	http://cvs.fedoraproject.org/viewvc/rpms/gdb/F-12/gdb-ia64-infcall-workaround.patch?content-type=text%2Fplain&view=co
FYI the ia64 kernel may lock up while dealing with this reproducer.

After an inferior call and some commands inferior $sp gets read by ptrace as 0.

The problem happens since arch-independent change:
	Re: [rfc, v3] Fix frame_id_inner comparison false positives
	http://sourceware.org/ml/gdb-patches/2008-08/msg00578.html
	http://sourceware.org/ml/gdb-cvs/2008-08/msg00182.html
	916dde5d38b45a659514e47942ece70aec04cd78
specifically its last part:
	* stack.c (return_command): Directly pop the selected frame.
which is at the bottom of this mail.

I have not found there a bug in this GDB change.  The problem is also not
reproducible on ia64 RHEL-4 (RHEL-4.8) which uses non-utrace legacy ptrace
implementation in its Linux kernel.


Thanks,
Jan


--- src/gdb/stack.c	2008/08/21 18:14:39	1.176
+++ src/gdb/stack.c	2008/08/26 17:40:25	1.177
@@ -1844,29 +1844,8 @@
 	error (_("Not confirmed"));
     }
 
-  /* NOTE: cagney/2003-01-18: Is this silly?  Rather than pop each
-     frame in turn, should this code just go straight to the relevant
-     frame and pop that?  */
-
-  /* First discard all frames inner-to the selected frame (making the
-     selected frame current).  */
-  {
-    struct frame_id selected_id = get_frame_id (get_selected_frame (NULL));
-    while (!frame_id_eq (selected_id, get_frame_id (get_current_frame ())))
-      {
-	struct frame_info *frame = get_current_frame ();
-	if (frame_id_inner (get_frame_arch (frame), selected_id,
-			    get_frame_id (frame)))
-	  /* Caught in the safety net, oops!  We've gone way past the
-             selected frame.  */
-	  error (_("Problem while popping stack frames (corrupt stack?)"));
-	frame_pop (get_current_frame ());
-      }
-  }
-
-  /* Second discard the selected frame (which is now also the current
-     frame).  */
-  frame_pop (get_current_frame ());
+  /* Discard the selected frame and all frames inner-to it.  */
+  frame_pop (get_selected_frame (NULL));
 
   /* Store RETURN_VALUE in the just-returned register set.  */
   if (return_value != NULL)


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch] infcall: Remove gdb_assert ($sp overflow)
  2010-02-26 22:45 ` Tom Tromey
  2010-02-27  1:19   ` [patch] infcall: Remove gdb_assert ($sp underflow) Jan Kratochvil
@ 2010-02-28 10:53   ` Joel Brobecker
  1 sibling, 0 replies; 8+ messages in thread
From: Joel Brobecker @ 2010-02-28 10:53 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Jan Kratochvil, gdb-patches

> Jan> set $sp=0
> Jan> call something()
> 
> I don't really have much problem with this patch, I guess, but do people
> really do this sort of thing?  Or is this a reduced case of some other
> scenario that actually does happen?

I used to do that (setting $sp) in an ancient testcase whose purpose
was to break the callstack. It turned out that breaking the callstack
was too platform specific, so I gave up on using this.

I am guessing that some people might try setting $sp for various
purposes (maybe debugging a problem with code that misaligns SP
for instance), and a screwup might lead to this situation too...

-- 
Joel


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch] infcall: Remove gdb_assert ($sp underflow)
  2010-02-27  0:46   ` [patch] infcall: Remove gdb_assert ($sp underflow) Jan Kratochvil
@ 2010-02-28 14:35     ` Daniel Jacobowitz
  2010-02-28 17:58       ` Jan Kratochvil
  0 siblings, 1 reply; 8+ messages in thread
From: Daniel Jacobowitz @ 2010-02-28 14:35 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On Sat, Feb 27, 2010 at 01:46:34AM +0100, Jan Kratochvil wrote:
> The tests have been already producing:
> 
> PASS: gdb.base/callfuncs.exp: sp=0: set $old_sp = $sp
> PASS: gdb.base/callfuncs.exp: sp=0: set $sp = 0
> PASS: gdb.base/callfuncs.exp: sp=0: call doubleit (1)
> PASS: gdb.base/callfuncs.exp: sp=0: set $sp = $old_sp
> PASS: gdb.base/callfuncs.exp: sp=-1: set $old_sp = $sp
> PASS: gdb.base/callfuncs.exp: sp=-1: set $sp = -1
> PASS: gdb.base/callfuncs.exp: sp=-1: call doubleit (1)
> PASS: gdb.base/callfuncs.exp: sp=-1: set $sp = $old_sp
> 

Oh, you're right.  I missed pf_prefix.  Either way is fine with me.

> +    gdb_test {sp == 0: call doubleit (1)}

Except what does this do?  I've never seen this syntax before, I'm
surprised that it works.

I think the patch is otherwise OK.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch] infcall: Remove gdb_assert ($sp underflow)
  2010-02-28 14:35     ` Daniel Jacobowitz
@ 2010-02-28 17:58       ` Jan Kratochvil
  0 siblings, 0 replies; 8+ messages in thread
From: Jan Kratochvil @ 2010-02-28 17:58 UTC (permalink / raw)
  To: gdb-patches

On Sun, 28 Feb 2010 15:35:09 +0100, Daniel Jacobowitz wrote:
> On Sat, Feb 27, 2010 at 01:46:34AM +0100, Jan Kratochvil wrote:
> > +    gdb_test {sp == 0: call doubleit (1)}
> 
> Except what does this do?  I've never seen this syntax before, I'm
> surprised that it works.

It generated false PASS - not testing the internal error at all.
	Undefined command: "sp".  Try "help".
Thanks for catching it.


> I think the patch is otherwise OK.

Checked-in.


Thanks,
Jan


http://sourceware.org/ml/gdb-cvs/2010-02/msg00222.html

--- src/gdb/ChangeLog	2010/02/28 15:04:10	1.11406
+++ src/gdb/ChangeLog	2010/02/28 17:56:36	1.11407
@@ -1,3 +1,8 @@
+2010-02-28  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* infcall.c (call_function_by_hand): Remove gdb_assert on sp and old_sp.
+	New comment.
+
 2010-02-28  Corinna Vinschen  <vinschen@redhat.com>
 
 	* Makefile.in (SUBDIR_MI_OBS): Move mi-common.o from here...
--- src/gdb/infcall.c	2010/01/28 22:07:58	1.126
+++ src/gdb/infcall.c	2010/02/28 17:56:36	1.127
@@ -518,10 +518,9 @@
 	      /* Stack grows up.  */
 	      sp = gdbarch_frame_align (gdbarch, old_sp + 1);
 	  }
-	gdb_assert ((gdbarch_inner_than (gdbarch, 1, 2)
-		    && sp <= old_sp)
-		    || (gdbarch_inner_than (gdbarch, 2, 1)
-		       && sp >= old_sp));
+	/* SP may have underflown address zero here from OLD_SP.  Memory access
+	   functions will probably fail in such case but that is a target's
+	   problem.  */
       }
     else
       /* FIXME: cagney/2002-09-18: Hey, you loose!
--- src/gdb/testsuite/ChangeLog	2010/02/26 05:50:35	1.2154
+++ src/gdb/testsuite/ChangeLog	2010/02/28 17:56:37	1.2155
@@ -1,3 +1,8 @@
+2010-02-28  Jan Kratochvil  <jan.kratochvil@redhat.com>
+	    Daniel Jacobowitz  <dan@codesourcery.com>
+
+	* gdb.base/callfuncs.exp: New tests for $spval 0 and -1.  Remove return.
+
 2010-02-25  David S. Miller  <davem@davemloft.net>
 
 	* gdb.base/catch-syscall.exp: Allow to run on sparc*-*-linux and
--- src/gdb/testsuite/gdb.base/callfuncs.exp	2010/01/01 07:32:00	1.31
+++ src/gdb/testsuite/gdb.base/callfuncs.exp	2010/02/28 17:56:37	1.32
@@ -469,5 +469,17 @@
     fail "nested call dummies preserve register contents"
 }
 
-return 0
+# GDB should not crash by internal error on $sp underflow during the inferior
+# call.  It is OK it will stop on some: Cannot access memory at address 0x$hex.
 
+if {![target_info exists gdb,nosignals] && ![istarget "*-*-uclinux*"]} {
+    gdb_test {set $old_sp = $sp}
+
+    gdb_test {set $sp = 0}
+    gdb_test "call doubleit (1)" "" "sp == 0: call doubleit (1)"
+
+    gdb_test {set $sp = -1}
+    gdb_test "call doubleit (1)" "" "sp == -1: call doubleit (1)"
+
+    gdb_test {set $sp = $old_sp}
+}


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2010-02-28 17:58 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-02-19 22:48 [patch] infcall: Remove gdb_assert ($sp overflow) Jan Kratochvil
2010-02-26 22:45 ` Tom Tromey
2010-02-27  1:19   ` [patch] infcall: Remove gdb_assert ($sp underflow) Jan Kratochvil
2010-02-28 10:53   ` [patch] infcall: Remove gdb_assert ($sp overflow) Joel Brobecker
2010-02-26 22:53 ` Daniel Jacobowitz
2010-02-27  0:46   ` [patch] infcall: Remove gdb_assert ($sp underflow) Jan Kratochvil
2010-02-28 14:35     ` Daniel Jacobowitz
2010-02-28 17:58       ` Jan Kratochvil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox