public inbox for frysk-cvs@sourceware.org
help / color / mirror / Atom feed
* [SCM]  master: Add plt stepping test for bug #5259.
@ 2008-03-10 15:25 mark
  0 siblings, 0 replies; only message in thread
From: mark @ 2008-03-10 15:25 UTC (permalink / raw)
  To: frysk-cvs

The branch, master has been updated
       via  63ac2a8e2f12fd140f2a7bd6335f286512460da9 (commit)
      from  83c4a9ba95be174298836adf0536cbb734051e56 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email.

- Log -----------------------------------------------------------------
commit 63ac2a8e2f12fd140f2a7bd6335f286512460da9
Author: Mark Wielaard <mwielaard@redhat.com>
Date:   Mon Mar 10 16:24:17 2008 +0100

    Add plt stepping test for bug #5259.
    
    frysk-core/frysk/stack/ChangeLog
    2008-03-10  Mark Wielaard  <mwielaard@redhat.com>
    
        * TestLibFunctionStepFrame.java: New test for bug #5259.
    
    frysk-core/frysk/pkglibdir/ChangeLog
    2008-03-10  Mark Wielaard  <mwielaard@redhat.com>
    
        * funit-libfunccall.c: New test program for TestLibFunctionStepFrame.

-----------------------------------------------------------------------

Summary of changes:
 frysk-core/frysk/pkglibdir/ChangeLog               |    4 +
 .../{funit-vfork.c => funit-libfunccall.c}         |   43 ++--
 frysk-core/frysk/stack/ChangeLog                   |    4 +
 .../frysk/stack/TestLibFunctionStepFrame.java      |  256 ++++++++++++++++++++
 4 files changed, 285 insertions(+), 22 deletions(-)
 copy frysk-core/frysk/pkglibdir/{funit-vfork.c => funit-libfunccall.c} (81%)
 create mode 100644 frysk-core/frysk/stack/TestLibFunctionStepFrame.java

First 500 lines of diff:
diff --git a/frysk-core/frysk/pkglibdir/ChangeLog b/frysk-core/frysk/pkglibdir/ChangeLog
index 10bb1ad..8ba0e2f 100644
--- a/frysk-core/frysk/pkglibdir/ChangeLog
+++ b/frysk-core/frysk/pkglibdir/ChangeLog
@@ -1,3 +1,7 @@
+2008-03-10  Mark Wielaard  <mwielaard@redhat.com>
+
+	* funit-libfunccall.c: New test program for TestLibFunctionStepFrame.
+
 2008-02-29  Sami Wagiaalla  <swagiaal@redhat.com>
 
 	* funit-steps.c: new test program.
diff --git a/frysk-core/frysk/pkglibdir/funit-vfork.c b/frysk-core/frysk/pkglibdir/funit-libfunccall.c
similarity index 81%
copy from frysk-core/frysk/pkglibdir/funit-vfork.c
copy to frysk-core/frysk/pkglibdir/funit-libfunccall.c
index d40b923..2055f27 100644
--- a/frysk-core/frysk/pkglibdir/funit-vfork.c
+++ b/frysk-core/frysk/pkglibdir/funit-libfunccall.c
@@ -1,6 +1,6 @@
 // This file is part of the program FRYSK.
 //
-// Copyright 2007 Red Hat Inc.
+// Copyright 2008, Red Hat Inc.
 //
 // FRYSK is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by
@@ -37,30 +37,29 @@
 // version and license this file solely under the GPL without
 // exception.
 
-#include <sys/types.h>
-#include <sys/wait.h>
 #include <stdio.h>
-#include <stdlib.h>
+#include <sys/types.h>
 #include <unistd.h>
 
+// Simple test prog that calls foo () twice, which just calls getpid ()
+// and returns.  Used to check calling shared (libc) library functions,
+// through plt entries always produce full and valid backtraces
+// containing all valid frames.
+
+int i;
+
+int
+foo (int x)
+{
+  i = 0;
+  getpid ();       // _libfunccall_
+  getpid ();       // _libfunccall2_
+  i++;             // _last_line_
+  return x - i;
+}
+
 int
-main(void)
+main (int argc, char *argv[], char *envp[])
 {
-  pid_t pid = vfork();
-  if (pid == -1)
-    {
-      perror ("vfork");
-      exit (1);
-    }
-  else if (pid == 0)
-    {
-      puts ("child");
-      _exit (1);
-    }
-  else
-    {
-      waitpid (pid, NULL, 0);
-      puts ("child done");
-    }
-  return 0;
+  return foo (1); // zero
 }
diff --git a/frysk-core/frysk/stack/ChangeLog b/frysk-core/frysk/stack/ChangeLog
index 3d5ef83..8ff178e 100644
--- a/frysk-core/frysk/stack/ChangeLog
+++ b/frysk-core/frysk/stack/ChangeLog
@@ -1,3 +1,7 @@
+2008-03-10  Mark Wielaard  <mwielaard@redhat.com>
+
+	* TestLibFunctionStepFrame.java: New test for bug #5259.
+
 2008-02-28  Andrew Cagney  <cagney@redhat.com>
 
 	* LibunwindAddressSpace.java: Use frysk.rsl.
diff --git a/frysk-core/frysk/stack/TestLibFunctionStepFrame.java b/frysk-core/frysk/stack/TestLibFunctionStepFrame.java
new file mode 100644
index 0000000..f1f8c59
--- /dev/null
+++ b/frysk-core/frysk/stack/TestLibFunctionStepFrame.java
@@ -0,0 +1,256 @@
+// This file is part of the program FRYSK.
+//
+// Copyright 2008, Red Hat Inc.
+//
+// FRYSK is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// FRYSK is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with FRYSK; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+// 
+// In addition, as a special exception, Red Hat, Inc. gives You the
+// additional right to link the code of FRYSK with code not covered
+// under the GNU General Public License ("Non-GPL Code") and to
+// distribute linked combinations including the two, subject to the
+// limitations in this paragraph. Non-GPL Code permitted under this
+// exception must only link to the code of FRYSK through those well
+// defined interfaces identified in the file named EXCEPTION found in
+// the source code files (the "Approved Interfaces"). The files of
+// Non-GPL Code may instantiate templates or use macros or inline
+// functions from the Approved Interfaces without causing the
+// resulting work to be covered by the GNU General Public
+// License. Only Red Hat, Inc. may make changes or additions to the
+// list of Approved Interfaces. You must obey the GNU General Public
+// License in all respects for all of the FRYSK code and other code
+// used in conjunction with FRYSK except the Non-GPL Code covered by
+// this exception. If you modify this file, you may extend this
+// exception to your version of the file, but you are not obligated to
+// do so. If you do not wish to provide this exception without
+// modification, you must delete this exception statement from your
+// version and license this file solely under the GPL without
+// exception.
+
+package frysk.stack;
+
+import java.io.*;
+import java.util.*;
+
+import frysk.config.*;
+
+import frysk.testbed.*;
+
+import frysk.proc.*;
+import frysk.symtab.*;
+import frysk.rt.*;
+
+/**
+ * Test making sure all frames are available when stepping (twice)
+ * through a shared library call that goes through a plt entry. It
+ * checks on each step that both the calling function and the main
+ * function are outer frames (in that order) of the inner frame.
+ *
+ * Note this checks the low level (libunwind) frames walking.  It
+ * doesn't test anything at a higher level or with the SteppingEngine
+ * (currently the SteppingEngine tries to explicitly step through the
+ * plt entries even when instruction stepping).
+ */
+public class TestLibFunctionStepFrame
+  extends TestLib
+  implements TaskObserver.Code, TaskObserver.Instruction
+{
+  public void testStepIntoLibFunctionCall()
+  {
+    if (unresolved(5259))
+      return;
+
+    String source = Config.getRootSrcDir()
+      + "frysk-core/frysk/pkglibdir/funit-libfunccall.c";
+
+    TestfileTokenScanner scanner = new TestfileTokenScanner(new File(source));
+    int firstLine = scanner.findTokenLine("_libfunccall_");
+    int secondLine = scanner.findTokenLine("_libfunccall2_");
+    int lastLine = scanner.findTokenLine("_last_line_");
+
+    File exe = Config.getPkgLibFile("funit-libfunccall");
+    DaemonBlockedAtEntry dbae = new DaemonBlockedAtEntry(exe);
+    
+    Task task = dbae.getMainTask();
+
+    LineBreakpoint bp1 = new  LineBreakpoint(-1, source, firstLine, 0);
+    LineBreakpoint bp2 = new  LineBreakpoint(-1, source, secondLine, 0);
+    LineBreakpoint bpLast = new  LineBreakpoint(-1, source, lastLine, 0);
+
+    List addresses = bp1.getBreakpointRawAddresses(task);
+    List addresses2 = bp2.getBreakpointRawAddresses(task);
+    List addressesLast = bpLast.getBreakpointRawAddresses(task);
+
+    // Test sanity checks
+    assertTrue("expecting one raw address1", addresses.size() == 1);
+    assertTrue("expecting one raw address2", addresses2.size() == 1);
+
+    long address1 = ((Long) addresses.get(0)).longValue();
+    long address2 = ((Long) addresses2.get(0)).longValue();
+    long addressLast = ((Long) addressesLast.get(0)).longValue();
+
+    task.requestAddCodeObserver(this, address1);
+    assertRunUntilStop("adding Code observer");
+
+    dbae.requestUnblock();
+    assertRunUntilStop("Continuing to initial breakpoint");
+
+    // From here on we will step through to check all frames.
+    task.requestAddInstructionObserver(this);
+    assertRunUntilStop("adding Instruction observer");
+
+    // One step and we should be at the first PLT instruction.
+    task.requestUnblock(this);
+    assertRunUntilStop("Do first step");
+
+    // We are at the first plt intruction (for the first time).
+    long firstPLTAddress = task.getPC();
+    Frame frame = StackFactory.createFrame(task);
+    assertFooAndMainOuterFrames("At first PLT address", frame);
+
+    // Count your steps. And bail out when there are too many.
+    int steps = 1;
+    boolean seenSecondCall = false;
+    long currentPC = task.getPC();
+    while (currentPC != addressLast && steps < 1000)
+      {
+	task.requestUnblock(this);
+	assertRunUntilStop("Do step: " + steps);
+
+	currentPC = task.getPC();
+	if (currentPC == address2)
+	  {
+	    seenSecondCall = true;
+	    // When we step we should be at the first PLTAddress again.
+	    // One step and we should be at the first PLT instruction.
+	    task.requestUnblock(this);
+	    assertRunUntilStop("Do first 'second' step");
+	    currentPC = task.getPC();
+	    assertEquals("Second time in PLT", currentPC, firstPLTAddress);
+
+	    frame = StackFactory.createFrame(task);
+	    assertFooAndMainOuterFrames("Second time in PLT", frame);
+	  }
+	else if (currentPC != addressLast)
+	  {
+	    frame = StackFactory.createFrame(task);
+	    assertFooAndMainOuterFrames("Stepping, #" + steps
+					+ " through (plt) call", frame);
+	  }
+      }
+
+    assertTrue("less than a thousand steps", steps < 1000);
+    assertTrue("seen second", seenSecondCall);
+  }
+
+
+  // Walks up the call stack and checks that both foo() and main() are
+  // in there, in that order, and that they are not the first inner
+  // frame.
+  private void assertFooAndMainOuterFrames(String message, Frame frame)
+  {
+    Symbol sym = frame.getSymbol();
+    String name = sym.getName();
+    boolean ok = name.indexOf("foo") == -1 && name.indexOf("main") == -1;
+    if (! ok)
+      printBacktrace(frame);
+    assertTrue(message + " first inner frame should not be foo or main", ok);
+
+    boolean foo_seen = false;
+    Frame outer = frame.getOuter();
+    while (ok && outer != null)
+      {
+	sym = outer.getSymbol();
+	name = sym.getName();
+	boolean sym_is_foo = name.indexOf("foo") != -1;
+	if (! foo_seen && sym_is_foo)
+	  foo_seen = true;
+	else if (foo_seen && sym_is_foo)
+	  {
+	    ok = false;
+	    printBacktrace(frame);
+	    assertTrue(message
+		       + " foo should be in the backtrace only once",
+		       ok);
+	  }
+
+	boolean sym_is_main = name.indexOf("main") != -1;
+	if (foo_seen && sym_is_main)
+	  break;
+
+	if (! foo_seen && sym_is_main)
+	  {
+	    ok = false;
+	    printBacktrace(frame);
+	    assertTrue(message
+		       + " foo should appear before main in backtrace",
+		       ok);
+	  }
+	outer = outer.getOuter();
+      }
+
+    ok = outer != null;
+    if (! ok)
+      printBacktrace(frame);
+    assertTrue(message
+	       + " both foo and main should be in the backtrace",
+	       ok);
+  }
+
+  // Helper function to print backtrace from given frame.
+  // Useful while debugging this test.
+  private void printBacktrace(Frame frame)
+  {
+    System.out.println(frame);
+    Frame outer = frame.getOuter();
+    while (outer != null)
+      {
+	System.out.println("\t" + outer);
+	outer = outer.getOuter();
+      }
+  }
+
+  // Code observer method, just stop and block when breakpoint hit.
+  public Action updateHit(Task task, long address)
+  {
+    Manager.eventLoop.requestStop();
+    return Action.BLOCK;
+  }
+
+  // Instruction observer method, just stop and block after each step.
+  public Action updateExecuted(Task task)
+  {
+    Manager.eventLoop.requestStop();
+    return Action.BLOCK;
+  }
+
+  // TaskObserver methods, only addedTo is interesting.
+
+  public void addFailed(Object observable, Throwable w)
+  {
+    // Whoa!
+    w.printStackTrace();
+  }
+  
+  public void addedTo(Object observable)
+  {
+    Manager.eventLoop.requestStop();
+  }
+
+  public void deletedFrom(Object observable)
+  {
+    // We never delete anything...
+    System.err.println("deletedFrom: " + observable);
+  }
+
+}


hooks/post-receive
--
frysk system monitor/debugger


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2008-03-10 15:25 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-03-10 15:25 [SCM] master: Add plt stepping test for bug #5259 mark

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).