diff --git a/frysk-common/ChangeLog b/frysk-common/ChangeLog index 8d1b606..10dc607 100644 --- a/frysk-common/ChangeLog +++ b/frysk-common/ChangeLog @@ -1,3 +1,26 @@ +2008-06-20 Andrew Cagney <cagney@redhat.com> + + * Makefile.rules (lib$(GEN_DIRNAME)-jni.so): Replace less explicit + %-jni.so target. + + * Makefile.rules (Runner): Delete LD_PRELOAD hack. + +2008-06-19 Andrew Cagney <cagney@redhat.com> + + * Makefile.gen.sh (jni): Delete. + * Makefile.rules (%-jni.so): Depend on $(JNI_ARCHIVE_LIST) and + $(JNI_OBJECT_LIST). + (jni): New phony target. + + * Makefile.rules (JNI_OBJECT_LIST): Define. + (JNI_LIBRARY_LIST): Define. + (JNI_ARCHIVE_LIST): Define. + (%-jni.so: %-jni.a): New rule. + +2008-06-17 Andrew Cagney <cagney@redhat.com> + + * Makefile.rules (Runner): Load libaudit.so. + 2008-06-09 Andrew Cagney <cagney@redhat.com> * Makefile.rules (Runner): (Really) Let JAVA be overwritten by an diff --git a/frysk-common/Makefile.gen.sh b/frysk-common/Makefile.gen.sh index a9dc667..6e7c3ab 100755 --- a/frysk-common/Makefile.gen.sh +++ b/frysk-common/Makefile.gen.sh @@ -895,8 +895,7 @@ noinst_LIBRARIES += lib${GEN_DIRNAME}-jni.a lib${GEN_MAKENAME}_jni_so_SOURCES = solib_PROGRAMS += lib${GEN_DIRNAME}-jni.so lib${GEN_DIRNAME}-jni.so: lib${GEN_DIRNAME}-jni.a -.PHONY: jni -jni: lib${GEN_DIRNAME}-jni.so ${GEN_DIRNAME}.jar +jni: lib${GEN_DIRNAME}-jni.so lib${GEN_MAKENAME}_jni_a_SOURCES += jni.cxx jnixx_sources = \$(wildcard \$(root_srcdir)/frysk-sys/jnixx/*.java) CLEANFILES += jni.hxx jni.cxx jni.hxx.gch diff --git a/frysk-common/Makefile.rules b/frysk-common/Makefile.rules index 7f30cd3..c80b81c 100644 --- a/frysk-common/Makefile.rules +++ b/frysk-common/Makefile.rules @@ -94,6 +94,7 @@ GEN_CLASSPATH = GEN_SOURCEPATH = $(srcdir) $(top_builddir) empty= space=$(empty) $(empty) +comma=$(empty),$(empty) JAVAROOT = classes # The list of libraries for the GCJ programs is different to that of @@ -189,6 +190,10 @@ AM_CCASFLAGS = \ $(ZZZ) +# Just build the jar / jni dependencies files. +.PHONY: jni +jni: ${GEN_DIRNAME}.jar + # Within the BUILT_SOURCES, need to force some dependencies. For # instance: JAVAH isn't run until all script-generated files it may # need to import have been generated. @@ -395,20 +400,8 @@ Runner: echo "" >> $@.tmp echo "# some pre-definitions" >> $@.tmp echo "elfutils=$(frysk_imports)/elfutils" >> $@.tmp - echo "libunwind=$(frysk_imports)/libunwind" >> $@.tmp echo "java=\"$(JAVA) $(GEN_GCJ_NO_SIGCHLD_FLAGS)\"" >> $@.tmp echo "" >> $@.tmp - echo "# Hack to pull in JNI dependences" >> $@.tmp - echo "export LD_PRELOAD=\\" >> $@.tmp - echo "\$${elfutils}/libelf/libelf.so\\ \\" >> $@.tmp - echo "\$${elfutils}/libdw/libdw.so\\ \\" >> $@.tmp - echo "\$${elfutils}/libasm/libasm.so\\ \\" >> $@.tmp - echo "\$${libunwind}-i386/src/.libs/libunwind-x86.so\\ \\" >> $@.tmp - echo "\$${libunwind}-ppc32/src/.libs/libunwind-ppc32.so\\ \\" >> $@.tmp - echo "\$${libunwind}-ppc64/src/.libs/libunwind-ppc64.so\\ \\" >> $@.tmp - echo "\$${libunwind}-x86_64/src/.libs/libunwind-x86_64.so\\ \\" >> $@.tmp - echo "libstdc++.so.6" >> $@.tmp - echo "" >> $@.tmp echo "# hack to hopefully find the right libstdc++.so" >> $@.tmp echo "export LD_LIBRARY_PATH=$(frysk_sys)\\" >> $@.tmp echo ":\$${elfutils}/backends\\" >> $@.tmp @@ -464,6 +457,36 @@ SUFFIXES += .so -Wl,--soname,$$soname,-z,-defs if readelf -d $@.tmp | fgrep -q TEXTREL; then exit 1; fi mv $@.tmp $@ + +# Build a JNI shared object from one or more archives and one or more +# object files. This lets frysk bundle up into a single somewhat +# large shared object, all the native code it needs to drag around. +# Over time it should become smaller. + +# A list of .a files that should be incorporated into the .so. +JNI_ARCHIVE_LIST = + +# List of shared objects required by this code. The link-loader will +# automatically pull these in as part of the build. +JNI_LIBRARY_LIST = + +# A list of extra object files that should be added to the .so. +JNI_OBJECT_LIST = + +lib$(GEN_DIRNAME)-jni.so: $(JNI_ARCHIVE_LIST) $(JNI_OBJECT_LIST) +lib$(GEN_DIRNAME)-jni.so: lib$(GEN_DIRNAME)-jni.a + soname=`basename $@` ; \ + $(CC) -shared -o $@.tmp \ + -Wl,--whole-archive \ + -Wl,$< \ + $(JNI_ARCHIVE_LIST:%=-Wl,%) \ + -Wl,--no-whole-archive \ + -Wl,--soname,$$soname,-z,-defs \ + $(JNI_OBJECT_LIST) \ + $(JNI_LIBRARY_LIST) + if readelf -d $@.tmp | fgrep TEXTREL; then exit 1; fi + mv $@.tmp $@ + # Clueless automake: Use a phony DATA entry to convince AUTOMAKE that # it really should install a .so file into LIBDIR. The obvious diff --git a/frysk-common/version.in b/frysk-common/version.in index bd73f47..6aed7c3 100644 --- a/frysk-common/version.in +++ b/frysk-common/version.in @@ -1 +1 @@ -0.4 +0.4.50 diff --git a/frysk-core/frysk/bindir/ChangeLog b/frysk-core/frysk/bindir/ChangeLog index 0429ed3..1097433 100644 --- a/frysk-core/frysk/bindir/ChangeLog +++ b/frysk-core/frysk/bindir/ChangeLog @@ -1,3 +1,30 @@ +2008-06-12 Andrew Cagney <cagney@redhat.com> + + * TestFexe.java (testExeOfDeletedFile()): Enable. Match expected + error. + * fexe.java: Use Exe.getName. + + * TestFexe.java (testExeOfDeletedFile()): New; mark as unresolved + 6621. + +2008-06-13 Petr Machata <pmachata@redhat.com> + + * ftrace.xml-in: Update. + +2008-06-10 Andrew Cagney <cagney@redhat.com> + + * TestFstack.java (testBackTraceWithFullPath): Specify "paths", + not "full-path". + + * TestFstack.java (testBackTrace) + (testBackTraceWithDebugNamesAndParams): Check for from <exe>. + * TestFstack.java (testBackTraceWithRich()): Mark as unresolved; + bug 6616. + * ferror.java: Use PrintDebugInfoStackOptions; don't specify the + default stack options. + * ftrace.java: Ditto. + * fstack.java: Ditto. + 2008-06-04 Sami Wagiaalla <swagiaal@redhat.com> * TestFstep.java: Marked tests are unresolved. diff --git a/frysk-core/frysk/bindir/TestFexe.java b/frysk-core/frysk/bindir/TestFexe.java index 6f79c80..5a37447 100644 --- a/frysk-core/frysk/bindir/TestFexe.java +++ b/frysk-core/frysk/bindir/TestFexe.java @@ -39,6 +39,7 @@ package frysk.bindir; +import frysk.testbed.TearDownFile; import frysk.testbed.TearDownExpect; import frysk.testbed.TestLib; import frysk.config.Prefix; @@ -87,4 +88,27 @@ public class TestFexe extends TestLib { e.expect("/bin/bash" + "\r\n"); } + public void testExeOfDeletedFile() { + TearDownExpect e = new TearDownExpect(); + TearDownFile exe = TearDownFile.create(); + // Create a copy of sleep that is executable. + e.send("cp /bin/sleep " + exe.getPath() + "\r"); + e.expect("cp .*\\$ "); + e.send("chmod +x " + exe.getPath() + "\r"); + e.expect("chmod .*\\$ "); + // Start sleep running; pid is in $!, save it. + e.send(exe.getAbsolutePath() + " 1000 &\r"); + e.send("pid=$! ; echo pid=$pid\r"); + e.expect("pid=[0-9]+\r\n\\$ "); + // Try fexe with the executable present. + e.send(Prefix.binFile("fexe").getPath() + " $pid\r"); + e.expect(exe.getName() + "\r\n\\$ "); + // Delete the executable + e.send("rm -f " + exe.getPath() + "\r"); + e.expect("\\$ "); + assertFalse("file exists", exe.stillExists()); + // Try fexe with the executable deleted + e.send(Prefix.binFile("fexe").getPath() + " $pid\r"); + e.expect("The link /proc/[0-9]+/exe points to the deleted file .*" + exe.getName() + "\\r\n\\$ "); + } } diff --git a/frysk-core/frysk/bindir/TestFstack.java b/frysk-core/frysk/bindir/TestFstack.java index aafeb66..952f12d 100644 --- a/frysk-core/frysk/bindir/TestFstack.java +++ b/frysk-core/frysk/bindir/TestFstack.java @@ -83,20 +83,20 @@ public class TestFstack extends TestLib { public void testBackTrace () { TearDownExpect e = fstack("funit-stack-outlined", new String[0]); // Just look for main. - e.expect ("main"); + e.expect ("main.* from funit-stack-outlined"); } public void testBackTraceWithDebugNamesAndParams() { TearDownExpect e = fstack("funit-stack-outlined", new String[] { "-print", "debug-names,params" }); - e.expect("\\#0 .* in third\\(int arg3\\) .*\\/funit-stack-outlined\\.c#"); + e.expect("\\#0 .* in third\\(int arg3\\) at funit-stack-outlined\\.c#[0-9]+ from funit-stack-outlined"); e.expect("\\#1"); } - public void testBackTraceWithFullPath () { + public void testBackTraceWithFullPath() { TearDownExpect e = fstack("funit-stack-outlined", new String[] { - "-rich", "-print", "full-path" + "-rich", "-print", "paths" }); e.expect (getCanonicalRootSrcDir() + ".*" @@ -136,11 +136,13 @@ public class TestFstack extends TestLib { } public void testBackTraceWithRich() { + if (unresolved(6616)) + return; TearDownExpect e = fstack("funit-stack-inlined", new String[] { "-rich" }); - e.expect("\\#0 .* third\\(int arg3.*\\)"); - e.expect("\\#1 .* second\\(int arg2.*\\)"); - e.expect("\\#2 .* first\\(int arg1.*\\)"); + e.expect("\\#0 .* third\\(int arg3\\)"); + e.expect("\\#1 .* second\\(int arg2\\)"); + e.expect("\\#2 .* first\\(int arg1\\)"); e.expect("\\#3 .* main\\(\\)"); } diff --git a/frysk-core/frysk/bindir/ferror.java b/frysk-core/frysk/bindir/ferror.java index ed0cbdb..3592edd 100644 --- a/frysk-core/frysk/bindir/ferror.java +++ b/frysk-core/frysk/bindir/ferror.java @@ -43,7 +43,7 @@ import java.io.PrintWriter; import java.util.regex.Matcher; import java.util.regex.Pattern; -import frysk.debuginfo.PrintStackOptions; +import frysk.debuginfo.PrintDebugInfoStackOptions; import frysk.isa.syscalls.Syscall; import frysk.proc.Action; import frysk.proc.Task; @@ -58,8 +58,8 @@ import gnu.classpath.tools.getopt.OptionGroup; public class ferror { - private static final PrintStackOptions stackPrintOptions - = new PrintStackOptions().setRich(); + private static final PrintDebugInfoStackOptions stackPrintOptions + = new PrintDebugInfoStackOptions(); private static final PrintWriter printWriter = new PrintWriter(System.out); private static Pattern writePattern; private static OptionGroup[] options() { diff --git a/frysk-core/frysk/bindir/fexe.java b/frysk-core/frysk/bindir/fexe.java index 2bcb374..e6a0600 100644 --- a/frysk-core/frysk/bindir/fexe.java +++ b/frysk-core/frysk/bindir/fexe.java @@ -84,11 +84,11 @@ public class fexe if (verbose) { ProcessIdentifier pid = ProcessIdentifierFactory.create(proc.getPid()); - System.out.println( proc.getPid() + System.out.println(proc.getPid() + " " + proc.getExeFile().getFile().getAbsolutePath() + " " - + Exe.get(pid) + + Exe.getName(pid) + " " + sysRootedPath); } else diff --git a/frysk-core/frysk/bindir/fstack.java b/frysk-core/frysk/bindir/fstack.java index a59bd43..89988a9 100644 --- a/frysk-core/frysk/bindir/fstack.java +++ b/frysk-core/frysk/bindir/fstack.java @@ -42,7 +42,7 @@ package frysk.bindir; import java.io.PrintWriter; import java.util.Iterator; import java.util.TreeMap; -import frysk.debuginfo.PrintStackOptions; +import frysk.debuginfo.PrintDebugInfoStackOptions; import frysk.event.Event; import frysk.event.ProcEvent; import frysk.proc.Proc; @@ -55,8 +55,8 @@ import gnu.classpath.tools.getopt.OptionGroup; public final class fstack { private static PrintWriter printWriter = new PrintWriter(System.out); - private static PrintStackOptions stackPrintOptions - = new PrintStackOptions(); + private static PrintDebugInfoStackOptions stackPrintOptions + = new PrintDebugInfoStackOptions(); private static final Log fine = Log.fine(fstack.class); public static void main(String[] args) { diff --git a/frysk-core/frysk/bindir/ftrace.java b/frysk-core/frysk/bindir/ftrace.java index 86cb8fc..34baff7 100644 --- a/frysk-core/frysk/bindir/ftrace.java +++ b/frysk-core/frysk/bindir/ftrace.java @@ -52,7 +52,7 @@ import gnu.classpath.tools.getopt.OptionException; import gnu.classpath.tools.getopt.OptionGroup; import inua.util.PrintWriter; -import frysk.debuginfo.PrintStackOptions; +import frysk.debuginfo.PrintDebugInfoStackOptions; import frysk.expr.FQIdentParser; import frysk.expr.FQIdentifier; import frysk.ftrace.AddrRule; @@ -94,8 +94,8 @@ class ftrace { private final FtraceController controller = new FtraceController(); private boolean allowInterpTracing = false; - private final PrintStackOptions stackPrintOptions - = new PrintStackOptions(); + private final PrintDebugInfoStackOptions stackPrintOptions + = new PrintDebugInfoStackOptions(); private final Ftrace tracer = new Ftrace(stackPrintOptions); private interface RuleMatcher { diff --git a/frysk-core/frysk/bindir/ftrace.xml-in b/frysk-core/frysk/bindir/ftrace.xml-in index 525fef3..7e66e0e 100644 --- a/frysk-core/frysk/bindir/ftrace.xml-in +++ b/frysk-core/frysk/bindir/ftrace.xml-in @@ -246,56 +246,56 @@ <title>SYMBOL RULE SYNTAX</title> <para>To decide which PLT slots or entry points should be traced, - following process takes place. Initial working set is empty. - Rules, if present, are then enumerated from left to right, and set - is modified depending on the rules. Rules are delimited by a - comma. Syntax of each rule is following:</para> + following process takes place. A set of symbols to trace + ("working set") is initially empty. Rules, if present, are then + enumerated from left to right, and set is modified depending on + the rules. Rules are delimited by a comma. Syntax of each rule + is following:</para> <para>[-]<replaceable>pattern</replaceable>[/<replaceable>options</replaceable>]</para> - <para>Optional "-" at the beginning of the rule means - removal from the working set. When the sign is omitted, the - default action is to add matching symbols to the working - set.</para> + <para>Without the optional "-" all symbols that match + the <replaceable>pattern</replaceable> are added to the working + set. With "-", matching symbols are removed.</para> - <para>If optional "/" is present at the end of the rule, + <para>If "/" is present at the end of the rule, following letters are interpreted as rule flags. Currently only one flag is available, "s". When present, it means ftrace should show a stack trace when it hits a symbol that matches this rule.</para> - <para>When a "-#" rule is considered that has - "s" flag, then the call should still be traced, but - stack trace shouldn't be generated.</para> + <para>When a "-" rule has an "/s" flag, the + call should still be traced, but stack trace shouldn't be + generated.</para> <para><replaceable>pattern</replaceable> defines which symbols or PLT slots from which libraries should be added or removed from - working set. Syntax of pattern is the following:</para> - - <para><optional>#<replaceable>soname</replaceable>#</optional> - <optional><replaceable>filename.c</replaceable>#</optional> - <optional>(<replaceable>proc</replaceable>|<replaceable>line</replaceable>)#</optional> - <optional>plt:</optional>symbol<optional>@<replaceable>version</replaceable></optional></para> + working set. Syntax of pattern is as follows:</para> + <para><optional>#<replaceable>soname</replaceable>#</optional><!-- + --><optional><replaceable>filename.c</replaceable>#</optional><!-- + --><optional>(<replaceable>proc</replaceable>|<replaceable>line</replaceable>)#</optional><!-- + --><optional>plt:</optional>symbol<optional>@<replaceable>version</replaceable></optional></para> <para><replaceable>soname</replaceable> component is matched - against a soname of a library in which we wish to track the call. - If the library has no associated soname or it is a main - executable, the match is done against the file name (without a - path). Two special sonames are distinguished: "MAIN", which - always matches main executable; and "INTERP", which always matches - ELF interpreter (dynamic linker) of the main executable. If the - component is missing, then the rule is applicable in all libraries - and in main executable.</para> + against a soname of a library in which we wish to trace the call. + If the library has no associated soname (such as is usual in case + of main executable), the match is done against the file name + (without a path). Two special sonames are distinguished: "MAIN", + which always matches main executable; and "INTERP", which always + matches ELF interpreter (dynamic linker) of the main executable. + If the component is missing, then the rule is applicable in all + libraries and in main executable.</para> <para><replaceable>filename.c</replaceable> component is matched - against the name of a file where the symbol is defined.</para> + against the name of a file where the symbol is defined. NOTE: + This is currently not implemented.</para> <para><replaceable>proc</replaceable> component is matched against the name of block surrounding the definition we wish to trace. If the block doesn't have a name, you can instead refer to it with the <replaceable>line</replaceable> number that the block - surrounds.</para> + surrounds. NOTE: This is currently not implemented.</para> <para><replaceable>symbol</replaceable> component is matched against the name of symbol under consideration. If @@ -306,11 +306,10 @@ against version associated with symbol. If the symbol has no associated version, it is considered to be an empty string. (It is possible to request symbol without a version with the pattern - "foo@".)</para> + "foo@".) NOTE: This is currently not implemented.</para> - <para>NOTE: A lot of this is not yet implemented. Currently all - the components are required to be plain strings, although in - future some form of globbing will be introduced.</para> + <para>All components are presented in glob syntax. See glob(7) + manual page for more details. See below for examples.</para> </refsect1> <refsect1> @@ -364,8 +363,8 @@ <para><replaceable>soname</replaceable> component is the same as in symbol tracing, i.e. it's matched against a soname of a library in which we wish to trace the address. Same rules apply regarding - INTERP and MAIN meta-sonames. Refer there for detailed - description.</para> + INTERP and MAIN meta-sonames. Refer to the chapter "SYMBOL RULE + SYNTAX" for detailed description.</para> <para>Even though <replaceable>soname</replaceable> is optional, at least one soname has to be specified at the beginning of the @@ -399,17 +398,16 @@ <cmdsynopsis><command>ftrace -sys='*stat*,3' ls</command></cmdsynopsis> <para>Various ways to tell ftrace that you want to stack trace on SIGUSR1:</para> <cmdsynopsis><command>ftrace -sig=USR1/s,usr1/s,SIGUSR1/s,sigusr1/s,10/s ~/sig</command></cmdsynopsis> - <para>Trace all library calls (NOTE globbing doesn't work yet):</para> + <para>Trace all library calls:</para> <cmdsynopsis><command>ftrace -sym=plt:* ls</command></cmdsynopsis> <para>Trace all library calls to functions that contain - substring "write" in their names (NOTE globbing doesn't work yet):</para> + substring "write" in their names:</para> <cmdsynopsis><command>ftrace -sym=plt:*write* ls</command></cmdsynopsis> <para>Trace memory functions done from libraries, i.e. not from - main executable (NOTE globbing doesn't work yet):</para> + main executable:</para> <cmdsynopsis><command>ftrace -sym='plt:*alloc,plt:free,-#MAIN#plt:*' ls</command></cmdsynopsis> <para>Stack trace on everything, except for memory allocation - functions (which should still be traced) (NOTE globbing doesn't - work yet):</para> + functions (which should still be traced):</para> <cmdsynopsis><command>ftrace -sym='plt:*/s,-plt:*alloc/s,-plt:free/s' ls</command></cmdsynopsis> </informalexample> diff --git a/frysk-core/frysk/debuginfo/ChangeLog b/frysk-core/frysk/debuginfo/ChangeLog index f74532f..cfcade3 100644 --- a/frysk-core/frysk/debuginfo/ChangeLog +++ b/frysk-core/frysk/debuginfo/ChangeLog @@ -1,3 +1,41 @@ +2008-03-20 Mark Wielaard <mark@klomp.org> + + * TestDebugInfoStackTrace.java (pushPopAssertions): Make sure + line is initialized. + +2008-06-15 Andrew Cagney <cagney@redhat.com> + + * gen-type-expect-tests.py (open_file): Use assert, not if/println + to detect and report bad values. + +2008-06-12 Andrew Cagney <cagney@redhat.com> + + * ObjectDeclarationNotFoundException.java: Extend + UserException. + * PieceLocation.java: Throw UserException. + +2008-06-11 Teresa Thomas <tthomas@redhat.com> + + * PieceLocation.java (length): Make public. + +2008-06-10 Andrew Cagney <cagney@redhat.com> + + * PrintDebugInfoStackOptions.java (printSourcePaths): New. + (setPrintPaths(boolean)): New. + * DebugInfoFrame.java: Update. + * TestFrameDebugInfo.java: Use setPrintPaths. + + * DebugInfoFrame.java (toPrint): Print the library using + Frame.printLibraryName. + + * DebugInfoFrame.java (toPrint(PrintWriter,boolean,boolean)): Delete. + (toPrint(PrintWriter,DebugInfoStackOptions)): New. + * PrintParameterOptions.java: New. + * VirtualDebugInfoFrame.java: Ditto. + * PrintDebugInfoStackOptions.java: Rename PrintStackOptions, + extend frysk.stack.PrintStackOptions. + * TestFrameDebugInfo.java: Update. + 2008-06-06 Andrew Cagney <cagney@redhat.com> * DebugInfo.java: Let DwflDie adjust for bias. diff --git a/frysk-core/frysk/debuginfo/DebugInfoFrame.java b/frysk-core/frysk/debuginfo/DebugInfoFrame.java index 02ecdca..586ed65 100644 --- a/frysk-core/frysk/debuginfo/DebugInfoFrame.java +++ b/frysk-core/frysk/debuginfo/DebugInfoFrame.java @@ -39,10 +39,10 @@ package frysk.debuginfo; +import frysk.util.ArchFormatter; import java.io.PrintWriter; import java.util.Iterator; import java.util.LinkedList; - import lib.dwfl.DwarfDie; import lib.dwfl.Dwfl; import lib.dwfl.DwflDie; @@ -186,39 +186,33 @@ public class DebugInfoFrame extends FrameDecorator { } private LineXXX lineXXX; - public void toPrint(PrintWriter writer, boolean printParameters, - boolean fullpath){ + public void toPrint(PrintWriter writer, + PrintDebugInfoStackOptions options) { Function subprogram = this.getSubprogram(); - if (subprogram != null) { - writer.print("0x"); - String addr = Long.toHexString(this.getAddress()); - int padding = 2 * this.getTask().getISA().wordSize() - addr.length(); - - for (int i = 0; i < padding; ++i) - writer.print('0'); - - writer.print(addr); - writer.print(" in " + subprogram.getName() + "("); - if (printParameters) { - subprogram.printParameters(writer, this); + writer.write(ArchFormatter.toHexString(getTask(), getAddress())); + writer.print(" in "); + writer.print(subprogram.getName()); + writer.print("("); + if (options.printParameters()) { + subprogram.printParameters(writer, this, options.printValues()); } - writer.print(") "); - - if (fullpath) { - SourceLocation line = this.getLine(); + writer.print(") at "); + SourceLocation line = this.getLine(); + if (options.printSourcePaths()) { writer.print(line.getFile().getPath()); - writer.print("#"); - writer.print(line.getLine()); } else { - SourceLocation line = this.getLine(); - writer.print(".../"+line.getFile().getName()); + writer.print(line.getFile().getName()); + } + writer.print("#"); + writer.print(line.getLine()); + if (line.getColumn() > 0) { writer.print("#"); - writer.print(line.getLine()); + writer.print(line.getColumn()); } - + printLibraryName(writer, options); } else { - super.toPrint(writer, true, fullpath); + super.toPrint(writer, options); } } diff --git a/frysk-core/frysk/debuginfo/DebugInfoStackFactory.java b/frysk-core/frysk/debuginfo/DebugInfoStackFactory.java index 7023da6..4adec65 100644 --- a/frysk-core/frysk/debuginfo/DebugInfoStackFactory.java +++ b/frysk-core/frysk/debuginfo/DebugInfoStackFactory.java @@ -51,9 +51,6 @@ import frysk.stack.StackFactory; */ public class DebugInfoStackFactory { - public static final PrintStackOptions DEFAULT - = new PrintStackOptions().setRich(); - /** * Create an ABI stack backtrace, make the simpler debug-info * methods. @@ -100,29 +97,31 @@ public class DebugInfoStackFactory { return innermostFrame; } - public static final void printTaskStackTrace (PrintWriter printWriter, Task task, PrintStackOptions options) - { - if (task != null){ - printWriter.println("Task #" + task.getTid()); - DebugInfoFrame frame = createDebugInfoStackTrace(task); - printStackTrace(printWriter, frame, options); - } - printWriter.flush(); + public static final void printTaskStackTrace(PrintWriter printWriter, + Task task, + PrintDebugInfoStackOptions options) { + if (task != null) { + printWriter.println("Task #" + task.getTid()); + DebugInfoFrame frame = createDebugInfoStackTrace(task); + printStackTrace(printWriter, frame, options); + } + printWriter.flush(); } - public static final void printVirtualTaskStackTrace (PrintWriter printWriter, Task task, PrintStackOptions options) - { - if (task != null){ - printWriter.println("Task #" + task.getTid()); - DebugInfoFrame frame = createVirtualStackTrace(task); - printStackTrace(printWriter,frame, options); - } - printWriter.flush(); + public static final void printVirtualTaskStackTrace(PrintWriter printWriter, + Task task, + PrintDebugInfoStackOptions options) { + if (task != null) { + printWriter.println("Task #" + task.getTid()); + DebugInfoFrame frame = createVirtualStackTrace(task); + printStackTrace(printWriter,frame, options); + } + printWriter.flush(); } public static void printStackTrace(PrintWriter writer, DebugInfoFrame topFrame, - PrintStackOptions options) { + PrintDebugInfoStackOptions options) { int count = 0; for (DebugInfoFrame frame = topFrame; frame != null; @@ -142,8 +141,7 @@ public class DebugInfoStackFactory { frame.printLevel(writer); writer.print(" "); - frame.toPrint(writer, options.printParams(), - options.printFullPaths()); + frame.toPrint(writer, options); writer.println(); if (options.printLocals()) { frame.printScopes(writer); diff --git a/frysk-core/frysk/debuginfo/ObjectDeclarationNotFoundException.java b/frysk-core/frysk/debuginfo/ObjectDeclarationNotFoundException.java index 6aee2a0..0f0b0c2 100644 --- a/frysk-core/frysk/debuginfo/ObjectDeclarationNotFoundException.java +++ b/frysk-core/frysk/debuginfo/ObjectDeclarationNotFoundException.java @@ -1,6 +1,6 @@ // This file is part of the program FRYSK. // -// Copyright 2007, Red Hat Inc. +// Copyright 2007, 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 @@ -39,16 +39,11 @@ package frysk.debuginfo; -public class ObjectDeclarationNotFoundException extends RuntimeException { +import frysk.UserException; +public class ObjectDeclarationNotFoundException extends UserException { public ObjectDeclarationNotFoundException(String name) { super("Object "+ name + " was not found"); } - - /** - * - */ private static final long serialVersionUID = 1L; - - } diff --git a/frysk-core/frysk/debuginfo/PieceLocation.java b/frysk-core/frysk/debuginfo/PieceLocation.java index b129e77..d636a6a 100644 --- a/frysk-core/frysk/debuginfo/PieceLocation.java +++ b/frysk-core/frysk/debuginfo/PieceLocation.java @@ -1,46 +1,46 @@ -//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. +// 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.debuginfo; import frysk.value.Location; - +import frysk.UserException; import java.io.PrintWriter; import java.util.Iterator; import java.util.List; @@ -86,7 +86,7 @@ extends Location { if (pieces.size()==1 && (pieces.get(0) instanceof MemoryPiece)) return ((MemoryPiece)pieces.get(0)).getMemory(); - throw new RuntimeException("Location not in contiguous memory."); + throw new UserException("Location not in contiguous memory."); } /** @@ -125,7 +125,7 @@ extends Location else indexCount += len; } - throw new RuntimeException("Out of range."); + throw new UserException("Out of range."); } /** @@ -155,7 +155,7 @@ extends Location else indexCount += len; } - throw new RuntimeException("Out of range."); + throw new UserException("Out of range."); } /** @@ -181,7 +181,7 @@ extends Location /** * Returns the number of bytes in location. */ - protected long length() + public long length() { long length = 0; for (Iterator it=pieces.iterator(); it.hasNext(); ) diff --git a/frysk-core/frysk/debuginfo/PrintDebugInfoStackOptions.java b/frysk-core/frysk/debuginfo/PrintDebugInfoStackOptions.java new file mode 100644 index 0000000..486eae3 --- /dev/null +++ b/frysk-core/frysk/debuginfo/PrintDebugInfoStackOptions.java @@ -0,0 +1,167 @@ +// This file is part of the program FRYSK. +// +// Copyright 2007, 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.debuginfo; + +import frysk.stack.PrintStackOptions; + +public class PrintDebugInfoStackOptions extends PrintStackOptions { + + public PrintDebugInfoStackOptions() { + // Note, the super calls clear. + } + + private boolean printParameters; + private boolean printLocals; + private boolean printInlineFunctions; + private boolean printDebugNames; + private boolean printValues; + private boolean printSourcePaths; + + /** + * Clear all options. + */ + public void clear() { + super.clear(); + printParameters = false; + printLocals = false; + printInlineFunctions = false; + printDebugNames = false; + printValues = false; + } + + /** + * Set things up for a light-weight, or low-cost, back-trace by + * limiting things to just the elf information. + */ + public void setLite() { + setAbi(); + setPrintDebugNames(true); + } + + /** + * Set things up for a rich, or detailed, back-trace by including + * inline frames and parameter information. + */ + public void setRich() { + setAbi(); + setPrintParameters(true); + setPrintInlineFunctions(true); + setPrintDebugNames(true); + } + + /** + * Print the full path to any source file. + */ + public void setPrintPaths(boolean printPaths) { + super.setPrintPaths(printPaths); + setPrintSourcePaths(printPaths); + } + + /** + * Print the parameter list (see also printValues). + */ + public boolean printParameters() { + return printParameters; + } + public void setPrintParameters(boolean printParameters) { + this.printParameters = printParameters; + } + + /** + * Print paramter and variable values (rather than just their + * names). + */ + public boolean printValues() { + return printValues; + } + public void setPrintValues(boolean printValues) { + this.printValues = printValues; + } + + /** + * Print the function's local variables. + */ + public boolean printLocals() { + return printLocals; + } + public void setPrintLocals(boolean printLocals) { + this.printLocals = printLocals; + } + + /** + * Print inline function instances. + */ + public boolean printInlineFunctions() { + return printInlineFunctions; + } + public void setPrintInlineFunctions(boolean printInlineFunctions) { + this.printInlineFunctions = printInlineFunctions; + } + + /** + * Print function and variable names using debug, rather than ABI, + * information. + */ + public boolean printDebugNames() { + return printDebugNames; + } + public void setPrintDebugNames(boolean printDebugNames) { + this.printDebugNames = printDebugNames; + } + + /** + * Print the full path to source files (instead of just the file + * name). + */ + public boolean printSourcePaths() { + return printSourcePaths; + } + public void setPrintSourcePaths(boolean printSourcePaths) { + this.printSourcePaths = printSourcePaths; + } + + public boolean abiOnly() { + return ! (printLocals + || printInlineFunctions + || printParameters + || printValues + || printDebugNames); + } +} diff --git a/frysk-core/frysk/debuginfo/PrintStackOptions.java b/frysk-core/frysk/debuginfo/PrintStackOptions.java deleted file mode 100644 index acae8e0..0000000 --- a/frysk-core/frysk/debuginfo/PrintStackOptions.java +++ /dev/null @@ -1,141 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2007, 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.debuginfo; - -public class PrintStackOptions { - - private int numberOfFrames = 10; - - private boolean printFullPaths = false; - - private boolean printParams = false; - private boolean printLocals = false; - private boolean printLibraries = false; - private boolean printInlineFunctions = false; - private boolean printDebugNames = false; - - public PrintStackOptions() { - } - - /** - * Set things up for a light-weight, or low-cost, back-trace by - * limiting things to just the elf information. - */ - public PrintStackOptions setLite() { - printParams = false; - printLocals = false; - printLibraries = true; - printInlineFunctions = false; - printDebugNames = true; - return this; - } - - /** - * Set things up for a rich, or detailed, back-trace by including - * inline frames and parameter information. - */ - public PrintStackOptions setRich() { - printParams = true; - printLocals = true; - printLibraries = true; - printInlineFunctions = true; - printDebugNames = true; - return this; - } - - /** - * Specify the number of frames to include in the back-trace, 0 to - * include all frames. - */ - public void setNumberOfFrames(int numberOfFrames) { - this.numberOfFrames = numberOfFrames; - } - public int numberOfFrames() { - return numberOfFrames; - } - - public void setPrintParams(boolean printParams) { - this.printParams = printParams; - } - public boolean printParams() { - return printParams; - } - - public void setPrintLocals(boolean printLocals) { - this.printLocals = printLocals; - } - public boolean printLocals() { - return printLocals; - } - - public void setPrintFullPaths(boolean printFullPaths) { - this.printFullPaths = printFullPaths; - } - public boolean printFullPaths() { - return printFullPaths; - } - - public void setPrintLibraries(boolean printLibraries) { - this.printLibraries = printLibraries; - } - public boolean printLibraries() { - return printLibraries; - } - - public void setPrintInlineFunctions(boolean printInlineFunctions) { - this.printInlineFunctions = printInlineFunctions; - } - public boolean printInlineFunctions() { - return printInlineFunctions; - } - - public void setPrintDebugNames(boolean printDebugNames) { - this.printDebugNames = printDebugNames; - } - public boolean printDebugNames() { - return printDebugNames; - } - - public boolean elfOnly() { - return ! (printLocals || printInlineFunctions || printParams - || printDebugNames); - } - -} diff --git a/frysk-core/frysk/debuginfo/TestDebugInfoStackTrace.java b/frysk-core/frysk/debuginfo/TestDebugInfoStackTrace.java index 35e2737..9f1d953 100644 --- a/frysk-core/frysk/debuginfo/TestDebugInfoStackTrace.java +++ b/frysk-core/frysk/debuginfo/TestDebugInfoStackTrace.java @@ -500,7 +500,7 @@ public class TestDebugInfoStackTrace public void pushPopAssertions () { DebugInfoFrame sFrame = DebugInfoStackFactory.createDebugInfoStackTrace(myTask); - SourceLocation line = null; + SourceLocation line = sFrame.getLine(); if (this.testState == PUSH || this.testState == POP) { diff --git a/frysk-core/frysk/debuginfo/TestFrameDebugInfo.java b/frysk-core/frysk/debuginfo/TestFrameDebugInfo.java index 439218f..74eead7 100644 --- a/frysk-core/frysk/debuginfo/TestFrameDebugInfo.java +++ b/frysk-core/frysk/debuginfo/TestFrameDebugInfo.java @@ -45,7 +45,6 @@ import java.util.Iterator; import java.util.LinkedList; import javax.naming.NameNotFoundException; - import lib.dwfl.DwTag; import lib.dwfl.DwarfDie; import lib.dwfl.Dwfl; @@ -85,11 +84,11 @@ public class TestFrameDebugInfo extends TestLib { StringWriter stringWriter = new StringWriter(); DebugInfoFrame frame = DebugInfoStackFactory.createDebugInfoStackTrace(task); - PrintStackOptions options = new PrintStackOptions(); + PrintDebugInfoStackOptions options = new PrintDebugInfoStackOptions(); options.setNumberOfFrames(20); - options.setPrintParams(true); + options.setPrintParameters(true); options.setPrintLocals(true); - options.setPrintFullPaths(true); + options.setPrintPaths(true); DebugInfoStackFactory.printStackTrace(new PrintWriter(stringWriter),frame, options); String string = stringWriter.getBuffer().toString(); @@ -307,11 +306,11 @@ public class TestFrameDebugInfo extends TestLib { Task task = (new DaemonBlockedAtSignal("funit-stack-inlined" + ext)).getMainTask(); StringWriter stringWriter = new StringWriter(); - PrintStackOptions options = new PrintStackOptions(); + PrintDebugInfoStackOptions options = new PrintDebugInfoStackOptions(); options.setNumberOfFrames(0); - options.setPrintParams(true); + options.setPrintParameters(true); options.setPrintLocals(true); - options.setPrintFullPaths(true); + options.setPrintPaths(true); DebugInfoStackFactory.printVirtualTaskStackTrace(new PrintWriter(stringWriter), task, options); assertTrue("contains inline", stringWriter.getBuffer().toString().contains("inline")); @@ -326,11 +325,11 @@ public class TestFrameDebugInfo extends TestLib { Task task = (new DaemonBlockedAtSignal("funit-stack-inlined")).getMainTask(); - PrintStackOptions options = new PrintStackOptions(); + PrintDebugInfoStackOptions options = new PrintDebugInfoStackOptions(); options.setNumberOfFrames(0); - options.setPrintParams(true); + options.setPrintParameters(true); options.setPrintLocals(true); - options.setPrintFullPaths(true); + options.setPrintPaths(true); DebugInfoFrame frame = DebugInfoStackFactory.createVirtualStackTrace(task); frame = frame.getOuterDebugInfoFrame(); diff --git a/frysk-core/frysk/debuginfo/TestPieceLocation.java b/frysk-core/frysk/debuginfo/TestPieceLocation.java index 1ea10c8..964d878 100644 --- a/frysk-core/frysk/debuginfo/TestPieceLocation.java +++ b/frysk-core/frysk/debuginfo/TestPieceLocation.java @@ -153,7 +153,7 @@ extends TestLib Location simple = PieceLocation.createSimpleLoc (3, 5, new ArrayByteBuffer(new byte[] { 127,127,127, 5, 6, 7, 8, 9, 127, 127 })); assertEquals ("Address", 3, simple.getAddress()); - assertEquals ("Length", 5, ((PieceLocation)simple).length()); + assertEquals ("Length", 5, simple.length()); } private Task getStoppedTask () diff --git a/frysk-core/frysk/debuginfo/VirtualDebugInfoFrame.java b/frysk-core/frysk/debuginfo/VirtualDebugInfoFrame.java index ae3ed76..7fb6039 100644 --- a/frysk-core/frysk/debuginfo/VirtualDebugInfoFrame.java +++ b/frysk-core/frysk/debuginfo/VirtualDebugInfoFrame.java @@ -52,9 +52,9 @@ public class VirtualDebugInfoFrame extends DebugInfoFrame { super(inner, decorated); } - public void toPrint(PrintWriter writer, boolean printParameters, - boolean fullpath) { - super.toPrint(writer, printParameters, fullpath); + public void toPrint(PrintWriter writer, + PrintDebugInfoStackOptions options) { + super.toPrint(writer, options); writer.print(" [inline]"); } diff --git a/frysk-core/frysk/debuginfo/gen-type-expect-tests.py b/frysk-core/frysk/debuginfo/gen-type-expect-tests.py index c8513c4..0daf18a 100644 --- a/frysk-core/frysk/debuginfo/gen-type-expect-tests.py +++ b/frysk-core/frysk/debuginfo/gen-type-expect-tests.py @@ -94,15 +94,10 @@ public class %s extends TestLib { print(''' void checkType(String symbol, String expected) { Type varType; - DwarfDie varDie = biasDie.getScopeVar(allDies, symbol); - if (varDie == null) - System.out.println("Error: Cannot find " + symbol); - assertNotNull(varDie); + assertNotNull("die for variable " + symbol, varDie); varType = typeFactory.getType(varDie.getType()); assertNotNull(varType); - // System.out.println("Expect: " + symbol + "\\n'" + - // expected + "'\\nGot:\\n'" + varType.toPrint()); assertEquals(testName + symbol, expected, varType.toPrint()); } @@ -115,19 +110,13 @@ public class %s extends TestLib { || expected.length() == 0) return; DwarfDie varDie = biasDie.getScopeVar(allDies, symbol); - if (varDie == null) - System.out.println("Error: Cannot find " + symbol); - assertNotNull(varDie); + assertNotNull("die for variable " + symbol, varDie); DebugInfo debugInfo = new DebugInfo(frame); Value value = debugInfo.print(symbol, frame); value.toPrint(pw, task.getMemory(), Format.NATURAL, 0); pw.flush(); String valueString = baos.toString(); - // System.out.println("Expect: " + symbol + - // "\\n'" + expected + "'\\nGot:\\n'" + - // valueString + "'" + " " + value.getType()); assertEquals(testName + symbol, expected, valueString); - baos.reset(); } } ''') diff --git a/frysk-core/frysk/dwfl/ChangeLog b/frysk-core/frysk/dwfl/ChangeLog index 542bf50..6ea8bf2 100644 --- a/frysk-core/frysk/dwfl/ChangeLog +++ b/frysk-core/frysk/dwfl/ChangeLog @@ -1,3 +1,9 @@ +2008-06-19 Andrew Cagney <cagney@redhat.com> + + * DwflCache.java (getDwfl()): Pass the task's memory to the Dwfl + and down to the native code, don't pass the vdso address. + * DwflFactory.java (updateDwfl): Don't set the module's memory. + 2008-06-03 Andrew Cagney <cagney@redhat.com> * DwflFactory.java (updateDwfl): Simplify by using Dwfl.mapBegin, diff --git a/frysk-core/frysk/dwfl/DwflCache.java b/frysk-core/frysk/dwfl/DwflCache.java index 15ffde3..4825f94 100644 --- a/frysk-core/frysk/dwfl/DwflCache.java +++ b/frysk-core/frysk/dwfl/DwflCache.java @@ -132,7 +132,7 @@ public class DwflCache { fine.log("creating new dwfl for task", task); File sysrootFile = (File)SysRootCache.getSysRoot(task); File relativeSysroot = getRelativeSysRoot(task.getProc().getExeFile().getSysRootedPath(), sysrootFile); - Dwfl dwfl = new Dwfl(relativeSysroot.getPath()); + Dwfl dwfl = new Dwfl(relativeSysroot.getPath(), task.getMemory()); DwflFactory.updateDwfl(dwfl, task); Mod mod = new Mod(dwfl, task.getMod()); modMap.put(task, mod); diff --git a/frysk-core/frysk/dwfl/DwflFactory.java b/frysk-core/frysk/dwfl/DwflFactory.java index 0f17713..eabb0c6 100644 --- a/frysk-core/frysk/dwfl/DwflFactory.java +++ b/frysk-core/frysk/dwfl/DwflFactory.java @@ -45,7 +45,6 @@ import frysk.proc.Proc; import frysk.proc.Task; import frysk.rsl.Log; import lib.dwfl.Dwfl; -import lib.dwfl.DwflModule; /** * Factory for creating Dwfl objects for Procs and Tasks. @@ -96,23 +95,15 @@ public class DwflFactory { static Dwfl updateDwfl(Dwfl dwfl, Task task) { Proc proc = task.getProc(); MemoryMap[] maps = proc.getMaps(); - long vdso = VDSOAddressLow(proc); - dwfl.mapBegin(vdso); + dwfl.mapBegin(); for (int i = 0; i < maps.length; i++) { MemoryMap map = maps[i]; dwfl.mapModule(map.name, map.addressLow, map.addressHigh, map.devMajor, map.devMinor, map.inode); } dwfl.mapEnd(); - DwflModule module = dwfl.getModule(vdso); fine.log("updateDwfl main task", proc.getMainTask(), - "memory", proc.getMainTask().getMemory(), - "dwfl module", module); - // XXX: Should this method instead have this block of memory - // pre-fetched and passed in? - if (module != null) { - module.setUserData(task.getMemory()); - } + "memory", proc.getMainTask().getMemory()); return dwfl; } } diff --git a/frysk-core/frysk/event/ChangeLog b/frysk-core/frysk/event/ChangeLog index b457707..13ecd79 100644 --- a/frysk-core/frysk/event/ChangeLog +++ b/frysk-core/frysk/event/ChangeLog @@ -1,3 +1,8 @@ +2008-06-20 Andrew Cagney <cagney@redhat.com> + + * PollEventLoop.java: Update; Poll et.al., moved to + frysk.sys.poll. + 2008-05-23 Teresa Thomas <tthomas@redhat.com> * ActionPointEvent.java: New file. diff --git a/frysk-core/frysk/event/PollEventLoop.java b/frysk-core/frysk/event/PollEventLoop.java index 8b841f9..31a09be 100644 --- a/frysk-core/frysk/event/PollEventLoop.java +++ b/frysk-core/frysk/event/PollEventLoop.java @@ -39,8 +39,9 @@ package frysk.event; -import frysk.sys.Poll; -import frysk.sys.PollBuilder; +import frysk.sys.FileDescriptor; +import frysk.sys.poll.Poll; +import frysk.sys.poll.PollBuilder; import frysk.sys.Signal; import frysk.sys.Wait; import frysk.sys.WaitBuilder; @@ -101,10 +102,8 @@ class PollEventLoop extends EventLoop { add (new PollWaitOnSigChild (waitBuilder)); } - private PollBuilder pollObserver = new PollBuilder () - { - public String toString () - { + private PollBuilder pollObserver = new PollBuilder() { + public String toString() { return ("{" + super.toString () + "}"); } public void signal(Signal sig) { @@ -112,7 +111,7 @@ class PollEventLoop extends EventLoop { processSignal (sig); } // Not yet using file descriptors. - public void pollIn (int fd) { + public void pollIn(FileDescriptor fd) { throw new RuntimeException ("should not happen"); } }; diff --git a/frysk-core/frysk/expr/CExpr.g b/frysk-core/frysk/expr/CExpr.g index 3ea45b6..2654a89 100644 --- a/frysk-core/frysk/expr/CExpr.g +++ b/frysk-core/frysk/expr/CExpr.g @@ -416,7 +416,7 @@ tokens { final FQIdentParser fqIdParser - = new FQIdentParser(this, true, false, true); + = new FQIdentParser(this, true, false, true, false); } AMPERSAND : '&' ; @@ -441,15 +441,20 @@ LCURLY : '{' ; LESSTHAN : "<" ; LESSTHANOREQUALTO : "<=" ; LPAREN : '(' ; -LSQUARE : '[' (('0'..'9') { - try { - Token tok = fqIdParser.parse($getText); - if (tok != null) { - $setToken(tok); - $setType(IDENT); - } - } catch (RecognitionException exc) { } - } )? ; +LSQUARE : '[' { + // We can't use ('0'..'9')? here, because even + // if there is 0..9, it still doesn't have to + // parse correctly as [a.b#c] syntax. But + // antlr would already match the digit. + if (((LA(1) >= '0' && LA(1) <= '9'))) + try { + Token tok = fqIdParser.parse($getText); + if (tok != null) { + $setToken(tok); + $setType(IDENT); + } + } catch (RecognitionException exc) { } + } ; MINUS : '-' ; MINUSEQUAL : "-=" ; MINUSMINUS : "--" ; diff --git a/frysk-core/frysk/expr/ChangeLog b/frysk-core/frysk/expr/ChangeLog index 9b25bfc..9816cdf 100644 --- a/frysk-core/frysk/expr/ChangeLog +++ b/frysk-core/frysk/expr/ChangeLog @@ -1,3 +1,47 @@ +2008-06-20 Petr Machata <pmachata@redhat.com> + + * FQIdentParser.java (ctor): Take extra argument + allowPeriodInSymbol. + (parseFtraceIdentifier): Pass true for the new argument. + (parseFQIdentifier): Likewise. + (symbolPattern, globPattern): Unstatic. + (symbolRe): Kill. + * CExpr.g (fqIdParser): Pass false for the new argument. + +2008-06-13 Petr Machata <pmachata@redhat.com> + + * FQIdentParser.java (containsGlobChar): Rename to + isWildcardPattern. Only require *, ? or [ to consider + a string to be a wildcard pattern. + * FQIdentifier.java: Adapt to above. + +2008-06-12 Andrew Cagney <cagney@redhat.com> + + * ScratchSymTab.java: Throw UserException. + +2008-06-12 Petr Machata <pmachata@redhat.com> + + * TestbedSymTab.java: Add "arr", an array variable + * TestArithmetics.java (testArrayAccess, testArraySlice): New tests. + +2008-06-12 Petr Machata <pmachata@redhat.com> + + * CExpr.g (LSQUARE): Don't use "('0'..'9')?" construct, instead + test the same in inline java code. + +2008-06-12 Petr Machata <pmachata@redhat.com> + + * FQIdentParser.java (containsGlobChar): New method. + * FQIdentPattern.java, FQIdentPatternAll.java: New files. + * FQIdentPatternExact.java, FQIdentPatternGlob.java: New files. + * FQIdentToken.java (globs): New field. + * FQIdentifier.java (soname, file, proc, symbol, version): Changed + type from String to FQIdentPattern. + +2008-06-10 Petr Machata <pmachata@redhat.com> + + * FQIdentParser.java: Implement glob parsing. + 2008-06-09 Petr Machata <pmachata@redhat.com> * FQIdentParser.java: Introduce parsing options. diff --git a/frysk-core/frysk/expr/FQIdentParser.java b/frysk-core/frysk/expr/FQIdentParser.java index 63035b9..2aa9ce2 100644 --- a/frysk-core/frysk/expr/FQIdentParser.java +++ b/frysk-core/frysk/expr/FQIdentParser.java @@ -52,6 +52,15 @@ import antlr.TokenStreamException; import antlr.InputBuffer; import antlr.CharBuffer; +/** + * Funky HPD #-syntax doesn't map very well to LL-k type parser (for + * constant 'k'). When written directly in antlr, we obviously get + * lots of lexical ambiguities. We work around that by doing + * arbitrary manual look-ahead and just parsing the tokens ourselves. + * FQIdentParser is where that parsing takes place. Besides + * supporting antlr lexical analyzer, the class can be used standalone + * to parse arbitrary strings. + */ public class FQIdentParser { private int i; @@ -61,6 +70,9 @@ public class FQIdentParser { private final boolean allowGlobs; private final boolean expectMoreTokens; + private final Pattern symbolPattern; + private final Pattern globPattern; + /** * @param allowDynamic Whether the [pid.tid#frame] portion of the * FQ syntax makes sense in given context. For example it @@ -80,12 +92,28 @@ public class FQIdentParser { FQIdentParser(CharScanner scanner, boolean allowDynamic, boolean allowGlobs, - boolean expectMoreTokens) { + boolean expectMoreTokens, + boolean allowPeriodInSymbol) { this.scanner = scanner; this.allowDynamic = allowDynamic; this.allowGlobs = allowGlobs; this.expectMoreTokens = expectMoreTokens; + + // This pattern deliberately doesn't check for initial letter. + // Relevant code checks this explicitly. This way, if user makes + // a mistake and writes e.g. something#123+b, we recognize "123" + // as a typo, while leaving out the part after a "+", which is + // certainly irrelevant. + String symbolRe = "[a-zA-Z0-9_$" + (allowPeriodInSymbol + ? "." : "") + "]+"; + this.symbolPattern = Pattern.compile(symbolRe); + this.globPattern + = Pattern.compile("(\\[(\\^?\\][^\\]]*" + // handles []abc] and [^]abc] + "|\\^[^\\]]+" + // handles [^abc] + "|[^^\\]][^\\]]*" + // handles [abc], and [ab^c] (cases where ^ isn't an operator) + "|\\^?\\[:[^:]+:\\]"+ // handles [[:abc:]] and [^[:abc:]] + ")\\]|" + symbolRe + "|\\*)+"); } private char fqLA(int i) throws CharStreamException { @@ -137,6 +165,20 @@ public class FQIdentParser { return matched.toString(); } + public static boolean isGlobChar(char c) { + return c == '*' || c == '?' || c == '[' + || c == ']' || c == '^' || c == ':' + || c == '-'; + } + + public static boolean isWildcardPattern(String str) { + // man 7 glob: """A string is a wildcard pattern if it + // contains one of the characters "?", "*" or "[".""" + return str.indexOf('*') != -1 + || str.indexOf('?') != -1 + || str.indexOf('[') != -1; + } + /** * @param initial Portion of the character stream that is part of * the identifier, but was already consumed by lexer. @@ -144,22 +186,9 @@ public class FQIdentParser { public FQIdentToken parse(String initial) throws RecognitionException, CharStreamException, TokenStreamException { - if (allowGlobs) - // XXX to fool java into thinking that we use allowGlobs - // when we actually don't. - System.out.print(""); - fqinit = initial; i = 0; - /* - * Funky HPD #-syntax doesn't map very well to LL-k type parser (for - * constant 'k'). When written directly, we get lots of lexical - * ambiguities. We work around that by doing arbitrary manual - * look-ahead and just parsing the tokens ourselves. Any whitespace - * or EOF stops the lookahead. - */ - String matched = ""; String part; @@ -259,7 +288,8 @@ public class FQIdentParser { if (!(Character.isJavaIdentifierStart(c) || c == '@' || (c == ':' && part.length() == 4 - && part.equals("plt:")))) { + && part.equals("plt:")) + || (allowGlobs && isGlobChar(c)))) { // Break out early if we are already // just waiting for symbol. @@ -296,22 +326,24 @@ public class FQIdentParser { part = part.substring(0, v); } - // This is delibaretely simplified and ignores request for initial letter. - // This is for better error reporting below, we first snip off irrelevant - // parts before yelling at user that his identifier sucks. - Matcher m = Pattern.compile("[a-zA-Z0-9_$]+").matcher(part); - if (m.lookingAt()) { - int diff = part.length() - m.end(); - if (diff > 0) { - matched = matched.substring(0, matched.length() - diff); - part = part.substring(0, m.end()); - } - } - else - throw new RecognitionException("Expected symbol name, got `" + part + "'."); - - if (!Character.isJavaIdentifierStart(part.charAt(0))) - throw new RecognitionException("Invalid symbol `" + part + "'."); + Matcher m = (allowGlobs ? globPattern : symbolPattern).matcher(part); + if (m.lookingAt()) { + int diff = part.length() - m.end(); + if (diff > 0) { + matched = matched.substring(0, matched.length() - diff); + part = part.substring(0, m.end()); + } + } else + throw new RecognitionException("Expected " + + (allowGlobs ? "glob" : "symbol name") + + ", got `" + part + "'."); + + c = part.charAt(0); + if (!(Character.isJavaIdentifierStart(c) + || (allowGlobs && isGlobChar(c)))) + throw new RecognitionException("Invalid symbol" + + (allowGlobs ? " glob" : "" ) + + " `" + part + "'."); FQIdentToken tok = new FQIdentToken(CExprParserTokenTypes.IDENT, matched); tok.dso = partDso; @@ -325,6 +357,7 @@ public class FQIdentParser { tok.threadId = partThreadId; tok.frameNumber = partFrameNum; tok.setLine(scanner.getLine()); + tok.globs = allowGlobs; fqmatch(matched); tok.setColumn(scanner.getColumn() - matched.length()); @@ -357,7 +390,8 @@ public class FQIdentParser { parseFQIdentifier(String str, boolean allowDynamic, boolean allowGlobs, - boolean expectMoreTokens) + boolean expectMoreTokens, + boolean allowPeriodInSymbol) throws ExtraGarbageException, InvalidTokenException { try { @@ -369,7 +403,8 @@ public class FQIdentParser { }; FQIdentParser parser = new FQIdentParser(scanner, allowDynamic, - allowGlobs, expectMoreTokens); + allowGlobs, expectMoreTokens, + allowPeriodInSymbol); FQIdentToken tok = parser.parse(""); if (scanner.LA(1) != CharScanner.EOF_CHAR) @@ -389,6 +424,6 @@ public class FQIdentParser { public static FQIdentifier parseFtraceIdentifier(String str) throws ExtraGarbageException, InvalidTokenException { - return parseFQIdentifier(str, false, true, false); + return parseFQIdentifier(str, false, true, false, true); } } diff --git a/frysk-core/frysk/expr/FQIdentPattern.java b/frysk-core/frysk/expr/FQIdentPattern.java new file mode 100644 index 0000000..03e0605 --- /dev/null +++ b/frysk-core/frysk/expr/FQIdentPattern.java @@ -0,0 +1,63 @@ +// 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.expr; + +public interface FQIdentPattern { + /** Pattern will never match anything. */ + public static final int CARD_NONE = 0; + /** Pattern will match at most one string. */ + public static final int CARD_ONE = 1; + /** Pattern may match more than one string. */ + public static final int CARD_MANY = 2; + /** Pattern will always match everything. */ + public static final int CARD_ALL = 3; + + /** + * Cardinality of this pattern. See various CARD_ constants for + * possible values. + */ + int cardinality(); + + /** + * Whether given string matches this pattern. STR can be a symbol + * name, soname, etc. + */ + boolean matches(String str); +} diff --git a/frysk-core/frysk/expr/FQIdentPatternAll.java b/frysk-core/frysk/expr/FQIdentPatternAll.java new file mode 100644 index 0000000..4e2ad9e --- /dev/null +++ b/frysk-core/frysk/expr/FQIdentPatternAll.java @@ -0,0 +1,62 @@ +// 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.expr; + +/** + * Pattern for part of the FQ identifier that is missing. Missing + * parts match everything. + */ +class FQIdentPatternAll implements FQIdentPattern { + public int cardinality() { + return CARD_ALL; + } + public boolean matches(String symbolName) { + return true; + } + public String toString() { + return "*"; + } + + /** + * Since we only ever need one instance of FQIdentPatternAll + * class, have it handy here. + */ + public static final FQIdentPatternAll instance = new FQIdentPatternAll(); +} diff --git a/frysk-core/frysk/expr/FQIdentPatternExact.java b/frysk-core/frysk/expr/FQIdentPatternExact.java new file mode 100644 index 0000000..8cdc75f --- /dev/null +++ b/frysk-core/frysk/expr/FQIdentPatternExact.java @@ -0,0 +1,61 @@ +// 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.expr; + +/** + * Pattern for exactly specified part of FQ identifier. Always + * matches at most one symbol. If matches(a) and matches(b), then + * a.equals(b). + */ +class FQIdentPatternExact implements FQIdentPattern { + private final String symbolName; + public FQIdentPatternExact(String symbolName) { + this.symbolName = symbolName; + } + public int cardinality() { + return CARD_ONE; + } + public boolean matches(String symbolName) { + return symbolName.equals(this.symbolName); + } + public String toString() { + return symbolName; + } +} diff --git a/frysk-core/frysk/expr/FQIdentPatternGlob.java b/frysk-core/frysk/expr/FQIdentPatternGlob.java new file mode 100644 index 0000000..918f11e --- /dev/null +++ b/frysk-core/frysk/expr/FQIdentPatternGlob.java @@ -0,0 +1,64 @@ +// 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.expr; + +import java.util.regex.Pattern; +import frysk.util.Glob; + +/** + * Pattern for part of FQ identifier specified by a glob. + */ +class FQIdentPatternGlob implements FQIdentPattern { + private final Pattern pattern; + private final String glob; + public FQIdentPatternGlob(String glob) { + this.pattern = Glob.compile(glob); + this.glob = glob; + } + public int cardinality() { + return CARD_MANY; + } + public boolean matches(String symbolName) { + return pattern.matcher(symbolName).matches(); + } + public String toString() { + return glob; + } +} diff --git a/frysk-core/frysk/expr/FQIdentToken.java b/frysk-core/frysk/expr/FQIdentToken.java index fdb5f42..81a56ec 100644 --- a/frysk-core/frysk/expr/FQIdentToken.java +++ b/frysk-core/frysk/expr/FQIdentToken.java @@ -47,6 +47,9 @@ public class FQIdentToken processId = null, threadId = null, frameNumber = null; public boolean wantPlt = false; + /** Whether the token may contain glob expressions. */ + public boolean globs = false; + public FQIdentToken(int t, String txt) { super (t, txt); } diff --git a/frysk-core/frysk/expr/FQIdentifier.java b/frysk-core/frysk/expr/FQIdentifier.java index 0859363..e73fbbe 100644 --- a/frysk-core/frysk/expr/FQIdentifier.java +++ b/frysk-core/frysk/expr/FQIdentifier.java @@ -47,30 +47,42 @@ import frysk.proc.Task; public class FQIdentifier { - final public String soname; - final public String file; - final public Long line; - final public String proc; - final public String symbol; - final public String version; + final public FQIdentPattern soname; + final public FQIdentPattern file; + final public FQIdentPattern proc; + final public FQIdentPattern symbol; + final public FQIdentPattern version; + final public boolean wantPlt; + + final public Long line; final public Long processId; final public Long threadId; final public Long frameNumber; final private int metasoname; - final private static int soname_null = -1; - final private static int soname_name = 0; - final private static int soname_MAIN = 2; - final private static int soname_INTERP = 3; + final private static int SONAME_NULL = -1; + final private static int SONAME_NAME = 0; + final private static int SONAME_MAIN = 2; + final private static int SONAME_INTERP = 3; final private boolean sonameIsPath; + + private FQIdentPattern getPatternFor(FQIdentToken tok, String str) { + if (str == null) + return FQIdentPatternAll.instance; + else if (!tok.globs || !FQIdentParser.isWildcardPattern(str)) + return new FQIdentPatternExact(str); + else + return new FQIdentPatternGlob(str); + } + public FQIdentifier(FQIdentToken tok) { - this.soname = tok.dso; - this.file = tok.file; - this.proc = tok.proc; - this.symbol = tok.symbol; - this.version = tok.version; + this.soname = getPatternFor(tok, tok.dso); + this.file = getPatternFor(tok, tok.file); + this.proc = getPatternFor(tok, tok.proc); + this.symbol = getPatternFor(tok, tok.symbol); + this.version = getPatternFor(tok, tok.version); this.wantPlt = tok.wantPlt; if (tok.processId != null) { @@ -88,22 +100,26 @@ public class FQIdentifier { else this.line = null; - if (soname == null) { + if (tok.dso == null) { this.sonameIsPath = false; - this.metasoname = soname_null; + this.metasoname = SONAME_NULL; } else { - this.sonameIsPath = soname.indexOf('/') != -1; - if (soname.equals("MAIN")) - this.metasoname = soname_MAIN; - else if (soname.equals("INTERP")) - this.metasoname = soname_INTERP; + this.sonameIsPath = tok.dso.indexOf('/') != -1; + if (tok.dso.equals("MAIN")) + this.metasoname = SONAME_MAIN; + else if (tok.dso.equals("INTERP")) + this.metasoname = SONAME_INTERP; else - this.metasoname = soname_name; + this.metasoname = SONAME_NAME; } } public String toString() { StringBuffer buf = new StringBuffer(); + if (processId != null) + buf.append('[').append(processId).append('.') + .append(threadId).append('#').append(frameNumber) + .append(']'); if (soname != null) buf.append('#').append(soname).append('#'); if (file != null) @@ -121,35 +137,46 @@ public class FQIdentifier { } /** - * Translate MAIN and INTERP meta-sonames to main binary and - * dynamic linker of given task. + * Check if given ObjectFile WHAT matches this soname identifier. */ - public String expandSoname(Task task) { - if (metasoname == soname_null) - return null; - else if (metasoname == soname_name) - return soname; + public boolean sonameMatches(Task task, ObjectFile what) { + if (metasoname == SONAME_NULL + || soname.cardinality() == FQIdentPattern.CARD_ALL) + return true; + + else if (sonameIsPath) + return soname.matches(what.getFilename().getPath()); + + else if (metasoname == SONAME_NAME) + return soname.matches(what.getSoname()); + else { // Don't cache so that the identifier is usable for // multiple tasks. String path = task.getProc().getExeFile().getSysRootedPath(); ObjectFile objf = ObjectFile.buildFromFile(path); - if (metasoname == soname_MAIN) - return objf.getSoname(); + if (metasoname == SONAME_MAIN) + return objf.getSoname().equals(what.getSoname()); else - return ObjectFile.buildFromFile(objf.getInterp()).getSoname(); + return ObjectFile.buildFromFile(objf.getInterp()) + .getSoname().equals(what.getSoname()); } } /** - * Check if given ObjectFile WHAT matches this soname identifier. + * Whether this identifier is plain, i.e. has no qualification. + * PLT references are not considered plain symbols. */ - public boolean sonameMatches(Task task, ObjectFile what) { - if (metasoname == soname_null) - return true; - else if (sonameIsPath) - return soname.equals(what.getFilename().getPath()); - else - return this.expandSoname(task).equals(what.getSoname()); + public boolean isPlain() { + return soname.cardinality() == FQIdentPattern.CARD_ALL + && file.cardinality() == FQIdentPattern.CARD_ALL + && line == null + && proc.cardinality() == FQIdentPattern.CARD_ALL + && symbol.cardinality() == FQIdentPattern.CARD_ALL + && version.cardinality() == FQIdentPattern.CARD_ALL + && wantPlt == false + && processId == null + && threadId == null + && frameNumber == null; } } diff --git a/frysk-core/frysk/expr/ScratchSymTab.java b/frysk-core/frysk/expr/ScratchSymTab.java index 6d69620..2f447aa 100644 --- a/frysk-core/frysk/expr/ScratchSymTab.java +++ b/frysk-core/frysk/expr/ScratchSymTab.java @@ -48,43 +48,44 @@ import frysk.value.ObjectDeclaration; import frysk.value.Type; import frysk.value.Value; import frysk.scopes.Variable; +import frysk.UserException; public class ScratchSymTab implements ExprSymTab { /** * Lookup S, assuming S is variable or constant. */ public Value getValue(String s) { - throw new RuntimeException("no values"); + throw new UserException("no values"); } /** * Lookup S, assuming S is a variable. */ public ObjectDeclaration getObjectInScope(DebugInfoFrame frame, String s) { - throw new RuntimeException("no variables"); + throw new UserException("no variables"); } /** * The byte order to use when creating new values. */ public ByteOrder order() { - throw new RuntimeException("no byte-order"); + throw new UserException("no byte-order"); } /** * Return the task's memory buffer */ public ByteBuffer taskMemory() { - throw new RuntimeException("no memory"); + throw new UserException("no memory"); } /** * Return the variable's value. */ public Value getValue(Variable v) { - throw new RuntimeException("no values"); + throw new UserException("no values"); } /** * Given a variable, return its type. */ public Type getType(Variable variable) { - throw new RuntimeException("no types"); + throw new UserException("no types"); } /** * Return the wordsize. diff --git a/frysk-core/frysk/expr/TestArithmetics.java b/frysk-core/frysk/expr/TestArithmetics.java index f537eaa..7cd9b2a 100644 --- a/frysk-core/frysk/expr/TestArithmetics.java +++ b/frysk-core/frysk/expr/TestArithmetics.java @@ -74,7 +74,20 @@ public class TestArithmetics extends TestCase { public void testDecrement() { checkVariableExpr("a.kappa-- + --a.kappa", 0); } - + + public void testArrayAccess() { + checkVariableExpr("arr[0]", 0x01020304); + checkVariableExpr("arr[1]", 0x05060708); + } + + public void testArraySlice() { + checkVariableExpr("arr[1:2][0]", 0x05060708); + checkVariableExpr("arr[1:2][1]", 0x09101112); + checkVariableExpr("arr[0:2][0:1][0:0][0]", 0x01020304); + checkVariableExpr("arr[0:2][1:2][0:0][0]", 0x05060708); + checkVariableExpr("arr[0:2][1:2][0:1][1]", 0x09101112); + } + private void checkErrorExpr(String input, String error) { Throwable t = null; try { @@ -95,7 +108,6 @@ public class TestArithmetics extends TestCase { public void testTokenError() { checkErrorExpr("1...2", "unexpected input: expecting '.', found '2'"); } - // Testing types private void checkExprType (String expr, String resultType){ ExprSymTab symTab = new TestbedSymTab(); diff --git a/frysk-core/frysk/expr/TestbedSymTab.java b/frysk-core/frysk/expr/TestbedSymTab.java index b01806b..866f519 100644 --- a/frysk-core/frysk/expr/TestbedSymTab.java +++ b/frysk-core/frysk/expr/TestbedSymTab.java @@ -42,19 +42,22 @@ package frysk.expr; import inua.eio.ByteBuffer; import inua.eio.ByteOrder; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; + import frysk.config.Host; import frysk.debuginfo.DebugInfoFrame; import frysk.scopes.SourceLocation; +import frysk.scopes.Variable; +import frysk.value.ArrayType; import frysk.value.ClassType; import frysk.value.ObjectDeclaration; import frysk.value.ScratchLocation; import frysk.value.StandardTypes; import frysk.value.Type; import frysk.value.Value; -import frysk.scopes.Variable; class TestbedSymTab implements ExprSymTab { private final SourceLocation scratchSourceLocation = SourceLocation.UNKNOWN; @@ -74,6 +77,20 @@ class TestbedSymTab implements ExprSymTab { }; private Value c1 = new Value(classType, new ScratchLocation(buf)); + private static ArrayList dims() { + final ArrayList a = new ArrayList(); + a.add(new Integer(3)); + return a; + } + private Type arrayType = new ArrayType(StandardTypes.INT32B_T, 12, dims()); + private byte[] arrayBuf = { + 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + 0x09, 0x10, 0x11, 0x12 + }; + private ScratchLocation arrayScratch = new ScratchLocation(arrayBuf); + private Value arr = new Value(arrayType, arrayScratch); + private HashMap symtab; TestbedSymTab () { symtab = new HashMap(); @@ -81,6 +98,7 @@ class TestbedSymTab implements ExprSymTab { symtab.put("b1", c1); symtab.put("b2", c1); symtab.put("c123", c1); + symtab.put("arr", arr); } /** @@ -108,7 +126,7 @@ class TestbedSymTab implements ExprSymTab { * Return the task's memory buffer. */ public ByteBuffer taskMemory() { - throw new RuntimeException("no memory"); + return null; } /** * Return the variable's value. diff --git a/frysk-core/frysk/ftrace/ChangeLog b/frysk-core/frysk/ftrace/ChangeLog index 19fd300..e2943d3 100644 --- a/frysk-core/frysk/ftrace/ChangeLog +++ b/frysk-core/frysk/ftrace/ChangeLog @@ -1,3 +1,21 @@ +2008-06-20 Petr Machata <pmachata@redhat.com> + + * Ftrace.java (getDriversForTask): Drop. + (driversForTask): Actually use it as a map(task->driver), instead + of map(task->map(mapping_path->driver)). + * TaskTracer.java (FunctionReturnObserver.add): Compare symbol + names via .equals, instead of comparing symbol pointers. + +2008-06-20 Petr Machata <pmachata@redhat.com> + + * Reporter.java: Keep a list of event entry tokens, and align + eventLeave with matching eventEntry. + +2008-06-10 Andrew Cagney <cagney@redhat.com> + + * Ftrace.java: Use PrintDebugInfoStackOptions. + * Reporter.java: Ditto. + 2008-06-05 Petr Machata <pmachata@redhat.com> * Ftrace.java: Fix race in attaching various task observers. diff --git a/frysk-core/frysk/ftrace/Ftrace.java b/frysk-core/frysk/ftrace/Ftrace.java index 68ecadb..b19c39e 100644 --- a/frysk-core/frysk/ftrace/Ftrace.java +++ b/frysk-core/frysk/ftrace/Ftrace.java @@ -47,7 +47,7 @@ import java.util.Set; import inua.util.PrintWriter; -import frysk.debuginfo.PrintStackOptions; +import frysk.debuginfo.PrintDebugInfoStackOptions; import frysk.dwfl.ObjectFile; import frysk.event.Event; import frysk.isa.signals.Signal; @@ -75,9 +75,9 @@ public class Ftrace { static private final Log finest = LogFactory.finest(Ftrace.class); static private final Log warning = LogFactory.warning(Ftrace.class); - private final PrintStackOptions stackPrintOptions; + private final PrintDebugInfoStackOptions stackPrintOptions; - public Ftrace(PrintStackOptions stackPrintOptions) { + public Ftrace(PrintDebugInfoStackOptions stackPrintOptions) { this.stackPrintOptions = stackPrintOptions; } @@ -654,15 +654,6 @@ public class Ftrace { return ObjectFile.buildFromFile(mapping.path); } - private Map getDriversForTask(Task task) { - Map drivers = (Map)driversForTask.get(task); - if (drivers == null) { - drivers = new HashMap(); - driversForTask.put(task, drivers); - } - return drivers; - } - public Action updateMappedFile(Task task, MemoryMapping mapping) { if (traceMmapUnmap) @@ -677,10 +668,12 @@ public class Ftrace { DwflModule module = getModuleForFile(task, mapping.path); - Map drivers = getDriversForTask(task); - Driver driver = new TaskTracer(Ftrace.this, task); - drivers.put(mapping.path, driver); - this.tracingController.fileMapped(task, objf, module, driver); + Driver driver = (Driver)driversForTask.get(task); + if (driver == null) { + driver = new TaskTracer(Ftrace.this, task); + driversForTask.put(task, driver); + } + tracingController.fileMapped(task, objf, module, driver); task.requestUnblock(this); return Action.BLOCK; @@ -700,8 +693,7 @@ public class Ftrace { DwflModule module = getModuleForFile(task, mapping.path); - Map drivers = getDriversForTask(task); - Driver driver = (Driver)drivers.get(mapping.path); + Driver driver = (Driver)driversForTask.get(task); if (driver == null) throw new AssertionError("There should be a driver for `" + mapping.path + "'."); diff --git a/frysk-core/frysk/ftrace/Reporter.java b/frysk-core/frysk/ftrace/Reporter.java index 3ed019b..876fc77 100644 --- a/frysk-core/frysk/ftrace/Reporter.java +++ b/frysk-core/frysk/ftrace/Reporter.java @@ -40,10 +40,11 @@ package frysk.ftrace; import java.util.HashMap; +import java.util.ArrayList; import inua.util.PrintWriter; -import frysk.debuginfo.PrintStackOptions; +import frysk.debuginfo.PrintDebugInfoStackOptions; import frysk.proc.Task; import frysk.util.ArchFormatter; import frysk.util.StackPrintUtil; @@ -53,28 +54,29 @@ class Reporter private PrintWriter writer; private Object lastItem = null; private Task lastTask = null; - private HashMap levelMap = new HashMap(); - private final PrintStackOptions stackPrintOptions; + + // HashMap<Task, ArrayList<Object>> -- array of entry tokens for each taks + private final HashMap tokenMap = new HashMap(); + + private final PrintDebugInfoStackOptions stackPrintOptions; private final boolean showPC; - public Reporter(PrintWriter writer, PrintStackOptions stackPrintOptions, boolean show) { + public Reporter(PrintWriter writer, + PrintDebugInfoStackOptions stackPrintOptions, + boolean show) { this.writer = writer; this.stackPrintOptions = stackPrintOptions; this.showPC = show; } - private int getLevel(Task task) + private ArrayList getTokens(Task task) { - int level = 0; - Integer l = (Integer)levelMap.get(task); - if (l != null) - level = l.intValue(); - return level; - } - - private void setLevel(Task task, int level) - { - levelMap.put(task, new Integer(level)); + ArrayList l = (ArrayList)tokenMap.get(task); + if (l == null) { + l = new ArrayList(); + tokenMap.put(task, l); + } + return l; } private boolean lineOpened() @@ -136,9 +138,9 @@ class Reporter public void eventEntry(Task task, Object item, String eventType, String eventName, Object[] args) { - int level = this.getLevel(task); - String spaces = ArchFormatter.repeat(' ', level); - this.setLevel(task, ++level); + ArrayList tokens = getTokens(task); + String spaces = ArchFormatter.repeat(' ', tokens.size()); + tokens.add(item); if (lineOpened()) writer.println('\\'); @@ -156,16 +158,24 @@ class Reporter public void eventLeave(Task task, Object item, String eventType, String eventName, Object retVal) { - int level = this.getLevel(task); - this.setLevel(task, --level); + String stray = ""; + + ArrayList tokens = getTokens(task); + int i = tokens.size() - 1; + while (i >= 0 && tokens.get(i) != item) + --i; + if (i < 0) + stray = "stray "; + else + tokens.subList(i, tokens.size()).clear(); if (!myLineOpened(task, item)) { if (lineOpened()) writer.println(); - String spaces = ArchFormatter.repeat(' ', level); + String spaces = ArchFormatter.repeat(' ', tokens.size()); writer.print(pidInfo(task) + " " + formatTaskPC(task) - + spaces + eventType + + spaces + stray + eventType + " " + eventName); } @@ -182,12 +192,12 @@ class Reporter public void eventSingle(Task task, String eventName, Object[] args) { - int level = this.getLevel(task); + ArrayList tokens = getTokens(task); if (lineOpened()) writer.println("\\"); writer.print(pidInfo(task) + " " + formatTaskPC(task) - + ArchFormatter.repeat(' ', level) + + ArchFormatter.repeat(' ', tokens.size()) + eventName); if (args != null) diff --git a/frysk-core/frysk/ftrace/SymbolRule.java b/frysk-core/frysk/ftrace/SymbolRule.java index 07a667f..6b1e18c 100644 --- a/frysk-core/frysk/ftrace/SymbolRule.java +++ b/frysk-core/frysk/ftrace/SymbolRule.java @@ -86,8 +86,7 @@ public class SymbolRule extends Rule { protected boolean checkNameMatches(final DwflSymbol symbol) { - if (fqid.symbol.equals(symbol.getName())) - return true; + return fqid.symbol.matches(symbol.getName()); // XXX Alias support didn't arrive yet. /* @@ -98,8 +97,6 @@ public class SymbolRule extends Rule { return true; } */ - - return false; } public boolean matches(Object traceable) { diff --git a/frysk-core/frysk/ftrace/TaskTracer.java b/frysk-core/frysk/ftrace/TaskTracer.java index 0ae6b0f..1aff7b6 100644 --- a/frysk-core/frysk/ftrace/TaskTracer.java +++ b/frysk-core/frysk/ftrace/TaskTracer.java @@ -81,6 +81,7 @@ class TaskTracer private final Ftrace ftrace; public TaskTracer(Ftrace ftrace, Task task) { + fine.log("New TaskTracer for", task); this.arch = ArchFactory.instance.getArch(task); this.ftrace = ftrace; } @@ -89,7 +90,20 @@ class TaskTracer { private final DwflSymbol symbol; private final boolean isPlt; + + /** + * TracePoint is chained when it shares return breakpoint with + * other breakpoint. When such a breakpoint is hit, it is + * assumed that both tracepoints have "left". This is used + * when both PLT and regular entry point are traced for one + * symbol. If PLT entry point hits, and regular entry point + * for the same symbol hits immediately after that, the two + * are chained. + */ private boolean chained = false; + + // When the TracePoint is frozen, it can't be chained to + // another TracePoint anymore. private boolean frozen = false; public TracePoint(DwflSymbol symbol) { @@ -119,6 +133,7 @@ class TaskTracer } public void setChained() { + fine.log("chained tracePoint", this); this.chained = true; } @@ -169,7 +184,8 @@ class TaskTracer TracePoint previous = (TracePoint)symbolList.getLast(); if (!previous.isFrozen() && previous.isPlt() && !tracePoint.isPlt() - && previous.getSymbol() == tracePoint.getSymbol()) + && previous.getSymbol().getName().equals + (tracePoint.getSymbol().getName())) tracePoint.setChained(); previous.freeze(); diff --git a/frysk-core/frysk/hpd/CLI.java b/frysk-core/frysk/hpd/CLI.java index 30bb51a..eb1533c 100644 --- a/frysk-core/frysk/hpd/CLI.java +++ b/frysk-core/frysk/hpd/CLI.java @@ -39,6 +39,7 @@ package frysk.hpd; +import frysk.UserException; import frysk.expr.ExprSearchEngine; import java.io.PrintWriter; import java.io.Writer; @@ -139,9 +140,9 @@ public class CLI { try { return topLevelCommand.complete(this, new Input(buffer), cursor, candidates); - } catch (RuntimeException e) { - if (nasty(e)) - e.printStackTrace(outWriter); + } catch (UserException e) { + // If anything user related fails, just give up on the + // completion. return -1; } } @@ -184,6 +185,10 @@ public class CLI { // Assign this proc to the passed in procID else idManager.manageProc(proc, this.taskID); + // Add this process to the runningProcs table + synchronized (this) { + this.runningProcs.add(proc); + } } /** @@ -296,33 +301,14 @@ public class CLI { return null; } - /** - * Identify "nasty", or internal exceptions; these are the - * RuntimeExceptions thrown by the Java system. - */ - private boolean nasty(Exception e) { - Throwable cause = e; - while (true) { - Throwable c = cause.getCause(); - if (c == null) - break; - cause = c; - } - return (cause instanceof NullPointerException - || cause instanceof ArrayIndexOutOfBoundsException - || cause instanceof ArrayStoreException - || cause instanceof ClassCastException - || e.getMessage() == null); - } - void printError(Exception e) { - if (nasty(e)) { + if (e instanceof UserException) { + outWriter.print("Error: "); + outWriter.println(e.getMessage()); + } else { outWriter.print("Internal Error: "); e.printStackTrace(outWriter); outWriter.println(); - } else { - outWriter.print("Error: "); - outWriter.println(e.getMessage()); } } diff --git a/frysk-core/frysk/hpd/ChangeLog b/frysk-core/frysk/hpd/ChangeLog index 61bfb02..87a1322 100644 --- a/frysk-core/frysk/hpd/ChangeLog +++ b/frysk-core/frysk/hpd/ChangeLog @@ -1,3 +1,43 @@ +2008-06-26 Rick Moseley <rmoseley@redhat.com> + + * CLI.java: Fix bz 6696. + * DetachCommand.java: Ditto. + * KillCommand.java: Ditto. + * TestKillCommand.java: Add test for fix. + + +2008-06-17 Teresa Thomas <tthomas@redhat.com> + + * TestWatchCommand.java (testWritePrevValue): New test. + +2008-06-12 Andrew Cagney <cagney@redhat.com> + + * CLI.java (nasty()): Delete. + (printError(Exception)): Check for UserException. + * InvalidCommandException.java: Extend UserException. + +2008-06-11 Rick Moseley <rmoseley@redhat.com> + + * TestCoreCommand.java: Fix bz #6614. + +2008-06-11 Teresa Thomas <tthomas@redhat.com> + + * TestWatchCommand.java (testWatchArraySlice): New test. + +2008-06-11 Andrew Cagney <cagney@redhat.com> + + * TestBreakpoints.java: Update to match backtrace output. + +2008-06-10 Andrew Cagney <cagney@redhat.com> + + * StackCommands.java: Use setPrintPaths. + +2008-06-10 Rick Moseley <rmoseley@redhat.com> + + * StartRun.java: Do not kill core procs. + * CoreCommand.java: Redo hash keys for core proc HashMap. + * TestCoreCommand.java: Add test cases. + 2008-06-06 Sami Wagiaalla <swagiaal@redhat.com> * TestFhpdThreads.java diff --git a/frysk-core/frysk/hpd/CoreCommand.java b/frysk-core/frysk/hpd/CoreCommand.java index ced6d22..eda33ff 100644 --- a/frysk-core/frysk/hpd/CoreCommand.java +++ b/frysk-core/frysk/hpd/CoreCommand.java @@ -119,7 +119,7 @@ public class CoreCommand extends ParameterizedCommand { } public static void load(Proc coreProc, CLI cli) { - load(coreProc, cli, null); + load(coreProc, cli, null); } public static void load(Proc coreProc, CLI cli, String sysroot) { @@ -139,7 +139,7 @@ public class CoreCommand extends ParameterizedCommand { } // Finally, done. synchronized (cli) { - cli.coreProcs.put(coreProc, new Integer(procID)); + cli.coreProcs.put(new Integer(procID), coreProc); cli.ptsetParams.put(new Integer(procID), coreProc.getCmdLine()); } cli.outWriter.println("Attached to core file: " diff --git a/frysk-core/frysk/hpd/DetachCommand.java b/frysk-core/frysk/hpd/DetachCommand.java index b76a603..e98e5a3 100644 --- a/frysk-core/frysk/hpd/DetachCommand.java +++ b/frysk-core/frysk/hpd/DetachCommand.java @@ -1,6 +1,6 @@ // This file is part of the program FRYSK. // -// Copyright 2005, 2006, 2007 Red Hat Inc. +// Copyright 2005, 2006, 2007, 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 @@ -72,12 +72,15 @@ class DetachCommand extends ParameterizedCommand { synchronized (cli) { startedByRun = cli.runningProcs.contains(proc); } - if (startedByRun) + if (!startedByRun) continue; // Delete all breakpoints. if (cli.steppingObserver != null) cli.getSteppingEngine().removeObserver(cli.steppingObserver, proc, true); + synchronized (cli) { + cli.runningProcs.remove(proc); + } } } diff --git a/frysk-core/frysk/hpd/InvalidCommandException.java b/frysk-core/frysk/hpd/InvalidCommandException.java index 8fcd5c5..8bbb585 100644 --- a/frysk-core/frysk/hpd/InvalidCommandException.java +++ b/frysk-core/frysk/hpd/InvalidCommandException.java @@ -1,6 +1,6 @@ // This file is part of the program FRYSK. // -// Copyright 2007 Red Hat Inc. +// Copyright 2007, 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 @@ -39,10 +39,12 @@ package frysk.hpd; +import frysk.UserException; + /** * The command was invalid. */ -public class InvalidCommandException extends RuntimeException { +public class InvalidCommandException extends UserException { static final long serialVersionUID = 1; InvalidCommandException(String message) { super(message); diff --git a/frysk-core/frysk/hpd/KillCommand.java b/frysk-core/frysk/hpd/KillCommand.java index a05f1cf..cf7dabc 100644 --- a/frysk-core/frysk/hpd/KillCommand.java +++ b/frysk-core/frysk/hpd/KillCommand.java @@ -156,6 +156,9 @@ public class KillCommand extends ParameterizedCommand { procPID = proc.getPid(); // Now, call the Proc object to kill off the executable(s) proc.requestKill(); + synchronized (cli) { + cli.runningProcs.remove(proc); + } if ((pid > 0)) return true; } @@ -202,17 +205,14 @@ public class KillCommand extends ParameterizedCommand { + " that was created from " + proc.getExeFile().getSysRootedPath(), Message.TYPE_NORMAL); proc.requestKill(); + synchronized (cli) { + cli.runningProcs.remove(proc); + } tempId = procId; returnProc = true; } } } - if (returnProc) { - synchronized (cli) { - // Clear the running procs set - cli.runningProcs.clear(); - } - } return returnProc; } diff --git a/frysk-core/frysk/hpd/StackCommands.java b/frysk-core/frysk/hpd/StackCommands.java index 8fd8a9f..16f183a 100644 --- a/frysk-core/frysk/hpd/StackCommands.java +++ b/frysk-core/frysk/hpd/StackCommands.java @@ -1,6 +1,6 @@ // This file is part of the program FRYSK. // -// Copyright 2005, 2006, 2007 Red Hat Inc. +// Copyright 2005, 2006, 2007, 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 @@ -41,10 +41,9 @@ package frysk.hpd; import java.util.Iterator; import java.util.List; - import frysk.debuginfo.DebugInfoFrame; import frysk.debuginfo.DebugInfoStackFactory; -import frysk.debuginfo.PrintStackOptions; +import frysk.debuginfo.PrintDebugInfoStackOptions; import frysk.proc.Task; abstract class StackCommands extends ParameterizedCommand { @@ -71,11 +70,12 @@ abstract class StackCommands extends ParameterizedCommand { static private void printStack(CLI cli, DebugInfoFrame frame, int stopLevel, Options options) { - PrintStackOptions printStackOptions = new PrintStackOptions(); + PrintDebugInfoStackOptions printStackOptions + = new PrintDebugInfoStackOptions(); printStackOptions.setNumberOfFrames(stopLevel); - printStackOptions.setPrintParams(true); + printStackOptions.setPrintParameters(true); printStackOptions.setPrintLocals(options.printLocals); - printStackOptions.setPrintFullPaths(true); + printStackOptions.setPrintPaths(true); DebugInfoStackFactory.printStackTrace(cli.outWriter, frame, printStackOptions); diff --git a/frysk-core/frysk/hpd/StartRun.java b/frysk-core/frysk/hpd/StartRun.java index 56bdc50..8a25ad1 100644 --- a/frysk-core/frysk/hpd/StartRun.java +++ b/frysk-core/frysk/hpd/StartRun.java @@ -168,11 +168,9 @@ abstract class StartRun extends ParameterizedCommand { cli.loadedProcs.remove(task.getProc()); } } - // Take care of core procs - // XXX: need to take care of parameters here that were passed into the - // process that created the core file + // Take care of core procs else if (!cli.coreProcs.isEmpty() && - cli.coreProcs.containsKey(task.getProc())) { + cli.coreProcs.containsKey(new Integer(taskData.getParentID()))) { run(cli, cmd, task.getProc().getExeFile().getSysRootedPath(), runToBreak, taskData.getParentID()); synchronized (cli) { @@ -265,8 +263,12 @@ abstract class StartRun extends ParameterizedCommand { while (foo.hasNext()) { taskData = (TaskData) foo.next(); Task task = taskData.getTask(); - if (task.getProc().getPid() != oldPid && - task.getProc().getPid() > 0) { + // Kill a proc only once + if (task.getProc().getPid() != oldPid && + // Don't kill loaded procs, don't have a PID assigned yet + task.getProc().getPid() > 0 && + // Don't kill core procs either, they have the old PID number + cli.coreProcs.get(new Integer(taskData.getParentID())) == null) { cli.execCommand("kill " + task.getProc().getPid() + "\n"); oldPid = task.getProc().getPid(); } diff --git a/frysk-core/frysk/hpd/TestBreakpoints.java b/frysk-core/frysk/hpd/TestBreakpoints.java index 2fe15a3..7a8d12c 100644 --- a/frysk-core/frysk/hpd/TestBreakpoints.java +++ b/frysk-core/frysk/hpd/TestBreakpoints.java @@ -96,7 +96,7 @@ public class TestBreakpoints e.send("go\n"); e.expect("go.*" + prompt + ".*Breakpoint.*sin.*"); e.send("where\n"); - e.expect("where.*#0.* (__)?sin \\(\\).*" + prompt); + e.expect("where.*#0.* (__)?sin\\(\\).*" + prompt); e.send("quit\n"); e.expect("Quitting..."); e.close(); diff --git a/frysk-core/frysk/hpd/TestCoreCommand.java b/frysk-core/frysk/hpd/TestCoreCommand.java index 787edf8..5179d6d 100644 --- a/frysk-core/frysk/hpd/TestCoreCommand.java +++ b/frysk-core/frysk/hpd/TestCoreCommand.java @@ -42,7 +42,9 @@ package frysk.hpd; import java.io.File; import frysk.testbed.CorefileFactory; import frysk.testbed.SlaveOffspring; +//import frysk.testbed.DaemonBlockedAtSignal; import frysk.config.Prefix; +//import frysk.proc.Proc; public class TestCoreCommand extends TestLib { @@ -106,4 +108,18 @@ public class TestCoreCommand extends TestLib { e.expect("Quitting\\.\\.\\."); e.close(); } + + public void testCoreLoadedParamsTwo() { + + File exe = new File("/bin/echo"); + File core = CorefileFactory.constructCoreAtEntry(exe, new String[] {"abcd"}); + e = new HpdTestbed(); + e.sendCommandExpectPrompt("core " + core.getPath(), "Attached to core.*"); + e.sendCommandExpectPrompt("info args", "abcd.*"); + e.sendCommandExpectPrompt("run", "running.*abcd.*" + + "Attached to process ([0-9]+).*" + "Running process ([0-9]+).*"); + e.send("quit\n"); + e.expect("Quitting\\.\\.\\."); + e.close(); + } } diff --git a/frysk-core/frysk/hpd/TestKillCommand.java b/frysk-core/frysk/hpd/TestKillCommand.java index 4a5446c..e3711d9 100644 --- a/frysk-core/frysk/hpd/TestKillCommand.java +++ b/frysk-core/frysk/hpd/TestKillCommand.java @@ -196,6 +196,37 @@ java.lang.NullPointerException } /** + * Test killing of a single proc NOT using the PID + */ + public void testKillAfterAttach() { + SlaveOffspring newProc = SlaveOffspring.createDaemon(); + int pid = newProc.getPid().intValue(); + e = new HpdTestbed(); + e.sendCommandExpectPrompt("attach " + pid, "Attached to process " + pid + ".*"); + e.sendCommandExpectPrompt("kill", "Killing process " + pid + ".*"); + try { Thread.sleep(500); } catch (Exception e) { } + e.send("quit\n"); + e.expect("Quitting\\.\\.\\..*"); + e.close(); + } + + /** + * Test killing of a single proc and then running + */ + public void testKillAfterAttachThenRun() { + SlaveOffspring newProc = SlaveOffspring.createDaemon(); + int pid = newProc.getPid().intValue(); + e = new HpdTestbed(); + e.sendCommandExpectPrompt("attach " + pid, "Attached to process " + pid + ".*"); + e.sendCommandExpectPrompt("kill", "Killing process " + pid + ".*"); + try { Thread.sleep(500); } catch (Exception e) { } + e.sendCommandExpectPrompt("run", "running with this command.*"); + e.send("quit\n"); + e.expect("Quitting\\.\\.\\..*"); + e.close(); + } + + /** * Test entering a non-integer as a PID */ public void testKillError() { diff --git a/frysk-core/frysk/hpd/TestWatchCommand.java b/frysk-core/frysk/hpd/TestWatchCommand.java index dbacbb4..c52a756 100644 --- a/frysk-core/frysk/hpd/TestWatchCommand.java +++ b/frysk-core/frysk/hpd/TestWatchCommand.java @@ -140,13 +140,26 @@ public class TestWatchCommand extends TestLib { e.close(); } + public void testWatchArraySlice() { + e = new HpdTestbed(); + e.sendCommandExpectPrompt("load " + Prefix.pkgLibFile("funit-ctypes").getPath(), + "Loaded executable file.*"); + e.sendCommandExpectPrompt("start", "Attached to process.*"); + + e.send("watch array[ 0:1]\n"); + e.expect(".*Uses [1-9]+ debug register.*"); + + e.send("quit\n"); + e.expect("Quitting\\.\\.\\."); + e.close(); + } + /* * Test to watch a data type whose size is larger than * that can be watched by all hardware watch registers * put together. - */ - public void testWatchOversized() - { + */ + public void testWatchOversized() { e = new HpdTestbed(); e.sendCommandExpectPrompt("load " + Prefix.pkgLibFile("funit-ctypes").getPath(), "Loaded executable file.*"); @@ -158,8 +171,8 @@ public class TestWatchCommand extends TestLib { e.send("quit\n"); e.expect("Quitting\\.\\.\\."); - e.close(); - } + e.close(); + } /* * Test to watch a variable that is smaller than the max @@ -207,7 +220,30 @@ public class TestWatchCommand extends TestLib { e.close(); } - + /* + * Test to check if user notified when value being + * written to is the same as previous value. + */ + public void testWritePrevValue() { + e = new HpdTestbed(); + e.sendCommandExpectPrompt("load " + Prefix.pkgLibFile("funit-ctypes").getPath(), + "Loaded executable file.*"); + e.send("break main\n"); + e.expect("breakpoint.*" + prompt); + e.send("run\n"); + e.expect("Attached to process ([0-9]+).*"); + + e.send("watch float_\n"); + e.expect(".*Watchpoint set: float_.*"); + + e.send("go\n"); + e.expect(".*Note: Value unchanged before and after access.*"); + + e.send("quit\n"); + e.expect("Quitting\\.\\.\\."); + e.close(); + } + private Task getStoppedTask() { return this.getStoppedTask("funit-ctypes"); } diff --git a/frysk-core/frysk/isa/watchpoints/ChangeLog b/frysk-core/frysk/isa/watchpoints/ChangeLog index 0dd75aa..cc0ef21 100644 --- a/frysk-core/frysk/isa/watchpoints/ChangeLog +++ b/frysk-core/frysk/isa/watchpoints/ChangeLog @@ -1,3 +1,12 @@ +2008-06-24 Phil Muldoon <pmuldoon@redhat.com> + + * WatchpointFunctions.java (getWatchpointMinLength): Really + return the minimum length. + +2008-06-16 Phil Muldoon <pmuldoon@redhat.com> + + * WatchpointFunctions.java (getTriggeredWatchpoints): New. + 2008-06-05 Phil Muldoon <pmuldoon@redhat.com> * WatchpointFunctions.java (getWatchpointMinLength): New. diff --git a/frysk-core/frysk/isa/watchpoints/WatchpointFunctions.java b/frysk-core/frysk/isa/watchpoints/WatchpointFunctions.java index 994d0cb..973678f 100644 --- a/frysk-core/frysk/isa/watchpoints/WatchpointFunctions.java +++ b/frysk-core/frysk/isa/watchpoints/WatchpointFunctions.java @@ -42,6 +42,7 @@ package frysk.isa.watchpoints; import java.util.ArrayList; import java.util.List; + import frysk.proc.Task; public abstract class WatchpointFunctions { @@ -107,13 +108,27 @@ public abstract class WatchpointFunctions { **/ public List getAllWatchpoints(Task task) { List listOfWP = new ArrayList(); - for (int i=0; i<getWatchpointCount(); i++) { + for (int i=0; i<getWatchpointCount(); i++) listOfWP.add(readWatchpoint(task,i)); - } return listOfWP; } /** + * Returns all the triggeed watchpoints k + * + * @param task - task on which to delete a watchpoint. + * + * @return List- List of watchpoints + * + **/ + public ArrayList getTriggeredWatchpoints(Task task) { + ArrayList listOfWP = new ArrayList(); + for (int i=0; i<getWatchpointCount(); i++) + if (hasWatchpointTriggered(task, i)) + listOfWP.add(readWatchpoint(task,i)); + return listOfWP; + } + /** * Reads the Debug control register. * * @param task - task to read the debug control @@ -176,7 +191,7 @@ public abstract class WatchpointFunctions { * @return int minimum length */ public final int getWatchpointMinLength() { - return watchpointMaxLength; + return watchpointMinLength; } } diff --git a/frysk-core/frysk/pkglibdir/ChangeLog b/frysk-core/frysk/pkglibdir/ChangeLog index 181dd43..9b88513 100644 --- a/frysk-core/frysk/pkglibdir/ChangeLog +++ b/frysk-core/frysk/pkglibdir/ChangeLog @@ -1,3 +1,12 @@ +2009-03-20 Mark Wielaard <mark@klomp.org> + + * FunitSimpleInterfaceTest.java (main): Work around compiler being + too smart...and noticing o == null. + +2008-06-17 Teresa Thomas <tthomas@redhat.com> + + * funit-ctypes.c: Write to float_. + 2008-06-06 Sami Wagiaalla <swagiaal@redhat.com> * funit-2threads.c: New test program. @@ -6,7 +15,7 @@ * funit-raise.S: Fix ADD parameter order. -2007-05-23 Teresa Thomas <tthomas@redhat.com> +2008-05-23 Teresa Thomas <tthomas@redhat.com> * funit-ctypes.c: New file. diff --git a/frysk-core/frysk/pkglibdir/FunitSimpleInterfaceTest.java b/frysk-core/frysk/pkglibdir/FunitSimpleInterfaceTest.java index dd2504e..3bb9de4 100644 --- a/frysk-core/frysk/pkglibdir/FunitSimpleInterfaceTest.java +++ b/frysk-core/frysk/pkglibdir/FunitSimpleInterfaceTest.java @@ -43,6 +43,8 @@ public class FunitSimpleInterfaceTest implements FunitSimpleInterface{ FunitSimpleInterface inter = new FunitSimpleInterfaceTest(); // Crash Object o = null; + if (o == inter) // Work around compiler being too smart... + o = inter; o.toString(); inter.simpleMethod(); } diff --git a/frysk-core/frysk/pkglibdir/funit-ctypes.c b/frysk-core/frysk/pkglibdir/funit-ctypes.c index 6a5e3fb..9337ab6 100644 --- a/frysk-core/frysk/pkglibdir/funit-ctypes.c +++ b/frysk-core/frysk/pkglibdir/funit-ctypes.c @@ -44,7 +44,7 @@ int array[4]; int bigArray[9]; -float float_ = 0.0; +float float_ = 1.9; double double_ = 0.0; long long long_long = 111; char char_ = 'A'; @@ -56,6 +56,7 @@ int main(int argc, char* argv[]) array[k] = k; double_ = 12.0; + float_ = 1.9; long_long = 0x11223344aabbccddLL; char_ = 'B'; diff --git a/frysk-core/frysk/proc/dead/ChangeLog b/frysk-core/frysk/proc/dead/ChangeLog index a66b5dd..d2b8beb 100644 --- a/frysk-core/frysk/proc/dead/ChangeLog +++ b/frysk-core/frysk/proc/dead/ChangeLog @@ -1,3 +1,16 @@ +2008-06-20 Andrew Cagney <cagney@redhat.com> + + * CorefileByteBuffer.java: Throw UserException, not + RuntimeException. + +2008-06-11 Andrew Cagney <cagney@redhat.com> + + * TestLinuxCore.java: Update to match stack trace output. + +2008-06-10 Andrew Cagney <cagney@redhat.com> + + * TestLinuxCore.java: Use PrintDebugInfoStackOptions. + 2008-06-04 Andrew Cagney <cagney@redhat.com> * LinuxCoreInfo.java (constructAuxv): Eliminate use of diff --git a/frysk-core/frysk/proc/dead/CorefileByteBuffer.java b/frysk-core/frysk/proc/dead/CorefileByteBuffer.java index 0abed3b..86274e6 100644 --- a/frysk-core/frysk/proc/dead/CorefileByteBuffer.java +++ b/frysk-core/frysk/proc/dead/CorefileByteBuffer.java @@ -39,6 +39,7 @@ package frysk.proc.dead; +import frysk.UserException; import frysk.sys.StatelessFile; import java.io.File; import java.util.ArrayList; @@ -92,10 +93,9 @@ public class CorefileByteBuffer extends ByteBuffer { closeCoreFileElf(elf); } - protected void poke(long arg0, int arg1) - { - throw new RuntimeException("Cannot poke into a corefile!"); - } + protected void poke(long arg0, int arg1) { + throw new UserException("Cannot poke into a corefile!"); + } protected int peek(long address) { @@ -120,20 +120,22 @@ public class CorefileByteBuffer extends ByteBuffer { long offset = metaLine.solibOffset + (address - metaLine.vaddr); temp.pread(offset, buffer,0,1); } else { - throw new RuntimeException("CorefileByteBuffer: Cannot peek() at address 0x"+ - Long.toHexString(address)+". Offset exists in file: " + - metaLine.name+" but that file cannot be accessed."); + throw new UserException + ("CorefileByteBuffer: Cannot peek() at address 0x" + + Long.toHexString(address)+". Offset exists in file: " + + metaLine.name+" but that file cannot be accessed."); } } } - else - throw new RuntimeException("CorefileByteBuffer: Cannot peek() " + - "at address 0x" + - Long.toHexString(address)+"." + - " Address location is unknown " + - " (not in corefile, executable or "+ - " mapped solibs)."); + else { + throw new UserException("CorefileByteBuffer: Cannot peek() " + + "at address 0x" + + Long.toHexString(address)+"." + + " Address location is unknown " + + " (not in corefile, executable or "+ + " mapped solibs)."); + } return buffer[0]; } @@ -236,14 +238,14 @@ public class CorefileByteBuffer extends ByteBuffer { //XXX: the boolean gate indicates offset not found. if (!foundOffset) - throw new RuntimeException("Cannot find file offset for given address 0x" - + Long.toHexString(address)); + throw new UserException("Cannot find file offset for given address 0x" + + Long.toHexString(address)); if (!presentInFile) - throw new RuntimeException("Cannot read file offset for given address 0x" - + Long.toHexString(address) + - ". It is elided from the core file"); + throw new UserException("Cannot read file offset for given address 0x" + + Long.toHexString(address) + + ". It is elided from the core file"); return offset; } @@ -295,9 +297,9 @@ public class CorefileByteBuffer extends ByteBuffer { "",0x1000)); } } - } - else - throw new RuntimeException("Cannot IO access " + this.coreFile.getPath()); + } else { + throw new UserException("Cannot IO access " + this.coreFile.getPath()); + } return (MapAddressHeader[]) localList.toArray(new MapAddressHeader[localList.size()]); } diff --git a/frysk-core/frysk/proc/dead/TestLinuxCore.java b/frysk-core/frysk/proc/dead/TestLinuxCore.java index d6fd1e3..9bd63d4 100644 --- a/frysk-core/frysk/proc/dead/TestLinuxCore.java +++ b/frysk-core/frysk/proc/dead/TestLinuxCore.java @@ -50,7 +50,7 @@ import java.util.Iterator; import lib.dwfl.DwflModule; import lib.dwfl.SymbolBuilder; import frysk.config.Prefix; -import frysk.debuginfo.PrintStackOptions; +import frysk.debuginfo.PrintDebugInfoStackOptions; import frysk.dwfl.DwflCache; import frysk.event.Event; import frysk.event.RequestStopEvent; @@ -111,7 +111,7 @@ public class TestLinuxCore extends TestLib { // relative -> absolute converstion is occuring. StacktraceAction coreStacktrace; StringWriter coreStackOutput = new StringWriter(); - PrintStackOptions options = new PrintStackOptions(); + PrintDebugInfoStackOptions options = new PrintDebugInfoStackOptions(); options.setNumberOfFrames(20); // Create a stackktrace of a the corefile process @@ -132,10 +132,10 @@ public class TestLinuxCore extends TestLib { String mainThread = "Task #\\d+\n" + "(#[\\d]+ 0x[\\da-f]+ in .*\n)*" - + "#[\\d]+ 0x[\\da-f]+ in server \\(\\).*\n" - + "#[\\d]+ 0x[\\da-f]+ in main \\(\\).*\n" - + "#[\\d]+ 0x[\\da-f]+ in __libc_start_main \\(\\).*\n" - + "#[\\d]+ 0x[\\da-f]+ in _start \\(\\).*\n\n"; + + "#[\\d]+ 0x[\\da-f]+ in server\\(\\).*\n" + + "#[\\d]+ 0x[\\da-f]+ in main\\(\\).*\n" + + "#[\\d]+ 0x[\\da-f]+ in __libc_start_main\\(\\).*\n" + + "#[\\d]+ 0x[\\da-f]+ in _start\\(\\).*\n\n"; String regex = new String(); regex += "(" + mainThread + ")"; @@ -143,7 +143,7 @@ public class TestLinuxCore extends TestLib { String result = coreStackOutput.getBuffer().toString(); assertTrue(result + "should match: " + regex + " threads", - result.matches(regex)); + result.matches(regex)); } @@ -211,7 +211,7 @@ public class TestLinuxCore extends TestLib { StacktraceAction coreStacktrace; StringWriter liveStackOutput = new StringWriter(); StringWriter coreStackOutput = new StringWriter(); - PrintStackOptions options = new PrintStackOptions(); + PrintDebugInfoStackOptions options = new PrintDebugInfoStackOptions(); options.setNumberOfFrames(20); // Create a Stacktrace of the blocked live process @@ -263,7 +263,6 @@ public class TestLinuxCore extends TestLib { assertEquals("Compare stack traces", liveStackOutput.getBuffer().toString(), coreStackOutput.getBuffer().toString()); - } private static class PrintEvent implements Event diff --git a/frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java b/frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java deleted file mode 100644 index adc0723..0000000 --- a/frysk-core/frysk/proc/live/AddressSpaceByteBuffer.java +++ /dev/null @@ -1,198 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2007, 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.proc.live; - -import inua.eio.ByteBuffer; -import frysk.sys.Errno; -import frysk.sys.ProcessIdentifier; -import frysk.sys.ptrace.AddressSpace; -import frysk.sys.proc.Mem; -import frysk.event.Request; -import frysk.proc.Manager; - -public class AddressSpaceByteBuffer extends ByteBuffer { - protected final AddressSpace addressSpace; - protected final ProcessIdentifier pid; - - // Direct files access if possible, or null otherwise. - private Mem mem; - - protected AddressSpaceByteBuffer (ProcessIdentifier pid, - AddressSpace addressSpace, - long lowerExtreem, long upperExtreem) { - super (lowerExtreem, upperExtreem); - this.pid = pid; - this.addressSpace = addressSpace; - peekRequest = new PeekRequest(); - pokeRequest = new PokeRequest(); - if (addressSpace == AddressSpace.TEXT - || addressSpace == AddressSpace.DATA) - // Try to use /proc; but if any error occures clear it and - // revert back to ptrace. - mem = new Mem(pid); - } - public AddressSpaceByteBuffer(ProcessIdentifier pid, - AddressSpace addressSpace) { - this(pid, addressSpace, 0, addressSpace.length()); - } - - - private class PeekRequest - extends Request - { - private long index; - private int value; - PeekRequest() - { - super(Manager.eventLoop); - } - public void execute () - { - value = addressSpace.peek(pid, index); - } - public int request (long index) - { - if (isEventLoopThread()) - return addressSpace.peek(pid, index); - else synchronized (this) { - this.index = index; - request(); - return value; - } - } - } - private final PeekRequest peekRequest; - protected int peek(long index) { - return peekRequest.request (index); - } - - private class PokeRequest - extends Request - { - private long index; - private int value; - PokeRequest() - { - super(Manager.eventLoop); - } - public void execute () - { - addressSpace.poke(pid, index, value); - } - public void request (long index, int value) - { - if (isEventLoopThread()) - addressSpace.poke(pid, index, value); - else synchronized (this) { - this.index = index; - this.value = value; - request(); - } - } - } - private final PokeRequest pokeRequest; - protected void poke(long index, int value) { - pokeRequest.request (index, value); - } - - private class TransferRequest extends Request { - private long index; - private byte[] bytes; - private int offset; - private int length; - private boolean write; - TransferRequest() { - super(Manager.eventLoop); - } - private void transfer(long index, byte[] bytes, int offset, int length, - boolean write) { - if (mem != null && !write) { - try { - mem.pread(index, bytes, offset, length); - return; - } catch (Errno e) { - // Give up on mem; and fall back to ptrace. This - // can happen when /proc isn't mounted, or when a - // process is terminating and the kernel scrubs - // the /proc entry before its time. - mem = null; - } - } - addressSpace.transfer(pid, index, bytes, offset, length, - write); - } - - public void execute() { - transfer(index, bytes, offset, length, write); - } - - public void request(long index, byte[] bytes, int offset, int length, - boolean write) { - if (isEventLoopThread()) - transfer(index, bytes, offset, length, write); - else synchronized (this) { - this.index = index; - this.bytes = bytes; - this.offset = offset; - this.length = length; - this.write = write; - super.request(); - } - } - } - private final TransferRequest transfer = new TransferRequest(); - - protected int peek(long index, byte[] bytes, int offset, int length) { - transfer.request(index, bytes, offset, length, false); // read - return length; - } - protected int poke(long index, byte[] bytes, int offset, int length) { - transfer.request(index, bytes, offset, length, true); // write - return length; - } - - protected ByteBuffer subBuffer (ByteBuffer parent, long lowerExtreem, - long upperExtreem) - { - AddressSpaceByteBuffer up = (AddressSpaceByteBuffer)parent; - return new AddressSpaceByteBuffer (up.pid, up.addressSpace, - lowerExtreem, upperExtreem); - } -} diff --git a/frysk-core/frysk/proc/live/BlockSpaceByteBuffer.java b/frysk-core/frysk/proc/live/BlockSpaceByteBuffer.java new file mode 100644 index 0000000..84b2c8a --- /dev/null +++ b/frysk-core/frysk/proc/live/BlockSpaceByteBuffer.java @@ -0,0 +1,130 @@ +// This file is part of the program FRYSK. +// +// Copyright 2006, 2007, 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.proc.live; + +import frysk.sys.ptrace.BlockSpace; +import frysk.event.Request; +import frysk.proc.Manager; +import inua.eio.ByteBuffer; +import frysk.sys.ProcessIdentifier; + +/* + * A ByteBuffer interface to structures returned by ptrace which must + * be read or written all at once e.g., the registers or floating + * point registers. + */ +public class BlockSpaceByteBuffer + extends ByteBuffer +{ + private final ProcessIdentifier pid; + private final BlockSpace registerSet; + private final byte[] bytes; + + private BlockSpaceByteBuffer(ProcessIdentifier pid, + BlockSpace registerSet, + long lowerExtreem, long upperExtreem) { + super(lowerExtreem, upperExtreem); + this.pid = pid; + this.registerSet = registerSet; + bytes = new byte[registerSet.length()]; + } + public BlockSpaceByteBuffer(ProcessIdentifier pid, + BlockSpace registerSet) { + this(pid, registerSet, 0, registerSet.length()); + } + + private class TransferRequest extends Request { + TransferRequest() { + super(Manager.eventLoop); + } + private boolean write; + public final void execute() { + registerSet.transfer(pid, bytes, write); + } + private void request(boolean write) { + if (isEventLoopThread()) { + registerSet.transfer(pid, bytes, write); + } else { + synchronized (this) { + this.write = write; + super.request(); + } + } + } + void getRegs() { + request(false); // read + } + void setRegs() { + request(true); // write + } + } + private final TransferRequest transfer = new TransferRequest(); + + protected int peek(long index) { + transfer.getRegs(); + return bytes[(int)index]; + } + + protected void poke(long index, int value) { + transfer.getRegs(); + bytes[(int)index] = (byte)value; + transfer.setRegs(); + } + + protected int peek(long index, byte[] bytes, int off, int len) { + transfer.getRegs(); + System.arraycopy(this.bytes, (int) index, bytes, off, len); + return len; + } + + protected int poke(long index, byte[] bytes, int off, int len) { + transfer.getRegs(); + System.arraycopy(bytes, off, this.bytes, (int) index, len); + transfer.setRegs(); + return len; + } + + protected ByteBuffer subBuffer(ByteBuffer parent, long lowerExtreem, + long upperExtreem) { + BlockSpaceByteBuffer up = (BlockSpaceByteBuffer)parent; + return new BlockSpaceByteBuffer(up.pid, up.registerSet, + lowerExtreem, upperExtreem); + } +} diff --git a/frysk-core/frysk/proc/live/ByteSpaceByteBuffer.java b/frysk-core/frysk/proc/live/ByteSpaceByteBuffer.java new file mode 100644 index 0000000..7cd405e --- /dev/null +++ b/frysk-core/frysk/proc/live/ByteSpaceByteBuffer.java @@ -0,0 +1,198 @@ +// This file is part of the program FRYSK. +// +// Copyright 2007, 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.proc.live; + +import inua.eio.ByteBuffer; +import frysk.sys.Errno; +import frysk.sys.ProcessIdentifier; +import frysk.sys.ptrace.ByteSpace; +import frysk.sys.proc.Mem; +import frysk.event.Request; +import frysk.proc.Manager; + +public class ByteSpaceByteBuffer extends ByteBuffer { + protected final ByteSpace addressSpace; + protected final ProcessIdentifier pid; + + // Direct files access if possible, or null otherwise. + private Mem mem; + + protected ByteSpaceByteBuffer (ProcessIdentifier pid, + ByteSpace addressSpace, + long lowerExtreem, long upperExtreem) { + super (lowerExtreem, upperExtreem); + this.pid = pid; + this.addressSpace = addressSpace; + peekRequest = new PeekRequest(); + pokeRequest = new PokeRequest(); + if (addressSpace == ByteSpace.TEXT + || addressSpace == ByteSpace.DATA) { + // Try to use /proc; but if any error occures clear it and + // revert back to ptrace. + mem = new Mem(pid); + } + } + public ByteSpaceByteBuffer(ProcessIdentifier pid, + ByteSpace addressSpace) { + this(pid, addressSpace, 0, addressSpace.length()); + } + + + private class PeekRequest + extends Request + { + private long index; + private int value; + PeekRequest() { + super(Manager.eventLoop); + } + public void execute() { + value = addressSpace.peek(pid, index); + } + public int request(long index) { + if (isEventLoopThread()) + return addressSpace.peek(pid, index); + else { + synchronized (this) { + this.index = index; + request(); + return value; + } + } + } + } + private final PeekRequest peekRequest; + protected int peek(long index) { + return peekRequest.request (index); + } + + private class PokeRequest + extends Request + { + private long index; + private int value; + PokeRequest() { + super(Manager.eventLoop); + } + public void execute() { + addressSpace.poke(pid, index, value); + } + public void request(long index, int value) { + if (isEventLoopThread()) + addressSpace.poke(pid, index, value); + else { + synchronized (this) { + this.index = index; + this.value = value; + request(); + } + } + } + } + private final PokeRequest pokeRequest; + protected void poke(long index, int value) { + pokeRequest.request (index, value); + } + + private class TransferRequest extends Request { + private long index; + private byte[] bytes; + private int offset; + private int length; + private boolean write; + TransferRequest() { + super(Manager.eventLoop); + } + private void transfer(long index, byte[] bytes, int offset, int length, + boolean write) { + if (mem != null && !write) { + try { + mem.pread(index, bytes, offset, length); + return; + } catch (Errno e) { + // Give up on mem; and fall back to ptrace. This + // can happen when /proc isn't mounted, or when a + // process is terminating and the kernel scrubs + // the /proc entry before its time. + mem = null; + } + } + addressSpace.transfer(pid, index, bytes, offset, length, + write); + } + + public void execute() { + transfer(index, bytes, offset, length, write); + } + + public void request(long index, byte[] bytes, int offset, int length, + boolean write) { + if (isEventLoopThread()) + transfer(index, bytes, offset, length, write); + else { + synchronized (this) { + this.index = index; + this.bytes = bytes; + this.offset = offset; + this.length = length; + this.write = write; + super.request(); + } + } + } + } + private final TransferRequest transfer = new TransferRequest(); + + protected int peek(long index, byte[] bytes, int offset, int length) { + transfer.request(index, bytes, offset, length, false); // read + return length; + } + protected int poke(long index, byte[] bytes, int offset, int length) { + transfer.request(index, bytes, offset, length, true); // write + return length; + } + + protected ByteBuffer subBuffer (ByteBuffer parent, long lowerExtreem, + long upperExtreem) { + ByteSpaceByteBuffer up = (ByteSpaceByteBuffer)parent; + return new ByteSpaceByteBuffer(up.pid, up.addressSpace, + lowerExtreem, upperExtreem); + } +} diff --git a/frysk-core/frysk/proc/live/ChangeLog b/frysk-core/frysk/proc/live/ChangeLog index eee24c5..49838f5 100644 --- a/frysk-core/frysk/proc/live/ChangeLog +++ b/frysk-core/frysk/proc/live/ChangeLog @@ -1,3 +1,21 @@ +2008-07-04 Andrew Cagney <cagney@redhat.com> + + * ByteSpaceByteBuffer.java: Rename AddressSpaceByteBuffer. + * BlockSpaceByteBuffer.java: Rename RegisterSetByteBuffer.. + * LogicalMemoryBuffer.java: Update. + * LinuxPtraceTask.java: Update. + * PtraceRegisterBanksFactory.java: Update. + * TestByteBuffer.java: Update. + +2008-06-16 Phil Muldoon <pmuldoon@redhat.com> + + * LinuxPtraceTaskState.java (Running.checkWatchpoint): Rewrite to use + WatchpointFunctions.getTriggeredWatchpoints(). + +2008-06-12 Andrew Cagney <cagney@redhat.com> + + * LinuxPtraceProc.java (getExe()): Delete. + 2008-06-06 Teresa Thomas <tthomas@redhat.com> * LinuxPtraceTaskState.java: Additional logging messages. diff --git a/frysk-core/frysk/proc/live/LinuxPtraceProc.java b/frysk-core/frysk/proc/live/LinuxPtraceProc.java index e854829..c7e1888 100644 --- a/frysk-core/frysk/proc/live/LinuxPtraceProc.java +++ b/frysk-core/frysk/proc/live/LinuxPtraceProc.java @@ -224,40 +224,15 @@ public class LinuxPtraceProc extends LiveProc { * and a second returning the exe as it should be (but possibly * isn't :-). Better yet have utrace handle it :-) */ - private String exe; - private String getExe() { + private SysRootFile exe; + public SysRootFile getExeFile() { if (exe == null) { - ProcessIdentifier pid - = ProcessIdentifierFactory.create(getPid()); - String exe = Exe.get(pid); - // Linux's /proc/$$/exe can get screwed up in several - // ways. Detect each here and return null. - if (exe.endsWith(" (deleted)")) - // Assume (possibly incorrectly) that a trailing - // "(deleted)" always indicates a deleted file. - return null; - if (exe.indexOf((char)0) >= 0) - // Assume that an EXE that has somehow ended up with - // an embedded NUL character is invalid. This happens - // when the kernel screws up "mv a-really-long-file - // $exe" leaving the updated EXE string with something - // like "$exe<NUL>ally-long-file (deleted)". - return null; - if (!new File(exe).exists()) - // Final sanity check; the above two should have covered - // all possible cases. But one never knows. - return null; - this.exe = exe; + File exeFile = new File(Exe.getName(pid)); + return new SysRootFile(SysRootCache.getSysRoot(exeFile.getName()), exeFile); } return exe; } - public SysRootFile getExeFile() { - String exe = getExe(); - File exeFile = new File(exe); - return new SysRootFile(SysRootCache.getSysRoot(exeFile.getName()), exeFile); - } - /** * If it hasn't already been read, read the stat structure. */ diff --git a/frysk-core/frysk/proc/live/LinuxPtraceTask.java b/frysk-core/frysk/proc/live/LinuxPtraceTask.java index 0ecadb3..8dc5c78 100644 --- a/frysk-core/frysk/proc/live/LinuxPtraceTask.java +++ b/frysk-core/frysk/proc/live/LinuxPtraceTask.java @@ -60,7 +60,7 @@ import inua.eio.ByteOrder; import frysk.sys.Errno; import frysk.sys.ProcessIdentifier; import frysk.sys.ptrace.Ptrace; -import frysk.sys.ptrace.AddressSpace; +import frysk.sys.ptrace.ByteSpace; import frysk.sys.Signal; import frysk.isa.syscalls.Syscall; import frysk.isa.ISA; @@ -140,8 +140,7 @@ public class LinuxPtraceTask extends LiveTask { ByteBuffer getRawMemory() { fine.log(this, "Begin fillMemory"); ByteOrder byteOrder = getISA().order(); - ByteBuffer memory = new AddressSpaceByteBuffer(tid, - AddressSpace.DATA); + ByteBuffer memory = new ByteSpaceByteBuffer(tid, ByteSpace.DATA); memory.order(byteOrder); fine.log(this, "End fillMemory"); return memory; @@ -155,7 +154,7 @@ public class LinuxPtraceTask extends LiveTask { fine.log(this, "exiting get memory"); ByteOrder byteOrder = getISA().order(); BreakpointAddresses breakpoints = ((LinuxPtraceProc)getProc()).breakpoints; - memory = new LogicalMemoryBuffer(tid, AddressSpace.DATA, + memory = new LogicalMemoryBuffer(tid, ByteSpace.DATA, breakpoints); memory.order(byteOrder); } diff --git a/frysk-core/frysk/proc/live/LinuxPtraceTaskState.java b/frysk-core/frysk/proc/live/LinuxPtraceTaskState.java index a819b9a..88286dc 100644 --- a/frysk-core/frysk/proc/live/LinuxPtraceTaskState.java +++ b/frysk-core/frysk/proc/live/LinuxPtraceTaskState.java @@ -39,18 +39,20 @@ package frysk.proc.live; -import frysk.sys.SignalSet; -import frysk.sys.proc.Status; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + import frysk.isa.watchpoints.WatchpointFunctionFactory; import frysk.isa.watchpoints.WatchpointFunctions; -import frysk.proc.TaskObserver; -import frysk.proc.Observer; import frysk.proc.Observable; -import java.util.Collection; -import java.util.Iterator; -import frysk.sys.Signal; +import frysk.proc.Observer; +import frysk.proc.TaskObserver; import frysk.rsl.Log; import frysk.rsl.LogFactory; +import frysk.sys.Signal; +import frysk.sys.SignalSet; +import frysk.sys.proc.Status; /** * A Linux Task's State tracked using PTRACE. @@ -938,15 +940,15 @@ abstract class LinuxPtraceTaskState extends State { if (watchpointFunction == null) { return blockers; } - for (int i=0; i<watchpointFunction.getWatchpointCount(); i++) { - // Test if a watchpoint has fired - if (watchpointFunction.hasWatchpointTriggered(task, i)) { - if (blockers == -1) - blockers = 0; - frysk.isa.watchpoints.Watchpoint trigger = watchpointFunction.readWatchpoint(task, i); - blockers += task.notifyWatchpoint(trigger.getAddress(), trigger.getRange(), trigger.isWriteOnly()); - watchpointFunction.resetWatchpoint(task, i); - } + + List triggeredWatchpoints = watchpointFunction.getTriggeredWatchpoints(task); + Iterator i = triggeredWatchpoints.iterator(); + while (i.hasNext()) { + frysk.isa.watchpoints.Watchpoint wp = (frysk.isa.watchpoints.Watchpoint) i.next(); + if (blockers == -1) + blockers = 0; + blockers += task.notifyWatchpoint(wp.getAddress(), wp.getRange(), wp.isWriteOnly()); + watchpointFunction.resetWatchpoint(task, wp.getRegister()); } return blockers; diff --git a/frysk-core/frysk/proc/live/LinuxWaitBuilder.java b/frysk-core/frysk/proc/live/LinuxWaitBuilder.java index 39ce518..0943eb9 100644 --- a/frysk-core/frysk/proc/live/LinuxWaitBuilder.java +++ b/frysk-core/frysk/proc/live/LinuxWaitBuilder.java @@ -113,7 +113,7 @@ class LinuxWaitBuilder implements WaitBuilder { private void logMissing(String what, ProcessIdentifier pid) { String warning = ("No task for " + what + " pid " + pid + " possibly caused by earlier [test] code" - + " failing to clean up all childen"); + + " failing to clean up all children"); System.out.println("WARNING: " + warning); fine.log(warning); } diff --git a/frysk-core/frysk/proc/live/LogicalMemoryBuffer.java b/frysk-core/frysk/proc/live/LogicalMemoryBuffer.java index 5d1330b..3227a5f 100644 --- a/frysk-core/frysk/proc/live/LogicalMemoryBuffer.java +++ b/frysk-core/frysk/proc/live/LogicalMemoryBuffer.java @@ -42,7 +42,7 @@ package frysk.proc.live; import frysk.sys.ProcessIdentifier; import java.util.Iterator; import inua.eio.ByteBuffer; -import frysk.sys.ptrace.AddressSpace; +import frysk.sys.ptrace.ByteSpace; /** * MemorySpaceByteBuffer that filters out anything the frysk core @@ -51,16 +51,15 @@ import frysk.sys.ptrace.AddressSpace; * replace the bytes with the logical bytes as the user would normally * see them from the process. */ -class LogicalMemoryBuffer extends AddressSpaceByteBuffer -{ - // The breakpoints associated with the process address space. - private final BreakpointAddresses breakpoints; +class LogicalMemoryBuffer extends ByteSpaceByteBuffer { + // The breakpoints associated with the process address space. + private final BreakpointAddresses breakpoints; /** * Private constructor used by subBuffer() */ private LogicalMemoryBuffer(ProcessIdentifier tid, - AddressSpace addressSpace, + ByteSpace addressSpace, BreakpointAddresses breakpoints, long lower, long upper) { super(tid, addressSpace, lower, upper); @@ -72,99 +71,90 @@ class LogicalMemoryBuffer extends AddressSpaceByteBuffer * memory space for a task when requested. */ LogicalMemoryBuffer(ProcessIdentifier tid, - AddressSpace addressSpace, + ByteSpace addressSpace, BreakpointAddresses breakpoints) { super(tid, addressSpace); this.breakpoints = breakpoints; } - protected int peek(long caret) - { - Breakpoint breakpoint = breakpoints.getBreakpoint(caret); - if (breakpoint != null) - { - // This really shouldn't happen, it means the breakpoint - // is already uninstalled. - Instruction instruction = breakpoint.getInstruction(); - if (instruction != null) - { - byte[] ibs = instruction.getBytes(); - return ibs[0] & 0xff; - } - } - return super.peek(caret); - } - - protected int peek(long index, byte[] bytes, int offset, int length) - { - synchronized (breakpoints) - { - Iterator it; - it = breakpoints.getBreakpoints(index, index + length); - int r = 0; - while (it.hasNext()) - { - Breakpoint breakpoint = (Breakpoint) it.next(); - // address - index falls inside the byte[] so will be at most - // a positive int apart. - int l = (int) (breakpoint.getAddress() - index) - r; - // Do we need to be worried about "short peeks"? - r += super.peek(index + r, bytes, offset + r, l); - - byte b; - Instruction instruction = breakpoint.getInstruction(); + protected int peek(long caret) + { + Breakpoint breakpoint = breakpoints.getBreakpoint(caret); + if (breakpoint != null) { // This really shouldn't happen, it means the breakpoint // is already uninstalled. - if (instruction != null) - b = instruction.getBytes()[0]; - else - b = (byte) super.peek(index + r); - bytes[offset + r] = b; - r++; - } - return super.peek(index + r, bytes, offset + r, length - r) + r; - } - } - - /** - * Pokes the value at the given index. Unless a breakpoint is set at - * that location (FIXME: this limitation should be lifted). - */ - protected void poke (long index, int value) - { - Breakpoint breakpoint = breakpoints.getBreakpoint(index); - if (breakpoint != null) - throw new UnsupportedOperationException("breakpoint set at: " + index); - - super.poke(index, value); - } + Instruction instruction = breakpoint.getInstruction(); + if (instruction != null) { + byte[] ibs = instruction.getBytes(); + return ibs[0] & 0xff; + } + } + return super.peek(caret); + } - /** - * Pokes the given bytes from offset at the index plus the given - * lenght. Unless a breakpoint is set in that range (FIXME: this - * limitation should be lifted). - */ - protected int poke(long index, byte[] bytes, int offset, int length) - { - synchronized (breakpoints) - { - Iterator it; - it = breakpoints.getBreakpoints(index, index + length); - if (it.hasNext()) - throw new UnsupportedOperationException("breakpoint set between " - + index + " and " - + index + length); - } + protected int peek(long index, byte[] bytes, int offset, int length) { + synchronized (breakpoints) { + Iterator it; + it = breakpoints.getBreakpoints(index, index + length); + int r = 0; + while (it.hasNext()) { + Breakpoint breakpoint = (Breakpoint) it.next(); + // address - index falls inside the byte[] so will be at most + // a positive int apart. + int l = (int) (breakpoint.getAddress() - index) - r; + // Do we need to be worried about "short peeks"? + r += super.peek(index + r, bytes, offset + r, l); + + byte b; + Instruction instruction = breakpoint.getInstruction(); + // This really shouldn't happen, it means the breakpoint + // is already uninstalled. + if (instruction != null) + b = instruction.getBytes()[0]; + else + b = (byte) super.peek(index + r); + bytes[offset + r] = b; + r++; + } + return super.peek(index + r, bytes, offset + r, length - r) + r; + } + } + + /** + * Pokes the value at the given index. Unless a breakpoint is set + * at that location (FIXME: this limitation should be lifted). + */ + protected void poke(long index, int value) { + Breakpoint breakpoint = breakpoints.getBreakpoint(index); + if (breakpoint != null) + throw new UnsupportedOperationException("breakpoint set at: " + index); - return super.poke(index, bytes, offset, length); - } + super.poke(index, value); + } + + /** + * Pokes the given bytes from offset at the index plus the given + * lenght. Unless a breakpoint is set in that range (FIXME: this + * limitation should be lifted). + */ + protected int poke(long index, byte[] bytes, int offset, int length) { + synchronized (breakpoints) { + Iterator it; + it = breakpoints.getBreakpoints(index, index + length); + if (it.hasNext()) + throw new UnsupportedOperationException("breakpoint set between " + + index + " and " + + index + length); + } + + return super.poke(index, bytes, offset, length); + } - protected ByteBuffer subBuffer(ByteBuffer parent, - long lower, long upper) - { - LogicalMemoryBuffer sub = (LogicalMemoryBuffer) parent; - return new LogicalMemoryBuffer (sub.pid, sub.addressSpace, - sub.breakpoints, - lower, upper); - } + protected ByteBuffer subBuffer(ByteBuffer parent, + long lower, long upper) { + LogicalMemoryBuffer sub = (LogicalMemoryBuffer) parent; + return new LogicalMemoryBuffer (sub.pid, sub.addressSpace, + sub.breakpoints, + lower, upper); + } } diff --git a/frysk-core/frysk/proc/live/PtraceRegisterBanksFactory.java b/frysk-core/frysk/proc/live/PtraceRegisterBanksFactory.java index daa86d9..dea7c53 100644 --- a/frysk-core/frysk/proc/live/PtraceRegisterBanksFactory.java +++ b/frysk-core/frysk/proc/live/PtraceRegisterBanksFactory.java @@ -44,8 +44,8 @@ import inua.eio.ByteBuffer; import inua.eio.ByteOrder; import frysk.isa.ISA; import frysk.sys.ProcessIdentifier; -import frysk.sys.ptrace.RegisterSet; -import frysk.sys.ptrace.AddressSpace; +import frysk.sys.ptrace.BlockSpace; +import frysk.sys.ptrace.ByteSpace; import frysk.isa.banks.RegisterBanks; import frysk.isa.banks.X86BankRegisters; import frysk.isa.banks.PPCBankRegisters; @@ -60,9 +60,9 @@ class PtraceRegisterBanksFactory { private static ByteBuffer[] x8664Banks(ProcessIdentifier pid) { ByteBuffer[] bankBuffers = new ByteBuffer[] { - new RegisterSetByteBuffer(pid, RegisterSet.REGS), - new RegisterSetByteBuffer(pid, RegisterSet.FPREGS), - new AddressSpaceByteBuffer(pid, AddressSpace.USR) + new BlockSpaceByteBuffer(pid, BlockSpace.REGS), + new BlockSpaceByteBuffer(pid, BlockSpace.FPREGS), + new ByteSpaceByteBuffer(pid, ByteSpace.USR) }; for (int i = 0; i < bankBuffers.length; i++) { bankBuffers[i].order(ByteOrder.LITTLE_ENDIAN); @@ -72,10 +72,10 @@ class PtraceRegisterBanksFactory { private static ByteBuffer[] ia32Banks(ProcessIdentifier pid) { ByteBuffer[] bankBuffers = new ByteBuffer[] { - new RegisterSetByteBuffer(pid, RegisterSet.REGS), - new RegisterSetByteBuffer(pid, RegisterSet.FPREGS), - new RegisterSetByteBuffer(pid, RegisterSet.FPXREGS), - new AddressSpaceByteBuffer(pid, AddressSpace.USR) + new BlockSpaceByteBuffer(pid, BlockSpace.REGS), + new BlockSpaceByteBuffer(pid, BlockSpace.FPREGS), + new BlockSpaceByteBuffer(pid, BlockSpace.FPXREGS), + new ByteSpaceByteBuffer(pid, ByteSpace.USR) }; for (int i = 0; i < bankBuffers.length; i++) { bankBuffers[i].order(ByteOrder.LITTLE_ENDIAN); @@ -85,7 +85,7 @@ class PtraceRegisterBanksFactory { private static ByteBuffer[] ppcBanksBE(ProcessIdentifier pid) { ByteBuffer[] bankBuffers = new ByteBuffer[] { - new AddressSpaceByteBuffer(pid, AddressSpace.USR) + new ByteSpaceByteBuffer(pid, ByteSpace.USR) }; for (int i = 0; i < bankBuffers.length; i++) { diff --git a/frysk-core/frysk/proc/live/RegisterSetByteBuffer.java b/frysk-core/frysk/proc/live/RegisterSetByteBuffer.java deleted file mode 100644 index 6b2c1ff..0000000 --- a/frysk-core/frysk/proc/live/RegisterSetByteBuffer.java +++ /dev/null @@ -1,131 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2006, 2007, 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.proc.live; - -import frysk.sys.ptrace.RegisterSet; -import frysk.event.Request; -import frysk.proc.Manager; -import inua.eio.ByteBuffer; -import frysk.sys.ProcessIdentifier; - -/* - * A ByteBuffer interface to structures returned by ptrace which must - * be read or written all at once e.g., the registers or floating - * point registers. - */ -public class RegisterSetByteBuffer - extends ByteBuffer -{ - private final ProcessIdentifier pid; - private final RegisterSet registerSet; - private final byte[] bytes; - - private RegisterSetByteBuffer(ProcessIdentifier pid, - RegisterSet registerSet, - long lowerExtreem, long upperExtreem) { - super(lowerExtreem, upperExtreem); - this.pid = pid; - this.registerSet = registerSet; - bytes = new byte[registerSet.length()]; - } - public RegisterSetByteBuffer(ProcessIdentifier pid, - RegisterSet registerSet) { - this(pid, registerSet, 0, registerSet.length()); - } - - private class TransferRequest extends Request { - TransferRequest() { - super(Manager.eventLoop); - } - private boolean write; - public final void execute() { - registerSet.transfer(pid, bytes, write); - } - private void request(boolean write) { - if (isEventLoopThread()) { - registerSet.transfer(pid, bytes, write); - } else { - synchronized (this) { - this.write = write; - super.request(); - } - } - } - void getRegs() { - request(false); // read - } - void setRegs() { - request(true); // write - } - } - private final TransferRequest transfer = new TransferRequest(); - - protected int peek(long index) { - transfer.getRegs(); - return bytes[(int)index]; - } - - protected void poke(long index, int value) { - transfer.getRegs(); - bytes[(int)index] = (byte)value; - transfer.setRegs(); - } - - protected int peek(long index, byte[] bytes, int off, int len) { - transfer.getRegs(); - System.arraycopy(this.bytes, (int) index, bytes, off, len); - return len; - } - - protected int poke(long index, byte[] bytes, int off, int len) { - transfer.getRegs(); - System.arraycopy(bytes, off, this.bytes, (int) index, len); - transfer.setRegs(); - return len; - } - - protected ByteBuffer subBuffer (ByteBuffer parent, long lowerExtreem, - long upperExtreem) - { - RegisterSetByteBuffer up = (RegisterSetByteBuffer)parent; - return new RegisterSetByteBuffer (up.pid, up.registerSet, - lowerExtreem, upperExtreem); - } -} diff --git a/frysk-core/frysk/proc/live/TestByteBuffer.java b/frysk-core/frysk/proc/live/TestByteBuffer.java index 1983682..f318b90 100644 --- a/frysk-core/frysk/proc/live/TestByteBuffer.java +++ b/frysk-core/frysk/proc/live/TestByteBuffer.java @@ -47,15 +47,13 @@ import frysk.proc.dummy.DummyProc; import frysk.testbed.ForkFactory; import frysk.testbed.DaemonBlockedAtEntry; import frysk.testbed.LocalMemory; -import frysk.sys.ptrace.RegisterSet; -import frysk.sys.ptrace.AddressSpace; +import frysk.sys.ptrace.BlockSpace; +import frysk.sys.ptrace.ByteSpace; import frysk.proc.Manager; import frysk.sys.ProcessIdentifier; import java.util.Arrays; -public class TestByteBuffer - extends TestCase -{ +public class TestByteBuffer extends TestCase { // There are 2 sets of byte buffers to check, those that hold memory // and those that hold various register values. private ByteBuffer[] addressBuffers; @@ -69,9 +67,9 @@ public class TestByteBuffer // Text and Data are the same, but can be accessed independently. ByteBuffer addressSpaceByteBufferText - = new AddressSpaceByteBuffer(pid, AddressSpace.TEXT); + = new ByteSpaceByteBuffer(pid, ByteSpace.TEXT); ByteBuffer addressSpaceByteBufferData - = new AddressSpaceByteBuffer(pid, AddressSpace.DATA); + = new ByteSpaceByteBuffer(pid, ByteSpace.DATA); // Cheat with the proc, it is not actually used if no // breakpoints are set (testing with breakpoints set is done @@ -80,7 +78,7 @@ public class TestByteBuffer Proc proc = new DummyProc(); BreakpointAddresses breakpoints = new BreakpointAddresses(proc); ByteBuffer memorySpaceByteBuffer - = new LogicalMemoryBuffer(pid, AddressSpace.TEXT, breakpoints); + = new LogicalMemoryBuffer(pid, ByteSpace.TEXT, breakpoints); addressBuffers = new ByteBuffer[] { addressSpaceByteBufferText, addressSpaceByteBufferData, @@ -88,18 +86,18 @@ public class TestByteBuffer // The USER area is seen as a register buffer. ByteBuffer usrByteBuffer - = new AddressSpaceByteBuffer(pid, AddressSpace.USR); + = new ByteSpaceByteBuffer(pid, ByteSpace.USR); // See how many other register sets there are. - if (RegisterSet.REGS != null) { + if (BlockSpace.REGS != null) { ByteBuffer registerByteBuffer - = new RegisterSetByteBuffer(pid, RegisterSet.REGS); - if (RegisterSet.FPREGS != null) { + = new BlockSpaceByteBuffer(pid, BlockSpace.REGS); + if (BlockSpace.FPREGS != null) { ByteBuffer fpregisterByteBuffer - = new RegisterSetByteBuffer(pid, RegisterSet.FPREGS); - if (RegisterSet.FPXREGS != null) { + = new BlockSpaceByteBuffer(pid, BlockSpace.FPREGS); + if (BlockSpace.FPXREGS != null) { ByteBuffer fpxregisterByteBuffer - = new RegisterSetByteBuffer(pid, RegisterSet.FPXREGS); + = new BlockSpaceByteBuffer(pid, BlockSpace.FPXREGS); registerBuffers = new ByteBuffer[] { usrByteBuffer, registerByteBuffer, fpregisterByteBuffer, @@ -118,17 +116,15 @@ public class TestByteBuffer } } - public void tearDown() throws Exception - { - addressBuffers = null; - registerBuffers = null; + public void tearDown() throws Exception { + addressBuffers = null; + registerBuffers = null; - // Clean up any left stuff processes/open files/etc. - super.tearDown(); + // Clean up any left stuff processes/open files/etc. + super.tearDown(); } - public void verifySlice(ByteBuffer buffer, long addr, int length) - { + public void verifySlice(ByteBuffer buffer, long addr, int length) { ByteBuffer slice = buffer.slice (addr, length); byte bytes[] = new byte[length]; buffer.get (addr, bytes, 0, length); @@ -138,37 +134,32 @@ public class TestByteBuffer } } - public void testSliceAddressBuffers() - { - for (int i = 0; i < addressBuffers.length; i++) - verifySlice(addressBuffers[i], LocalMemory.getCodeAddr(), - LocalMemory.getCodeBytes().length); + public void testSliceAddressBuffers() { + for (int i = 0; i < addressBuffers.length; i++) + verifySlice(addressBuffers[i], LocalMemory.getCodeAddr(), + LocalMemory.getCodeBytes().length); } - public void testSliceRegisterBuffers() - { - for (int i = 0; i < registerBuffers.length; i++) - verifySlice(registerBuffers[i], 4, 4); + public void testSliceRegisterBuffers() { + for (int i = 0; i < registerBuffers.length; i++) + verifySlice(registerBuffers[i], 4, 4); } - private void verifyModify(ByteBuffer buffer, long addr) - { + private void verifyModify(ByteBuffer buffer, long addr) { // Read, modify, read. byte oldByte = buffer.get(addr); buffer.putByte(addr, (byte)~oldByte); assertEquals ("modified", (byte)~oldByte, buffer.get(addr)); } - public void testModifyRegisterBuffers() - { - for (int i = 0; i < registerBuffers.length; i++) - verifyModify(registerBuffers[i], 0); + public void testModifyRegisterBuffers() { + for (int i = 0; i < registerBuffers.length; i++) + verifyModify(registerBuffers[i], 0); } - public void testModifyAddressBuffers() - { - for (int i = 0; i < addressBuffers.length; i++) - verifyModify(addressBuffers[i], LocalMemory.getCodeAddr()); + public void testModifyAddressBuffers() { + for (int i = 0; i < addressBuffers.length; i++) + verifyModify(addressBuffers[i], LocalMemory.getCodeAddr()); } private void verifyAsyncModify(ByteBuffer buffer, long addr) { @@ -218,71 +209,61 @@ public class TestByteBuffer } } public void testAsyncRegisterBuffers() { - for (int i = 0; i < registerBuffers.length; i++) - verifyAsyncModify(registerBuffers[0], 0); + for (int i = 0; i < registerBuffers.length; i++) + verifyAsyncModify(registerBuffers[0], 0); } public void testAsyncAddressBuffers() { - for (int i = 0; i < addressBuffers.length; i++) - verifyAsyncModify(addressBuffers[i], - LocalMemory.getCodeAddr()); + for (int i = 0; i < addressBuffers.length; i++) + verifyAsyncModify(addressBuffers[i], + LocalMemory.getCodeAddr()); } - public void verifyPeeks(ByteBuffer buffer, long addr, byte[] origBytes) - { - byte bytes[] = new byte[origBytes.length]; - buffer.get(addr, bytes, 0, bytes.length); - for (int i = 0; i < bytes.length; i++) - assertEquals ("byte at " + i, bytes[i], origBytes[i]); + public void verifyPeeks(ByteBuffer buffer, long addr, byte[] origBytes) { + byte bytes[] = new byte[origBytes.length]; + buffer.get(addr, bytes, 0, bytes.length); + for (int i = 0; i < bytes.length; i++) + assertEquals ("byte at " + i, bytes[i], origBytes[i]); } - public void testAddressBufferPeeks() - { - long addr = LocalMemory.getCodeAddr(); - byte[] origBytes = LocalMemory.getCodeBytes(); - for (int i = 0; i < addressBuffers.length; i++) - verifyPeeks(addressBuffers[i], addr, origBytes); + public void testAddressBufferPeeks() { + long addr = LocalMemory.getCodeAddr(); + byte[] origBytes = LocalMemory.getCodeBytes(); + for (int i = 0; i < addressBuffers.length; i++) + verifyPeeks(addressBuffers[i], addr, origBytes); } - public void testRegisterBufferPeeks() - { - // Check that simple get loop is similar to bulk get. - long addr = 4; - byte[] origBytes = new byte[16]; - for (int i = 0; i < registerBuffers.length; i++) - { - for (int j = 0; j < origBytes.length; j++) - origBytes[j] = registerBuffers[i].get(addr + j); - verifyPeeks(registerBuffers[i], addr, origBytes); + public void testRegisterBufferPeeks() { + // Check that simple get loop is similar to bulk get. + long addr = 4; + byte[] origBytes = new byte[16]; + for (int i = 0; i < registerBuffers.length; i++) { + for (int j = 0; j < origBytes.length; j++) + origBytes[j] = registerBuffers[i].get(addr + j); + verifyPeeks(registerBuffers[i], addr, origBytes); } } - private class AsyncPeeks - implements Runnable - { + private class AsyncPeeks implements Runnable { private ByteBuffer buffer; private long addr; private int length; private byte[] bytes; private Exception e; - AsyncPeeks (ByteBuffer buffer, long addr, int length) - { + AsyncPeeks (ByteBuffer buffer, long addr, int length) { this.buffer = buffer; this.addr = addr; this.length = length; this.bytes = new byte[length]; } - public void run () - { + public void run() { try { buffer.get (addr, bytes, 0, length); - } - catch (Exception e) { + } catch (Exception e) { this.e = e; } Manager.eventLoop.requestStop(); } - void call (byte[] origBytes) - { + void call (byte[] origBytes) { // Force the event loop to running on this thread. Ugly, and is to // to be removed when bug #4688 is resolved. Manager.eventLoop.runPolling(1); @@ -297,71 +278,64 @@ public class TestByteBuffer } } - public void testAsyncPeeks () - { - byte[] origBytes = LocalMemory.getCodeBytes(); - for (int i = 0; i < addressBuffers.length; i++) - new AsyncPeeks(addressBuffers[i], LocalMemory.getCodeAddr(), - LocalMemory.getCodeBytes().length).call(origBytes); + public void testAsyncPeeks() { + byte[] origBytes = LocalMemory.getCodeBytes(); + for (int i = 0; i < addressBuffers.length; i++) + new AsyncPeeks(addressBuffers[i], LocalMemory.getCodeAddr(), + LocalMemory.getCodeBytes().length).call(origBytes); } - public void testAsycnPeeksRegisters() - { - // Check position() and (async) get() - int length = 8; - byte[] origBytes = new byte[length]; - long address = 4; - for (int i = 0; i < registerBuffers.length; i++) - { - registerBuffers[i].position(address); - registerBuffers[i].get(origBytes); - new AsyncPeeks(registerBuffers[i], address, - length).call(origBytes); + public void testAsycnPeeksRegisters() { + // Check position() and (async) get() + int length = 8; + byte[] origBytes = new byte[length]; + long address = 4; + for (int i = 0; i < registerBuffers.length; i++) { + registerBuffers[i].position(address); + registerBuffers[i].get(origBytes); + new AsyncPeeks(registerBuffers[i], address, + length).call(origBytes); } } - private void verifyBulkPut(ByteBuffer buffer, long addr, int len) - { - // Pasting the same bytes back over the old buffer in bulk - // and read it back in. - byte[] oldBytes = new byte[len]; - buffer.position(addr); - buffer.get(oldBytes); - buffer.position(addr); - buffer.put(oldBytes); - byte[] newBytes = new byte[len]; - buffer.position(addr); - buffer.get(newBytes); - assertTrue(Arrays.equals(oldBytes, newBytes)); - } + private void verifyBulkPut(ByteBuffer buffer, long addr, int len) { + // Pasting the same bytes back over the old buffer in bulk + // and read it back in. + byte[] oldBytes = new byte[len]; + buffer.position(addr); + buffer.get(oldBytes); + buffer.position(addr); + buffer.put(oldBytes); + byte[] newBytes = new byte[len]; + buffer.position(addr); + buffer.get(newBytes); + assertTrue(Arrays.equals(oldBytes, newBytes)); + } - public void testBulkPutRegisterBuffers() - { - for (int i = 0; i < registerBuffers.length; i++) - verifyBulkPut(registerBuffers[i], 4, 4); - } + public void testBulkPutRegisterBuffers() { + for (int i = 0; i < registerBuffers.length; i++) + verifyBulkPut(registerBuffers[i], 4, 4); + } - public void testBulkPutAddressBuffers() - { - for (int i = 0; i < addressBuffers.length; i++) - verifyBulkPut(addressBuffers[i], LocalMemory.getCodeAddr(), - LocalMemory.getCodeBytes().length); - } + public void testBulkPutAddressBuffers() { + for (int i = 0; i < addressBuffers.length; i++) + verifyBulkPut(addressBuffers[i], LocalMemory.getCodeAddr(), + LocalMemory.getCodeBytes().length); + } - public void testMemoryBufferCapacity() - { - Task task = new DaemonBlockedAtEntry("funit-slave").getMainTask(); - switch(task.getISA().wordSize()){ + public void testMemoryBufferCapacity() { + Task task = new DaemonBlockedAtEntry("funit-slave").getMainTask(); + switch(task.getISA().wordSize()){ case 4: - assertEquals("Memory Buffer Capacity: ", 0xffffffffL, - task.getMemory().capacity()); - break; + assertEquals("Memory Buffer Capacity: ", 0xffffffffL, + task.getMemory().capacity()); + break; case 8: - assertEquals("Memory Buffer Capacity: ", 0xffffffffffffffffL, - task.getMemory().capacity()); - break; + assertEquals("Memory Buffer Capacity: ", 0xffffffffffffffffL, + task.getMemory().capacity()); + break; default: - fail("unknown word size"); + fail("unknown word size"); } } diff --git a/frysk-core/frysk/rt/ChangeLog b/frysk-core/frysk/rt/ChangeLog index 5622595..b438129 100644 --- a/frysk-core/frysk/rt/ChangeLog +++ b/frysk-core/frysk/rt/ChangeLog @@ -1,4 +1,17 @@ -2008-06-06 Teresa Thomas <tthomas@redhat.com> +2008-06-17 Teresa Thomas <tthomas@redhat.com> + + * WatchObserverInstaller.java + (WatchpointObserver.updateHit): Print message if value + unchanged before and after access. + (install): Throw exception if numberOfObservers + calculated is 0. + +2008-06-11 Teresa Thomas <tthomas@redhat.com> + + * WatchObserverInstaller.java (install): Use Location.length() + instead of Type.getSize(). + +2008-06-06 Teresa Thomas <tthomas@redhat.com> * Breakpoint.java (updateHit): Update log message. diff --git a/frysk-core/frysk/rt/WatchObserverInstaller.java b/frysk-core/frysk/rt/WatchObserverInstaller.java index df0034d..1d376b3 100644 --- a/frysk-core/frysk/rt/WatchObserverInstaller.java +++ b/frysk-core/frysk/rt/WatchObserverInstaller.java @@ -91,8 +91,8 @@ public class WatchObserverInstaller { (task.getISA()).getWatchpointMaxLength(); long variableAddress = expr.getLocation().getAddress(); - int variableLength = expr.getType().getSize(); - + int variableLength = (int)expr.getLocation().length(); + if (variableLength > (watchpointCount-watchpointsInUse) * maxWatchLength ) { throw new RuntimeException ("Watch error: Available watchpoints not " + "sufficient to watch complete value."); @@ -102,6 +102,11 @@ public class WatchObserverInstaller { // to completely watch the variable. int numberOfObservers = (int)Math.ceil((double)variableLength/ (double)maxWatchLength); + + if (numberOfObservers == 0) { + throw new RuntimeException ("Error: Watchpoint cannot be installed"); + } + int observerNumber = 1; // Add watchpoint observers to task. @@ -156,11 +161,15 @@ public class WatchObserverInstaller { public Action updateHit(Task task, long address, int length) { String newValue = expr.getValue().toPrint - (Format.NATURAL, task.getMemory()); + (Format.NATURAL, task.getMemory()); String watchMessage = "Watchpoint hit: " + exprString + "\n" + " Value before hit = " + oldValue + "\n" + " Value after hit = " + newValue + "\n"; + + if (oldValue.equals(newValue)) { + watchMessage += "Note: Value unchanged before and after access\n"; + } // Remember the previous value oldValue = newValue; diff --git a/frysk-core/frysk/scopes/ChangeLog b/frysk-core/frysk/scopes/ChangeLog index 670e7f5..ff21a6f 100644 --- a/frysk-core/frysk/scopes/ChangeLog +++ b/frysk-core/frysk/scopes/ChangeLog @@ -1,3 +1,8 @@ +2008-06-10 Andrew Cagney <cagney@redhat.com> + + * Function.java (printParameters): Add boolean printValues + parameter. + 2008-06-06 Andrew Cagney <cagney@redhat.com> * TestScopeFactory.java: Let DwflDie adjust for bias. diff --git a/frysk-core/frysk/scopes/Function.java b/frysk-core/frysk/scopes/Function.java index 71d3f8a..cc4c426 100644 --- a/frysk-core/frysk/scopes/Function.java +++ b/frysk-core/frysk/scopes/Function.java @@ -227,19 +227,17 @@ public class Function extends NamedScope { } - public void printParameters (PrintWriter writer, DebugInfoFrame frame) - { - - Iterator iterator = this.parameters.iterator(); - while(iterator.hasNext()) { - Variable parameter = (Variable) iterator.next(); - parameter.toPrint(writer, frame); - writer.flush(); - if(parameters.indexOf(parameter) < (this.parameters.size()-1)){ - writer.print(","); - } - } - + public void printParameters(PrintWriter writer, DebugInfoFrame frame, + boolean printValues) { + Iterator iterator = this.parameters.iterator(); + while(iterator.hasNext()) { + Variable parameter = (Variable) iterator.next(); + parameter.toPrint(writer, frame); + writer.flush(); + if(parameters.indexOf(parameter) < (this.parameters.size()-1)){ + writer.print(","); + } + } } } diff --git a/frysk-core/frysk/solib/ChangeLog b/frysk-core/frysk/solib/ChangeLog index c1f7205..529a5a1 100644 --- a/frysk-core/frysk/solib/ChangeLog +++ b/frysk-core/frysk/solib/ChangeLog @@ -1,3 +1,8 @@ +2008-06-23 Rick Moseley <rmoseley@redhat.com> + + * DynamicSegment.java: Made getEntryPoint public. + + 2008-03-10 Andrew Cagney <cagney@redhat.com> * MemoryMapFactory.java: Update to match MemoryMap. diff --git a/frysk-core/frysk/solib/DynamicSegment.java b/frysk-core/frysk/solib/DynamicSegment.java index e773894..d9a98c5 100644 --- a/frysk-core/frysk/solib/DynamicSegment.java +++ b/frysk-core/frysk/solib/DynamicSegment.java @@ -51,7 +51,7 @@ import frysk.proc.Auxv; * to extract the information are all closed. */ -class DynamicSegment { +public class DynamicSegment { private static final Log fine = Log.fine(DynamicSegment.class); final long addr; @@ -99,7 +99,7 @@ class DynamicSegment { * Helper function to locate and report the backing Executables * entry point */ - private static long getEntryPoint(Elf exeElf) { + public static long getEntryPoint(Elf exeElf) { fine.log("getEntryPoint", exeElf); ElfEHeader eHeader = exeElf.getEHeader(); if (eHeader == null) diff --git a/frysk-core/frysk/stack/ChangeLog b/frysk-core/frysk/stack/ChangeLog index 4f95b4b..8e99fc2 100644 --- a/frysk-core/frysk/stack/ChangeLog +++ b/frysk-core/frysk/stack/ChangeLog @@ -1,3 +1,22 @@ +2008-06-11 Andrew Cagney <cagney@redhat.com> + + * Frame.java: Drop space in "function ()". + +2008-06-10 Andrew Cagney <cagney@redhat.com> + + * Frame.java (toPrint): Use printLibraryPaths. + * PrintStackOptions.java (printLibraryPaths): Replace printFullPaths. + (setPrintPaths(boolean)): New. + + * Frame.java (printLibraryName(PrintWriter,PrintStackOptions)): New. + (toPrint(PrintWriter,PrintStackOptions)): Use. + + * Frame.java (toPrint(PrintWriter,PrintStackOptions)): Replace + toPrint(PrintWriter,boolean,boolean). + (toPrint(PrintWriter)): Delete. + * PrintStackOptions.java: New. + * StackFactory.java: Use. + 2008-06-03 Andrew Cagney <cagney@redhat.com> * TestFrame.java: Use DwflModule.getModules() and not diff --git a/frysk-core/frysk/stack/Frame.java b/frysk-core/frysk/stack/Frame.java index 285aee7..6ba3dc1 100644 --- a/frysk-core/frysk/stack/Frame.java +++ b/frysk-core/frysk/stack/Frame.java @@ -46,7 +46,6 @@ import java.io.StringWriter; import lib.dwfl.Dwfl; import lib.dwfl.DwflModule; import frysk.dwfl.DwflCache; -import frysk.dwfl.DwflFactory; import frysk.isa.registers.Register; import frysk.proc.Task; import frysk.rsl.Log; @@ -150,43 +149,45 @@ public abstract class Frame { * Write a simple string representation of this stack frame. * @param printWriter */ - public void toPrint (PrintWriter writer) { - toPrint(writer, true, true); - } - - /** - * Write a simple string representation of this stack frame. - * @param printWriter - */ - public void toPrint (PrintWriter writer, boolean printSource, boolean fullpath) { + public void toPrint(PrintWriter writer, PrintStackOptions options) { writer.write(ArchFormatter.toHexString(getTask(), getAddress())); // the symbol, if known append (), .. Symbol symbol = getSymbol(); writer.write(" in "); writer.write(symbol.getDemangledName()); - if (symbol != SymbolFactory.UNKNOWN) - writer.write(" ()"); - - if(printSource){ + if (symbol != SymbolFactory.UNKNOWN) { + // XXX: Perhaps this should not print the (). + writer.write("()"); + } + printLibraryName(writer, options); + } + + /** + * If requrested by the stack options, print the library name + * using the form " from LIBRARY". + */ + protected void printLibraryName(PrintWriter writer, + PrintStackOptions options) { + if (options.printLibraryNames()) { // the library if known ... - File library = new File(getLibraryName()); + String library = getLibraryName(); if (library != null) { writer.print(" from "); - - if(DwflFactory.isVDSO(this.getTask().getProc(), this.getTask().getProc().getMap(getAdjustedAddress())) - || library.getName().contains("[stack]")){ - writer.print(library.getName()); - }else{ - - if(fullpath){ - writer.print(library.getPath()); - }else{ - writer.print(".../"+library.getName()); + if (library.startsWith("[")) { + // Things like [vdso], [stack], ... + writer.print(library); + } else { + // Should there be separate libraryFullPath? + if (options.printLibraryPaths()) { + writer.print(library); + } else { + // Discard the path + writer.print(new File(library).getName()); } } } - } + } } public String getLibraryName() { @@ -195,7 +196,7 @@ public abstract class Frame { if (dwflModule != null) { return dwflModule.getName(); } else { - return "Unknown"; + return null; } } @@ -209,7 +210,7 @@ public abstract class Frame { PrintWriter pw = new PrintWriter(sw); pw.print(this.getClass().getName()); pw.print('['); - toPrint(pw, false, false); + toPrint(pw, PrintStackOptions.DEFAULT); pw.print(']'); pw.flush(); return sw.toString(); diff --git a/frysk-core/frysk/stack/PrintStackOptions.java b/frysk-core/frysk/stack/PrintStackOptions.java new file mode 100644 index 0000000..2e3f161 --- /dev/null +++ b/frysk-core/frysk/stack/PrintStackOptions.java @@ -0,0 +1,110 @@ +// This file is part of the program FRYSK. +// +// Copyright 2007, 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; + +public class PrintStackOptions { + + static final PrintStackOptions DEFAULT = new PrintStackOptions(); + + private int numberOfFrames = 10; + + private boolean printLibraryPaths; + private boolean printLibraryNames; + + public PrintStackOptions() { + clear(); + } + + /** + * Clear all stack options, a very raw ABI stack trace will be + * produced. + */ + public void clear() { + printLibraryPaths = false; + printLibraryNames = false; + } + + /** + * Generate an ABI backtrace using ELF symbols and shared library + * names. + */ + public void setAbi() { + clear(); + printLibraryPaths = false; + printLibraryNames = true; + } + + /** + * Include the full path to any files. + */ + public void setPrintPaths(boolean printPaths) { + setPrintLibraryPaths(printPaths); + } + + /** + * Specify the number of frames to include in the back-trace, 0 to + * include all frames. + */ + public void setNumberOfFrames(int numberOfFrames) { + this.numberOfFrames = numberOfFrames; + } + public int numberOfFrames() { + return numberOfFrames; + } + + public void setPrintLibraryPaths(boolean printLibraryPaths) { + this.printLibraryPaths = printLibraryPaths; + } + public boolean printLibraryPaths() { + return printLibraryPaths; + } + + public void setPrintLibraryNames(boolean printLibraryNames) { + this.printLibraryNames = printLibraryNames; + } + public boolean printLibraryNames() { + return printLibraryNames; + } + + public boolean abiOnly() { + return true; + } + +} diff --git a/frysk-core/frysk/stack/StackFactory.java b/frysk-core/frysk/stack/StackFactory.java index 358adb2..c1e05e5 100644 --- a/frysk-core/frysk/stack/StackFactory.java +++ b/frysk-core/frysk/stack/StackFactory.java @@ -44,7 +44,6 @@ import java.io.PrintWriter; import java.util.WeakHashMap; import lib.unwind.Cursor; -import frysk.debuginfo.PrintStackOptions; import frysk.proc.Task; public class StackFactory @@ -87,23 +86,25 @@ public class StackFactory } public static final void printTaskStackTrace(PrintWriter writer, - Task task, PrintStackOptions options) { + Task task, + PrintStackOptions options) { if (task != null) { writer.print("Task #"); writer.print(task.getTid()); writer.println(); Frame frame = StackFactory.createFrame(task); for (int i = 0; frame != null; frame = frame.getOuter(),i++) { - - if (options.numberOfFrames() > 0 && i >= options.numberOfFrames()) { + if (options.numberOfFrames() > 0 + && i >= options.numberOfFrames()) { writer.println("..."); break; + } else if (options.numberOfFrames() < 0 + && i >= -options.numberOfFrames()) { + break; } - frame.printLevel(writer); writer.print(" "); - frame.toPrint(writer, options.printLibraries(), - options.printFullPaths()); + frame.toPrint(writer, options); writer.println(); } } @@ -114,7 +115,7 @@ public class StackFactory for (; frame != null; frame = frame.getOuter()) { frame.printLevel(writer); writer.print(" "); - frame.toPrint(writer); + frame.toPrint(writer, PrintStackOptions.DEFAULT); writer.println(); } } diff --git a/frysk-core/frysk/symtab/ChangeLog b/frysk-core/frysk/symtab/ChangeLog index ba96d4e..33bc6fb 100644 --- a/frysk-core/frysk/symtab/ChangeLog +++ b/frysk-core/frysk/symtab/ChangeLog @@ -1,3 +1,13 @@ +2008-06-19 Andrew Cagney <cagney@redhat.com> + + * TestSymbol.java (testNoSymbolAfterGlobal()): Enable. + (testNoSymbolAfterLocal()): Enable. + (testAfterGlobalContiningSize0()): Enable. + (testAfterLocalContiningSize0()): Enable. + + * TestSymbol.java: Re-number arg param so that matching + funit-symbols.S is easier. + 2008-06-05 Andrew Cagney <cagney@redhat.com> * DwflSymbol.java: Use DwflDie. diff --git a/frysk-core/frysk/symtab/TestSymbol.java b/frysk-core/frysk/symtab/TestSymbol.java index 79bf39a..a0228b3 100644 --- a/frysk-core/frysk/symtab/TestSymbol.java +++ b/frysk-core/frysk/symtab/TestSymbol.java @@ -46,13 +46,13 @@ import frysk.testbed.DaemonBlockedAtSignal; public class TestSymbol extends TestLib { - private void symbolTest (String command, int numberOfArgs, - String name, boolean addressValid, - boolean sizeValid) { - // Construct an argument list containing numberOfArgs dummy - // arguments. The inferior program just looks at ARGC to - // determine what to do. - String[] fullCommand = new String[numberOfArgs + 1]; + private void symbolTest(String command, int numberOfArgs, + String name, boolean addressValid, + boolean sizeValid) { + // Construct an argument list numberOfArgs long (including + // arg[0] the program). The inferior program just looks at + // ARGC to determine what to do. + String[] fullCommand = new String[numberOfArgs]; fullCommand[0] = getExecPath (command); for (int i = 1; i < fullCommand.length; i++) { fullCommand[i] = Integer.toString(i); @@ -80,128 +80,120 @@ public class TestSymbol private String unknown = SymbolFactory.UNKNOWN.getName (); public void testDebug () { - symbolTest("funit-symbols", 1, "global_st_size", true, true); + symbolTest("funit-symbols", 2, "global_st_size", true, true); } public void testNoDebug () { - symbolTest("funit-symbols-nodebug", 1, "global_st_size", true, true); + symbolTest("funit-symbols-nodebug", 2, "global_st_size", true, true); } public void testStripped () { - symbolTest("funit-symbols-stripped", 1, unknown, false, false); + symbolTest("funit-symbols-stripped", 2, unknown, false, false); } public void testStaticDebug () { - symbolTest("funit-symbols", 2, "local_st_size", true, true); + symbolTest("funit-symbols", 3, "local_st_size", true, true); } public void testStaticNoDebug () { - symbolTest("funit-symbols-nodebug", 2, "local_st_size", true, true); + symbolTest("funit-symbols-nodebug", 3, "local_st_size", true, true); } public void testStaticStripped () { - symbolTest("funit-symbols-stripped", 2, unknown, false, false); + symbolTest("funit-symbols-stripped", 3, unknown, false, false); } public void testNoSize() { - symbolTest("funit-symbols", 3, "global_st_size_0", true, false); + symbolTest("funit-symbols", 4, "global_st_size_0", true, false); } public void testNoDebugNoSize() { - symbolTest("funit-symbols-nodebug", 3, "global_st_size_0", + symbolTest("funit-symbols-nodebug", 4, "global_st_size_0", true, false); } public void testStrippedNoSize() { - symbolTest("funit-symbols-stripped", 3, unknown, false, false); + symbolTest("funit-symbols-stripped", 4, unknown, false, false); } public void testStaticNoSize() { - symbolTest("funit-symbols", 4, "local_st_size_0", true, false); + symbolTest("funit-symbols", 5, "local_st_size_0", true, false); } public void testStaticNoDebugNoSize() { - symbolTest("funit-symbols-nodebug", 4, "local_st_size_0", true, false); + symbolTest("funit-symbols-nodebug", 5, "local_st_size_0", true, false); } public void testStaticStrippedNoSize() { - symbolTest("funit-symbols-stripped", 4, unknown, false, false); + symbolTest("funit-symbols-stripped", 5, unknown, false, false); } public void testGlobalInGlobal() { - symbolTest(5, "global_in_global", true, true); + symbolTest(6, "global_in_global", true, true); } public void testLocalInGlobal() { if (unresolved(5941)) return; - symbolTest(6, "local_in_global", true, true); + symbolTest(7, "local_in_global", true, true); } public void testGlobalInLocal() { - symbolTest(7, "global_in_local", true, true); + symbolTest(8, "global_in_local", true, true); } public void testLocalInLocal() { - symbolTest(8, "local_in_local", true, true); + symbolTest(9, "local_in_local", true, true); } public void testGlobalAfterNested() { - symbolTest(9, "global_outer", true, true); + symbolTest(10, "global_outer", true, true); } public void testLocalAfterNested() { - symbolTest(10, "local_outer", true, true); + symbolTest(11, "local_outer", true, true); } public void testNoSymbolAfterGlobal() { - if (unresolved(5941)) - return; - symbolTest(11, unknown, false, false); + symbolTest(12, unknown, false, false); } public void testNoSymbolAfterLocal() { - if (unresolved(5941)) - return; - symbolTest(12, unknown, false, false); + symbolTest(13, unknown, false, false); } public void testGlobalSize0InGlobal() { - symbolTest(13, "global_after_0", true, true); + symbolTest(14, "global_after_0", true, true); } public void testLocalSize0InGlobal() { - symbolTest(14, "global_after_0", true, true); + symbolTest(15, "global_after_0", true, true); } public void testGlobalSize0InLocal() { - symbolTest(15, "local_after_0", true, true); + symbolTest(16, "local_after_0", true, true); } public void testLocalSize0InLocal() { - symbolTest(16, "local_after_0", true, true); + symbolTest(17, "local_after_0", true, true); } public void testGlobalAfterNestedSize0() { - symbolTest(17, "global_after_0", true, true); + symbolTest(18, "global_after_0", true, true); } public void testLocalAfterNestedSize0() { - symbolTest(18, "local_after_0", true, true); + symbolTest(19, "local_after_0", true, true); } public void testSmallGlobalAtLargeGlobal() { - symbolTest(19, "small_global_at_large_global", true, true); + symbolTest(20, "small_global_at_large_global", true, true); } public void testSmallLocalAtLargeGlobal() { if (unresolved(5941)) return; - symbolTest(20, "small_local_at_large_global", true, true); + symbolTest(21, "small_local_at_large_global", true, true); } public void testSmallGlobalAtLargeLocal() { - symbolTest(21, "small_global_at_large_local", true, true); + symbolTest(22, "small_global_at_large_local", true, true); } public void testSmallLocalAtLargeLocal() { - symbolTest(22, "small_local_at_large_local", true, true); + symbolTest(23, "small_local_at_large_local", true, true); } public void testAfterGlobalContiningSize0() { - if (unresolved(5941)) - return; - symbolTest(23, unknown, false, false); + symbolTest(24, unknown, false, false); } public void testAfterLocalContiningSize0() { - if (unresolved(5941)) - return; - symbolTest(24, unknown, false, false); + symbolTest(25, unknown, false, false); } } diff --git a/frysk-core/frysk/testbed/ChangeLog b/frysk-core/frysk/testbed/ChangeLog index 1babdc8..90aee82 100644 --- a/frysk-core/frysk/testbed/ChangeLog +++ b/frysk-core/frysk/testbed/ChangeLog @@ -1,3 +1,12 @@ +2008-06-11 Rick Moseley <rmoseley@redhat.com> + + * CorefileFactory.java: Change method to call + DaemonBlockedAtEntry instead of DaemonBlockedAtSignal. + +2008-06-10 Rick Moseley <rmoseley@redhat.com> + + * CorefileFactory.java: Add method to pass args. + 2008-06-06 Rick Moseley <rmoseley@redhat.com> * SlaveOffspring.java: Add methods to accept commandline args. diff --git a/frysk-core/frysk/testbed/CorefileFactory.java b/frysk-core/frysk/testbed/CorefileFactory.java index 18d9354..571869d 100644 --- a/frysk-core/frysk/testbed/CorefileFactory.java +++ b/frysk-core/frysk/testbed/CorefileFactory.java @@ -74,6 +74,21 @@ public class CorefileFactory extends TestLib { = new DaemonBlockedAtSignal(exeFile).getMainTask().getProc(); return constructCore(ackProc); } + + /** + * Given a path to an executable it will run it until it sigfaults + * then extracts a corefile at that point, and return a File + * representing that core file. + */ + public static File constructCoreAtEntry(File exeFile, String[] args) { + String[] newargs = new String[args.length + 1]; + newargs[0] = exeFile.getAbsolutePath(); + for (int i = 0; i < args.length; i++) + newargs[i+1] = args[i]; + final Proc ackProc + = new DaemonBlockedAtEntry(newargs).getMainTask().getProc(); + return constructCore(ackProc); + } /** * Given a path to an executable it will run it until it sigfaults diff --git a/frysk-core/frysk/util/ChangeLog b/frysk-core/frysk/util/ChangeLog index bf95319..30aa6e4 100644 --- a/frysk-core/frysk/util/ChangeLog +++ b/frysk-core/frysk/util/ChangeLog @@ -1,3 +1,31 @@ +2008-06-13 Petr Machata <pmachata@redhat.com> + + * Glob.java: Support ! as character set negation operator. + * TestGlob.java: New class, suite of test cases for Glob compiler. + +2008-06-12 Andrew Cagney <cagney@redhat.com> + + * CommandlineParser.java: Catch UserException, not + RuntimeException. + +2008-06-11 Andrew Cagney <cagney@redhat.com> + + * StackPrintUtil.java: Fix typo - missing \n. + + * TestStackTraceAction.java: Update to match stack backtrace. + +2008-06-10 Andrew Cagney <cagney@redhat.com> + + * TestStackTraceAction.java: Use setPrintPaths. + * stack-options.xml: Add paths, lib-paths, src-paths, values to + print options. + + * TestStackTraceAction.java: Use PrintDebugInfoStackOptions. + * StackPrintUtil.java: Ditto. + * StacktraceAction.java: Ditto. + * FCatch.java: Ditto. + * StressTestStackTraceAction.java: Ditto. + 2008-05-20 Andrew Cagney <cagney@redhat.com> * CommandlineParser.java (isCoreFile(String)) diff --git a/frysk-core/frysk/util/CommandlineParser.java b/frysk-core/frysk/util/CommandlineParser.java index d2887f8..e0c6a32 100644 --- a/frysk-core/frysk/util/CommandlineParser.java +++ b/frysk-core/frysk/util/CommandlineParser.java @@ -39,6 +39,7 @@ package frysk.util; +import frysk.UserException; import frysk.config.FryskVersion; import java.io.File; import java.util.LinkedList; @@ -160,12 +161,14 @@ public abstract class CommandlineParser { String[] result = doParse(args); validate(); return result; - } catch (Exception e) { + } catch (OptionException e) { fine.log(this, "parse failed", e); - if (e.getMessage() == null) - System.err.println("Error: " + e.toString()); - else - System.err.println("Error: " + e.getMessage()); + System.err.println("Error: " + e.getMessage()); + System.exit(1); + return null; // To fool Java + } catch (UserException e) { + fine.log(this, "external problem", e); + System.err.println("Error: " + e.getMessage()); System.exit(1); return null; // To fool Java } diff --git a/frysk-core/frysk/util/FCatch.java b/frysk-core/frysk/util/FCatch.java index 476ffe8..3157ed9 100644 --- a/frysk-core/frysk/util/FCatch.java +++ b/frysk-core/frysk/util/FCatch.java @@ -43,7 +43,7 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.util.HashMap; -import frysk.debuginfo.PrintStackOptions; +import frysk.debuginfo.PrintDebugInfoStackOptions; import frysk.isa.signals.Signal; import frysk.proc.Action; import frysk.proc.Task; @@ -54,7 +54,8 @@ import gnu.classpath.tools.getopt.OptionGroup; public class FCatch { private static final Log fine = Log.fine(FCatch.class); - private final PrintStackOptions stackPrintOptions = new PrintStackOptions(); + private final PrintDebugInfoStackOptions stackPrintOptions + = new PrintDebugInfoStackOptions(); private PrintWriter printWriter = new PrintWriter(System.out); HashMap signaledTasks = new HashMap(); diff --git a/frysk-core/frysk/util/Glob.java b/frysk-core/frysk/util/Glob.java index 96c40c4..0bb0632 100644 --- a/frysk-core/frysk/util/Glob.java +++ b/frysk-core/frysk/util/Glob.java @@ -1,6 +1,6 @@ // This file is part of the program FRYSK. // -// Copyright 2005, 2006, 2007, 2008, Red Hat Inc. +// Copyright 2007, 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 @@ -44,53 +44,57 @@ import java.util.regex.PatternSyntaxException; public class Glob { - private static int matchCharacterClass(String glob, int from) + private static int matchCharacterClass(char[] glob, int from) throws PatternSyntaxException { int i = from + 2; - while (glob.charAt(++i) != ':' && i < glob.length()) + while (glob[++i] != ':' && i < glob.length) continue; - if (i >= glob.length() || glob.charAt(++i) != ']') + if (i >= glob.length || glob[++i] != ']') throw new PatternSyntaxException - ("Unmatched '['.", glob, from); + ("Unmatched '['.", new String(glob), from); return i; } - private static int matchBrack(String glob, int from) + private static int matchBrack(char[] glob, int from) throws PatternSyntaxException { int i = from + 1; - if (glob.charAt(i) == '^') // Complement operator. + // Complement operator. + if (glob[i] == '^') ++i; + else if (glob[i] == '!') + glob[i++] = '^'; // On first character, both [ and ] are legal. But when [ is // foolowed with :, it's character class. - if (glob.charAt(i) == '[' && glob.charAt(i + 1) == ':') + if (glob[i] == '[' && glob[i + 1] == ':') i = matchCharacterClass(glob, i) + 1; else ++i; // skip any character, including [ or ] boolean escape = false; - for (; i < glob.length(); ++i) { - char c = glob.charAt(i); + for (; i < glob.length; ++i) { + char c = glob[i]; if (escape) { ++i; escape = false; } - else if (c == '[' && glob.charAt(i + 1) == ':') + else if (c == '[' && glob[i + 1] == ':') i = matchCharacterClass(glob, i); else if (c == ']') return i; } throw new PatternSyntaxException - ("Unmatched '" + glob.charAt(from) + "'.", glob, from); + ("Unmatched '" + glob[from] + "'.", new String(glob), from); } - private static String toRegex(String glob) { + // Package private so that TestGlob can access it. + static String toRegex(char[] glob) { StringBuffer buf = new StringBuffer(); boolean escape = false; - for(int i = 0; i < glob.length(); ++i) { - char c = glob.charAt(i); + for(int i = 0; i < glob.length; ++i) { + char c = glob[i]; if (escape) { if (c == '\\') buf.append("\\\\"); @@ -107,7 +111,7 @@ public class Glob { escape = true; else if (c == '[') { int j = matchBrack(glob, i); - buf.append(glob.substring(i, j+1)); + buf.append(glob, i, j - i + 1); i = j; } else if (c == '*') @@ -124,10 +128,10 @@ public class Glob { } public static Pattern compile(String glob) { - return Pattern.compile(toRegex(glob)); + return Pattern.compile(toRegex(glob.toCharArray())); } public static Pattern compile(String glob, int flags) { - return Pattern.compile(toRegex(glob), flags); + return Pattern.compile(toRegex(glob.toCharArray()), flags); } } diff --git a/frysk-core/frysk/util/StackPrintUtil.java b/frysk-core/frysk/util/StackPrintUtil.java index a4b85ac..ab7fc01 100644 --- a/frysk-core/frysk/util/StackPrintUtil.java +++ b/frysk-core/frysk/util/StackPrintUtil.java @@ -47,7 +47,7 @@ import java.util.StringTokenizer; import gnu.classpath.tools.getopt.Option; import gnu.classpath.tools.getopt.OptionException; import gnu.classpath.tools.getopt.OptionGroup; -import frysk.debuginfo.PrintStackOptions; +import frysk.debuginfo.PrintDebugInfoStackOptions; /** * Framework for printing stack backtraces; both providing a standard @@ -58,7 +58,10 @@ public class StackPrintUtil { * Create, in a separate group, the standard set of stack-print * options provided by utilities. */ - public static OptionGroup options(final PrintStackOptions options) { + public static OptionGroup options(final PrintDebugInfoStackOptions options) { + // Set the default, which matches the documentation; and is + // consistent across all utilities. + options.setAbi(); OptionGroup group = new OptionGroup("Stack print options"); group.add(new Option("number-of-frames", ("number of frames to print. Specify '0' or" @@ -90,11 +93,12 @@ public class StackPrintUtil { group.add(new Option ("print", "select the back-trace information to display\n" + "OPTION is:\n" - + "debug-names: use debug-info names (e.g., DWARF)\n" - + "full-path: include the full (untruncated) path to files\n" + + "debug-names: print debug-info names (e.g., DWARF)\n" + + "paths: include the full path to source files (src-paths) and libraries (lib-paths)\n" + "inline: include inlined frames\n" - + "locals: include each functions local variables\n" - + "params: include function parameters\n" + + "locals: include each function's local variables\n" + //+ "params: include function parameters\n" + + "values: include values of parameters and variables\n" + "OPTIONs can be negated by prefixing a '-'", "OPTION,...") { public void parsed(String arg) throws OptionException { @@ -110,14 +114,20 @@ public class StackPrintUtil { } if (name.equals("debug-names")) { options.setPrintDebugNames(val); - } else if (name.equals("full-path")) { - options.setPrintFullPaths(val); + } else if (name.equals("paths")) { + options.setPrintPaths(val); + } else if (name.equals("lib-paths")) { + options.setPrintLibraryPaths(val); + } else if (name.equals("src-paths")) { + options.setPrintSourcePaths(val); } else if (name.equals("inline")) { options.setPrintInlineFunctions(val); } else if (name.equals("locals")) { options.setPrintLocals(val); } else if (name.equals("params")) { - options.setPrintParams(val); + options.setPrintParameters(val); + } else if (name.equals("values")) { + options.setPrintValues(val); } else { throw new OptionException ("unknown -print OPTION: " + name); @@ -132,9 +142,9 @@ public class StackPrintUtil { * Given a task, a writer, and the selected stack-print-options, * produce a stack back-trace. */ - public static void print(Task task, PrintStackOptions options, + public static void print(Task task, PrintDebugInfoStackOptions options, PrintWriter printWriter) { - if (options.elfOnly()) { + if (options.abiOnly()) { StackFactory.printTaskStackTrace(printWriter, task, options); } else if (options.printInlineFunctions()) { DebugInfoStackFactory.printVirtualTaskStackTrace(printWriter, diff --git a/frysk-core/frysk/util/StacktraceAction.java b/frysk-core/frysk/util/StacktraceAction.java index e3b9a70..9b83662 100644 --- a/frysk-core/frysk/util/StacktraceAction.java +++ b/frysk-core/frysk/util/StacktraceAction.java @@ -45,7 +45,7 @@ import java.util.Iterator; import java.util.TreeMap; import frysk.rsl.Log; import frysk.debuginfo.DebugInfoStackFactory; -import frysk.debuginfo.PrintStackOptions; +import frysk.debuginfo.PrintDebugInfoStackOptions; import frysk.event.Event; import frysk.event.RequestStopEvent; import frysk.event.SignalEvent; @@ -77,7 +77,7 @@ public abstract class StacktraceAction implements ProcBlockObserver { private Event event; - PrintStackOptions options; + PrintDebugInfoStackOptions options; /** * Runs a stacktrace on the given process. @@ -97,14 +97,14 @@ public abstract class StacktraceAction implements ProcBlockObserver { * file path is printed other wise only the name of the file is printed. * @throws ProcException */ - public StacktraceAction (PrintWriter printWriter, Proc theProc, Event theEvent, PrintStackOptions options) - { - event = theEvent; - - this.options = options; - this.printWriter = printWriter; - Manager.eventLoop.add(new InterruptEvent(theProc)); - } + public StacktraceAction (PrintWriter printWriter, Proc theProc, + Event theEvent, + PrintDebugInfoStackOptions options) { + event = theEvent; + this.options = options; + this.printWriter = printWriter; + Manager.eventLoop.add(new InterruptEvent(theProc)); + } public final void existingTask (Task task) { @@ -126,27 +126,27 @@ public abstract class StacktraceAction implements ProcBlockObserver { "because", w); } - private final void printTasks () - { - fine.log(this, "printTasks"); - Iterator iter = sortedTasks.values().iterator(); - while (iter.hasNext()) - { - Task task = (Task) iter.next(); - - if(options.elfOnly()){ - StackFactory.printTaskStackTrace(printWriter,task,options); - }else{ - if(options.printInlineFunctions()){ - DebugInfoStackFactory.printVirtualTaskStackTrace(printWriter,task,options); - }else{ - DebugInfoStackFactory.printTaskStackTrace(printWriter,task,options); - } + private final void printTasks() { + fine.log(this, "printTasks"); + Iterator iter = sortedTasks.values().iterator(); + while (iter.hasNext()) { + Task task = (Task) iter.next(); + + if (options.abiOnly()) { + StackFactory.printTaskStackTrace(printWriter,task,options); + } else { + if (options.printInlineFunctions()) { + DebugInfoStackFactory + .printVirtualTaskStackTrace(printWriter,task,options); + } else { + DebugInfoStackFactory + .printTaskStackTrace(printWriter, task, options); + } } - printWriter.println(); - } - fine.log(this, "exiting printTasks"); - } + printWriter.println(); + } + fine.log(this, "exiting printTasks"); + } public void flush(){ this.printWriter.flush(); diff --git a/frysk-core/frysk/util/StressTestStackTraceAction.java b/frysk-core/frysk/util/StressTestStackTraceAction.java index c454239..75ccf5f 100644 --- a/frysk-core/frysk/util/StressTestStackTraceAction.java +++ b/frysk-core/frysk/util/StressTestStackTraceAction.java @@ -43,7 +43,7 @@ package frysk.util; import java.io.PrintWriter; import java.io.StringWriter; import frysk.rsl.Log; -import frysk.debuginfo.PrintStackOptions; +import frysk.debuginfo.PrintDebugInfoStackOptions; import frysk.event.Event; import frysk.event.RequestStopEvent; import frysk.proc.Manager; @@ -80,9 +80,9 @@ public class StressTestStackTraceAction extends TestLib { FunitThreadsOffspring ackProc = new FunitThreadsOffspring(threads); final Proc proc = ackProc.assertRunToFindProc(); - PrintStackOptions options = new PrintStackOptions(); + PrintDebugInfoStackOptions options = new PrintDebugInfoStackOptions(); options.setNumberOfFrames(20); - options.setPrintParams(true); + options.setPrintParameters(true); StacktraceAction stacker = new StacktraceAction(new PrintWriter(stringWriter),proc, new Event() { diff --git a/frysk-core/frysk/util/TestGlob.java b/frysk-core/frysk/util/TestGlob.java new file mode 100644 index 0000000..8efa4b8 --- /dev/null +++ b/frysk-core/frysk/util/TestGlob.java @@ -0,0 +1,73 @@ +// 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.util; + +import frysk.junit.TestCase; + +public class TestGlob + extends TestCase { + + private void translate(String glob, String expect) { + String pattern = Glob.toRegex(glob.toCharArray()); + assertEquals(glob + " -> " + expect, pattern, expect); + } + + public void testGlobs() { + translate("*", ".*"); + translate("?", "."); + translate(".*", "\\..*"); + translate("*.*", ".*\\..*"); + translate("*a*", ".*a.*"); + translate("[abc]", "[abc]"); + translate("[^abc]", "[^abc]"); + translate("[!abc]", "[^abc]"); + translate("[]]", "[]]"); + translate("[[]", "[[]"); + translate("[^]]", "[^]]"); + translate("[^a-z]", "[^a-z]"); + translate("[abc\\]]", "[abc\\]]"); + translate("[abc\\]def]", "[abc\\]def]"); + translate("[[:space:]]", "[[:space:]]"); + translate("[^[:space:]]", "[^[:space:]]"); + translate("[![:space:]]", "[^[:space:]]"); + translate("[^a-z]*", "[^a-z].*"); + translate("[^a-z]bar*", "[^a-z]bar.*"); + } +} diff --git a/frysk-core/frysk/util/TestStackTraceAction.java b/frysk-core/frysk/util/TestStackTraceAction.java index 0db2626..3fd33cf 100644 --- a/frysk-core/frysk/util/TestStackTraceAction.java +++ b/frysk-core/frysk/util/TestStackTraceAction.java @@ -43,7 +43,7 @@ package frysk.util; import java.io.PrintWriter; import java.io.StringWriter; import frysk.rsl.Log; -import frysk.debuginfo.PrintStackOptions; +import frysk.debuginfo.PrintDebugInfoStackOptions; import frysk.event.RequestStopEvent; import frysk.proc.Manager; import frysk.proc.Proc; @@ -78,23 +78,23 @@ public class TestStackTraceAction extends TestLib { static void multiThreaded(SlaveOffspring ackProc, int numSecondaryThreads) { - PrintStackOptions options = new PrintStackOptions(); + PrintDebugInfoStackOptions options = new PrintDebugInfoStackOptions(); options.setNumberOfFrames(20); - options.setPrintFullPaths(true); - options.setPrintLibraries(true); + options.setPrintPaths(true); + options.setPrintLibraryNames(true); StringWriter stringWriter = new StringWriter(); String mainThread = "Task #\\d+\n" + "(#[\\d]+ 0x[\\da-f]+ in .*\n)*" - + "#[\\d]+ 0x[\\da-f]+ in server \\(\\).*\n" - + "#[\\d]+ 0x[\\da-f]+ in main \\(\\).*\n" - + "#[\\d]+ 0x[\\da-f]+ in __libc_start_main \\(\\).*\n" - + "#[\\d]+ 0x[\\da-f]+ in _start \\(\\).*\n\n"; + + "#[\\d]+ 0x[\\da-f]+ in server\\(\\).*\n" + + "#[\\d]+ 0x[\\da-f]+ in main\\(\\).*\n" + + "#[\\d]+ 0x[\\da-f]+ in __libc_start_main\\(\\).*\n" + + "#[\\d]+ 0x[\\da-f]+ in _start\\(\\).*\n\n"; String thread = "Task #\\d+\n" + "(#[\\d]+ 0x[\\da-f]+ in .*\n)*" - + "#[\\d]+ 0x[\\da-f]+ in server \\(\\).*\n" - + "#[\\d]+ 0x[\\da-f]+ in start_thread \\(\\).*\n" - + "#[\\d]+ 0x[\\da-f]+ in (__)?clone \\(\\).*\n\n"; + + "#[\\d]+ 0x[\\da-f]+ in server\\(\\).*\n" + + "#[\\d]+ 0x[\\da-f]+ in start_thread\\(\\).*\n" + + "#[\\d]+ 0x[\\da-f]+ in (__)?clone\\(\\).*\n\n"; final Proc proc = ackProc.assertRunToFindProc(); diff --git a/frysk-core/frysk/util/stack-options.xml b/frysk-core/frysk/util/stack-options.xml index 90eeab4..5555d01 100644 --- a/frysk-core/frysk/util/stack-options.xml +++ b/frysk-core/frysk/util/stack-options.xml @@ -74,19 +74,36 @@ </varlistentry> <varlistentry> - <term><option>-print <replaceable>print-option</replaceable>,...</option></term> + <term> + <option>-print <replaceable>print-option</replaceable>,...</option> + </term> <listitem> - <para>Specify the level of detail to include in a stack + <para> + Specify the level of detail to include in a stack back-trace. <replaceable>print-option</replaceable> can be - any of: debug-names - use debug information, such as DWARF, - to determine the name of functions; full-path - do not - truncate file paths; inline - include in-line function in - back-trace; locals - to include local variables from each - frame; params - include the values of any parameters. To - negate a <replaceable>print-option</replaceable> prefix it - with "-".</para></listitem> + any of: + </para> + + <para>debug-names: use debug information, such as DWARF, to + determine the name of functions</para> + + <para>paths: include the full path to source files and + libraries</para> + + <para>inline: include in-line function in back-trace</para> + + <para>locals: to include local variables from each + frame</para> + + <para>params: include the function parameters</para> + + <para> + To negate a <replaceable>print-option</replaceable> prefix + it with "-". + </para> + + </listitem> </varlistentry> - </variablelist> </refsect2> diff --git a/frysk-core/frysk/value/ByteBufferLocation.java b/frysk-core/frysk/value/ByteBufferLocation.java index 4aff9e4..915cad9 100644 --- a/frysk-core/frysk/value/ByteBufferLocation.java +++ b/frysk-core/frysk/value/ByteBufferLocation.java @@ -106,7 +106,7 @@ public class ByteBufferLocation buffer.putByte(offset, value); } - protected long length() { + public long length() { return buffer.capacity(); } } diff --git a/frysk-core/frysk/value/ChangeLog b/frysk-core/frysk/value/ChangeLog index fdf4a5e..14a7ad6 100644 --- a/frysk-core/frysk/value/ChangeLog +++ b/frysk-core/frysk/value/ChangeLog @@ -1,3 +1,8 @@ +2008-06-11 Teresa Thomas <tthomas@redhat.com> + + * Location.java (length): Make public. + * ByteBufferLocation.java (length): Ditto. + 2008-04-30 Stan Cox <scox@redhat.com> * Type.java (toPrintBrief): New. diff --git a/frysk-core/frysk/value/Location.java b/frysk-core/frysk/value/Location.java index 0659547..27b52a0 100644 --- a/frysk-core/frysk/value/Location.java +++ b/frysk-core/frysk/value/Location.java @@ -170,9 +170,9 @@ public abstract class Location /** * The length of the location, in bytes. This MUST be a long (or - * BigIneger) as a value's size could be bigger than 32-bits. + * BigInteger) as a value's size could be bigger than 32-bits. */ - protected abstract long length(); + public abstract long length(); /** * Print this Location. diff --git a/frysk-gui/frysk/gui/monitor/ChangeLog b/frysk-gui/frysk/gui/monitor/ChangeLog index a857f69..5b5d90a 100644 --- a/frysk-gui/frysk/gui/monitor/ChangeLog +++ b/frysk-gui/frysk/gui/monitor/ChangeLog @@ -1,3 +1,8 @@ +2008-06-10 Andrew Cagney <cagney@redhat.com> + + * eventviewer/Event.java: Use PrintDebugInfoStackOptions and + setPrintParameters. + 2008-04-10 Sami Wagiaalla <swagiaal@redhat.com> * GuiProc.java: updated isOwned() to allow all processes diff --git a/frysk-gui/frysk/gui/monitor/eventviewer/Event.java b/frysk-gui/frysk/gui/monitor/eventviewer/Event.java index ad1cf86..824364c 100644 --- a/frysk-gui/frysk/gui/monitor/eventviewer/Event.java +++ b/frysk-gui/frysk/gui/monitor/eventviewer/Event.java @@ -48,7 +48,7 @@ import org.gnu.gdk.GdkCairo; import frysk.debuginfo.DebugInfoFrame; import frysk.debuginfo.DebugInfoStackFactory; -import frysk.debuginfo.PrintStackOptions; +import frysk.debuginfo.PrintDebugInfoStackOptions; import frysk.gui.monitor.GuiObject; import frysk.gui.monitor.GuiTask; import frysk.gui.monitor.WindowManager; @@ -225,8 +225,8 @@ public class Event extends GuiObject stringWriter.write(this.getName() + ": " + this.getToolTip() + "\n"); if(frame != null){ - PrintStackOptions options = new PrintStackOptions(); - options.setPrintParams(true); + PrintDebugInfoStackOptions options = new PrintDebugInfoStackOptions(); + options.setPrintParameters(true); options.setNumberOfFrames(20); DebugInfoStackFactory.printStackTrace(new PrintWriter(stringWriter),frame,options); diff --git a/frysk-gui/frysk/gui/srcwin/ChangeLog b/frysk-gui/frysk/gui/srcwin/ChangeLog index 57fe952..fe5f98f 100644 --- a/frysk-gui/frysk/gui/srcwin/ChangeLog +++ b/frysk-gui/frysk/gui/srcwin/ChangeLog @@ -1,3 +1,14 @@ +2008-06-23 Rick Moseley <rmoseley@redhat.com> + + * SourceBuffer.java: Call getEntryPoint to get address. + * SourceWindow.java: Add "load" capability. + * SourceWindowFactory.java: Add loadExecutable method. + +2008-06-10 Andrew Cagney <cagney@redhat.com> + + * CurrentStackView.java (STACK_OPTIONS): New. Pass to + Frame.toPrint. + 2008-05-15 Tim Moore <timoore@redhat.com> * SourceBuffer.java (disassemblerFrame): Use lib.dwfl.Disassembler. diff --git a/frysk-gui/frysk/gui/srcwin/CurrentStackView.java b/frysk-gui/frysk/gui/srcwin/CurrentStackView.java index 45ac270..737a1a3 100644 --- a/frysk-gui/frysk/gui/srcwin/CurrentStackView.java +++ b/frysk-gui/frysk/gui/srcwin/CurrentStackView.java @@ -1,6 +1,6 @@ // This file is part of the program FRYSK. // -// Copyright 2005, 2007, Red Hat Inc. +// Copyright 2005, 2007, 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,9 +37,9 @@ // version and license this file solely under the GPL without // exception. - package frysk.gui.srcwin; +import frysk.debuginfo.PrintDebugInfoStackOptions; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Iterator; @@ -80,6 +80,13 @@ public class CurrentStackView new DataColumnString(), new DataColumnObject() }; + private static final PrintDebugInfoStackOptions STACK_OPTIONS; + static { + STACK_OPTIONS = new PrintDebugInfoStackOptions(); + STACK_OPTIONS.setPrintParameters(true); + } + + private static DebugInfoFrame currentFrame; private LinkedList observers; @@ -119,8 +126,7 @@ public class CurrentStackView this.getSelection().addListener(this); } - public void refreshProc (DebugInfoFrame[] frames, int current) - { + public void refreshProc (DebugInfoFrame[] frames, int current) { TreeIter iter = null; TreePath path = ((TreeRowReference) this.stackArray[current]).getPath(); @@ -184,7 +190,7 @@ public class CurrentStackView StringWriter stringWriter = new StringWriter(); stringWriter.write("# " + (++level) + " "); - frame.toPrint(new PrintWriter(stringWriter),true,true); + frame.toPrint(new PrintWriter(stringWriter), STACK_OPTIONS); row = stringWriter.toString(); if (hasInlinedCode) @@ -288,7 +294,7 @@ public class CurrentStackView StringWriter stringWriter = new StringWriter(); stringWriter.write(row = "# " + (++level) + " "); - frame.toPrint(new PrintWriter(stringWriter),true,true); + frame.toPrint(new PrintWriter(stringWriter), STACK_OPTIONS); row = stringWriter.toString(); if (hasInlinedCode) diff --git a/frysk-gui/frysk/gui/srcwin/SourceBuffer.java b/frysk-gui/frysk/gui/srcwin/SourceBuffer.java index 0957b49..5950415 100644 --- a/frysk-gui/frysk/gui/srcwin/SourceBuffer.java +++ b/frysk-gui/frysk/gui/srcwin/SourceBuffer.java @@ -50,6 +50,8 @@ import java.util.List; import lib.dwfl.Disassembler; import lib.dwfl.Instruction; +import lib.dwfl.Elf; +import lib.dwfl.ElfCommand; import org.gnu.gdk.Color; import org.gnu.glib.JGException; @@ -80,6 +82,7 @@ import frysk.gui.srcwin.prefs.SyntaxPreference.SyntaxPreferenceListener; import frysk.proc.Task; import frysk.rt.LineXXX; import frysk.scopes.SourceLocation; +import frysk.solib.DynamicSegment; import frysk.value.Value; /** @@ -850,10 +853,17 @@ public class SourceBuffer extends TextBuffer { task.getMemory()); long address = frame.getAddress(); + // If the address is 0, use the entry point as the address to disassemble + if (address == 0) { + Elf elf = new Elf(task.getProc().getExeFile().getFile(), + ElfCommand.ELF_C_READ); + address = DynamicSegment.getEntryPoint(elf); + } this.deleteText(this.getStartIter(), this.getEndIter()); List instructionsList = diss.disassembleInstructions(address, 40); + Iterator iter = instructionsList.iterator(); while (iter.hasNext()) { diff --git a/frysk-gui/frysk/gui/srcwin/SourceWindow.java b/frysk-gui/frysk/gui/srcwin/SourceWindow.java index dfc8124..06a7a9e 100644 --- a/frysk-gui/frysk/gui/srcwin/SourceWindow.java +++ b/frysk-gui/frysk/gui/srcwin/SourceWindow.java @@ -167,6 +167,8 @@ public class SourceWindow extends Window { private Action close; private Action open_core; + + private Action open_load; private Action open_executable; @@ -580,7 +582,7 @@ public class SourceWindow extends Window { /** * Populates the stack browser window * - * @param frames An array of DebugInfoFrames used to popuate information + * @param frames An array of DebugInfoFrames used to populate information * inside the stack frame window. */ public void populateStackBrowser(DebugInfoFrame[][] frames) { @@ -886,7 +888,8 @@ public class SourceWindow extends Window { Proc[] newSwProc = new Proc[numProcs]; DOMFactory.clearDOMSourceMap(this.swProc[this.current]); - this.steppingEngine.detachProc(this.swProc[this.current], kill); + if (this.swProc[this.current].getPid() != 0) + this.steppingEngine.detachProc(this.swProc[this.current], kill); int j = 0; for (int i = 0; i < oldSize; i++) { @@ -916,7 +919,7 @@ public class SourceWindow extends Window { /*********************************************************************** * Getters and Setters **********************************************************************/ - + public Proc getSwProc() { if (this.swProc.length > 0) return this.swProc[this.current]; @@ -986,7 +989,7 @@ public class SourceWindow extends Window { this.open_core = new Action("open", "Examine core file...", "Examine core file", GtkStockItem.OPEN.getString()); this.open_core.setAccelGroup(ag); - this.open_core.setAccelPath("<sourceWin>/File/Examine core file..."); + this.open_core.setAccelPath("<sourceWin>/Processes/Examine core file..."); this.open_core.addListener(new org.gnu.gtk.event.ActionListener() { public void actionEvent(ActionEvent action) { // SourceWindow.this.glade.getWidget(SOURCE_WINDOW).destroy(); @@ -1023,7 +1026,7 @@ public class SourceWindow extends Window { // to // select a file name public void fileActivated(FileChooserEvent event) { - examineCoreFile(chooser.getFilename()); + examineCoreFile(); } }); setDefaultIcon(IconManager.windowIcon); @@ -1036,15 +1039,84 @@ public class SourceWindow extends Window { // The OK button was clicked, go open a source window for this // core file else if (response == ResponseType.OK.getValue()) { - examineCoreFile(chooser.getFilename()); + examineCoreFile(); chooser.destroy(); } } }); - AccelMap.changeEntry("<sourceWin>/File/Examine core file...", + AccelMap.changeEntry("<sourceWin>/Processes/Examine core file...", KeyValue.o, ModifierType.CONTROL_MASK, true); this.open_core.connectAccelerator(); + + // Load executable action + this.open_load = new Action("Load an executable", + "Load a process...", "Load a process from a file", + GtkStockItem.OPEN.getString()); + this.open_load.setAccelGroup(ag); + this.open_load + .setAccelPath("<sourceWin>/Processes/Load a process..."); + this.open_load.addListener(new ActionListener() { + public void actionEvent(ActionEvent action) { + try { + glade_fc = new LibGlade(Prefix.gladeFile(FILECHOOSER_GLADE).getAbsolutePath(), null); + fc = (FileChooserDialog) glade_fc + .getWidget("frysk_filechooserdialog"); + fc.addListener(new LifeCycleListener() { + public void lifeCycleEvent(LifeCycleEvent event) { + } + + public boolean lifeCycleQuery(LifeCycleEvent event) { + if (event.isOfType(LifeCycleEvent.Type.DELETE) + || event + .isOfType(LifeCycleEvent.Type.DESTROY)) + fc.destroy(); + return false; + } + }); + fc.addListener(new FileChooserListener() { + public void currentFolderChanged(FileChooserEvent event) { + } + + public void selectionChanged(FileChooserEvent event) { + } + + public void updatePreview(FileChooserEvent event) { + } + + // This method is called when the "Enter" key is pressed + // to + // select a file name in the chooser + public void fileActivated(FileChooserEvent event) { + loadExecutableFile(); + } + }); + fc.setIcon(IconManager.windowIcon); + fc.setDefaultResponse(FileChooserEvent.Type.FILE_ACTIVATED + .getID()); + fc.setCurrentFolder(System.getProperty("user.home")); + CheckButton term_activate = (CheckButton) glade_fc + .getWidget("term_activate"); + term_activate.setSensitive(false); + gtk_widget_set_size_request(fc.getHandle(), 300, 600); + int response = fc.open(); + // "OK" key has been clicked + if (response == ResponseType.OK.getValue()) + loadExecutableFile(); + // "Cancel" key has been clicked + if (response == ResponseType.CANCEL.getValue()) + fc.destroy(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + + AccelMap.changeEntry("<sourceWin>/Processes/Load executable file...", + KeyValue.l, ModifierType.CONTROL_MASK, true); + this.open_load.connectAccelerator(); + + // Close action this.close = new Action("close", "Close", "Close Window", GtkStockItem.CLOSE.getString()); @@ -1345,9 +1417,11 @@ public class SourceWindow extends Window { fc.setDefaultResponse(FileChooserEvent.Type.FILE_ACTIVATED .getID()); fc.setCurrentFolder(System.getProperty("user.home")); - gtk_widget_set_size_request(fc.getHandle(), 300, 300); + CheckButton term_activate = (CheckButton) glade_fc + .getWidget("term_activate"); + term_activate.setSensitive(false); + gtk_widget_set_size_request(fc.getHandle(), 300, 1000); int response = fc.open(); - gtk_widget_set_size_request(fc.getHandle(), 300, 300); // "OK" key has been clicked if (response == ResponseType.OK.getValue()) activateProc(); @@ -1570,17 +1644,41 @@ public class SourceWindow extends Window { } /** - * This method will activate a window to allow the user to exemaine a + * This method will activate a window to allow the user to examine a * core file * * @param filename - * String containing the path to the core file * */ - private void examineCoreFile(String filename) { + private void examineCoreFile() { + Entry task_options = (Entry) glade_fc.getWidget("task_options"); + String task_opt = task_options.getText(); + String filename = fc.getFilename(); + fc.destroy(); + String[] stds = { "/dev/null", "/dev/null", "/dev/null" }; + addProc(filename, "", task_opt, stds[0], stds[1], stds[2]); SourceWindowFactory.attachToCore(new File(filename)); - this.destroy(); } + + /** + * This method will activate a window to allow the user to load an + * executable file + * + * @param filename - + * String containing the path to the executable file + * + */ + private void loadExecutableFile() { + Entry task_options = (Entry) glade_fc.getWidget("task_options"); + String task_opt = task_options.getText(); + String filename = fc.getFilename(); + fc.destroy(); + String[] stds = { "/dev/null", "/dev/null", "/dev/null" }; + addProc(filename, "", task_opt, stds[0], stds[1], stds[2]); + SourceWindowFactory.loadExecutable(new File(filename), null); + //this.destroy(); +} /** * Creates the toolbar menus with initialized Actions. @@ -1589,11 +1687,14 @@ public class SourceWindow extends Window { // File menu MenuItem menu = new MenuItem("File", true); - // MenuItem mi = (MenuItem) this.open_core.createMenuItem(); + /* MenuItem mi = (MenuItem) this.open_core.createMenuItem(); + Menu tmp = new Menu(); + tmp.append(mi); + mi = (MenuItem) this.open_load.createMenuItem(); + tmp.append(mi); + mi = new MenuItem(); // Separator + tmp.append(mi); */ Menu tmp = new Menu(); - // tmp.append(mi); - // mi = new MenuItem(); // Separator - // tmp.append(mi); MenuItem mi = (MenuItem) this.close.createMenuItem(); tmp.append(mi); @@ -1686,14 +1787,16 @@ public class SourceWindow extends Window { menu = new MenuItem("Processes", false); tmp = new Menu(); - mi = (MenuItem) this.open_executable.createMenuItem(); + mi = (MenuItem) this.attach_proc.createMenuItem(); tmp.append(mi); mi = new MenuItem(); // Separator tmp.append(mi); - mi = (MenuItem) this.attach_proc.createMenuItem(); + mi = (MenuItem) this.open_executable.createMenuItem(); tmp.append(mi); mi = (MenuItem) this.open_core.createMenuItem(); tmp.append(mi); + mi = (MenuItem) this.open_load.createMenuItem(); + tmp.append(mi); menu.setSubmenu(tmp); ((MenuBar) this.glade.getWidget("menubar")).append(menu); diff --git a/frysk-gui/frysk/gui/srcwin/SourceWindowFactory.java b/frysk-gui/frysk/gui/srcwin/SourceWindowFactory.java index e662bb7..652ee6c 100644 --- a/frysk-gui/frysk/gui/srcwin/SourceWindowFactory.java +++ b/frysk-gui/frysk/gui/srcwin/SourceWindowFactory.java @@ -51,6 +51,7 @@ import org.gnu.gtk.event.LifeCycleListener; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; import frysk.proc.dead.LinuxCoreFactory; +import frysk.proc.dead.LinuxExeFactory; import frysk.config.Prefix; import frysk.proc.TaskAttachedObserverXXX; import frysk.debuginfo.DebugInfoFrame; @@ -140,16 +141,28 @@ public class SourceWindowFactory public static void attachToCore(File coreFile) { Proc proc = LinuxCoreFactory.createProc(coreFile); - LinkedList tasks = proc.getTasks(); - DebugInfoFrame[] framez = new DebugInfoFrame[tasks.size()]; - Iterator iter = tasks.iterator(); - for (int i = 0; iter.hasNext(); i++) - { - Task task = (Task) iter.next(); - framez[i] = DebugInfoStackFactory.createDebugInfoStackTrace(task); - } - createSourceWindow(framez); - } + LinkedList tasks = proc.getTasks(); + DebugInfoFrame[] framez = new DebugInfoFrame[tasks.size()]; + Iterator iter = tasks.iterator(); + for (int i = 0; iter.hasNext(); i++) { + Task task = (Task) iter.next(); + framez[i] = DebugInfoStackFactory.createDebugInfoStackTrace(task); + } + createSourceWindow(framez); + } + + public static void loadExecutable(File exeFile, String[] args) { + Proc proc = LinuxExeFactory.createProc(exeFile, args); + + LinkedList tasks = proc.getTasks(); + DebugInfoFrame[] framez = new DebugInfoFrame[tasks.size()]; + Iterator iter = tasks.iterator(); + for (int i = 0; iter.hasNext(); i++) { + Task task = (Task) iter.next(); + framez[i] = DebugInfoStackFactory.createDebugInfoStackTrace(task); + } + createSourceWindow(framez); + } public static AttachedObserver startNewProc(String file, String env_variables, String options, String stdin, String stdout, String stderr) diff --git a/frysk-imports/elfutils/libdwfl/ChangeLog b/frysk-imports/elfutils/libdwfl/ChangeLog index ac95d68..e1d00f1 100644 --- a/frysk-imports/elfutils/libdwfl/ChangeLog +++ b/frysk-imports/elfutils/libdwfl/ChangeLog @@ -1,3 +1,8 @@ +2008-06-19 Andrew Cagney <cagney@redhat.com> + + * dwfl_module_addrsym.c (dwfl_module_addrsym): Correctly update + min_label. + 2008-06-07 Andrew Cagney <cagney@redhat.com> * dwfl_module_getdwarf.c (open_elf): Don't align the module's load diff --git a/frysk-imports/elfutils/libdwfl/dwfl_module_addrsym.c b/frysk-imports/elfutils/libdwfl/dwfl_module_addrsym.c index c34a31b..77033a6 100644 --- a/frysk-imports/elfutils/libdwfl/dwfl_module_addrsym.c +++ b/frysk-imports/elfutils/libdwfl/dwfl_module_addrsym.c @@ -49,10 +49,13 @@ #include "libdwflP.h" +#include <stdio.h> + const char * dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, GElf_Sym *closest_sym, GElf_Word *shndxp) { + // fprintf(stderr, "looking up %lx\n", (long) addr); int syments = INTUSE(dwfl_module_getsymtab) (mod); if (syments < 0) return NULL; @@ -116,15 +119,20 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, GElf_Sym sym; GElf_Word shndx; const char *name = INTUSE(dwfl_module_getsym) (mod, i, &sym, &shndx); + // fprintf(stderr, "symbol %s at 0x%lx 0x%ld\n", name, (long) sym.st_value, (long) sym.st_size); + /* Even if we don't choose this symbol, its existence excludes + any sizeless symbol (assembly label) that is below its upper + bound. */ + if (name != NULL && sym.st_value <= addr + && sym.st_value + sym.st_size > min_label) { + min_label = sym.st_value + sym.st_size; + // fprintf(stderr, " min to %s size ends at %lx\n", name, (long) min_label); + } if (name != NULL && sym.st_value <= addr && (sym.st_size == 0 || addr - sym.st_value < sym.st_size)) { - /* Even if we don't choose this symbol, its existence - excludes any sizeless symbol (assembly label) that - is inside its bounds. */ - if (sym.st_value + sym.st_size > addr) - min_label = sym.st_value + sym.st_size; + // fprintf(stderr, " candidate %s at 0x%lx 0x%ld\n", name, (long) sym.st_value, (long) sym.st_size); /* This symbol is a better candidate than the current one if it's a named symbol, not a section or file symbol, @@ -140,6 +148,7 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, { if (sym.st_size != 0) { + // fprintf(stderr, " closest %s at %lx\n", name, (long)sym.st_value); *closest_sym = sym; closest_shndx = shndx; closest_name = name; @@ -155,6 +164,7 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, || (sizeless_sym.st_value == sym.st_value && strcmp(name, sizeless_name) < 0)) { + // fprintf(stderr, " sizeless %s at %lx\n", name, (long)sym.st_value); sizeless_sym = sym; sizeless_shndx = shndx; sizeless_name = name; @@ -171,6 +181,7 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, || (closest_sym->st_size == sym.st_size && strcmp(name, closest_name) < 0))) { + // fprintf(stderr, " alt closest %s at %lx\n", name, (long)sym.st_value); *closest_sym = sym; closest_shndx = shndx; closest_name = name; diff --git a/frysk-sys/ChangeLog b/frysk-sys/ChangeLog index 52b6d1c..c482e0e 100644 --- a/frysk-sys/ChangeLog +++ b/frysk-sys/ChangeLog @@ -1,3 +1,9 @@ +2008-06-19 Andrew Cagney <cagney@redhat.com> + + * Makefile.am (JNI_LIBRARY_LIST): Define. + (JNI_ARCHIVE_LIST): Define. + (JNI_OBJECT_LIST): Define. + 2008-05-27 Andrew Cagney <cagney@redhat.com> * Makefile.am (JniRunner.java): Delete. diff --git a/frysk-sys/Makefile.am b/frysk-sys/Makefile.am index 24032eb..79ef060 100644 --- a/frysk-sys/Makefile.am +++ b/frysk-sys/Makefile.am @@ -71,6 +71,21 @@ lib/unwind/cni/Unwind%.cxx: lib/unwind/Unwind%.java lib/unwind/cni/UnwindH.hxx lib/unwind/Unwind%.java: lib/unwind/Unwind.java +# Depend on these runtimes. +JNI_LIBRARY_LIST += -lstdc++ +JNI_LIBRARY_LIST += -laudit +# Bundle in the local elfutils code. +JNI_ARCHIVE_LIST += ../frysk-imports/elfutils/libasm/libasm_pic.a +JNI_ARCHIVE_LIST += ../frysk-imports/elfutils/libdwfl/libdwfl_pic.a +JNI_ARCHIVE_LIST += ../frysk-imports/elfutils/libdw/libdw_pic.a +JNI_ARCHIVE_LIST += ../frysk-imports/elfutils/libelf/libelf_pic.a +JNI_ARCHIVE_LIST += ../frysk-imports/elfutils/libebl/libebl.a +# Bundle in the local libunwind code. +JNI_OBJECT_LIST += ../frysk-imports/libunwind-i386/src/{,dwarf/,mi/,x86/}.libs/*.o +JNI_OBJECT_LIST += ../frysk-imports/libunwind-x86_64/src/{,dwarf/,mi/,x86_64/}.libs/*.o +JNI_OBJECT_LIST += ../frysk-imports/libunwind-ppc32/src/{,dwarf/,mi/,ppc32/}.libs/*.o +JNI_OBJECT_LIST += ../frysk-imports/libunwind-ppc64/src/{,dwarf/,mi/,ppc64/}.libs/*.o + # jnixx's auto-detect algorithm misses hidden class references, # explicitly add them here. JNIXX_CLASSES += frysk.sys.ProcessIdentifierFactory diff --git a/frysk-sys/frysk/ChangeLog b/frysk-sys/frysk/ChangeLog index e0baf3a..36193fc 100644 --- a/frysk-sys/frysk/ChangeLog +++ b/frysk-sys/frysk/ChangeLog @@ -1,3 +1,7 @@ +2008-06-12 Andrew Cagney <cagney@redhat.com> + + * ExternalException.java: New. + 2008-03-03 Andrew Cagney <cagney@redhat.com> * TestConfig.java: Move to frysk.config. diff --git a/frysk-sys/frysk/InternalException.java b/frysk-sys/frysk/InternalException.java new file mode 100644 index 0000000..fe85caa --- /dev/null +++ b/frysk-sys/frysk/InternalException.java @@ -0,0 +1,71 @@ +// 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; + +/** + * An internal problem has occured; for instance, we got an event we + * have no idea what to do with. This is different to a user or + * external exception in that the problem is occuring due to issues + * with the frysk code. When displaying InternalExceptions they + * should include a backtrace. + * + * Main-loop code catching this class of problem should print a full + * stack back trace. One way of doing this is: + * + * try { + * .. + * } catch (UserException e) { + * System.out.println(e.getMessage()); + * System.exit(1); + * } catch (RuntimeException e) { + * e.printStackTrace(System.out); + * System.exit(1); + * } + * + * The alternative is an internal, or runtime exception, where frysk's + * code base is internally getting things seriously wrong. + */ + +public class InternalException extends RuntimeException { + static final long serialVersionUID = 0; + public InternalException(String what) { + super(what); + } +} diff --git a/frysk-sys/frysk/UserException.java b/frysk-sys/frysk/UserException.java new file mode 100644 index 0000000..76ba9f7 --- /dev/null +++ b/frysk-sys/frysk/UserException.java @@ -0,0 +1,73 @@ +// 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; + +/** + * An exception triggered by information tied to the user, for + * instance a missing or corrupt input file. This can be considered, + * while still exceptional, a largely run-of-the-mill occurance and + * such exceptions should be displayed to the user as errors. + * + * Main-loop code catching this class of problem should just print the + * error message. One way of doing this is: + * + * try { + * .. + * } catch (UserException e) { + * System.out.println(e.getMessage()); + * System.exit(1); + * } catch (RuntimeException e) { + * e.printStackTrace(System.out); + * System.exit(1); + * } + * + * The alternative is an internal, or runtime exception, where frysk's + * code base is internally getting things seriously wrong. + */ + +public class UserException extends RuntimeException { + static final long serialVersionUID = 0; + public UserException(String message) { + super(message); + } + public UserException(String message, Throwable t) { + super(message, t); + } +} diff --git a/frysk-sys/frysk/expunit/ChangeLog b/frysk-sys/frysk/expunit/ChangeLog index 3434555..b81903d 100644 --- a/frysk-sys/frysk/expunit/ChangeLog +++ b/frysk-sys/frysk/expunit/ChangeLog @@ -1,3 +1,8 @@ +2008-06-12 Andrew Cagney <cagney@redhat.com> + + * TestExpect (testShell()): New. + * Expect.java (Expect()): New. + 2008-03-11 Andrew Cagney <cagney@redhat.com> * Child.java: Use LogFinest. diff --git a/frysk-sys/frysk/expunit/Expect.java b/frysk-sys/frysk/expunit/Expect.java index 1d07b91..d2542f6 100644 --- a/frysk-sys/frysk/expunit/Expect.java +++ b/frysk-sys/frysk/expunit/Expect.java @@ -91,6 +91,17 @@ public class Expect { } /** + * Create a bash shell sitting at a prompt. + */ + public Expect() { + this(new String[] { + "/bin/bash", "-c", + "export PS1=$\\ ; export PS2=>\\ ; exec /bin/bash --norc --noprofile" + }); + expect("\\$ "); + } + + /** * Clean up. * * XXX: This drains all outstanding WAITPID events, and SIGCHLD diff --git a/frysk-sys/frysk/expunit/TestExpect.java b/frysk-sys/frysk/expunit/TestExpect.java index 32bd302..b7b2f83 100644 --- a/frysk-sys/frysk/expunit/TestExpect.java +++ b/frysk-sys/frysk/expunit/TestExpect.java @@ -151,4 +151,13 @@ public class TestExpect }); assertEquals ("brk mode", "-brkint", g.toString ()); } + + public void testShell() { + Expect e = new Expect(); + // send a command, check that all, especially the prompt, are + // correct. + e.send("echo hi\r"); + e.expect("echo hi\r\nhi\r\n\\$ "); + } + } diff --git a/frysk-sys/frysk/rsl/ChangeLog b/frysk-sys/frysk/rsl/ChangeLog index f611e11..87484e4 100644 --- a/frysk-sys/frysk/rsl/ChangeLog +++ b/frysk-sys/frysk/rsl/ChangeLog @@ -1,3 +1,12 @@ +2008-06-20 Andrew Cagney <cagney@redhat.com> + + * Printer.java: Include the inner most stack frame when printing + exceptions. + +2008-06-19 Andrew Cagney <cagney@redhat.com> + + * Log.java: Add more methods. + 2008-06-04 Andrew Cagney <cagney@redhat.com> * Log.java (finest(Class)): New. diff --git a/frysk-sys/frysk/rsl/Log.java b/frysk-sys/frysk/rsl/Log.java index 1557332..27f1245 100644 --- a/frysk-sys/frysk/rsl/Log.java +++ b/frysk-sys/frysk/rsl/Log.java @@ -421,6 +421,13 @@ public final class Log { prefix(self).print(p1).print(p2).print(p3).print(p4).print(p5).print(p6).print(p7).print(p8).print(p9).print(p10).print(p11).suffix(); } + // dynamic 12 parameters + public void log(Object self, String p1, Object p2, String p3, long p4, String p5, long p6, String p7, int p8, String p9, int p10, String p11, int p12) { + if (!logging) + return; + prefix(self).print(p1).print(p2).print(p3).print(p4).print(p5).print(p6).print(p7).print(p8).print(p9).print(p10).print(p11).print(p12).suffix(); + } + /** * Assuming the use: <tt>log("caller", log.CALLER)</tt> prints the diff --git a/frysk-sys/frysk/rsl/Printer.java b/frysk-sys/frysk/rsl/Printer.java index a8e926d..5ebec05 100644 --- a/frysk-sys/frysk/rsl/Printer.java +++ b/frysk-sys/frysk/rsl/Printer.java @@ -158,11 +158,23 @@ public final class Printer { */ private void dump(Throwable t) { out.print("<<exception "); - out.print(t.toString()); - for (Throwable cause = t.getCause(); cause != null; - cause = cause.getCause()) { + while (true) { + out.print(t.toString()); + StackTraceElement[] stack = t.getStackTrace(); + for (int i = 0; i < stack.length; i++) { + if (i >= 1) { + // XXX: the cap is some what arbitrary + out.print(" ..."); + break; + } else { + out.print(" <at> "); + out.print(stack[i].toString()); + } + } + t = t.getCause(); + if (t == null) + break; out.print(" <caused-by> "); - out.print(cause.toString()); } out.print(">>"); } diff --git a/frysk-sys/frysk/sys/ChangeLog b/frysk-sys/frysk/sys/ChangeLog index 28e04a9..a96417f 100644 --- a/frysk-sys/frysk/sys/ChangeLog +++ b/frysk-sys/frysk/sys/ChangeLog @@ -1,3 +1,26 @@ +2008-07-07 Andrew Cagney <cagney@redhat.com> + + * cni/Fork.hxx: Remove utrace stubs. + * Fork.java: Ditto. + * jni/Fork.hxx: Ditto. + * jni/Fork.cxx: Ditto. + * cni/Fork.cxx: Ditto. + +2008-06-20 Andrew Cagney <cagney@redhat.com> + + * Poll.java: Move to frysk.sys.poll. + * PollBuilder.java: Ditto. + * jni/Poll.cxx: Ditto. + * cni/Poll.cxx: Ditto. + +2008-06-12 Andrew Cagney <cagney@redhat.com> + + * cni/Errno.cxx (throwUserException): New. + * cni/Errno.hxx (throwUserException): New. + + * Errno.java-sh: Extend ExternalException. + * cni/Errno.cxx: Update. + 2008-06-02 Andrew Cagney <cagney@redhat.com> * TestLeakingFileDescriptor.java: Mark as unsupported under JNI. diff --git a/frysk-sys/frysk/sys/Errno.java-sh b/frysk-sys/frysk/sys/Errno.java-sh index fdbf585..c87ae21 100644 --- a/frysk-sys/frysk/sys/Errno.java-sh +++ b/frysk-sys/frysk/sys/Errno.java-sh @@ -44,12 +44,14 @@ cat <<EOF package frysk.sys; +import frysk.UserException; + /** * Unix Host Errors. * * Do not confuse this with target errors and target error numbers. */ -public class Errno extends RuntimeException { +public class Errno extends UserException { static final long serialVersionUID = 0; private final String message; diff --git a/frysk-sys/frysk/sys/Fork.java b/frysk-sys/frysk/sys/Fork.java index 7e2f39c..46c98cb 100644 --- a/frysk-sys/frysk/sys/Fork.java +++ b/frysk-sys/frysk/sys/Fork.java @@ -53,9 +53,6 @@ public final class Fork { private static native int ptrace(String exe, String in, String out, String err, String[] args, String[] environ); - private static native int utrace(String exe, - String in, String out, String err, - String[] args, String[] environ); private static native int daemon(String exe, String in, String out, String err, String[] args, String[] environ); @@ -118,29 +115,6 @@ public final class Fork { } /** - * Create a child process running EXE with arguments ARGS[0...]; - * mark the process for utracing. - * - * Also wire up IN, OUT, and ERR. - */ - public static ProcessIdentifier utrace(File exe, - String in, String out, - String err, String[] args) { - return ProcessIdentifierFactory.create(utrace(exe.getPath(), - in, out, err, - args, null)); - } - /** - * Create a child process running ARGS[0] with arguments - * ARGV[0...]; mark the process for utracing. - */ - public static ProcessIdentifier utrace(String[] args) { - return ProcessIdentifierFactory.create(utrace(args[0], - null, null, null, - args, null)); - } - - /** * Create a "daemon" process running ARGV[0] with arguments * ARGV[1...]; a daemon has process ID 1 as its parent. */ diff --git a/frysk-sys/frysk/sys/Poll.java b/frysk-sys/frysk/sys/Poll.java deleted file mode 100644 index 8496fd8..0000000 --- a/frysk-sys/frysk/sys/Poll.java +++ /dev/null @@ -1,104 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2005, 2007, 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.sys; - -/** - * Poll like interface for waiting on kernel events. - * - * This object, loosely based on the poll and pselect interfaces, - * provides a call blocks until a UNIX event (signal, FD ready), the - * timeout expires, or an unexpected interrupt occures. The client - * (which extends this object) is notified via the abstract notify - * methods. - */ - -public final class Poll -{ - /** - * Set of signals checked during poll. - */ - static protected SignalSet signalSet = new SignalSet (); - private static native void addSignalHandler (Signal sig); - /** - * Add Sig to the set of signals checked during poll. - */ - public static void add (Signal sig) { - signalSet.add(sig); - addSignalHandler(sig); - } - /** - * Empty the set of signals, and file descriptors, checked during - * poll. - */ - public static void empty () - { - // Note that this doesn't restore any signal handlers. - signalSet.empty (); - } - - /** - * Manage the file descriptors watched by the poll call. - */ - public static final class Fds { - long fds; - public Fds() { - fds = malloc(); - } - protected void finalize() { - free(fds); - } - private static native long malloc(); - private static native void free(long fds); - public void addPollIn(int fd) { - fds = addPollIn(fds, fd); - } - private static native long addPollIn(long fds, int fd); - } - static protected Fds pollFds = new Fds (); - - /** - * Poll the system for either FD, or signal events. Block for - * timeout milliseconds (if timeout is +ve or zero), or until the - * next event (if timeout is -ve). Return when an event might - * have occured. - */ - public static native void poll (PollBuilder observer, - long timeout); -} diff --git a/frysk-sys/frysk/sys/PollBuilder.java b/frysk-sys/frysk/sys/PollBuilder.java deleted file mode 100644 index 8c13aab..0000000 --- a/frysk-sys/frysk/sys/PollBuilder.java +++ /dev/null @@ -1,48 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2005, 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.sys; - -/** - * Notify client of Poll events. - */ -public interface PollBuilder { - void signal(Signal sig); - void pollIn (int fd); -} diff --git a/frysk-sys/frysk/sys/cni/Errno.cxx b/frysk-sys/frysk/sys/cni/Errno.cxx index d2878c1..4ccac23 100644 --- a/frysk-sys/frysk/sys/cni/Errno.cxx +++ b/frysk-sys/frysk/sys/cni/Errno.cxx @@ -52,6 +52,7 @@ #include <java/lang/Thread.h> #include <java/lang/ArrayIndexOutOfBoundsException.h> +#include "frysk/UserException.h" #include "frysk/sys/Errno.h" #include "frysk/sys/Errno$Ebadf.h" #include "frysk/sys/Errno$Enomem.h" @@ -162,6 +163,14 @@ throwErrno (int err, const char *prefix) throwErrno (err, ajprintf ("%s: %s", prefix, strerror (err))); } +void throwUserException(const char *format, ...) { + va_list ap; + va_start(ap, format); + jstring message = vajprintf(format, ap); + va_end(ap); + throw new frysk::UserException(message); +} + void throwRuntimeException (const char *message) { diff --git a/frysk-sys/frysk/sys/cni/Errno.hxx b/frysk-sys/frysk/sys/cni/Errno.hxx index 6bcde43..5838b0f 100644 --- a/frysk-sys/frysk/sys/cni/Errno.hxx +++ b/frysk-sys/frysk/sys/cni/Errno.hxx @@ -47,6 +47,10 @@ extern void throwErrno (int err, const char *prefix) extern void throwErrno (int err, const char *prefix, const char *suffix, ...) __attribute__ ((noreturn)) __attribute__((format (printf, 3, 4))); +// <<prefix>>: <<strerror(err)>> (<<suffix>> ...) +extern void throwUserException(const char *format, ...) + __attribute__ ((noreturn)) __attribute__((format (printf, 1, 2))); + // <<message>> extern void throwRuntimeException (const char *message) __attribute__ ((noreturn)); diff --git a/frysk-sys/frysk/sys/cni/Fork.cxx b/frysk-sys/frysk/sys/cni/Fork.cxx index 9d35ffd..ef6e3a8 100644 --- a/frysk-sys/frysk/sys/cni/Fork.cxx +++ b/frysk-sys/frysk/sys/cni/Fork.cxx @@ -115,9 +115,6 @@ spawn(tracing trace, redirect& redirection, exec& execute) { ::_exit(errno); } break; - case UTRACE: - fprintf(stderr, "\n\n>>>>> in spawn(...utrace)\n\n"); - break; case CHILD: break; case DAEMON: @@ -188,13 +185,6 @@ frysk::sys::Fork::ptrace(jstring exe, } jint -frysk::sys::Fork::utrace(jstring exe, - jstring in, jstring out, jstring err, - jstringArray args, jstringArray environ) { - return ::spawn(exe, in, out, err, args, environ, UTRACE); -} - -jint frysk::sys::Fork::daemon (jstring exe, jstring in, jstring out, jstring err, jstringArray args, jstringArray environ) { return ::spawn(exe, in, out, err, args, environ, DAEMON); diff --git a/frysk-sys/frysk/sys/cni/Fork.hxx b/frysk-sys/frysk/sys/cni/Fork.hxx index a4b8438..2cc021b 100644 --- a/frysk-sys/frysk/sys/cni/Fork.hxx +++ b/frysk-sys/frysk/sys/cni/Fork.hxx @@ -41,7 +41,6 @@ enum tracing { CHILD, DAEMON, PTRACE, - UTRACE, }; /** diff --git a/frysk-sys/frysk/sys/cni/Poll.cxx b/frysk-sys/frysk/sys/cni/Poll.cxx deleted file mode 100644 index 1cffb92..0000000 --- a/frysk-sys/frysk/sys/cni/Poll.cxx +++ /dev/null @@ -1,245 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2005, 2006, 2007, 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. - -#include <sys/poll.h> -#include <setjmp.h> -#include <signal.h> -#include <alloca.h> -#include <errno.h> -#include <pthread.h> -#include <stdio.h> -#include <sys/types.h> -#include <unistd.h> -#include <linux/unistd.h> -#include <linux.syscall.h> - -_syscall2(int, tkill, pid_t, tid, int, sig); - -#include <gcj/cni.h> -#include <gnu/gcj/RawDataManaged.h> - -#include "frysk/sys/cni/Errno.hxx" -#include "frysk/sys/ProcessIdentifier.h" -#include "frysk/sys/Tid.h" -#include "frysk/sys/Poll.h" -#include "frysk/sys/Signal.h" -#include "frysk/sys/SignalSet.h" -#include "frysk/sys/cni/SignalSet.hxx" -#include "frysk/sys/Poll$Fds.h" -#include "frysk/sys/PollBuilder.h" - - -// If there's a signal abort the wait() function using a longjmp (and -// return the signal). Should the jmpbuf be per-thread? - -struct poll_jmpbuf { - pid_t tid; - sigjmp_buf buf; -}; -struct poll_jmpbuf poll_jmpbuf; - -static void -handler (int signum, siginfo_t *siginfo, void *context) -{ - // For what ever reason, the signal can come in on the wrong thread. - // When that occures, re-direct it (explicitly) to the thread that - // can handle the signal. - pid_t me = frysk::sys::Tid::tid(); - if (poll_jmpbuf.tid == me) { -#if 0 - fprintf (stderr, "pid %d got signal %d (%s) from %d\n", - me, siginfo->si_signo, strsignal (siginfo->si_signo), - siginfo->si_pid); -#endif - siglongjmp (poll_jmpbuf.buf, signum); - } - else - // XXX: Want to edit this thread's mask so that from now on it - // blocks this signal, don't know a way to do it though. - tkill (poll_jmpbuf.tid, signum); -} - -void -frysk::sys::Poll::addSignalHandler (frysk::sys::Signal* sig) -{ - int signum = sig->hashCode (); - // Make certain that the signal is masked (this is ment to be - // process wide). - sigset_t mask; - sigemptyset (&mask); - sigaddset (&mask, signum); - // XXX: In a multi-threaded environment this call is not well - // defined (although it does help reduce the number of signals - // directed to the wrong thread). - sigprocmask (SIG_BLOCK, &mask, NULL); - // Install the above signal handler (it long jumps back to the code - // that enabled the signal). To avoid potential recursion, all - // signals are masked while the handler is running. - struct sigaction sa; - memset (&sa, 0, sizeof (sa)); - sa.sa_sigaction = handler; - sa.sa_flags = SA_SIGINFO; - sigfillset (&sa.sa_mask); - sigaction (signum, &sa, NULL); -} - - - -jlong -frysk::sys::Poll$Fds::malloc() { - // Allocate a non-empty buffer, marked with a sentinel. - struct pollfd* fds = (struct pollfd*) JvMalloc(sizeof (struct pollfd)); - fds->fd = -1; // sentinel - return (jlong)(long) fds; -} - -void -frysk::sys::Poll$Fds::free(jlong fds) { - JvFree((struct pollfd*)(long)fds); -} - -static jlong -addPollFd(jlong pollFds, int fd, short event) { - struct pollfd* ufds = (struct pollfd*) pollFds; - // If the FD is alreay listed, just add the event; end up with a - // count of fds. - int numFds; - for (numFds = 0; ufds[numFds].fd >= 0; numFds++) { - if (ufds[numFds].fd == fd) { - ufds[numFds].events |= event; - return pollFds; - } - } - // Create space for the new fd (and retain space for the sentinel). - ufds = (struct pollfd*) JvRealloc(ufds, (numFds + 2) * sizeof (struct pollfd)); - ufds[numFds + 0].fd = fd; - ufds[numFds + 0].events = event; - ufds[numFds + 1].fd = -1; - return (jlong) (long) ufds; -} - -jlong -frysk::sys::Poll$Fds::addPollIn(jlong fds, jint fd) { - return addPollFd(fds, fd, POLLIN); -} - - - -void -frysk::sys::Poll::poll(frysk::sys::PollBuilder* pollObserver, jlong timeout) { - // Compute the current number of poll fds. - struct pollfd* fds = (struct pollfd*)pollFds->fds; - int numFds; - for (numFds = 0; fds[numFds].fd >= 0; numFds++); - - // Set up a SIGSETJMP call that jumps back to here when any watched - // signal is delivered. The signals are accumulated in a sigset, - // and removed from the current of signals being unmasked, and the - // timer is set to zero forcing a non-blocking poll. - - sigset_t signals; - sigemptyset (&signals); - sigset_t mask = *getRawSet (signalSet); - int signum = sigsetjmp (poll_jmpbuf.buf, 1); - if (signum > 0) { - // Remove the signal from the local copy of the signal-mask set, - // doing this allows other signals to get through (otherwize this - // code could be swamped by a single re-occuring signal). - sigdelset (&mask, signum); - // Add it to those that have fired. - sigaddset (&signals, signum); - // Make the poll non-blocking. Now that at least one event has - // been detected, this method should not block instead returning - // immediatly after the file descriptors have been polled. - timeout = 0; - } - - // Unblock signals, and then wait for an event. There is a window - // between the unmask and poll system calls during which a signal - // could be delivered that doesn't interrupt the poll call. Avoid - // this race by having the signal handler longjmp back to the above - // setjmp, re-starting this code, forcing the poll (even if it - // wasn't reached) to be canceled. - - poll_jmpbuf.tid = frysk::sys::Tid::tid(); - errno = ::pthread_sigmask (SIG_UNBLOCK, &mask, 0); - if (errno != 0) - throwErrno (errno, "pthread_sigmask.UNBLOCK"); - int status = ::poll (fds, numFds, timeout); - if (status < 0) - status = -errno; // Save the errno across the next system call. - errno = ::pthread_sigmask (SIG_BLOCK, &mask, NULL); - if (errno != 0) - throwErrno (errno, "pthread_sigmask.BLOCK"); - - // Did something go wrong? - if (status < 0) { - switch (-status) { - case EINTR: - break; - default: - throwErrno (-status, "poll"); - } - } - - // Deliver any signals received during the poll; XXX: Is there a - // more efficient way of doing this? - - for (int i = 1; i < 32; i++) { - if (sigismember (&signals, i)) { - // Find the signal object. - frysk::sys::Signal* sig = frysk::sys::Signal::valueOf (i); - // Notify the client of the signal. - pollObserver->signal (sig); - } - } - - // Did a file descriptor fire, status when +ve, contains the number - // of file descriptors that fired one or more events. - - struct pollfd* pollfd = (struct pollfd*) pollFds; - while (status > 0) { - if (pollfd->revents != 0) { - if (pollfd->revents & POLLIN) - pollObserver->pollIn (pollfd->fd); - status--; - } - pollfd++; - } -} diff --git a/frysk-sys/frysk/sys/jni/Fork.cxx b/frysk-sys/frysk/sys/jni/Fork.cxx index 02d9799..bb1549b 100644 --- a/frysk-sys/frysk/sys/jni/Fork.cxx +++ b/frysk-sys/frysk/sys/jni/Fork.cxx @@ -115,9 +115,6 @@ spawn(jnixx::env env, tracing trace, redirect& redirection, exec& execute) { ::_exit(errno); } break; - case UTRACE: - fprintf(stderr, "\n\n>>>>> in spawn(...utrace)\n\n"); - break; case CHILD: break; case DAEMON: @@ -199,14 +196,6 @@ frysk::sys::Fork::ptrace(jnixx::env env, String exe, } jint -frysk::sys::Fork::utrace(jnixx::env env, String exe, - String in, String out, String err, - jnixx::array<String> args, - jnixx::array<String> environ) { - return ::spawn(env, exe, in, out, err, args, environ, UTRACE); -} - -jint frysk::sys::Fork::daemon(jnixx::env env, String exe, String in, String out, String err, jnixx::array<String> args, diff --git a/frysk-sys/frysk/sys/jni/Fork.hxx b/frysk-sys/frysk/sys/jni/Fork.hxx index 2df12a4..6bf9dd1 100644 --- a/frysk-sys/frysk/sys/jni/Fork.hxx +++ b/frysk-sys/frysk/sys/jni/Fork.hxx @@ -41,7 +41,6 @@ enum tracing { CHILD, DAEMON, PTRACE, - UTRACE, }; /** diff --git a/frysk-sys/frysk/sys/jni/Poll.cxx b/frysk-sys/frysk/sys/jni/Poll.cxx deleted file mode 100644 index a0f0eaa..0000000 --- a/frysk-sys/frysk/sys/jni/Poll.cxx +++ /dev/null @@ -1,239 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2005, 2006, 2007, 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. - -#include <malloc.h> -#include <string.h> -#include <sys/poll.h> -#include <setjmp.h> -#include <signal.h> -#include <alloca.h> -#include <errno.h> -#include <pthread.h> -#include <stdio.h> -#include <sys/types.h> -#include <unistd.h> -#include <linux/unistd.h> -#include <linux.syscall.h> -#include <sys/syscall.h> - -#include "jni.hxx" - -#include "jnixx/exceptions.hxx" -#include "frysk/sys/jni/SignalSet.hxx" - -using namespace java::lang; -using namespace frysk::sys; - -// If there's a signal abort the wait() function using a longjmp (and -// return the signal). Should the jmpbuf be per-thread? - -struct poll_jmpbuf { - pid_t tid; - sigjmp_buf buf; -}; -struct poll_jmpbuf poll_jmpbuf; - -static void -handler(int signum, siginfo_t *siginfo, void *context) { - // For what ever reason, the signal can come in on the wrong thread. - // When that occures, re-direct it (explicitly) to the thread that - // can handle the signal. - pid_t me = ::syscall(SYS_gettid); - if (poll_jmpbuf.tid == me) { -#if 0 - fprintf (stderr, "pid %d got signal %d (%s) from %d\n", - me, siginfo->si_signo, strsignal (siginfo->si_signo), - siginfo->si_pid); -#endif - siglongjmp (poll_jmpbuf.buf, signum); - } - else - // XXX: Want to edit this thread's mask so that from now on it - // blocks this signal, don't know a way to do it though. - ::syscall(SYS_tkill, poll_jmpbuf.tid, signum); -} - -void -Poll::addSignalHandler(jnixx::env env, Signal sig) { - int signum = sig.hashCode(env); - // Make certain that the signal is masked (this is ment to be - // process wide). - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, signum); - // XXX: In a multi-threaded environment this call is not well - // defined (although it does help reduce the number of signals - // directed to the wrong thread). - sigprocmask(SIG_BLOCK, &mask, NULL); - // Install the above signal handler (it long jumps back to the code - // that enabled the signal). To avoid potential recursion, all - // signals are masked while the handler is running. - struct sigaction sa; - memset(&sa, 0, sizeof (sa)); - sa.sa_sigaction = handler; - sa.sa_flags = SA_SIGINFO; - sigfillset(&sa.sa_mask); - sigaction(signum, &sa, NULL); -} - - - -jlong -Poll$Fds::malloc(jnixx::env env) { - // Allocate a non-empty buffer, marked with a sentinel. - struct pollfd* fds = (struct pollfd*) ::malloc (sizeof (struct pollfd)); - fds->fd = -1; // sentinel - return (jlong)(long) fds; -} - -void -Poll$Fds::free(jnixx::env env, jlong fds) { - ::free((struct pollfd*)(long)fds); -} - -static jlong -addPollFd(jlong pollFds, int fd, short event) { - struct pollfd* ufds = (struct pollfd*) pollFds; - // If the FD is alreay listed, just add the event; end up with a - // count of fds. - int numFds; - for (numFds = 0; ufds[numFds].fd >= 0; numFds++) { - if (ufds[numFds].fd == fd) { - ufds[numFds].events |= event; - return pollFds; - } - } - // Create space for the new fd (and retain space for the sentinel). - ufds = (struct pollfd*) ::realloc(ufds, (numFds + 2) * sizeof (struct pollfd)); - ufds[numFds + 0].fd = fd; - ufds[numFds + 0].events = event; - ufds[numFds + 1].fd = -1; - return (jlong) (long) ufds; -} - -jlong -Poll$Fds::addPollIn(jnixx::env env, jlong fds, jint fd) { - return addPollFd(fds, fd, POLLIN); -} - - - -void -Poll::poll(jnixx::env env, PollBuilder pollObserver, jlong timeout) { - // Compute the current number of poll fds. - struct pollfd* fds = (struct pollfd*)GetPollFds(env).GetFds(env); - int numFds; - for (numFds = 0; fds[numFds].fd >= 0; numFds++); - - // Set up a SIGSETJMP call that jumps back to here when any watched - // signal is delivered. The signals are accumulated in a sigset, - // and removed from the current of signals being unmasked, and the - // timer is set to zero forcing a non-blocking poll. - - sigset_t signals; - sigemptyset(&signals); - sigset_t mask = *getRawSet(env, GetSignalSet(env)); - int signum = sigsetjmp(poll_jmpbuf.buf, 1); - if (signum > 0) { - // Remove the signal from the local copy of the signal-mask set, - // doing this allows other signals to get through (otherwize this - // code could be swamped by a single re-occuring signal). - sigdelset(&mask, signum); - // Add it to those that have fired. - sigaddset(&signals, signum); - // Make the poll non-blocking. Now that at least one event has - // been detected, this method should not block instead returning - // immediatly after the file descriptors have been polled. - timeout = 0; - } - - // Unblock signals, and then wait for an event. There is a window - // between the unmask and poll system calls during which a signal - // could be delivered that doesn't interrupt the poll call. Avoid - // this race by having the signal handler longjmp back to the above - // setjmp, re-starting this code, forcing the poll (even if it - // wasn't reached) to be canceled. - - poll_jmpbuf.tid = ::syscall(SYS_gettid); - errno = ::pthread_sigmask (SIG_UNBLOCK, &mask, 0); - if (errno != 0) - errnoException(env, errno, "pthread_sigmask.UNBLOCK"); - int status = ::poll (fds, numFds, timeout); - if (status < 0) - status = -errno; // Save the errno across the next system call. - errno = ::pthread_sigmask (SIG_BLOCK, &mask, NULL); - if (errno != 0) - errnoException(env, errno, "pthread_sigmask.BLOCK"); - - // Did something go wrong? - if (status < 0) { - switch (-status) { - case EINTR: - break; - default: - errnoException(env, -status, "poll"); - } - } - - // Deliver any signals received during the poll; XXX: Is there a - // more efficient way of doing this? - - for (int i = 1; i < 32; i++) { - if (sigismember (&signals, i)) { - // Find the signal object. - Signal sig = Signal::valueOf(env, i); - // Notify the client of the signal. - pollObserver.signal(env, sig); - } - } - - // Did a file descriptor fire, status when +ve, contains the number - // of file descriptors that fired one or more events. - - for (int i = 0; i < numFds; i++) { - if (status <= 0) - // bail early - break; - if (fds[i].revents != 0) { - if (fds[i].revents & POLLIN) - pollObserver.pollIn(env, fds[i].fd); - status--; - } - } -} diff --git a/frysk-sys/frysk/sys/poll/ChangeLog b/frysk-sys/frysk/sys/poll/ChangeLog new file mode 100644 index 0000000..236b189 --- /dev/null +++ b/frysk-sys/frysk/sys/poll/ChangeLog @@ -0,0 +1,16 @@ +2008-06-20 Andrew Cagney <cagney@redhat.com> + + * Poll.java: Moved from frysk.sys. + * PollBuilder.java: Ditto. + * jni/Poll.cxx: Ditto. + * cni/Poll.cxx: Ditto. + * PollFileDescriptors.java: Extract from Poll.java. + * jni/PollFileDescriptors.java: Extract from jni/Poll.cxx. + * cni/PollFileDescriptors.java: Similar. + +Local Variables: +mode: change-log +left-margin: 8 +fill-column: 74 +version-control: never +End: diff --git a/frysk-sys/frysk/sys/poll/Poll.java b/frysk-sys/frysk/sys/poll/Poll.java new file mode 100644 index 0000000..bef9c0a --- /dev/null +++ b/frysk-sys/frysk/sys/poll/Poll.java @@ -0,0 +1,93 @@ +// This file is part of the program FRYSK. +// +// Copyright 2005, 2007, 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.sys.poll; + +import frysk.sys.SignalSet; +import frysk.sys.Signal; + +/** + * Poll like interface for waiting on kernel events. + * + * This object, loosely based on the poll and pselect interfaces, + * provides a call blocks until a UNIX event (signal, FD ready), the + * timeout expires, or an unexpected interrupt occures. The client + * (which extends this object) is notified via the abstract notify + * methods. + */ + +public final class Poll { + /** + * Set of signals checked during poll. + */ + static protected SignalSet signalSet = new SignalSet (); + /** + * Add Sig to the set of signals checked during poll. + */ + public static void add(Signal sig) { + signalSet.add(sig); + addSignalHandler(sig); + } + private static native void addSignalHandler(Signal sig); + /** + * Empty the set of signals, and file descriptors, checked during + * poll. + */ + public static void empty() { + // Note that this doesn't restore any signal handlers. + signalSet.empty (); + } + + /** + * Poll the system for either FD, or signal events. Block for + * timeout milliseconds (if timeout is +ve or zero), or until the + * next event (if timeout is -ve). Return when an event might + * have occured. + */ + public static void poll(PollBuilder observer, long timeout) { + poll(observer, timeout, pollFds.pollFds, pollFds.fds.toArray()); + } + private static native void poll(PollBuilder observer, long timeout, + long pollFds, Object[] fds); + + /** + * Set of pollfdS. + */ + static protected PollFileDescriptors pollFds = new PollFileDescriptors(); +} diff --git a/frysk-sys/frysk/sys/poll/PollBuilder.java b/frysk-sys/frysk/sys/poll/PollBuilder.java new file mode 100644 index 0000000..d3f6c3d --- /dev/null +++ b/frysk-sys/frysk/sys/poll/PollBuilder.java @@ -0,0 +1,51 @@ +// This file is part of the program FRYSK. +// +// Copyright 2005, 2007, 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.sys.poll; + +import frysk.sys.Signal; +import frysk.sys.FileDescriptor; + +/** + * Notify client of Poll events. + */ +public interface PollBuilder { + void signal(Signal sig); + void pollIn(FileDescriptor fd); +} diff --git a/frysk-sys/frysk/sys/poll/PollFileDescriptors.java b/frysk-sys/frysk/sys/poll/PollFileDescriptors.java new file mode 100644 index 0000000..0f1380e --- /dev/null +++ b/frysk-sys/frysk/sys/poll/PollFileDescriptors.java @@ -0,0 +1,73 @@ +// This file is part of the program FRYSK. +// +// Copyright 2005, 2007, 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.sys.poll; + +import frysk.sys.FileDescriptor; + +import java.util.ArrayList; + +/** + * Manage the file descriptors watched by the poll call. + */ +public class PollFileDescriptors { + long pollFds = malloc(); + private static native long malloc(); + final ArrayList fds = new ArrayList(); + + public PollFileDescriptors() { + } + + protected void finalize() { + free(pollFds); + } + private static native void free(long pollFds); + + public void addPollIn(FileDescriptor fd) { + int i = fds.indexOf(fd); + if (i >= 0) { + setPollIn(pollFds, i); + } else { + fds.add(fd); + pollFds = addPollIn(pollFds, fds.size(), fd.getFd()); + } + } + private static native void setPollIn(long pollFds, int pos); + private static native long addPollIn(long pollFds, int pos, int fd); +} diff --git a/frysk-sys/frysk/sys/poll/cni/Poll.cxx b/frysk-sys/frysk/sys/poll/cni/Poll.cxx new file mode 100644 index 0000000..5d6f367 --- /dev/null +++ b/frysk-sys/frysk/sys/poll/cni/Poll.cxx @@ -0,0 +1,203 @@ +// This file is part of the program FRYSK. +// +// Copyright 2005, 2006, 2007, 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. + +#include <sys/poll.h> +#include <setjmp.h> +#include <signal.h> +#include <alloca.h> +#include <errno.h> +#include <pthread.h> +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> +#include <linux/unistd.h> +#include <linux.syscall.h> + +_syscall2(int, tkill, pid_t, tid, int, sig); + +#include <gcj/cni.h> + +#include "frysk/sys/cni/Errno.hxx" +#include "frysk/sys/ProcessIdentifier.h" +#include "frysk/sys/FileDescriptor.h" +#include "frysk/sys/Tid.h" +#include "frysk/sys/Signal.h" +#include "frysk/sys/SignalSet.h" +#include "frysk/sys/cni/SignalSet.hxx" +#include "frysk/sys/poll/Poll.h" +#include "frysk/sys/poll/PollBuilder.h" + +using namespace java::lang; +using namespace frysk::sys::poll; + +// If there's a signal abort the wait() function using a longjmp (and +// return the signal). Should the jmpbuf be per-thread? + +struct poll_jmpbuf { + pid_t tid; + sigjmp_buf buf; +}; +struct poll_jmpbuf poll_jmpbuf; + +static void +handler (int signum, siginfo_t *siginfo, void *context) +{ + // For what ever reason, the signal can come in on the wrong thread. + // When that occures, re-direct it (explicitly) to the thread that + // can handle the signal. + pid_t me = frysk::sys::Tid::tid(); + if (poll_jmpbuf.tid == me) { +#if 0 + fprintf (stderr, "pid %d got signal %d (%s) from %d\n", + me, siginfo->si_signo, strsignal (siginfo->si_signo), + siginfo->si_pid); +#endif + siglongjmp (poll_jmpbuf.buf, signum); + } + else + // XXX: Want to edit this thread's mask so that from now on it + // blocks this signal, don't know a way to do it though. + tkill (poll_jmpbuf.tid, signum); +} + +void +Poll::addSignalHandler (frysk::sys::Signal* sig) { + int signum = sig->hashCode (); + // Make certain that the signal is masked (this is ment to be + // process wide). + sigset_t mask; + sigemptyset (&mask); + sigaddset (&mask, signum); + // XXX: In a multi-threaded environment this call is not well + // defined (although it does help reduce the number of signals + // directed to the wrong thread). + sigprocmask (SIG_BLOCK, &mask, NULL); + // Install the above signal handler (it long jumps back to the code + // that enabled the signal). To avoid potential recursion, all + // signals are masked while the handler is running. + struct sigaction sa; + memset (&sa, 0, sizeof (sa)); + sa.sa_sigaction = handler; + sa.sa_flags = SA_SIGINFO; + sigfillset (&sa.sa_mask); + sigaction (signum, &sa, NULL); +} + + + +#define POLLFDS ((struct pollfd*)pollFds) + +void +Poll::poll(PollBuilder* pollObserver, jlong timeout, jlong pollFds, + jobjectArray fds) { + int nfds = fds->length; + + // Set up a SIGSETJMP call that jumps back to here when any watched + // signal is delivered. The signals are accumulated in a sigset, + // and removed from the current of signals being unmasked, and the + // timer is set to zero forcing a non-blocking poll. + + sigset_t signals; + sigemptyset (&signals); + sigset_t mask = *getRawSet (signalSet); + int signum = sigsetjmp (poll_jmpbuf.buf, 1); + if (signum > 0) { + // Remove the signal from the local copy of the signal-mask set, + // doing this allows other signals to get through (otherwize this + // code could be swamped by a single re-occuring signal). + sigdelset (&mask, signum); + // Add it to those that have fired. + sigaddset (&signals, signum); + // Make the poll non-blocking. Now that at least one event has + // been detected, this method should not block instead returning + // immediatly after the file descriptors have been polled. + timeout = 0; + } + + // Unblock signals, and then wait for an event. There is a window + // between the unmask and poll system calls during which a signal + // could be delivered that doesn't interrupt the poll call. Avoid + // this race by having the signal handler longjmp back to the above + // setjmp, re-starting this code, forcing the poll (even if it + // wasn't reached) to be canceled. + + poll_jmpbuf.tid = frysk::sys::Tid::tid(); + errno = ::pthread_sigmask (SIG_UNBLOCK, &mask, 0); + if (errno != 0) + throwErrno (errno, "pthread_sigmask.UNBLOCK"); + int status = ::poll(POLLFDS, nfds, timeout); + if (status < 0) + status = -errno; // Save the errno across the next system call. + errno = ::pthread_sigmask(SIG_BLOCK, &mask, NULL); + if (errno != 0) + throwErrno(errno, "pthread_sigmask.BLOCK"); + + // Did something go wrong? + if (status < 0) { + switch (-status) { + case EINTR: + break; + default: + throwErrno(-status, "poll"); + } + } + + // Deliver any signals received during the poll; XXX: Is there a + // more efficient way of doing this? + + for (int i = 1; i < 32; i++) { + if (sigismember (&signals, i)) { + // Find the signal object. + frysk::sys::Signal* sig = frysk::sys::Signal::valueOf (i); + // Notify the client of the signal. + pollObserver->signal(sig); + } + } + + // Did a file descriptor fire, status when +ve, contains the number + // of file descriptors that fired one or more events. + + for (int i = 0; i < nfds && status > 0; i++) { + if (POLLFDS[i].revents != 0) { + if (POLLFDS[i].revents & POLLIN) + pollObserver->pollIn((frysk::sys::FileDescriptor*)(elements(fds)[i])); + status--; + } + } +} diff --git a/frysk-sys/frysk/sys/poll/cni/PollFileDescriptors.cxx b/frysk-sys/frysk/sys/poll/cni/PollFileDescriptors.cxx new file mode 100644 index 0000000..e03424b --- /dev/null +++ b/frysk-sys/frysk/sys/poll/cni/PollFileDescriptors.cxx @@ -0,0 +1,77 @@ +// This file is part of the program FRYSK. +// +// Copyright 2005, 2006, 2007, 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. + +#include <poll.h> + +#include <gcj/cni.h> + +#include "frysk/sys/FileDescriptor.h" +#include "frysk/sys/poll/PollFileDescriptors.h" + +using namespace java::lang; +using namespace frysk::sys::poll; + +#define POLLFDS ((struct pollfd*)pollFds) + +jlong +PollFileDescriptors::malloc() { + // Allocate a non-empty buffer, marked with a sentinel. + struct pollfd* pollFds = (struct pollfd*) JvMalloc(sizeof (struct pollfd)); + return (jlong)(long)pollFds; +} + +void +PollFileDescriptors::free(jlong pollFds) { + JvFree(POLLFDS); +} + +void +PollFileDescriptors::setPollIn(jlong pollFds, jint pos) { + POLLFDS[pos].events |= POLLIN; +} + +jlong +PollFileDescriptors::addPollIn(jlong pollFds, jint pos, jint fd) { + // Create space for the new fd (and retain space for the sentinel). + struct pollfd* ufds + = (struct pollfd*) JvRealloc(POLLFDS, (pos + 1)*sizeof (struct pollfd)); + ufds[pos].fd = fd; + ufds[pos].events = POLLIN; + return (jlong) (long) ufds; +} diff --git a/frysk-sys/frysk/sys/poll/jni/Poll.cxx b/frysk-sys/frysk/sys/poll/jni/Poll.cxx new file mode 100644 index 0000000..85950c0 --- /dev/null +++ b/frysk-sys/frysk/sys/poll/jni/Poll.cxx @@ -0,0 +1,199 @@ +// This file is part of the program FRYSK. +// +// Copyright 2005, 2006, 2007, 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. + +#include <malloc.h> +#include <string.h> +#include <sys/poll.h> +#include <setjmp.h> +#include <signal.h> +#include <alloca.h> +#include <errno.h> +#include <pthread.h> +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> +#include <linux/unistd.h> +#include <linux.syscall.h> +#include <sys/syscall.h> + +#include "jni.hxx" + +#include "jnixx/exceptions.hxx" +#include "frysk/sys/jni/SignalSet.hxx" + +using namespace java::lang; +using namespace frysk::sys::poll; + +// If there's a signal abort the wait() function using a longjmp (and +// return the signal). Should the jmpbuf be per-thread? + +struct poll_jmpbuf { + pid_t tid; + sigjmp_buf buf; +}; +struct poll_jmpbuf poll_jmpbuf; + +static void +handler(int signum, siginfo_t *siginfo, void *context) { + // For what ever reason, the signal can come in on the wrong thread. + // When that occures, re-direct it (explicitly) to the thread that + // can handle the signal. + pid_t me = ::syscall(SYS_gettid); + if (poll_jmpbuf.tid == me) { +#if 0 + fprintf (stderr, "pid %d got signal %d (%s) from %d\n", + me, siginfo->si_signo, strsignal (siginfo->si_signo), + siginfo->si_pid); +#endif + siglongjmp (poll_jmpbuf.buf, signum); + } + else + // XXX: Want to edit this thread's mask so that from now on it + // blocks this signal, don't know a way to do it though. + ::syscall(SYS_tkill, poll_jmpbuf.tid, signum); +} + +void +Poll::addSignalHandler(jnixx::env env, Signal sig) { + int signum = sig.hashCode(env); + // Make certain that the signal is masked (this is ment to be + // process wide). + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, signum); + // XXX: In a multi-threaded environment this call is not well + // defined (although it does help reduce the number of signals + // directed to the wrong thread). + sigprocmask(SIG_BLOCK, &mask, NULL); + // Install the above signal handler (it long jumps back to the code + // that enabled the signal). To avoid potential recursion, all + // signals are masked while the handler is running. + struct sigaction sa; + memset(&sa, 0, sizeof (sa)); + sa.sa_sigaction = handler; + sa.sa_flags = SA_SIGINFO; + sigfillset(&sa.sa_mask); + sigaction(signum, &sa, NULL); +} + + + +#define POLLFDS ((struct pollfd*)pollFds) + +void +Poll::poll(jnixx::env env, PollBuilder pollObserver, jlong timeout, + jlong pollFds, ::jnixx::array<Object> fds) { + int nfds = fds.GetArrayLength(env); + + // Set up a SIGSETJMP call that jumps back to here when any watched + // signal is delivered. The signals are accumulated in a sigset, + // and removed from the current of signals being unmasked, and the + // timer is set to zero forcing a non-blocking poll. + + sigset_t signals; + sigemptyset(&signals); + sigset_t mask = *getRawSet(env, GetSignalSet(env)); + int signum = sigsetjmp(poll_jmpbuf.buf, 1); + if (signum > 0) { + // Remove the signal from the local copy of the signal-mask set, + // doing this allows other signals to get through (otherwize this + // code could be swamped by a single re-occuring signal). + sigdelset(&mask, signum); + // Add it to those that have fired. + sigaddset(&signals, signum); + // Make the poll non-blocking. Now that at least one event has + // been detected, this method should not block instead returning + // immediatly after the file descriptors have been polled. + timeout = 0; + } + + // Unblock signals, and then wait for an event. There is a window + // between the unmask and poll system calls during which a signal + // could be delivered that doesn't interrupt the poll call. Avoid + // this race by having the signal handler longjmp back to the above + // setjmp, re-starting this code, forcing the poll (even if it + // wasn't reached) to be canceled. + + poll_jmpbuf.tid = ::syscall(SYS_gettid); + errno = ::pthread_sigmask(SIG_UNBLOCK, &mask, 0); + if (errno != 0) + errnoException(env, errno, "pthread_sigmask.UNBLOCK"); + int status = ::poll(POLLFDS, nfds, timeout); + if (status < 0) + status = -errno; // Save the errno across the next system call. + errno = ::pthread_sigmask(SIG_BLOCK, &mask, NULL); + if (errno != 0) + errnoException(env, errno, "pthread_sigmask.BLOCK"); + + // Did something go wrong? + if (status < 0) { + switch (-status) { + case EINTR: + break; + default: + errnoException(env, -status, "poll"); + } + } + + // Deliver any signals received during the poll; XXX: Is there a + // more efficient way of doing this? + + for (int i = 1; i < 32; i++) { + if (sigismember(&signals, i)) { + // Find the signal object. + Signal sig = Signal::valueOf(env, i); + // Notify the client of the signal. + pollObserver.signal(env, sig); + } + } + + // Did a file descriptor fire, status when +ve, contains the number + // of file descriptors that fired one or more events. + + for (int i = 0; i < nfds && status > 0; i++) { + if (POLLFDS[i].revents != 0) { + if (POLLFDS[i].revents & POLLIN) { + frysk::sys::FileDescriptor fd + = frysk::sys::FileDescriptor(env, fds.GetObjectArrayElement(env, i)._object); + pollObserver.pollIn(env, fd); + } + status--; + } + } +} diff --git a/frysk-sys/frysk/sys/poll/jni/PollFileDescriptors.cxx b/frysk-sys/frysk/sys/poll/jni/PollFileDescriptors.cxx new file mode 100644 index 0000000..586d34c --- /dev/null +++ b/frysk-sys/frysk/sys/poll/jni/PollFileDescriptors.cxx @@ -0,0 +1,77 @@ +// This file is part of the program FRYSK. +// +// Copyright 2005, 2006, 2007, 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. + +#include <poll.h> +#include <malloc.h> + +#include "jni.hxx" + +using namespace java::lang; +using namespace frysk::sys::poll; + +#define POLLFDS ((struct pollfd*)pollFds) + +jlong +PollFileDescriptors::malloc(jnixx::env env) { + // Allocate a non-empty buffer, marked with a sentinel. + struct pollfd* fds = (struct pollfd*) ::malloc (sizeof (struct pollfd)); + fds->fd = -1; // sentinel + return (jlong)(long) fds; +} + +void +PollFileDescriptors::free(jnixx::env env, jlong pollFds) { + ::free(POLLFDS); +} + +void +PollFileDescriptors::setPollIn(jnixx::env env, jlong pollFds, jint pos) { + POLLFDS[pos].events |= POLLIN; +} + +jlong +PollFileDescriptors::addPollIn(jnixx::env env, jlong pollFds, + jint pos, int fd) { + // Create space for the new fd (and retain space for the sentinel). + struct pollfd* ufds + = (struct pollfd*) ::realloc(POLLFDS, (pos + 1)*sizeof (struct pollfd)); + ufds[pos].fd = fd; + ufds[pos].events = POLLIN; + return (jlong) (long) ufds; +} diff --git a/frysk-sys/frysk/sys/proc/ChangeLog b/frysk-sys/frysk/sys/proc/ChangeLog index 84cf92d..b6ac106 100644 --- a/frysk-sys/frysk/sys/proc/ChangeLog +++ b/frysk-sys/frysk/sys/proc/ChangeLog @@ -1,3 +1,15 @@ +2008-06-20 Andrew Cagney <cagney@redhat.com> + + * jni/ProcBuilder.cxx (ProcBuilder::construct): Catch a Throwable. + * jni/ProcBuilder.cxx (ProcBuilder::construct): Ditto. + +2008-06-12 Andrew Cagney <cagney@redhat.com> + + * Exe.java (getName): Rename get. + (openReadOnly): New. + * jni/Exe.cxx (Exe::getName): Update. + * cni/Exe.cxx (Exe::getName): Update. + 2008-06-04 Andrew Cagney <cagney@redhat.com> * TestMaps.java (testNative()): New. diff --git a/frysk-sys/frysk/sys/proc/Exe.java b/frysk-sys/frysk/sys/proc/Exe.java index 07c9a05..23e33be 100644 --- a/frysk-sys/frysk/sys/proc/Exe.java +++ b/frysk-sys/frysk/sys/proc/Exe.java @@ -43,14 +43,11 @@ import frysk.sys.ProcessIdentifier; /** * The contents of <tt>/proc/PID/exe</tt>. - * - * XXX: Should this be more like a builder or like Stat where there's - * a refresh method that detects that the contents actually changed? */ public class Exe { - public static String get(ProcessIdentifier pid) { - return get(pid.intValue()); + public static String getName(ProcessIdentifier pid) { + return getName(pid.intValue()); } - private static native String get (int pid); + private static native String getName(int pid); } diff --git a/frysk-sys/frysk/sys/proc/cni/Exe.cxx b/frysk-sys/frysk/sys/proc/cni/Exe.cxx index 6f258c5..8b583fb 100644 --- a/frysk-sys/frysk/sys/proc/cni/Exe.cxx +++ b/frysk-sys/frysk/sys/proc/cni/Exe.cxx @@ -48,22 +48,46 @@ #include "frysk/sys/proc/Exe.h" jstring -frysk::sys::proc::Exe::get (jint pid) -{ +frysk::sys::proc::Exe::getName(jint pid) { char file[FILENAME_MAX]; if (::snprintf (file, sizeof file, "/proc/%d/exe", (int) pid) >= FILENAME_MAX) - throwRuntimeException ("snprintf: buffer overflow"); + throwRuntimeException("snprintf: buffer overflow"); // /proc/$$/exe contains a soft-link specifying the name of the // executable, possibly with "(deleted)" appended. That link's // upper bound is determined by FILENAME_MAX since that is the - // longest possible allowable file name. - const int maxLen = FILENAME_MAX + sizeof (" (deleted)") + 1; + // longest possible allowable file name. Note that readlink doesn't + // NUL terminate so need to leave space for that. + const char deleted[] = " (deleted)"; + const int maxLen = FILENAME_MAX + sizeof(deleted) + 1; char link[maxLen]; - int len = ::readlink (file, link, sizeof (link)); + int len = ::readlink(file, link, sizeof(link) - 1); if (len < 0 || len >= maxLen) - throwErrno (errno, "readlink"); + throwErrno(errno, "readlink"); + link[len] = '\0'; + + // Linux's /proc/$$/exe can get screwed up in several ways. Detect + // each here and return null. + if ((int) strlen(link) != len) { + // Assume that an EXE that has somehow ended up with an embedded + // NUL character is invalid. This happens when the kernel screws + // up "mv a-really-long-file $exe" leaving the updated EXE string + // with something like "$exe<NUL>ally-long-file (deleted)". + throwUserException("The link %s is corrupt", file); + } + + if (strstr(link, deleted) + strlen(deleted) - link == len) { + // Assume (possibly incorrectly) that a trailing "(deleted)" + // always indicates a deleted file. + link[len - strlen(deleted)] = '\0'; + throwUserException("The link %s points to the deleted file %s", + file, link); + } + + if (access(link, F_OK) != 0) { + throwErrno(errno, "file %s", link); + } // Note that some kernels have a "feature" where the link can become // corrupted. Just retun that, the caller needs to decide if the diff --git a/frysk-sys/frysk/sys/proc/cni/ProcBuilder.cxx b/frysk-sys/frysk/sys/proc/cni/ProcBuilder.cxx index 20c09e6..2b0bc85 100644 --- a/frysk-sys/frysk/sys/proc/cni/ProcBuilder.cxx +++ b/frysk-sys/frysk/sys/proc/cni/ProcBuilder.cxx @@ -97,9 +97,9 @@ frysk::sys::proc::ProcBuilder::construct(jint pid, frysk::rsl::Log* warning) { try { build(frysk::sys::ProcessIdentifierFactory::create(id)); - } catch (java::lang::RuntimeException *e) { + } catch (java::lang::Throwable *t) { ::closedir(proc); - throw e; + throw t; } } diff --git a/frysk-sys/frysk/sys/proc/jni/Exe.cxx b/frysk-sys/frysk/sys/proc/jni/Exe.cxx index 12745a8..112f363 100644 --- a/frysk-sys/frysk/sys/proc/jni/Exe.cxx +++ b/frysk-sys/frysk/sys/proc/jni/Exe.cxx @@ -49,7 +49,7 @@ using namespace java::lang; String -frysk::sys::proc::Exe::get(jnixx::env env, jint pid) { +frysk::sys::proc::Exe::getName(jnixx::env env, jint pid) { // Get the name of the EXE in /proc. char file[FILENAME_MAX]; if (::snprintf(file, sizeof file, "/proc/%d/exe", (int) pid) @@ -60,13 +60,36 @@ frysk::sys::proc::Exe::get(jnixx::env env, jint pid) { // executable, possibly with "(deleted)" appended. That link's // upper bound is determined by FILENAME_MAX since that is the // longest possible allowable file name. - const int maxLen = FILENAME_MAX + sizeof (" (deleted)") + 1; + const char deleted[] = " (deleted)"; + const int maxLen = FILENAME_MAX + sizeof(deleted) + 1; char link[maxLen]; - int len = ::readlink (file, link, sizeof (link) - 1); + int len = ::readlink (file, link, sizeof(link) - 1); if (len < 0 || len >= maxLen) errnoException(env, errno, "readlink"); link[len] = '\0'; + // Linux's /proc/$$/exe can get screwed up in several ways. Detect + // each here and return null. + if ((int) strlen(link) != len) { + // Assume that an EXE that has somehow ended up with an embedded + // NUL character is invalid. This happens when the kernel screws + // up "mv a-really-long-file $exe" leaving the updated EXE string + // with something like "$exe<NUL>ally-long-file (deleted)". + userException(env, "The link %s is corrupt", file); + } + + if (strstr(link, deleted) + strlen(deleted) - link == len) { + // Assume (possibly incorrectly) that a trailing "(deleted)" + // always indicates a deleted file. + link[len - strlen(deleted)] = '\0'; + userException(env, "The link %s points to the deleted file %s", + file, link); + } + + if (access(link, F_OK) != 0) { + errnoException(env, errno, "file %s", link); + } + // Note that some kernels have a "feature" where the link can become // corrupted. Just retun that, the caller needs to decide if the // extracted link is valid. diff --git a/frysk-sys/frysk/sys/proc/jni/ProcBuilder.cxx b/frysk-sys/frysk/sys/proc/jni/ProcBuilder.cxx index 866dfd1..2cc52ae 100644 --- a/frysk-sys/frysk/sys/proc/jni/ProcBuilder.cxx +++ b/frysk-sys/frysk/sys/proc/jni/ProcBuilder.cxx @@ -92,9 +92,9 @@ frysk::sys::proc::ProcBuilder::construct(::jnixx::env env, jint pid, try { build(env, frysk::sys::ProcessIdentifierFactory::create(env, id)); - } catch (java::lang::RuntimeException *e) { + } catch (java::lang::Throwable t) { ::closedir(proc); - throw e; + throw t; } } diff --git a/frysk-sys/frysk/sys/ptrace/AddressSpace.java b/frysk-sys/frysk/sys/ptrace/AddressSpace.java deleted file mode 100644 index b9203ba..0000000 --- a/frysk-sys/frysk/sys/ptrace/AddressSpace.java +++ /dev/null @@ -1,145 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2005, 2006, 2007, 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.sys.ptrace; - -import frysk.rsl.Log; -import frysk.sys.ProcessIdentifier; - -/** - * A ptrace address space, that can be peeked or poked a "word" at - * a time. - */ -public class AddressSpace { - private static final Log fine = Log.fine(AddressSpace.class); - - private final long length; - private final String name; - private final int ptPeek; - private final int ptPoke; - - AddressSpace(long length, String name, int ptPeek, int ptPoke) { - this.name = super.toString() + ":" + name; - this.length = length; - this.ptPeek = ptPeek; - this.ptPoke = ptPoke; - } - - public String toString() { - return name; - } - public long length() { - return length; - } - - /** - * Fetch a byte at ADDR of process PID. - */ - public int peek(ProcessIdentifier pid, long addr) { - fine.log(this, "peek", pid, "addr", addr, "..."); - int ret = peek(pid.intValue(), addr); - fine.log("... peek", pid, "returns", ret); - return ret; - } - private native int peek (int pid, long addr); - - /** - * Store the byte at ADDR of process PID. - */ - public void poke(ProcessIdentifier pid, long addr, int data) { - fine.log(this, "poke", pid, "addr", addr, "data", (long) data); - poke(pid.intValue(), addr, data); - } - private native void poke(int pid, long addr, int data); - - /** - * Transfer data between the local BYTES array and process PID. - * Locally the data starts at OFFSET and goes for LENGTH bytes. - * - * This is a host oriented transfer; hence LENGTH, which must fall - * within the bounds of BYTES, is an int. - */ - public void transfer(ProcessIdentifier pid, long addr, - byte[] bytes, int offset, int length, - boolean write) { - fine.log(this, "transfer", pid, "addr", addr, - "offset", offset, "length", length, - write ? "write ..." : "read ..."); - transfer(write ? ptPoke : ptPeek, pid.intValue(), addr, - bytes, offset, length); - } - - /** - * Transfer data between the local BYTES array and process PID. - * Up to LENGTH bytes are copied, starting at OFFSET in the BYTES - * array. The number of bytes actually transfered is returned. - * - * This is a target oriented transfer; hence LENGTH, as an address - * sized quantity, is a long and can be larger than the bounds of - * BYTES. - */ - public int transfer(ProcessIdentifier pid, long addr, long length, - byte[] bytes, int offset, boolean write) { - fine.log(this, "transfer", pid, "addr", addr, "length", length, - "offset", offset, write ? "write ..." : "read ..."); - int size; - if (offset >= 0 && length >= 0) { - if (offset + length > bytes.length) - size = bytes.length - offset; - else - size = (int) length; - } else { - size = -1; // triggers exception - } - transfer(write ? ptPoke : ptPeek, pid.intValue(), addr, - bytes, offset, size); - return size; - } - - private native final void transfer(int op, int pid, long addr, - byte[] bytes, int offset, int length); - - private static native AddressSpace text(); - private static native AddressSpace data(); - private static native AddressSpace usr(); - - public static final AddressSpace TEXT = text(); - public static final AddressSpace DATA = data(); - public static final AddressSpace USR = usr(); -} diff --git a/frysk-sys/frysk/sys/ptrace/BlockSpace.java b/frysk-sys/frysk/sys/ptrace/BlockSpace.java new file mode 100644 index 0000000..916fc1a --- /dev/null +++ b/frysk-sys/frysk/sys/ptrace/BlockSpace.java @@ -0,0 +1,90 @@ +// This file is part of the program FRYSK. +// +// Copyright 2005, 2006, 2007, 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.sys.ptrace; + +import frysk.rsl.Log; +import frysk.sys.ProcessIdentifier; + +/** + * A ptrace space that is transfered to/from PID in bulk. + * + * One day, someone will implement caching of this, minimizing the + * need for redundant transfers. + */ +public class BlockSpace { + private static final Log fine = Log.fine(BlockSpace.class); + + private final int ptLength; + private final int ptGet; + private final int ptSet; + + BlockSpace(int ptLength, int ptGet, int ptSet) { + this.ptLength = ptLength; + this.ptGet = ptGet; + this.ptSet = ptSet; + } + + /** + * Return the size of the register set in bytes. + */ + public int length() { + return ptLength; + } + + /** + * Fetch PID's register set into DATA. + */ + public void transfer(ProcessIdentifier pid, byte[] data, + boolean write) { + fine.log(this, "transfer", pid, write ? "write ..." : "read ..."); + transfer(write ? ptSet : ptGet, pid.intValue(), data, ptLength); + } + + private static native void transfer(int op, int pid, byte[] data, + int length); + + private static native BlockSpace regs(); + private static native BlockSpace fpregs(); + private static native BlockSpace fpxregs(); + + public static final BlockSpace REGS = regs(); + public static final BlockSpace FPREGS = fpregs(); + public static final BlockSpace FPXREGS = fpxregs(); +} diff --git a/frysk-sys/frysk/sys/ptrace/ByteSpace.java b/frysk-sys/frysk/sys/ptrace/ByteSpace.java new file mode 100644 index 0000000..e28b906 --- /dev/null +++ b/frysk-sys/frysk/sys/ptrace/ByteSpace.java @@ -0,0 +1,145 @@ +// This file is part of the program FRYSK. +// +// Copyright 2005, 2006, 2007, 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.sys.ptrace; + +import frysk.rsl.Log; +import frysk.sys.ProcessIdentifier; + +/** + * A ptrace space, that can be efficiently peeked and poked a "word" + * or even "byte" at a time. + */ +public class ByteSpace { + private static final Log fine = Log.fine(ByteSpace.class); + + private final long length; + private final String name; + private final int ptPeek; + private final int ptPoke; + + ByteSpace(long length, String name, int ptPeek, int ptPoke) { + this.name = super.toString() + ":" + name; + this.length = length; + this.ptPeek = ptPeek; + this.ptPoke = ptPoke; + } + + public String toString() { + return name; + } + public long length() { + return length; + } + + /** + * Fetch a byte at ADDR of process PID. + */ + public int peek(ProcessIdentifier pid, long addr) { + fine.log(this, "peek", pid, "addr", addr, "..."); + int ret = peek(pid.intValue(), addr); + fine.log("... peek", pid, "returns", ret); + return ret; + } + private native int peek (int pid, long addr); + + /** + * Store the byte at ADDR of process PID. + */ + public void poke(ProcessIdentifier pid, long addr, int data) { + fine.log(this, "poke", pid, "addr", addr, "data", (long) data); + poke(pid.intValue(), addr, data); + } + private native void poke(int pid, long addr, int data); + + /** + * Transfer data between the local BYTES array and process PID. + * Locally the data starts at OFFSET and goes for LENGTH bytes. + * + * This is a host oriented transfer; hence LENGTH, which must fall + * within the bounds of BYTES, is an int. + */ + public void transfer(ProcessIdentifier pid, long addr, + byte[] bytes, int offset, int length, + boolean write) { + fine.log(this, "transfer", pid, "addr", addr, + "offset", offset, "length", length, + write ? "write ..." : "read ..."); + transfer(write ? ptPoke : ptPeek, pid.intValue(), addr, + bytes, offset, length); + } + + /** + * Transfer data between the local BYTES array and process PID. + * Up to LENGTH bytes are copied, starting at OFFSET in the BYTES + * array. The number of bytes actually transfered is returned. + * + * This is a target oriented transfer; hence LENGTH, as an address + * sized quantity, is a long and can be larger than the bounds of + * BYTES. + */ + public int transfer(ProcessIdentifier pid, long addr, long length, + byte[] bytes, int offset, boolean write) { + fine.log(this, "transfer", pid, "addr", addr, "length", length, + "offset", offset, write ? "write ..." : "read ..."); + int size; + if (offset >= 0 && length >= 0) { + if (offset + length > bytes.length) + size = bytes.length - offset; + else + size = (int) length; + } else { + size = -1; // triggers exception + } + transfer(write ? ptPoke : ptPeek, pid.intValue(), addr, + bytes, offset, size); + return size; + } + + private native final void transfer(int op, int pid, long addr, + byte[] bytes, int offset, int length); + + private static native ByteSpace text(); + private static native ByteSpace data(); + private static native ByteSpace usr(); + + public static final ByteSpace TEXT = text(); + public static final ByteSpace DATA = data(); + public static final ByteSpace USR = usr(); +} diff --git a/frysk-sys/frysk/sys/ptrace/ChangeLog b/frysk-sys/frysk/sys/ptrace/ChangeLog index 9484163..0a363c5 100644 --- a/frysk-sys/frysk/sys/ptrace/ChangeLog +++ b/frysk-sys/frysk/sys/ptrace/ChangeLog @@ -1,3 +1,30 @@ +2008-07-07 Andrew Cagney <cagney@redhat.com> + + * Utrace.java: Delete stub. + * jni/Utrace.java: Delete stub. + * cni/Utrace.java: Delete stub. + * TestUtrace.java: Delete stub. + +2008-07-04 Andrew Cagney <cagney@redhat.com> + + * jni/ByteSpace.cxx: Rename jni/AddressSpace.java. + * cni/ByteSpace.cxx: Rename cni/AddressSpace.java. + * jni/BlockSpace.cxx: Rename jni/RegisterSet.java. + * cni/BlockSpace.cxx: Rename cni/RegisterSet.java. + * ByteSpace.java: Rename AddressSpace.java. + * BlockSpace.java: Rename RegisterSet.java. + * TestRegisterSet.java: Update. + * TestAddressSpace.java: Update. + +2008-06-20 Andrew Cagney <cagney@redhat.com> + + * jni/AddressSpace.cxx: Simplify debug code. + * cni/AddressSpace.cxx: Ditto. + * jni/Ptrace.hxx (ptraceOpToString(int)): Declare. + * cni/Ptrace.hxx (ptraceOpToString(int)): Ditto. + * jni/Ptrace.cxx (ptraceOpToString): Rename op_as_string. + * cni/Ptrace.cxx (ptraceOpToString): Ditto. + 2008-05-25 Andrew Cagney <cagney@redhat.com> * jni/AddressSpace.cxx: Use jbyteArrayElements. diff --git a/frysk-sys/frysk/sys/ptrace/RegisterSet.java b/frysk-sys/frysk/sys/ptrace/RegisterSet.java deleted file mode 100644 index 7fa028a..0000000 --- a/frysk-sys/frysk/sys/ptrace/RegisterSet.java +++ /dev/null @@ -1,87 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2005, 2006, 2007, 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.sys.ptrace; - -import frysk.rsl.Log; -import frysk.sys.ProcessIdentifier; - -/** - * A ptrace register set that is transfered to/from PID in bulk. - */ -public class RegisterSet { - private static final Log fine = Log.fine(RegisterSet.class); - - private final int ptLength; - private final int ptGet; - private final int ptSet; - - RegisterSet(int ptLength, int ptGet, int ptSet) { - this.ptLength = ptLength; - this.ptGet = ptGet; - this.ptSet = ptSet; - } - - /** - * Return the size of the register set in bytes. - */ - public int length() { - return ptLength; - } - - /** - * Fetch PID's register set into DATA. - */ - public void transfer(ProcessIdentifier pid, byte[] data, - boolean write) { - fine.log(this, "transfer", pid, write ? "write ..." : "read ..."); - transfer(write ? ptSet : ptGet, pid.intValue(), data, ptLength); - } - - private static native void transfer(int op, int pid, byte[] data, - int length); - - private static native RegisterSet regs(); - private static native RegisterSet fpregs(); - private static native RegisterSet fpxregs(); - - public static final RegisterSet REGS = regs(); - public static final RegisterSet FPREGS = fpregs(); - public static final RegisterSet FPXREGS = fpxregs(); -} diff --git a/frysk-sys/frysk/sys/ptrace/TestAddressSpace.java b/frysk-sys/frysk/sys/ptrace/TestAddressSpace.java index 3eea99e..05c9cb9 100644 --- a/frysk-sys/frysk/sys/ptrace/TestAddressSpace.java +++ b/frysk-sys/frysk/sys/ptrace/TestAddressSpace.java @@ -59,7 +59,7 @@ public class TestAddressSpace extends TestCase { } private void verifyBytes(String what, ProcessIdentifier pid, - AddressSpace space, + ByteSpace space, byte[] bytes, long addr) { for (int i = 0; i < bytes.length; i++) { assertEquals(what + " " + i + " at " + addr + " in " + space, @@ -68,34 +68,34 @@ public class TestAddressSpace extends TestCase { } } - private void verifyPeek(String what, AddressSpace space, + private void verifyPeek(String what, ByteSpace space, byte[] bytes, long addr) { verifyBytes(what, ForkFactory.attachedDaemon(), space, bytes, addr); } public void testTextValPeek() { - verifyPeek("TextVal", AddressSpace.TEXT, + verifyPeek("TextVal", ByteSpace.TEXT, LocalMemory.getDataBytes(), LocalMemory.getDataAddr()); } public void testDataValPeek() { - verifyPeek("DataVal", AddressSpace.DATA, + verifyPeek("DataVal", ByteSpace.DATA, LocalMemory.getDataBytes(), LocalMemory.getDataAddr()); } public void testTextFuncPeek() { - verifyPeek("TextFunc", AddressSpace.TEXT, + verifyPeek("TextFunc", ByteSpace.TEXT, LocalMemory.getCodeBytes(), LocalMemory.getCodeAddr()); } public void testDataFuncPeek() { - verifyPeek("DataFunc", AddressSpace.DATA, + verifyPeek("DataFunc", ByteSpace.DATA, LocalMemory.getCodeBytes(), LocalMemory.getCodeAddr()); } public void testDataStackPeek() { LocalMemory.constructStack(new StackBuilder() { public void stack(long addr, byte[] bytes) { - verifyPeek("DataStack", AddressSpace.DATA, + verifyPeek("DataStack", ByteSpace.DATA, bytes, addr); } }); @@ -103,13 +103,13 @@ public class TestAddressSpace extends TestCase { public void testTextStackPeek() { LocalMemory.constructStack(new StackBuilder() { public void stack(long addr, byte[] bytes) { - verifyPeek("DataStack", AddressSpace.TEXT, + verifyPeek("DataStack", ByteSpace.TEXT, bytes, addr); } }); } - public void verifyPoke(String what, AddressSpace space, + public void verifyPoke(String what, ByteSpace space, byte[] bytes, long addr) { ProcessIdentifier pid = ForkFactory.attachedDaemon(); for (byte i = 4; i < 12; i++) { @@ -119,29 +119,29 @@ public class TestAddressSpace extends TestCase { } } public void testTextValPoke() { - verifyPoke("TextVal", AddressSpace.TEXT, + verifyPoke("TextVal", ByteSpace.TEXT, LocalMemory.getDataBytes(), LocalMemory.getDataAddr()); } public void testDataValPoke() { - verifyPoke("DataVal", AddressSpace.DATA, + verifyPoke("DataVal", ByteSpace.DATA, LocalMemory.getDataBytes(), LocalMemory.getDataAddr()); } public void testTextFuncPoke() { - verifyPoke("TextFunc", AddressSpace.TEXT, + verifyPoke("TextFunc", ByteSpace.TEXT, LocalMemory.getCodeBytes(), LocalMemory.getCodeAddr()); } public void testDataFuncPoke() { - verifyPoke("DataFunc", AddressSpace.DATA, + verifyPoke("DataFunc", ByteSpace.DATA, LocalMemory.getCodeBytes(), LocalMemory.getCodeAddr()); } public void testDataStackPoke() { LocalMemory.constructStack(new StackBuilder() { public void stack(long addr, byte[] bytes) { - verifyPoke("DataStack", AddressSpace.DATA, + verifyPoke("DataStack", ByteSpace.DATA, bytes, addr); } }); @@ -149,13 +149,13 @@ public class TestAddressSpace extends TestCase { public void testTextStackPoke() { LocalMemory.constructStack(new StackBuilder() { public void stack(long addr, byte[] bytes) { - verifyPoke("DataStack", AddressSpace.TEXT, + verifyPoke("DataStack", ByteSpace.TEXT, bytes, addr); } }); } - private void verifyPeekBytes(String why, AddressSpace space, + private void verifyPeekBytes(String why, ByteSpace space, byte[] startBytes, long startAddr) { ProcessIdentifier pid = ForkFactory.attachedDaemon(); byte[] pidBytes = new byte[startBytes.length]; @@ -183,29 +183,29 @@ public class TestAddressSpace extends TestCase { } } public void testTextValPeekBytes() { - verifyPeekBytes ("TextVal", AddressSpace.TEXT, + verifyPeekBytes ("TextVal", ByteSpace.TEXT, LocalMemory.getDataBytes(), LocalMemory.getDataAddr()); } public void testDataValPeekBytes() { - verifyPeekBytes ("DataVal", AddressSpace.DATA, + verifyPeekBytes ("DataVal", ByteSpace.DATA, LocalMemory.getDataBytes(), LocalMemory.getDataAddr()); } public void testTextFuncPeekBytes() { - verifyPeekBytes("TextFunc", AddressSpace.TEXT, + verifyPeekBytes("TextFunc", ByteSpace.TEXT, LocalMemory.getCodeBytes(), LocalMemory.getCodeAddr()); } public void testDataFuncPeekBytes() { - verifyPeekBytes("DataFunc", AddressSpace.DATA, + verifyPeekBytes("DataFunc", ByteSpace.DATA, LocalMemory.getCodeBytes(), LocalMemory.getCodeAddr()); } public void testDataStackPeekBytes() { LocalMemory.constructStack(new StackBuilder() { public void stack(long addr, byte[] bytes) { - verifyPeekBytes("DataStack", AddressSpace.DATA, + verifyPeekBytes("DataStack", ByteSpace.DATA, bytes, addr); } }); @@ -213,13 +213,13 @@ public class TestAddressSpace extends TestCase { public void testTextStackPeekBytes() { LocalMemory.constructStack(new StackBuilder() { public void stack(long addr, byte[] bytes) { - verifyPeekBytes("DataStack", AddressSpace.TEXT, + verifyPeekBytes("DataStack", ByteSpace.TEXT, bytes, addr); } }); } - private void verifyPokeBytes(String why, AddressSpace space, + private void verifyPokeBytes(String why, ByteSpace space, byte[] startBytes, long startAddr) { ProcessIdentifier pid = ForkFactory.attachedDaemon(); byte[] newBytes = new byte[startBytes.length]; @@ -256,29 +256,29 @@ public class TestAddressSpace extends TestCase { } } public void testTextValPokeBytes() { - verifyPokeBytes("TextVal", AddressSpace.TEXT, + verifyPokeBytes("TextVal", ByteSpace.TEXT, LocalMemory.getDataBytes(), LocalMemory.getDataAddr()); } public void testDataValPokeBytes() { - verifyPokeBytes("DataVal", AddressSpace.DATA, + verifyPokeBytes("DataVal", ByteSpace.DATA, LocalMemory.getDataBytes(), LocalMemory.getDataAddr()); } public void testTextFuncPokeBytes() { - verifyPokeBytes("TextFunc", AddressSpace.TEXT, + verifyPokeBytes("TextFunc", ByteSpace.TEXT, LocalMemory.getCodeBytes(), LocalMemory.getCodeAddr()); } public void testDataFuncPokeBytes() { - verifyPokeBytes("DataFunc", AddressSpace.DATA, + verifyPokeBytes("DataFunc", ByteSpace.DATA, LocalMemory.getCodeBytes(), LocalMemory.getCodeAddr()); } public void testDataStackPokeBytes() { LocalMemory.constructStack(new StackBuilder() { public void stack(long addr, byte[] bytes) { - verifyPokeBytes("DataStack", AddressSpace.DATA, + verifyPokeBytes("DataStack", ByteSpace.DATA, bytes, addr); } }); @@ -286,7 +286,7 @@ public class TestAddressSpace extends TestCase { public void testTextStackPokeBytes() { LocalMemory.constructStack(new StackBuilder() { public void stack(long addr, byte[] bytes) { - verifyPokeBytes("DataStack", AddressSpace.TEXT, + verifyPokeBytes("DataStack", ByteSpace.TEXT, bytes, addr); } }); @@ -297,7 +297,7 @@ public class TestAddressSpace extends TestCase { ProcessIdentifier pid = ForkFactory.attachedDaemon(); boolean caught = false; try { - AddressSpace.DATA.transfer(pid, LocalMemory.getCodeAddr(), + ByteSpace.DATA.transfer(pid, LocalMemory.getCodeAddr(), bytes, offset, length, false); // read } catch (ArrayIndexOutOfBoundsException e) { diff --git a/frysk-sys/frysk/sys/ptrace/TestRegisterSet.java b/frysk-sys/frysk/sys/ptrace/TestRegisterSet.java index 4d6b3d4..df351bb 100644 --- a/frysk-sys/frysk/sys/ptrace/TestRegisterSet.java +++ b/frysk-sys/frysk/sys/ptrace/TestRegisterSet.java @@ -56,7 +56,7 @@ public class TestRegisterSet extends TestCase { TearDownProcess.tearDown (); } - private void verifyTransfer(String what, RegisterSet regs) { + private void verifyTransfer(String what, BlockSpace regs) { if (unsupported(what, regs == null)) return; ProcessIdentifier pid = ForkFactory.attachedDaemon(); @@ -71,12 +71,12 @@ public class TestRegisterSet extends TestCase { } public void testREGS() { - verifyTransfer("REGS", RegisterSet.REGS); + verifyTransfer("REGS", BlockSpace.REGS); } public void testFPREGS() { - verifyTransfer("FPREGS", RegisterSet.FPREGS); + verifyTransfer("FPREGS", BlockSpace.FPREGS); } public void testFPXREGS() { - verifyTransfer("FPXREGS", RegisterSet.FPXREGS); + verifyTransfer("FPXREGS", BlockSpace.FPXREGS); } } diff --git a/frysk-sys/frysk/sys/ptrace/TestUtrace.java b/frysk-sys/frysk/sys/ptrace/TestUtrace.java deleted file mode 100644 index e04c5be..0000000 --- a/frysk-sys/frysk/sys/ptrace/TestUtrace.java +++ /dev/null @@ -1,156 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2005, 2007, 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.sys.ptrace; - -import frysk.sys.ProcessIdentifier; -import frysk.junit.TestCase; -import frysk.testbed.TearDownProcess; -import frysk.sys.Fork; -//import frysk.sys.Itimer; -//import frysk.sys.Execute; -//import frysk.sys.Errno; -//import frysk.sys.DaemonFactory; -//import frysk.sys.Wait; -//import frysk.sys.Signal; -//import frysk.sys.UnhandledWaitBuilder; - -/** - * Check the plumming of Ptrace. - */ - -public class TestUtrace extends TestCase { - /** - * Rip down everything related to PID. - */ - public void tearDown() { - TearDownProcess.tearDown (); - } - - public void testChildContinue() { - final ProcessIdentifier pid - = Fork.utrace(new String[] { - "/bin/true" - }); - System.err.println("pid = " + pid); - /***************** kill for now - assertTrue("pid", pid.intValue() > 0); - TearDownProcess.add(pid); - - // The initial stop. - Wait.waitOnce(pid, new UnhandledWaitBuilder() { - private final ProcessIdentifier id = pid; - protected void unhandled(String why) { - fail (why); - } - public void stopped(ProcessIdentifier pid, Signal signal) { - assertSame("stopped pid", id, pid); - assertSame("stopped sig", Signal.TRAP, signal); - } - }); - - Utrace.singleStep(pid, Signal.NONE); - Wait.waitOnce(pid, new UnhandledWaitBuilder() { - private final ProcessIdentifier id = pid; - protected void unhandled(String why) { - fail (why); - } - public void stopped(ProcessIdentifier pid, Signal signal) { - assertSame("stopped pid", id, pid); - assertSame("stopped sig", Signal.TRAP, signal); - } - }); - - Utrace.cont(pid, Signal.TERM); - Wait.waitOnce(pid, new UnhandledWaitBuilder() { - private final ProcessIdentifier id = pid; - protected void unhandled(String why) { - fail (why); - } - public void terminated(ProcessIdentifier pid, Signal signal, - int status, boolean coreDumped) { - assertSame("terminated pid", id, pid); - assertSame("terminated signal", Signal.TERM, signal); - assertEquals("terminated status", -Signal.TERM.intValue(), - status); - } - }); - ********************/ - } - - /** - * Check attach (to oneself). - */ - /********************** kill it for now - public void testAttachDetach() { - final ProcessIdentifier pid = DaemonFactory.create(new Execute() { - public void execute() { - Itimer.sleep (TestCase.getTimeoutSeconds()); - } - }); - TearDownProcess.add(pid); - assertTrue ("pid", pid.intValue() > 0); - - Utrace.attach(pid); - Wait.waitOnce(pid, new UnhandledWaitBuilder() { - private final ProcessIdentifier id = pid; - protected void unhandled(String why) { - fail (why); - } - public void stopped(ProcessIdentifier pid, Signal signal) { - assertSame("stopped pid", id, pid); - assertSame("stopped sig", Signal.STOP, signal); - } - }); - - Utrace.detach(pid, Signal.NONE); - Errno errno = null; - try { - Wait.waitOnce(pid, new UnhandledWaitBuilder() { - protected void unhandled(String why) { - fail (why); - } - }); - } catch (Errno e) { - errno = e; - } - assertEquals("Errno", Errno.Echild.class, errno.getClass()); - } - **********************************/ -} diff --git a/frysk-sys/frysk/sys/ptrace/Utrace.java b/frysk-sys/frysk/sys/ptrace/Utrace.java deleted file mode 100644 index 89efccf..0000000 --- a/frysk-sys/frysk/sys/ptrace/Utrace.java +++ /dev/null @@ -1,123 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2005, 2006, 2007, 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.sys.ptrace; - -import frysk.rsl.Log; -import frysk.sys.ProcessIdentifier; -import frysk.sys.Signal; - -/** - * Trace a process. - */ - -public class Utrace { - private static final Log fine = Log.fine(Utrace.class); - - /** - * Attach to the process specified by PID. - */ - public static void attach(ProcessIdentifier pid) { - fine.log("attach", pid); - attach(pid.intValue()); - } - private static native void attach(int pid); - - /** - * Detach from the process specified by PID. - */ - public static void detach(ProcessIdentifier pid, Signal signal) { - fine.log("detach", pid, "signal", signal); - detach(pid.intValue(), signal.intValue()); - } - private static native void detach(int pid, int sig); - - /** - * Single-step (instruction step) the process specified by PID, if - * SIG is non-zero, deliver the signal. - */ - public static void singleStep(ProcessIdentifier pid, Signal signal) { - fine.log("signleStep", pid, "signal", signal); - singleStep(pid.intValue(), signal.intValue()); - } - private static native void singleStep(int pid, int sig); - - /** - * Continue the process specified by PID, if SIG is non-zero, - * deliver the signal. - */ - public static void cont(ProcessIdentifier pid, Signal signal) { - fine.log("cont", pid, "signal", signal); - cont(pid.intValue(), signal.intValue()); - } - private static native void cont(int pid, int signal); - - /** - * Continue the process specified by PID, stopping when there is a - * system-call; if SIG is non-zero deliver the signal. - */ - public static void sysCall(ProcessIdentifier pid, Signal signal) { - fine.log("sysCall", pid, "signal", signal); - sysCall(pid.intValue(), signal.intValue()); - } - private static native void sysCall(int pid, int sig); - - /** - * Fetch the auxilary information associated with PID's last WAIT - * event. - */ - public static long getEventMsg(ProcessIdentifier pid) { - fine.log("getEventMsg", pid, "..."); - long ret = getEventMsg(pid.intValue()); - fine.log("... getEventMsg", pid, "returns", ret); - return ret; - } - private static native long getEventMsg(int pid); - - /** - * Set PID's trace options. OPTIONS is formed by or'ing the - * values returned by the option* methods below. - */ - public static void setOptions(ProcessIdentifier pid, long options) { - fine.log("setOptions", pid, "options", options); - setOptions(pid.intValue(), options); - } - private static native void setOptions (int pid, long options); - -} diff --git a/frysk-sys/frysk/sys/ptrace/cni/AddressSpace.cxx b/frysk-sys/frysk/sys/ptrace/cni/AddressSpace.cxx deleted file mode 100644 index 232e1f3..0000000 --- a/frysk-sys/frysk/sys/ptrace/cni/AddressSpace.cxx +++ /dev/null @@ -1,189 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2005, 2006, 2007, 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. - -#include <stdint.h> -#include <sys/types.h> -#include <sys/ptrace.h> -#include "linux.ptrace.h" - -#include <gcj/cni.h> - -#include <java/lang/System.h> -#include <java/lang/Thread.h> -#include <java/lang/ArrayIndexOutOfBoundsException.h> - -#include "frysk/sys/ptrace/cni/Ptrace.hxx" -#include "frysk/sys/cni/Errno.hxx" -#include "frysk/sys/ptrace/AddressSpace.h" - -union word { - long l; - uint8_t b[sizeof (long)]; -}; - -jint -frysk::sys::ptrace::AddressSpace::peek(jint pid, jlong addr) { - union word w; - long paddr = addr & -sizeof(long); -#if DEBUG - fprintf(stderr, "peek 0x%lx paddr 0x%lx", (long)addr, paddr); -#endif - w.l = ptraceOp(ptPeek, pid, (void*)paddr, 0); -#if DEBUG - fprintf(stderr, " word 0x%lx", w.l); -#endif - int index = addr & (sizeof(long) - 1); -#if DEBUG - fprintf(stderr, " index %d", index); -#endif - uint8_t byte = w.b[index]; -#if DEBUG - fprintf(stderr, " byte %d/0x%x\n", byte, byte); -#endif - return byte; -} - -void -frysk::sys::ptrace::AddressSpace::poke(jint pid, jlong addr, jint data) { - // Implement read-modify-write - union word w; -#if DEBUG - fprintf(stderr, "poke 0x%x", (int)(data & 0xff)); -#endif - long paddr = addr & -sizeof(long); -#if DEBUG - fprintf(stderr, " addr 0x%lx paddr 0x%lx", (long)addr, paddr); -#endif - w.l = ptraceOp(ptPeek, pid, (void*)paddr, 0); -#if DEBUG - fprintf(stderr, " word 0x%lx", w.l); -#endif - int index = addr & (sizeof(long) - 1); -#if DEBUG - fprintf (stderr, " index %d", index); -#endif - w.b[index] = data; -#if DEBUG - fprintf(stderr, " word 0x%lx\n", w.l); -#endif - ptraceOp(ptPoke, pid, (void*)(addr & -sizeof(long)), w.l); -} - -void -frysk::sys::ptrace::AddressSpace::transfer(jint op, jint pid, jlong addr, - jbyteArray bytes, jint offset, - jint length) { - verifyBounds(bytes, offset, length); - // Somewhat more clueful implementation - for (jlong i = 0; i < length;) { -#if DEBUG - fprintf(stderr, - "transfer pid %d addr 0x%lx length %d offset %d op %d (%s)", - (int)pid, (long)addr, (int)length, (int)offset, - (int)op, op_as_string(op)); -#endif - - union word w; - unsigned long waddr = addr & -sizeof(long); - unsigned long woff = (addr - waddr); - unsigned long remaining = length - i; - unsigned long wend; - if (remaining > sizeof(long) - woff) - wend = sizeof(long); - else - wend = woff + remaining; - long wlen = wend - woff; - -#if DEBUG - fprintf(stderr, - " i %ld waddr 0x%lx woff %lu wend %lu remaining %lu wlen %lu", - (long)i, waddr, woff, wend, remaining, wlen); -#endif - - // Either a peek; or a partial write requiring read/modify/write. - if (op == ptPeek || woff != 0 || wend != sizeof(long)) { - w.l = ptraceOp(ptPeek, pid, (void*)waddr, 0); -#if DEBUG - fprintf(stderr, " peek 0x%lx", w.l); -#endif - } - - // extract or modify - if (op == ptPeek) - memcpy(offset + i + elements(bytes), &w.b[woff], wlen); - else { - memcpy(&w.b[woff], offset + i + elements(bytes), wlen); -#if DEBUG - fprintf(stderr, " poke 0x%lx", w.l); -#endif - w.l = ptraceOp(ptPoke, pid, (void*)waddr, w.l); - } - - i += wlen; - addr += wlen; - -#if DEBUG - fprintf(stderr, "\n"); -#endif - } -} - -frysk::sys::ptrace::AddressSpace* -frysk::sys::ptrace::AddressSpace::text() { - return new frysk::sys::ptrace::AddressSpace(-1UL, - JvNewStringUTF("TEXT"), - PTRACE_PEEKTEXT, - PTRACE_POKETEXT); -} - -frysk::sys::ptrace::AddressSpace* -frysk::sys::ptrace::AddressSpace::data() { - return new frysk::sys::ptrace::AddressSpace(-1UL, - JvNewStringUTF("DATA"), - PTRACE_PEEKDATA, - PTRACE_POKEDATA); -} - -frysk::sys::ptrace::AddressSpace* -frysk::sys::ptrace::AddressSpace::usr() { - return new frysk::sys::ptrace::AddressSpace(-1UL, - JvNewStringUTF("USR"), - PTRACE_PEEKUSR, - PTRACE_POKEUSR); -} diff --git a/frysk-sys/frysk/sys/ptrace/cni/BlockSpace.cxx b/frysk-sys/frysk/sys/ptrace/cni/BlockSpace.cxx new file mode 100644 index 0000000..d7abd59 --- /dev/null +++ b/frysk-sys/frysk/sys/ptrace/cni/BlockSpace.cxx @@ -0,0 +1,89 @@ +// This file is part of the program FRYSK. +// +// Copyright 2005, 2006, 2007, 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. + +#include <stdint.h> +#include <sys/types.h> +#include <sys/ptrace.h> +#include "linux.ptrace.h" +#include <sys/user.h> + +#include <gcj/cni.h> + +#include "frysk/sys/cni/Errno.hxx" +#include "frysk/sys/ptrace/cni/Ptrace.hxx" +#include "frysk/sys/ptrace/BlockSpace.h" + +void +frysk::sys::ptrace::BlockSpace::transfer(jint op, jint pid, jbyteArray data, + jint length) { + verifyBounds(data, 0, length); + ptraceOp(op, pid, NULL, (long) elements(data)); +} + +frysk::sys::ptrace::BlockSpace* +frysk::sys::ptrace::BlockSpace::regs() { +#if defined(__i386__)|| defined(__x86_64__) + return new frysk::sys::ptrace::BlockSpace(sizeof(user_regs_struct), + PTRACE_GETREGS, PTRACE_SETREGS); +#else + return NULL; +#endif +} + +frysk::sys::ptrace::BlockSpace* +frysk::sys::ptrace::BlockSpace::fpregs() { +#if defined(__i386__)|| defined(__x86_64__) + return new frysk::sys::ptrace::BlockSpace(sizeof(user_fpregs_struct), + PTRACE_GETFPREGS, + PTRACE_SETFPREGS); +#else + return NULL; +#endif +} + +frysk::sys::ptrace::BlockSpace* +frysk::sys::ptrace::BlockSpace::fpxregs() { +#if defined(__i386__) + return new frysk::sys::ptrace::BlockSpace(sizeof(user_fpxregs_struct), + PTRACE_GETFPXREGS, + PTRACE_SETFPXREGS); +#else + return NULL; +#endif +} diff --git a/frysk-sys/frysk/sys/ptrace/cni/ByteSpace.cxx b/frysk-sys/frysk/sys/ptrace/cni/ByteSpace.cxx new file mode 100644 index 0000000..5911736 --- /dev/null +++ b/frysk-sys/frysk/sys/ptrace/cni/ByteSpace.cxx @@ -0,0 +1,177 @@ +// This file is part of the program FRYSK. +// +// Copyright 2005, 2006, 2007, 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. + +#define DEBUG 0 + +#include <stdio.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/ptrace.h> +#include "linux.ptrace.h" + +#include <gcj/cni.h> + +#include <java/lang/System.h> +#include <java/lang/Thread.h> +#include <java/lang/ArrayIndexOutOfBoundsException.h> + +#include "frysk/sys/ptrace/cni/Ptrace.hxx" +#include "frysk/sys/cni/Errno.hxx" +#include "frysk/sys/ptrace/ByteSpace.h" + +union word { + long l; + uint8_t b[sizeof (long)]; +}; + +jint +frysk::sys::ptrace::ByteSpace::peek(jint pid, jlong addr) { + union word w; + long paddr = addr & -sizeof(long); + if (DEBUG) + fprintf(stderr, "peek 0x%lx paddr 0x%lx", (long)addr, paddr); + w.l = ptraceOp(ptPeek, pid, (void*)paddr, 0); + if (DEBUG) + fprintf(stderr, " word 0x%lx", w.l); + int index = addr & (sizeof(long) - 1); + if (DEBUG) + fprintf(stderr, " index %d", index); + uint8_t byte = w.b[index]; + if (DEBUG) + fprintf(stderr, " byte %d/0x%x\n", byte, byte); + return byte; +} + +void +frysk::sys::ptrace::ByteSpace::poke(jint pid, jlong addr, jint data) { + // Implement read-modify-write + union word w; + if (DEBUG) + fprintf(stderr, "poke 0x%x", (int)(data & 0xff)); + long paddr = addr & -sizeof(long); + if (DEBUG) + fprintf(stderr, " addr 0x%lx paddr 0x%lx", (long)addr, paddr); + w.l = ptraceOp(ptPeek, pid, (void*)paddr, 0); + if (DEBUG) + fprintf(stderr, " word 0x%lx", w.l); + int index = addr & (sizeof(long) - 1); + if (DEBUG) + fprintf (stderr, " index %d", index); + w.b[index] = data; + if (DEBUG) + fprintf(stderr, " word 0x%lx\n", w.l); + ptraceOp(ptPoke, pid, (void*)(addr & -sizeof(long)), w.l); +} + +void +frysk::sys::ptrace::ByteSpace::transfer(jint op, jint pid, jlong addr, + jbyteArray bytes, jint offset, + jint length) { + verifyBounds(bytes, offset, length); + // Somewhat more clueful implementation + for (jlong i = 0; i < length;) { + if (DEBUG) + fprintf(stderr, + "transfer pid %d addr 0x%lx length %d offset %d op %d (%s) ...", + (int)pid, (long)addr, (int)length, (int)offset, + (int)op, ptraceOpToString(op)); + union word w; + unsigned long waddr = addr & -sizeof(long); + unsigned long woff = (addr - waddr); + unsigned long remaining = length - i; + unsigned long wend; + if (remaining > sizeof(long) - woff) + wend = sizeof(long); + else + wend = woff + remaining; + long wlen = wend - woff; + + if (DEBUG) + fprintf(stderr, + " i %ld waddr 0x%lx woff %lu wend %lu remaining %lu wlen %lu ...", + (long)i, waddr, woff, wend, remaining, wlen); + + // Either a peek; or a partial write requiring read/modify/write. + if (op == ptPeek || woff != 0 || wend != sizeof(long)) { + w.l = ptraceOp(ptPeek, pid, (void*)waddr, 0); + if (DEBUG) + fprintf(stderr, " peek 0x%lx ...", w.l); + } + + // extract or modify + if (op == ptPeek) + memcpy(offset + i + elements(bytes), &w.b[woff], wlen); + else { + memcpy(&w.b[woff], offset + i + elements(bytes), wlen); + if (DEBUG) + fprintf(stderr, " poke 0x%lx ...", w.l); + w.l = ptraceOp(ptPoke, pid, (void*)waddr, w.l); + } + + i += wlen; + addr += wlen; + + if (DEBUG) + fprintf(stderr, "\n"); + } +} + +frysk::sys::ptrace::ByteSpace* +frysk::sys::ptrace::ByteSpace::text() { + return new frysk::sys::ptrace::ByteSpace(-1UL, + JvNewStringUTF("TEXT"), + PTRACE_PEEKTEXT, + PTRACE_POKETEXT); +} + +frysk::sys::ptrace::ByteSpace* +frysk::sys::ptrace::ByteSpace::data() { + return new frysk::sys::ptrace::ByteSpace(-1UL, + JvNewStringUTF("DATA"), + PTRACE_PEEKDATA, + PTRACE_POKEDATA); +} + +frysk::sys::ptrace::ByteSpace* +frysk::sys::ptrace::ByteSpace::usr() { + return new frysk::sys::ptrace::ByteSpace(-1UL, + JvNewStringUTF("USR"), + PTRACE_PEEKUSR, + PTRACE_POKEUSR); +} diff --git a/frysk-sys/frysk/sys/ptrace/cni/Ptrace.cxx b/frysk-sys/frysk/sys/ptrace/cni/Ptrace.cxx index 4aa12eb..3375efd 100644 --- a/frysk-sys/frysk/sys/ptrace/cni/Ptrace.cxx +++ b/frysk-sys/frysk/sys/ptrace/cni/Ptrace.cxx @@ -37,6 +37,10 @@ // version and license this file solely under the GPL without // exception. +#define DEBUG 0 + +#include <stdio.h> +#include <string.h> #include <errno.h> #include <sys/ptrace.h> #include "linux.ptrace.h" @@ -47,8 +51,8 @@ #include "frysk/sys/ptrace/Ptrace.h" #include "frysk/sys/ptrace/cni/Ptrace.hxx" -static const char* -op_as_string(int op) { +const char* +ptraceOpToString(int op) { switch(op) { #define OP(NAME) case NAME: return #NAME OP(PTRACE_ATTACH); @@ -82,10 +86,14 @@ op_as_string(int op) { long ptraceOp(int op, int pid, void* addr, long data) { errno = 0; - long result = ::ptrace ((enum __ptrace_request) op, pid, addr, data); - if (errno != 0) + long result = ::ptrace((enum __ptrace_request) op, pid, addr, data); + if (errno != 0) { + int err = errno; + if (DEBUG) + fprintf(stderr, "throwing %s\n", strerror(err)); throwErrno(errno, "ptrace", "op 0x%x (%s), pid %d, addr 0x%lx, data 0x%lx", - op, op_as_string(op), pid, (long)addr, data); + op, ptraceOpToString(op), pid, (long)addr, data); + } return result; } diff --git a/frysk-sys/frysk/sys/ptrace/cni/Ptrace.hxx b/frysk-sys/frysk/sys/ptrace/cni/Ptrace.hxx index 78bda4d..1da0f03 100644 --- a/frysk-sys/frysk/sys/ptrace/cni/Ptrace.hxx +++ b/frysk-sys/frysk/sys/ptrace/cni/Ptrace.hxx @@ -38,3 +38,4 @@ // exception. extern long ptraceOp(int, int, void*, long); +extern const char *ptraceOpToString(int op); diff --git a/frysk-sys/frysk/sys/ptrace/cni/RegisterSet.cxx b/frysk-sys/frysk/sys/ptrace/cni/RegisterSet.cxx deleted file mode 100644 index 2c3a861..0000000 --- a/frysk-sys/frysk/sys/ptrace/cni/RegisterSet.cxx +++ /dev/null @@ -1,89 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2005, 2006, 2007, 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. - -#include <stdint.h> -#include <sys/types.h> -#include <sys/ptrace.h> -#include "linux.ptrace.h" -#include <sys/user.h> - -#include <gcj/cni.h> - -#include "frysk/sys/cni/Errno.hxx" -#include "frysk/sys/ptrace/cni/Ptrace.hxx" -#include "frysk/sys/ptrace/RegisterSet.h" - -void -frysk::sys::ptrace::RegisterSet::transfer(jint op, jint pid, jbyteArray data, - jint length) { - verifyBounds(data, 0, length); - ptraceOp(op, pid, NULL, (long) elements(data)); -} - -frysk::sys::ptrace::RegisterSet* -frysk::sys::ptrace::RegisterSet::regs() { -#if defined(__i386__)|| defined(__x86_64__) - return new frysk::sys::ptrace::RegisterSet(sizeof(user_regs_struct), - PTRACE_GETREGS, PTRACE_SETREGS); -#else - return NULL; -#endif -} - -frysk::sys::ptrace::RegisterSet* -frysk::sys::ptrace::RegisterSet::fpregs() { -#if defined(__i386__)|| defined(__x86_64__) - return new frysk::sys::ptrace::RegisterSet(sizeof(user_fpregs_struct), - PTRACE_GETFPREGS, - PTRACE_SETFPREGS); -#else - return NULL; -#endif -} - -frysk::sys::ptrace::RegisterSet* -frysk::sys::ptrace::RegisterSet::fpxregs() { -#if defined(__i386__) - return new frysk::sys::ptrace::RegisterSet(sizeof(user_fpxregs_struct), - PTRACE_GETFPXREGS, - PTRACE_SETFPXREGS); -#else - return NULL; -#endif -} diff --git a/frysk-sys/frysk/sys/ptrace/cni/Utrace.cxx b/frysk-sys/frysk/sys/ptrace/cni/Utrace.cxx deleted file mode 100644 index cdc0ac7..0000000 --- a/frysk-sys/frysk/sys/ptrace/cni/Utrace.cxx +++ /dev/null @@ -1,91 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2005, 2006, 2007, 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. - -#include <errno.h> -#include <stdio.h> -#include <sys/ptrace.h> -#include "linux.ptrace.h" - -#include <gcj/cni.h> - -#include "frysk/sys/cni/Errno.hxx" -#include "frysk/sys/ptrace/Utrace.h" -//#include "frysk/sys/ptrace/cni/Utrace.hxx" - -void -frysk::sys::ptrace::Utrace::attach(jint pid) { - fprintf (stderr, "\n\n>>>>PTRACE_ATTACH via utrace\n\n"); -} - -void -frysk::sys::ptrace::Utrace::detach(jint pid, jint sig) { - fprintf (stderr, "\n\n>>>>PTRACE_DETACH via utrace\n\n"); -} - -void -frysk::sys::ptrace::Utrace::singleStep(jint pid, jint sig) { - fprintf (stderr, "\n\n>>>>PTRACE_SINGLESTEP via utrace\n\n"); -} - -void -frysk::sys::ptrace::Utrace::cont(jint pid, jint sig) { - fprintf (stderr, "\n\n>>>>PTRACE_CONT via utrace\n\n"); -} - -void -frysk::sys::ptrace::Utrace::sysCall(jint pid, jint sig) { - fprintf (stderr, "\n\n>>>>PTRACE_SYSCALL via utrace\n\n"); -} - -jlong -frysk::sys::ptrace::Utrace::getEventMsg(jint pid) { - /* Note: PTRACE_GETEVENTMSG ends up calling the function - kernel/ptrace.c: ptrace_ptraceOp() and that uses put_user to store - child->ptrace_message write sizeof(ptrace_message) bytes into the - MESSAGE parameter. include/linux/sched.h declares ptrace_message - as a long. */ - fprintf (stderr, "\n\n>>>> PTRACE_GETEVENTMSG via utrace\n\n"); - return -1; -} - -void -frysk::sys::ptrace::Utrace::setOptions(jint pid, jlong options) { - fprintf (stderr, "\n\n>>>>PTRACE_SETOPTIONS via utrace\n"); -} - diff --git a/frysk-sys/frysk/sys/ptrace/jni/AddressSpace.cxx b/frysk-sys/frysk/sys/ptrace/jni/AddressSpace.cxx deleted file mode 100644 index 598d8cc..0000000 --- a/frysk-sys/frysk/sys/ptrace/jni/AddressSpace.cxx +++ /dev/null @@ -1,193 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2005, 2006, 2007, 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. - -#include <stdint.h> -#include <sys/types.h> -#include <sys/ptrace.h> -#include "linux.ptrace.h" -#include <string.h> - -#include "jni.hxx" -#include "jnixx/bounds.hxx" -#include "jnixx/elements.hxx" - -#include "frysk/sys/ptrace/jni/Ptrace.hxx" - -using namespace java::lang; - -union word { - long l; - uint8_t b[sizeof (long)]; -}; - -jint -frysk::sys::ptrace::AddressSpace::peek(::jnixx::env env, jint pid, jlong addr) { - union word w; - long paddr = addr & -sizeof(long); -#if DEBUG - fprintf(stderr, "peek 0x%lx paddr 0x%lx", (long)addr, paddr); -#endif - w.l = ptraceOp(env, GetPtPeek(env), pid, (void*)paddr, 0); -#if DEBUG - fprintf(stderr, " word 0x%lx", w.l); -#endif - int index = addr & (sizeof(long) - 1); -#if DEBUG - fprintf(stderr, " index %d", index); -#endif - uint8_t byte = w.b[index]; -#if DEBUG - fprintf(stderr, " byte %d/0x%x\n", byte, byte); -#endif - return byte; -} - -void -frysk::sys::ptrace::AddressSpace::poke(::jnixx::env env, jint pid, jlong addr, jint data) { - // Implement read-modify-write - union word w; -#if DEBUG - fprintf(stderr, "poke 0x%x", (int)(data & 0xff)); -#endif - long paddr = addr & -sizeof(long); -#if DEBUG - fprintf(stderr, " addr 0x%lx paddr 0x%lx", (long)addr, paddr); -#endif - w.l = ptraceOp(env, GetPtPeek(env), pid, (void*)paddr, 0); -#if DEBUG - fprintf(stderr, " word 0x%lx", w.l); -#endif - int index = addr & (sizeof(long) - 1); -#if DEBUG - fprintf (stderr, " index %d", index); -#endif - w.b[index] = data; -#if DEBUG - fprintf(stderr, " word 0x%lx\n", w.l); -#endif - ptraceOp(env, GetPtPoke(env), pid, (void*)(addr & -sizeof(long)), w.l); -} - -void -frysk::sys::ptrace::AddressSpace::transfer(::jnixx::env env, - jint op, jint pid, jlong addr, - ::jnixx::jbyteArray byteArray, - jint offset, jint length) { - const int ptPeek = GetPtPeek(env); - const int ptPoke = GetPtPoke(env); - verifyBounds(env, byteArray, offset, length); - // Somewhat more clueful implementation - for (jlong i = 0; i < length;) { -#if DEBUG - fprintf(stderr, - "transfer pid %d addr 0x%lx length %d offset %d op %d (%s)", - (int)pid, (long)addr, (int)length, (int)offset, - (int)op, op_as_string(op)); -#endif - - union word w; - unsigned long waddr = addr & -sizeof(long); - unsigned long woff = (addr - waddr); - unsigned long remaining = length - i; - unsigned long wend; - if (remaining > sizeof(long) - woff) - wend = sizeof(long); - else - wend = woff + remaining; - long wlen = wend - woff; - -#if DEBUG - fprintf(stderr, - " i %ld waddr 0x%lx woff %lu wend %lu remaining %lu wlen %lu", - (long)i, waddr, woff, wend, remaining, wlen); -#endif - - // Either a peek; or a partial write requiring read/modify/write. - if (op == ptPeek || woff != 0 || wend != sizeof(long)) { - w.l = ptraceOp(env, ptPeek, pid, (void*)waddr, 0); -#if DEBUG - fprintf(stderr, " peek 0x%lx", w.l); -#endif - } - - // extract or modify - jbyteArrayElements bytes = jbyteArrayElements(env, byteArray); - if (op == ptPeek) - memcpy(offset + i + bytes.elements(), &w.b[woff], wlen); - else { - memcpy(&w.b[woff], offset + i + bytes.elements(), wlen); -#if DEBUG - fprintf(stderr, " poke 0x%lx", w.l); -#endif - w.l = ptraceOp(env, ptPoke, pid, (void*)waddr, w.l); - } - bytes.release(); - - i += wlen; - addr += wlen; - -#if DEBUG - fprintf(stderr, "\n"); -#endif - } -} - -frysk::sys::ptrace::AddressSpace -frysk::sys::ptrace::AddressSpace::text(::jnixx::env env) { - return frysk::sys::ptrace::AddressSpace::New(env, -1UL, - String::NewStringUTF(env, "TEXT"), - PTRACE_PEEKTEXT, - PTRACE_POKETEXT); -} - -frysk::sys::ptrace::AddressSpace -frysk::sys::ptrace::AddressSpace::data(::jnixx::env env) { - return frysk::sys::ptrace::AddressSpace::New(env, -1UL, - String::NewStringUTF(env, "DATA"), - PTRACE_PEEKDATA, - PTRACE_POKEDATA); -} - -frysk::sys::ptrace::AddressSpace -frysk::sys::ptrace::AddressSpace::usr(::jnixx::env env) { - return frysk::sys::ptrace::AddressSpace::New(env, -1UL, - String::NewStringUTF(env, "USR"), - PTRACE_PEEKUSR, - PTRACE_POKEUSR); -} diff --git a/frysk-sys/frysk/sys/ptrace/jni/BlockSpace.cxx b/frysk-sys/frysk/sys/ptrace/jni/BlockSpace.cxx new file mode 100644 index 0000000..00f54e8 --- /dev/null +++ b/frysk-sys/frysk/sys/ptrace/jni/BlockSpace.cxx @@ -0,0 +1,88 @@ +// This file is part of the program FRYSK. +// +// Copyright 2005, 2006, 2007, 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. + +#include <stdint.h> +#include <sys/types.h> +#include <sys/ptrace.h> +#include "linux.ptrace.h" +#include <sys/user.h> + +#include "jni.hxx" + +#include "frysk/sys/ptrace/jni/Ptrace.hxx" +#include "jnixx/elements.hxx" +#include "jnixx/bounds.hxx" + +void +frysk::sys::ptrace::BlockSpace::transfer(::jnixx::env env, + jint op, jint pid, + ::jnixx::jbyteArray data, + jint length) { + verifyBounds(env, data, length); + jbyteArrayElements bytes = jbyteArrayElements(env, data); + ptraceOp(env, op, pid, NULL, (long) bytes.elements()); + bytes.release(); +} + +frysk::sys::ptrace::BlockSpace +frysk::sys::ptrace::BlockSpace::regs(::jnixx::env env) { +#if defined(__i386__)|| defined(__x86_64__) + return New(env, sizeof(user_regs_struct), PTRACE_GETREGS, PTRACE_SETREGS); +#else + return BlockSpace(env, NULL); +#endif +} + +frysk::sys::ptrace::BlockSpace +frysk::sys::ptrace::BlockSpace::fpregs(::jnixx::env env) { +#if defined(__i386__)|| defined(__x86_64__) + return New(env, sizeof(user_fpregs_struct), PTRACE_GETFPREGS, PTRACE_SETFPREGS); +#else + return BlockSpace(env, NULL); +#endif +} + +frysk::sys::ptrace::BlockSpace +frysk::sys::ptrace::BlockSpace::fpxregs(::jnixx::env env) { +#if defined(__i386__) + return New(env, sizeof(user_fpxregs_struct), PTRACE_GETFPXREGS, PTRACE_SETFPXREGS); +#else + return BlockSpace(env, NULL); +#endif +} diff --git a/frysk-sys/frysk/sys/ptrace/jni/ByteSpace.cxx b/frysk-sys/frysk/sys/ptrace/jni/ByteSpace.cxx new file mode 100644 index 0000000..0fa5fe3 --- /dev/null +++ b/frysk-sys/frysk/sys/ptrace/jni/ByteSpace.cxx @@ -0,0 +1,181 @@ +// This file is part of the program FRYSK. +// +// Copyright 2005, 2006, 2007, 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. + +#define DEBUG 0 + +#include <stdio.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/ptrace.h> +#include "linux.ptrace.h" +#include <string.h> + +#include "jni.hxx" +#include "jnixx/bounds.hxx" +#include "jnixx/elements.hxx" + +#include "frysk/sys/ptrace/jni/Ptrace.hxx" + +using namespace java::lang; + +union word { + long l; + uint8_t b[sizeof (long)]; +}; + +jint +frysk::sys::ptrace::ByteSpace::peek(::jnixx::env env, jint pid, jlong addr) { + union word w; + long paddr = addr & -sizeof(long); + if (DEBUG) + fprintf(stderr, "peek 0x%lx paddr 0x%lx", (long)addr, paddr); + w.l = ptraceOp(env, GetPtPeek(env), pid, (void*)paddr, 0); + if (DEBUG) + fprintf(stderr, " word 0x%lx", w.l); + int index = addr & (sizeof(long) - 1); + if (DEBUG) + fprintf(stderr, " index %d", index); + uint8_t byte = w.b[index]; + if (DEBUG) + fprintf(stderr, " byte %d/0x%x\n", byte, byte); + return byte; +} + +void +frysk::sys::ptrace::ByteSpace::poke(::jnixx::env env, jint pid, jlong addr, jint data) { + // Implement read-modify-write + union word w; + if (DEBUG) + fprintf(stderr, "poke 0x%x", (int)(data & 0xff)); + long paddr = addr & -sizeof(long); + if (DEBUG) + fprintf(stderr, " addr 0x%lx paddr 0x%lx", (long)addr, paddr); + w.l = ptraceOp(env, GetPtPeek(env), pid, (void*)paddr, 0); + if (DEBUG) + fprintf(stderr, " word 0x%lx", w.l); + int index = addr & (sizeof(long) - 1); + if (DEBUG) + fprintf (stderr, " index %d", index); + w.b[index] = data; + if (DEBUG) + fprintf(stderr, " word 0x%lx\n", w.l); + ptraceOp(env, GetPtPoke(env), pid, (void*)(addr & -sizeof(long)), w.l); +} + +void +frysk::sys::ptrace::ByteSpace::transfer(::jnixx::env env, + jint op, jint pid, jlong addr, + ::jnixx::jbyteArray byteArray, + jint offset, jint length) { + const int ptPeek = GetPtPeek(env); + const int ptPoke = GetPtPoke(env); + verifyBounds(env, byteArray, offset, length); + // Somewhat more clueful implementation + for (jlong i = 0; i < length;) { + if (DEBUG) + fprintf(stderr, + "transfer pid %d addr 0x%lx length %d offset %d op %d (%s) ...", + (int)pid, (long)addr, (int)length, (int)offset, + (int)op, ptraceOpToString(op)); + union word w; + unsigned long waddr = addr & -sizeof(long); + unsigned long woff = (addr - waddr); + unsigned long remaining = length - i; + unsigned long wend; + if (remaining > sizeof(long) - woff) + wend = sizeof(long); + else + wend = woff + remaining; + long wlen = wend - woff; + + if (DEBUG) + fprintf(stderr, + " i %ld waddr 0x%lx woff %lu wend %lu remaining %lu wlen %lu ...", + (long)i, waddr, woff, wend, remaining, wlen); + + // Either a peek; or a partial write requiring read/modify/write. + if (op == ptPeek || woff != 0 || wend != sizeof(long)) { + w.l = ptraceOp(env, ptPeek, pid, (void*)waddr, 0); + if (DEBUG) + fprintf(stderr, " peek 0x%lx ...", w.l); + } + + // extract or modify + jbyteArrayElements bytes = jbyteArrayElements(env, byteArray); + if (op == ptPeek) + memcpy(offset + i + bytes.elements(), &w.b[woff], wlen); + else { + memcpy(&w.b[woff], offset + i + bytes.elements(), wlen); + if (DEBUG) + fprintf(stderr, " poke 0x%lx ...", w.l); + w.l = ptraceOp(env, ptPoke, pid, (void*)waddr, w.l); + } + bytes.release(); + + i += wlen; + addr += wlen; + + if (DEBUG) + fprintf(stderr, "\n"); + } +} + +frysk::sys::ptrace::ByteSpace +frysk::sys::ptrace::ByteSpace::text(::jnixx::env env) { + return frysk::sys::ptrace::ByteSpace::New(env, -1UL, + String::NewStringUTF(env, "TEXT"), + PTRACE_PEEKTEXT, + PTRACE_POKETEXT); +} + +frysk::sys::ptrace::ByteSpace +frysk::sys::ptrace::ByteSpace::data(::jnixx::env env) { + return frysk::sys::ptrace::ByteSpace::New(env, -1UL, + String::NewStringUTF(env, "DATA"), + PTRACE_PEEKDATA, + PTRACE_POKEDATA); +} + +frysk::sys::ptrace::ByteSpace +frysk::sys::ptrace::ByteSpace::usr(::jnixx::env env) { + return frysk::sys::ptrace::ByteSpace::New(env, -1UL, + String::NewStringUTF(env, "USR"), + PTRACE_PEEKUSR, + PTRACE_POKEUSR); +} diff --git a/frysk-sys/frysk/sys/ptrace/jni/Ptrace.cxx b/frysk-sys/frysk/sys/ptrace/jni/Ptrace.cxx index 1a7c13f..dce86e5 100644 --- a/frysk-sys/frysk/sys/ptrace/jni/Ptrace.cxx +++ b/frysk-sys/frysk/sys/ptrace/jni/Ptrace.cxx @@ -37,6 +37,10 @@ // version and license this file solely under the GPL without // exception. +#define DEBUG 0 + +#include <stdio.h> +#include <string.h> #include <errno.h> #include <sys/ptrace.h> #include "linux.ptrace.h" @@ -47,8 +51,8 @@ #include "jnixx/exceptions.hxx" -static const char* -op_as_string(int op) { +const char* +ptraceOpToString(int op) { switch(op) { #define OP(NAME) case NAME: return #NAME OP(PTRACE_ATTACH); @@ -82,11 +86,15 @@ op_as_string(int op) { long ptraceOp(::jnixx::env env, int op, int pid, void* addr, long data) { errno = 0; - long result = ::ptrace ((enum __ptrace_request) op, pid, addr, data); - if (errno != 0) + long result = ::ptrace((enum __ptrace_request) op, pid, addr, data); + if (errno != 0) { + int err = errno; + if (DEBUG) + fprintf(stderr, "throwing %s\n", strerror(err)); errnoException(env, errno, "ptrace", "op 0x%x (%s), pid %d, addr 0x%lx, data 0x%lx", - op, op_as_string(op), pid, (long)addr, data); + op, ptraceOpToString(op), pid, (long)addr, data); + } return result; } diff --git a/frysk-sys/frysk/sys/ptrace/jni/Ptrace.hxx b/frysk-sys/frysk/sys/ptrace/jni/Ptrace.hxx index be134ef..46e2edd 100644 --- a/frysk-sys/frysk/sys/ptrace/jni/Ptrace.hxx +++ b/frysk-sys/frysk/sys/ptrace/jni/Ptrace.hxx @@ -38,3 +38,4 @@ // exception. extern long ptraceOp(::jnixx::env, int, int, void*, long); +extern const char *ptraceOpToString(int op); diff --git a/frysk-sys/frysk/sys/ptrace/jni/RegisterSet.cxx b/frysk-sys/frysk/sys/ptrace/jni/RegisterSet.cxx deleted file mode 100644 index d8fe8ca..0000000 --- a/frysk-sys/frysk/sys/ptrace/jni/RegisterSet.cxx +++ /dev/null @@ -1,88 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2005, 2006, 2007, 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. - -#include <stdint.h> -#include <sys/types.h> -#include <sys/ptrace.h> -#include "linux.ptrace.h" -#include <sys/user.h> - -#include "jni.hxx" - -#include "frysk/sys/ptrace/jni/Ptrace.hxx" -#include "jnixx/elements.hxx" -#include "jnixx/bounds.hxx" - -void -frysk::sys::ptrace::RegisterSet::transfer(::jnixx::env env, - jint op, jint pid, - ::jnixx::jbyteArray data, - jint length) { - verifyBounds(env, data, length); - jbyteArrayElements bytes = jbyteArrayElements(env, data); - ptraceOp(env, op, pid, NULL, (long) bytes.elements()); - bytes.release(); -} - -frysk::sys::ptrace::RegisterSet -frysk::sys::ptrace::RegisterSet::regs(::jnixx::env env) { -#if defined(__i386__)|| defined(__x86_64__) - return New(env, sizeof(user_regs_struct), PTRACE_GETREGS, PTRACE_SETREGS); -#else - return RegisterSet(env, NULL); -#endif -} - -frysk::sys::ptrace::RegisterSet -frysk::sys::ptrace::RegisterSet::fpregs(::jnixx::env env) { -#if defined(__i386__)|| defined(__x86_64__) - return New(env, sizeof(user_fpregs_struct), PTRACE_GETFPREGS, PTRACE_SETFPREGS); -#else - return RegisterSet(env, NULL); -#endif -} - -frysk::sys::ptrace::RegisterSet -frysk::sys::ptrace::RegisterSet::fpxregs(::jnixx::env env) { -#if defined(__i386__) - return New(env, sizeof(user_fpxregs_struct), PTRACE_GETFPXREGS, PTRACE_SETFPXREGS); -#else - return RegisterSet(env, NULL); -#endif -} diff --git a/frysk-sys/frysk/sys/ptrace/jni/Utrace.cxx b/frysk-sys/frysk/sys/ptrace/jni/Utrace.cxx deleted file mode 100644 index b358932..0000000 --- a/frysk-sys/frysk/sys/ptrace/jni/Utrace.cxx +++ /dev/null @@ -1,40 +0,0 @@ -// 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. - -#include "jni.hxx" diff --git a/frysk-sys/frysk/testbed/ChangeLog b/frysk-sys/frysk/testbed/ChangeLog index 60bdb8a..4b44ac6 100644 --- a/frysk-sys/frysk/testbed/ChangeLog +++ b/frysk-sys/frysk/testbed/ChangeLog @@ -1,3 +1,18 @@ +2008-07-04 Andrew Cagney <cagney@redhat.com> + + * LocalMemory.java: Update; AddressSpace renamed to ByteSpace. + +2008-06-19 Andrew Cagney <cagney@redhat.com> + + * TestLocalMemory.java (testMemoryByteBuffer()): New. + * LocalMemory.java (getByteBuffer()): New. + * jni/LocalMemory.cxx (LocalMemory::peek): Implement. + * cni/LocalMemory.cxx (LocalMemory::peek): Implement. + +2008-06-12 Andrew Cagney <cagney@redhat.com> + + * TearDownExpect.java (TearDownExpect()): Add. + 2008-06-06 Andrew Cagney <cagney@redhat.com> * LocalMemory.java (getModuleName()): New. diff --git a/frysk-sys/frysk/testbed/LocalMemory.java b/frysk-sys/frysk/testbed/LocalMemory.java index c79f331..c9ff821 100644 --- a/frysk-sys/frysk/testbed/LocalMemory.java +++ b/frysk-sys/frysk/testbed/LocalMemory.java @@ -39,6 +39,9 @@ package frysk.testbed; +import inua.eio.ByteBuffer; +import frysk.sys.ptrace.ByteSpace; + /** * Provide access to known local areas of memory. * @@ -102,4 +105,20 @@ public class LocalMemory { * will be so large that it is negative. */ public static native void constructStack(StackBuilder builder); + + /** + * Return a byte-buffer capable of reading any address of this + * thread's memory. + */ + public static ByteBuffer getByteBuffer() { + return new ByteBuffer(0, ByteSpace.DATA.length()) { + protected int peek(long offset) { + return LocalMemory.peek(offset); + } + protected void poke(long offset, int b) { + // do nothing + } + }; + } + private static native int peek(long addr); } diff --git a/frysk-sys/frysk/testbed/TearDownExpect.java b/frysk-sys/frysk/testbed/TearDownExpect.java index 0e50faf..7bbdcfb 100644 --- a/frysk-sys/frysk/testbed/TearDownExpect.java +++ b/frysk-sys/frysk/testbed/TearDownExpect.java @@ -65,6 +65,10 @@ public class TearDownExpect extends Expect { super(command); add(this); } + public TearDownExpect() { + super(); + add(this); + } /** * Collection of expect classes. diff --git a/frysk-sys/frysk/testbed/TestLocalMemory.java b/frysk-sys/frysk/testbed/TestLocalMemory.java index f378d55..4d4447c 100644 --- a/frysk-sys/frysk/testbed/TestLocalMemory.java +++ b/frysk-sys/frysk/testbed/TestLocalMemory.java @@ -1,6 +1,6 @@ // This file is part of the program FRYSK. // -// Copyright 2007, Red Hat Inc. +// Copyright 2007, 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 @@ -40,13 +40,12 @@ package frysk.testbed; import frysk.junit.TestCase; +import inua.eio.ByteBuffer; /** * Check that LocalMemory addresses are pointing where expected. */ -public class TestLocalMemory - extends TestCase -{ +public class TestLocalMemory extends TestCase { /** * Check that the stack address changes as new stack frames are * created. @@ -96,4 +95,12 @@ public class TestLocalMemory byte[] bytes = LocalMemory.getDataBytes(); assertEquals("data byte[0]", 43, bytes[0]); } + + + public void testMemoryByteBuffer() { + ByteBuffer memory = LocalMemory.getByteBuffer(); + assertEquals("data", LocalMemory.getDataBytes()[0], + memory.get(LocalMemory.getDataAddr())); + } + } diff --git a/frysk-sys/frysk/testbed/cni/LocalMemory.cxx b/frysk-sys/frysk/testbed/cni/LocalMemory.cxx index f2944ea..8afd4af 100644 --- a/frysk-sys/frysk/testbed/cni/LocalMemory.cxx +++ b/frysk-sys/frysk/testbed/cni/LocalMemory.cxx @@ -1,6 +1,6 @@ // This file is part of the program FRYSK. // -// Copyright 2005, 2006, 2007, 2008 Red Hat Inc. +// Copyright 2005, 2006, 2007, 2008, 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 @@ -130,3 +130,8 @@ LocalMemory::getModuleName() { // be deleted. return JvNewStringUTF("TestRunner"); } + +jint +LocalMemory::peek(jlong addr) { + return *(unsigned char*)addr; +} diff --git a/frysk-sys/frysk/testbed/jni/LocalMemory.cxx b/frysk-sys/frysk/testbed/jni/LocalMemory.cxx index 840e129..9324cf2 100644 --- a/frysk-sys/frysk/testbed/jni/LocalMemory.cxx +++ b/frysk-sys/frysk/testbed/jni/LocalMemory.cxx @@ -127,3 +127,8 @@ String LocalMemory::getModuleName(::jnixx::env env) { return String::NewStringUTF(env, "libfrysk-sys-jni.so"); } + +jint +LocalMemory::peek(::jnixx::env env, jlong addr) { + return *(unsigned char*)addr; +} diff --git a/frysk-sys/inua/ChangeLog b/frysk-sys/inua/ChangeLog index 1827bf2..16ae59b 100644 --- a/frysk-sys/inua/ChangeLog +++ b/frysk-sys/inua/ChangeLog @@ -1,3 +1,8 @@ +2008-07-04 Andrew Cagney <cagney@redhat.com> + + * eio/ByteBuffer.java: Throw InternalException. + * eio/BufferUnderflowException.java: Extend UserException. + 2008-06-05 Andrew Cagney <cagney@redhat.com> * eio/ByteBuffer.java: Add missing indexed word get/put methods. diff --git a/frysk-sys/inua/eio/BufferUnderflowException.java b/frysk-sys/inua/eio/BufferUnderflowException.java index a17063d..2f9f7ed 100644 --- a/frysk-sys/inua/eio/BufferUnderflowException.java +++ b/frysk-sys/inua/eio/BufferUnderflowException.java @@ -34,10 +34,14 @@ // modification, you must delete this exception statement from your // version and license this file solely under the GPL without // exception. + package inua.eio; -public class BufferUnderflowException - extends java.nio.BufferUnderflowException -{ +import frysk.UserException; + +public class BufferUnderflowException extends UserException { private static final long serialVersionUID = 1L; + BufferUnderflowException(long address) { + super("Address 0x" + Long.toHexString(address) + " out of bounds"); + } } diff --git a/frysk-sys/inua/eio/ByteBuffer.java b/frysk-sys/inua/eio/ByteBuffer.java index 6549a58..873e481 100644 --- a/frysk-sys/inua/eio/ByteBuffer.java +++ b/frysk-sys/inua/eio/ByteBuffer.java @@ -40,9 +40,10 @@ * A ByteBuffer. Just like {@link java.nio.ByteBuffer} only 64-bit. */ - package inua.eio; +import frysk.InternalException; + public abstract class ByteBuffer extends Buffer { @@ -293,9 +294,8 @@ public abstract class ByteBuffer * Given BUFFER, return a new subBuffer. Used by {@link #slice}. */ protected ByteBuffer subBuffer (ByteBuffer buffer, long lowerExtreem, - long upperExtreem) - { - throw new RuntimeException("not implemented"); + long upperExtreem) { + throw new InternalException("not implemented"); } public ByteBuffer slice (long off, long len) @@ -321,14 +321,12 @@ public abstract class ByteBuffer return (byte) peek(lowWater + index); } - public ByteBuffer get (long index, byte[] dst, int off, int len) - throws BufferUnderflowException - { - if (ULong.GT(index + len, limit())) - throw new BufferUnderflowException(); - peekFully(lowWater + index,dst,off,len); - return this; - } + public ByteBuffer get(long index, byte[] dst, int off, int len) { + if (ULong.GT(index + len, limit())) + throw new BufferUnderflowException(index + len); + peekFully(lowWater + index,dst,off,len); + return this; + } public int safeGet (long index, byte[] dst, int off, int len) { @@ -339,35 +337,29 @@ public abstract class ByteBuffer return maxLen; } - public ByteBuffer get (byte[] dst, int off, int len) - throws BufferUnderflowException - { - if (ULong.GT(len, remaining())) - throw new BufferUnderflowException(); - peek(cursor, dst, off, len); - cursor += len; - return this; - } + public ByteBuffer get(byte[] dst, int off, int len) { + if (ULong.GT(len, remaining())) + throw new BufferUnderflowException(len); + peek(cursor, dst, off, len); + cursor += len; + return this; + } - public final ByteBuffer get (byte[] dst) throws BufferUnderflowException - { - return get(dst, 0, dst.length); - } + public final ByteBuffer get (byte[] dst) { + return get(dst, 0, dst.length); + } - public ByteBuffer put (byte[] src, int off, int len) - throws BufferUnderflowException - { - if (ULong.GT(len, remaining())) - throw new BufferUnderflowException(); - poke(cursor, src, off, len); - cursor += len; - return this; - } + public ByteBuffer put (byte[] src, int off, int len) { + if (ULong.GT(len, remaining())) + throw new BufferUnderflowException(len); + poke(cursor, src, off, len); + cursor += len; + return this; + } - public final ByteBuffer put (byte[] src) throws BufferUnderflowException - { - return put(src, 0, src.length); - } + public final ByteBuffer put (byte[] src) { + return put(src, 0, src.length); + } protected ByteOrdered byteOrdered; diff --git a/frysk-sys/jnixx/ChangeLog b/frysk-sys/jnixx/ChangeLog index 7fdd6ba..d9ce902 100644 --- a/frysk-sys/jnixx/ChangeLog +++ b/frysk-sys/jnixx/ChangeLog @@ -1,3 +1,14 @@ +2008-06-20 Andrew Cagney <cagney@redhat.com> + + * elements.hxx (slurp): Return the BUF. + (FileElements::slurp): Update. + * elements.cxx (slurp): Update; when file-not-found return NULL. + +2008-06-12 Andrew Cagney <cagney@redhat.com> + + * exceptions.cxx (userException): Implement. + * exceptions.hxx (userException): Declare. + 2008-06-04 Andrew Cagney <cagney@redhat.com> * elements.cxx (slurp): Don't count the terminating NUL in the diff --git a/frysk-sys/jnixx/elements.cxx b/frysk-sys/jnixx/elements.cxx index 4a432ae..4200f2f 100644 --- a/frysk-sys/jnixx/elements.cxx +++ b/frysk-sys/jnixx/elements.cxx @@ -102,12 +102,13 @@ chars2strings(::jnixx::env env, char** argv) { return strings; } -void -slurp(jnixx::env env, const char file[], jbyte*& buf, jsize& len) { +jbyte* +slurp(jnixx::env env, const char file[], jsize& len) { // Attempt to open the file. int fd = ::open(file, O_RDONLY); if (fd < 0) { - errnoException(env, errno, "open", "file %s", file); + len = 0; + return NULL; } // Initially allocate space for two BUFSIZE reads (and an extra NUL @@ -117,7 +118,7 @@ slurp(jnixx::env env, const char file[], jbyte*& buf, jsize& len) { // reads are needed to confirm EOF. Allocating 2&BUFSIZE ensures // that there's always space for at least two reads. Ref SW #3370 jsize allocated = BUFSIZ * 2 + 1; - buf = (jbyte*) ::malloc(allocated); + jbyte* buf = (jbyte*) ::malloc(allocated); if (buf == NULL) { errnoException(env, errno, "malloc"); } @@ -131,9 +132,8 @@ slurp(jnixx::env env, const char file[], jbyte*& buf, jsize& len) { ::close(fd); ::free(buf); // Abandon the read with elements == NULL. - buf = NULL; len = 0; - return; + return NULL; } else if (size == 0) { break; } @@ -149,7 +149,6 @@ slurp(jnixx::env env, const char file[], jbyte*& buf, jsize& len) { int err = errno; ::close(fd); ::free(buf); - buf = NULL; len = 0; errnoException(env, err, "realloc"); } @@ -162,4 +161,5 @@ slurp(jnixx::env env, const char file[], jbyte*& buf, jsize& len) { // Guarentee that the buffer is NUL terminated; but don't count that // as part of the buffer. buf[len] = '\0'; + return buf; } diff --git a/frysk-sys/jnixx/elements.hxx b/frysk-sys/jnixx/elements.hxx index 75f137f..dcf8109 100644 --- a/frysk-sys/jnixx/elements.hxx +++ b/frysk-sys/jnixx/elements.hxx @@ -49,7 +49,13 @@ extern char** strings2chars(::jnixx::env, ::jnixx::array<java::lang::String>); extern ::jnixx::array<java::lang::String> chars2strings(::jnixx::env, char**); -extern void slurp(::jnixx::env, const char[], jbyte* (&), jsize&); + +/** + * Attempt to read the entire contents of the specified file. Return + * BUF and set LEN, or NULL should the open fail. The BUF will be NUL + * terminated but the NUL will not be included in the character count. + */ +extern jbyte* slurp(::jnixx::env, const char file[], jsize& len); class StringArrayChars { private: @@ -239,9 +245,8 @@ public: } protected: void slurp(jnixx::env& env, type* (&buf), jsize &len) { - jbyte* buffer; jsize length; - ::slurp(env, file, buffer, length); + jbyte* buffer = ::slurp(env, file, length); buf = (type*)buffer; len = length / sizeof(type); } diff --git a/frysk-sys/jnixx/exceptions.cxx b/frysk-sys/jnixx/exceptions.cxx index 2f5ce80..928e0fd 100644 --- a/frysk-sys/jnixx/exceptions.cxx +++ b/frysk-sys/jnixx/exceptions.cxx @@ -150,3 +150,26 @@ runtimeException(::jnixx::env& env, const char *fmt, ...) { throw e; } } + + +void +userException(::jnixx::env& env, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + char *message = NULL; + if (::vasprintf(&message, fmt, ap) < 0) { + // If this fails things are pretty much stuffed. + int err = errno; + fprintf(stderr, "warning: vasprintf in runtimeException failed: %s", + ::strerror(err)); + RuntimeException::ThrowNew(env, "vasprintf in runtimeException failed"); + } + va_end(ap); + try { + frysk::UserException::ThrowNew(env, message); + } catch (java::lang::Throwable e) { + // Always executed. + ::free(message); + throw e; + } +} diff --git a/frysk-sys/jnixx/exceptions.hxx b/frysk-sys/jnixx/exceptions.hxx index 877356c..36fde6f 100644 --- a/frysk-sys/jnixx/exceptions.hxx +++ b/frysk-sys/jnixx/exceptions.hxx @@ -52,3 +52,7 @@ extern void errnoException(::jnixx::env& env, int error, const char *prefix, extern void runtimeException(::jnixx::env& env, const char *fmt, ...) __attribute__((noreturn)) __attribute__((format (printf, 2, 3))); + +extern void userException(::jnixx::env& env, const char *fmt, ...) + __attribute__((noreturn)) + __attribute__((format (printf, 2, 3))); diff --git a/frysk-sys/lib/dwfl/ChangeLog b/frysk-sys/lib/dwfl/ChangeLog index 762b92a..43dc64a 100644 --- a/frysk-sys/lib/dwfl/ChangeLog +++ b/frysk-sys/lib/dwfl/ChangeLog @@ -1,3 +1,41 @@ +2008-06-19 Andrew Cagney <cagney@redhat.com> + + * cni/Dwfl.cxx (dwfl_frysk_proc_find_elf): Always set file_name so + elfutils realises that the ELF was set. + * jni/Dwfl.cxx: Ditto. + * TestDwfl.java (testMapContainsVdso): Check the vdso's elf. + * Dwfl.java (mapModule): Include segments starting with "[". + + * DwflTestbed.java (createFromSelf()): Pass LocalMemory to the Dwfl. + * cni/DwflModule.cxx (DwflModule::setUserData): Delete. + * jni/DwflModule.cxx (DwflModule::setUserData): Delete. + * Dwfl.java (Dwfl(String,ByteBuffer)): New. + * DwflModule.java (setUserData(Object)): Delete. + * jni/Dwfl.cxx: Update. + * cni/Dwfl.cxx: Update. + + * Dwfl.java (mapModule): Correctly add maps such as [vdso]. + * TestDwfl.java (testMapContainsVdso()): New. + * DwflTestbed.java (VdsoBuilder): Delete. + (createFromSelf()): Don't pass in the vdso. + +2008-06-16 Andrew Cagney <cagney@redhat.com> + + * DwflModule.java (get_cu_dies): Add pointer parameter. + * cni/DwflModule.cxx (DwflModule::get_cu_dies): Update. + * jni/DwflModule.cxx (DwflModule::get_cu_dies): Implement, missing. + +2008-06-15 Andrew Cagney <cagney@redhat.com> + + * DwarfDie.java (get_scopevar): Return an int. + * jni/DwarfDie.cxx (DwarfDie::get_scopevar): Only examine the die + when its valid. + * cni/DwarfDie.cxx (DwarfDie::get_scopevar): Ditto. + +2008-06-12 Andrew Cagney <cagney@redhat.com> + + * ElfException.java: Extend UserException. + 2008-06-07 Andrew Cagney <cagney@redhat.com> * jni/ElfSymbol.cxx (ElfSymbol::elf_load_verneed): Don't delete a diff --git a/frysk-sys/lib/dwfl/DwarfDie.java b/frysk-sys/lib/dwfl/DwarfDie.java index dda1671..bc2d24b 100644 --- a/frysk-sys/lib/dwfl/DwarfDie.java +++ b/frysk-sys/lib/dwfl/DwarfDie.java @@ -476,7 +476,8 @@ public class DwarfDie { private native long[] get_scopes_die (); - private native long get_scopevar (long[] die_scope, long[] scopes, String variable); + private native int get_scopevar(long[] die_scope, long[] scopes, + String variable); private native long get_scopevar_names (long[] scopes, String variable); diff --git a/frysk-sys/lib/dwfl/Dwfl.java b/frysk-sys/lib/dwfl/Dwfl.java index 9e9ef82..f540e9f 100644 --- a/frysk-sys/lib/dwfl/Dwfl.java +++ b/frysk-sys/lib/dwfl/Dwfl.java @@ -43,25 +43,37 @@ import java.util.LinkedHashMap; import java.util.LinkedList; import frysk.rsl.Log; import inua.eio.ULong; +import inua.eio.ByteBuffer; public class Dwfl { private static final Log fine = Log.fine(Dwfl.class); private static final Log finest = Log.finest(Dwfl.class); + private long userdata; private long pointer; private long callbacks; protected final DwarfDieFactory factory = DwarfDieFactory.getFactory(); /** - * Create a dwfl with the specified debug-info search path. + * Create a dwfl with the specified debug-info search path and + * memory. + */ + public Dwfl(String debugInfoPath, ByteBuffer memory) { + callbacks = dwfl_callbacks_begin(debugInfoPath); + userdata = dwfl_userdata_begin(memory); + pointer = dwfl_begin(callbacks); + } + private static native long dwfl_callbacks_begin(String debugInfoSearchPath); + private static native long dwfl_userdata_begin(ByteBuffer memory); + private static native long dwfl_begin(long callbacks); + /** + * Create a dwfl with the specified debug-info search path and + * memory. */ public Dwfl(String debugInfoPath) { - callbacks = callbacksBegin(debugInfoPath); - pointer = dwflBegin(callbacks); + this(debugInfoPath, null); } - private static native long callbacksBegin(String debugInfoSearchPath); - private static native long dwflBegin(long callbacks); protected void finalize () { if (this.pointer != 0) { @@ -71,14 +83,16 @@ public class Dwfl { } public void close() { if (this.pointer != 0) { - dwflEnd(pointer); + dwfl_end(pointer); this.pointer = 0; - callbacksEnd(callbacks); + dwfl_userdata_end(userdata); + dwfl_callbacks_end(callbacks); this.callbacks = 0; } } - private static native void dwflEnd(long pointer); - private static native void callbacksEnd(long callbacks); + private static native void dwfl_end(long pointer); + private static native void dwfl_userdata_end(long userdata); + private static native void dwfl_callbacks_end(long callbacks); public DwflLine getSourceLine (long addr) { DwflModule module = getModule(addr); @@ -158,32 +172,33 @@ public class Dwfl { */ public void reportBegin() { fine.log(this, "reportBegin"); - reportBegin(pointer); + dwfl_report_begin(pointer); // fill modulesArray with the current modules and then clear // the set. Will iterate over the old modules so that they // are re-used. getModules(); modules.clear(); } - private static native void reportBegin(long pointer); + private static native void dwfl_report_begin(long pointer); /** * Finish a refresh of the address map. */ public void reportEnd() { fine.log(this, "reportEnd"); - reportEnd(pointer); + dwfl_report_end(pointer); // Finished; scrub references to old modules. modulesArray = null; } - private static native void reportEnd(long pointer); + private static native void dwfl_report_end(long pointer); /** * Report a mapped component. */ public void reportModule(String moduleName, long low, long high) { fine.log(this, "reportModule", moduleName, "low", low, "high", high); - long modulePointer = reportModule(pointer, moduleName, low, high); + long modulePointer = dwfl_report_module(pointer, moduleName, low, high, + userdata); for (int i = 0; i < modulesArray.length; i++) { DwflModule module = modulesArray[i]; if (module.getName().equals(moduleName) @@ -202,8 +217,10 @@ public class Dwfl { finest.log(this, "reportModule creating", module); modules.put(new Long(modulePointer), module); } - private static native long reportModule(long pointer, String moduleName, - long low, long high); + private static native long dwfl_report_module(long pointer, + String moduleName, + long low, long high, + long userdata); private String name; private long low; @@ -211,14 +228,12 @@ public class Dwfl { private int devMajor; private int devMinor; private int inode; - private long vdso; /** * Start refreshing the address map using raw information * extracted from /proc/pid/maps. */ - public void mapBegin(long vdso) { + public void mapBegin() { reportBegin(); - this.vdso = vdso; name = null; } /** @@ -226,28 +241,35 @@ public class Dwfl { */ public void mapModule(String name, long low, long high, int devMajor, int devMinor, int inode) { - if (this.name != null && this.name.equals(name) + finest.log(this, "mapModule", name, "low", low, "high", high, + "devMajor", devMajor, "devMinor", devMinor, "inode", inode); + if (this.name != null + && this.name.equals(name) && this.devMajor == devMajor && this.devMinor == devMinor && this.inode == inode ) { + finest.log(this, "extending to", high); // A repeat of a previous map (but with more addresses) // extend the address range. this.high = high; } else { if (this.name != null) { // There's a previous map, report and flush it. + finest.log(this, "reporting", this.name); reportModule(this.name, this.low, this.high); this.name = null; } - if (name.equals("") - || (devMajor == 0 && devMinor == 0 && inode == 0)) { - // An empty map, do nothing. - } else if (this.vdso == low) { - // A vdso, report it immediatly. - reportModule(name, low, high); + if (name == null) { + finest.log(this, "ignoring null name"); + } else if (name.equals("")) { + finest.log(this, "ignoring empty name"); + } else if (name.indexOf("(deleted") >= 0) { + finest.log(this, "ignoring deleted", name); + } else if (!name.startsWith("/") && !name.equals("[vdso]")) { + finest.log(this, "ignoring non-file", name); } else { - // A new map, save it. + // A new map, save it, will be reported later. this.name = name; this.low = low; this.high = high; diff --git a/frysk-sys/lib/dwfl/DwflModule.java b/frysk-sys/lib/dwfl/DwflModule.java index b262ec4..b73d3c6 100644 --- a/frysk-sys/lib/dwfl/DwflModule.java +++ b/frysk-sys/lib/dwfl/DwflModule.java @@ -40,6 +40,7 @@ package lib.dwfl; import java.util.LinkedList; +import java.util.List; /** * A wrapper object around the libdwfl Dwfl_Module structure. @@ -65,7 +66,10 @@ public class DwflModule { public String toString() { - return name + " pointer: 0x" + Long.toHexString(pointer); + return name + + " 0x" + Long.toHexString(low) + + "..0x" + Long.toHexString(high) + + " pointer=0x" + Long.toHexString(pointer); } public long lowAddress() { @@ -132,8 +136,6 @@ public class DwflModule { public native void getSymbolByName(String name, SymbolBuilder symbolBuilder); - - public native void setUserData(Object data); /** * Get the debuginfo path for DwflModule @@ -142,10 +144,12 @@ public class DwflModule { */ public native String getDebuginfo(); - public LinkedList getCuDies(){ - return get_cu_dies(); + public List getCuDies(){ + List list = new LinkedList(); + get_cu_dies(pointer, list); + return list; } - private native LinkedList get_cu_dies(); + private static native void get_cu_dies(long pointer, List list); public DwflDie getCompilationUnit(long addr) { // Find the die, grab the bias as it flies by. diff --git a/frysk-sys/lib/dwfl/DwflTestbed.java b/frysk-sys/lib/dwfl/DwflTestbed.java index 80aed86..3c931bf 100644 --- a/frysk-sys/lib/dwfl/DwflTestbed.java +++ b/frysk-sys/lib/dwfl/DwflTestbed.java @@ -39,26 +39,12 @@ package lib.dwfl; +import frysk.testbed.LocalMemory; import frysk.sys.proc.MapsBuilder; import frysk.sys.Pid; -import frysk.sys.proc.AuxvBuilder; public class DwflTestbed { - private static class VdsoBuilder extends AuxvBuilder { - long address; - public void buildBuffer(byte[] auxv) { - } - public void buildDimensions(int wordSize, boolean bigEndian, - int numberElements) { - } - public void buildAuxiliary(int index, int type, long value) { - if (type == inua.elf.AT.SYSINFO_EHDR) { - address = value; - } - } - } - private static class ModuleBuilder extends MapsBuilder { private final Dwfl dwfl; ModuleBuilder(Dwfl dwfl) { @@ -90,11 +76,9 @@ public class DwflTestbed { * Create a dwfl from this process. */ static Dwfl createFromSelf() { - Dwfl dwfl = new Dwfl(""); + Dwfl dwfl = new Dwfl("", LocalMemory.getByteBuffer()); ModuleBuilder maps = new ModuleBuilder(dwfl); - VdsoBuilder vdso = new VdsoBuilder(); - vdso.construct(Pid.get()); - dwfl.mapBegin(vdso.address); + dwfl.mapBegin(); maps.construct(Pid.get()); dwfl.mapEnd(); return dwfl; diff --git a/frysk-sys/lib/dwfl/ElfException.java b/frysk-sys/lib/dwfl/ElfException.java index 86306e8..6454a34 100644 --- a/frysk-sys/lib/dwfl/ElfException.java +++ b/frysk-sys/lib/dwfl/ElfException.java @@ -39,12 +39,14 @@ package lib.dwfl; +import frysk.UserException; + /** * The Elf back-end detected a problem; it might be an invalid * operation; it might also be a corrupt part of an elf file. */ -public class ElfException extends RuntimeException { +public class ElfException extends UserException { private static final long serialVersionUID = 400112389738713948L; ElfException(Throwable t) { diff --git a/frysk-sys/lib/dwfl/TestDwfl.java b/frysk-sys/lib/dwfl/TestDwfl.java index d8076d2..2d2bcc4 100644 --- a/frysk-sys/lib/dwfl/TestDwfl.java +++ b/frysk-sys/lib/dwfl/TestDwfl.java @@ -232,4 +232,20 @@ public class TestDwfl extends TestCase { } assertTrue(foundAddress); } + + public void testMapContainsVdso() { + Dwfl dwfl = DwflTestbed.createFromSelf(); + DwflModule[] modules = dwfl.getModules(); + DwflModule vdso = null; + for (int i = 0; i < modules.length; i++) { + DwflModule module = modules[i]; + finest.log("module", i, "name", module); + if (module.getName().equals("[vdso]")) { + vdso = module; + break; + } + } + assertNotNull("vdso", vdso); + assertNotNull("elf", vdso.getElf()); + } } diff --git a/frysk-sys/lib/dwfl/cni/DwarfDie.cxx b/frysk-sys/lib/dwfl/cni/DwarfDie.cxx index c562d2e..b10689d 100644 --- a/frysk-sys/lib/dwfl/cni/DwarfDie.cxx +++ b/frysk-sys/lib/dwfl/cni/DwarfDie.cxx @@ -1,6 +1,6 @@ // This file is part of the program FRYSK. // -// Copyright 2005, 2007, Red Hat Inc. +// Copyright 2005, 2007, 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 @@ -165,10 +165,9 @@ lib::dwfl::DwarfDie::get_scopes_die() Dwarf_Die *var_die; -jlong -lib::dwfl::DwarfDie::get_scopevar (jlongArray die_scope, jlongArray scopes, - jstring variable) -{ +jint +lib::dwfl::DwarfDie::get_scopevar(jlongArray die_scope, jlongArray scopes, + jstring variable) { var_die = (Dwarf_Die*)JvMalloc(sizeof(Dwarf_Die)); int nscopes = JvGetArrayLength (scopes); @@ -176,11 +175,10 @@ lib::dwfl::DwarfDie::get_scopevar (jlongArray die_scope, jlongArray scopes, Dwarf_Die *dies[nscopes]; jlong* scopesp = elements(scopes); - for(int i = 0; i < nscopes; i++) - { - jlong dieptr = scopesp[i]; - dies[i] = (Dwarf_Die*)dieptr; - } + for(int i = 0; i < nscopes; i++) { + jlong dieptr = scopesp[i]; + dies[i] = (Dwarf_Die*)dieptr; + } int utf_variable_len = variable->length (); char utf_variable[utf_variable_len + 1]; @@ -190,16 +188,15 @@ lib::dwfl::DwarfDie::get_scopevar (jlongArray die_scope, jlongArray scopes, int code = dwarf_getscopevar (*dies, nscopes, utf_variable, 0, NULL, 0, 0, var_die); - if (code >= 0) - { - if (dwarf_tag (var_die) != DW_TAG_variable) - return -1; - jlong* longp = elements(die_scope); - longp[0] = (jlong)var_die; // Die for variable - longp[1] = code; // Die for scope - } - else if (dwarf_tag (var_die) != DW_TAG_variable) - return -1; + if (code >= 0) { + if (dwarf_tag(var_die) != DW_TAG_variable) + return -1; + jlong* longp = elements(die_scope); + longp[0] = (jlong)var_die; // Die for variable + longp[1] = code; // Die for scope + } else { + ::free(var_die); + } return code; } diff --git a/frysk-sys/lib/dwfl/cni/Dwfl.cxx b/frysk-sys/lib/dwfl/cni/Dwfl.cxx index ceb76aa..e17af96 100644 --- a/frysk-sys/lib/dwfl/cni/Dwfl.cxx +++ b/frysk-sys/lib/dwfl/cni/Dwfl.cxx @@ -79,7 +79,6 @@ read_proc_memory (void *arg, void *data, GElf_Addr address, size_t minread, size_t maxread) { inua::eio::ByteBuffer* memory = (inua::eio::ByteBuffer *) arg; - jbyteArray bytes = JvNewByteArray(maxread); ssize_t nread = memory->safeGet((off64_t) address, bytes, 0, maxread); memcpy(data, elements(bytes), nread); @@ -94,41 +93,37 @@ dwfl_frysk_proc_find_elf (Dwfl_Module *mod, const char *module_name, Dwarf_Addr base, char **file_name, Elf **elfp) { - // There is an edge case here that was tripped by a corefile case. In that case the - // specified executable was defined as a relative path (ie ../foo/bar). And that is - // perfectly valid path name. However when the corefile created its maps it did not - // convert that path to an absolute path, causing the test below to fail and consider - // the file ../foo/bar to be an in memory elf image. - if (module_name[0] == '/') - { - int fd = open64 (module_name, O_RDONLY); - if (fd >= 0) - { - *file_name = strdup (module_name); - if (*file_name == NULL) - { - close (fd); - return ENOMEM; - } - } - return fd; - } - else - { - /* Special case for in-memory ELF image. */ - inua::eio::ByteBuffer * memory = (inua::eio::ByteBuffer *) *userdata; - - *elfp = elf_from_remote_memory (base, NULL, &read_proc_memory, memory); - + // There is an edge case here that was tripped by a corefile + // case. In that case the specified executable was defined as a + // relative path (ie ../foo/bar). And that is perfectly valid path + // name. However when the corefile created its maps it did not + // convert that path to an absolute path, causing the test below to + // fail and consider the file ../foo/bar to be an in memory elf + // image. + if (module_name[0] == '/') { + // Pass back the file name and let dwfl take care of the rest. + *file_name = strdup (module_name); + return -1; + } else { + *elfp = elf_from_remote_memory (base, NULL, &read_proc_memory, *userdata); + if (*elfp != NULL) { + *file_name = ::strdup(module_name); + } return -1; } +} + +jlong +lib::dwfl::Dwfl::dwfl_userdata_begin(inua::eio::ByteBuffer *memory) { + return (jlong)memory; +} - //abort (); - return -1; +void +lib::dwfl::Dwfl::dwfl_userdata_end(jlong userdata) { } jlong -lib::dwfl::Dwfl::callbacksBegin(jstring debugInfoPath) { +lib::dwfl::Dwfl::dwfl_callbacks_begin(jstring debugInfoPath) { char** path = (char**) JvMalloc(sizeof (char*)); int len = JvGetStringUTFLength(debugInfoPath); *path = (char*)JvMalloc(len + 1); @@ -145,45 +140,54 @@ lib::dwfl::Dwfl::callbacksBegin(jstring debugInfoPath) { } void -lib::dwfl::Dwfl::callbacksEnd(jlong callbacks) { +lib::dwfl::Dwfl::dwfl_callbacks_end(jlong callbacks) { JvFree(*DWFL_CALLBACKS->debuginfo_path); JvFree(DWFL_CALLBACKS->debuginfo_path); JvFree(DWFL_CALLBACKS); } jlong -lib::dwfl::Dwfl::dwflBegin(jlong callbacks) { +lib::dwfl::Dwfl::dwfl_begin(jlong callbacks) { return (jlong) ::dwfl_begin(DWFL_CALLBACKS); } void -lib::dwfl::Dwfl::dwflEnd(jlong pointer){ +lib::dwfl::Dwfl::dwfl_end(jlong pointer){ ::dwfl_end(DWFL_POINTER); } void -lib::dwfl::Dwfl::reportBegin(jlong pointer) { +lib::dwfl::Dwfl::dwfl_report_begin(jlong pointer) { ::dwfl_report_begin(DWFL_POINTER); } void -lib::dwfl::Dwfl::reportEnd(jlong pointer) { +lib::dwfl::Dwfl::dwfl_report_end(jlong pointer) { ::dwfl_report_end(DWFL_POINTER, NULL, NULL); } jlong -lib::dwfl::Dwfl::reportModule(jlong pointer, jstring moduleName, - jlong low, jlong high) { +lib::dwfl::Dwfl::dwfl_report_module(jlong pointer, jstring moduleName, + jlong low, jlong high, jlong userdata) { jsize len = JvGetStringUTFLength(moduleName); char modName[len+1]; JvGetStringUTFRegion(moduleName, 0, len, modName); modName[len] = '\0'; - - return (jlong) ::dwfl_report_module(DWFL_POINTER, modName, - (::Dwarf_Addr) low, - (::Dwarf_Addr) high); + + Dwfl_Module* module = ::dwfl_report_module(DWFL_POINTER, modName, + (::Dwarf_Addr) low, + (::Dwarf_Addr) high); + if (userdata != 0) { + // Get the address of the module's userdata, and store a global + // reference to memory in there. The global ref is detroyed along + // with the Dwfl. + void **userdatap; + ::dwfl_module_info(module, &userdatap, NULL, NULL, NULL, NULL, NULL, NULL); + *userdatap = (void*)userdata; + } + return (jlong) module; } extern "C" int moduleCounter(Dwfl_Module *, void **, const char *, diff --git a/frysk-sys/lib/dwfl/cni/DwflModule.cxx b/frysk-sys/lib/dwfl/cni/DwflModule.cxx index ad85344..97892ff 100644 --- a/frysk-sys/lib/dwfl/cni/DwflModule.cxx +++ b/frysk-sys/lib/dwfl/cni/DwflModule.cxx @@ -45,6 +45,9 @@ #include <gnu/gcj/RawData.h> +#include <java/util/List.h> + + #include "lib/dwfl/DwflModule.h" #include "lib/dwfl/DwarfDie.h" #include "lib/dwfl/DwflLine.h" @@ -65,18 +68,15 @@ #define DWFL_MODULE_POINTER ((Dwfl_Module *) pointer) lib::dwfl::ModuleElfBias* -lib::dwfl::DwflModule::module_getelf() -{ - Dwarf_Addr bias = 0; - ::Elf *elf = dwfl_module_getelf(DWFL_MODULE_POINTER, &bias); - if(elf == NULL) - return NULL; - - lib::dwfl::ModuleElfBias *ret = new lib::dwfl::ModuleElfBias(); - ret->elf = new lib::dwfl::Elf((jlong) elf); - ret->bias = (jlong) bias; - - return ret; +lib::dwfl::DwflModule::module_getelf() { + Dwarf_Addr bias = 0; + ::Elf *elf = dwfl_module_getelf(DWFL_MODULE_POINTER, &bias); + if(elf == NULL) + return NULL; + lib::dwfl::ModuleElfBias *ret = new lib::dwfl::ModuleElfBias(); + ret->elf = new lib::dwfl::Elf((jlong) elf); + ret->bias = (jlong) bias; + return ret; } typedef JArray<lib::dwfl::DwflLine *> DwflLineArray; @@ -337,17 +337,6 @@ lib::dwfl::DwflModule::getSymbolByName(jstring name, } } -void -lib::dwfl::DwflModule::setUserData(jobject data) -{ - void **userdata = NULL; - dwfl_module_info(DWFL_MODULE_POINTER, &userdata, NULL, NULL, NULL, NULL, NULL, - NULL); - - *userdata = data; - -} - /* * Get the DebugInfo paths if present */ @@ -443,35 +432,21 @@ lib::dwfl::DwflModule::offdie(jlong die, jlong offset){ return dwarfDie; } -java::util::LinkedList* -lib::dwfl::DwflModule::get_cu_dies() -{ - - java::util::LinkedList* list = new java::util::LinkedList(); - - Dwarf_Die* cu; - Dwarf_Die lastcu; - Dwarf_Addr bias; - - cu = dwfl_module_nextcu((::Dwfl_Module*)this->pointer, NULL, &bias); - - fflush(stdout); - while ( cu != NULL){ - +void +lib::dwfl::DwflModule::get_cu_dies(jlong pointer, + java::util::List *list) { + Dwarf_Die* cu; + Dwarf_Addr bias; + cu = dwfl_module_nextcu(DWFL_MODULE_POINTER, NULL, &bias); + while (cu != NULL) { Dwarf_Die *die = (Dwarf_Die*)JvMalloc(sizeof(Dwarf_Die)); - - memcpy(die, cu, sizeof(*die)); - lib::dwfl::DwarfDie* cuDie = lib::dwfl::DwarfDieFactory::getFactory()->makeDie((jlong)die, NULL); - cuDie->setManageDie(true); - - list->add(cuDie); - - memcpy(&lastcu, cu, sizeof(*cu)); - cu = dwfl_module_nextcu((::Dwfl_Module*)this->pointer, &lastcu, &bias); - - } - - return list; + memcpy(die, cu, sizeof(*die)); + lib::dwfl::DwarfDie* cuDie + = lib::dwfl::DwarfDieFactory::getFactory()->makeDie((jlong)die, NULL); + cuDie->setManageDie(true); + list->add(cuDie); + cu = dwfl_module_nextcu(DWFL_MODULE_POINTER, cu, &bias); + } } jlong diff --git a/frysk-sys/lib/dwfl/jni/DwarfDie.cxx b/frysk-sys/lib/dwfl/jni/DwarfDie.cxx index 0935d19..0da40c1 100644 --- a/frysk-sys/lib/dwfl/jni/DwarfDie.cxx +++ b/frysk-sys/lib/dwfl/jni/DwarfDie.cxx @@ -148,7 +148,7 @@ lib::dwfl::DwarfDie::get_scopes_die(jnixx::env env) { return longs; } -jlong +jint lib::dwfl::DwarfDie::get_scopevar(jnixx::env env, jnixx::jlongArray jdie_scope, jnixx::jlongArray jscopes, String jvariable) { // FIXME: This appears to be leaked? @@ -169,8 +169,8 @@ lib::dwfl::DwarfDie::get_scopevar(jnixx::env env, jnixx::jlongArray jdie_scope, jlongArrayElements die_scope = jlongArrayElements(env, jdie_scope); die_scope.elements()[0] = (jlong)var_die; // Die for variable die_scope.elements()[1] = code; // Die for scope - } else if (dwarf_tag (var_die) != DW_TAG_variable) { - return -1; + } else { + ::free(var_die); } return code; } diff --git a/frysk-sys/lib/dwfl/jni/Dwfl.cxx b/frysk-sys/lib/dwfl/jni/Dwfl.cxx index c984daa..7be62a5 100644 --- a/frysk-sys/lib/dwfl/jni/Dwfl.cxx +++ b/frysk-sys/lib/dwfl/jni/Dwfl.cxx @@ -70,34 +70,28 @@ extern "C" { // Assume the method was parameterised with POINTER. #define DWFL_POINTER ((::Dwfl *)pointer) -// Ditto for callbacks pointer. -#define DWFL_CALLBACKS ((::Dwfl_Callbacks*)callbacks) + -struct proc_memory_context { - jnixx::env env; - inua::eio::ByteBuffer memory; - proc_memory_context(jnixx::env env, inua::eio::ByteBuffer memory) { - this->env = env; - this->memory = memory; - } -}; +// Our data associated with the dwfl (well actually the Dwfl_Module). +// Need to make memory available so that, in the case of the vdso, it +// can be slurped from memory. static ssize_t -read_proc_memory(void *arg, void *data, GElf_Addr address, +read_proc_memory(void *userdata, void *data, GElf_Addr address, size_t minread, size_t maxread) { - fprintf(stderr, "wft does data %p get set? - perhaps it isn't called\n", - data); - proc_memory_context* context = (proc_memory_context*) arg; - jnixx::jbyteArray bytes - = jnixx::jbyteArray::NewByteArray(context->env, maxread); - ssize_t nread - = context->memory.safeGet(context->env, (off64_t) address, bytes, 0, - maxread); - jbyteArrayElements bytesp = jbyteArrayElements(context->env, bytes); + // Get the current thread's ENV; can't save it in dwfl_userdata + // since can't determine, ahead of time, which thread will call this + // code. + ::jnixx::env env = Object::_env_(); + ::inua::eio::ByteBuffer memory + = ::inua::eio::ByteBuffer(env, (jobject)userdata); + jnixx::jbyteArray bytes = jnixx::jbyteArray::NewByteArray(env, maxread); + ssize_t nread = memory.safeGet(env, (off64_t) address, bytes, 0, maxread); + jbyteArrayElements bytesp = jbyteArrayElements(env, bytes); memcpy(data, bytesp.elements(), nread); if (nread > 0 && (size_t) nread < minread) nread = 0; - bytes.DeleteLocalRef(context->env); + bytes.DeleteLocalRef(env); return nread; } @@ -113,28 +107,40 @@ dwfl_frysk_proc_find_elf(Dwfl_Module *mod, // that path to an absolute path, causing the test below to fail and // consider the file ../foo/bar to be an in memory elf image. if (module_name[0] == '/') { - int fd = ::open64(module_name, O_RDONLY); - if (fd >= 0) { + // Return the file name, and then let elfutils decide what to do. + *file_name = ::strdup(module_name); + return -1; + } else { + // dwfl passes in the address of the Dwfl_Module user pointer + // contained within. That pointer has been previously stuffed + // with our "userdata". + *elfp = elf_from_remote_memory (base, NULL, &read_proc_memory, *userdata); + if (*elfp != NULL) { + // Poke something into FILE_NAME so that the caller notices that + // we've done something to ELF. *file_name = ::strdup(module_name); - if (*file_name == NULL) { - ::close(fd); - return ENOMEM; - } } - return fd; - } else { - /* Special case for in-memory ELF image. */ - fprintf(stderr, "wft does userdata %p get set? - perhaps it isn't called\n", *userdata); - proc_memory_context* context = (proc_memory_context*) *userdata; - *elfp = elf_from_remote_memory (base, NULL, &read_proc_memory, context); return -1; } - //abort (); - return -1; } jlong -lib::dwfl::Dwfl::callbacksBegin(jnixx::env env, String jdebugInfoPath) { +lib::dwfl::Dwfl::dwfl_userdata_begin(jnixx::env env, + inua::eio::ByteBuffer memory) { + return (jlong) env.NewGlobalRef(memory._object); +} + +void +lib::dwfl::Dwfl::dwfl_userdata_end(jnixx::env env, jlong userdata) { + env.DeleteGlobalRef((jobject)userdata); +} + + + +#define DWFL_CALLBACKS ((::Dwfl_Callbacks*)callbacks) + +jlong +lib::dwfl::Dwfl::dwfl_callbacks_begin(jnixx::env env, String jdebugInfoPath) { jstringUTFChars debugInfoPath = jstringUTFChars(env, jdebugInfoPath); char** path = (char**) ::malloc(sizeof (char*)); if (path == NULL) { @@ -150,38 +156,49 @@ lib::dwfl::Dwfl::callbacksBegin(jnixx::env env, String jdebugInfoPath) { } void -lib::dwfl::Dwfl::callbacksEnd(jnixx::env env, jlong callbacks) { +lib::dwfl::Dwfl::dwfl_callbacks_end(jnixx::env env, jlong callbacks) { ::free(*DWFL_CALLBACKS->debuginfo_path); ::free(DWFL_CALLBACKS->debuginfo_path); ::free(DWFL_CALLBACKS); } jlong -lib::dwfl::Dwfl::dwflBegin(jnixx::env env, jlong callbacks) { +lib::dwfl::Dwfl::dwfl_begin(jnixx::env env, jlong callbacks) { return (jlong) ::dwfl_begin(DWFL_CALLBACKS); } void -lib::dwfl::Dwfl::dwflEnd(jnixx::env env, jlong pointer) { +lib::dwfl::Dwfl::dwfl_end(jnixx::env env, jlong pointer) { ::dwfl_end(DWFL_POINTER); } void -lib::dwfl::Dwfl::reportBegin(jnixx::env env, jlong pointer) { +lib::dwfl::Dwfl::dwfl_report_begin(jnixx::env env, jlong pointer) { ::dwfl_report_begin(DWFL_POINTER); } void -lib::dwfl::Dwfl::reportEnd(jnixx::env env, jlong pointer) { +lib::dwfl::Dwfl::dwfl_report_end(jnixx::env env, jlong pointer) { ::dwfl_report_end(DWFL_POINTER, NULL, NULL); } jlong -lib::dwfl::Dwfl::reportModule(jnixx::env env, jlong pointer, - String jmoduleName, jlong low, jlong high) { +lib::dwfl::Dwfl::dwfl_report_module(jnixx::env env, jlong pointer, + String jmoduleName, jlong low, jlong high, + jlong userdata) { jstringUTFChars moduleName = jstringUTFChars(env, jmoduleName); - return (jlong) ::dwfl_report_module(DWFL_POINTER, moduleName.elements(), - (::Dwarf_Addr) low, - (::Dwarf_Addr) high); + Dwfl_Module *module = ::dwfl_report_module(DWFL_POINTER, + moduleName.elements(), + (::Dwarf_Addr) low, + (::Dwarf_Addr) high); + if (userdata != 0) { + // Get the address of the module's userdata, and store a global + // reference to memory in there. The global ref is detroyed along + // with the Dwfl. + void **userdatap; + ::dwfl_module_info(module, &userdatap, NULL, NULL, NULL, NULL, NULL, NULL); + *userdatap = (void*)userdata; + } + return (jlong)module; } diff --git a/frysk-sys/lib/dwfl/jni/DwflModule.cxx b/frysk-sys/lib/dwfl/jni/DwflModule.cxx index 09092ce..d730d49 100644 --- a/frysk-sys/lib/dwfl/jni/DwflModule.cxx +++ b/frysk-sys/lib/dwfl/jni/DwflModule.cxx @@ -301,15 +301,6 @@ lib::dwfl::DwflModule::getSymbolByName(jnixx::env env, String jname, } } -void -lib::dwfl::DwflModule::setUserData(jnixx::env env, Object data) { - void **userdata = NULL; - fprintf(stderr, "user data is %p\n", userdata); - dwfl_module_info(DWFL_MODULE_POINTER_FIXME, &userdata, NULL, NULL, NULL, NULL, NULL, - NULL); - *userdata = data._object; -} - /* * Get the DebugInfo paths if present */ @@ -396,6 +387,24 @@ lib::dwfl::DwflModule::offdie(jnixx::env env, jlong die, jlong offset) { return dwarfDie; } +void +lib::dwfl::DwflModule::get_cu_dies(::jnixx::env env, jlong pointer, + java::util::List list) { + Dwarf_Die* cu; + Dwarf_Addr bias; + cu = dwfl_module_nextcu(DWFL_MODULE_POINTER, NULL, &bias); + + while (cu != NULL) { + Dwarf_Die *die = (Dwarf_Die*)::malloc(sizeof(Dwarf_Die)); + memcpy(die, cu, sizeof(*die)); + lib::dwfl::DwarfDie cuDie + = lib::dwfl::DwarfDieFactory::getFactory(env).makeDie(env, (jlong)die, lib::dwfl::DwflModule(env, NULL)); + cuDie.setManageDie(env, true); + list.add(env, cuDie); + cu = dwfl_module_nextcu(DWFL_MODULE_POINTER, cu, &bias); + } +} + jlong lib::dwfl::DwflModule::dwflModuleAddrdie(jnixx::env env, jlong pointer, jlong addr) { diff --git a/frysk-sys/lib/unwind/ChangeLog b/frysk-sys/lib/unwind/ChangeLog index 39bcd79..5e72c59 100644 --- a/frysk-sys/lib/unwind/ChangeLog +++ b/frysk-sys/lib/unwind/ChangeLog @@ -1,3 +1,9 @@ +2008-06-20 Andrew Cagney <cagney@redhat.com> + + * jni/UnwindH.hxx (access_mem): Catch Throwable and then use + instanceof to identify a UserException. + * cni/UnwindH.hxx (access_mem): Ditto. + 2008-05-26 Andrew Cagney <cagney@redhat.com> * jni/ElfImage.cxx: Delete. diff --git a/frysk-sys/lib/unwind/cni/UnwindH.hxx b/frysk-sys/lib/unwind/cni/UnwindH.hxx index 925b8af..1469bcd 100644 --- a/frysk-sys/lib/unwind/cni/UnwindH.hxx +++ b/frysk-sys/lib/unwind/cni/UnwindH.hxx @@ -62,6 +62,7 @@ #include <java/lang/ArrayIndexOutOfBoundsException.h> #include "inua/eio/ByteBuffer.h" +#include "frysk/UserException.h" #include "frysk/rsl/Log.h" #include "frysk/rsl/cni/Log.hxx" #include "lib/dwfl/Dwfl.h" @@ -149,11 +150,15 @@ access_mem(::unw_addr_space_t as, ::unw_word_t addr, tmp, (jboolean) write); memcpy(valp, elements(tmp), JvGetArrayLength(tmp)); return ret; - } catch (RuntimeException *t) { - // We have to catch all RuntimeExceptions here since there - // is no indicator for just "invalid memory location". - // Core files might have "holes" in their memory. - return -UNW_EINVAL; + } catch (Throwable *t) { + if (frysk::UserException::class$.isInstance(t)) { + // We have to catch all RuntimeExceptions here since there + // is no indicator for just "invalid memory location". + // Core files might have "holes" in their memory. + return -UNW_EINVAL; + } else { + throw t; + } } } diff --git a/frysk-sys/lib/unwind/jni/UnwindH.hxx b/frysk-sys/lib/unwind/jni/UnwindH.hxx index 3f42723..76e57b7 100644 --- a/frysk-sys/lib/unwind/jni/UnwindH.hxx +++ b/frysk-sys/lib/unwind/jni/UnwindH.hxx @@ -147,11 +147,15 @@ access_mem(::unw_addr_space_t as, ::unw_word_t addr, tmp.release(); jtmp.DeleteLocalRef(env); return ret; - } catch (RuntimeException *t) { - // We have to catch all RuntimeExceptions here since there - // is no indicator for just "invalid memory location". - // Core files might have "holes" in their memory. - return -UNW_EINVAL; + } catch (Throwable t) { + if (t.IsInstanceOf(env, frysk::UserException::_class_(env))) { + // We have to catch all RuntimeExceptions here since there is no + // indicator for just "invalid memory location". Core files + // might have "holes" in their memory. + return -UNW_EINVAL; + } else { + throw t; + } } } diff --git a/htdocs/people/index.html b/htdocs/people/index.html index c825940..81fd68f 100644 --- a/htdocs/people/index.html +++ b/htdocs/people/index.html @@ -147,6 +147,14 @@ Professional Experience Year Program. </p> Technlogy Center. Currently contributes with PPC-related code to the Frysk Project. He also has contributions to GDB and binutils as well. </p> +<h3>Teresa Thomas</h3> + +<p>Teresa is a Computer Engineering student at the University of Toronto, +currently working as an intern at Red Hat Canada Ltd. She has worked +on various aspects of Frysk's core, including the expression parser +and evaluator, high level watchpoint implementation, IEEE 754/854 +floating point support and the DWARF location evaluator. </p> + <h3>Sami Wagiaalla</h3> <p>Sami is an intern at Red Hat from the University of Alberta. He is