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<task, Map<address, List<TracePoint>>> */ 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: linkBe 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).