mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-01 14:15:23 +02:00
[244435] - Added registers to the PDA debugger exmple.
This commit is contained in:
parent
938067e4ce
commit
eeba5abcba
17 changed files with 1344 additions and 993 deletions
|
@ -19,12 +19,14 @@ 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.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;
|
||||
|
||||
|
@ -34,16 +36,41 @@ import java.util.regex.Pattern;
|
|||
@SuppressWarnings("serial")
|
||||
public class PDAVirtualMachine {
|
||||
|
||||
class Stack extends LinkedList<Object> {
|
||||
static class Stack extends LinkedList<Object> {
|
||||
@Override
|
||||
public Object pop() {
|
||||
return isEmpty() ? 0 : remove(size() - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
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<String, BitField> fBitFields = new LinkedHashMap<String, BitField>(0);
|
||||
int fValue;
|
||||
}
|
||||
|
||||
static class BitField {
|
||||
BitField(String name) {
|
||||
fName = name;
|
||||
}
|
||||
String fName;
|
||||
int fBitOffset;
|
||||
int fBitCount;
|
||||
Map<String, Integer> fMnemonics = new LinkedHashMap<String, Integer>(0);
|
||||
}
|
||||
|
||||
Map<String,Register> fRegisters = new LinkedHashMap<String,Register>(0);
|
||||
|
||||
class Args {
|
||||
final String[] fArgs;
|
||||
|
||||
|
@ -69,6 +96,15 @@ public class PDAVirtualMachine {
|
|||
return 0;
|
||||
}
|
||||
|
||||
boolean getNextBooleanArg() {
|
||||
String arg = getNextStringArg();
|
||||
try {
|
||||
return Boolean.parseBoolean(arg);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Object getNextIntOrStringArg() {
|
||||
String arg = getNextStringArg();
|
||||
try {
|
||||
|
@ -133,7 +169,7 @@ public class PDAVirtualMachine {
|
|||
|
||||
int fNextThreadId = 1;
|
||||
|
||||
private boolean fStarted = true;
|
||||
boolean fStarted = true;
|
||||
/**
|
||||
* The code is stored as an array of strings, each line of the source file
|
||||
* being one entry in the array.
|
||||
|
@ -144,7 +180,9 @@ public class PDAVirtualMachine {
|
|||
final Map<String, Integer> fLabels;
|
||||
|
||||
/** Each stack frame is a mapping of variable names to values. */
|
||||
class Frame extends LinkedHashMap<String, Object> {
|
||||
class Frame {
|
||||
final Map<String, Object> fLocalVariables = new LinkedHashMap<String, Object>();
|
||||
|
||||
/**
|
||||
* The name of the function in this frame
|
||||
*/
|
||||
|
@ -160,8 +198,63 @@ public class PDAVirtualMachine {
|
|||
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 = fRegisters.get(getRegisterPartOfName(name));
|
||||
if (reg == null) return;
|
||||
String bitFieldName = getBitFieldPartOfName(name);
|
||||
if (bitFieldName != null) {
|
||||
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 = bitField.fMnemonics.get(value);
|
||||
}
|
||||
if (intValue != null) {
|
||||
int bitFieldMask = 2^(bitField.fBitCount - 1);
|
||||
int registerMask = ~(bitFieldMask << bitField.fBitOffset);
|
||||
int bitFieldValue = 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 = fRegisters.get(getRegisterPartOfName(name));
|
||||
if (reg == null) return null;
|
||||
String bitFieldName = getBitFieldPartOfName(name);
|
||||
if (bitFieldName != null) {
|
||||
BitField bitField = reg.fBitFields.get(bitFieldName);
|
||||
if (bitField == null) return null;
|
||||
int bitFieldMask = 2^(bitField.fBitCount - 1);
|
||||
int registerMask = bitFieldMask << bitField.fBitOffset;
|
||||
return (reg.fValue & registerMask) >> bitField.fBitOffset;
|
||||
} else {
|
||||
return 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.
|
||||
|
@ -385,7 +478,7 @@ public class PDAVirtualMachine {
|
|||
String instruction = thread.fThreadCode[thread.fCurrentFrame.fPC];
|
||||
thread.fCurrentFrame.fPC++;
|
||||
doOneInstruction(thread, instruction);
|
||||
if (thread.fCurrentFrame.fPC > thread.fThreadCode.length) {
|
||||
if (thread.fCurrentFrame.fPC >= thread.fThreadCode.length) {
|
||||
// Thread reached end of code, exit from the thread.
|
||||
thread.fRun = false;
|
||||
} else if (thread.fStepReturn) {
|
||||
|
@ -446,6 +539,7 @@ public class PDAVirtualMachine {
|
|||
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);
|
||||
|
@ -571,15 +665,18 @@ public class PDAVirtualMachine {
|
|||
}
|
||||
Args args = new Args(tokens.toArray(new String[tokens.size()]));
|
||||
|
||||
if ("clear".equals(command)) debugClearBreakpoint(args);
|
||||
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 ("exit".equals(command)) debugExit();
|
||||
else if ("frame".equals(command)) debugFrame(args);
|
||||
else if ("groups".equals(command)) debugGroups(args);
|
||||
else if ("popdata".equals(command)) debugPop(args);
|
||||
else if ("pushdata".equals(command)) debugPush(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);
|
||||
|
@ -600,6 +697,37 @@ public class PDAVirtualMachine {
|
|||
}
|
||||
}
|
||||
|
||||
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 : thread.fFrames.get(sfnumber);
|
||||
|
||||
String varDot = var + ".";
|
||||
List<String> children = new ArrayList<String>();
|
||||
for (String localVar : frame.fLocalVariables.keySet()) {
|
||||
if (localVar.startsWith(varDot) && localVar.indexOf('.', varDot.length() + 1) == -1) {
|
||||
children.add(localVar);
|
||||
}
|
||||
}
|
||||
|
||||
StringBuffer result = new StringBuffer();
|
||||
for (String child : children) {
|
||||
result.append(child);
|
||||
result.append('|');
|
||||
}
|
||||
result.append('\n');
|
||||
|
||||
sendCommandResponse(result.toString());
|
||||
}
|
||||
|
||||
void debugClearBreakpoint(Args args) {
|
||||
int line = args.getNextIntArg();
|
||||
|
||||
|
@ -609,6 +737,43 @@ public class PDAVirtualMachine {
|
|||
|
||||
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 (Object val : thread.fStack) {
|
||||
result.append(val);
|
||||
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 = 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");
|
||||
|
@ -665,43 +830,6 @@ public class PDAVirtualMachine {
|
|||
sendDebugEvent("resumed " + thread.fID + " eval", false);
|
||||
}
|
||||
|
||||
void debugData(Args args) {
|
||||
PDAThread thread = args.getThreadArg();
|
||||
if (thread == null) {
|
||||
sendCommandResponse("error: invalid thread\n");
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuffer result = new StringBuffer();
|
||||
for (Object val : thread.fStack) {
|
||||
result.append(val);
|
||||
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 = 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 debugEventStop(Args args) {
|
||||
String event = args.getNextStringArg();
|
||||
int stop = args.getNextIntArg();
|
||||
|
@ -732,6 +860,20 @@ public class PDAVirtualMachine {
|
|||
sendCommandResponse(printFrame(frame) + "\n");
|
||||
}
|
||||
|
||||
void debugGroups(Args args) {
|
||||
TreeSet<String> groups = new TreeSet<String>();
|
||||
for (Register reg : fRegisters.values()) {
|
||||
groups.add(reg.fGroup);
|
||||
}
|
||||
StringBuffer response = new StringBuffer();
|
||||
for (String group : groups) {
|
||||
response.append(group);
|
||||
response.append('|');
|
||||
}
|
||||
response.append('\n');
|
||||
sendCommandResponse(response.toString());
|
||||
}
|
||||
|
||||
void debugPop(Args args) {
|
||||
PDAThread thread = args.getThreadArg();
|
||||
if (thread == null) {
|
||||
|
@ -755,6 +897,38 @@ public class PDAVirtualMachine {
|
|||
sendCommandResponse("ok\n");
|
||||
}
|
||||
|
||||
void debugRegisters(Args args) {
|
||||
String group = args.getNextStringArg();
|
||||
|
||||
StringBuffer response = new StringBuffer();
|
||||
for (Register reg : fRegisters.values()) {
|
||||
if (group.equals(reg.fGroup)) {
|
||||
response.append(reg.fName);
|
||||
response.append(' ');
|
||||
response.append(reg.fIsWriteable);
|
||||
for (BitField bitField : reg.fBitFields.values()) {
|
||||
response.append('|');
|
||||
response.append(bitField.fName);
|
||||
response.append(' ');
|
||||
response.append(bitField.fBitOffset);
|
||||
response.append(' ');
|
||||
response.append(bitField.fBitCount);
|
||||
response.append(' ');
|
||||
for (Map.Entry<String, Integer> mnemonicEntry : bitField.fMnemonics.entrySet()) {
|
||||
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) {
|
||||
|
@ -814,9 +988,9 @@ public class PDAVirtualMachine {
|
|||
Object val = args.getNextIntOrStringArg();
|
||||
|
||||
if (sfnumber >= thread.fFrames.size()) {
|
||||
thread.fCurrentFrame.put(var, val);
|
||||
thread.fCurrentFrame.set(var, val);
|
||||
} else {
|
||||
thread.fFrames.get(sfnumber).put(var, val);
|
||||
thread.fFrames.get(sfnumber).set(var, val);
|
||||
}
|
||||
sendCommandResponse("ok\n");
|
||||
}
|
||||
|
@ -859,9 +1033,11 @@ public class PDAVirtualMachine {
|
|||
buf.append(frame.fPC);
|
||||
buf.append('|');
|
||||
buf.append(frame.fFunction);
|
||||
for (String var : frame.keySet()) {
|
||||
buf.append('|');
|
||||
buf.append(var);
|
||||
for (String var : frame.fLocalVariables.keySet()) {
|
||||
if (var.indexOf('.') == -1) {
|
||||
buf.append('|');
|
||||
buf.append(var);
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
@ -1062,6 +1238,52 @@ public class PDAVirtualMachine {
|
|||
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 = 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 = fRegisters.get(regName);
|
||||
if (reg == null) return;
|
||||
BitField bitField = reg.fBitFields.get(bitFieldName);
|
||||
if (bitField == null) return;
|
||||
bitField.fMnemonics.put(args.getNextStringArg(), 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);
|
||||
|
@ -1095,7 +1317,7 @@ public class PDAVirtualMachine {
|
|||
String arg = args.getNextStringArg();
|
||||
if (arg.startsWith("$")) {
|
||||
String var = arg.substring(1);
|
||||
thread.fCurrentFrame.put(var, thread.fStack.pop());
|
||||
thread.fCurrentFrame.set(var, thread.fStack.pop());
|
||||
String key = thread.fCurrentFrame.fFunction + "::" + var;
|
||||
if (fWatchpoints.containsKey(key) && (fWatchpoints.get(key) & 2) != 0) {
|
||||
fSuspendVM = thread.fID + " watch write " + key;
|
||||
|
@ -1107,21 +1329,26 @@ public class PDAVirtualMachine {
|
|||
|
||||
void iPush(PDAThread thread, Args args) {
|
||||
String arg = args.getNextStringArg();
|
||||
if (arg.startsWith("$")) {
|
||||
String var = arg.substring(1);
|
||||
Object val = thread.fCurrentFrame.containsKey(var) ? thread.fCurrentFrame.get(var) : "<undefined>";
|
||||
thread.fStack.push(val);
|
||||
String key = thread.fCurrentFrame.fFunction + "::" + var;
|
||||
if (fWatchpoints.containsKey(key) && (fWatchpoints.get(key) & 1) != 0) {
|
||||
fSuspendVM = thread.fID + " watch read " + key;
|
||||
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) && (fWatchpoints.get(key) & 1) != 0) {
|
||||
fSuspendVM = thread.fID + " watch read " + key;
|
||||
}
|
||||
} else {
|
||||
Object val = arg;
|
||||
try {
|
||||
val = Integer.parseInt(arg);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
thread.fStack.push(val);
|
||||
}
|
||||
} else {
|
||||
Object val = arg;
|
||||
try {
|
||||
val = Integer.parseInt(arg);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
thread.fStack.push(val);
|
||||
|
||||
arg = args.getNextStringArg();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1137,7 +1364,7 @@ public class PDAVirtualMachine {
|
|||
|
||||
void iVar(PDAThread thread, Args args) {
|
||||
String var = args.getNextStringArg();
|
||||
thread.fCurrentFrame.put(var, 0);
|
||||
thread.fCurrentFrame.set(var, 0);
|
||||
}
|
||||
|
||||
void iInternalEndEval(PDAThread thread, Args args) {
|
||||
|
|
38
plugins/org.eclipse.dd.examples.pda/pdavm/tests/vmtest10.pda
Normal file
38
plugins/org.eclipse.dd.examples.pda/pdavm/tests/vmtest10.pda
Normal file
|
@ -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
|
|
@ -0,0 +1,8 @@
|
|||
var a
|
||||
var a.b
|
||||
var a.c
|
||||
push 1
|
||||
pop $a.b
|
||||
push $a.b
|
||||
output
|
||||
halt
|
72
plugins/org.eclipse.dd.examples.pda/samples/registers.pda
Normal file
72
plugins/org.eclipse.dd.examples.pda/samples/registers.pda
Normal file
|
@ -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
|
|
@ -1,8 +1,23 @@
|
|||
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
|
|
@ -21,7 +21,6 @@ import org.eclipse.dd.dsf.datamodel.AbstractDMEvent;
|
|||
import org.eclipse.dd.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.IExpressions;
|
||||
import org.eclipse.dd.dsf.debug.service.IStack;
|
||||
import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IResumedDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
||||
|
@ -32,7 +31,9 @@ import org.eclipse.dd.dsf.service.AbstractDsfService;
|
|||
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.examples.pda.PDAPlugin;
|
||||
import org.eclipse.dd.examples.pda.service.commands.PDAChildrenCommand;
|
||||
import org.eclipse.dd.examples.pda.service.commands.PDACommandResult;
|
||||
import org.eclipse.dd.examples.pda.service.commands.PDAListResult;
|
||||
import org.eclipse.dd.examples.pda.service.commands.PDASetVarCommand;
|
||||
import org.eclipse.dd.examples.pda.service.commands.PDAVarCommand;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
@ -163,7 +164,7 @@ public class PDAExpressions extends AbstractDsfService implements IExpressions {
|
|||
|
||||
|
||||
private PDACommandControl fCommandControl;
|
||||
private IStack fStack;
|
||||
private PDAStack fStack;
|
||||
|
||||
private CommandCache fCommandCache;
|
||||
|
||||
|
@ -188,7 +189,7 @@ public class PDAExpressions extends AbstractDsfService implements IExpressions {
|
|||
|
||||
private void doInitialize(final RequestMonitor rm) {
|
||||
fCommandControl = getServicesTracker().getService(PDACommandControl.class);
|
||||
fStack = getServicesTracker().getService(IStack.class);
|
||||
fStack = getServicesTracker().getService(PDAStack.class);
|
||||
fCommandCache = new CommandCache(getSession(), fCommandControl);
|
||||
|
||||
getSession().addServiceEventListener(this, null);
|
||||
|
@ -212,19 +213,23 @@ public class PDAExpressions extends AbstractDsfService implements IExpressions {
|
|||
|
||||
public IExpressionDMContext createExpression(IDMContext ctx, String expression) {
|
||||
// Create an expression based on the given context and string expression.
|
||||
// The PDA debugger can only evaluate variables as expressions and only
|
||||
// in context of a frame.
|
||||
PDAThreadDMContext threadCtx = DMContexts.getAncestorOfType(ctx, PDAThreadDMContext.class);
|
||||
IFrameDMContext frameCtx = DMContexts.getAncestorOfType(ctx, IFrameDMContext.class);
|
||||
if (threadCtx != null && frameCtx != null) {
|
||||
if (threadCtx != null) {
|
||||
// The PDA debugger can only evaluate variables as expressions and only
|
||||
// in context of a frame, so if a frame is not given, create a top-level frame.
|
||||
IFrameDMContext frameCtx = DMContexts.getAncestorOfType(ctx, IFrameDMContext.class);
|
||||
if (frameCtx == null) {
|
||||
frameCtx = fStack.getFrameDMContext(threadCtx, 0);
|
||||
}
|
||||
|
||||
return new ExpressionDMContext(getSession().getId(), frameCtx, expression);
|
||||
} else {
|
||||
// If the thread or a frame cannot be found in context, return an "invalid"
|
||||
// expression context, because a null return value is not allowed.
|
||||
// Evaluating an invalid expression context will always yield an
|
||||
// error.
|
||||
return new InvalidExpressionDMContext(getSession().getId(), ctx, expression);
|
||||
}
|
||||
}
|
||||
|
||||
// If the thread cannot be found in context, return an "invalid"
|
||||
// expression context, because a null return value is not allowed.
|
||||
// Evaluating an invalid expression context will always yield an
|
||||
// error.
|
||||
return new InvalidExpressionDMContext(getSession().getId(), ctx, expression);
|
||||
}
|
||||
|
||||
public void getBaseExpressions(IExpressionDMContext exprContext, DataRequestMonitor<IExpressionDMContext[]> rm) {
|
||||
|
@ -246,25 +251,99 @@ public class PDAExpressions extends AbstractDsfService implements IExpressions {
|
|||
}
|
||||
}
|
||||
|
||||
public void getSubExpressionCount(IExpressionDMContext exprCtx, DataRequestMonitor<Integer> rm) {
|
||||
PDAPlugin.failRequest(rm, NOT_SUPPORTED, "Not supported");
|
||||
public void getSubExpressionCount(final IExpressionDMContext exprCtx, final DataRequestMonitor<Integer> rm) {
|
||||
if (exprCtx instanceof ExpressionDMContext) {
|
||||
final PDAThreadDMContext threadCtx = DMContexts.getAncestorOfType(exprCtx, PDAThreadDMContext.class);
|
||||
final IFrameDMContext frameCtx = DMContexts.getAncestorOfType(exprCtx, IFrameDMContext.class);
|
||||
|
||||
// First retrieve the stack depth, needed to properly calculate
|
||||
// the frame index that is used by the PDAVarCommand.
|
||||
fStack.getStackDepth(
|
||||
frameCtx, 0,
|
||||
new DataRequestMonitor<Integer>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
// Calculate the frame index.
|
||||
int frameId = getData() - frameCtx.getLevel() - 1;
|
||||
|
||||
// Send the command to evaluate the variable.
|
||||
fCommandCache.execute(
|
||||
new PDAChildrenCommand(threadCtx, frameId, exprCtx.getExpression()),
|
||||
new DataRequestMonitor<PDAListResult>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
rm.setData(getData().fValues.length);
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
PDAPlugin.failRequest(rm, INVALID_HANDLE, "Invalid context");
|
||||
}
|
||||
}
|
||||
|
||||
public void getSubExpressions(IExpressionDMContext exprCtx, DataRequestMonitor<IExpressionDMContext[]> rm) {
|
||||
PDAPlugin.failRequest(rm, NOT_SUPPORTED, "Not supported");
|
||||
getSubExpressions(exprCtx, -1, -1, rm);
|
||||
}
|
||||
|
||||
public void getSubExpressions(IExpressionDMContext exprCtx, int startIndex, int length,
|
||||
DataRequestMonitor<IExpressionDMContext[]> rm)
|
||||
public void getSubExpressions(final IExpressionDMContext exprCtx, final int startIndexArg, final int lengthArg,
|
||||
final DataRequestMonitor<IExpressionDMContext[]> rm)
|
||||
{
|
||||
PDAPlugin.failRequest(rm, NOT_SUPPORTED, "Not supported");
|
||||
if (exprCtx instanceof ExpressionDMContext) {
|
||||
final PDAThreadDMContext threadCtx = DMContexts.getAncestorOfType(exprCtx, PDAThreadDMContext.class);
|
||||
final IFrameDMContext frameCtx = DMContexts.getAncestorOfType(exprCtx, IFrameDMContext.class);
|
||||
|
||||
// First retrieve the stack depth, needed to properly calculate
|
||||
// the frame index that is used by the PDAVarCommand.
|
||||
fStack.getStackDepth(
|
||||
frameCtx, 0,
|
||||
new DataRequestMonitor<Integer>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
// Calculate the frame index.
|
||||
int frameId = getData() - frameCtx.getLevel() - 1;
|
||||
|
||||
// Send the command to evaluate the variable.
|
||||
fCommandCache.execute(
|
||||
new PDAChildrenCommand(threadCtx, frameId, exprCtx.getExpression()),
|
||||
new DataRequestMonitor<PDAListResult>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
int start = startIndexArg > 0 ? startIndexArg : 0;
|
||||
int end = lengthArg > 0 ? (start + lengthArg) : getData().fValues.length;
|
||||
IExpressionDMContext[] contexts = new IExpressionDMContext[end - start];
|
||||
for (int i = start; i < end && i < getData().fValues.length; i++) {
|
||||
contexts[i] = new ExpressionDMContext(
|
||||
getSession().getId(), frameCtx, getData().fValues[i]);
|
||||
}
|
||||
rm.setData(contexts);
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
PDAPlugin.failRequest(rm, INVALID_HANDLE, "Invalid context");
|
||||
}
|
||||
}
|
||||
|
||||
public void getAvailableFormats(IFormattedDataDMContext dmc, DataRequestMonitor<String[]> rm) {
|
||||
// PDA debugger doesn't support formatting the expression. Natural
|
||||
// formatting is the only available option.
|
||||
rm.setData(new String[] { NATURAL_FORMAT });
|
||||
rm.done();
|
||||
public void getAvailableFormats(IFormattedDataDMContext dmc, final DataRequestMonitor<String[]> rm) {
|
||||
getFormattedExpressionValue(
|
||||
new FormattedValueDMContext(this, dmc, NATURAL_FORMAT),
|
||||
new DataRequestMonitor<FormattedValueDMData>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
try {
|
||||
Integer.parseInt(getData().getFormattedValue());
|
||||
rm.setData(new String[] { NATURAL_FORMAT, STRING_FORMAT, HEX_FORMAT, DECIMAL_FORMAT, OCTAL_FORMAT, BINARY_FORMAT });
|
||||
rm.done();
|
||||
} catch (NumberFormatException e) {
|
||||
rm.setData(new String[] { NATURAL_FORMAT, STRING_FORMAT });
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public FormattedValueDMContext getFormattedValueContext(IFormattedDataDMContext exprCtx, String formatId) {
|
||||
|
@ -275,6 +354,7 @@ public class PDAExpressions extends AbstractDsfService implements IExpressions {
|
|||
public void getFormattedExpressionValue(FormattedValueDMContext formattedCtx,
|
||||
final DataRequestMonitor<FormattedValueDMData> rm)
|
||||
{
|
||||
final String formatId = formattedCtx.getFormatID();
|
||||
final ExpressionDMContext exprCtx = DMContexts.getAncestorOfType(formattedCtx, ExpressionDMContext.class);
|
||||
if (exprCtx != null) {
|
||||
final PDAThreadDMContext threadCtx = DMContexts.getAncestorOfType(exprCtx, PDAThreadDMContext.class);
|
||||
|
@ -296,21 +376,95 @@ public class PDAExpressions extends AbstractDsfService implements IExpressions {
|
|||
new DataRequestMonitor<PDACommandResult>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
rm.setData(new FormattedValueDMData(getData().fResponseText));
|
||||
rm.done();
|
||||
if (NATURAL_FORMAT.equals(formatId) || STRING_FORMAT.equals(formatId)) {
|
||||
rm.setData(new FormattedValueDMData(getData().fResponseText));
|
||||
rm.done();
|
||||
} else {
|
||||
int result;
|
||||
try {
|
||||
int intResult = Integer.parseInt(getData().fResponseText);
|
||||
String formattedResult = "";
|
||||
if (HEX_FORMAT.equals(formatId)) {
|
||||
formattedResult = Integer.toHexString(intResult);
|
||||
StringBuffer prefix = new StringBuffer("0x");
|
||||
for (int i = 0; i < 8 - formattedResult.length(); i++) {
|
||||
prefix.append('0');
|
||||
}
|
||||
prefix.append(formattedResult);
|
||||
formattedResult = prefix.toString();
|
||||
} else if (OCTAL_FORMAT.equals(formatId)) {
|
||||
formattedResult = Integer.toOctalString(intResult);
|
||||
StringBuffer prefix = new StringBuffer("0c");
|
||||
for (int i = 0; i < 16 - formattedResult.length(); i++) {
|
||||
prefix.append('0');
|
||||
}
|
||||
prefix.append(formattedResult);
|
||||
formattedResult = prefix.toString();
|
||||
} else if (BINARY_FORMAT.equals(formatId)) {
|
||||
formattedResult = Integer.toBinaryString(intResult);
|
||||
StringBuffer prefix = new StringBuffer("0b");
|
||||
for (int i = 0; i < 32 - formattedResult.length(); i++) {
|
||||
prefix.append('0');
|
||||
}
|
||||
prefix.append(formattedResult);
|
||||
formattedResult = prefix.toString();
|
||||
} else if (DECIMAL_FORMAT.equals(formatId)) {
|
||||
formattedResult = Integer.toString(intResult);
|
||||
} else {
|
||||
PDAPlugin.failRequest(rm, INVALID_HANDLE, "Invalid format");
|
||||
}
|
||||
rm.setData(new FormattedValueDMData(formattedResult));
|
||||
rm.done();
|
||||
} catch (NumberFormatException e) {
|
||||
PDAPlugin.failRequest(rm, REQUEST_FAILED, "Cannot format value");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
PDAPlugin.failRequest(rm, INVALID_HANDLE, "Invalid expression context " + formattedCtx);
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void writeExpression(final IExpressionDMContext exprCtx, final String exprValue, String formatId,
|
||||
final RequestMonitor rm)
|
||||
{
|
||||
writeExpression(exprCtx, exprValue, formatId, true, rm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to write an expression, with an additional parameter to suppress
|
||||
* issuing of the expression changed event.
|
||||
* @see IExpressions#writeExpression(org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext, String, String, RequestMonitor)
|
||||
*/
|
||||
public void writeExpression(final IExpressionDMContext exprCtx, String formattedExprValue, String formatId,
|
||||
final boolean sendEvent, final RequestMonitor rm)
|
||||
{
|
||||
String value = null;
|
||||
try {
|
||||
int intValue = 0;
|
||||
if (HEX_FORMAT.equals(formatId)) {
|
||||
if (formattedExprValue.startsWith("0x")) formattedExprValue = formattedExprValue.substring(2);
|
||||
value = Integer.toString( Integer.parseInt(formattedExprValue, 16) );
|
||||
} else if (DECIMAL_FORMAT.equals(formatId)) {
|
||||
value = Integer.toString( Integer.parseInt(formattedExprValue, 10) );
|
||||
} else if (OCTAL_FORMAT.equals(formatId)) {
|
||||
if (formattedExprValue.startsWith("0c")) formattedExprValue = formattedExprValue.substring(2);
|
||||
value = Integer.toString( Integer.parseInt(formattedExprValue, 8) );
|
||||
} else if (BINARY_FORMAT.equals(formatId)) {
|
||||
if (formattedExprValue.startsWith("0b")) formattedExprValue = formattedExprValue.substring(2);
|
||||
value = Integer.toString( Integer.parseInt(formattedExprValue, 2) );
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
PDAPlugin.failRequest(rm, INVALID_HANDLE, "Value not formatted properly");
|
||||
}
|
||||
|
||||
final String exprValue = value != null ? value : formattedExprValue;
|
||||
|
||||
|
||||
if (exprCtx instanceof ExpressionDMContext) {
|
||||
final PDAThreadDMContext threadCtx = DMContexts.getAncestorOfType(exprCtx, PDAThreadDMContext.class);
|
||||
final IFrameDMContext frameCtx = DMContexts.getAncestorOfType(exprCtx, IFrameDMContext.class);
|
||||
|
@ -331,7 +485,13 @@ public class PDAExpressions extends AbstractDsfService implements IExpressions {
|
|||
new DataRequestMonitor<PDACommandResult>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
getSession().dispatchEvent(new ExpressionChangedDMEvent(exprCtx), getProperties());
|
||||
if (sendEvent) {
|
||||
getSession().dispatchEvent(new ExpressionChangedDMEvent(exprCtx), getProperties());
|
||||
}
|
||||
// An expression changed, clear the cache corresponding to
|
||||
// this event. Since the var evaluate commands, use the thread
|
||||
// context, we have to clear all the cache entries for that thread.
|
||||
fCommandCache.reset(DMContexts.getAncestorOfType(exprCtx, PDAThreadDMContext.class));
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
|
@ -339,7 +499,6 @@ public class PDAExpressions extends AbstractDsfService implements IExpressions {
|
|||
});
|
||||
} else {
|
||||
PDAPlugin.failRequest(rm, INVALID_HANDLE, "Invalid expression context " + exprCtx);
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -352,7 +511,6 @@ public class PDAExpressions extends AbstractDsfService implements IExpressions {
|
|||
getFormattedExpressionValue((FormattedValueDMContext) dmc, (DataRequestMonitor<FormattedValueDMData>) rm);
|
||||
} else {
|
||||
PDAPlugin.failRequest(rm, INVALID_HANDLE, "Unknown DMC type");
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -362,7 +520,7 @@ public class PDAExpressions extends AbstractDsfService implements IExpressions {
|
|||
// will fail. Also reset the cache unless it was a step command.
|
||||
fCommandCache.setContextAvailable(e.getDMContext(), false);
|
||||
if (!e.getReason().equals(StateChangeReason.STEP)) {
|
||||
fCommandCache.reset();
|
||||
fCommandCache.reset(e.getDMContext());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,6 +529,15 @@ public class PDAExpressions extends AbstractDsfService implements IExpressions {
|
|||
public void eventDispatched(ISuspendedDMEvent e) {
|
||||
// Enable sending commands to target and clear the cache.
|
||||
fCommandCache.setContextAvailable(e.getDMContext(), true);
|
||||
fCommandCache.reset();
|
||||
fCommandCache.reset(e.getDMContext());
|
||||
}
|
||||
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(ExpressionChangedDMEvent e) {
|
||||
// An expression changed, clear the cache corresponding to
|
||||
// this event. Since the var evaluate commands, use the thread
|
||||
// context, we have to clear all the cache entries for that thread.
|
||||
fCommandCache.reset(DMContexts.getAncestorOfType(e.getDMContext(), PDAThreadDMContext.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -445,6 +445,13 @@ public class PDAStack extends AbstractDsfService implements IStack2 {
|
|||
PDAPlugin.failRequest(rm, IDsfStatusConstants.INVALID_HANDLE, "Unknown context type");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a frame context for the given thread and level;
|
||||
*/
|
||||
public IFrameDMContext getFrameDMContext(PDAThreadDMContext thread, int level) {
|
||||
return new FrameDMContext(getSession().getId(), thread, level);
|
||||
}
|
||||
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(IResumedDMEvent e) {
|
||||
|
@ -452,7 +459,7 @@ public class PDAStack extends AbstractDsfService implements IStack2 {
|
|||
// fail. Also reset the cache unless it was a step command.
|
||||
fCommandCache.setContextAvailable(e.getDMContext(), false);
|
||||
if (!e.getReason().equals(StateChangeReason.STEP)) {
|
||||
fCommandCache.reset();
|
||||
fCommandCache.reset(e.getDMContext());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -461,6 +468,6 @@ public class PDAStack extends AbstractDsfService implements IStack2 {
|
|||
public void eventDispatched(ISuspendedDMEvent e) {
|
||||
// Enable sending commands to target and clear the cache.
|
||||
fCommandCache.setContextAvailable(e.getDMContext(), true);
|
||||
fCommandCache.reset();
|
||||
fCommandCache.reset(e.getDMContext());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*******************************************************************************
|
||||
* 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.dd.examples.pda.service.commands;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
|
||||
/**
|
||||
* Object representing a bit field in the stack command results.
|
||||
*
|
||||
* @see PDARegistersCommand
|
||||
*/
|
||||
@Immutable
|
||||
public class PDABitField {
|
||||
|
||||
final public String fName;
|
||||
final public int fOffset;
|
||||
final public int fCount;
|
||||
final public Map<String, String> fMnemonics;
|
||||
|
||||
PDABitField(String bitFieldString) {
|
||||
StringTokenizer st = new StringTokenizer(bitFieldString, " ");
|
||||
|
||||
fName = st.nextToken();
|
||||
fOffset = Integer.parseInt(st.nextToken());
|
||||
fCount = Integer.parseInt(st.nextToken());
|
||||
|
||||
fMnemonics = new LinkedHashMap<String, String>(0);
|
||||
while (st.hasMoreTokens()) {
|
||||
fMnemonics.put(st.nextToken(), st.nextToken());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*******************************************************************************
|
||||
* 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.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAThreadDMContext;
|
||||
|
||||
/**
|
||||
* 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>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDAChildrenCommand extends AbstractPDACommand<PDAListResult> {
|
||||
|
||||
public PDAChildrenCommand(PDAThreadDMContext thread, int frameId, String name ) {
|
||||
super(thread, "children " + thread.getID() + " " + frameId + " " + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PDAListResult createResult(String resultText) {
|
||||
return new PDAListResult(resultText);
|
||||
}
|
||||
}
|
|
@ -25,14 +25,14 @@ import org.eclipse.dd.examples.pda.service.PDAThreadDMContext;
|
|||
* </pre>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDADataCommand extends AbstractPDACommand<PDADataCommandResult> {
|
||||
public class PDADataCommand extends AbstractPDACommand<PDAListResult> {
|
||||
|
||||
public PDADataCommand(PDAThreadDMContext thread) {
|
||||
super(thread, "data " + thread.getID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PDADataCommandResult createResult(String resultText) {
|
||||
return new PDADataCommandResult(resultText);
|
||||
public PDAListResult createResult(String resultText) {
|
||||
return new PDAListResult(resultText);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*******************************************************************************
|
||||
* 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.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Retrieves register groups information
|
||||
*
|
||||
* <pre>
|
||||
* C: groups
|
||||
* R: {group 1}|{group 2}|{group 3}|...|
|
||||
* </pre>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDAGroupsCommand extends AbstractPDACommand<PDAListResult> {
|
||||
|
||||
public PDAGroupsCommand(PDAVirtualMachineDMContext context) {
|
||||
super(context, "groups");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PDAListResult createResult(String resultText) {
|
||||
return new PDAListResult(resultText);
|
||||
}
|
||||
}
|
|
@ -21,11 +21,11 @@ import org.eclipse.dd.dsf.concurrent.Immutable;
|
|||
* @see PDADataCommand
|
||||
*/
|
||||
@Immutable
|
||||
public class PDADataCommandResult extends PDACommandResult {
|
||||
public class PDAListResult extends PDACommandResult {
|
||||
|
||||
final public String[] fValues;
|
||||
|
||||
PDADataCommandResult(String response) {
|
||||
PDAListResult(String response) {
|
||||
super(response);
|
||||
StringTokenizer st = new StringTokenizer(response, "|");
|
||||
List<String> valuesList = new ArrayList<String>();
|
||||
|
@ -33,7 +33,7 @@ public class PDADataCommandResult extends PDACommandResult {
|
|||
while (st.hasMoreTokens()) {
|
||||
String token = st.nextToken();
|
||||
if (token.length() != 0) {
|
||||
valuesList.add(st.nextToken());
|
||||
valuesList.add(token);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*******************************************************************************
|
||||
* 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.dd.examples.pda.service.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
|
||||
/**
|
||||
* Object representing a register in the registers command results.
|
||||
*
|
||||
* @see PDARCommand
|
||||
*/
|
||||
@Immutable
|
||||
public class PDARegister {
|
||||
|
||||
final public String fName;
|
||||
final public boolean fWritable;
|
||||
final public PDABitField[] fBitFields;
|
||||
|
||||
PDARegister(String regString) {
|
||||
StringTokenizer st = new StringTokenizer(regString, "|");
|
||||
|
||||
String regInfo = st.nextToken();
|
||||
StringTokenizer regSt = new StringTokenizer(regInfo, " ");
|
||||
fName = regSt.nextToken();
|
||||
fWritable = Boolean.parseBoolean(regSt.nextToken());
|
||||
|
||||
List<PDABitField> bitFieldsList = new ArrayList<PDABitField>();
|
||||
while (st.hasMoreTokens()) {
|
||||
bitFieldsList.add(new PDABitField(st.nextToken()));
|
||||
}
|
||||
fBitFields = bitFieldsList.toArray(new PDABitField[bitFieldsList.size()]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*******************************************************************************
|
||||
* 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.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAThreadDMContext;
|
||||
|
||||
/**
|
||||
* 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>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDARegistersCommand extends AbstractPDACommand<PDARegistersCommandResult> {
|
||||
|
||||
public PDARegistersCommand(PDAThreadDMContext context, String group) {
|
||||
super(context, "registers " + group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PDARegistersCommandResult createResult(String resultText) {
|
||||
return new PDARegistersCommandResult(resultText);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*******************************************************************************
|
||||
* 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.dd.examples.pda.service.commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
|
||||
|
||||
/**
|
||||
* @see PDARegistersCommand
|
||||
*/
|
||||
@Immutable
|
||||
public class PDARegistersCommandResult extends PDACommandResult {
|
||||
|
||||
/**
|
||||
* Array of registers returned by the registers commands.
|
||||
*/
|
||||
final public PDARegister[] fRegisters;
|
||||
|
||||
PDARegistersCommandResult(String response) {
|
||||
super(response);
|
||||
StringTokenizer st = new StringTokenizer(response, "#");
|
||||
List<PDARegister> regList = new ArrayList<PDARegister>();
|
||||
|
||||
while (st.hasMoreTokens()) {
|
||||
regList.add(new PDARegister(st.nextToken()));
|
||||
}
|
||||
fRegisters = regList.toArray(new PDARegister[regList.size()]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*******************************************************************************
|
||||
* 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.dd.tests.pda.service.command;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.eclipse.dd.examples.pda.PDAPlugin;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class Test10 extends CommandControlTestsBase {
|
||||
|
||||
@BeforeClass
|
||||
public static void setProgram() {
|
||||
File programFile = PDAPlugin.getFileInPlugin(new Path("pdavm/tests/vmtest10.pda"));
|
||||
|
||||
fProgram = programFile.getPath();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisters() throws Throwable {
|
||||
expectEvent("started 1");
|
||||
// run to the end of register definitions
|
||||
sendCommand("set 10 1");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("registers");
|
||||
expectEvent("registers");
|
||||
expectEvent("registers");
|
||||
expectEvent("registers");
|
||||
expectEvent("registers");
|
||||
expectEvent("registers");
|
||||
expectEvent("registers");
|
||||
expectEvent("registers");
|
||||
expectEvent("registers");
|
||||
expectEvent("vmsuspended 1 breakpoint 10");
|
||||
|
||||
// Test the definitions commands
|
||||
sendCommand("groups", "group1|group2|");
|
||||
sendCommand("registers group1", "reg1 true|field1 0 2 |field2 2 2 zero 0 one 1 two 2 three 3 #reg2 false#");
|
||||
sendCommand("registers group2", "reg3 true#");
|
||||
|
||||
// Run to the end of the program
|
||||
sendCommand("set 37 1");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectOutput("1");
|
||||
expectOutput("2");
|
||||
expectOutput("0");
|
||||
expectOutput("4");
|
||||
expectOutput("0");
|
||||
expectOutput("0");
|
||||
expectOutput("2");
|
||||
expectOutput("8");
|
||||
expectEvent("vmsuspended 1 breakpoint 37");
|
||||
|
||||
// Test var get/set commands
|
||||
sendCommand("var 1 1 $reg1", "8");
|
||||
sendCommand("var 1 1 $reg1.field1", "0");
|
||||
sendCommand("var 1 1 $reg1.field2", "2");
|
||||
sendCommand("setvar 1 1 $reg1.field2 3");
|
||||
sendCommand("var 1 1 $reg1.field2", "3");
|
||||
sendCommand("setvar 1 1 $reg1 1");
|
||||
sendCommand("var 1 1 $reg1", "1");
|
||||
|
||||
// exit
|
||||
sendCommand("exit");
|
||||
expectEvent("terminated");
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue