[SCM] master: Forgotten changelogs, no longer unresolved x8664 testcases.

pmachata@sourceware.org pmachata@sourceware.org
Wed Nov 14 21:21:00 GMT 2007


The branch, master has been updated
       via  e60eaf6b29b3ca49957843adc7e69f898f0f1a43 (commit)
       via  3c64e31d42bfb708ca142a559a4014d362eb0fc3 (commit)
       via  d66f674eb1d4f67e0f6f92a7ba39edc89cb74a39 (commit)
      from  5d772e1456994a832874051dd9eb307af3e4dd53 (commit)

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

- Log -----------------------------------------------------------------
commit e60eaf6b29b3ca49957843adc7e69f898f0f1a43
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed Nov 14 21:38:00 2007 +0100

    Forgotten changelogs, no longer unresolved x8664 testcases.

commit 3c64e31d42bfb708ca142a559a4014d362eb0fc3
Author: Petr Machata <pmachata@redhat.com>
Date:   Wed Nov 14 21:27:52 2007 +0100

    Revamp mapping system.
    
    * Instead of trying to merge several maps into one, ltrace now carries each mapping separately.  As soon as the file gets mapped (the file, or part thereof), the controller is asked to provide working set.  This working set is then applied or removed depending on which parts are mapped or unmapped.  The reason for this is that it turned out that x8664 maps libraries uncontinuously, and dl_debug_state observer choked on that, because it saw the wrong mapping.  Problem is that with uncontinuous mapping, you can't merge several mappings into one logical mapping anymore, because some files can be doubly-mapped.  So we track each mapping separately.
    * Resolves: #5321
    * As usual, the coding style of the code that I touched was java-ized.

commit d66f674eb1d4f67e0f6f92a7ba39edc89cb74a39
Author: Petr Machata <pmachata@redhat.com>
Date:   Sat Nov 10 17:37:18 2007 +0100

    Mapping guard refactorings
    
    It's now more similar to traditional frysk observer pattern (with
    requestAdd et. al.).  The two guards are reimplemented as subclasses
    of more general Guard abstract class.  Each task has guard of its own,
    it's not created one guard per observer anymore.  Of course having a
    guard per proc would be yet better...

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

Summary of changes:
 frysk-core/frysk/ftrace/ChangeLog                  |   27 ++
 frysk-core/frysk/ftrace/Ltrace.java                |  379 +++++++++++++-------
 frysk-core/frysk/ftrace/MappingGuard.java          |  245 ++++++++++----
 ...MappingController.java => MappingObserver.java} |   12 +-
 frysk-core/frysk/ftrace/MemoryMapping.java         |  169 +++++----
 frysk-core/frysk/ftrace/ObjectFile.java            |   76 ++---
 frysk-core/frysk/ftrace/Symbol.java                |    4 +-
 frysk-core/frysk/ftrace/TestLtrace.java            |   11 -
 frysk-core/frysk/ftrace/TracePoint.java            |   30 +-
 9 files changed, 610 insertions(+), 343 deletions(-)
 rename frysk-core/frysk/ftrace/{MappingController.java => MappingObserver.java} (85%)

First 500 lines of diff:
diff --git a/frysk-core/frysk/ftrace/ChangeLog b/frysk-core/frysk/ftrace/ChangeLog
index ce715bc..f369a79 100644
--- a/frysk-core/frysk/ftrace/ChangeLog
+++ b/frysk-core/frysk/ftrace/ChangeLog
@@ -1,3 +1,19 @@
+2007-11-14  Petr Machata  <pmachata@redhat.com>
+
+	* TestLtrace.java (testAllLibrariesGetDetected): No longer
+	unresolvedx8664.
+	(testCallRecorded): Ditto.
+	(testArgumentsCorrect1): Ditto.
+
+2007-11-14  Petr Machata  <pmachata@redhat.com>
+
+	* frysk-core/frysk/ftrace/Symbol.java (offset): New field.
+	* frysk-core/frysk/ftrace/TracePoint.java (offset): New field.
+	* frysk-core/frysk/ftrace/ObjectFile.java: Support `offset'.
+	* frysk-core/frysk/ftrace/MemoryMapping.java: Rewritten.
+	* frysk-core/frysk/ftrace/MappingGuard.java: Adapted to above.
+	* frysk-core/frysk/ftrace/Ltrace.java: Adapted to above.
+
 2007-11-13  Sami Wagiaalla  <swagiaal@redhat.com>
 
 	* TestLtrace.java (testAllLibrariesGetDetected): Marked
@@ -5,6 +21,17 @@
 	(testCallRecorded): Ditto.
 	(testArgumentsCorrect1): Ditto.
 
+2007-11-10  Petr Machata  <pmachata@redhat.com>
+
+	* MappingController.java: Renamed to MappingObserver.java.
+	* MappingGuard.java: Turned into more frysk task observer like pattern.
+	(MappingGuard.MappingGuardB) new abstract base class
+	(MappingGuard.SyscallMappingGuard) concrete guard implementation
+	(MappingGuard.DebugStateMappingGuard) another concrete guard impl.
+	(MappingGuard.requestAddMappingObserver,
+	 MappingGuard.requestDeleteMappingObserver) new static methods
+	* Ltrace.java: accomodate for the changes above
+
 2007-11-08  Petr Machata  <pmachata@redhat.com>
 
 	* MappingController.java: New file.
diff --git a/frysk-core/frysk/ftrace/Ltrace.java b/frysk-core/frysk/ftrace/Ltrace.java
index 97979c9..e3e4bfc 100644
--- a/frysk-core/frysk/ftrace/Ltrace.java
+++ b/frysk-core/frysk/ftrace/Ltrace.java
@@ -158,10 +158,8 @@ public class Ltrace
    * @param blocker An observer that blocks current process until
    * the tasks are processed.  Unblock is requested here.
    */
-  private void addProc(Proc proc, TaskObserver blocker)
+  private void addProc(Proc proc)
   {
-    Task mainTask = proc.getMainTask();
-
     // If a task appears after the getTasks() list is generated, but
     // before ProcTasks iteration below, it will be reported as
     // existing at ProcTasks iteration.  This set exists to
@@ -197,9 +195,6 @@ public class Ltrace
 	public void addedTo(Object arg0) {}
 	public void deletedFrom(Object arg0) {}
       });
-
-    if (blocker != null)
-      mainTask.requestUnblock(blocker);
   }
 
   private Map taskArchHandlers = new HashMap();
@@ -259,7 +254,7 @@ public class Ltrace
 	ProcId id = proc.getId();
 	if (pidsToTrace.contains(id))
 	  {
-	    addProc(proc, null);
+	    addProc(proc);
 	    pidsToTrace.remove(id);
 	    if (pidsToTrace.isEmpty())
 	      Manager.host.observableProcAddedXXX.deleteObserver(this);
@@ -295,8 +290,9 @@ public class Ltrace
     Manager.host.requestCreateAttachedProc(command, new TaskObserver.Attached() {
 	public Action updateAttached (Task task)
 	{
-	  addProc(task.getProc(), this);
-	  ltraceTaskObserver.updateAttached(task);
+	  addProc(task.getProc());
+	  ltraceTaskObserver.updateAttached(task, null);
+	  task.requestUnblock(this);
 	  return Action.BLOCK;
 	}
 	public void addFailed (Object arg0, Throwable w) {}
@@ -315,7 +311,7 @@ public class Ltrace
 	       TaskObserver.Signaled,
 	       TaskObserver.Terminated,
 	       TaskObserver.Terminating,
-	       MappingController
+	       MappingObserver
   {
     /** Remembers which files are currently mapped in which task. */
     private HashMap mapsForTask = new HashMap();
@@ -329,50 +325,9 @@ public class Ltrace
         Map<task, Map<address, List<TracePoint>>> */
     private HashMap retBreakpointsForTask = new HashMap();
 
-    /** Keeps track of map/unmap events. */
-    private MappingGuard mappingGuard = new MappingGuard(this);
-
-    // ---------------------
-    // --- ltrace driver ---
-    // ---------------------
-
-    private class DriverImpl
-      implements Ltrace.Driver
-    {
-      final long relocation;
-
-      public DriverImpl(long relocation)
-      {
-	this.relocation = relocation;
-      }
-
-      public void tracePoint(Task task, TracePoint tp)
-      {
-	long addr = tp.address + this.relocation;
-	Long laddr = new Long(addr);
-	logger.log(Level.CONFIG, "Will trace `" + tp.symbol.name
-		   + "' at 0x" + Long.toHexString(addr), this);
-
-	// FIXME: probably handle aliases at a lower
-	// lever.  Each tracepoint should point to a list
-	// of symbols that alias it, and should be present
-	// only once in an ObjectFile.
-	synchronized (LtraceTaskObserver.this) {
-	    HashMap breakpoints = (HashMap)breakpointsForTask.get(task);
-	    if (breakpoints.containsKey(laddr)) {
-		// We got an alias.  Put the symbol with the
-		// shorter name into the map.
-		TracePoint original = (TracePoint)breakpoints.get(laddr);
-		if (tp.symbol.name.length() < original.symbol.name.length())
-		  breakpoints.put(laddr, tp);
-	    }
-	    else {
-		task.requestAddCodeObserver(ltraceTaskObserver, laddr.longValue());
-		breakpoints.put(laddr, tp);
-	    }
-	}
-      }
-    }
+	/** Remembers working set preferences for each task.
+	    Map<Task, Map<File, TracePointWorkingSet>> */
+	private HashMap driversForTask = new HashMap();
 
     // ------------------------
     // --- syscall observer ---
@@ -621,7 +576,7 @@ public class Ltrace
     // --- attached/terminated/terminating observers ---
     // -------------------------------------------------
 
-    public Action updateAttached (Task task)
+    public void updateAttached(Task task, TaskObserver blocker)
     {
       // Per-task initialization.
       long pc = task.getIsa().pc(task);
@@ -629,14 +584,17 @@ public class Ltrace
 		 "new task attached at 0x" + Long.toHexString(pc)
 		 + ", pid=" + task.getTaskId().intValue());
 
-      this.mapsForTask.put(task, java.util.Collections.EMPTY_SET);
+      this.mapsForTask.put(task, java.util.Collections.EMPTY_MAP);
       this.breakpointsForTask.put(task, new HashMap());
       this.retBreakpointsForTask.put(task, new HashMap());
 
       this.checkMapUnmapUpdates(task, false);
-      mappingGuard.attachTo(task);
+      MappingGuard.requestAddMappingObserver(task, this);
+    }
 
-      task.requestUnblock(this);
+    public Action updateAttached (Task task)
+    {
+      updateAttached(task, this);
       return Action.BLOCK;
     }
 
@@ -671,7 +629,7 @@ public class Ltrace
     {
       if(traceChildren)
 	{
-	  addProc(offspring.getProc(), null);
+	  addProc(offspring.getProc());
 	  offspring.requestUnblock(this);
 	  return Action.BLOCK;
 	}
@@ -696,84 +654,250 @@ public class Ltrace
 
 
 
-    // ----------------------------
-    // --- mmap/munmap handling ---
-    // ----------------------------
+      // ----------------------------
+      // --- mmap/munmap handling ---
+      // ----------------------------
 
-    /** Implementation of MappingController interface... */
-    public void checkMapUnmapUpdates(Task task)
-    {
-	checkMapUnmapUpdates(task, false);
-    }
+      private class TracePointWorkingSet
+	  implements Ltrace.Driver
+      {
+	  private Set tracePoints = new HashSet();
 
-    private void checkMapUnmapUpdates(Task task, boolean terminating)
-    {
-      Set mappedFiles = (Set)this.mapsForTask.get(task);
-      Set newMappedFiles = terminating ?
-	java.util.Collections.EMPTY_SET : MemoryMapping.buildForPid(task.getTid());
-
-      // Assume that files get EITHER mapped, OR unmapped.  Because
-      // under normal conditions, each map/unmap will get spotted,
-      // this is a reasonable assumption.
-      if (newMappedFiles.size() > mappedFiles.size()) {
-	  Set diff = new HashSet(newMappedFiles);
-	  diff.removeAll(mappedFiles);
-	  for (Iterator it = diff.iterator(); it.hasNext(); ) {
-	      MemoryMapping info = (MemoryMapping)it.next();
-	      this.updateMappedFile(task, info);
+	  public void tracePoint(Task task, TracePoint tp)
+	  {
+	      logger.log(Level.CONFIG, "Request for tracing `{0}'", tp.symbol.name);
+	      tracePoints.add(tp);
+	  }
+
+	  public void populateBreakpoints(Task task, MemoryMapping.Part part)
+	  {
+	      for (Iterator it = tracePoints.iterator(); it.hasNext(); ) {
+		  TracePoint tp = (TracePoint)it.next();
+		  if (tp.offset >= part.offset
+		      && tp.offset < part.offset + part.addressHigh - part.addressLow) {
+		      logger.log(Level.FINER,
+				 "Will trace `" + tp.symbol.name + "', "
+				 + "address=0x" + Long.toHexString(tp.address) + "; "
+				 + "offset=0x" + Long.toHexString(tp.offset) + "; "
+				 + "part at=0x" + Long.toHexString(part.addressLow)
+				 + ".." + Long.toHexString(part.addressHigh) + "; "
+				 + "part off=0x" + Long.toHexString(part.offset) + ";");
+
+		      long actualAddress = tp.offset - part.offset + part.addressLow;
+		      Long laddr = new Long(actualAddress);
+		      logger.log(Level.CONFIG,
+				 "Will trace `" + tp.symbol.name
+				 + "' at 0x" + Long.toHexString(actualAddress));
+
+		      // FIXME: probably handle aliases at a lower
+		      // lever.  Each tracepoint should point to a list
+		      // of symbols that alias it, and should be present
+		      // only once in an ObjectFile.
+		      synchronized (LtraceTaskObserver.this) {
+			  HashMap breakpoints = (HashMap)breakpointsForTask.get(task);
+			  if (breakpoints.containsKey(laddr)) {
+			      // We got an alias.  Put the symbol with the
+			      // shorter name into the map.
+			      TracePoint original = (TracePoint)breakpoints.get(laddr);
+			      if (tp.symbol.name.length() < original.symbol.name.length())
+				  breakpoints.put(laddr, tp);
+			  }
+			  else {
+			      task.requestAddCodeObserver(ltraceTaskObserver, laddr.longValue());
+			      breakpoints.put(laddr, tp);
+			  }
+		      }
+		  }
+	      }
+	  }
+
+	  public void evacuateBreakpoints(Task task, MemoryMapping.Part part)
+	  {
+	      for (Iterator it = tracePoints.iterator(); it.hasNext(); ) {
+		  TracePoint tp = (TracePoint)it.next();
+		  if (tp.offset >= part.offset
+		      && tp.offset < part.offset + part.addressHigh - part.addressLow) {
+
+		      long actualAddress = tp.offset - part.offset + part.addressLow;
+		      Long laddr = new Long(actualAddress);
+		      logger.log(Level.CONFIG,
+				 "Stopping tracing of `" + tp.symbol.name
+				 + "' at 0x" + Long.toHexString(actualAddress));
+
+		      // FIXME: Handle aliases.
+		      synchronized (LtraceTaskObserver.this) {
+			  HashMap breakpoints = (HashMap)breakpointsForTask.get(task);
+			  TracePoint original = (TracePoint)breakpoints.remove(laddr);
+			  if (original == null)
+			      throw new AssertionError("Couldn't find breakpoint to remove!");
+			  task.requestDeleteCodeObserver(ltraceTaskObserver, laddr.longValue());
+		      }
+		  }
+	      }
 	  }
       }
-      else if (newMappedFiles.size() < mappedFiles.size()) {
-	  // We can avoid artificial `diff' set here, to gain a
-	  // little performance.
-	  mappedFiles.removeAll(newMappedFiles);
-	  for (Iterator it = mappedFiles.iterator(); it.hasNext(); ) {
-	      MemoryMapping info = (MemoryMapping)it.next();
-	      this.updateUnmappedFile(task, info);
+
+      /** Implementation of MappingObserver interface... */
+      public Action updateMapping(Task task) {
+	  checkMapUnmapUpdates(task, false);
+	  task.requestUnblock(this);
+	  return Action.BLOCK;
+      }
+
+      private void checkMapUnmapUpdates(Task task, boolean terminating)
+      {
+	  Map oldMappings = (Map)this.mapsForTask.get(task);
+	  final Map newMappings;
+	  if (terminating)
+	      newMappings = java.util.Collections.EMPTY_MAP;
+	  else
+	      newMappings = MemoryMapping.buildForPid(task.getTid());
+
+	  // Resolve full mmaps, and partial mmaps and unmaps.
+	  for (Iterator it = newMappings.entrySet().iterator(); it.hasNext(); ) {
+	      Map.Entry entry = (Map.Entry)it.next();
+	      Object oKey = entry.getKey(); // actually File
+	      MemoryMapping newMapping = (MemoryMapping)entry.getValue();
+	      if (!oldMappings.containsKey(oKey)) {
+		  this.updateMappedFile(task, newMapping);
+	      }
+	      else {
+		  // Remove the key from old set, so that at the end, only
+		  // unmapped values are left.
+		  MemoryMapping oldMapping = (MemoryMapping)oldMappings.remove(oKey);
+		  int oldSize = oldMapping.parts.size();
+		  int newSize = newMapping.parts.size();
+		  if (oldSize < newSize) {
+		      // newMapping.parts[oldSize:] is VERY likely the new stuff
+		      for (int i = oldMapping.parts.size(); i < newMapping.parts.size(); ++i) {
+			  MemoryMapping.Part part = (MemoryMapping.Part)newMapping.parts.get(i);
+			  this.updateMappedPart(task, newMapping, part);
+		      }
+		  }
+		  else if (oldSize > newSize) {
+		      // Find first non-matching Part.
+		      int i = 0;
+		      int j = 0;
+		      while (i < oldSize && j < newSize
+			     && oldMapping.parts.get(i).equals(newMapping.parts.get(j))) {
+			  ++i;
+			  ++j;
+		      }
+
+		      // If `j' is at the end, the remaining old parts
+		      // are unmapped.  Otherwise only the portion
+		      // until the first matching part is unmapped.
+		      while (i < oldSize
+			     && (j >= newSize
+				 || !oldMapping.parts.get(i).equals(newMapping.parts.get(j)))) {
+			  MemoryMapping.Part part = (MemoryMapping.Part)oldMapping.parts.get(i);
+			  this.updateUnmappedPart(task, oldMapping, part);
+			  ++i;
+		      }
+		  }
+	      }
+	  }
+
+	  // Resolve full unmaps.
+	  for (Iterator it = oldMappings.entrySet().iterator(); it.hasNext(); ) {
+	      Map.Entry entry = (Map.Entry)it.next();
+	      MemoryMapping removedMapping = (MemoryMapping)entry.getValue();
+	      this.updateUnmappedFile(task, removedMapping);
 	  }
+
+	  this.mapsForTask.put(task, newMappings);
       }
 
-      this.mapsForTask.put(task, newMappedFiles);
-    }
+      private void updateMappedPart(Task task, MemoryMapping mapping,
+				    MemoryMapping.Part part,
+				    TracePointWorkingSet driver)
+      {
+	  driver.populateBreakpoints(task, part);
+      }
 
-    private void updateMappedFile(final Task task, MemoryMapping mapping)
-    {
-      synchronized(observers)
-	{
-	  for (Iterator it = observers.iterator(); it.hasNext(); )
-	    {
-	      LtraceObserver o = (LtraceObserver)it.next();
-	      o.fileMapped(task, mapping.path);
-	    }
-	}
+      private void updateUnmappedPart(Task task, MemoryMapping mapping,
+				    MemoryMapping.Part part,
+				    TracePointWorkingSet driver)
+      {
+	  driver.evacuateBreakpoints(task, part);
+      }
 
-      // Try to load the mappped file as ELF.  Assume all
-      // executable-mmapped ELF files are libraries.
-      if (!mapping.permExecute)
-	return;
-      ObjectFile objf = ObjectFile.buildFromFile(mapping.path);
-      if (objf == null)
-	return;
-
-      // It's actually cheaper to create one driver per task and file
-      // loaded, than to look up relocation for each TracePoint
-      // processed by the driver.
-      long relocation = mapping.addressLow - objf.getBaseAddress();
-      DriverImpl driver = new DriverImpl(relocation);
-      ltraceController.fileMapped(task, objf, driver);
-    }
+      private void updateMappedPart(Task task, MemoryMapping mapping, MemoryMapping.Part part)
+      {
+	  // At this point we already know client preferences
+	  // regarding which tracepoints should be in working set.
+	  // Just apply this knowledge on new mapped part: all working
+	  // set elements that fall into this part should be observed.
+
+	  // This has to be non-null, we already called
+	  // updateMappedFile when the file was mapped:
+	  Map drivers = (Map)driversForTask.get(task);
+	  TracePointWorkingSet driver = (TracePointWorkingSet)drivers.get(mapping.path);
+	  updateMappedPart(task, mapping, part, driver);
+      }
 
-    private void updateUnmappedFile (Task task, MemoryMapping mapping)
-    {
-      synchronized(observers)
-	{
-	  for (Iterator it = observers.iterator(); it.hasNext(); )
-	    {
-	      LtraceObserver o = (LtraceObserver)it.next();
-	      o.fileUnmapped(task, mapping.path);
-	    }
-	}
-    }
+      private void updateUnmappedPart(Task task, MemoryMapping mapping, MemoryMapping.Part part)
+      {
+	  // This has to be non-null.
+	  Map drivers = (Map)driversForTask.get(task);
+	  TracePointWorkingSet driver = (TracePointWorkingSet)drivers.get(mapping.path);
+	  updateUnmappedPart(task, mapping, part, driver);
+      }
+
+      private void updateMappedFile(Task task, MemoryMapping mapping)
+      {
+	  // New file has been mapped.  Notify all observers (TODO: this
+	  // should go away once ltrace becomes true observer), and let
+	  // client define working set of this file.  Then implement the
+	  // working set via updateMappedPart of each part in mapping.
+	  synchronized(observers) {
+	      for (Iterator it = observers.iterator(); it.hasNext(); ) {
+		  LtraceObserver o = (LtraceObserver)it.next();
+		  o.fileMapped(task, mapping.path);
+	      }
+	  }
+
+	  ObjectFile objf = ObjectFile.buildFromFile(mapping.path);
+	  if (objf == null)
+	      return;
+
+	  TracePointWorkingSet driver = new TracePointWorkingSet();
+	  Map drivers = (Map)driversForTask.get(task);
+	  if (drivers == null) {
+	      drivers = new HashMap();
+	      driversForTask.put(task, drivers);
+	  }
+	  drivers.put(mapping.path, driver);
+	  ltraceController.fileMapped(task, objf, driver);
+
+	  for (Iterator it = mapping.parts.iterator(); it.hasNext(); ) {
+	      MemoryMapping.Part part = (MemoryMapping.Part)it.next();
+	      if (part.permExecute)
+		  updateMappedPart(task, mapping, part, driver);
+	  }
+      }
+
+      private void updateUnmappedFile (Task task, MemoryMapping mapping)
+      {
+	  // TODO: this should go away once ltrace becomes true
+	  // observer.
+	  synchronized(observers) {
+	      for (Iterator it = observers.iterator(); it.hasNext(); ) {
+		  LtraceObserver o = (LtraceObserver)it.next();
+		  o.fileUnmapped(task, mapping.path);
+	      }
+	  }
+
+	  // This has to be non-null.
+	  Map drivers = (Map)driversForTask.get(task);
+	  TracePointWorkingSet driver = (TracePointWorkingSet)drivers.get(mapping.path);


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



More information about the Frysk-cvs mailing list