diff options
83 files changed, 4351 insertions, 1781 deletions
diff --git a/org.eclipse.debug.examples.core/.classpath b/org.eclipse.debug.examples.core/.classpath index 3e3e97273..9f8cf0e63 100644 --- a/org.eclipse.debug.examples.core/.classpath +++ b/org.eclipse.debug.examples.core/.classpath @@ -2,6 +2,7 @@ <classpath> <classpathentry kind="src" path="src"/> <classpathentry kind="src" path="src_ant"/> + <classpathentry kind="src" path="pdavm/src"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4"/> <classpathentry kind="output" path="bin"/> diff --git a/org.eclipse.debug.examples.core/META-INF/MANIFEST.MF b/org.eclipse.debug.examples.core/META-INF/MANIFEST.MF index 03f4944c1..c0a830633 100644 --- a/org.eclipse.debug.examples.core/META-INF/MANIFEST.MF +++ b/org.eclipse.debug.examples.core/META-INF/MANIFEST.MF @@ -15,6 +15,7 @@ Export-Package: org.eclipse.debug.examples.core.midi.launcher, org.eclipse.debug.examples.core.pda.breakpoints, org.eclipse.debug.examples.core.pda.launcher, org.eclipse.debug.examples.core.pda.model, - org.eclipse.debug.examples.core.pda.sourcelookup + org.eclipse.debug.examples.core.pda.sourcelookup, + org.eclipse.debug.examples.core.protocol Bundle-RequiredExecutionEnvironment: J2SE-1.4 Bundle-ActivationPolicy: lazy diff --git a/org.eclipse.debug.examples.core/pdavm/docs/protocol.html b/org.eclipse.debug.examples.core/pdavm/docs/protocol.html deleted file mode 100644 index 9e2b92749..000000000 --- a/org.eclipse.debug.examples.core/pdavm/docs/protocol.html +++ /dev/null @@ -1,198 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html> -<head> - <meta content="text/html; charset=ISO-8859-1" - http-equiv="content-type"> - <title>PDA Debugger Protocol Reference</title> -</head> -<body> - -<h2>PDA Debugger Protocol Reference</h2> - -<h3>clear</h3> -Clears any breakpoint set on given line -<pre> - C: clear {line} - R: ok -</pre> - - -<h3>data</h3> -Retrieves data stack information -<pre> - C: data - R: {value 1}|{value 2}|{value 3}|...| -</pre> - - -<h3>drop</h3> -Returns from the current frame without executing the rest of instructions. - -<pre> - C: drop - R: ok - E: resumed drop - E: suspended drop -</pre> - - -<h3>eval</h3> -Sets what events cause the execution to stop. - -<pre> - C: eval {instruction}%20{parameter}|{instruction}%20{parameter}|... - R: ok - E: resume client - E: evalresult result - E: suspended eval -</pre> - - -<h3>eventstop</h3> -Sets what events cause the execution to stop. - -<pre> - C: eventstop {event_name} {0|1} - R: ok - ... - E: suspended event {event_name} -</pre> - - -<h3>exit</h3> -Instructs the debugger to exit. - -<pre> - C: exit - R: ok -</pre> - - -<h3>popdata</h3> -Pops the top value from the data stack - -<pre> - C: popdata - R: ok -</pre> - - -<h3>pushdata</h3> -Pushes the given value on top of the data stack. - -<pre> - C: pushdata {value} - R: ok -</pre> - - -<h3>resume</h3> -Resumes the execution - -<pre> - C: resume - R: ok - E: resumed client -</pre> - - -<h3>set</h3> -Sets a breakpoint at given line - -<pre> - C: set {line_number} - R: ok - C: resume - E: resumed client - E: suspended breakpoint line_number -</pre> - - -<h3>setdata</h3> -Sets a data value in the data stack at the given location - -<pre> - C: setdata {index} {value} - R: ok -</pre> - - -<h3>setvar</h3> -Sets a variable value - -<pre> - C: setvar {frame_number} {variable} {value} - R: ok -</pre> - - -<h3>stack</h3> -Retrieves command stack information - -<pre> - C: stack - R: {file}|{line}|{function}|{var_1}|{var_2}|...{file}|{line}|{function}|{var_1}|{var_2}|...... -</pre> - - -<h3>step</h3> -Executes next instruction - -<pre> - C: step - R: ok - E: resumed step - E: suspended step -</pre> - - -<h3>stepreturn</h3> -Executes instructions until the current subroutine is finished - -<pre> - C: stepreturn - R: ok - E: resumed step - E: suspended step -</pre> - - -<h3>suspend</h3> -Suspends execution - -<pre> - C: suspend - R: ok - E: suspended client -</pre> - - -<h3>var</h3> -Retrieves variable value - -<pre> - C: var {frame_number} {variable_name} - R: {variable_value} -</pre> - - -<h3>watch</h3> -Sets a watchpoint on a given variable - -<pre> - C: watch {function}::{variable_name} {watch_operation} - R: ok - C: resume - R: resumed client - E: suspended watch {watch_operation} {function}::{variable_name} -</pre> - -The <code>watch_operation<code> value can be: -<ul> - <li>0 - no watch</li> - <li>1 - read watch</li> - <li>2 - write watch</li> - <li>3 - both, etc.</li> -</ul> -</body> -</html> diff --git a/org.eclipse.debug.examples.core/pdavm/pda.pl b/org.eclipse.debug.examples.core/pdavm/pda.pl deleted file mode 100644 index de0866eba..000000000 --- a/org.eclipse.debug.examples.core/pdavm/pda.pl +++ /dev/null @@ -1,678 +0,0 @@ -#!perl.exe - -use strict; -use warnings; -use IO::Socket; - -##################################################################### -# Copyright (c) 2005, 2008 IBM Corporation and others. -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://www.eclipse.org/legal/epl-v10.html -# -# Contributors: -# Bjorn Freeman-Benson - initial API and implementation -# Pawel Piech - WindRiver Systems - Bug 217211: PDA example debugger does not run on linux -##################################################################### - -##################################################################### -# # -# I N I T I A L I Z A T I O N A N D V A R I A B L E S # -# # -##################################################################### -# -# The push down automata stack (the data stack) -# -my @stack; -# -# Load all the code into memory -# The code is stored as an array of strings, each line of -# the source file being one entry in the array. -# -my $filename = shift; -open INFILE, $filename or die $!; -my @code = <INFILE>; -close INFILE; - -my %labels; -sub map_labels { - # - # A mapping of labels to indicies in the code array - # - %labels = ( ); - my $idx = 0; - while( $idx <= $#code ) { - if( length $code[$idx] > 0 ) { - $code[$idx] =~ /^\s*(.+?)\s*$/; - $code[$idx] = $1; - $labels{$1} = $idx if( $code[$idx] =~ /^:(\S+)/ ); - } else { - $code[$idx] = "\n"; - } - $idx ++; - } -} -map_labels(); -# -# The stack of stack frames (the control stack) -# Each stack frame is a mapping of variable names to values. -# There are a number of special variable names: -# _pc_ is the current program counter in the frame -# the pc points to the next instruction to be executed -# _func_ is the name of the function in this frame -# -my @frames; -my $currentframe; -$currentframe = { - _pc_ => 0, - _func_ => 'main' - }; - -# -# The command line argument to start a debug session. -# -my $debugflag = shift; -# -# The port to listen for debug commands on -# and the port to send debug events to -# -my $debugport; -my $debugport2; -# -# The socket to listen for debug commands on -# and the socket to send debug events on -# -my $debugsock; -my $debugsock2; -# -# An input buffer -# -my $debugbuf; -# -# Breakpoint array -# breakpoints are stored as a boolean for each line of code -# if the boolean is true, there is a breakpoint on that line -# -my @breakpoints; -# -# Mapping of debugger commands to functions that evaluate them -# -my %debug_commands = ( - clear => \&debug_clear_breakpoint, - data => \&debug_data, - drop => \&debug_drop_frame, - eval => \&debug_eval, - eventstop => \&debug_event_stop, - exit => \&debug_exit, - popdata => \&debug_pop, - pushdata => \&debug_push, - resume => \&debug_resume, - set => \&debug_set_breakpoint, - setdata => \&debug_set_data, - setvar => \&debug_set_variable, - stack => \&debug_stack, - step => \&debug_step, - stepreturn => \&debug_step_return, - suspend => \&debug_suspend, - var => \&debug_var, - watch => \&debug_watch -); - -# -# The run flag is true if the VM is running. -# If the run flag is false, the VM exits the -# next time the main instruction loop runs. -# -my $run = 1; -# -# The suspend flag is true if the VM should suspend -# running the program and just listen for debug commands. -# -my $suspend = 0; -my $started = 1; -$suspend = "client" if( $debugflag ); -# -# The step flag is used to control single-stepping. -# See the implementation of the "step" debug command. -# The stepreturn flag is used to control step-return. -# The eventstops table holds which events cause suspends and which do not. -# The watchpoints table holds watchpoint information. -# variablename_stackframedepth => N -# N = 0 is no watch -# N = 1 is read watch -# N = 2 is write watch -# N = 3 is both, etc. -# -my $step = 0; -my $stepreturn = 0; -my %eventstops = ( "unimpinstr" => 0, - "nosuchlabel" => 0, - ); -my %watchpoints = ( ); - -# -# Mapping of the names of the instructions to the functions that evaluate them -# -my %instructions = ( - add => \&add, - branch_not_zero => \&branch_not_zero, - call => \&call, - dec => \&dec, - dup => \&dup, - halt => \&halt, - output => \&output, - pop => \&ipop, - push => \&ipush, - return => \&ireturn, - var => \&var, - xyzzy => \&internal_end_eval, -); - -##################################################################### -# # -# M A I N I N T E R P R E T E R # -# # -##################################################################### -# -# Open a debug session if the command line argument is given. -# -start_debugger(); -send_debug_event( "started", 0 ); -debug_ui() if( $suspend ); -# -# The main run loop -# -while( $run ) { - check_for_breakpoint(); - debug_ui() if( $suspend ); - yield_to_debug(); - my $instruction = fetch_instruction(); - increment_pc(); - do_one_instruction($instruction); - if( $$currentframe{_pc_} > $#code ) { - $run = 0; - } elsif( $stepreturn ) { - $instruction = fetch_instruction(); - $suspend = "step" if( is_return_instruction($instruction) ); - } -} -send_debug_event( "terminated", 0 ); - -sub fetch_instruction { - my $pc = $$currentframe{_pc_}; - my $theinstruction = $code[$pc]; - return $theinstruction; -} -sub is_return_instruction { - my $theinstruction = shift; - if( $theinstruction =~ /^:/ ) { - return 0; - } elsif( $theinstruction =~ /^#/ ) { - return 0; - } else { - $theinstruction =~ /^(\S+)\s*(.*)/; - return $1 eq "return"; - } -} -sub increment_pc { - my $pc = $$currentframe{_pc_}; - $pc++; - $$currentframe{_pc_} = $pc; -} -sub decrement_pc { - my $pc = $$currentframe{_pc_}; - $pc--; - $$currentframe{_pc_} = $pc; -} -sub do_one_instruction { - my $theinstruction = shift; - if( $theinstruction =~ /^:/ ) { - # label - $suspend = "step" if( $step ); - } elsif( $theinstruction =~ /^#/ ) { - # comment - } else { - $theinstruction =~ /^(\S+)\s*(.*)/; - my $op = $1; - my $instr = $instructions{$op}; - if( $instr ) { - &$instr( $theinstruction, $2 ); - $suspend = "step" if( $step ); - } else { - send_debug_event( "unimplemented instruction $op", 1 ); - if( $eventstops{"unimpinstr"} ) { - $suspend = "event unimpinstr"; - decrement_pc(); - } - } - } -} - -##################################################################### -# # -# I N S T R U C T I O N S # -# # -##################################################################### -sub add { - my $val1 = pop @stack; - my $val2 = pop @stack; - my $val = $val1 + $val2; - push @stack, $val; -} - -sub branch_not_zero { - my $val = pop @stack; - if( $val ) { - shift; - my $label = shift; - my $dest = $labels{$label}; - if( !defined $dest ) { - send_debug_event( "no such label $label", 1 ); - if( $eventstops{"nosuchlabel"} ) { - $suspend = "event nosuchlabel"; - push @stack, $val; - decrement_pc(); - } - } else { - $$currentframe{_pc_} = $dest; - } - } -} - -sub call { - shift; - my $label = shift; - my $dest = $labels{$label}; - if( !defined $dest ) { - send_debug_event( "no such label $label", 1 ); - if( $eventstops{"nosuchlabel"} ) { - $suspend = "event nosuchlabel"; - decrement_pc(); - } - } else { - push @frames, $currentframe; - $currentframe = { - _pc_ => $dest, - _func_ => $label - }; - } -} - -sub dec { - my $val = pop @stack; - $val--; - push @stack, $val; -} - -sub dup { - my $val = pop @stack; - push @stack, $val; - push @stack, $val; -} - -sub halt { - $run = 0; -} - -sub output { - my $val = pop @stack; - print "$val\n"; -} - -sub ipop { - shift; - my $arg = shift; - if( $arg =~ /^\$(.*)/ ) { - $$currentframe{$1} = pop @stack; - my $key = "$$currentframe{_func_}\:\:$1"; - if( defined $watchpoints{$key} ) { - if( $watchpoints{$key} & 2 ) { - $suspend = "watch write $key"; - } - } - } else { - pop @stack; - } -} - -sub ipush { - shift; - my $arg = shift; - if( $arg =~ /^\$(.*)/ ) { - my $val = $$currentframe{$1}; - push @stack, $val; - my $key = "$$currentframe{_func_}\:\:$1"; - if( defined $watchpoints{$key} ) { - if( $watchpoints{$key} & 1 ) { - $suspend = "watch read $key"; - } - } - } else { - push @stack, $arg; - } -} - -sub ireturn { - $currentframe = pop @frames; -} - -sub var { - shift; - my $name = shift; - $$currentframe{$name} = 0; -} - -##################################################################### -# # -# D E B U G G E R I N T E R F A C E # -# # -##################################################################### - -sub check_for_breakpoint { - if( $debugflag ) { - my $pc = $$currentframe{_pc_}; - if( $breakpoints[$pc] ) { - $suspend = "breakpoint $pc" unless $suspend eq "eval"; - } - } -} -# -# For each instruction, we check the debug co-routine for -# control input. If there is input, we process it. -# -sub yield_to_debug { - if( $debugflag ) { - my $bytes_to_read = 1024; - my $bytes_read = sysread($debugsock, $debugbuf, $bytes_to_read); - if( defined($bytes_read) ) { - #print "read $bytes_to_read\n"; - my $rin = ''; - my $win = ''; - my $ein = ''; - vec($rin,fileno($debugsock),1) = 1; - $ein = $rin | $win; - my $debugline = $debugbuf; - while( !($debugline =~ /\n/) ) { - select($rin, undef, undef, undef); - my $bytes_to_read = 1024; - my $bytes_read = sysread($debugsock, $debugbuf, $bytes_to_read); - $debugline .= $debugbuf; - } - #print "read: $debugline"; - process_debug_command($debugline); - $debugline = ''; - } else { - # no bytes read - } - } -} - -# -# If the execution is suspended, then we go into the debug -# ui loop, reading and processing instructions. -# -sub debug_ui { - return unless( $suspend ); - my $pc = $$currentframe{_pc_}; - if (!$started) { - send_debug_event( "suspended $suspend", 0 ); - } else { - $started = 0; - } - $step = 0; - $stepreturn = 0; - my $rin = ''; - my $win = ''; - my $ein = ''; - vec($rin,fileno($debugsock),1) = 1; - $ein = $rin | $win; - my $debugline = ''; - while( $suspend ) { - select($rin, undef, undef, undef); - my $bytes_to_read = 1024; - my $bytes_read = sysread($debugsock, $debugbuf, $bytes_to_read); - $debugline .= $debugbuf; - if( $debugline =~ /\n/ ) { - #print "read: $debugline"; - process_debug_command($debugline); - $debugline = ''; - } - } - send_debug_event( "resumed step", 0 ) if( $step ); - send_debug_event( "resumed client", 0 ) unless( $step ); -} - -sub process_debug_command { - my $line = shift; - return if( length $line < 2 ); - my @words = split /\s/, $line; - my $command = lc($words[0]); - my $dfunc = $debug_commands{$words[0]}; - if( $dfunc ) { - &$dfunc( @words ); - } -} - -sub debug_clear_breakpoint { - shift; - my $line = shift; - $breakpoints[$line] = 0; - print $debugsock "ok\n"; -} -my @saved_code; -my %saved_labels; -my $saved_pc; -sub debug_eval { - shift; - my $code = shift; - my @lines = split /\|/, $code; - my $newpc = scalar @code; - @saved_code = @code; - %saved_labels = %labels; - foreach my $line ( @lines ) { - $line =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; - push @code, $line; - } - push @code, "xyzzy"; - map_labels(); - $saved_pc = $$currentframe{_pc_}; - $$currentframe{_pc_} = $newpc; - print $debugsock "ok\n"; - $suspend = 0; -} -sub internal_end_eval { - my $result = pop @stack; - @code = @saved_code; - %labels = %saved_labels; - $$currentframe{_pc_} = $saved_pc; - send_debug_event( "evalresult $result", 0 ); - $suspend = "eval"; -} - -sub debug_data { - my $result = ''; - foreach my $d ( @stack ) { - $result .= $d . '|'; - } - print $debugsock "$result\n"; -} -sub debug_drop_frame { - ireturn(); - decrement_pc(); - print $debugsock "ok\n"; - send_debug_event( "resumed drop", 0 ); - send_debug_event( "suspended drop", 0 ); -} -sub debug_event_stop { - shift; - my $event = shift; - my $bool = shift; - $eventstops{$event} = $bool; - print $debugsock "ok\n"; -} -sub debug_exit { - print $debugsock "ok\n"; - send_debug_event( "terminated", 0 ); - exit 0; -} -sub debug_pop { - pop @stack; - print $debugsock "ok\n"; -} -sub debug_push { - shift; - my $value = shift; - push @stack, $value; - print $debugsock "ok\n"; -} -sub debug_resume { - $suspend = 0; - print $debugsock "ok\n"; -} -sub debug_set_breakpoint { - shift; - my $line = shift; - $breakpoints[$line] = 1; - print $debugsock "ok\n"; -} -sub debug_set_data { - shift; - my $offset = shift; - my $value = shift; - $stack[$offset] = $value; - print $debugsock "ok\n"; -} -sub debug_set_variable { - shift; - my $sfnumber = shift; - my $var = shift; - my $value = shift; - if( $sfnumber > $#frames ) { - $$currentframe{$var} = $value; - } else { - my $theframe = $frames[$sfnumber]; - $$theframe{$var} = $value; - } - print $debugsock "ok\n"; -} -sub debug_stack { - my $result = ''; - foreach my $frame ( @frames ) { - $result .= print_frame($frame); - $result .= '#'; - } - $result .= print_frame($currentframe); - print $debugsock "$result\n"; -} -sub debug_step { - # set suspend to 0 to allow the debug loop to exit back to - # the instruction loop and thus run an instruction. However, - # we want to come back to the debug loop right away, so the - # step flag is set to true which will cause the suspend flag - # to get set to true when we get to the next instruction. - $step = 1; - $suspend = 0; - print $debugsock "ok\n"; -} -sub debug_step_return { - $stepreturn = 1; - $suspend = 0; - print $debugsock "ok\n"; -} -sub debug_suspend { - $suspend = "client"; - print $debugsock "ok\n"; -} -sub debug_var { - shift; - my $sfnumber = shift; - my $var = shift; - if( $sfnumber > $#frames ) { - print $debugsock "$$currentframe{$var}\n"; - } else { - my $theframe = $frames[$sfnumber]; - print $debugsock "$$theframe{$var}\n"; - } -} -sub debug_watch { - shift; - my $key = shift; - my $value = shift; - $watchpoints{$key} = $value; - print $debugsock "ok\n"; -} -# -# Some event has happened so notify the debugger. -# If there is no debugger, we may still want to report the -# event (such as if it is an error). -# -sub send_debug_event { - my $event = shift; - if( $debugflag ) { - print $debugsock2 "$event\n"; - } else { - my $use_stderr = shift; - print "Error: $event\n" if $use_stderr; - } -} -# -# The stack frame output is: -# frame # frame # frame ... -# where each frame is: -# filename | line number | function name | var | var | var | var ... -# -sub print_frame { - my $frame = shift; - my $result = $filename; - $result .= '|' . $$frame{_pc_}; - $result .= '|' . $$frame{_func_}; - for my $var ( keys %$frame ) { - $result .= '|' . $var unless( substr($var,0,1) eq '_'); - } - return $result; -} - -sub start_debugger { - if( defined($debugflag) ) { - if( $debugflag eq "-debug" ) { - { # make STDOUT unbuffered - my $ofh = select STDOUT; - $| = 1; - select $ofh; - } - $debugflag = 1; - $debugport = shift @ARGV; - $debugport2 = shift @ARGV; - print "-debug $debugport $debugport2\n"; - - my $mainsock = new IO::Socket::INET (LocalHost => '127.0.0.1', - LocalPort => $debugport, - Listen => 1, - Proto => 'tcp', - Reuse => 1, - ); - $debugsock = $mainsock->accept(); - - # make the socket non-blocking on windows - my $set_it = "1"; - my $ioctl_val = 0x80000000 | (4 << 16) | (ord('f') << 8) | 126; - ioctl($debugsock, $ioctl_val, $set_it); - - # make the socket non-blocking on linux - $debugsock->blocking(0); - - my $mainsock2 = new IO::Socket::INET (LocalHost => '127.0.0.1', - LocalPort => $debugport2, - Listen => 1, - Proto => 'tcp', - Reuse => 1, - ); - $debugsock2 = $mainsock2->accept(); - - print "debug connection accepted\n"; - } else { - $debugflag = 0; - } - } -} diff --git a/org.eclipse.debug.examples.core/pdavm/src/org/eclipse/debug/examples/pdavm/PDAVirtualMachine.java b/org.eclipse.debug.examples.core/pdavm/src/org/eclipse/debug/examples/pdavm/PDAVirtualMachine.java new file mode 100644 index 000000000..98a56ddc3 --- /dev/null +++ b/org.eclipse.debug.examples.core/pdavm/src/org/eclipse/debug/examples/pdavm/PDAVirtualMachine.java @@ -0,0 +1,1408 @@ +/******************************************************************************* + * Copyright (c) 2005, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) + *******************************************************************************/ +package org.eclipse.debug.examples.pdavm; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.StringWriter; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Push Down Automata interpreter. + * + * @since 3.5 + */ +public class PDAVirtualMachine { + + static class Stack extends LinkedList { + private static final long serialVersionUID = 1L; + + public Object pop() { + return isEmpty() ? new Integer(0) : remove(size() - 1); + } + + public void push(Object value) { + add(value); + } + } + + static class Register { + Register(String name) { + fName = name; + } + String fName; + String fGroup = "<no_group>"; + boolean fIsWriteable = true; + Map fBitFields = new LinkedHashMap(0); + int fValue; + } + + static class BitField { + BitField(String name) { + fName = name; + } + String fName; + int fBitOffset; + int fBitCount; + Map fMnemonics = new LinkedHashMap(0); + } + + Map fRegisters = new LinkedHashMap(0); + + class Args { + final String[] fArgs; + + int next = 0; + + Args(String[] args) { + fArgs = args; + } + + boolean hasNextArg() { + return fArgs.length > next; + } + + String getNextStringArg() { + if (fArgs.length > next) { + return fArgs[next++]; + } + return ""; + } + + int getNextIntArg() { + String arg = getNextStringArg(); + try { + return Integer.parseInt(arg); + } catch (NumberFormatException e) { + } + return 0; + } + + boolean getNextBooleanArg() { + String arg = getNextStringArg(); + try { + return Boolean.getBoolean(arg); + } catch (NumberFormatException e) { + } + return false; + } + + Object getNextIntOrStringArg() { + String arg = getNextStringArg(); + try { + return new Integer(arg); + } catch (NumberFormatException e) { + } + return arg; + } + + PDAThread getThreadArg() { + int id = getNextIntArg(); + return (PDAThread)fThreads.get( new Integer(id) ); + } + } + + class PDAThread { + final int fID; + + /** The push down automata data stack (the data stack). */ + final Stack fStack = new Stack(); + + /** + * PDAThread copy of the code. It can differ from the program if + * performing an evaluation. + */ + String[] fThreadCode; + + /** PDAThread copy of the labels. */ + Map fThreadLabels; + + /** The stack of stack frames (the control stack) */ + final List fFrames = new LinkedList(); + + /** Current stack frame (not includced in fFrames) */ + Frame fCurrentFrame; + + /** + * The run flag is true if the thread is running. If the run flag is + * false, the thread exits the next time the main instruction loop runs. + */ + boolean fRun = true; + + String fSuspend = null; + + boolean fStep = false; + + boolean fStepReturn = false; + + int fSavedPC; + + boolean fPerformingEval = false; + + PDAThread(int id, String function, int pc) { + fID = id; + fCurrentFrame = new Frame(function, pc); + fThreadCode = fCode; + fThreadLabels = fLabels; + } + } + + final Map fThreads = new LinkedHashMap(); + + int fNextThreadId = 1; + + boolean fStarted = true; + /** + * The code is stored as an array of strings, each line of the source file + * being one entry in the array. + */ + final String[] fCode; + + /** A mapping of labels to indicies in the code array */ + final Map fLabels; + + /** Each stack frame is a mapping of variable names to values. */ + class Frame { + final Map fLocalVariables = new LinkedHashMap(); + + /** + * The name of the function in this frame + */ + final String fFunction; + + /** + * The current program counter in the frame the pc points to the next + * instruction to be executed + */ + int fPC; + + Frame(String function, int pc) { + fFunction = function; + fPC = pc; + } + + void set(String name, Object value) { + if (name.startsWith("$")) { + setRegisterValue(name, value); + } else { + fLocalVariables.put(name, value); + } + } + + Object get(String name) { + if (name.startsWith("$")) { + return getRegisterValue(name); + } else { + return fLocalVariables.get(name); + } + } + } + + void setRegisterValue(String name, Object value) { + Register reg = (Register)fRegisters.get(getRegisterPartOfName(name)); + if (reg == null) return; + String bitFieldName = getBitFieldPartOfName(name); + if (bitFieldName != null) { + BitField bitField = (BitField)reg.fBitFields.get(bitFieldName); + if (bitField == null) return; + Integer intValue = null; + if (value instanceof Integer) { + intValue = (Integer)value; + } else if (value instanceof String) { + intValue = (Integer)bitField.fMnemonics.get(value); + } + if (intValue != null) { + int bitFieldMask = 2^(bitField.fBitCount - 1); + int registerMask = ~(bitFieldMask << bitField.fBitOffset); + int bitFieldValue = intValue.intValue() & bitFieldMask; + reg.fValue = (reg.fValue & registerMask) | (bitFieldValue << bitField.fBitOffset); + } + } else if (value instanceof Integer) { + reg.fValue = ((Integer)value).intValue(); + } + } + + Object getRegisterValue(String name) { + Register reg = (Register)fRegisters.get(getRegisterPartOfName(name)); + if (reg == null) return null; + String bitFieldName = getBitFieldPartOfName(name); + if (bitFieldName != null) { + BitField bitField = (BitField)reg.fBitFields.get(bitFieldName); + if (bitField == null) return null; + int bitFieldMask = 2^(bitField.fBitCount - 1); + int registerMask = bitFieldMask << bitField.fBitOffset; + return new Integer( (reg.fValue & registerMask) >> bitField.fBitOffset ); + } else { + return new Integer(reg.fValue); + } + } + + /** + * Breakpoints are stored per each each line of code. The boolean indicates + * whether the whole VM should suspend or just the triggering thread. + */ + final Map fBreakpoints = new HashMap(); + + /** + * The suspend flag is true if the VM should suspend running the program and + * just listen for debug commands. + */ + String fSuspendVM; + + /** Flag indicating whether the debugger is performing a step. */ + boolean fStepVM = false; + + /** Flag indicating whether the debugger is performing a step return */ + boolean fStepReturnVM = false; + + int fSteppingThread = 0; + + /** Name of the pda program being debugged */ + final String fFilename; + + /** The command line argument to start a debug session. */ + final boolean fDebug; + + /** The port to listen for debug commands on */ + final int fCommandPort; + + /** + * Command socket for receiving debug commands and sending command responses + */ + Socket fCommandSocket; + + /** Command socket reader */ + BufferedReader fCommandReceiveStream; + + /** Command socket write stream. */ + OutputStream fCommandResponseStream; + + /** The port to send debug events to */ + final int fEventPort; + + /** Event socket */ + Socket fEventSocket; + + /** Event socket and write stream. */ + OutputStream fEventStream; + + /** The eventstops table holds which events cause suspends and which do not. */ + final Map fEventStops = new HashMap(); + { + fEventStops.put("unimpinstr", Boolean.FALSE); + fEventStops.put("nosuchlabel", Boolean.FALSE); + } + + /** + * The watchpoints table holds watchpoint information. + * <p/> + * variablename_stackframedepth => N + * <ul> + * <li>N = 0 is no watch</li> + * <li>N = 1 is read watch</li> + * <li>N = 2 is write watch</li> + * <li>N = 3 is both, etc.</li> + */ + final Map fWatchpoints = new HashMap(); + + public static void main(String[] args) { + String programFile = args.length >= 1 ? args[0] : null; + if (programFile == null) { + System.err.println("Error: No program specified"); + return; + } + + String debugFlag = args.length >= 2 ? args[1] : ""; + boolean debug = "-debug".equals(debugFlag); + int commandPort = 0; + int eventPort = 0; + + if (debug) { + String commandPortStr = args.length >= 3 ? args[2] : ""; + try { + commandPort = Integer.parseInt(commandPortStr); + } catch (NumberFormatException e) { + System.err.println("Error: Invalid command port"); + return; + } + + String eventPortStr = args.length >= 4 ? args[3] : ""; + try { + eventPort = Integer.parseInt(eventPortStr); + } catch (NumberFormatException e) { + System.err.println("Error: Invalid event port"); + return; + } + } + + PDAVirtualMachine pdaVM = null; + try { + pdaVM = new PDAVirtualMachine(programFile, debug, commandPort, eventPort); + pdaVM.startDebugger(); + } catch (IOException e) { + System.err.println("Error: " + e.toString()); + return; + } + pdaVM.run(); + } + + PDAVirtualMachine(String inputFile, boolean debug, int commandPort, int eventPort) throws IOException { + fFilename = inputFile; + + // Load all the code into memory + FileReader fileReader = new FileReader(inputFile); + StringWriter stringWriter = new StringWriter(); + List code = new LinkedList(); + int c = fileReader.read(); + while (c != -1) { + if (c == '\n') { + code.add(stringWriter.toString().trim()); + stringWriter = new StringWriter(); + } else { + stringWriter.write(c); + } + c = fileReader.read(); + } + code.add(stringWriter.toString().trim()); + fCode = (String[])code.toArray(new String[code.size()]); + + fLabels = mapLabels(fCode); + + fDebug = debug; + fCommandPort = commandPort; + fEventPort = eventPort; + } + + /** + * Initializes the labels map + */ + Map mapLabels(String[] code) { + Map labels = new HashMap(); + for (int i = 0; i < code.length; i++) { + if (code[i].length() != 0 && code[i].charAt(0) == ':') { + labels.put(code[i].substring(1), new Integer(i)); + } + } + return labels; + } + + void sendCommandResponse(String response) { + try { + fCommandResponseStream.write(response.getBytes()); + fCommandResponseStream.flush(); + } catch (IOException e) { + } + } + + void sendDebugEvent(String event, boolean error) { + if (fDebug) { + try { + fEventStream.write(event.getBytes()); + fEventStream.write('\n'); + fEventStream.flush(); + } catch (IOException e) { + System.err.println("Error: " + e); + System.exit(1); + } + } else if (error) { + System.err.println("Error: " + event); + } + } + + void startDebugger() throws IOException { + if (fDebug) { + System.out.println("-debug " + fCommandPort + " " + fEventPort); + } + + ServerSocket commandServerSocket = new ServerSocket(fCommandPort); + fCommandSocket = commandServerSocket.accept(); + fCommandReceiveStream = new BufferedReader(new InputStreamReader(fCommandSocket.getInputStream())); + fCommandResponseStream = new PrintStream(fCommandSocket.getOutputStream()); + commandServerSocket.close(); + + ServerSocket eventServerSocket = new ServerSocket(fEventPort); + fEventSocket = eventServerSocket.accept(); + fEventStream = new PrintStream(fEventSocket.getOutputStream()); + eventServerSocket.close(); + + System.out.println("debug connection accepted"); + + fSuspendVM = "client"; + } + + void run() { + int id = fNextThreadId++; + sendDebugEvent("vmstarted", false); + fThreads.put(new Integer(id), new PDAThread(id, "main", 0)); + if (fDebug) { + sendDebugEvent("started " + id, false); + } + + boolean allThreadsSuspended = false; + while (!fThreads.isEmpty()) { + checkForBreakpoint(); + + if (fSuspendVM != null) { + debugUI(); + } else { + yieldToDebug(allThreadsSuspended); + if (fSuspendVM != null) { + // Received a command to suspend VM, skip executing threads. + continue; + } + } + + PDAThread[] threadsCopy = (PDAThread[])fThreads.values().toArray(new PDAThread[fThreads.size()]); + allThreadsSuspended = true; + for (int i = 0; i < threadsCopy.length; i++) { + PDAThread thread = threadsCopy[i]; + if (thread.fSuspend == null) { + allThreadsSuspended = false; + + String instruction = thread.fThreadCode[thread.fCurrentFrame.fPC]; + thread.fCurrentFrame.fPC++; + doOneInstruction(thread, instruction); + if (thread.fCurrentFrame.fPC >= thread.fThreadCode.length) { + // Thread reached end of code, exit from the thread. + thread.fRun = false; + } else if (thread.fStepReturn) { + // If this thread is in a step-return operation, check + // if we've returned from a call. + instruction = thread.fThreadCode[thread.fCurrentFrame.fPC]; + if ("return".equals(instruction)) { + // Note: this will only be triggered if the current + // thread also has the fStepReturn flag set. + if (fStepReturnVM) { + fSuspendVM = thread.fID + " step"; + } else { + thread.fSuspend = "step"; + } + } + } + if (!thread.fRun) { + sendDebugEvent("exited " + thread.fID, false); + fThreads.remove(new Integer(thread.fID)); + } else if (thread.fSuspend != null) { + sendDebugEvent("suspended " + thread.fID + " " + thread.fSuspend, false); + thread.fStep = thread.fStepReturn = thread.fPerformingEval = false; + } + } + } + + // Force thread context switch to avoid starving out other + // processes in the system. + Thread.yield(); + } + + sendDebugEvent("vmterminated", false); + if (fDebug) { + try { + fCommandReceiveStream.close(); + fCommandResponseStream.close(); + fCommandSocket.close(); + fEventStream.close(); + fEventSocket.close(); + } catch (IOException e) { + System.out.println("Error: " + e); + } + } + + } + + void doOneInstruction(PDAThread thread, String instr) { + StringTokenizer tokenizer = new StringTokenizer(instr); + String op = tokenizer.nextToken(); + List tokens = new LinkedList(); + while (tokenizer.hasMoreTokens()) { + tokens.add(tokenizer.nextToken()); + } + Args args = new Args( (String[])tokens.toArray(new String[tokens.size()]) ); + + boolean opValid = true; + if (op.equals("add")) iAdd(thread, args); + else if (op.equals("branch_not_zero")) iBranchNotZero(thread, args); + else if (op.equals("call")) iCall(thread, args); + else if (op.equals("dec")) iDec(thread, args); + else if (op.equals("def")) iDef(thread, args); + else if (op.equals("dup")) iDup(thread, args); + else if (op.equals("exec")) iExec(thread, args); + else if (op.equals("halt")) iHalt(thread, args); + else if (op.equals("output")) iOutput(thread, args); + else if (op.equals("pop")) iPop(thread, args); + else if (op.equals("push")) iPush(thread, args); + else if (op.equals("return")) iReturn(thread, args); + else if (op.equals("var")) iVar(thread, args); + else if (op.equals("xyzzy")) iInternalEndEval(thread, args); + else if (op.startsWith(":")) {} // label + else if (op.startsWith("#")) {} // comment + else { + opValid = false; + } + + if (!opValid) { + sendDebugEvent("unimplemented instruction " + op, true); + if ( ((Boolean)fEventStops.get("unimpinstr")).booleanValue() ) { + fSuspendVM = thread.fID + " event unimpinstr"; + thread.fCurrentFrame.fPC--; + } + } else if (thread.fStep) { + if (fStepVM) { + fSuspendVM = thread.fID + " step"; + fStepVM = false; + } else { + thread.fSuspend = "step"; + } + thread.fStep = false; + } + } + + void checkForBreakpoint() { + if (fDebug) { + for (Iterator itr = fThreads.values().iterator(); itr.hasNext();) { + PDAThread thread = (PDAThread)itr.next(); + Integer pc = new Integer(thread.fCurrentFrame.fPC); + // Suspend for breakpoint if: + // - the VM is not yet set to suspend, for e.g. as a result of step end, + // - the thread is not yet suspended and is not performing an evaluation + // - the breakpoints table contains a breakpoint for the given line. + if (fSuspendVM == null && + thread.fSuspend == null && !thread.fPerformingEval && + fBreakpoints.containsKey(pc)) + { + if ( ((Boolean)fBreakpoints.get(pc)).booleanValue() ) { + fSuspendVM = thread.fID + " breakpoint " + pc; + } else { + thread.fSuspend = "breakpoint " + pc; + thread.fStep = thread.fStepReturn = false; + sendDebugEvent("suspended " + thread.fID + " " + thread.fSuspend, false); + } + } + } + } + } + + /** + * After each instruction, we check the debug command channel for control input. If + * there are commands, process them. + */ + void yieldToDebug(boolean allThreadsSuspended) { + if (fDebug) { + String line = ""; + try { + if (allThreadsSuspended || fCommandReceiveStream.ready()) { + line = fCommandReceiveStream.readLine(); + processDebugCommand(line); + } + } catch (IOException e) { + System.err.println("Error: " + e); + System.exit(1); + } + } + } + + /** + * Service the debugger commands while the VM is suspended + */ + void debugUI() { + if (!fStarted) { + sendDebugEvent("vmsuspended " + fSuspendVM, false); + } else { + fStarted = false; + } + + // Clear all stepping flags. In case the VM suspended while + // a step operation was being performed for the VM or some thread. + fStepVM = fStepReturnVM = false; + for (Iterator itr = fThreads.values().iterator(); itr.hasNext();) { + PDAThread thread = (PDAThread)itr.next(); + thread.fSuspend = null; + thread.fStep = thread.fStepReturn = thread.fPerformingEval = false; + } + + while (fSuspendVM != null) { + String line = ""; + try { + line = fCommandReceiveStream.readLine(); + } catch (IOException e) { + System.err.println("Error: " + e); + System.exit(1); + return; + } + processDebugCommand(line); + } + + if (fStepVM || fStepReturnVM) { + sendDebugEvent("vmresumed step", false); + } else { + sendDebugEvent("vmresumed client", false); + } + } + + void processDebugCommand(String line) { + StringTokenizer tokenizer = new StringTokenizer(line.trim()); + if (line.length() == 0) { + return; + } + + String command = tokenizer.nextToken(); + List tokens = new LinkedList(); + while (tokenizer.hasMoreTokens()) { + tokens.add(tokenizer.nextToken()); + } + Args args = new Args( (String[])tokens.toArray(new String[tokens.size()])); + + if ("children".equals(command)) debugChildren(args); + else if ("clear".equals(command)) debugClearBreakpoint(args); + else if ("data".equals(command)) debugData(args); + else if ("drop".equals(command)) debugDropFrame(args); + else if ("eval".equals(command)) debugEval(args); + else if ("eventstop".equals(command)) debugEventStop(args); + else if ("frame".equals(command)) debugFrame(args); + else if ("groups".equals(command)) debugGroups(args); + else if ("popdata".equals(command)) debugPopData(args); + else if ("pushdata".equals(command)) debugPushData(args); + else if ("registers".equals(command)) debugRegisters(args); + else if ("resume".equals(command)) debugResume(args); + else if ("set".equals(command)) debugSetBreakpoint(args); + else if ("setdata".equals(command)) debugSetData(args); + else if ("setvar".equals(command)) debugSetVariable(args); + else if ("stack".equals(command)) debugStack(args); + else if ("stackdepth".equals(command)) debugStackDepth(args); + else if ("state".equals(command)) debugState(args); + else if ("step".equals(command)) debugStep(args); + else if ("stepreturn".equals(command)) debugStepReturn(args); + else if ("suspend".equals(command)) debugSuspend(args); + else if ("terminate".equals(command)) debugTerminate(); + else if ("threads".equals(command)) debugThreads(); + else if ("var".equals(command)) debugVar(args); + else if ("vmresume".equals(command)) debugVMResume(); + else if ("vmsuspend".equals(command)) debugVMSuspend(); + else if ("watch".equals(command)) debugWatch(args); + else { + sendCommandResponse("error: invalid command\n"); + } + } + + void debugChildren(Args args) { + PDAThread thread = args.getThreadArg(); + if (thread == null) { + sendCommandResponse("error: invalid thread\n"); + return; + } + + int sfnumber = args.getNextIntArg(); + String var = args.getNextStringArg(); + + Frame frame = sfnumber >= thread.fFrames.size() + ? thread.fCurrentFrame : (Frame)thread.fFrames.get(sfnumber); + + String varDot = var + "."; + List children = new ArrayList(); + for (Iterator itr = frame.fLocalVariables.keySet().iterator(); itr.hasNext();) { + String localVar = (String)itr.next(); + if (localVar.startsWith(varDot) && localVar.indexOf('.', varDot.length() + 1) == -1) { + children.add(localVar); + } + } + + StringBuffer result = new StringBuffer(); + for (Iterator itr = children.iterator(); itr.hasNext();) { + result.append(itr.next()); + result.append('|'); + } + result.append('\n'); + + sendCommandResponse(result.toString()); + } + + void debugClearBreakpoint(Args args) { + int line = args.getNextIntArg(); + + fBreakpoints.remove( new Integer(line) ); + sendCommandResponse("ok\n"); + } + + private static Pattern fPackPattern = Pattern.compile("%([a-fA-F0-9][a-fA-F0-9])"); + + void debugData(Args args) { + PDAThread thread = args.getThreadArg(); + if (thread == null) { + sendCommandResponse("error: invalid thread\n"); + return; + } + + StringBuffer result = new StringBuffer(); + for (Iterator itr = thread.fStack.iterator(); itr.hasNext();) { + result.append(itr.next()); + result.append('|'); + } + result.append('\n'); + sendCommandResponse(result.toString()); + } + + void debugDropFrame(Args args) { + PDAThread thread = args.getThreadArg(); + if (thread == null) { + sendCommandResponse("error: invalid thread\n"); + return; + } + + if (!thread.fFrames.isEmpty()) { + thread.fCurrentFrame = (Frame)thread.fFrames.remove(thread.fFrames.size() - 1); + } + thread.fCurrentFrame.fPC--; + sendCommandResponse("ok\n"); + if (fSuspendVM != null) { + sendDebugEvent("vmresumed drop", false); + sendDebugEvent("vmsuspended " + thread.fID + " drop", false); + } else { + sendDebugEvent("resumed " + thread.fID + " drop", false); + sendDebugEvent("suspended " + thread.fID + " drop", false); + } + } + + void debugEval(Args args) { + if (fSuspendVM != null) { + sendCommandResponse("error: cannot evaluate while vm is suspended\n"); + return; + } + + PDAThread thread = args.getThreadArg(); + if (thread == null) { + sendCommandResponse("error: invalid thread\n"); + return; + } + + if (thread.fSuspend == null) { + sendCommandResponse("error: thread running\n"); + return; + } + + StringTokenizer tokenizer = new StringTokenizer(args.getNextStringArg(), "|"); + tokenizer.countTokens(); + + int numEvalLines = tokenizer.countTokens(); + thread.fThreadCode = new String[fCode.length + numEvalLines + 1]; + System.arraycopy(fCode, 0, thread.fThreadCode, 0, fCode.length); + for (int i = 0; i < numEvalLines; i++) { + String line = tokenizer.nextToken(); + StringBuffer lineBuf = new StringBuffer(line.length()); + Matcher matcher = fPackPattern.matcher(line); + int lastMatchEnd = 0; + while (matcher.find()) { + lineBuf.append(line.substring(lastMatchEnd, matcher.start())); + String charCode = line.substring(matcher.start() + 1, matcher.start() + 3); + try { + lineBuf.append((char) Integer.parseInt(charCode, 16)); + } catch (NumberFormatException e) { + } + lastMatchEnd = matcher.end(); + } + if (lastMatchEnd < line.length()) { + lineBuf.append(line.substring(lastMatchEnd)); + } + thread.fThreadCode[fCode.length + i] = lineBuf.toString(); + } + thread.fThreadCode[fCode.length + numEvalLines] = "xyzzy"; + thread.fThreadLabels = mapLabels(fCode); + + thread.fSavedPC = thread.fCurrentFrame.fPC; + thread.fCurrentFrame.fPC = fCode.length; + thread.fPerformingEval = true; + + thread.fSuspend = null; + + sendCommandResponse("ok\n"); + + sendDebugEvent("resumed " + thread.fID + " eval", false); + } + + void debugEventStop(Args args) { + String event = args.getNextStringArg(); + int stop = args.getNextIntArg(); + fEventStops.put(event, new Boolean(stop > 0)); + sendCommandResponse("ok\n"); + } + + void debugTerminate() { + sendCommandResponse("ok\n"); + sendDebugEvent("vmterminated", false); + System.exit(0); + } + + void debugFrame(Args args) { + PDAThread thread = args.getThreadArg(); + if (thread == null) { + sendCommandResponse("error: invalid thread\n"); + return; + } + + int sfnumber = args.getNextIntArg(); + Frame frame = null; + if (sfnumber >= thread.fFrames.size()) { + frame = thread.fCurrentFrame; + } else { + frame = (Frame)thread.fFrames.get(sfnumber); + } + sendCommandResponse(printFrame(frame) + "\n"); + } + + void debugGroups(Args args) { + TreeSet groups = new TreeSet(); + for (Iterator itr = fRegisters.values().iterator(); itr.hasNext();) { + Register reg = (Register)itr.next(); + groups.add(reg.fGroup); + } + StringBuffer response = new StringBuffer(); + for (Iterator itr = groups.iterator(); itr.hasNext();) { + response.append(itr.next()); + response.append('|'); + } + response.append('\n'); + sendCommandResponse(response.toString()); + } + + void debugPopData(Args args) { + PDAThread thread = args.getThreadArg(); + if (thread == null) { + sendCommandResponse("error: invalid thread\n"); + return; + } + + thread.fStack.pop(); + sendCommandResponse("ok\n"); + } + + void debugPushData(Args args) { + PDAThread thread = args.getThreadArg(); + if (thread == null) { + sendCommandResponse("error: invalid thread\n"); + return; + } + + Object val = args.getNextIntOrStringArg(); + thread.fStack.push(val); + sendCommandResponse("ok\n"); + } + + void debugRegisters(Args args) { + String group = args.getNextStringArg(); + + StringBuffer response = new StringBuffer(); + for (Iterator itr = fRegisters.values().iterator(); itr.hasNext();) { + Register reg = (Register)itr.next(); + if (group.equals(reg.fGroup)) { + response.append(reg.fName); + response.append(' '); + response.append(reg.fIsWriteable); + for (Iterator itr2 = reg.fBitFields.values().iterator(); itr2.hasNext();) { + BitField bitField = (BitField)itr2.next(); + response.append('|'); + response.append(bitField.fName); + response.append(' '); + response.append(bitField.fBitOffset); + response.append(' '); + response.append(bitField.fBitCount); + response.append(' '); + for (Iterator itr3 = bitField.fMnemonics.entrySet().iterator(); itr3.hasNext();) { + Map.Entry mnemonicEntry = (Map.Entry)itr3.next(); + response.append(mnemonicEntry.getKey()); + response.append(' '); + response.append(mnemonicEntry.getValue()); + response.append(' '); + } + } + + response.append('#'); + } + } + response.append('\n'); + sendCommandResponse(response.toString()); + } + + void debugResume(Args args) { + PDAThread thread = args.getThreadArg(); + if (thread == null) { + sendCommandResponse("error: invalid thread\n"); + return; + } + if (fSuspendVM != null) { + sendCommandResponse("error: cannot resume thread when vm is suspended\n"); + return; + } + if (thread.fSuspend == null) { + sendCommandResponse("error: thread already running\n"); + return; + } + + thread.fSuspend = null; + sendDebugEvent("resumed " + thread.fID + " client", false); + + sendCommandResponse("ok\n"); + } + + void debugSetBreakpoint(Args args) { + int line = args.getNextIntArg(); + int stopVM = args.getNextIntArg(); + + fBreakpoints.put(new Integer(line), new Boolean(stopVM != 0)); + sendCommandResponse("ok\n"); + } + + void debugSetData(Args args) { + PDAThread thread = args.getThreadArg(); + if (thread == null) { + sendCommandResponse("error: invalid thread\n"); + return; + } + + int offset = args.getNextIntArg(); + Object val = args.getNextIntOrStringArg(); + + if (offset < thread.fStack.size()) { + thread.fStack.set(offset, val); + } else { + thread.fStack.add(0, val); + } + sendCommandResponse("ok\n"); + } + + void debugSetVariable(Args args) { + PDAThread thread = args.getThreadArg(); + if (thread == null) { + sendCommandResponse("error: invalid thread\n"); + return; + } + + int sfnumber = args.getNextIntArg(); + String var = args.getNextStringArg(); + Object val = args.getNextIntOrStringArg(); + while (args.hasNextArg()) { + val = val.toString() + " " + args.getNextStringArg(); + } + + if (sfnumber >= thread.fFrames.size()) { + thread.fCurrentFrame.set(var, val); + } else { + ((Frame)thread.fFrames.get(sfnumber)).set(var, val); + } + sendCommandResponse("ok\n"); + } + + void debugStack(Args args) { + PDAThread thread = args.getThreadArg(); + if (thread == null) { + sendCommandResponse("error: invalid thread\n"); + return; + } + + StringBuffer result = new StringBuffer(); + + for (Iterator itr = thread.fFrames.iterator(); itr.hasNext();) { + Frame frame = (Frame)itr.next(); + result.append(printFrame(frame)); + result.append('#'); + } + result.append(printFrame(thread.fCurrentFrame)); + result.append('\n'); + sendCommandResponse(result.toString()); + } + + void debugStackDepth(Args args) { + PDAThread thread = args.getThreadArg(); + if (thread == null) { + sendCommandResponse("error: invalid thread\n"); + return; + } + sendCommandResponse( Integer.toString(thread.fFrames.size() + 1) + "\n" ); + } + + + /** + * The stack frame output is: frame # frame # frame ... where each frame is: + * filename | line number | function name | var | var | var | var ... + */ + private String printFrame(Frame frame) { + StringBuffer buf = new StringBuffer(); + buf.append(fFilename); + buf.append('|'); + buf.append(frame.fPC); + buf.append('|'); + buf.append(frame.fFunction); + for (Iterator itr = frame.fLocalVariables.keySet().iterator(); itr.hasNext();) { + String var = (String)itr.next(); + if (var.indexOf('.') == -1) { + buf.append('|'); + buf.append(var); + } + } + return buf.toString(); + } + + void debugState(Args args) { + PDAThread thread = args.getThreadArg(); + String response = null; + if (thread == null) { + response = fSuspendVM == null ? "running" : fSuspendVM; + } else if (fSuspendVM != null) { + response = "vm"; + } else { + response = thread.fSuspend == null ? "running" : thread.fSuspend; + } + sendCommandResponse(response + "\n"); + } + + void debugStep(Args args) { + PDAThread thread = args.getThreadArg(); + if (thread == null) { + sendCommandResponse("error: invalid thread\n"); + return; + } + + // Set suspend to null to allow the debug loop to exit back to the + // instruction loop and thus run an instruction. However, we want to + // come back to the debug loop right away, so the step flag is set to + // true which will cause the suspend flag to get set to true when we + // get to the next instruction. + if (fSuspendVM != null) { + // All threads are suspended, so suspend all threads again when + // step completes. + fSuspendVM = null; + fStepVM = true; + // Also mark the thread that initiated the step to mark it as + // the triggering thread when suspending. + thread.fStep = true; + } else { + if (thread.fSuspend == null) { + sendCommandResponse("error: thread already running\n"); + return; + } + thread.fSuspend = null; + thread.fStep = true; + sendDebugEvent("resumed " + thread.fID + " step", false); + } + sendCommandResponse("ok\n"); + } + + void debugStepReturn(Args args) { + PDAThread thread = args.getThreadArg(); + if (thread == null) { + sendCommandResponse("error: invalid thread\n"); + return; + } + + if (fSuspendVM != null) { + fSuspendVM = null; + fStepReturnVM = true; + thread.fStepReturn = true; + } else { + if (thread.fSuspend == null) { + sendCommandResponse("error: thread running\n"); + return; + } + thread.fSuspend = null; + thread.fStepReturn = true; + sendDebugEvent("resumed " + thread.fID + " step", false); + } + sendCommandResponse("ok\n"); + } + + void debugSuspend(Args args) { + PDAThread thread = args.getThreadArg(); + if (thread == null) { + sendCommandResponse("error: invalid thread\n"); + return; + } + if (fSuspendVM != null) { + sendCommandResponse("error: vm already suspended\n"); + return; + } + if (thread.fSuspend != null) { + sendCommandResponse("error: thread already suspended\n"); + return; + } + + thread.fSuspend = "client"; + sendDebugEvent("suspended " + thread.fID + " client", false); + sendCommandResponse("ok\n"); + } + + void debugThreads() { + StringBuffer response = new StringBuffer(); + for (Iterator itr = fThreads.keySet().iterator(); itr.hasNext();) { + response.append(itr.next()); + response.append(' '); + } + sendCommandResponse(response.toString().trim() + "\n"); + } + + void debugVar(Args args) { + PDAThread thread = args.getThreadArg(); + if (thread == null) { + sendCommandResponse("error: invalid thread\n"); + return; + } + + int sfnumber = args.getNextIntArg(); + String var = args.getNextStringArg(); + + Frame frame = sfnumber >= thread.fFrames.size() + ? thread.fCurrentFrame : (Frame)thread.fFrames.get(sfnumber); + + Object val = frame.get(var); + if (val == null) { + sendCommandResponse("error: variable undefined\n"); + } else { + sendCommandResponse(val.toString() + "\n"); + } + } + + void debugVMResume() { + if (fSuspendVM == null) { + sendCommandResponse("error: vm already running\n"); + return; + } + + fSuspendVM = null; + sendCommandResponse("ok\n"); + } + + void debugVMSuspend() { + if (fSuspendVM != null) { + sendCommandResponse("error: vm already suspended\n"); + return; + } + + fSuspendVM = "client"; + sendCommandResponse("ok\n"); + } + + void debugWatch(Args args) { + String funcAndVar = args.getNextStringArg(); + int flags = args.getNextIntArg(); + fWatchpoints.put(funcAndVar, new Integer(flags)); + sendCommandResponse("ok\n"); + } + + void iAdd(PDAThread thread, Args args) { + Object val1 = thread.fStack.pop(); + Object val2 = thread.fStack.pop(); + if (val1 instanceof Integer && val2 instanceof Integer) { + int intVal1 = ((Integer) val1).intValue(); + int intVal2 = ((Integer) val2).intValue(); + thread.fStack.push( new Integer(intVal1 + intVal2) ); + } else { + thread.fStack.push( new Integer(-1) ); + } + } + + void iBranchNotZero(PDAThread thread, Args args) { + Object val = thread.fStack.pop(); + if (val instanceof Integer && ((Integer) val).intValue() != 0) { + String label = args.getNextStringArg(); + if (thread.fThreadLabels.containsKey(label)) { + thread.fCurrentFrame.fPC = ((Integer)thread.fThreadLabels.get(label)).intValue(); + } else { + sendDebugEvent("no such label " + label, true); + if ( ((Boolean)fEventStops.get("nosuchlabel")).booleanValue() ) { + fSuspendVM = thread.fID + " event nosuchlabel"; + thread.fStack.push(val); + thread.fCurrentFrame.fPC--; + } + } + } + } + + void iCall(PDAThread thread, Args args) { + String label = args.getNextStringArg(); + if (thread.fThreadLabels.containsKey(label)) { + thread.fFrames.add(thread.fCurrentFrame); + thread.fCurrentFrame = new Frame(label, ((Integer)thread.fThreadLabels.get(label)).intValue()); + } else { + sendDebugEvent("no such label " + label, true); + if ( ((Boolean)fEventStops.get("nosuchlabel")).booleanValue() ) { + fSuspendVM = thread.fID + " event nosuchlabel"; + thread.fCurrentFrame.fPC--; + } + } + } + + void iDec(PDAThread thread, Args args) { + Object val = thread.fStack.pop(); + if (val instanceof Integer) { + val = new Integer(((Integer) val).intValue() - 1); + } + thread.fStack.push(val); + } + + void iDef(PDAThread thread, Args args) { + String type = args.getNextStringArg(); + + String name = args.getNextStringArg(); + String regName = getRegisterPartOfName(name); + String bitFieldName = getBitFieldPartOfName(name); + + if ("register".equals(type)) { + Register reg = new Register(regName); + reg.fGroup = args.getNextStringArg(); + fRegisters.put(regName, reg); + reg.fIsWriteable = args.getNextBooleanArg(); + } else if ("bitfield".equals(type)) { + Register reg = (Register)fRegisters.get(regName); + if (reg == null) return; + BitField bitField = new BitField(bitFieldName); + bitField.fBitOffset = args.getNextIntArg(); + bitField.fBitCount = args.getNextIntArg(); + reg.fBitFields.put(bitFieldName, bitField); + } else if ("mnemonic".equals(type)) { + Register reg = (Register)fRegisters.get(regName); + if (reg == null) return; + BitField bitField = (BitField)reg.fBitFields.get(bitFieldName); + if (bitField == null) return; + bitField.fMnemonics.put(args.getNextStringArg(), new Integer(args.getNextIntArg())); + } + sendDebugEvent("registers", false); + } + + private String getRegisterPartOfName(String name) { + if (name.startsWith("$")) { + int end = name.indexOf('.'); + end = end != -1 ? end : name.length(); + return name.substring(1, end); + } + return null; + } + + private String getBitFieldPartOfName(String name) { + int start = name.indexOf('.'); + if (name.startsWith("$") && start != -1) { + return name.substring(start + 1, name.length()); + } + return null; + } + + void iDup(PDAThread thread, Args args) { + Object val = thread.fStack.pop(); + thread.fStack.push(val); + thread.fStack.push(val); + } + + void iExec(PDAThread thread, Args args) { + String label = args.getNextStringArg(); + if (fLabels.containsKey(label)) { + int id = fNextThreadId++; + fThreads.put( new Integer(id), new PDAThread(id, label, ((Integer)fLabels.get(label)).intValue()) ); + sendDebugEvent("started " + id, false); + } else { + sendDebugEvent("no such label " + label, true); + if ( ((Boolean)fEventStops.get("nosuchlabel")).booleanValue() ) { + thread.fSuspend = "event nosuchlabel"; + thread.fCurrentFrame.fPC--; + } + } + } + + void iHalt(PDAThread thread, Args args) { + thread.fRun = false; + } + + void iOutput(PDAThread thread, Args args) { + System.out.println(thread.fStack.pop()); + } + + void iPop(PDAThread thread, Args args) { + String arg = args.getNextStringArg(); + if (arg.startsWith("$")) { + String var = arg.substring(1); + thread.fCurrentFrame.set(var, thread.fStack.pop()); + String key = thread.fCurrentFrame.fFunction + "::" + var; + if ( fWatchpoints.containsKey(key) && (((Integer)fWatchpoints.get(key)).intValue() & 2) != 0 ) { + fSuspendVM = thread.fID + " watch write " + key; + } + } else { + thread.fStack.pop(); + } + } + + void iPush(PDAThread thread, Args args) { + String arg = args.getNextStringArg(); + while (arg.length() != 0) { + if (arg.startsWith("$")) { + String var = arg.substring(1); + Object val = thread.fCurrentFrame.get(var); + if (val == null) val = "<undefined>"; + thread.fStack.push(val); + String key = thread.fCurrentFrame.fFunction + "::" + var; + if (fWatchpoints.containsKey(key) && (((Integer)fWatchpoints.get(key)).intValue() & 1) != 0) { + fSuspendVM = thread.fID + " watch read " + key; + } + } else { + Object val = arg; + if (args.hasNextArg()) { + while (args.hasNextArg()) { + val = val.toString() + " " + args.getNextStringArg(); + } + } else { + try { + val = new Integer(arg); + } catch (NumberFormatException e) { + } + } + thread.fStack.push(val); + } + + arg = args.getNextStringArg(); + } + } + + void iReturn(PDAThread thread, Args args) { + if (!thread.fFrames.isEmpty()) { + thread.fCurrentFrame = (Frame)thread.fFrames.remove(thread.fFrames.size() - 1); + } else { + // Execution returned from the top frame, which means this thread + // should exit. + thread.fRun = false; + } + } + + void iVar(PDAThread thread, Args args) { + String var = args.getNextStringArg(); + thread.fCurrentFrame.set(var, new Integer(0)); + } + + void iInternalEndEval(PDAThread thread, Args args) { + Object result = thread.fStack.pop(); + thread.fThreadCode = fCode; + thread.fThreadLabels = fLabels; + thread.fCurrentFrame.fPC = thread.fSavedPC; + sendDebugEvent("evalresult " + result, false); + thread.fSuspend = "eval"; + thread.fPerformingEval = false; + } + +} diff --git a/org.eclipse.debug.examples.core/pdavm/tests/vmtest10.pda b/org.eclipse.debug.examples.core/pdavm/tests/vmtest10.pda new file mode 100644 index 000000000..837277f5f --- /dev/null +++ b/org.eclipse.debug.examples.core/pdavm/tests/vmtest10.pda @@ -0,0 +1,38 @@ +def register $reg1 group1 true +def register $reg2 group1 false +def register $reg3 group2 true +def bitfield $reg1.field1 0 2 +def bitfield $reg1.field2 2 2 +def mnemonic $reg1.field2 zero 0 +def mnemonic $reg1.field2 one 1 +def mnemonic $reg1.field2 two 2 +def mnemonic $reg1.field2 three 3 +push 1 +pop $$reg1 +push $$reg1 +output +push 2 +pop $$reg1.field1 +push $$reg1.field1 +output +push 4 +pop $$reg1.field1 +push $$reg1.field1 +output +push 1 +pop $$reg1.field2 +push $$reg1 +output +push zero +pop $$reg1.field2 +push $$reg1.field2 +output +push $$reg1 +output +push 2 +pop $$reg1.field2 +push $$reg1.field2 +output +push $$reg1 +output +halt
\ No newline at end of file diff --git a/org.eclipse.debug.examples.core/pdavm/tests/vmtest3.pda b/org.eclipse.debug.examples.core/pdavm/tests/vmtest3.pda index a9fcfc2a8..5aecdc5e6 100644 --- a/org.eclipse.debug.examples.core/pdavm/tests/vmtest3.pda +++ b/org.eclipse.debug.examples.core/pdavm/tests/vmtest3.pda @@ -8,4 +8,6 @@ add call zippy add output +push 1 +branch_not_zero swishy halt diff --git a/org.eclipse.debug.examples.core/pdavm/tests/vmtest9.pda b/org.eclipse.debug.examples.core/pdavm/tests/vmtest9.pda new file mode 100644 index 000000000..336a251d9 --- /dev/null +++ b/org.eclipse.debug.examples.core/pdavm/tests/vmtest9.pda @@ -0,0 +1,23 @@ +push 5 +:thread_create +exec foo +dec +dup +branch_not_zero thread_create +push finished +output +halt +:foo +push thread_created +output +call inner +halt +:inner +var b +call inner2 +push 2 +return +:inner2 +var c +push 3 +return diff --git a/org.eclipse.debug.examples.core/pdavm/tests/vmtest_children.pda b/org.eclipse.debug.examples.core/pdavm/tests/vmtest_children.pda new file mode 100644 index 000000000..b0bbd163d --- /dev/null +++ b/org.eclipse.debug.examples.core/pdavm/tests/vmtest_children.pda @@ -0,0 +1,8 @@ +var a +var a.b +var a.c +push 1 +pop $a.b +push $a.b +output +halt diff --git a/org.eclipse.debug.examples.core/pdavm/tests/vmtests.pl b/org.eclipse.debug.examples.core/pdavm/tests/vmtests.pl deleted file mode 100644 index 0e2f8a358..000000000 --- a/org.eclipse.debug.examples.core/pdavm/tests/vmtests.pl +++ /dev/null @@ -1,448 +0,0 @@ -#!perl.exe - -use strict; -use warnings; -use IO::Socket; - -##################################################################### -# Copyright (c) 2004-2005 IBM Corporation and others. -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://www.eclipse.org/legal/epl-v10.html -# -# Contributors: -# Bjorn Freeman-Benson - initial API and implementation -##################################################################### -# -# This test is designed to run on Windows: -# -# cd c:\eclipse\workspace\org.eclipse.debug.examples.core -# perl pdavm\tests\vmtests.pl -# -# If the tests fail, they often indicate that by hanging in an -# infinite loop. Additionally, the vm under test often becomes -# a 100% CPU usage zombie. Use the task manager to kill them. -# -my $socket1; -my $socket2; - -sub expect_output { - my $expect = shift; - my $line = <PROGRAM_OUTPUT>; - chomp($line); - return if( $line eq $expect ); - die "expected output: $expect\nSaw output: $line"; -} -sub expect_output_eof { - my $line = <PROGRAM_OUTPUT>; - return if( !defined $line ); - die "expected: EOF on output"; -} -sub send_command { - my $string = shift; - my $expect = shift; - $expect = "ok" if( !defined $expect ); - #print STDERR "SEND: $string\n"; - print $socket1 "$string\n"; - my $result = <$socket1>; - chomp($result); - #print STDERR "RESULT: $result\n"; - die "sent: $string\nexpected: $expect\nsaw: $result" if( !($result eq $expect) ); -} -sub expect_event { - my $string = shift; - my $event = <$socket2>; - chomp($event); - #print STDERR "EVENT: $event\n"; - die "expected event: $string\nsaw event: $event" if( !($string eq $event) ); -} -sub setup_sockets { - #print STDERR "calling socket 12345\n"; - $socket1 = IO::Socket::INET->new( - Proto => "tcp", - PeerAddr => "localhost", - PeerPort => "12345", - Timeout => 10, - ) - or die "cannot connect to debug socket 12345"; - #print STDERR "calling socket 12346\n"; - $socket2 = IO::Socket::INET->new( - Proto => "tcp", - PeerAddr => "localhost", - PeerPort => "12346", - Timeout => 10, - ) - or die "cannot connect to debug socket 12346"; - #print STDERR "done calling sockets\n"; -} - -sub test2 { - print "test2 (common debug commands)..\n"; - - my $kidpid; - die "can't fork: $!" unless defined($kidpid = fork()); - if( $kidpid ) { - #print STDERR "starting program\n"; - open PROGRAM_OUTPUT, "perl pdavm\\pda.pl pdavm\\tests\\vmtest2.pda -debug 12345 12346 |"; - #print STDERR "done starting program\n"; - expect_output("-debug 12345 12346"); - expect_output("debug connection accepted"); - expect_output("10"); - expect_output_eof(); - exit 0; - } else { - setup_sockets(); - expect_event("started"); - # test step - send_command("step"); - expect_event("resumed step"); - expect_event("suspended step"); - # test breakpoint - send_command("set 4"); - send_command("data", "6|"); - send_command("resume"); - expect_event("resumed client"); - expect_event("suspended breakpoint 4"); - # test data stack - send_command("data", "6|7|8|9|"); - send_command("popdata"); - send_command("data", "6|7|8|"); - send_command("pushdata 11"); - send_command("data", "6|7|8|11|"); - send_command("setdata 1 2"); - send_command("data", "6|2|8|11|"); - # test call stack - send_command("set 12"); - send_command("set 19"); - send_command("stepreturn"); - expect_event("resumed client"); - expect_event("suspended breakpoint 12"); - send_command("clear 19"); - send_command("stack", "pdavm\\tests\\vmtest2.pda|6|main#pdavm\\tests\\vmtest2.pda|18|sub1|m|n#pdavm\\tests\\vmtest2.pda|12|sub2" ); - send_command("stepreturn"); - expect_event("resumed client"); - expect_event("suspended step"); - send_command("stack", "pdavm\\tests\\vmtest2.pda|6|main#pdavm\\tests\\vmtest2.pda|18|sub1|m|n#pdavm\\tests\\vmtest2.pda|13|sub2" ); - send_command("stepreturn"); - expect_event("resumed client"); - expect_event("suspended step"); - send_command("stack", "pdavm\\tests\\vmtest2.pda|6|main#pdavm\\tests\\vmtest2.pda|22|sub1|m|n" ); - send_command("set 6"); - send_command("stepreturn"); - expect_event("resumed client"); - expect_event("suspended breakpoint 6"); - # test set and clear - send_command("set 27"); - send_command("set 29"); - send_command("set 33"); - send_command("resume"); - expect_event("resumed client"); - expect_event("suspended breakpoint 33"); - send_command("resume"); - expect_event("resumed client"); - expect_event("suspended breakpoint 27"); - send_command("clear 33"); - send_command("resume"); - expect_event("resumed client"); - expect_event("suspended breakpoint 29"); - # test var and setvar - send_command("set 47"); - send_command("resume"); - expect_event("resumed client"); - expect_event("suspended breakpoint 47"); - send_command("var 1 b", "4"); - send_command("var 2 b", "2"); - send_command("var 1 a", "0"); - send_command("setvar 1 a 99"); - send_command("data", "6|2|8|11|27|1|4|"); - send_command("step"); - expect_event("resumed step"); - expect_event("suspended step"); - send_command("var 1 a", "99"); - send_command("step"); - expect_event("resumed step"); - expect_event("suspended step"); - send_command("data", "6|2|8|11|27|1|4|99|"); - # test exit - send_command("exit"); - expect_event("terminated"); - } - #print STDERR "waiting for child\n"; - wait(); - #print STDERR "child joined\n"; - close PROGRAM_OUTPUT; - print "test2..SUCCESS\n"; -} - -sub test3 { - print "test3 (uncaught events)..\n"; - - my $kidpid; - die "can't fork: $!" unless defined($kidpid = fork()); - if( $kidpid ) { - #print STDERR "starting program\n"; - open PROGRAM_OUTPUT, "perl pdavm\\pda.pl pdavm\\tests\\vmtest3.pda -debug 12345 12346 |"; - #print STDERR "done starting program\n"; - expect_output("-debug 12345 12346"); - expect_output("debug connection accepted"); - expect_output("10"); - expect_output_eof(); - exit 0; - } else { - setup_sockets(); - expect_event("started"); - send_command("resume"); - expect_event("resumed client"); - expect_event("unimplemented instruction foobar"); - expect_event("no such label zippy"); - expect_event("terminated"); - } - #print STDERR "waiting for child\n"; - wait(); - #print STDERR "child joined\n"; - close PROGRAM_OUTPUT; - print "test3..SUCCESS\n"; -} -sub test4 { - print "test4 (caught events)..\n"; - - my $kidpid; - die "can't fork: $!" unless defined($kidpid = fork()); - if( $kidpid ) { - #print STDERR "starting program\n"; - open PROGRAM_OUTPUT, "perl pdavm\\pda.pl pdavm\\tests\\vmtest3.pda -debug 12345 12346 |"; - #print STDERR "done starting program\n"; - expect_output("-debug 12345 12346"); - expect_output("debug connection accepted"); - expect_output("10"); - expect_output_eof(); - exit 0; - } else { - setup_sockets(); - expect_event("started"); - send_command("eventstop unimpinstr 1"); - send_command("resume"); - expect_event("resumed client"); - expect_event("unimplemented instruction foobar"); - expect_event("suspended event unimpinstr"); - send_command("eventstop unimpinstr 0"); - send_command("resume"); - expect_event("resumed client"); - expect_event("unimplemented instruction foobar"); - expect_event("no such label zippy"); - expect_event("terminated"); - } - #print STDERR "waiting for child\n"; - wait(); - #print STDERR "child joined\n"; - close PROGRAM_OUTPUT; - print "test4..SUCCESS\n"; -} -sub test5 { - print "test5 (caught events)..\n"; - - my $kidpid; - die "can't fork: $!" unless defined($kidpid = fork()); - if( $kidpid ) { - #print STDERR "starting program\n"; - open PROGRAM_OUTPUT, "perl pdavm\\pda.pl pdavm\\tests\\vmtest3.pda -debug 12345 12346 |"; - #print STDERR "done starting program\n"; - expect_output("-debug 12345 12346"); - expect_output("debug connection accepted"); - expect_output("10"); - expect_output_eof(); - exit 0; - } else { - setup_sockets(); - expect_event("started"); - send_command("eventstop nosuchlabel 1"); - send_command("resume"); - expect_event("resumed client"); - expect_event("unimplemented instruction foobar"); - expect_event("no such label zippy"); - expect_event("suspended event nosuchlabel"); - send_command("eventstop nosuchlabel 0"); - send_command("resume"); - expect_event("resumed client"); - expect_event("no such label zippy"); - expect_event("terminated"); - } - #print STDERR "waiting for child\n"; - wait(); - #print STDERR "child joined\n"; - close PROGRAM_OUTPUT; - print "test5..SUCCESS\n"; -} -sub test6 { - print "test6 (watch points)..\n"; - - my $kidpid; - die "can't fork: $!" unless defined($kidpid = fork()); - if( $kidpid ) { - #print STDERR "starting program\n"; - open PROGRAM_OUTPUT, "perl pdavm\\pda.pl pdavm\\tests\\vmtest6.pda -debug 12345 12346 |"; - #print STDERR "done starting program\n"; - expect_output("-debug 12345 12346"); - expect_output("debug connection accepted"); - expect_output("8"); - expect_output_eof(); - exit 0; - } else { - setup_sockets(); - expect_event("started"); - send_command("watch inner::a 1"); - send_command("watch main::a 2"); - send_command("resume"); - expect_event("resumed client"); - expect_event("suspended watch write main::a"); - send_command("stack", "pdavm\\tests\\vmtest6.pda|4|main|a|b"); - send_command("resume"); - expect_event("resumed client"); - expect_event("suspended watch read inner::a"); - send_command("stack", "pdavm\\tests\\vmtest6.pda|10|main|a|b#pdavm\\tests\\vmtest6.pda|25|inner|a|c"); - send_command("watch inner::a 0"); - send_command("resume"); - expect_event("resumed client"); - expect_event("terminated"); - } - #print STDERR "waiting for child\n"; - wait(); - #print STDERR "child joined\n"; - close PROGRAM_OUTPUT; - print "test6..SUCCESS\n"; -} -sub test7 { - print "test7 (eval)..\n"; - - my $kidpid; - die "can't fork: $!" unless defined($kidpid = fork()); - if( $kidpid ) { - #print STDERR "starting program\n"; - open PROGRAM_OUTPUT, "perl pdavm\\pda.pl pdavm\\tests\\vmtest6.pda -debug 12345 12346 |"; - #print STDERR "done starting program\n"; - expect_output("-debug 12345 12346"); - expect_output("debug connection accepted"); - expect_output("8"); - expect_output_eof(); - exit 0; - } else { - setup_sockets(); - expect_event("started"); - send_command("set 25"); - send_command("resume"); - expect_event("resumed client"); - expect_event("suspended breakpoint 25"); - # - send_command("eval push%204|push%205|add"); - expect_event("resumed client"); - expect_event("evalresult 9"); - expect_event("suspended eval"); - # - send_command("step"); - expect_event("resumed step"); - expect_event("suspended step"); - send_command("stack", "pdavm\\tests\\vmtest6.pda|10|main|a|b#pdavm\\tests\\vmtest6.pda|26|inner|a|c"); - send_command("data", "4|4|"); - send_command("eval call%20other"); - expect_event("resumed client"); - expect_event("evalresult 15"); - expect_event("suspended eval"); - send_command("stack", "pdavm\\tests\\vmtest6.pda|10|main|a|b#pdavm\\tests\\vmtest6.pda|26|inner|a|c"); - send_command("data", "4|4|"); - send_command("resume"); - expect_event("resumed client"); - expect_event("terminated"); - } - #print STDERR "waiting for child\n"; - wait(); - #print STDERR "child joined\n"; - close PROGRAM_OUTPUT; - print "test7..SUCCESS\n"; -} -sub test1 { - print "test1 (normal run mode)..\n"; - open PROGRAM_OUTPUT, "perl pdavm\\pda.pl examples\\example.pda |" or die $!; - expect_output("\"hello\""); - expect_output("\"barfoo\""); - expect_output("\"first\""); - expect_output("\"second\""); - expect_output("12"); - expect_output("11"); - expect_output("10"); - expect_output("\"barfoo\""); - expect_output("\"first\""); - expect_output("\"second\""); - expect_output("\"end\""); - expect_output_eof(); - print "test1..SUCCESS\n"; -} -sub test8 { - print "test8 (drop to frame)..\n"; - - my $kidpid; - die "can't fork: $!" unless defined($kidpid = fork()); - if( $kidpid ) { - #print STDERR "starting program\n"; - open PROGRAM_OUTPUT, "perl pdavm\\pda.pl pdavm\\tests\\vmtest8.pda -debug 12345 12346 |"; - #print STDERR "done starting program\n"; - expect_output("-debug 12345 12346"); - expect_output("debug connection accepted"); - expect_output("1"); - expect_output_eof(); - exit 0; - } else { - setup_sockets(); - expect_event("started"); - send_command("step"); - expect_event("resumed step"); - expect_event("suspended step"); - send_command("step"); - expect_event("resumed step"); - expect_event("suspended step"); - send_command("step"); - expect_event("resumed step"); - expect_event("suspended step"); - send_command("step"); - expect_event("resumed step"); - expect_event("suspended step"); - send_command("step"); - expect_event("resumed step"); - expect_event("suspended step"); - send_command("step"); - expect_event("resumed step"); - expect_event("suspended step"); - send_command("step"); - expect_event("resumed step"); - expect_event("suspended step"); - send_command("stack", "pdavm\\tests\\vmtest8.pda|2|main|a#pdavm\\tests\\vmtest8.pda|8|inner|b#pdavm\\tests\\vmtest8.pda|12|inner2|c"); - send_command("drop"); - expect_event("suspended drop"); - send_command("stack", "pdavm\\tests\\vmtest8.pda|2|main|a#pdavm\\tests\\vmtest8.pda|7|inner|b"); - send_command("step"); - expect_event("resumed step"); - expect_event("suspended step"); - send_command("stack", "pdavm\\tests\\vmtest8.pda|2|main|a#pdavm\\tests\\vmtest8.pda|8|inner|b#pdavm\\tests\\vmtest8.pda|10|inner2"); - send_command("resume"); - expect_event("resumed client"); - expect_event("terminated"); - } - #print STDERR "waiting for child\n"; - wait(); - #print STDERR "child joined\n"; - close PROGRAM_OUTPUT; - print "test8..SUCCESS\n"; -} - -# -# Run the tests -# -test1(); -test2(); -test3(); -test4(); -test5(); -test6(); -test7(); -test8(); -print "All tests complete\n";
\ No newline at end of file diff --git a/org.eclipse.debug.examples.core/samples/registers.pda b/org.eclipse.debug.examples.core/samples/registers.pda new file mode 100644 index 000000000..97fd8d409 --- /dev/null +++ b/org.eclipse.debug.examples.core/samples/registers.pda @@ -0,0 +1,72 @@ +def register $pc General true +def register $sp General true +def register $status General true +def bitfield $status.BITS_00_07 0 8 +def bitfield $status.BITS_08_15 8 8 +def bitfield $status.BITS_16_23 16 8 +def bitfield $status.BITS_24_31 24 8 +def mnemonic $status.BITS_24_31 three 3 +def mnemonic $status.BITS_24_31 twelve 12 +def mnemonic $status.BITS_24_31 fourty_eight 48 +def mnemonic $status.BITS_24_31 one_nighty_two 192 +def register $stackdepth General true +def register $stack[0] General true +def register $stack[1] General true +def register $stack[2] General true +def register $stack[3] General true +def register $stack[4] General true +push 103 +pop $$pc +push 306 +push 2 +pop $$sp +push 400 +pop $$status +push 5 +pop $$stackdepth +push 12 +pop $$stack[0] +push 45 +pop $$stack[1] +push 146 +pop $$stack[2] +push 215 +pop $$stack[3] +push 251 +pop $$stack[4] +push 306 +pop $$stack[5] +def register $total-instructions Analysis false +def register $add-instructions Analysis false +def register $call-instructions Analysis false +def register $dec-instructions Analysis false +def register $dup-instructions Analysis false +def register $halt-instructions Analysis false +def register $output-instructions Analysis false +def register $pop-instructions Analysis false +def register $push-instructions Analysis false +def register $return-instructions Analysis false +def register $var-instructions Analysis false +push 1046 +pop $$total-instructions +push 12 +pop $$add-instructions +push 24 +pop $$call-instructions +push 36 +pop $$dec-instructions +push 50 +pop $$dup-instructions +push 62 +pop $$halt-instructions +push 74 +pop $$output-instructions +push 106 +pop $$pop-instructions +push 120 +pop $$push-instructions +push 132 +pop $$return-instructions +push 144 +pop $$var-instructions +halt
\ No newline at end of file diff --git a/org.eclipse.debug.examples.core/samples/stack.pda b/org.eclipse.debug.examples.core/samples/stack.pda new file mode 100644 index 000000000..c7fa1628b --- /dev/null +++ b/org.eclipse.debug.examples.core/samples/stack.pda @@ -0,0 +1,21 @@ +push 5 +:thread_create +exec stack +dec +dup +branch_not_zero thread_create +push finished +output +halt +:stack +push 100 +:inner +dup +output +dup +branch_not_zero descend +return +:descend +dec +call inner +return
\ No newline at end of file diff --git a/org.eclipse.debug.examples.core/samples/structures.pda b/org.eclipse.debug.examples.core/samples/structures.pda index 97858b079..4cc881728 100644 --- a/org.eclipse.debug.examples.core/samples/structures.pda +++ b/org.eclipse.debug.examples.core/samples/structures.pda @@ -1,8 +1,29 @@ +push a +push b +push c +push x +push y +push z push one two three push 1 2 3 +push I II III var x +var x.a +var x.b var y +var y.c +var y.d +var y.d.1 +var y.d.2 +var y.d.3 pop $x +pop $x.a +pop $x.b pop $y +pop $y.c +pop $y.d +pop $y.d.1 +pop $y.d.2 +pop $y.d.3 push Done output
\ No newline at end of file diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDALineBreakpoint.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDALineBreakpoint.java index 24062b0b5..894d7432c 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDALineBreakpoint.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDALineBreakpoint.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.breakpoints; @@ -16,14 +17,18 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IBreakpoint; -import org.eclipse.debug.core.model.IThread; import org.eclipse.debug.core.model.LineBreakpoint; import org.eclipse.debug.examples.core.pda.DebugCorePlugin; import org.eclipse.debug.examples.core.pda.model.IPDAEventListener; import org.eclipse.debug.examples.core.pda.model.PDADebugTarget; import org.eclipse.debug.examples.core.pda.model.PDAThread; +import org.eclipse.debug.examples.core.protocol.PDAClearBreakpointCommand; +import org.eclipse.debug.examples.core.protocol.PDAEvent; +import org.eclipse.debug.examples.core.protocol.PDARunControlEvent; +import org.eclipse.debug.examples.core.protocol.PDASetBreakpointCommand; +import org.eclipse.debug.examples.core.protocol.PDASuspendedEvent; +import org.eclipse.debug.examples.core.protocol.PDAVMSuspendedEvent; /** @@ -108,7 +113,7 @@ public class PDALineBreakpoint extends LineBreakpoint implements IPDAEventListen //#ifdef ex3 //# // TODO: Exercise 3 - create breakpoint request in interpreter //#else - target.sendRequest("set " + (getLineNumber() - 1)); + target.sendCommand(new PDASetBreakpointCommand((getLineNumber() - 1), false)); //#endif } @@ -123,7 +128,7 @@ public class PDALineBreakpoint extends LineBreakpoint implements IPDAEventListen //#ifdef ex3 //# // TODO: Exercise 3 - clear breakpoint request in interpreter //#else - target.sendRequest("clear " + (getLineNumber() - 1)); + target.sendCommand(new PDAClearBreakpointCommand((getLineNumber() - 1))); //#endif } @@ -154,16 +159,12 @@ public class PDALineBreakpoint extends LineBreakpoint implements IPDAEventListen /** * Notify's the PDA interprettor that this breakpoint has been hit. */ - protected void notifyThread() { + protected void notifyThread(int threadId) { if (fTarget != null) { - try { - IThread[] threads = fTarget.getThreads(); - if (threads.length == 1) { - PDAThread thread = (PDAThread)threads[0]; - thread.suspendedBy(this); - } - } catch (DebugException e) { - } + PDAThread thread = fTarget.getThread(threadId); + if (thread != null) { + thread.suspendedBy(this); + } } } @@ -173,9 +174,12 @@ public class PDALineBreakpoint extends LineBreakpoint implements IPDAEventListen * * @see org.eclipse.debug.examples.core.pda.model.IPDAEventListener#handleEvent(java.lang.String) */ - public void handleEvent(String event) { - if (event.startsWith("suspended breakpoint")) { - handleHit(event); + public void handleEvent(PDAEvent event) { + if (event instanceof PDASuspendedEvent || event instanceof PDAVMSuspendedEvent) { + PDARunControlEvent rcEvent = (PDARunControlEvent)event; + if (rcEvent.fReason.equals("breakpoint")) { + handleHit(rcEvent); + } } } @@ -184,16 +188,16 @@ public class PDALineBreakpoint extends LineBreakpoint implements IPDAEventListen * * @param event breakpoint event */ - private void handleHit(String event) { - int lastSpace = event.lastIndexOf(' '); + private void handleHit(PDARunControlEvent event) { + int lastSpace = event.fMessage.lastIndexOf(' '); if (lastSpace > 0) { - String line = event.substring(lastSpace + 1); + String line = event.fMessage.substring(lastSpace + 1); int lineNumber = Integer.parseInt(line); // breakpoints event line numbers are 0 based, model objects are 1 based lineNumber++; try { if (getLineNumber() == lineNumber) { - notifyThread(); + notifyThread(event.fThreadId); } } catch (CoreException e) { } diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDAWatchpoint.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDAWatchpoint.java index ab819d0b5..651532909 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDAWatchpoint.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDAWatchpoint.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.breakpoints; @@ -19,6 +20,11 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.core.model.IWatchpoint; import org.eclipse.debug.examples.core.pda.model.PDADebugTarget; +import org.eclipse.debug.examples.core.protocol.PDAEvent; +import org.eclipse.debug.examples.core.protocol.PDARunControlEvent; +import org.eclipse.debug.examples.core.protocol.PDASuspendedEvent; +import org.eclipse.debug.examples.core.protocol.PDAVMSuspendedEvent; +import org.eclipse.debug.examples.core.protocol.PDAWatchCommand; /** @@ -177,23 +183,26 @@ public class PDAWatchpoint extends PDALineBreakpoint implements IWatchpoint { if (isModification()) { flag = flag | 2; } - target.sendRequest("watch " + getFunctionName() + "::" + getVariableName() + " " + flag); + target.sendCommand(new PDAWatchCommand(getFunctionName(), getVariableName(), flag)); } /* (non-Javadoc) * @see org.eclipse.debug.examples.core.pda.breakpoints.PDALineBreakpoint#clearRequest(org.eclipse.debug.examples.core.pda.model.PDADebugTarget) */ protected void clearRequest(PDADebugTarget target) throws CoreException { - target.sendRequest("watch " + getFunctionName() + "::" + getVariableName() + " " + 0); + target.sendCommand(new PDAWatchCommand(getFunctionName(), getVariableName(), 0)); } /* (non-Javadoc) * @see org.eclipse.debug.examples.core.pda.model.IPDAEventListener#handleEvent(java.lang.String) */ - public void handleEvent(String event) { - if (event.startsWith("suspended watch")) { - handleHit(event); - } + public void handleEvent(PDAEvent event) { + if (event instanceof PDASuspendedEvent || event instanceof PDAVMSuspendedEvent) { + PDARunControlEvent rcEvent = (PDARunControlEvent)event; + if (rcEvent.fReason.equals("watch")) { + handleHit(rcEvent); + } + } } /** @@ -201,8 +210,8 @@ public class PDAWatchpoint extends PDALineBreakpoint implements IWatchpoint { * * @param event breakpoint event */ - private void handleHit(String event) { - String[] strings = event.split(" "); + private void handleHit(PDARunControlEvent event) { + String[] strings = event.fMessage.split(" "); if (strings.length == 4) { String fv = strings[3]; int j = fv.indexOf("::"); @@ -212,7 +221,7 @@ public class PDAWatchpoint extends PDALineBreakpoint implements IWatchpoint { try { if (getVariableName().equals(var) && getFunctionName().equals(fcn)) { setSuspendType(strings[2]); - notifyThread(); + notifyThread(event.fThreadId); } } catch (CoreException e) { } diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/launcher/PDALaunchDelegate.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/launcher/PDALaunchDelegate.java index b5fd026dd..be7db91dd 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/launcher/PDALaunchDelegate.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/launcher/PDALaunchDelegate.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.launcher; @@ -55,28 +56,23 @@ public class PDALaunchDelegate extends LaunchConfigurationDelegate { List commandList = new ArrayList(); - // Perl executable - IValueVariable perl = VariablesPlugin.getDefault().getStringVariableManager().getValueVariable(DebugCorePlugin.VARIALBE_PERL_EXECUTABLE); - if (perl == null) { - abort("Perl executable location undefined. Check value of ${perlExecutable}.", null); - } - String path = perl.getValue(); - if (path == null) { - abort("Perl executable location unspecified. Check value of ${perlExecutable}.", null); - } - File exe = new File(path); - if (!exe.exists()) { - abort(MessageFormat.format("Specified Perl executable {0} does not exist. Check value of $perlExecutable.", new String[]{path}), null); - } - commandList.add(path); - - // Add PDA VM - File vm = DebugCorePlugin.getFileInPlugin(new Path("pdavm/pda.pl")); - if (vm == null) { - abort("Missing PDA VM", null); - } - commandList.add(vm.getAbsolutePath()); - + // Get Java VM path + String javaVMHome = System.getProperty("java.home"); + String javaVMExec = javaVMHome + File.separatorChar + "bin" + File.separatorChar + "java"; + if (File.separatorChar == '\\') { + javaVMExec += ".exe"; + } + File exe = new File(javaVMExec); + if (!exe.exists()) { + abort(MessageFormat.format("Specified java VM executable {0} does not exist.", new Object[]{javaVMExec}), null); + } + commandList.add(javaVMExec); + + commandList.add("-cp"); + commandList.add(File.pathSeparator + DebugCorePlugin.getFileInPlugin(new Path("bin"))); + + commandList.add("org.eclipse.debug.examples.pdavm.PDAVirtualMachine"); + // program name String program = configuration.getAttribute(DebugCorePlugin.ATTR_PDA_PROGRAM, (String)null); if (program == null) { @@ -106,7 +102,7 @@ public class PDALaunchDelegate extends LaunchConfigurationDelegate { String[] commandLine = (String[]) commandList.toArray(new String[commandList.size()]); Process process = DebugPlugin.exec(commandLine, null); - IProcess p = DebugPlugin.newProcess(launch, process, path); + IProcess p = DebugPlugin.newProcess(launch, process, javaVMExec); // if in debug mode, create a debug target if (mode.equals(ILaunchManager.DEBUG_MODE)) { IDebugTarget target = new PDADebugTarget(launch, p, requestPort, eventPort); diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/IPDAEventListener.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/IPDAEventListener.java index 6935ad32b..b681dc880 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/IPDAEventListener.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/IPDAEventListener.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,46 +8,28 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; +import org.eclipse.debug.examples.core.protocol.PDAEvent; + /** * Listeners are notified of events occurring in a PDA program * being interpreted. - * <p> - * The events generated by the interpreter are: - * <ul> - * <li><code>started</code> - the interpreter has started (guaranteed to be the - * first event sent)</li> - * <li><code>terminated</code> - the interpreter has terminated (guaranteed to be - * the last event sent)</li> - * <li><code>suspended X</code> - the interpreter has suspended and entered debug mode; - * <code>X</code> is the cause of the suspension: - * <ul> - * <li><code>breakpoint N</code> - a breakpoint at line <code>N</code> was hit</li> - * <li><code>client</code> - a client request to suspend has completed</li> - * <li><code>drop</code> - a client request to drop a frame has completed</li> - * <li><code>event E</code> - an error was encountered, where <code>E</code> is one - * of <code>unimpinstr</code> or <code>nosuchlabel</code></li> - * <li><code>step</code> - a step request has completed</li> - * <li><code>watch A F::V</code> - a watchpoint was hit for reason <code>A</code> - * (<code>read</code> or <code>write</code>), on variable <code>V</code> in - * function <code>F</code></li> - * </ul> - * </li> - * <li><code>resumed X</code> - the interpreter has resumed execution in run mode; - * <code>X</code> is the cause of the resume: - * <ul> - * <li><code>step</code> - a step request has been initiated</li> - * <li><code>client</code> - a client request to resume has been initiated</li> - * </ul> - * </li> - * <li><code>unimplemented instruction X</code> - an unimplemented instruction <code>X</code> - * was encountered</li> - * <li><code>no such label X</code> - a branch or call to an unknown label <code>X</code> - * was encountered</li> - * </ul> - * </p> + * + * @see org.eclipse.debug.examples.core.protocol.PDAVMStarted + * @see org.eclipse.debug.examples.core.protocol.PDAVMTerminated + * @see org.eclipse.debug.examples.core.protocol.PDAVMSuspneded + * @see org.eclipse.debug.examples.core.protocol.PDAVMResumed + * @see org.eclipse.debug.examples.core.protocol.PDAStarted + * @see org.eclipse.debug.examples.core.protocol.PDAExited + * @see org.eclipse.debug.examples.core.protocol.PDASuspended + * @see org.eclipse.debug.examples.core.protocol.PDAResumed + * @see org.eclipse.debug.examples.core.protocol.PDAUnimplementedInstructionEvent + * @see org.eclipse.debug.examples.core.protocol.PDARegisterData + * @see org.eclipse.debug.examples.core.protocol.PDANoSuchLabelEvent + * @see org.eclipse.debug.examples.core.protocol.PDAEvalResultEvent */ public interface IPDAEventListener { @@ -57,6 +39,6 @@ public interface IPDAEventListener { * * @param event the event */ - public void handleEvent(String event); + public void handleEvent(PDAEvent event); } diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAArray.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAArray.java index e27e1bad1..bcc07ba35 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAArray.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAArray.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; @@ -23,7 +24,7 @@ public class PDAArray extends PDAValue { * @throws DebugException */ public PDAArray(PDAValue value) throws DebugException { - super(value.getPDADebugTarget(), value.getValueString()); + super(value.getVariable(), value.getValueString()); } /* (non-Javadoc) @@ -42,7 +43,7 @@ public class PDAArray extends PDAValue { IVariable[] variables = new IVariable[words.length]; for (int i = 0; i < words.length; i++) { String word = words[i]; - variables[i] = new PDAArrayEntry(getPDADebugTarget(), i, new PDAValue(getPDADebugTarget(), word)); + variables[i] = new PDAArrayEntry(getPDADebugTarget(), i, new PDAValue(getVariable(), word)); } return variables; } diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugElement.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugElement.java index e64f22050..6bf39f31d 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugElement.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugElement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; @@ -17,6 +18,8 @@ import org.eclipse.debug.core.IBreakpointManager; import org.eclipse.debug.core.model.DebugElement; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.examples.core.pda.DebugCorePlugin; +import org.eclipse.debug.examples.core.protocol.PDACommand; +import org.eclipse.debug.examples.core.protocol.PDACommandResult; /** @@ -41,61 +44,50 @@ public class PDADebugElement extends DebugElement { } /** - * Sends a request to the PDA interpreter, waits for and returns the reply. - * <p> - * Interpreter commands and replies are as follows: - * <ul> - * <li><code>clear N</code> - clear the breakpoint on line <code>N</code>; - * reply is <code>ok</code></li> - * <li><code>data</code> - return the contents of the data stack; reply is the data - * from oldest to newest as a single string <code>"value|value|value|...|value|"</code></li> - * <li><code>drop</code> - pops the top stack frame off the call stack setting the - * instruction pointer to the calling statement in the calling frame</li> - * <li><code>eventstop E B</code> - optionally stop the interpreter when an error event - * <code>E</code> is encountered; <code>B</code> specifies stop (<code>1</code>) or - * continue (<code>0</code>). The possible events are <code>unimpinstr</code> and - * <code>nosuchlabel</code>. Reply is <code>ok</code>. When an event is encountered, - * the interpreter sends the error event (for example <code>unimlpemented instruction foo</code>) - * and corresponding suspend event (for example <code>suspended event unimpinstr</code>).</li> - * <li><code>exit</code> - end the interpreter; reply is <code>ok</code></li> - * <li><code>popdata</code> - pop the top value off the data stack; reply is the value</li> - * <li><code>pushdata V</code> - push the value <code>V</code> onto the data stack; reply is - * <code>ok</code></li> - * <li><code>resume</code> - resume execution of the program; reply is <code>ok</code></li> - * <li><code>set N</code> - set a line breakpoint on line <code>N</code> (lines are indexed - * from 0); reply is <code>ok</code></li> - * <li><code>setdata N V</code> - set the contents of data stack element <code>N</code> to - * value <code>V</code> (the data stack is indexed from 0, 0 being the oldest); reply - * is <code>ok</code></li> - * <li><code>setvar N M V</code> - set the contents of variable <code>M</code> from the control - * stack <code>N</code> to value <code>V</code> (the control stack is indexed from 0, - * 0 being the oldest); reply is <code>ok</code></li> - * <li><code>stack</code> - return the contents of the control stack (program counters, function and - * variable names); reply is control stack from oldest to newest as a single string - * <code>frame#frame#frame...#frame</code> where each frame is a string - * <code>"filename|pc|function name|variable name|variable name|...|variable name"</code></li> - * <li><code>step</code> - single step forward; reply is <code>ok</code></li> - * <li><code>stepreturn</code> - single step forward until the next <code>return</code> op code; - * stop before executing the <code>return</code> ; reply is <code>ok</code></li> - * <li><code>suspend</code> - suspend execution of the program and listen for debug commands; - * reply is <code>ok</code></li> - * <li><code>watch F::V M</code> - set a watchpoint on variable <code>V</code> in function - * <code>F</code> to magic value <code>M</code>; the magic value is a bit flag corresponding - * to read access (1), write access (2), or both (3); the magic value 0 clears the watchpoint; - * reply is <code>ok</code></li> - * <li><code>var N M</code> - return the contents of variable <code>M</code> in the control - * stack frame <code>N</code> (stack frames are indexed from 0, 0 being the oldest); - * reply is variable value</li> - * </ul> - * </p> - * - * @param request command - * @return reply - * @throws DebugException if the request fails - */ - public String sendRequest(String request) throws DebugException { - return getPDADebugTarget().sendRequest(request); - } + * Sends a request to the PDA interpreter, waits for and returns the reply. + * + * @param request command + * @return reply + * @throws DebugException if the request fails + * + * @see org.eclipse.debug.examples.core.protocol.PDATerminateCommand + * @see org.eclipse.debug.examples.core.protocol.PDAVMSuspendCommand + * @see org.eclipse.debug.examples.core.protocol.PDAVMResumeCommand + * + * @see org.eclipse.debug.examples.core.protocol.PDASuspendCommand + * @see org.eclipse.debug.examples.core.protocol.PDAResumeCommand + * @see org.eclipse.debug.examples.core.protocol.PDAStepCommand + * @see org.eclipse.debug.examples.core.protocol.PDADropFrameCommand + * + * @see org.eclipse.debug.examples.core.protocol.PDASetBreakpointCommand + * @see org.eclipse.debug.examples.core.protocol.PDAClearBreakpointCommand + * @see org.eclipse.debug.examples.core.protocol.PDAWatchCommand + * + * @see org.eclipse.debug.examples.core.protocol.PDADataCommand + * @see org.eclipse.debug.examples.core.protocol.PDASetDataCommand + * @see org.eclipse.debug.examples.core.protocol.PDAPopDataCommand + * @see org.eclipse.debug.examples.core.protocol.PDAPushDataCommand + * + * @see org.eclipse.debug.examples.core.protocol.PDAEvalCommand + * + * @see org.eclipse.debug.examples.core.protocol.PDAEventStopCommand + * + * @see org.eclipse.debug.examples.core.protocol.PDAStackCommand + * @see org.eclipse.debug.examples.core.protocol.PDAStackDepthCommand + * @see org.eclipse.debug.examples.core.protocol.PDAFrameCommand + * + * @see org.eclipse.debug.examples.core.protocol.PDASetVarCommand + * @see org.eclipse.debug.examples.core.protocol.PDAVarCommand + * @see org.eclipse.debug.examples.core.protocol.PDAChildrenCommand + * + * @see org.eclipse.debug.examples.core.protocol.PDAGroupsCommand + * @see org.eclipse.debug.examples.core.protocol.PDARegistersCommand + * + * @since 3.5 + */ + public PDACommandResult sendCommand(PDACommand command) throws DebugException { + return getPDADebugTarget().sendCommand(command); + } /** * Returns the debug target as a PDA target. diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugTarget.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugTarget.java index 6df9fad76..44437af5d 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugTarget.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugTarget.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; @@ -17,7 +18,11 @@ import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.net.UnknownHostException; -import java.util.Vector; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IMarkerDelta; @@ -29,6 +34,7 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.IBreakpointManager; import org.eclipse.debug.core.IBreakpointManagerListener; @@ -38,10 +44,22 @@ import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IMemoryBlock; import org.eclipse.debug.core.model.IProcess; import org.eclipse.debug.core.model.IThread; -import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.examples.core.pda.DebugCorePlugin; import org.eclipse.debug.examples.core.pda.breakpoints.PDALineBreakpoint; import org.eclipse.debug.examples.core.pda.breakpoints.PDARunToLineBreakpoint; +import org.eclipse.debug.examples.core.protocol.PDACommand; +import org.eclipse.debug.examples.core.protocol.PDACommandResult; +import org.eclipse.debug.examples.core.protocol.PDAEvent; +import org.eclipse.debug.examples.core.protocol.PDAEventStopCommand; +import org.eclipse.debug.examples.core.protocol.PDAExitedEvent; +import org.eclipse.debug.examples.core.protocol.PDAStartedEvent; +import org.eclipse.debug.examples.core.protocol.PDATerminateCommand; +import org.eclipse.debug.examples.core.protocol.PDAVMResumeCommand; +import org.eclipse.debug.examples.core.protocol.PDAVMResumedEvent; +import org.eclipse.debug.examples.core.protocol.PDAVMStartedEvent; +import org.eclipse.debug.examples.core.protocol.PDAVMSuspendCommand; +import org.eclipse.debug.examples.core.protocol.PDAVMSuspendedEvent; +import org.eclipse.debug.examples.core.protocol.PDAVMTerminatedEvent; /** @@ -62,17 +80,20 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr private Socket fEventSocket; private BufferedReader fEventReader; + // suspended state + private boolean fVMSuspended = false; + // terminated state private boolean fTerminated = false; // threads - private IThread[] fThreads; - private PDAThread fThread; + private Map fThreads = Collections.synchronizedMap(new LinkedHashMap()); // event dispatch job private EventDispatchJob fEventDispatch; + // event listeners - private Vector fEventListeners = new Vector(); + private List fEventListeners = Collections.synchronizedList(new ArrayList()); /** * Listens to events from the PDA VM and fires corresponding @@ -89,18 +110,28 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor) */ protected IStatus run(IProgressMonitor monitor) { - String event = ""; - while (!isTerminated() && event != null) { + String message = ""; + while (!isTerminated() && message != null) { try { - event = fEventReader.readLine(); - if (event != null) { + message = fEventReader.readLine(); + System.out.println(message); + if (message != null) { + PDAEvent event = null; + try { + event = PDAEvent.parseEvent(message); + } + catch (IllegalArgumentException e) { + DebugCorePlugin.getDefault().getLog().log( + new Status (IStatus.ERROR, "org.eclipse.debug.examples.core", "Error parsing PDA event", e)); + continue; + } Object[] listeners = fEventListeners.toArray(); for (int i = 0; i < listeners.length; i++) { ((IPDAEventListener)listeners[i]).handleEvent(event); } } } catch (IOException e) { - terminated(); + vmTerminated(); } } return Status.OK_STATUS; @@ -116,9 +147,11 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr * @param listener event listener */ public void addEventListener(IPDAEventListener listener) { - if (!fEventListeners.contains(listener)) { - fEventListeners.add(listener); - } + synchronized(fEventListeners) { + if (!fEventListeners.contains(listener)) { + fEventListeners.add(listener); + } + } } /** @@ -167,8 +200,6 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr } catch (IOException e) { requestFailed("Unable to connect to PDA VM", e); } - fThread = new PDAThread(this); - fThreads = new IThread[] {fThread}; fEventDispatch = new EventDispatchJob(); fEventDispatch.schedule(); IBreakpointManager breakpointManager = getBreakpointManager(); @@ -176,8 +207,8 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr breakpointManager.addBreakpointManagerListener(this); // initialize error hanlding to suspend on 'unimplemented instructions' // and 'no such label' errors - sendRequest("eventstop unimpinstr 1"); - sendRequest("eventstop nosuchlabel 1"); + sendCommand(new PDAEventStopCommand(PDAEventStopCommand.UNIMPINSTR, true)); + sendCommand(new PDAEventStopCommand(PDAEventStopCommand.NOSUCHLABEL, true)); } /* (non-Javadoc) @@ -190,13 +221,15 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr * @see org.eclipse.debug.core.model.IDebugTarget#getThreads() */ public IThread[] getThreads() throws DebugException { - return fThreads; + synchronized (fThreads) { + return (IThread[])fThreads.values().toArray(new IThread[fThreads.size()]); + } } /* (non-Javadoc) * @see org.eclipse.debug.core.model.IDebugTarget#hasThreads() */ public boolean hasThreads() throws DebugException { - return true; + return fThreads.size() > 0; } /* (non-Javadoc) * @see org.eclipse.debug.core.model.IDebugTarget#getName() @@ -253,14 +286,18 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr /* (non-Javadoc) * @see org.eclipse.debug.core.model.ITerminate#isTerminated() */ - public boolean isTerminated() { + public synchronized boolean isTerminated() { return fTerminated || getProcess().isTerminated(); } /* (non-Javadoc) * @see org.eclipse.debug.core.model.ITerminate#terminate() */ public void terminate() throws DebugException { - getThread().terminate(); +//#ifdef ex2 +//# // TODO: Exercise 2 - send termination request to interpreter +//#else + sendCommand(new PDATerminateCommand()); +//#endif } /* (non-Javadoc) * @see org.eclipse.debug.core.model.ISuspendResume#canResume() @@ -277,22 +314,24 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr /* (non-Javadoc) * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended() */ - public boolean isSuspended() { - return !isTerminated() && getThread().isSuspended(); + public synchronized boolean isSuspended() { + return !isTerminated() && fVMSuspended; } + /* (non-Javadoc) * @see org.eclipse.debug.core.model.ISuspendResume#resume() */ public void resume() throws DebugException { - getThread().resume(); + sendCommand(new PDAVMResumeCommand()); } /* (non-Javadoc) * @see org.eclipse.debug.core.model.ISuspendResume#suspend() */ public void suspend() throws DebugException { - getThread().suspend(); + sendCommand(new PDAVMSuspendCommand()); } + /* (non-Javadoc) * @see org.eclipse.debug.core.IBreakpointListener#breakpointAdded(org.eclipse.debug.core.model.IBreakpoint) */ @@ -368,7 +407,7 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr * Notification we have connected to the VM and it has started. * Resume the VM. */ - private void started() { + private void vmStarted(PDAVMStartedEvent event) { fireCreationEvent(); installDeferredBreakpoints(); try { @@ -391,10 +430,9 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr /** * Called when this debug target terminates. */ - private synchronized void terminated() { - fTerminated = true; - fThread = null; - fThreads = new IThread[0]; + private void vmTerminated() { + setTerminated(true); + fThreads.clear(); IBreakpointManager breakpointManager = getBreakpointManager(); breakpointManager.removeBreakpointListener(this); breakpointManager.removeBreakpointManagerListener(this); @@ -402,29 +440,58 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr removeEventListener(this); } - /** - * Returns the values on the data stack (top down) - * - * @return the values on the data stack (top down) - */ - public IValue[] getDataStack() throws DebugException { - String dataStack = sendRequest("data"); - if (dataStack != null && dataStack.length() > 0) { - String[] values = dataStack.split("\\|"); - IValue[] theValues = new IValue[values.length]; - for (int i = 0; i < values.length; i++) { - String value = values[values.length - i - 1]; - theValues[i] = new PDAStackValue(this, value, i); - } - return theValues; - } - return new IValue[0]; + private void vmResumed(PDAVMResumedEvent event) { + setVMSuspended(false); + fireResumeEvent(calcDetail(event.fReason)); + } + + private void vmSuspended(PDAVMSuspendedEvent event) { + setVMSuspended(true); + int detail = DebugEvent.UNSPECIFIED; + fireSuspendEvent(calcDetail(event.fReason)); + } + + private int calcDetail(String reason) { + if (reason.equals("breakpoint") || reason.equals("watch")) { + return DebugEvent.BREAKPOINT; + } else if (reason.equals("step")) { + return DebugEvent.STEP_OVER; + } else if (reason.equals("drop")) { + return DebugEvent.STEP_RETURN; + } else if (reason.equals("client")) { + return DebugEvent.CLIENT_REQUEST; + } else if (reason.equals("event")) { + return DebugEvent.BREAKPOINT; + } else { + return DebugEvent.UNSPECIFIED; + } + } + + private void started(PDAStartedEvent event) { + PDAThread newThread = new PDAThread(this, event.fThreadId); + fThreads.put(new Integer(event.fThreadId), newThread); + newThread.start(); + } + + private void exited(PDAExitedEvent event) { + PDAThread thread = (PDAThread)fThreads.remove(new Integer(event.fThreadId)); + if (thread != null) { + thread.exit(); + } + } + + private synchronized void setVMSuspended(boolean suspended) { + fVMSuspended = suspended; } + private synchronized void setTerminated(boolean terminated) { + fTerminated = terminated; + } + /* (non-Javadoc) * @see org.eclipse.debug.examples.core.pda.model.PDADebugElement#sendRequest(java.lang.String) */ - public String sendRequest(String request) throws DebugException { + private String sendRequest(String request) throws DebugException { synchronized (fRequestSocket) { fRequestWriter.println(request); fRequestWriter.flush(); @@ -438,6 +505,11 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr return null; } + public PDACommandResult sendCommand(PDACommand command) throws DebugException { + String response = sendRequest(command.getRequest()); + return command.createResult(response); + } + /** * When the breakpoint manager disables, remove all registered breakpoints * requests from the VM. When it enables, reinstall them. @@ -452,74 +524,45 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr } } } - - /** - * Returns whether popping the data stack is currently permitted - * - * @return whether popping the data stack is currently permitted - */ - public boolean canPop() { - try { - return !isTerminated() && isSuspended() && getDataStack().length > 0; - } catch (DebugException e) { - } - return false; - } - - /** - * Pops and returns the top of the data stack - * - * @return the top value on the stack - * @throws DebugException if the stack is empty or the request fails - */ - public IValue pop() throws DebugException { - IValue[] dataStack = getDataStack(); - if (dataStack.length > 0) { - sendRequest("popdata"); - return dataStack[0]; - } - requestFailed("Empty stack", null); - return null; - } - - /** - * Returns whether pushing a value is currently supported. - * - * @return whether pushing a value is currently supported - */ - public boolean canPush() { - return !isTerminated() && isSuspended(); - } - - /** - * Pushes a value onto the stack. - * - * @param value value to push - * @throws DebugException on failure - */ - public void push(String value) throws DebugException { - sendRequest("pushdata " + value); - } /* (non-Javadoc) * @see org.eclipse.debug.examples.core.pda.model.IPDAEventListener#handleEvent(java.lang.String) */ - public void handleEvent(String event) { - if (event.equals("started")) { - started(); - } else if (event.equals("terminated")) { - terminated(); - } + public void handleEvent(PDAEvent event) { + if (event instanceof PDAStartedEvent) { + started((PDAStartedEvent)event); + } else if (event instanceof PDAExitedEvent) { + exited((PDAExitedEvent)event); + } else if (event instanceof PDAVMStartedEvent) { + vmStarted((PDAVMStartedEvent)event); + } else if (event instanceof PDAVMTerminatedEvent) { + vmTerminated(); + } else if (event instanceof PDAVMSuspendedEvent) { + vmSuspended((PDAVMSuspendedEvent)event); + } else if (event instanceof PDAVMResumedEvent) { + vmResumed((PDAVMResumedEvent)event); + } } /** * Returns this debug target's single thread, or <code>null</code> * if terminated. * + * @param threadId ID of the thread to return, or <code>0</code> + * to return the first available thread * @return this debug target's single thread, or <code>null</code> * if terminated */ - public synchronized PDAThread getThread() { - return fThread; + public PDAThread getThread(int threadId) { + if (threadId > 0) { + return (PDAThread)fThreads.get(new Integer(threadId)); + } else { + synchronized(fThreads) { + if (fThreads.size() > 0) { + return (PDAThread)fThreads.values().iterator().next(); + } + } + } + return null; } } diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackFrame.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackFrame.java index a3cbe43c8..fbd1c7bb8 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackFrame.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackFrame.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; @@ -17,6 +18,7 @@ import org.eclipse.debug.core.model.IRegisterGroup; import org.eclipse.debug.core.model.IStackFrame; import org.eclipse.debug.core.model.IThread; import org.eclipse.debug.core.model.IVariable; +import org.eclipse.debug.examples.core.protocol.PDAFrameData; /** * PDA stack frame. @@ -37,7 +39,7 @@ public class PDAStackFrame extends PDADebugElement implements IStackFrame { * @param data frame data * @param id stack frame id (0 is the bottom of the stack) */ - public PDAStackFrame(PDAThread thread, String data, int id) { + public PDAStackFrame(PDAThread thread, PDAFrameData data, int id) { super(thread.getPDADebugTarget()); fId = id; fThread = thread; @@ -49,17 +51,13 @@ public class PDAStackFrame extends PDADebugElement implements IStackFrame { * * @param data */ - private void init(String data) { - String[] strings = data.split("\\|"); - String fileName = strings[0]; - fFileName = (new Path(fileName)).lastSegment(); - String pc = strings[1]; - fPC = Integer.parseInt(pc) + 1; - fName = strings[2]; - int numVars = strings.length - 3; - IVariable[] vars = new IVariable[numVars]; - for (int i = 0; i < numVars; i++) { - vars[i] = new PDAVariable(this, strings[i + 3]); + private void init(PDAFrameData data) { + fFileName = data.fFilePath.lastSegment(); + fPC = data.fPC + 1; + fName = data.fFunction; + IVariable[] vars = new IVariable[data.fVariables.length]; + for (int i = 0; i < data.fVariables.length; i++) { + vars[i] = new PDAVariable(this, data.fVariables[i]); } fThread.setVariables(this, vars); } @@ -247,5 +245,15 @@ public class PDAStackFrame extends PDADebugElement implements IStackFrame { return fId; } + /** + * Returns the stack frame's thread's unique identifier + * + * @return this stack frame's thread's unique identifier + * + * @since 3.5 + */ + protected int getThreadIdentifier() { + return fThread.getIdentifier(); + } } diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackValue.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackValue.java index 2f13211f4..a7909d485 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackValue.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackValue.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,15 +8,22 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IValue; +import org.eclipse.debug.core.model.IVariable; + /** * A value on the data stack */ -public class PDAStackValue extends PDAValue { - - private int fIndex; +public class PDAStackValue extends PDADebugElement implements IValue { + + final private PDAThread fThread; + final private String fValue; + final private int fIndex; /** * Constructs a value that appears on the data stack @@ -25,17 +32,55 @@ public class PDAStackValue extends PDAValue { * @param value value on the stack * @param index index on the stack */ - public PDAStackValue(PDADebugTarget target, String value, int index) { - super(target, value); + public PDAStackValue(PDAThread thread, String value, int index) { + super(thread.getDebugTarget()); + fThread = thread; + fValue = value; fIndex = index; } + public PDAThread getThread() { + return fThread; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IValue#getValueString() + */ + public String getValueString() throws DebugException { + return fValue; + } + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IValue#isAllocated() + */ + public boolean isAllocated() throws DebugException { + return true; + } + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IValue#getVariables() + */ + public IVariable[] getVariables() throws DebugException { + return new IVariable[0]; + } + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IValue#hasVariables() + */ + public boolean hasVariables() throws DebugException { + return false; + } + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IValue#getReferenceTypeName() + */ + public String getReferenceTypeName() throws DebugException { + return null; + } /* * (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object obj) { - return super.equals(obj) && ((PDAStackValue)obj).fIndex == fIndex; + return obj instanceof PDAStackValue && + ((PDAStackValue)obj).fValue.equals(fValue) && + ((PDAStackValue)obj).fIndex == fIndex; } /* * (non-Javadoc) diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAThread.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAThread.java index 6a4102ac3..e9dfd9bea 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAThread.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAThread.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,9 +8,11 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -19,13 +21,37 @@ import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.core.model.IStackFrame; import org.eclipse.debug.core.model.IThread; +import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.core.model.IVariable; +import org.eclipse.debug.examples.core.protocol.PDADataCommand; +import org.eclipse.debug.examples.core.protocol.PDADropFrameCommand; +import org.eclipse.debug.examples.core.protocol.PDAEvent; +import org.eclipse.debug.examples.core.protocol.PDAListResult; +import org.eclipse.debug.examples.core.protocol.PDANoSuchLabelEvent; +import org.eclipse.debug.examples.core.protocol.PDAPopDataCommand; +import org.eclipse.debug.examples.core.protocol.PDAPushDataCommand; +import org.eclipse.debug.examples.core.protocol.PDAResumeCommand; +import org.eclipse.debug.examples.core.protocol.PDAResumedEvent; +import org.eclipse.debug.examples.core.protocol.PDARunControlEvent; +import org.eclipse.debug.examples.core.protocol.PDAStackCommand; +import org.eclipse.debug.examples.core.protocol.PDAStackCommandResult; +import org.eclipse.debug.examples.core.protocol.PDAStepCommand; +import org.eclipse.debug.examples.core.protocol.PDASuspendCommand; +import org.eclipse.debug.examples.core.protocol.PDASuspendedEvent; +import org.eclipse.debug.examples.core.protocol.PDAUnimplementedInstructionEvent; +import org.eclipse.debug.examples.core.protocol.PDAVMResumedEvent; +import org.eclipse.debug.examples.core.protocol.PDAVMSuspendedEvent; /** * A PDA thread. A PDA VM is single threaded. */ public class PDAThread extends PDADebugElement implements IThread, IPDAEventListener { + /** + * ID of this thread as reported by PDA. + */ + private final int fThreadId; + /** * Breakpoint this thread is suspended at or <code>null</code> * if none. @@ -38,7 +64,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList private boolean fStepping = false; /** - * Wether this thread is suspended + * Whether this thread is suspended */ private boolean fSuspended = false; @@ -50,16 +76,36 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList /** * Table mapping stack frames to current variables */ - private Map fVariables = new HashMap(); + private Map fVariables = Collections.synchronizedMap(new HashMap()); /** * Constructs a new thread for the given target * * @param target VM */ - public PDAThread(PDADebugTarget target) { + public PDAThread(PDADebugTarget target, int threadId) { super(target); - getPDADebugTarget().addEventListener(this); + fThreadId = threadId; + } + + /** + * Called by the debug target after the thread is created. + * + * @since 3.5 + */ + void start() { + fireCreationEvent(); + getPDADebugTarget().addEventListener(this); + } + + /** + * Called by the debug target before the thread is removed. + * + * @since 3.5 + */ + void exit() { + getPDADebugTarget().removeEventListener(this); + fireTerminateEvent(); } /* (non-Javadoc) @@ -67,16 +113,12 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList */ public IStackFrame[] getStackFrames() throws DebugException { if (isSuspended()) { - String framesData = sendRequest("stack"); - if (framesData != null) { - String[] frames = framesData.split("#"); - IStackFrame[] theFrames = new IStackFrame[frames.length]; - for (int i = 0; i < frames.length; i++) { - String data = frames[i]; - theFrames[frames.length - i - 1] = new PDAStackFrame(this, data, i); - } - return theFrames; + PDAStackCommandResult result = (PDAStackCommandResult)sendCommand(new PDAStackCommand(fThreadId)); + IStackFrame[] frames = new IStackFrame[result.fFrames.length]; + for (int i = 0; i < result.fFrames.length; i++) { + frames[frames.length - i - 1] = new PDAStackFrame(this, result.fFrames[i], i); } + return frames; } return new IStackFrame[0]; } @@ -109,10 +151,11 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList public String getName() { return "Main thread"; } + /* (non-Javadoc) * @see org.eclipse.debug.core.model.IThread#getBreakpoints() */ - public IBreakpoint[] getBreakpoints() { + public synchronized IBreakpoint[] getBreakpoints() { if (fBreakpoint == null) { return new IBreakpoint[0]; } @@ -124,7 +167,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * * @param breakpoint breakpoint */ - public void suspendedBy(IBreakpoint breakpoint) { + public synchronized void suspendedBy(IBreakpoint breakpoint) { fBreakpoint = breakpoint; suspended(DebugEvent.BREAKPOINT); } @@ -133,7 +176,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * @see org.eclipse.debug.core.model.ISuspendResume#canResume() */ public boolean canResume() { - return isSuspended(); + return isSuspended() && !getDebugTarget().isSuspended(); } /* (non-Javadoc) * @see org.eclipse.debug.core.model.ISuspendResume#canSuspend() @@ -145,7 +188,15 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended() */ public boolean isSuspended() { - return fSuspended && !isTerminated(); + if (getDebugTarget().isTerminated()) { + return false; + } + if (getDebugTarget().isSuspended()) { + return true; + } + synchronized (this) { + return fSuspended; + } } /* (non-Javadoc) * @see org.eclipse.debug.core.model.ISuspendResume#resume() @@ -154,7 +205,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList //#ifdef ex2 //# // TODO: Exercise 2 - send resume request to interpreter //#else - sendRequest("resume"); + sendCommand(new PDAResumeCommand(fThreadId)); //#endif } /* (non-Javadoc) @@ -164,7 +215,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList //#ifdef ex2 //# // TODO: Exercise 2 - send suspend request to interpreter //#else - sendRequest("suspend"); + sendCommand(new PDASuspendCommand(fThreadId)); //#endif } /* (non-Javadoc) @@ -200,7 +251,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * @see org.eclipse.debug.core.model.IStep#stepOver() */ public void stepOver() throws DebugException { - sendRequest("step"); + sendCommand(new PDAStepCommand(fThreadId)); } /* (non-Javadoc) * @see org.eclipse.debug.core.model.IStep#stepReturn() @@ -223,11 +274,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * @see org.eclipse.debug.core.model.ITerminate#terminate() */ public void terminate() throws DebugException { - //#ifdef ex2 -//# // TODO: Exercise 2 - send termination request to interpreter - //#else - sendRequest("exit"); - //#endif + getDebugTarget().terminate(); } /** @@ -235,7 +282,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * * @param stepping whether stepping */ - private void setStepping(boolean stepping) { + private synchronized void setStepping(boolean stepping) { fStepping = stepping; } @@ -244,7 +291,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * * @param suspended whether suspended */ - private void setSuspended(boolean suspended) { + private synchronized void setSuspended(boolean suspended) { fSuspended = suspended; } @@ -254,15 +301,15 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * * @param event one of 'unimpinstr' or 'nosuchlabel' or <code>null</code> */ - private void setError(String event) { + private synchronized void setError(String event) { fErrorEvent = event; } /** - * Returns the most revent error event encountered since the last + * Returns the most recent error event encountered since the last * suspend, or <code>null</code> if none. * - * @return the most revent error event encountered since the last + * @return the most recent error event encountered since the last * suspend, or <code>null</code> if none */ public Object getError() { @@ -272,63 +319,65 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList /* (non-Javadoc) * @see org.eclipse.debug.examples.core.pda.model.IPDAEventListener#handleEvent(java.lang.String) */ - public void handleEvent(String event) { - // clear previous state - fBreakpoint = null; - setStepping(false); - - // handle events - if (event.startsWith("resumed")) { - setSuspended(false); - if (event.endsWith("step")) { - setStepping(true); - resumed(DebugEvent.STEP_OVER); - //#ifdef ex2 -//# } -//# // TODO: Exercise 2 - handle/fire "client" resume event - //#else - } else if (event.endsWith("client")) { - resumed(DebugEvent.CLIENT_REQUEST); - } - //#endif - //#ifdef ex5 -//# // TODO: Exercise 5 - handle start of drop event - //#else - else if (event.endsWith("drop")) { - resumed(DebugEvent.STEP_RETURN); - } - //#endif - } else if (event.startsWith("suspended")) { - setSuspended(true); - //#ifdef ex2 -//# // TODO: Exercise 2 - handle/fire "client" suspend event -//# if (event.endsWith("step")) { -//# suspended(DebugEvent.STEP_END); -//# } else if (event.startsWith("suspended event") && getError() != null) { -//# exceptionHit(); -//# } - //#else - if (event.endsWith("client")) { - suspended(DebugEvent.CLIENT_REQUEST); - } else if (event.endsWith("step")) { - suspended(DebugEvent.STEP_END); - } else if (event.startsWith("suspended event") && getError() != null) { - exceptionHit(); - } - //#endif - //#ifdef ex5 -//# // TODO: Exercise 5 - handle end of drop event - //#else - else if (event.endsWith("drop")) { - suspended(DebugEvent.STEP_END); - } - //#endif - } else if (event.equals("started")) { - fireCreationEvent(); - } else { - setError(event); - } - + public void handleEvent(PDAEvent _event) { + if (_event instanceof PDARunControlEvent && fThreadId == ((PDARunControlEvent)_event).fThreadId) { + PDARunControlEvent event = (PDARunControlEvent)_event; + // clear previous state + fBreakpoint = null; + setStepping(false); + + // handle events + if (event instanceof PDAResumedEvent || event instanceof PDAVMResumedEvent) { + setSuspended(false); + if ("step".equals(event.fReason)) { + setStepping(true); + resumed(DebugEvent.STEP_OVER); + //#ifdef ex2 + //# } + //# // TODO: Exercise 2 - handle/fire "client" resume event + //#else + } else if ("client".equals(event.fReason)) { + resumed(DebugEvent.CLIENT_REQUEST); + } + //#endif + //#ifdef ex5 + //# // TODO: Exercise 5 - handle start of drop event + //#else + else if ("drop".equals(event.fReason)) { + resumed(DebugEvent.STEP_RETURN); + } + //#endif + } else if (event instanceof PDASuspendedEvent || event instanceof PDAVMSuspendedEvent) { + setSuspended(true); + //#ifdef ex2 + //# // TODO: Exercise 2 - handle/fire "client" suspend event + //# if (event.endsWith("step")) { + //# suspended(DebugEvent.STEP_END); + //# } else if (event.startsWith("suspended event") && getError() != null) { + //# exceptionHit(); + //# } + //#else + if ("client".equals(event.fReason)) { + suspended(DebugEvent.CLIENT_REQUEST); + } else if ("step".equals(event.fReason)) { + suspended(DebugEvent.STEP_END); + } else if ("event".equals(event.fReason) && getError() != null) { + exceptionHit(); + } + //#endif + //#ifdef ex5 + //# // TODO: Exercise 5 - handle end of drop event + //#else + else if ("drop".equals(event.fReason)) { + suspended(DebugEvent.STEP_END); + } + //#endif + } else if (_event instanceof PDANoSuchLabelEvent || + _event instanceof PDAUnimplementedInstructionEvent) + { + setError(event.fMessage); + } + } } /** @@ -341,9 +390,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList */ private void resumed(int detail) { setError(null); - synchronized (fVariables) { - fVariables.clear(); - } + fVariables.clear(); fireResumeEvent(detail); } @@ -398,12 +445,14 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * Pops the top frame off the callstack. * * @throws DebugException + * + * @since 3.5 */ - public void pop() throws DebugException { + public void popFrame() throws DebugException { //#ifdef ex5 //# // TODO: Exercise 5 - send drop request //#else - sendRequest("drop"); + sendCommand(new PDADropFrameCommand(fThreadId)); //#endif } @@ -411,8 +460,10 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * Returns whether this thread can pop the top stack frame. * * @return whether this thread can pop the top stack frame + * + * @since 3.5 */ - public boolean canPop() { + public boolean canPopFrame() { //#ifdef ex5 //# // TODO: Exercise 5 - allow pop if there is more than 1 frame on the stack //#else @@ -423,4 +474,90 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList //#endif return false; } + + /** + * Returns the values on the data stack (top down) + * + * @return the values on the data stack (top down) + * + * @since 3.5 + */ + public IValue[] getDataStack() throws DebugException { + PDAListResult result = (PDAListResult)sendCommand(new PDADataCommand(fThreadId)); + if (result.fValues.length > 0) { + IValue[] values = new IValue[result.fValues.length]; + for (int i = 0; i < result.fValues.length; i++) { + values[values.length - i - 1] = new PDAStackValue(this, result.fValues[i], i); + } + return values; + } + return new IValue[0]; + } + + /** + * Returns whether popping the data stack is currently permitted + * + * @return whether popping the data stack is currently permitted + * + * @since 3.5 + */ + public boolean canPopData() { + try { + return !isTerminated() && isSuspended() && getDataStack().length > 0; + } catch (DebugException e) { + } + return false; + } + + /** + * Pops and returns the top of the data stack + * + * @return the top value on the stack + * @throws DebugException if the stack is empty or the request fails + * + * @since 3.5 + */ + public IValue popData() throws DebugException { + IValue[] dataStack = getDataStack(); + if (dataStack.length > 0) { + sendCommand(new PDAPopDataCommand(fThreadId)); + return dataStack[0]; + } + requestFailed("Empty stack", null); + return null; + } + + /** + * Returns whether pushing a value is currently supported. + * + * @return whether pushing a value is currently supported + * + * @since 3.5 + */ + public boolean canPushData() { + return !isTerminated() && isSuspended(); + } + + /** + * Pushes a value onto the stack. + * + * @param value value to push + * @throws DebugException on failure + * + * @since 3.5 + */ + public void pushData(String value) throws DebugException { + sendCommand(new PDAPushDataCommand(fThreadId, value)); + } + + /** + * Returns this thread's unique identifier + * + * @return this thread's unique identifier + * + * @since 3.5 + */ + public int getIdentifier() { + return fThreadId; + } } diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAValue.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAValue.java index e871004af..e3f371588 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAValue.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAValue.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,22 +8,27 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.core.model.IVariable; +import org.eclipse.debug.examples.core.protocol.PDAChildrenCommand; +import org.eclipse.debug.examples.core.protocol.PDAListResult; /** * Value of a PDA variable. */ public class PDAValue extends PDADebugElement implements IValue { - private String fValue; + final private PDAVariable fVariable; + final private String fValue; - public PDAValue(PDADebugTarget target, String value) { - super(target); + public PDAValue(PDAVariable variable, String value) { + super(variable.getStackFrame().getPDADebugTarget()); + fVariable = variable; fValue = value; } @@ -54,12 +59,26 @@ public class PDAValue extends PDADebugElement implements IValue { * @see org.eclipse.debug.core.model.IValue#getVariables() */ public IVariable[] getVariables() throws DebugException { - return new IVariable[0]; + PDAStackFrame frame = fVariable.getStackFrame(); + PDAListResult result = (PDAListResult) sendCommand( + new PDAChildrenCommand(frame.getThreadIdentifier(), frame.getIdentifier(), fVariable.getName()) ); + + IVariable[] children = new IVariable[result.fValues.length]; + for(int i = 0; i < result.fValues.length; i++) { + children[i] = new PDAVariable(frame, result.fValues[i]); + } + return children; } /* (non-Javadoc) * @see org.eclipse.debug.core.model.IValue#hasVariables() */ public boolean hasVariables() throws DebugException { + if (getVariables().length != 0) { + return true; + } + // Value with multiple words can be show as an array using logical + // structures. If the value has multiple words, it needs to indicate + // that it has children even if logical structures are not turned on. return fValue.split("\\W+").length > 1; } /* @@ -76,4 +95,15 @@ public class PDAValue extends PDADebugElement implements IValue { public int hashCode() { return fValue.hashCode(); } + + /** + * Returns the variable that this value was created for. + * + * @return The variable that this value was created for. + * + * @since 3.5 + */ + public PDAVariable getVariable() { + return fVariable; + } } diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAVariable.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAVariable.java index b0ddd6433..135a173c7 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAVariable.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAVariable.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -9,6 +9,7 @@ * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation * Wind River Systems - added support for IToggleBreakpointsTargetFactory + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; @@ -16,6 +17,9 @@ import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.core.model.IVariable; +import org.eclipse.debug.examples.core.protocol.PDACommandResult; +import org.eclipse.debug.examples.core.protocol.PDASetVarCommand; +import org.eclipse.debug.examples.core.protocol.PDAVarCommand; /** * A variable in a PDA stack frame @@ -43,8 +47,9 @@ public class PDAVariable extends PDADebugElement implements IVariable { * @see org.eclipse.debug.core.model.IVariable#getValue() */ public IValue getValue() throws DebugException { - String value = sendRequest("var " + getStackFrame().getIdentifier() + " " + getName()); - return new PDAValue(this.getPDADebugTarget(), value); + PDACommandResult result = sendCommand(new PDAVarCommand( + fFrame.getThreadIdentifier(), getStackFrame().getIdentifier(), getName())); + return new PDAValue(this, result.fResponseText); } /* (non-Javadoc) @@ -69,7 +74,8 @@ public class PDAVariable extends PDADebugElement implements IVariable { * @see org.eclipse.debug.core.model.IValueModification#setValue(java.lang.String) */ public void setValue(String expression) throws DebugException { - sendRequest("setvar " + getStackFrame().getIdentifier() + " " + getName() + " " + expression); + sendCommand(new PDASetVarCommand( + fFrame.getThreadIdentifier(), getStackFrame().getIdentifier(), getName(), expression)); fireChangeEvent(DebugEvent.CONTENT); } /* (non-Javadoc) diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDABitFieldData.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDABitFieldData.java new file mode 100644 index 000000000..116b3db72 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDABitFieldData.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.StringTokenizer; + +/** + * Object representing a bit field in the stack command results. + * + * @see PDARegistersCommand + */ +public class PDABitFieldData { + + final public String fName; + final public int fOffset; + final public int fCount; + final public Map fMnemonics; + + PDABitFieldData(String bitFieldString) { + StringTokenizer st = new StringTokenizer(bitFieldString, " "); + + fName = st.nextToken(); + fOffset = Integer.parseInt(st.nextToken()); + fCount = Integer.parseInt(st.nextToken()); + + fMnemonics = new LinkedHashMap(0); + while (st.hasMoreTokens()) { + fMnemonics.put(st.nextToken(), st.nextToken()); + } + } +}
\ No newline at end of file diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAChildrenCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAChildrenCommand.java new file mode 100644 index 000000000..e9392fafb --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAChildrenCommand.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Retrieves data stack information + * + * <pre> + * C: children {thread_id} {frame_id} {variable_name} + * R: {child variable 1}|{child variable 2}|{child variable 3}|...| + * + * Errors: + * error: invalid thread + * </pre> + */ +public class PDAChildrenCommand extends PDACommand { + + public PDAChildrenCommand(int threadId, int frameId, String name ) { + super("children " + threadId + " " + frameId + " " + name); + } + + public PDACommandResult createResult(String resultText) { + return new PDAListResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAClearBreakpointCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAClearBreakpointCommand.java new file mode 100644 index 000000000..9522b007d --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAClearBreakpointCommand.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Clears any breakpoint set on given line + * + * <pre> + * C: clear {line} + * R: ok + * </pre> + */ +public class PDAClearBreakpointCommand extends PDACommand { + + public PDAClearBreakpointCommand(int line) { + super("clear " + (line - 1)); + } + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDACommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDACommand.java new file mode 100644 index 000000000..f3ab89d7a --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDACommand.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2007, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Base class for PDA commands. Sub-classes should format the request string + * and implement the method to create the proper result object. + */ +abstract public class PDACommand { + + final private String fRequest; + + public PDACommand(String request) { + fRequest = request; + } + + /** + * Returns the request to be sent to PDA. + */ + public String getRequest() { + return fRequest; + } + + /** + * Returns the command result based on the given PDA response. This command + * uses the class type parameter as the return type to allow the compiler to + * enforce the correct command result. This class must be implemented by + * each command to create the concrete result type. + */ + abstract public PDACommandResult createResult(String resultText); +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDACommandResult.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDACommandResult.java new file mode 100644 index 000000000..737678c44 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDACommandResult.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + + +/** + * Basic command result object. This command result simply allows access to the + * PDA response. Sub-classes may override to optionally parse the response text + * and return higher-level objects. + */ +public class PDACommandResult { + + final public String fResponseText; + + public PDACommandResult(String response) { + fResponseText = response; + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDADataCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDADataCommand.java new file mode 100644 index 000000000..f3bddaad2 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDADataCommand.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Return the contents of the data stack; reply is the data from oldest to newest + * as a single string + * + * <pre> + * C: data {thread_id} + * R: {value 1}|{value 2}|{value 3}|...| + * + * Errors: + * error: invalid thread + * </pre> + */ +public class PDADataCommand extends PDACommand { + + public PDADataCommand(int threadId) { + super("data " + threadId); + } + + public PDACommandResult createResult(String resultText) { + return new PDAListResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDADropFrameCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDADropFrameCommand.java new file mode 100644 index 000000000..3955afcd0 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDADropFrameCommand.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Pops the top stack frame off the call stack setting the instruction pointer to + * the calling statement in the calling frame + * + * <pre> + * If VM running: + * C: drop {thread_id} + * R: ok + * E: resumed {thread_id} drop + * E: suspended {thread_id} drop + * + * If VM suspended: + * C: drop {thread_id} + * R: ok + * E: vmresumed drop + * E: vmsuspended {thread_id} drop + * + * Errors: + * error: invalid thread + * </pre> + */ +public class PDADropFrameCommand extends PDACommand { + + public PDADropFrameCommand(int threadId) { + super("drop " + threadId); + } + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAEvalCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAEvalCommand.java new file mode 100644 index 000000000..3a8aa7cbf --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAEvalCommand.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Causes the interperter to execute the given set of instructions. At the end + * of the evaluation the top value is poped off the stack and returned in the + * evaluation result. + * + * <pre> + * C: eval {thread_id} {instruction}%20{parameter}|{instruction}%20{parameter}|... + * R: ok + * E: resumed {thread_id} client + * E: evalresult result + * E: suspended {thread_id} eval + * + * Errors: + * error: invalid thread + * error: cannot evaluate while vm is suspended + * error: thread running + * </pre> + * + * Where event_name could be <code>unimpinstr</code> or <code>nosuchlabel</code>. + */ +public class PDAEvalCommand extends PDACommand { + + public PDAEvalCommand(int threadId, String operation) { + super("eval " + threadId + " " + operation); + } + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAEvalResultEvent.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAEvalResultEvent.java new file mode 100644 index 000000000..397eeca7b --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAEvalResultEvent.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +/** + * Eval result event generated when an evaluation has completed. + * + * <pre> + * E: evalresult {result} + * </pre> + */ +public class PDAEvalResultEvent extends PDAEvent { + + public final String fResult; + + public PDAEvalResultEvent(String message) { + super(message); + fResult = message.substring(getName(message).length() + 1); + } + + public static boolean isEventMessage(String message) { + return message.startsWith("evalresult"); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAEvent.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAEvent.java new file mode 100644 index 000000000..fdc217844 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAEvent.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +/** + * Base class for PDA events. + */ +public class PDAEvent { + public final String fMessage; + public final String fName; + + public PDAEvent(String message) { + fMessage = message; + fName = getName(message); + } + + protected String getName(String message) { + int nameEnd = message.indexOf(' '); + nameEnd = nameEnd == -1 ? message.length() : nameEnd; + return message.substring(0, nameEnd); + } + + public static PDAEvent parseEvent(String message) { + if (PDAEvalResultEvent.isEventMessage(message)) { + return new PDAEvalResultEvent(message); + } + else if (PDAExitedEvent.isEventMessage(message)) { + return new PDAExitedEvent(message); + } + else if (PDANoSuchLabelEvent.isEventMessage(message)) { + return new PDANoSuchLabelEvent(message); + } + else if (PDARegistersEvent.isEventMessage(message)) { + return new PDARegistersEvent(message); + } + else if (PDAResumedEvent.isEventMessage(message)) { + return new PDAResumedEvent(message); + } + else if (PDAStartedEvent.isEventMessage(message)) { + return new PDAStartedEvent(message); + } + else if (PDASuspendedEvent.isEventMessage(message)) { + return new PDASuspendedEvent(message); + } + else if (PDATerminatedEvent.isEventMessage(message)) { + return new PDATerminatedEvent(message); + } + else if (PDAUnimplementedInstructionEvent.isEventMessage(message)) { + return new PDAUnimplementedInstructionEvent(message); + } + else if (PDAVMResumedEvent.isEventMessage(message)) { + return new PDAVMResumedEvent(message); + } + else if (PDAVMStartedEvent.isEventMessage(message)) { + return new PDAVMStartedEvent(message); + } + else if (PDAVMSuspendedEvent.isEventMessage(message)) { + return new PDAVMSuspendedEvent(message); + } + else if (PDAExitedEvent.isEventMessage(message)) { + return new PDAExitedEvent(message); + } + else { + return new PDAEvent(message); + } + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAEventStopCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAEventStopCommand.java new file mode 100644 index 000000000..f02519cf9 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAEventStopCommand.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Optionally stop the interpreter when an error event <code>event_name</code> + * is encountered; <code>{0|1}</code> specifies stop (<code>1</code>) or + * continue (<code>0</code>). The possible events are <code>unimpinstr</code> and + * <code>nosuchlabel</code>. Reply is <code>ok</code>. When an event is encountered, + * the interpreter sends the error event (for example <code>unimlpemented instruction + * foo</code>) and corresponding suspend event (for example <code>suspended event + * unimpinstr</code>). + * + * <pre> + * C: eventstop {event_name} {0|1} + * R: ok + * ... + * E: suspended event {event_name} + * </pre> + * + * Where event_name could be <code>unimpinstr</code> or <code>nosuchlabel</code>. + */ + +public class PDAEventStopCommand extends PDACommand { + + public static final int UNIMPINSTR = 0; + public static final int NOSUCHLABEL = 1; + + public PDAEventStopCommand(int event, boolean enable) { + super("eventstop " + + (event == UNIMPINSTR ? "unimpinstr " : "nosuchlabel ") + + (enable ? "1" : "0")); + } + + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAExitedEvent.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAExitedEvent.java new file mode 100644 index 000000000..98ccaa331 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAExitedEvent.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +/** + * Exited event generated when a thread has exited. + * + * <pre> + * E: started {thread_id} + * </pre> + */ +public class PDAExitedEvent extends PDARunControlEvent { + + public PDAExitedEvent(String message) { + super(message); + } + + public static boolean isEventMessage(String message) { + return message.startsWith("exited"); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAFrameCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAFrameCommand.java new file mode 100644 index 000000000..81b0463ee --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAFrameCommand.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Retrieves command stack frame information for frame <code>frame_number</code> + * (stack frames are indexed from 0, 0 being the oldest). + * + * <pre> + * C: stack {thread_id} {frame_number} + * R: {file}|{line}|{function}|{var_1}|{var_2}|... + * + * Errors: + * error: invalid thread + * </pre> + */ +public class PDAFrameCommand extends PDACommand { + + public PDAFrameCommand(int threadId, int frameNum) { + super("frame " + threadId + " " + frameNum); + } + + + public PDACommandResult createResult(String resultText) { + return new PDAFrameCommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAFrameCommandResult.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAFrameCommandResult.java new file mode 100644 index 000000000..953acf704 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAFrameCommandResult.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + + +/** + * @see PDAFrameCommand + */ + +public class PDAFrameCommandResult extends PDACommandResult { + + /** + * Frame data return by the frame command. + */ + final public PDAFrameData fFrame; + + PDAFrameCommandResult(String response) { + super(response); + fFrame = new PDAFrameData(response); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAFrameData.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAFrameData.java new file mode 100644 index 000000000..45de9ad46 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAFrameData.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +/** + * Object representing a frame in the stack command results. + * + * @see PDAStackCommand + */ + +public class PDAFrameData { + + final public IPath fFilePath; + final public int fPC; + final public String fFunction; + final public String[] fVariables; + + PDAFrameData(String frameString) { + StringTokenizer st = new StringTokenizer(frameString, "|"); + + fFilePath = new Path(st.nextToken()); + fPC = Integer.parseInt(st.nextToken()); + fFunction = st.nextToken(); + + List variablesList = new ArrayList(); + while (st.hasMoreTokens()) { + variablesList.add(st.nextToken()); + } + fVariables = (String[])variablesList.toArray(new String[variablesList.size()]); + } +}
\ No newline at end of file diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAGroupsCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAGroupsCommand.java new file mode 100644 index 000000000..9dcffbdc8 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAGroupsCommand.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Retrieves register groups information + * + * <pre> + * C: groups + * R: {group 1}|{group 2}|{group 3}|...| + * </pre> + */ + +public class PDAGroupsCommand extends PDACommand { + + public PDAGroupsCommand() { + super("groups"); + } + + + public PDACommandResult createResult(String resultText) { + return new PDAListResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAListResult.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAListResult.java new file mode 100644 index 000000000..3ba409dd6 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAListResult.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + + +/** + * @see PDADataCommand + */ + +public class PDAListResult extends PDACommandResult { + + final public String[] fValues; + + PDAListResult(String response) { + super(response); + StringTokenizer st = new StringTokenizer(response, "|"); + List valuesList = new ArrayList(); + + while (st.hasMoreTokens()) { + String token = st.nextToken(); + if (token.length() != 0) { + valuesList.add(token); + } + } + + fValues = new String[valuesList.size()]; + for (int i = 0; i < valuesList.size(); i++) { + fValues[i] = (String)valuesList.get(i); + } + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDANoSuchLabelEvent.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDANoSuchLabelEvent.java new file mode 100644 index 000000000..11d6a1b05 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDANoSuchLabelEvent.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +/** + * No Such Label event generated when the PDA program encounters an call to a + * non-existant label in a PDA program. + * + * <pre> + * E: no such label {label} + * </pre> + */ +public class PDANoSuchLabelEvent extends PDAEvent { + + public final String fLabel; + + public PDANoSuchLabelEvent(String message) { + super(message); + fLabel = message.substring(getName(message).length() + 1); + } + + public static boolean isEventMessage(String message) { + return message.startsWith("no such label"); + } + + protected String getName(String message) { + if (isEventMessage(message)) { + return "no such label"; + } + throw new IllegalArgumentException("Invalid event: " + message); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAPopDataCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAPopDataCommand.java new file mode 100644 index 000000000..bfc7cfe9e --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAPopDataCommand.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Pops the top value from the data stack + * + * <pre> + * C: popdata {thread_id} + * R: ok + * + * Errors: + * error: invalid thread + * </pre> + */ +public class PDAPopDataCommand extends PDACommand { + + public PDAPopDataCommand(int threadId) { + super("popdata " + threadId); + } + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAPushDataCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAPushDataCommand.java new file mode 100644 index 000000000..6969d3e02 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAPushDataCommand.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Pushes the given value on top of the data stack. + * + * <pre> + * C: pushdata {thread_id} {value} + * R: ok + * + * Errors: + * error: invalid thread + * </pre> + */ + +public class PDAPushDataCommand extends PDACommand { + + public PDAPushDataCommand(int threadId, String value) { + super("pushdata " + threadId + " " + value); + } + + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDARegisterData.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDARegisterData.java new file mode 100644 index 000000000..5adfadd3f --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDARegisterData.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +/** + * Object representing a register in the registers command results. + * + * @see PDARCommand + */ + +public class PDARegisterData { + + final public String fName; + final public boolean fWritable; + final public PDABitFieldData[] fBitFields; + + PDARegisterData(String regString) { + StringTokenizer st = new StringTokenizer(regString, "|"); + + String regInfo = st.nextToken(); + StringTokenizer regSt = new StringTokenizer(regInfo, " "); + fName = regSt.nextToken(); + fWritable = Boolean.getBoolean(regSt.nextToken()); + + List bitFieldsList = new ArrayList(); + while (st.hasMoreTokens()) { + bitFieldsList.add(new PDABitFieldData(st.nextToken())); + } + fBitFields = (PDABitFieldData[])bitFieldsList.toArray(new PDABitFieldData[bitFieldsList.size()]); + } +}
\ No newline at end of file diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDARegistersCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDARegistersCommand.java new file mode 100644 index 000000000..4bdfcaa5f --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDARegistersCommand.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Retrieves registers definition information + * + * <pre> + * C: registers {group name} + * R: {register name} {true|false}|{bit field name} {start bit} {bit count} {mnemonic 1} {mnemonic 2} ...#{register name} ... + * </pre> + */ + +public class PDARegistersCommand extends PDACommand { + + public PDARegistersCommand(String group) { + super("registers " + group); + } + + + public PDACommandResult createResult(String resultText) { + return new PDARegistersCommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDARegistersCommandResult.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDARegistersCommandResult.java new file mode 100644 index 000000000..76c935341 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDARegistersCommandResult.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + + +/** + * @see PDARegistersCommand + */ + +public class PDARegistersCommandResult extends PDACommandResult { + + /** + * Array of registers returned by the registers commands. + */ + final public PDARegisterData[] fRegisters; + + PDARegistersCommandResult(String response) { + super(response); + StringTokenizer st = new StringTokenizer(response, "#"); + List regList = new ArrayList(); + + while (st.hasMoreTokens()) { + regList.add(new PDARegisterData(st.nextToken())); + } + fRegisters = (PDARegisterData[])regList.toArray(new PDARegisterData[regList.size()]); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDARegistersEvent.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDARegistersEvent.java new file mode 100644 index 000000000..8a79ade44 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDARegistersEvent.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +/** + * Registers event generated when the registers' definitions are changed in a + * program. + * + * <pre> + * E: registers + * </pre> + */ +public class PDARegistersEvent extends PDAEvent { + + public PDARegistersEvent(String message) { + super(message); + } + + public static boolean isEventMessage(String message) { + return message.startsWith("registers"); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAResumeCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAResumeCommand.java new file mode 100644 index 000000000..a7b084159 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAResumeCommand.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Resumes the execution of a single thread. Can be issued only if the virtual + * machine is running. + * + * <pre> + * C: resume {thread_id} + * R: ok + * E: resumed {thread_id} client + * + * Errors: + * error: invalid thread + * error: cannot resume thread when vm is suspended + * error: thread already running + * </pre> + */ + +public class PDAResumeCommand extends PDACommand { + + public PDAResumeCommand(int threadId) { + super("resume " + threadId); + } + + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAResumedEvent.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAResumedEvent.java new file mode 100644 index 000000000..81bd4f9d7 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAResumedEvent.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +/** + * Resumed event generated when a thread is resumed. + * + * <pre> + * E: resumed {thread_id} [reason] + * </pre> + */ +public class PDAResumedEvent extends PDARunControlEvent { + + public PDAResumedEvent(String message) { + super(message); + } + + public static boolean isEventMessage(String message) { + return message.startsWith("resumed"); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDARunControlEvent.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDARunControlEvent.java new file mode 100644 index 000000000..3590f04e5 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDARunControlEvent.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Base class for run-control events. + */ +public class PDARunControlEvent extends PDAEvent { + + public final int fThreadId; + public final String fReason; + + public PDARunControlEvent(String message) { + super(message); + fThreadId = getThreadId(message); + fReason = getStateChangeReason(message); + } + + protected int getThreadId(String message) { + int nameEnd = getName(message).length(); + if ( Character.isDigit(message.charAt(nameEnd + 1)) ) { + int threadIdEnd = message.indexOf(' ', nameEnd + 1); + threadIdEnd = threadIdEnd == -1 ? message.length() : threadIdEnd; + try { + return Integer.parseInt(message.substring(nameEnd + 1, threadIdEnd)); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid event: " + message); + } + } else { + return -1; + } + } + + protected String getStateChangeReason(String message) { + int idx = getName(message).length(); + if ( Character.isDigit(message.charAt(idx + 1)) ) { + idx = message.indexOf(' ', idx + 1); + idx = idx == -1 ? message.length() : idx + 1; + } else { + idx++; + } + if (idx >= message.length()) { + return ""; + } + + int endIdx = message.indexOf(' ', idx); + endIdx = endIdx == -1 ? message.length() : endIdx; + return message.substring(idx, endIdx); + } + + protected String getName(String message) { + int nameEnd = message.indexOf(' '); + nameEnd = nameEnd == -1 ? message.length() : nameEnd; + return message.substring(0, nameEnd); + } + + public static boolean isEventMessage(String message) { + return message.startsWith("started"); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDASetBreakpointCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDASetBreakpointCommand.java new file mode 100644 index 000000000..098507fc0 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDASetBreakpointCommand.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Sets a breakpoint at given line + * + * <pre> + * Suspend a single thread: + * C: set {line_number} 0 + * R: ok + * C: resume {thread_id} + * E: resumed {thread_id} client + * E: suspended {thread_id} breakpoint line_number + * + * Suspend the VM: + * C: set {line_number} 1 + * R: ok + * C: vmresume + * E: vmresumed client + * E: vmsuspended {thread_id} breakpoint line_number + * </pre> + */ + +public class PDASetBreakpointCommand extends PDACommand { + + public PDASetBreakpointCommand(int line, boolean stopVM) { + super("set " + + line + " " + + (stopVM ? "1" : "0")); + } + + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDASetDataCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDASetDataCommand.java new file mode 100644 index 000000000..12d8d177e --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDASetDataCommand.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Sets a data value in the data stack at the given location (the data stack is + * indexed from 0, 0 being the oldest). + * + * <pre> + * C: setdata {thread_id} {index} {value} + * R: ok + * + * Errors: + * error: invalid thread + * </pre> + */ +public class PDASetDataCommand extends PDACommand { + + public PDASetDataCommand(int threadId, int index, String value) { + super("setdata " + threadId + " " + index + " " + value); + } + + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDASetVarCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDASetVarCommand.java new file mode 100644 index 000000000..4cde68f2c --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDASetVarCommand.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Set the contents of variable <code>variable</code> from the control stack + * <code>frame_number</code> to value <code>value</code> (the control stack is + * indexed from 0, 0 being the oldest). + * + * <pre> + * C: setvar {thread_id} {frame_number} {variable} {value} + * R: ok + * + * Errors: + * error: invalid thread + * </pre> + */ + +public class PDASetVarCommand extends PDACommand { + + public PDASetVarCommand(int threadId, int frame, String variable, String value) { + super("setvar " + threadId + " " + frame + " " + variable + " " + value); + } + + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStackCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStackCommand.java new file mode 100644 index 000000000..08f6dd673 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStackCommand.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Return the contents of the control stack (program counters, function and + * variable names). The reply is control stack from oldest to newest as a single string + * <code>frame#frame#frame...#frame</code>, where each frame is a string + * <code>"filename|pc|function name|variable name|variable name|...|variable name"</code></li>. + * + * <pre> + * C: stack {thread_id} + * R: {file}|{line}|{function}|{var_1}|{var_2}|...#{file}|{line}|{function}|{var_1}|{var_2}|...#... + * + * Errors: + * error: invalid thread + * </pre> + */ + +public class PDAStackCommand extends PDACommand { + + public PDAStackCommand(int threadId) { + super("stack " + threadId); + } + + + public PDACommandResult createResult(String resultText) { + return new PDAStackCommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStackCommandResult.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStackCommandResult.java new file mode 100644 index 000000000..6562dd279 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStackCommandResult.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + + +/** + * @see PDAStackCommand + */ + +public class PDAStackCommandResult extends PDACommandResult { + + /** + * Array of frames return by the stack commands. The frames are ordered + * with the highest-level frame first. + */ + final public PDAFrameData[] fFrames; + + PDAStackCommandResult(String response) { + super(response); + StringTokenizer st = new StringTokenizer(response, "#"); + List framesList = new ArrayList(); + + while (st.hasMoreTokens()) { + framesList.add(new PDAFrameData(st.nextToken())); + } + fFrames = (PDAFrameData[])framesList.toArray(new PDAFrameData[framesList.size()]); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStackDepthCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStackDepthCommand.java new file mode 100644 index 000000000..34e40d648 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStackDepthCommand.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Retrieves command stack depth + * + * <pre> + * C: stackdepth {thread_id} + * R: {depth} + * + * Errors: + * error: invalid thread + * </pre> + */ + +public class PDAStackDepthCommand extends PDACommand { + + public PDAStackDepthCommand(int threadId) { + super("stackdepth " + threadId); + } + + + public PDACommandResult createResult(String resultText) { + return new PDAStackDepthCommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStackDepthCommandResult.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStackDepthCommandResult.java new file mode 100644 index 000000000..81bb90680 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStackDepthCommandResult.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + + +/** + * @see PDADataCommand + */ + +public class PDAStackDepthCommandResult extends PDACommandResult { + + final public int fDepth; + + PDAStackDepthCommandResult(String response) { + super(response); + int depth = 1; // default to something that won't cause NPEs + try { + depth = Integer.parseInt(response); + } catch (NumberFormatException e) {} + fDepth = depth; + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStartedEvent.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStartedEvent.java new file mode 100644 index 000000000..1a1b5cdec --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStartedEvent.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +/** + * Started event generated when a new thread is started. A started event + * is always sent for the first thread when a PDA program is started. + * + * <pre> + * E: started {thread_id} + * </pre> + */ +public class PDAStartedEvent extends PDARunControlEvent { + + public PDAStartedEvent(String message) { + super(message); + } + + public static boolean isEventMessage(String message) { + return message.startsWith("started"); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStepCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStepCommand.java new file mode 100644 index 000000000..e948cfb74 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStepCommand.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Executes next instruction + * + * <pre> + * If VM running: + * C: step {thread_id} + * R: ok + * E: resumed {thread_id} step + * E: suspended {thread_id} step + * + * If VM suspended: + * C: step {thread_id} + * R: ok + * E: vmresumed step + * E: vmsuspended {thread_id} step + * + * Errors: + * error: invalid thread + * </pre> + */ + +public class PDAStepCommand extends PDACommand { + + public PDAStepCommand(int threadId) { + super("step " + threadId); + } + + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStepReturnCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStepReturnCommand.java new file mode 100644 index 000000000..5211c90a9 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAStepReturnCommand.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Single step forward until the next <code>return</code> op code. Stop before + * executing the <code>return</code> . + * + * <pre> + * If VM running: + * C: stepreturn {thread_id} + * R: ok + * E: resumed {thread_id} client + * E: suspended {thread_id} step + * + * If VM suspended: + * C: stepreturn {thread_id} + * R: ok + * E: vmresumed client + * E: vmsuspended {thread_id} step + * + * Errors: + * error: invalid thread + * </pre> + */ + +public class PDAStepReturnCommand extends PDACommand { + + public PDAStepReturnCommand(int threadId) { + super("stepreturn " + threadId); + } + + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDASuspendCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDASuspendCommand.java new file mode 100644 index 000000000..3da5f2f53 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDASuspendCommand.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Suspends execution of a single thread. Can be issued only if the virtual + * machine is running. + * + * <pre> + * C: suspend {thread_id} + * R: ok + * E: suspended {thread_id} client + * + * Errors: + * error: invalid thread + error: vm already suspended + * error: thread already suspended + * </pre> + */ + +public class PDASuspendCommand extends PDACommand { + + public PDASuspendCommand(int threadId) { + super("suspend " + threadId); + } + + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDASuspendedEvent.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDASuspendedEvent.java new file mode 100644 index 000000000..7ed4eb330 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDASuspendedEvent.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +/** + * Suspended event generated when a thread is suspended. + * + * <pre> + * E: suspended {thread_id} [reason] + * </pre> + * + * <code>[reason]</code> is the cause of the suspension and it's optional: + * <ul> + * <li><code>breakpoint N</code> - a breakpoint at line <code>N</code> was hit</li> + * <li><code>client</code> - a client request to suspend has completed</li> + * <li><code>drop</code> - a client request to drop a frame has completed</li> + * <li><code>event E</code> - an error was encountered, where <code>E</code> is one + * of <code>unimpinstr</code> or <code>nosuchlabel</code></li> + * <li><code>step</code> - a step request has completed</li> + * <li><code>watch A F::V</code> - a watchpoint was hit for reason <code>A</code> + * (<code>read</code> or <code>write</code>), on variable <code>V</code> in + * function <code>F</code></li> + * </ul> + + */ +public class PDASuspendedEvent extends PDARunControlEvent { + + public PDASuspendedEvent(String message) { + super(message); + } + + public static boolean isEventMessage(String message) { + return message.startsWith("suspended"); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDATerminateCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDATerminateCommand.java new file mode 100644 index 000000000..1b3eabb1d --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDATerminateCommand.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Instructs the debugger to terminate. + * + * <pre> + * C: terminate + * R: ok + * E: vmterminated + * </pre> + */ + +public class PDATerminateCommand extends PDACommand { + + public PDATerminateCommand() { + super("terminate"); + } + + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDATerminatedEvent.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDATerminatedEvent.java new file mode 100644 index 000000000..7a3a55fdd --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDATerminatedEvent.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +/** + * Terminated event generated when the PDA program has ended execution. + * + * <pre> + * E: termianted + * </pre> + */ +public class PDATerminatedEvent extends PDAEvent { + + public PDATerminatedEvent(String message) { + super(message); + } + + public static boolean isEventMessage(String message) { + return message.startsWith("terminated"); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAUnimplementedInstructionEvent.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAUnimplementedInstructionEvent.java new file mode 100644 index 000000000..8c51c1ef8 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAUnimplementedInstructionEvent.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +/** + * Unimplemented Instruction event generated when the PDA program encounters + * an instruction that it does not recognize. This event is usually followed + * by a VM Suspended event. + * + * <pre> + * E: unimplemented instruction {label} + * </pre> + */ +public class PDAUnimplementedInstructionEvent extends PDAEvent { + + public final String fOperation; + + public PDAUnimplementedInstructionEvent(String message) { + super(message); + fOperation = message.substring(getName(message).length() + 1); + } + + public static boolean isEventMessage(String message) { + return message.startsWith("unimplemented instruction"); + } + + protected String getName(String message) { + if (isEventMessage(message)) { + return "unimplemented instruction"; + } + throw new IllegalArgumentException("Invalid event: " + message); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMResumeCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMResumeCommand.java new file mode 100644 index 000000000..2c2a03d3e --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMResumeCommand.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Resumes the execution of the whole virtual machine + * + * <pre> + * C: vmresume + * R: ok + * E: vmresumed client + * + * Errors: + * error: vm already running + * </pre> + */ + +public class PDAVMResumeCommand extends PDACommand { + + public PDAVMResumeCommand() { + super("vmresume"); + } + + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMResumedEvent.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMResumedEvent.java new file mode 100644 index 000000000..56fbace71 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMResumedEvent.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +/** + * VM Resumed event generated when the whole virtual machine is resumed. When + * the VM is resumed all previously suspended threads are resumed as well. + * + * <pre> + * E: vmresumed [reason] + * </pre> + * + * <code>[reason]</code> is the cause of the resume: and it's optional: + * <ul> + * <li><code>step</code> - a step request has been initiated</li> + * <li><code>client</code> - a client request to resume has been initiated</li> + * </ul> + */ +public class PDAVMResumedEvent extends PDARunControlEvent { + + public PDAVMResumedEvent(String message) { + super(message); + } + + public static boolean isEventMessage(String message) { + return message.startsWith("vmresumed"); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMStartedEvent.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMStartedEvent.java new file mode 100644 index 000000000..a98a10c55 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMStartedEvent.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +/** + * VM started event generated when the the interpreter has started (guaranteed + * to be the first event sent) + * + * <pre> + * E: vmstarted + * </pre> + */ +public class PDAVMStartedEvent extends PDAEvent { + + public PDAVMStartedEvent(String message) { + super(message); + } + + public static boolean isEventMessage(String message) { + return message.startsWith("vmstarted"); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMSuspendCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMSuspendCommand.java new file mode 100644 index 000000000..693d59a7f --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMSuspendCommand.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Suspends the execution of the whole virtual machine + * + * <pre> + * C: vmsuspend + * R: ok + * E: vmsuspended client + * + * Errors: + * error: thread already suspended + * </pre> + */ + +public class PDAVMSuspendCommand extends PDACommand { + + public PDAVMSuspendCommand() { + super("vmsuspend"); + } + + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMSuspendedEvent.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMSuspendedEvent.java new file mode 100644 index 000000000..9385fae59 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMSuspendedEvent.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +/** + * VM Suspended event generated when the virtual machine is suspended. If the VM + * is suspended as a result of a thread event (e.g. thread hitting a breakpoint), + * then the thread_id is included in the event. + * + * <pre> + * E: vmsuspended [thread_id] {reason} + * </pre> + * + * <code>{reason}</code> is the cause of the suspension: + * <ul> + * <li><code>breakpoint N</code> - a breakpoint at line <code>N</code> was hit</li> + * <li><code>client</code> - a client request to suspend has completed</li> + * <li><code>drop</code> - a client request to drop a frame has completed</li> + * <li><code>event E</code> - an error was encountered, where <code>E</code> is one + * of <code>unimpinstr</code> or <code>nosuchlabel</code></li> + * <li><code>step</code> - a step request has completed</li> + * <li><code>watch A F::V</code> - a watchpoint was hit for reason <code>A</code> + * (<code>read</code> or <code>write</code>), on variable <code>V</code> in + * function <code>F</code></li> + * </ul> + */ +public class PDAVMSuspendedEvent extends PDARunControlEvent { + + public PDAVMSuspendedEvent(String message) { + super(message); + } + + public static boolean isEventMessage(String message) { + return message.startsWith("vmsuspended"); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMTerminatedEvent.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMTerminatedEvent.java new file mode 100644 index 000000000..624afc9f5 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVMTerminatedEvent.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + +/** + * Terminated event generated when the PDA program has ended execution. + * + * <pre> + * E: termianted + * </pre> + */ +public class PDAVMTerminatedEvent extends PDAEvent { + + public PDAVMTerminatedEvent(String message) { + super(message); + } + + public static boolean isEventMessage(String message) { + return message.startsWith("vmterminated"); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVarCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVarCommand.java new file mode 100644 index 000000000..c9c0497fa --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAVarCommand.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Return the contents of variable <code>variable_name</code> in the control + * stack frame <code>frame_number</code> (stack frames are indexed from 0, 0 + * being the oldest). + * + * <pre> + * C: var {thread_id} {frame_number} {variable_name} + * R: {variable_value} + * + * Errors: + * error: invalid thread + * error: variable undefined + * </pre> + */ + +public class PDAVarCommand extends PDACommand { + + public PDAVarCommand(int threadId, int frameId, String name) { + super("var " + threadId + " " + frameId + " " + name); + } + + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAWatchCommand.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAWatchCommand.java new file mode 100644 index 000000000..f45ad0208 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/PDAWatchCommand.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.core.protocol; + + +/** + * Set a watchpoint on variable <code>variable_name</code> in function + * <code>function</code> to magic value <code>watch_operation</code>. The magic + * value is a bit flag corresponding to read access (1), write access (2), or + * both (3); the magic value 0 clears the watchpoint. + * + * <pre> + * C: watch {function}::{variable_name} {watch_operation} + * R: ok + * C: vmresume + * R: vmresumed client + * E: vmsuspended {thread_id} watch {watch_operation} {function}::{variable_name} + * </pre> + */ +public class PDAWatchCommand extends PDACommand { + + public static final int READ = 1; + public static final int WRITE = 2; + public static final int BOTH = READ | WRITE; + public static final int NONE = 0; + + public PDAWatchCommand(String function, String variable, int operation) { + super("watch " + function+ "::" + variable + " " + operation); + } + + + public PDACommandResult createResult(String resultText) { + return new PDACommandResult(resultText); + } +} diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/package.html b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/package.html new file mode 100644 index 000000000..90bdaae51 --- /dev/null +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/protocol/package.html @@ -0,0 +1,99 @@ +<!doctype html public "-//w3c//dtd html 4.0 transitional//en"> +<html> + +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +<title>PDA Interpreter Debug Protocol</title> +</head> + +<body bgcolor="#FFFFFF"> + +<p>Provides classes representing PDA protocol commands, command results and events</p> + +<h2>Package Specification</h2> + +<h3>Virtual Machine execution control</h3> +<h4>Commands</h4> +<ul> +<li>{@link PDATerminateCommand}</li> +<li>{@link PDAVMSuspendCommand}</li> +<li>{@link PDAVMResumeCommand}</li> +<li>{@link PDAEventStopCommand}</li> +</ul> +<h4>Events</h4> +<ul> +<li>{@link PDAVMStarted}</li> +<li>{@link PDAVMTerminated}</li> +<li>{@link PDAVMSuspneded}</li> +<li>{@link PDAVMResumed}</li> +<li>{@link PDAUnimplementedInstructionEvent}</li> +<li>{@link PDANoSuchLabelEvent}</li> +</ul> + +<h3>Thread execution control</h3> +<h4>Commands</h4> +<ul> +<li>{@link PDASuspendCommand}</li> +<li>{@link PDAResumeCommand}</li> +<li>{@link PDAStepCommand}</li> +<li>{@link PDADropFrameCommand}</li> +</ul> +<h4>Events</h4> +<ul> +<li>{@link PDAStarted}</li> +<li>{@link PDAExited}</li> +<li>{@link PDASuspended}</li> +<li>{@link PDAResumed}</li> +</ul> + +<h3>Breakpoints</h3> +<h4>Commands</h4> +<ul> +<li>{@link PDASetBreakpointCommand}</li> +<li>{@link PDAClearBreakpointCommand}</li> +<li>{@link PDAWatchCommand}</li> +</ul> + +<h3>Data stack</h3> +<h4>Commands</h4> +<ul> +<li>{@link PDADataCommand}</li> +<li>{@link PDASetDataCommand}</li> +<li>{@link PDAPopDataCommand}</li> +<li>{@link PDAPushDataCommand}</li> +</ul> + +<h3>Expression evaluation</h3> +<h4>Commands</h4> +<ul> +<li>{@link PDAEvalCommand}</li> +</ul> +<h4>Events</h4> +<ul> +<li>{@link PDAEvalResultEvent}</li> +</ul> + +<h3>Execution control stack</h3> +<h4>Commands</h4> +<ul> +<li>{@link PDAStackCommand}</li> +<li>{@link PDAStackDepthCommand}</li> +<li>{@link PDAFrameCommand}</li> +<li>{@link PDAVarCommand}</li> +<li>{@link PDASetVarCommand}</li> +<li>{@link PDAChildrenCommand}</li> +</ul> + +<h3>Registers</h3> +<h4>Commands</h4> +<ul> +<li>{@link PDAGroupsCommand}</li> +<li>{@link PDARegistersCommand}</li> +</ul> +<h4>Events</h4> +<ul> +<li>{@link PDARegistersEvent}</li> +</ul> + +</body> +</html> diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/PDADebugTargetContentProvider.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/PDADebugTargetContentProvider.java index ab33ae4f2..ed0c069ee 100644 --- a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/PDADebugTargetContentProvider.java +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/adapters/PDADebugTargetContentProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.ui.pda.adapters; @@ -27,7 +28,7 @@ public class PDADebugTargetContentProvider extends ElementContentProvider { * @see org.eclipse.debug.internal.ui.model.elements.ElementContentProvider#getChildCount(java.lang.Object, org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext, org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate) */ protected int getChildCount(Object element, IPresentationContext context, IViewerUpdate monitor) throws CoreException { - PDAThread thread = ((PDADebugTarget) element).getThread(); + PDAThread thread = ((PDADebugTarget) element).getThread(0); if (thread != null) { if (thread.hasStackFrames()) { return thread.getStackFrames().length; @@ -40,7 +41,7 @@ public class PDADebugTargetContentProvider extends ElementContentProvider { * @see org.eclipse.debug.internal.ui.model.elements.ElementContentProvider#hasChildren(java.lang.Object, org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext, org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate) */ protected boolean hasChildren(Object element, IPresentationContext context, IViewerUpdate monitor) throws CoreException { - PDAThread thread = ((PDADebugTarget) element).getThread(); + PDAThread thread = ((PDADebugTarget) element).getThread(0); if (thread != null) { return thread.hasStackFrames(); } @@ -52,7 +53,7 @@ public class PDADebugTargetContentProvider extends ElementContentProvider { */ protected Object[] getChildren(Object parent, int index, int length, IPresentationContext context, IViewerUpdate monitor) throws CoreException { if (context.getId().equals(IDebugUIConstants.ID_DEBUG_VIEW)) { - PDAThread thread = ((PDADebugTarget) parent).getThread(); + PDAThread thread = ((PDADebugTarget) parent).getThread(0); if (thread != null) { return getElements(thread.getStackFrames(), index, length); } diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PopFrameActionDelegate.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PopFrameActionDelegate.java index 1c13bac19..43e35dc26 100644 --- a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PopFrameActionDelegate.java +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/editor/PopFrameActionDelegate.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.ui.pda.editor; @@ -41,7 +42,7 @@ public class PopFrameActionDelegate implements IObjectActionDelegate, IActionDel //# // TODO: Exercise 5 - pop the top frame //#else try { - fThread.pop(); + fThread.popFrame(); } catch (DebugException e) { } //#endif @@ -61,7 +62,7 @@ public class PopFrameActionDelegate implements IObjectActionDelegate, IActionDel //#else fThread = (PDAThread) frame.getThread(); try { - action.setEnabled(fThread.canPop() && fThread.getTopStackFrame().equals(frame)); + action.setEnabled(fThread.canPopFrame() && fThread.getTopStackFrame().equals(frame)); } catch (DebugException e) { } return; diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/AbstractDataStackViewHandler.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/AbstractDataStackViewHandler.java index 2fd5ec826..d9a279f4b 100644 --- a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/AbstractDataStackViewHandler.java +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/AbstractDataStackViewHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008 Wind River Systems and others. + * Copyright (c) 2008, 2009 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13,9 +13,8 @@ package org.eclipse.debug.examples.ui.pda.views; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; -import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.debug.examples.core.pda.model.PDADebugElement; -import org.eclipse.debug.examples.core.pda.model.PDADebugTarget; +import org.eclipse.debug.examples.core.pda.model.PDAStackFrame; +import org.eclipse.debug.examples.core.pda.model.PDAThread; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; @@ -34,16 +33,20 @@ abstract public class AbstractDataStackViewHandler extends AbstractHandler { ISelection selection = DebugUITools.getDebugContextForEventChecked(event); if (selection instanceof IStructuredSelection) { - IStructuredSelection ss = (IStructuredSelection)selection; - if (ss.getFirstElement() instanceof IAdaptable) { - PDADebugElement element = (PDADebugElement) - ((IAdaptable)ss.getFirstElement()).getAdapter(PDADebugElement.class); - if (element != null) { - doExecute( - view, - (PDADebugTarget)element.getDebugTarget(), - HandlerUtil.getCurrentSelectionChecked(event)); - } + Object element = ((IStructuredSelection)selection).getFirstElement(); + + PDAThread thread = null; + if (element instanceof PDAThread) { + thread = (PDAThread)element; + } else if (element instanceof PDAStackFrame) { + thread = (PDAThread)((PDAStackFrame)element).getThread(); + } + + if (element != null) { + doExecute( + view, + thread, + HandlerUtil.getCurrentSelectionChecked(event)); } } } else { @@ -59,5 +62,5 @@ abstract public class AbstractDataStackViewHandler extends AbstractHandler { * @param target The current active debug target. * @param selection The current selection in view. */ - abstract protected void doExecute(DataStackView view, PDADebugTarget target, ISelection selection) throws ExecutionException; + abstract protected void doExecute(DataStackView view, PDAThread target, ISelection selection) throws ExecutionException; } diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/CanPushTester.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/CanPushTester.java index 9be29dceb..10b5acd31 100644 --- a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/CanPushTester.java +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/CanPushTester.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008 Wind River Systems and others. + * Copyright (c) 2008, 2009 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13,7 +13,8 @@ package org.eclipse.debug.examples.ui.pda.views; import org.eclipse.core.expressions.PropertyTester; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.debug.examples.core.pda.model.PDADebugElement; -import org.eclipse.debug.examples.core.pda.model.PDADebugTarget; +import org.eclipse.debug.examples.core.pda.model.PDAStackFrame; +import org.eclipse.debug.examples.core.pda.model.PDAThread; /** * Property tester for use with standard expressions to determine whether @@ -28,9 +29,15 @@ public class CanPushTester extends PropertyTester { if (receiver instanceof IAdaptable) { PDADebugElement element = (PDADebugElement) ((IAdaptable)receiver).getAdapter(PDADebugElement.class); - if (element != null) { - PDADebugTarget target = (PDADebugTarget)element.getDebugTarget(); - return target.canPush(); + PDAThread thread = null; + if (element instanceof PDAThread) { + thread = (PDAThread)element; + } else if (element instanceof PDAStackFrame) { + thread = (PDAThread)((PDAStackFrame)element).getThread(); + } + + if (thread != null) { + return thread.canPushData(); } } } diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/DataStackView.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/DataStackView.java index 5eeaa37a6..5e204755b 100644 --- a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/DataStackView.java +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/DataStackView.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -9,37 +9,39 @@ * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation * Wind River - Pawel Piech - replaced actions with handlers (bug 229219) + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) ******************************************************************************/ package org.eclipse.debug.examples.ui.pda.views; -import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugException; -import org.eclipse.debug.core.model.IDebugElement; -import org.eclipse.debug.core.model.IDebugTarget; -import org.eclipse.debug.examples.core.pda.DebugCorePlugin; -import org.eclipse.debug.examples.core.pda.model.PDADebugTarget; +import org.eclipse.debug.examples.core.pda.model.PDAStackFrame; +import org.eclipse.debug.examples.core.pda.model.PDAThread; import org.eclipse.debug.ui.AbstractDebugView; import org.eclipse.debug.ui.DebugUITools; -import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.debug.ui.contexts.DebugContextEvent; +import org.eclipse.debug.ui.contexts.IDebugContextListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchActionConstants; -import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.progress.UIJob; /** * View of the PDA VM data stack */ -public class DataStackView extends AbstractDebugView implements ISelectionListener { +public class DataStackView extends AbstractDebugView implements IDebugContextListener { - private PDADebugTarget fTarget; + private PDAThread fThread; class StackViewContentProvider implements ITreeContentProvider { @@ -47,9 +49,9 @@ public class DataStackView extends AbstractDebugView implements ISelectionListen * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) */ public Object[] getChildren(Object parentElement) { - if (parentElement instanceof PDADebugTarget) { + if (parentElement instanceof PDAThread) { try { - return ((PDADebugTarget)parentElement).getDataStack(); + return ((PDAThread)parentElement).getDataStack(); } catch (DebugException e) { } } @@ -60,10 +62,10 @@ public class DataStackView extends AbstractDebugView implements ISelectionListen * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object) */ public Object getParent(Object element) { - if (element instanceof IDebugTarget) { + if (element instanceof PDAThread) { return null; } else { - return ((IDebugElement)element).getDebugTarget(); + return fThread; } } @@ -71,10 +73,7 @@ public class DataStackView extends AbstractDebugView implements ISelectionListen * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object) */ public boolean hasChildren(Object element) { - if (element instanceof IDebugElement) { - return getChildren(element).length > 0; - } - return false; + return element instanceof PDAThread; } /* (non-Javadoc) @@ -105,7 +104,7 @@ public class DataStackView extends AbstractDebugView implements ISelectionListen TreeViewer viewer = new TreeViewer(parent); viewer.setLabelProvider(DebugUITools.newDebugModelPresentation()); viewer.setContentProvider(new StackViewContentProvider()); - getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, this); + DebugUITools.getDebugContextManager().getContextService(getSite().getWorkbenchWindow()).addDebugContextListener(this); getSite().setSelectionProvider(viewer); return viewer; } @@ -135,33 +134,40 @@ public class DataStackView extends AbstractDebugView implements ISelectionListen * @see org.eclipse.ui.IWorkbenchPart#dispose() */ public void dispose() { - getSite().getWorkbenchWindow().getSelectionService().removeSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, this); + DebugUITools.getDebugContextManager().getContextService(getSite().getWorkbenchWindow()).removeDebugContextListener(this); super.dispose(); } - /* (non-Javadoc) - * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) - */ - public void selectionChanged(IWorkbenchPart part, ISelection selection) { - update(); + + public void debugContextChanged(final DebugContextEvent event) { + new UIJob(getSite().getShell().getDisplay(), "DataStackView update") { + { + setSystem(true); + } + + public IStatus runInUIThread(IProgressMonitor monitor) { + update(event.getContext()); + return Status.OK_STATUS; + } + }.schedule(); } /** - * Updates the view for the selected target (if suspended) + * Updates the view for the selected thread (if suspended) */ - private synchronized void update() { - IAdaptable adaptable = DebugUITools.getDebugContext(); - fTarget = null; - if (adaptable != null) { - IDebugElement element = (IDebugElement) adaptable.getAdapter(IDebugElement.class); - if (element != null) { - if (element.getModelIdentifier().equals(DebugCorePlugin.ID_PDA_DEBUG_MODEL)) { - fTarget = (PDADebugTarget) element.getDebugTarget(); - } - } - } + private void update(ISelection context) { + fThread = null; + + if (context instanceof IStructuredSelection) { + Object element = ((IStructuredSelection)context).getFirstElement(); + if (element instanceof PDAThread) { + fThread = (PDAThread)element; + } else if (element instanceof PDAStackFrame) { + fThread = (PDAThread)((PDAStackFrame)element).getThread(); + } + } Object input = null; - if (fTarget != null && fTarget.isSuspended()) { - input = fTarget; + if (fThread != null && fThread.isSuspended()) { + input = fThread; } getViewer().setInput(input); getViewer().refresh(); diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/PopHandler.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/PopHandler.java index 59f00c857..1c0c5bc72 100644 --- a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/PopHandler.java +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/PopHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008 Wind River Systems and others. + * Copyright (c) 2008, 2009 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -16,7 +16,7 @@ import java.util.List; import org.eclipse.core.commands.ExecutionException; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IValue; -import org.eclipse.debug.examples.core.pda.model.PDADebugTarget; +import org.eclipse.debug.examples.core.pda.model.PDAThread; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.TreeViewer; @@ -27,28 +27,28 @@ import org.eclipse.jface.viewers.TreeViewer; */ public class PopHandler extends AbstractDataStackViewHandler { - protected void doExecute(DataStackView view, PDADebugTarget target, ISelection selection) throws ExecutionException { + protected void doExecute(DataStackView view, PDAThread thread, ISelection selection) throws ExecutionException { TreeViewer viewer = (TreeViewer)view.getViewer(); Object popee = selection instanceof IStructuredSelection ? ((IStructuredSelection)selection).getFirstElement() : null; if (popee != null) { try { - IValue[] stack = target.getDataStack(); + IValue[] stack = thread.getDataStack(); List restore = new ArrayList(); for (int i = 0; i < stack.length; i++) { Object value = stack[i]; if (popee.equals(value)) { // pop & stop - target.pop(); + thread.popData(); break; } else { // remember value to push back on - restore.add(target.pop()); + restore.add(thread.popData()); } } while (!restore.isEmpty()) { IValue value = (IValue) restore.remove(restore.size() - 1); - target.push(value.getValueString()); + thread.pushData(value.getValueString()); } } catch (DebugException e) { throw new ExecutionException("Failed to execute push command", e); diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/PushHandler.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/PushHandler.java index 306508f5a..58fbc7c0e 100644 --- a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/PushHandler.java +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/views/PushHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008 Wind River Systems and others. + * Copyright (c) 2008, 2009 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -12,7 +12,7 @@ package org.eclipse.debug.examples.ui.pda.views; import org.eclipse.core.commands.ExecutionException; import org.eclipse.debug.core.DebugException; -import org.eclipse.debug.examples.core.pda.model.PDADebugTarget; +import org.eclipse.debug.examples.core.pda.model.PDAThread; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.window.Window; @@ -22,11 +22,11 @@ import org.eclipse.jface.window.Window; */ public class PushHandler extends AbstractDataStackViewHandler { - protected void doExecute(DataStackView view, PDADebugTarget target, ISelection selection) throws ExecutionException { + protected void doExecute(DataStackView view, PDAThread thread, ISelection selection) throws ExecutionException { InputDialog dialog = new InputDialog(view.getSite().getShell(), "Specify Value", "Enter value to push", null, null); if (dialog.open() == Window.OK) { try { - target.push(dialog.getValue()); + thread.pushData(dialog.getValue()); } catch (DebugException e) { throw new ExecutionException("Failed to execute push command", e); } |