public inbox for frysk-cvs@sourceware.org
help / color / mirror / Atom feed
From: pmachata@sourceware.org
To: frysk-cvs@sourceware.org
Subject: [SCM] frysk system monitor/debugger branch, master, updated. b64b53ab72226ccc8c0bab0372a6de8328d22f81
Date: Thu, 08 Nov 2007 13:07:00 -0000	[thread overview]
Message-ID: <20071108130703.24640.qmail@sourceware.org> (raw)

The branch, master has been updated
       via  b64b53ab72226ccc8c0bab0372a6de8328d22f81 (commit)
      from  9db08d018eb772dc97a7244e1c8bde3fbd523f8d (commit)

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

- Log -----------------------------------------------------------------
commit b64b53ab72226ccc8c0bab0372a6de8328d22f81
Author: Petr Machata <pmachata@redhat.com>
Date:   Thu Nov 8 14:02:46 2007 +0100

    Support for _dl_debug_state mmap/unmap guard.
    
    * Map/unmap guard refactored to class of its own.  Method attachTo(Task) will pick either _dl_debug_state-based guard, or syscall-based guard if the former isn't available for some reason.
    * Few coding style changes across the code.  Trying to become java compliant if the resulting patch is small enough.

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

Summary of changes:
 frysk-core/frysk/bindir/ChangeLog                  |    4 +
 frysk-core/frysk/bindir/fltrace.java               |   16 +-
 frysk-core/frysk/ftrace/ChangeLog                  |   10 +
 frysk-core/frysk/ftrace/Ltrace.java                |   41 ++---
 ...traceController.java => MappingController.java} |   17 +-
 frysk-core/frysk/ftrace/MappingGuard.java          |  182 ++++++++++++++++++++
 frysk-core/frysk/ftrace/ObjectFile.java            |  121 ++++++++------
 7 files changed, 300 insertions(+), 91 deletions(-)
 copy frysk-core/frysk/ftrace/{LtraceController.java => MappingController.java} (85%)
 create mode 100644 frysk-core/frysk/ftrace/MappingGuard.java

First 500 lines of diff:
diff --git a/frysk-core/frysk/bindir/ChangeLog b/frysk-core/frysk/bindir/ChangeLog
index 1b9e5b0..efc7825 100644
--- a/frysk-core/frysk/bindir/ChangeLog
+++ b/frysk-core/frysk/bindir/ChangeLog
@@ -1,3 +1,7 @@
+2007-11-08  Petr Machata  <pmachata@redhat.com>
+
+	* fltrace.java (MyLtraceObserver.pidInfo): new method
+
 2007-11-08  Phil Muldoon  <pmuldoon@redhat.com>
 
 	* TestFhd.java (testHpdCore): Add unresolved(5295).
diff --git a/frysk-core/frysk/bindir/fltrace.java b/frysk-core/frysk/bindir/fltrace.java
index 0b6c2e0..36ac581 100644
--- a/frysk-core/frysk/bindir/fltrace.java
+++ b/frysk-core/frysk/bindir/fltrace.java
@@ -325,6 +325,11 @@ public class fltrace
 	return new String(fill);
       }
 
+      private String pidInfo(Task task)
+      {
+	  return "[" + task.getProc().getPid() + "." + task.getTid() + "]";
+      }
+
       private void eventEntry(Task task, Object item, String eventType,
 			      String eventName, Object[] args)
       {
@@ -335,7 +340,7 @@ public class fltrace
         if (lineOpened())
 	  System.err.println('\\');
 
-    	System.err.print("[" + task.getTaskId().intValue() + "] "
+    	System.err.print(pidInfo(task) + " "
 			 + spaces + eventType + " ");
 	System.err.print(eventName + "(");
 	for (int i = 0; i < args.length; ++i) {
@@ -365,8 +370,7 @@ public class fltrace
             if (lineOpened())
 	      System.err.println();
 	    String spaces = repeat(' ', level);
-	    System.err.print("[" + task.getTaskId().intValue() + "] "
-			     + spaces + eventType + " " + eventName);
+	    System.err.print(pidInfo(task) + " " + spaces + eventType + " " + eventName);
 	  }
 
 	System.err.println(" = " + retVal);
@@ -376,12 +380,11 @@ public class fltrace
 
       private void eventSingle(Task task, String eventName)
       {
-	int pid = task.getTid();
 	int level = this.getLevel(task);
 
         if (lineOpened())
 	  System.err.println("\\");
-	System.err.println("[" + pid + "] " + repeat(' ', level) + eventName);
+	System.err.println(pidInfo(task) + " " + repeat(' ', level) + eventName);
 
         updateOpenLine(null, null);
       }
@@ -455,8 +458,7 @@ public class fltrace
       {
 	if (lineOpened())
 	  System.err.println('\\');
-	int pid = task.getTid();
-	System.err.print("[" + pid + "] ");
+	System.err.print(pidInfo(task) + " ");
 	if (signal)
 	  System.err.println("killed by " + Sig.toPrintString(value));
 	else
diff --git a/frysk-core/frysk/ftrace/ChangeLog b/frysk-core/frysk/ftrace/ChangeLog
index 99bbec7..2be067c 100644
--- a/frysk-core/frysk/ftrace/ChangeLog
+++ b/frysk-core/frysk/ftrace/ChangeLog
@@ -1,3 +1,13 @@
+2007-11-08  Petr Machata  <pmachata@redhat.com>
+
+	* MappingController.java: New file.
+	* MappingGuard.java: New file.
+	* Ltrace.java: No longer trace syscalls by default.
+	(LtraceTaskObserver.updateSyscallLeave): Move to MappingGuard.
+	* ObjectFile.java: Now loads program interpreter.
+	(setInterp, getInterp): New methods.
+	(lookupTracePoint): New method.
+
 2007-11-02  Petr Machata  <pmachata@redhat.com>
 
 	* TestLtrace.java (testArgumentsCorrect1): New test.
diff --git a/frysk-core/frysk/ftrace/Ltrace.java b/frysk-core/frysk/ftrace/Ltrace.java
index b359c4c..97979c9 100644
--- a/frysk-core/frysk/ftrace/Ltrace.java
+++ b/frysk-core/frysk/ftrace/Ltrace.java
@@ -73,10 +73,11 @@ public class Ltrace
   // True if we're tracing signals as well.
   boolean traceSignals = false;
 
-  // True if we're tracing syscalls.  Currently true by default,
-  // because we need to trace syscalls for correct mmap/munmap
-  // handling.
-  boolean traceSyscalls = true;
+  // True if we're tracing syscalls.
+  // TODO: this shouldn't be part of Ltrace class at all.  Make it so
+  // that Ltrace observes Tasks, and plug Ltrace into Ftrace's
+  // framework.
+  boolean traceSyscalls = false;
 
   // Task counter.
   int numTasks = 0;
@@ -313,7 +314,8 @@ public class Ltrace
 	       TaskObserver.Syscall,
 	       TaskObserver.Signaled,
 	       TaskObserver.Terminated,
-	       TaskObserver.Terminating
+	       TaskObserver.Terminating,
+	       MappingController
   {
     /** Remembers which files are currently mapped in which task. */
     private HashMap mapsForTask = new HashMap();
@@ -327,6 +329,9 @@ public class Ltrace
         Map&lt;task, Map&lt;address, List&lt;TracePoint&gt;&gt;&gt; */
     private HashMap retBreakpointsForTask = new HashMap();
 
+    /** Keeps track of map/unmap events. */
+    private MappingGuard mappingGuard = new MappingGuard(this);
+
     // ---------------------
     // --- ltrace driver ---
     // ---------------------
@@ -479,21 +484,6 @@ public class Ltrace
 	    }
 	}
 
-      // Unfortunately, I know of no reasonable, (as in platform
-      // independent) way to find whether a syscall is mmap,
-      // munmap, or anything else.  Hence this hack, which is
-      // probably still much better than rescanning the map on
-      // each syscall.
-      String name = syscall.getName();
-
-      if (name.indexOf("mmap") != -1
-	  || name.indexOf("munmap") != -1)
-	{
-	  this.checkMapUnmapUpdates(task, false);
-	  task.requestUnblock(this);
-	  return Action.BLOCK;
-	}
-
       return Action.CONTINUE;
     }
 
@@ -637,15 +627,14 @@ public class Ltrace
       long pc = task.getIsa().pc(task);
       logger.log(Level.FINE,
 		 "new task attached at 0x" + Long.toHexString(pc)
-		 + ", pid=" + task.getTaskId().intValue(), this);
+		 + ", pid=" + task.getTaskId().intValue());
 
       this.mapsForTask.put(task, java.util.Collections.EMPTY_SET);
-
-      // Can't use the EMPTY_MAPs here, cause these get modified directly.
       this.breakpointsForTask.put(task, new HashMap());
       this.retBreakpointsForTask.put(task, new HashMap());
 
       this.checkMapUnmapUpdates(task, false);
+      mappingGuard.attachTo(task);
 
       task.requestUnblock(this);
       return Action.BLOCK;
@@ -711,6 +700,12 @@ public class Ltrace
     // --- mmap/munmap handling ---
     // ----------------------------
 
+    /** Implementation of MappingController interface... */
+    public void checkMapUnmapUpdates(Task task)
+    {
+	checkMapUnmapUpdates(task, false);
+    }
+
     private void checkMapUnmapUpdates(Task task, boolean terminating)
     {
       Set mappedFiles = (Set)this.mapsForTask.get(task);
diff --git a/frysk-core/frysk/ftrace/LtraceController.java b/frysk-core/frysk/ftrace/MappingController.java
similarity index 85%
copy from frysk-core/frysk/ftrace/LtraceController.java
copy to frysk-core/frysk/ftrace/MappingController.java
index aae77e2..6f1b02f 100644
--- a/frysk-core/frysk/ftrace/LtraceController.java
+++ b/frysk-core/frysk/ftrace/MappingController.java
@@ -40,14 +40,15 @@
 package frysk.ftrace;
 
 /**
- * The LtraceController interface is used for decisions on what should
- * be done with each loaded library.
+ * Mapping guards signal request to rescan mappings through this
+ * interface.  The interface is package-private, because noone from
+ * outside should have to use it.
  */
-public interface LtraceController
+interface MappingController
 {
-  /**
-   * New library FILE was mapped in task TASK.  Use DRIVER to tell
-   * ltrace what to do.
-   */
-  void fileMapped(frysk.proc.Task task, ObjectFile file, Ltrace.Driver driver);
+    /**
+     * New library FILE was mapped in task TASK.  Use DRIVER to tell
+     * ltrace what to do.
+     */
+    void checkMapUnmapUpdates(frysk.proc.Task task);
 }
diff --git a/frysk-core/frysk/ftrace/MappingGuard.java b/frysk-core/frysk/ftrace/MappingGuard.java
new file mode 100644
index 0000000..e88e226
--- /dev/null
+++ b/frysk-core/frysk/ftrace/MappingGuard.java
@@ -0,0 +1,182 @@
+// This file is part of the program FRYSK.
+//
+// Copyright 2007, 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.ftrace;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.logging.*;
+
+import frysk.proc.Action;
+import frysk.proc.Task;
+import frysk.proc.TaskObserver;
+
+class MappingGuard
+    implements TaskObserver.Code,
+	       TaskObserver.Syscall
+{
+    protected static final Logger logger = Logger.getLogger(FtraceLogger.LOGGER_ID);
+    private HashMap syscallCache = new HashMap();
+    private MappingController ltraceProper;
+
+    public MappingGuard(MappingController ltraceProper) {
+	this.ltraceProper = ltraceProper;
+    }
+
+    public Action updateHit (Task task, long address)
+    {
+	ltraceProper.checkMapUnmapUpdates(task);
+	task.requestUnblock(this);
+	return Action.BLOCK;
+    }
+
+    public Action updateSyscallEnter (Task task)
+    {
+	frysk.proc.Syscall syscall = task.getSyscallEventInfo().getSyscall(task);
+	syscallCache.put(task, syscall);
+	return Action.CONTINUE;
+    }
+
+    public Action updateSyscallExit (Task task)
+    {
+	frysk.proc.Syscall syscall = (frysk.proc.Syscall)syscallCache.remove(task);
+
+	// Unfortunately, I know of no reasonable (as in
+	// platform independent) way to find whether a syscall
+	// is mmap, munmap, or anything else.  Hence this hack,
+	// which is probably still much better than rescanning
+	// the map on each syscall.
+	String name = syscall.getName();
+	if (name.indexOf("mmap") != -1 || name.indexOf("munmap") != -1) {
+	    ltraceProper.checkMapUnmapUpdates(task);
+	    task.requestUnblock(this);
+	    return Action.BLOCK;
+	}
+
+	return Action.CONTINUE;
+    }
+
+    public void addFailed(Object o, Throwable t) {}
+    public void deletedFrom(Object o) {}
+    public void addedTo(Object o) {}
+
+    /**
+     * Try to setup guard based on _dl_debug_state.
+     *
+     * Set up _dl_debug_state observer to spot each mapping.  The
+     * proper way to do this is to look up the DT_DEBUG entry in
+     * task's DYNAMIC segment, and look into the structure it points
+     * to.  But we would have to wait for dynamic linker to fill
+     * this info, and meanwhile we would miss all the
+     * mapping/unmapping.
+     *
+     * @return true on success, false on failure.
+     */
+    private boolean setupDebugStateObserver(Task task)
+    {
+	logger.log(Level.FINE, "Entering....");
+
+	java.io.File f = new java.io.File(task.getProc().getExe());
+	ObjectFile objf = ObjectFile.buildFromFile(f);
+	String interp = objf.getInterp();
+	if (interp == null) {
+	    // We're boned.
+	    logger.log(Level.WARNING, "`{1}' has no interpreter.", f);
+	    return false;
+	}
+
+	java.io.File interppath = new java.io.File(interp);
+	try {
+	    interppath = interppath.getCanonicalFile();
+	}
+	catch (java.io.IOException e) {
+	    logger.log(Level.WARNING,
+		       "Couldn't get canonical path of ELF interpreter `{1}'.",
+		       interppath);
+	    return false;
+	}
+
+	ObjectFile interpf = ObjectFile.buildFromFile(interppath);
+	TracePoint tp = null;
+	try {
+	    tp = interpf.lookupTracePoint("_dl_debug_state",
+					  TracePointOrigin.DYNAMIC);
+	    if (tp == null) {
+		logger.log(Level.FINE,
+			   "Symbol _dl_debug_state not found in `{1}'.",
+			   interppath);
+		return false;
+	    }
+	}
+	catch (lib.dwfl.ElfException e) {
+	    e.printStackTrace();
+	    logger.log(Level.WARNING,
+		       "Problem reading DYNAMIC entry points from `{1}'",
+		       interppath);
+	    return false;
+	}
+
+	// Load initial set of mapped files.
+	Set currentMappings = MemoryMapping.buildForPid(task.getTid());
+	long relocation = -1;
+	for (Iterator it = currentMappings.iterator(); it.hasNext(); ) {
+	    MemoryMapping mm = (MemoryMapping)it.next();
+	    if (mm.path.equals(interppath)) {
+		relocation = mm.addressLow - interpf.getBaseAddress();
+		break;
+	    }
+	}
+	if (relocation == -1) {
+	    logger.log(Level.FINE, "Couldn't obtain relocation of interpreter.");
+	    return false;
+	}
+
+	// There we go!
+	long fin = tp.address + relocation;
+	task.requestAddCodeObserver(this, fin);
+	return true;
+    }
+
+    public void attachTo(Task task)
+    {
+	if (!setupDebugStateObserver(task))
+	    task.requestAddSyscallObserver(this);
+    }
+}
diff --git a/frysk-core/frysk/ftrace/ObjectFile.java b/frysk-core/frysk/ftrace/ObjectFile.java
index 8400e1e..ba9dbd7 100644
--- a/frysk-core/frysk/ftrace/ObjectFile.java
+++ b/frysk-core/frysk/ftrace/ObjectFile.java
@@ -71,6 +71,7 @@ public class ObjectFile
 {
   private File filename;
   private String soname = null;
+  private String interp = null;
   private long baseAddress = 0;
   private long entryPoint = 0;
   private static HashMap cachedFiles = new HashMap();
@@ -181,20 +182,18 @@ public class ObjectFile
       throws lib.dwfl.ElfException
     {
       ArrayList tracePoints = (ArrayList)this.tracePointMap.get(origin);
-      if (tracePoints != null)
-	{
+      if (tracePoints != null) {
 	  logger.log(Level.FINE, "" + tracePoints.size() + " tracepoints for origin " + origin + " retrieved from cache.");
 	  return tracePoints;
-	}
+      }
 
       logger.log(Level.FINE, "Loading tracepoints for origin " + origin + ".");
       if ((origin == TracePointOrigin.PLT
 	   || origin == TracePointOrigin.DYNAMIC)
 	  && this.haveDynamic)
-	{
+      {
 	  // Initialize dynamic symbol list for PLT if necessary...
-	  if (this.dynamicSymbolList == null)
-	    {
+	  if (this.dynamicSymbolList == null) {
 	      long count = ElfSymbol.symbolsCount(ObjectFile.this.dynamicSymtab);
 	      assertFitsToInt(count, "Symbol count");
 	      this.dynamicSymbolList = new Symbol[(int)count];
@@ -202,10 +201,9 @@ public class ObjectFile
 		= new ElfSymbol.Loader(ObjectFile.this.dynamicSymtab, ObjectFile.this.dynamicVersym,
 				       ObjectFile.this.dynamicVerdef, ObjectFile.this.dynamicVerdefCount,
 				       ObjectFile.this.dynamicVerneed, ObjectFile.this.dynamicVerneedCount);
-	    }
+	  }
 
-	  if (origin == TracePointOrigin.DYNAMIC)
-	    {
+	  if (origin == TracePointOrigin.DYNAMIC) {
 	      // Load dynamic symtab and PLT entries.
 	      logger.log(Level.FINER, "Loading dynamic symtab.");
 	      this.origin = TracePointOrigin.DYNAMIC;
@@ -213,10 +211,9 @@ public class ObjectFile
 	      this.tracePointMap.put(this.origin, this.tracePoints);
 
 	      this.dynamicLoader.loadAll(this);
-	    }
+	  }
 
-	  if (origin == TracePointOrigin.PLT)
-	    {
+	  if (origin == TracePointOrigin.PLT) {
 	      int pltCount = ObjectFile.this.pltRelocs.length;
 	      logger.log(Level.FINER, "Loading " + pltCount + " PLT entries.");
 
@@ -234,22 +231,20 @@ public class ObjectFile
 		/* XXX HACK: 386/x64 specific.  In general we want
 		 * platform-independent way of asking whether it's
 		 * JMP_SLOT relocation. */
-		if (ObjectFile.this.pltRelocs[i].type == 7)
-		  {
+		if (ObjectFile.this.pltRelocs[i].type == 7) {
 		    long pltEntryAddr = ObjectFile.this.pltAddr + pltEntrySize * (i + 1);
 		    long symbolIndex = ObjectFile.this.pltRelocs[i].symbolIndex;
 
 		    assertFitsToInt(symbolIndex, "Symbol associated with PLT entry");
 		    Symbol symbol = this.dynamicSymbolList[(int)symbolIndex];
-		    if (symbol == null)
-		      {
+		    if (symbol == null) {
 			logger.log(Level.FINEST,
 				   "Lazy loading symbol #" + symbolIndex);
 			this.origin = TracePointOrigin.DYNAMIC;
 			this.tracePoints = tracePointsDynamic;
 			this.dynamicLoader.load(symbolIndex, this);
 			symbol = this.dynamicSymbolList[(int)symbolIndex];
-		      }
+		    }
 		    if (symbol == null)
 		      throw new AssertionError("Dynamic symbol still not initialized.");
 
@@ -259,12 +254,11 @@ public class ObjectFile
 		    this.origin = TracePointOrigin.PLT;
 		    this.tracePoints = tracePointsPlt;
 		    this.addNewTracepoint(pltEntryAddr, symbol);
-		  }
-	    }
-	}
+		}
+	  }
+      }


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


                 reply	other threads:[~2007-11-08 13:07 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20071108130703.24640.qmail@sourceware.org \
    --to=pmachata@sourceware.org \
    --cc=frysk-cvs@sourceware.org \
    --cc=frysk@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).