mspsim motes now implements new WatchpointMote interface, simplified code
This commit is contained in:
parent
088f2e12a8
commit
2e583c733e
4 changed files with 274 additions and 440 deletions
|
@ -32,10 +32,10 @@
|
||||||
package se.sics.cooja.mspmote;
|
package se.sics.cooja.mspmote;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import se.sics.cooja.MoteInterfaceHandler;
|
|
||||||
import se.sics.cooja.Simulation;
|
import se.sics.cooja.Simulation;
|
||||||
import se.sics.cooja.interfaces.*;
|
|
||||||
import se.sics.mspsim.platform.esb.ESBNode;
|
import se.sics.mspsim.platform.esb.ESBNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -31,12 +31,13 @@
|
||||||
|
|
||||||
package se.sics.cooja.mspmote;
|
package se.sics.cooja.mspmote;
|
||||||
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.Hashtable;
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
@ -56,14 +57,12 @@ import se.sics.cooja.interfaces.IPAddress;
|
||||||
import se.sics.cooja.motes.AbstractEmulatedMote;
|
import se.sics.cooja.motes.AbstractEmulatedMote;
|
||||||
import se.sics.cooja.mspmote.interfaces.MspSerial;
|
import se.sics.cooja.mspmote.interfaces.MspSerial;
|
||||||
import se.sics.cooja.mspmote.plugins.CodeVisualizerSkin;
|
import se.sics.cooja.mspmote.plugins.CodeVisualizerSkin;
|
||||||
import se.sics.cooja.mspmote.plugins.MspBreakpointContainer;
|
import se.sics.cooja.mspmote.plugins.MspBreakpoint;
|
||||||
import se.sics.cooja.plugins.BufferListener.BufferAccess;
|
|
||||||
import se.sics.cooja.plugins.Visualizer;
|
import se.sics.cooja.plugins.Visualizer;
|
||||||
import se.sics.mspsim.cli.CommandContext;
|
import se.sics.mspsim.cli.CommandContext;
|
||||||
import se.sics.mspsim.cli.CommandHandler;
|
import se.sics.mspsim.cli.CommandHandler;
|
||||||
import se.sics.mspsim.cli.LineListener;
|
import se.sics.mspsim.cli.LineListener;
|
||||||
import se.sics.mspsim.cli.LineOutputStream;
|
import se.sics.mspsim.cli.LineOutputStream;
|
||||||
import se.sics.mspsim.core.CPUMonitor;
|
|
||||||
import se.sics.mspsim.core.EmulationException;
|
import se.sics.mspsim.core.EmulationException;
|
||||||
import se.sics.mspsim.core.MSP430;
|
import se.sics.mspsim.core.MSP430;
|
||||||
import se.sics.mspsim.core.MSP430Constants;
|
import se.sics.mspsim.core.MSP430Constants;
|
||||||
|
@ -103,15 +102,11 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
||||||
private int heapStartAddress;
|
private int heapStartAddress;
|
||||||
private StackOverflowObservable stackOverflowObservable = new StackOverflowObservable();
|
private StackOverflowObservable stackOverflowObservable = new StackOverflowObservable();
|
||||||
|
|
||||||
private MspBreakpointContainer breakpointsContainer;
|
|
||||||
|
|
||||||
public MspMote() {
|
public MspMote() {
|
||||||
myMoteType = null;
|
myMoteType = null;
|
||||||
myCpu = null;
|
myCpu = null;
|
||||||
myMemory = null;
|
myMemory = null;
|
||||||
myMoteInterfaceHandler = null;
|
myMoteInterfaceHandler = null;
|
||||||
|
|
||||||
/* Scheduled from setConfigXML */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MspMote(MspMoteType moteType, Simulation simulation) {
|
public MspMote(MspMoteType moteType, Simulation simulation) {
|
||||||
|
@ -130,9 +125,8 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
||||||
/* TODO Setup COOJA-specific window manager */
|
/* TODO Setup COOJA-specific window manager */
|
||||||
registry.registerComponent("windowManager", new JFrameWindowManager());
|
registry.registerComponent("windowManager", new JFrameWindowManager());
|
||||||
|
|
||||||
/* Create watchpoint container */
|
|
||||||
try {
|
try {
|
||||||
breakpointsContainer = new MspBreakpointContainer(this, ((MspMoteType)getType()).getFirmwareDebugInfo());
|
debuggingInfo = ((MspMoteType)getType()).getFirmwareDebugInfo();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw (RuntimeException) new RuntimeException("Error: " + e.getMessage()).initCause(e);
|
throw (RuntimeException) new RuntimeException("Error: " + e.getMessage()).initCause(e);
|
||||||
}
|
}
|
||||||
|
@ -300,7 +294,6 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
||||||
|
|
||||||
if (stopNextInstruction) {
|
if (stopNextInstruction) {
|
||||||
stopNextInstruction = false;
|
stopNextInstruction = false;
|
||||||
/*sendCLICommandAndPrint("trace 1000");*/ /* TODO Enable */
|
|
||||||
scheduleNextWakeup(t);
|
scheduleNextWakeup(t);
|
||||||
throw new RuntimeException("MSPSim requested simulation stop");
|
throw new RuntimeException("MSPSim requested simulation stop");
|
||||||
}
|
}
|
||||||
|
@ -333,6 +326,10 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
||||||
/*logger.debug(t + ": Schedule next wakeup at " + nextExecute);*/
|
/*logger.debug(t + ": Schedule next wakeup at " + nextExecute);*/
|
||||||
scheduleNextWakeup(nextExecute);
|
scheduleNextWakeup(nextExecute);
|
||||||
|
|
||||||
|
if (stopNextInstruction) {
|
||||||
|
stopNextInstruction = false;
|
||||||
|
throw new RuntimeException("MSPSim requested simulation stop");
|
||||||
|
}
|
||||||
|
|
||||||
/* XXX TODO Reimplement stack monitoring using MSPSim internals */
|
/* XXX TODO Reimplement stack monitoring using MSPSim internals */
|
||||||
/*if (monitorStackUsage) {
|
/*if (monitorStackUsage) {
|
||||||
|
@ -391,9 +388,8 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
||||||
myMoteInterfaceHandler = createMoteInterfaceHandler();
|
myMoteInterfaceHandler = createMoteInterfaceHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create watchpoint container */
|
|
||||||
try {
|
try {
|
||||||
breakpointsContainer = new MspBreakpointContainer(this, ((MspMoteType)getType()).getFirmwareDebugInfo());
|
debuggingInfo = ((MspMoteType)getType()).getFirmwareDebugInfo();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw (RuntimeException) new RuntimeException("Error: " + e.getMessage()).initCause(e);
|
throw (RuntimeException) new RuntimeException("Error: " + e.getMessage()).initCause(e);
|
||||||
}
|
}
|
||||||
|
@ -404,7 +400,7 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
||||||
if (name.equals("motetype_identifier")) {
|
if (name.equals("motetype_identifier")) {
|
||||||
/* Ignored: handled by simulation */
|
/* Ignored: handled by simulation */
|
||||||
} else if ("breakpoints".equals(element.getName())) {
|
} else if ("breakpoints".equals(element.getName())) {
|
||||||
breakpointsContainer.setConfigXML(element.getChildren(), visAvailable);
|
setWatchpointConfigXML(element.getChildren(), visAvailable);
|
||||||
} else if (name.equals("interface_config")) {
|
} else if (name.equals("interface_config")) {
|
||||||
String intfClass = element.getText().trim();
|
String intfClass = element.getText().trim();
|
||||||
if (intfClass.equals("se.sics.cooja.mspmote.interfaces.MspIPAddress")) {
|
if (intfClass.equals("se.sics.cooja.mspmote.interfaces.MspIPAddress")) {
|
||||||
|
@ -440,7 +436,7 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
||||||
|
|
||||||
/* Breakpoints */
|
/* Breakpoints */
|
||||||
element = new Element("breakpoints");
|
element = new Element("breakpoints");
|
||||||
element.addContent(breakpointsContainer.getConfigXML());
|
element.addContent(getWatchpointConfigXML());
|
||||||
config.add(element);
|
config.add(element);
|
||||||
|
|
||||||
// Mote interfaces
|
// Mote interfaces
|
||||||
|
@ -458,39 +454,13 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Watchpoints: Forward to breakpoint container */
|
|
||||||
public void addWatchpointListener(ActionListener listener) {
|
|
||||||
breakpointsContainer.addWatchpointListener(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Watchpoint getLastWatchpoint() {
|
|
||||||
return breakpointsContainer.getLastWatchpoint();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mote getMote() {
|
|
||||||
return breakpointsContainer.getMote();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActionListener[] getWatchpointListeners() {
|
|
||||||
return breakpointsContainer.getWatchpointListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeWatchpointListener(ActionListener listener) {
|
|
||||||
breakpointsContainer.removeWatchpointListener(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MspBreakpointContainer getBreakpointsContainer() {
|
|
||||||
return breakpointsContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getExecutionDetails() {
|
public String getExecutionDetails() {
|
||||||
return executeCLICommand("stacktrace");
|
return executeCLICommand("stacktrace");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPCString() {
|
public String getPCString() {
|
||||||
int pc = myCpu.getPC();
|
int pc = myCpu.getPC();
|
||||||
ELF elf = (ELF)myCpu.getRegistry().getComponent(ELF.class);
|
ELF elf = myCpu.getRegistry().getComponent(ELF.class);
|
||||||
DebugInfo di = elf.getDebugInfo(pc);
|
DebugInfo di = elf.getDebugInfo(pc);
|
||||||
|
|
||||||
/* Following code examples from MSPsim, DebugCommands.java */
|
/* Following code examples from MSPsim, DebugCommands.java */
|
||||||
|
@ -539,4 +509,144 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc
|
||||||
|
|
||||||
/*return executeCLICommand("line " + myCpu.getPC());*/
|
/*return executeCLICommand("line " + myCpu.getPC());*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* WatchpointMote */
|
||||||
|
private ArrayList<WatchpointListener> watchpointListeners = new ArrayList<WatchpointListener>();
|
||||||
|
private ArrayList<MspBreakpoint> watchpoints = new ArrayList<MspBreakpoint>();
|
||||||
|
private Hashtable<File, Hashtable<Integer, Integer>> debuggingInfo = null;
|
||||||
|
|
||||||
|
public void addWatchpointListener(WatchpointListener listener) {
|
||||||
|
watchpointListeners.add(listener);
|
||||||
|
}
|
||||||
|
public void removeWatchpointListener(WatchpointListener listener) {
|
||||||
|
watchpointListeners.remove(listener);
|
||||||
|
}
|
||||||
|
public WatchpointListener[] getWatchpointListeners() {
|
||||||
|
return watchpointListeners.toArray(new WatchpointListener[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Watchpoint addBreakpoint(File codeFile, int lineNr, int address) {
|
||||||
|
MspBreakpoint bp = new MspBreakpoint(this, address, codeFile, new Integer(lineNr));
|
||||||
|
watchpoints.add(bp);
|
||||||
|
|
||||||
|
for (WatchpointListener listener: watchpointListeners) {
|
||||||
|
listener.watchpointsChanged();
|
||||||
|
}
|
||||||
|
return bp;
|
||||||
|
}
|
||||||
|
public void removeBreakpoint(Watchpoint watchpoint) {
|
||||||
|
((MspBreakpoint)watchpoint).unregisterBreakpoint();
|
||||||
|
watchpoints.remove(watchpoint);
|
||||||
|
|
||||||
|
for (WatchpointListener listener: watchpointListeners) {
|
||||||
|
listener.watchpointsChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Watchpoint[] getBreakpoints() {
|
||||||
|
return watchpoints.toArray(new Watchpoint[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean breakpointExists(int address) {
|
||||||
|
if (address < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (Watchpoint watchpoint: watchpoints) {
|
||||||
|
if (watchpoint.getExecutableAddress() == address) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public boolean breakpointExists(File file, int lineNr) {
|
||||||
|
for (Watchpoint watchpoint: watchpoints) {
|
||||||
|
if (watchpoint.getCodeFile() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (watchpoint.getCodeFile().compareTo(file) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (watchpoint.getLineNumber() != lineNr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getExecutableAddressOf(File file, int lineNr) {
|
||||||
|
if (file == null || lineNr < 0 || debuggingInfo == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Match file */
|
||||||
|
Hashtable<Integer, Integer> lineTable = debuggingInfo.get(file);
|
||||||
|
if (lineTable == null) {
|
||||||
|
Enumeration<File> fileEnum = debuggingInfo.keys();
|
||||||
|
while (fileEnum.hasMoreElements()) {
|
||||||
|
File f = fileEnum.nextElement();
|
||||||
|
if (f != null && f.getName().equals(file.getName())) {
|
||||||
|
lineTable = debuggingInfo.get(f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lineTable == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Match line number */
|
||||||
|
Integer address = lineTable.get(lineNr);
|
||||||
|
if (address != null) {
|
||||||
|
Enumeration<Integer> lineEnum = lineTable.keys();
|
||||||
|
while (lineEnum.hasMoreElements()) {
|
||||||
|
Integer l = lineEnum.nextElement();
|
||||||
|
if (l != null && l.intValue() == lineNr) {
|
||||||
|
/* Found line address */
|
||||||
|
return lineTable.get(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void signalBreakpointTrigger(MspBreakpoint b) {
|
||||||
|
if (b.stopsSimulation() && getSimulation().isRunning()) {
|
||||||
|
/* Stop simulation immediately */
|
||||||
|
stopNextInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Notify listeners */
|
||||||
|
WatchpointListener[] listeners = getWatchpointListeners();
|
||||||
|
for (WatchpointListener listener: listeners) {
|
||||||
|
listener.watchpointTriggered(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Element> getWatchpointConfigXML() {
|
||||||
|
ArrayList<Element> config = new ArrayList<Element>();
|
||||||
|
Element element;
|
||||||
|
|
||||||
|
for (MspBreakpoint breakpoint: watchpoints) {
|
||||||
|
element = new Element("breakpoint");
|
||||||
|
element.addContent(breakpoint.getConfigXML());
|
||||||
|
config.add(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
public boolean setWatchpointConfigXML(Collection<Element> configXML, boolean visAvailable) {
|
||||||
|
for (Element element : configXML) {
|
||||||
|
if (element.getName().equals("breakpoint")) {
|
||||||
|
MspBreakpoint breakpoint = new MspBreakpoint(this);
|
||||||
|
if (!breakpoint.setConfigXML(element.getChildren(), visAvailable)) {
|
||||||
|
logger.warn("Could not restore breakpoint: " + breakpoint);
|
||||||
|
} else {
|
||||||
|
watchpoints.add(breakpoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,101 +34,125 @@ package se.sics.cooja.mspmote.plugins;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
import se.sics.cooja.Watchpoint;
|
import se.sics.cooja.Watchpoint;
|
||||||
import se.sics.cooja.mspmote.MspMote;
|
import se.sics.cooja.mspmote.MspMote;
|
||||||
|
import se.sics.cooja.util.StringUtils;
|
||||||
import se.sics.mspsim.core.CPUMonitor;
|
import se.sics.mspsim.core.CPUMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Breakpoint.
|
* Mspsim watchpoint.
|
||||||
* Contains meta data such source code file and line number.
|
|
||||||
*
|
*
|
||||||
* @author Fredrik Osterlind
|
* @author Fredrik Osterlind
|
||||||
*/
|
*/
|
||||||
public class MspBreakpoint implements Watchpoint {
|
public class MspBreakpoint implements Watchpoint {
|
||||||
private static Logger logger = Logger.getLogger(MspBreakpoint.class);
|
private static Logger logger = Logger.getLogger(MspBreakpoint.class);
|
||||||
|
|
||||||
private MspBreakpointContainer breakpoints;
|
|
||||||
private MspMote mspMote;
|
private MspMote mspMote;
|
||||||
|
|
||||||
|
private int address = -1; /* Binary address */
|
||||||
|
private File codeFile = null; /* Source code, may be null*/
|
||||||
|
private int lineNr = -1; /* Source code line number, may be null */
|
||||||
|
|
||||||
private CPUMonitor cpuMonitor = null;
|
private CPUMonitor cpuMonitor = null;
|
||||||
|
|
||||||
private boolean stopsSimulation = true;
|
private boolean stopsSimulation = true;
|
||||||
|
|
||||||
private Integer address = null; /* Binary address */
|
|
||||||
|
|
||||||
private File codeFile = null; /* Source code, may be null*/
|
|
||||||
private Integer lineNr = null; /* Source code line number, may be null */
|
|
||||||
|
|
||||||
private String msg = null;
|
private String msg = null;
|
||||||
private Color color = Color.BLACK;
|
private Color color = Color.BLACK;
|
||||||
|
|
||||||
public MspBreakpoint(MspBreakpointContainer breakpoints, MspMote mote) {
|
private String contikiCode = null;
|
||||||
this.breakpoints = breakpoints;
|
|
||||||
|
public MspBreakpoint(MspMote mote) {
|
||||||
this.mspMote = mote;
|
this.mspMote = mote;
|
||||||
|
/* expects setConfigXML(..) */
|
||||||
}
|
}
|
||||||
|
|
||||||
public MspBreakpoint(MspBreakpointContainer breakpoints, MspMote mote, Integer address) {
|
public MspBreakpoint(MspMote mote, Integer address, File codeFile, Integer lineNr) {
|
||||||
this(breakpoints, mote);
|
this(mote);
|
||||||
this.address = address;
|
this.address = address;
|
||||||
|
this.codeFile = codeFile;
|
||||||
|
this.lineNr = lineNr;
|
||||||
|
|
||||||
createMonitor();
|
createMonitor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MspBreakpoint(MspBreakpointContainer breakpoints, MspMote mote, Integer address, File codeFile, Integer lineNr) {
|
|
||||||
this(breakpoints, mote, address);
|
|
||||||
this.codeFile = codeFile;
|
|
||||||
this.lineNr = lineNr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return MSP mote
|
|
||||||
*/
|
|
||||||
public MspMote getMote() {
|
public MspMote getMote() {
|
||||||
return mspMote;
|
return mspMote;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public Color getColor() {
|
||||||
* @return Executable address
|
return color;
|
||||||
*/
|
}
|
||||||
public Integer getExecutableAddress() {
|
public void setColor(Color color) {
|
||||||
return address;
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
String desc = "";
|
||||||
|
if (codeFile != null) {
|
||||||
|
desc += codeFile.getPath() + ":" + lineNr + " (0x" + Integer.toHexString(address) + ")";
|
||||||
|
} else if (address >= 0) {
|
||||||
|
desc += "0x" + Integer.toHexString(address);
|
||||||
|
}
|
||||||
|
if (msg != null) {
|
||||||
|
desc += "\n\n" + msg;
|
||||||
|
}
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
public void setUserMessage(String msg) {
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
public String getUserMessage() {
|
||||||
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Source code file
|
|
||||||
*/
|
|
||||||
public File getCodeFile() {
|
public File getCodeFile() {
|
||||||
return codeFile;
|
return codeFile;
|
||||||
}
|
}
|
||||||
|
public int getLineNumber() {
|
||||||
/**
|
|
||||||
* @return Source code file line number
|
|
||||||
*/
|
|
||||||
public Integer getLineNumber() {
|
|
||||||
return lineNr;
|
return lineNr;
|
||||||
}
|
}
|
||||||
|
public int getExecutableAddress() {
|
||||||
public boolean stopsSimulation() {
|
return address;
|
||||||
return stopsSimulation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStopsSimulation(boolean stops) {
|
public void setStopsSimulation(boolean stops) {
|
||||||
stopsSimulation = stops;
|
stopsSimulation = stops;
|
||||||
}
|
}
|
||||||
|
public boolean stopsSimulation() {
|
||||||
|
return stopsSimulation;
|
||||||
|
}
|
||||||
|
|
||||||
private void createMonitor() {
|
private void createMonitor() {
|
||||||
cpuMonitor = new CPUMonitor() {
|
cpuMonitor = new CPUMonitor() {
|
||||||
public void cpuAction(int type, int adr, int data) {
|
public void cpuAction(int type, int adr, int data) {
|
||||||
breakpoints.signalBreakpointTrigger(MspBreakpoint.this);
|
if (type != CPUMonitor.EXECUTE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mspMote.signalBreakpointTrigger(MspBreakpoint.this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
mspMote.getCPU().addWatchPoint(address, cpuMonitor);
|
mspMote.getCPU().addWatchPoint(address, cpuMonitor);
|
||||||
|
|
||||||
|
|
||||||
|
/* Remember Contiki code, to verify it when reloaded */
|
||||||
|
if (contikiCode == null) {
|
||||||
|
final String code = StringUtils.loadFromFile(codeFile);
|
||||||
|
if (code != null) {
|
||||||
|
String[] lines = code.split("\n");
|
||||||
|
if (lineNr-1 < lines.length) {
|
||||||
|
contikiCode = lines[lineNr-1].trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unregisterBreakpoint() {
|
public void unregisterBreakpoint() {
|
||||||
|
@ -136,27 +160,25 @@ public class MspBreakpoint implements Watchpoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<Element> getConfigXML() {
|
public Collection<Element> getConfigXML() {
|
||||||
Vector<Element> config = new Vector<Element>();
|
ArrayList<Element> config = new ArrayList<Element>();
|
||||||
Element element;
|
Element element;
|
||||||
|
|
||||||
element = new Element("address");
|
|
||||||
element.setText(address.toString());
|
|
||||||
config.add(element);
|
|
||||||
|
|
||||||
element = new Element("stops");
|
element = new Element("stops");
|
||||||
element.setText("" + stopsSimulation);
|
element.setText("" + stopsSimulation);
|
||||||
config.add(element);
|
config.add(element);
|
||||||
|
|
||||||
if (codeFile != null) {
|
element = new Element("codefile");
|
||||||
element = new Element("codefile");
|
File file = mspMote.getSimulation().getGUI().createPortablePath(codeFile);
|
||||||
File file = mspMote.getSimulation().getGUI().createPortablePath(codeFile);
|
element.setText(file.getPath().replaceAll("\\\\", "/"));
|
||||||
element.setText(file.getPath().replaceAll("\\\\", "/"));
|
config.add(element);
|
||||||
config.add(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lineNr != null) {
|
element = new Element("line");
|
||||||
element = new Element("line");
|
element.setText("" + lineNr);
|
||||||
element.setText(lineNr.toString());
|
config.add(element);
|
||||||
|
|
||||||
|
if (contikiCode != null) {
|
||||||
|
element = new Element("contikicode");
|
||||||
|
element.setText(contikiCode);
|
||||||
config.add(element);
|
config.add(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,8 +215,23 @@ public class MspBreakpoint implements Watchpoint {
|
||||||
}
|
}
|
||||||
} else if (element.getName().equals("line")) {
|
} else if (element.getName().equals("line")) {
|
||||||
lineNr = Integer.parseInt(element.getText());
|
lineNr = Integer.parseInt(element.getText());
|
||||||
} else if (element.getName().equals("address")) {
|
} else if (element.getName().equals("contikicode")) {
|
||||||
address = Integer.parseInt(element.getText());
|
String lastContikiCode = element.getText().trim();
|
||||||
|
|
||||||
|
/* Verify that Contiki code did not change */
|
||||||
|
final String code = StringUtils.loadFromFile(codeFile);
|
||||||
|
if (code != null) {
|
||||||
|
String[] lines = code.split("\n");
|
||||||
|
if (lineNr-1 < lines.length) {
|
||||||
|
contikiCode = lines[lineNr-1].trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lastContikiCode.equals(contikiCode)) {
|
||||||
|
logger.warn("Detected modified Contiki code at breakpoint: " + codeFile.getPath() + ":" + lineNr + ".");
|
||||||
|
logger.warn("From: '" + lastContikiCode + "'");
|
||||||
|
logger.warn(" To: '" + contikiCode + "'");
|
||||||
|
}
|
||||||
} else if (element.getName().equals("msg")) {
|
} else if (element.getName().equals("msg")) {
|
||||||
msg = element.getText();
|
msg = element.getText();
|
||||||
} else if (element.getName().equals("color")) {
|
} else if (element.getName().equals("color")) {
|
||||||
|
@ -204,51 +241,18 @@ public class MspBreakpoint implements Watchpoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address == null) {
|
/* Update executable address */
|
||||||
|
address = mspMote.getExecutableAddressOf(codeFile, lineNr);
|
||||||
|
if (address < 0) {
|
||||||
|
logger.fatal("Could not restore breakpoint, did source code change?");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO Save source code line */
|
|
||||||
|
|
||||||
if (codeFile != null && lineNr != null) {
|
|
||||||
/* Update executable address */
|
|
||||||
address = mspMote.getBreakpointsContainer().getExecutableAddressOf(codeFile, lineNr);
|
|
||||||
if (address == null) {
|
|
||||||
logger.fatal("Could not restore breakpoint, did source code change?");
|
|
||||||
address = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
createMonitor();
|
createMonitor();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUserMessage(String msg) {
|
public String toString() {
|
||||||
this.msg = msg;
|
return getMote() + ": " + getDescription();
|
||||||
}
|
}
|
||||||
public String getUserMessage() {
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColor(Color color) {
|
|
||||||
this.color = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDescription() {
|
|
||||||
String desc = "";
|
|
||||||
if (codeFile != null) {
|
|
||||||
desc += codeFile.getPath() + ":" + lineNr + " (0x" + Integer.toHexString(address.intValue()) + ")";
|
|
||||||
} else if (address != null) {
|
|
||||||
desc += "0x" + Integer.toHexString(address.intValue());
|
|
||||||
}
|
|
||||||
if (msg != null) {
|
|
||||||
desc += "\n\n" + msg;
|
|
||||||
}
|
|
||||||
return desc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Color getColor() {
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,280 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2009, Swedish Institute of Computer Science.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the Institute nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* $Id: MspBreakpointContainer.java,v 1.3 2010/01/21 22:32:32 fros4943 Exp $
|
|
||||||
*/
|
|
||||||
|
|
||||||
package se.sics.cooja.mspmote.plugins;
|
|
||||||
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
import org.jdom.Element;
|
|
||||||
|
|
||||||
import se.sics.cooja.WatchpointMote;
|
|
||||||
import se.sics.cooja.mspmote.MspMote;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Breakpoint collection
|
|
||||||
*
|
|
||||||
* @author Fredrik Osterlind
|
|
||||||
*/
|
|
||||||
public class MspBreakpointContainer implements WatchpointMote {
|
|
||||||
private static Logger logger = Logger.getLogger(MspBreakpointContainer.class);
|
|
||||||
|
|
||||||
private Hashtable<File, Hashtable<Integer, Integer>> debuggingInfo = null;
|
|
||||||
private MspMote mspMote;
|
|
||||||
|
|
||||||
private ArrayList<MspBreakpoint> breakpoints = new ArrayList<MspBreakpoint>();
|
|
||||||
private ArrayList<ActionListener> listeners = new ArrayList<ActionListener>();
|
|
||||||
private MspBreakpoint lastTriggeredBreakpoint = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param debuggingInfo Debugging information read from firmware file
|
|
||||||
* @param mote Mote
|
|
||||||
*/
|
|
||||||
public MspBreakpointContainer(MspMote mote, Hashtable<File, Hashtable<Integer, Integer>> debuggingInfo) {
|
|
||||||
this.mspMote = mote;
|
|
||||||
this.debuggingInfo = debuggingInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add breakpoint at given address.
|
|
||||||
*
|
|
||||||
* @param address Executable address
|
|
||||||
*/
|
|
||||||
public void addBreakpoint(Integer address) {
|
|
||||||
addBreakpoint((File) null, (Integer) null, address);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add breakpoint at given address with given meta data.
|
|
||||||
*
|
|
||||||
* @param codeFile Source code file
|
|
||||||
* @param lineNr Source code file line number
|
|
||||||
* @param address Executable address
|
|
||||||
* @return Added breakpoint
|
|
||||||
*/
|
|
||||||
public MspBreakpoint addBreakpoint(File codeFile, int lineNr, Integer address) {
|
|
||||||
MspBreakpoint bp = new MspBreakpoint(this, mspMote, address, codeFile, new Integer(lineNr));
|
|
||||||
breakpoints.add(bp);
|
|
||||||
|
|
||||||
/* Notify listeners */
|
|
||||||
lastTriggeredBreakpoint = null;
|
|
||||||
for (ActionListener listener: listeners) {
|
|
||||||
listener.actionPerformed(null);
|
|
||||||
}
|
|
||||||
return bp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove breakpoint at given address.
|
|
||||||
*
|
|
||||||
* @param address Executable address
|
|
||||||
*/
|
|
||||||
public MspBreakpoint removeBreakpoint(Integer address) {
|
|
||||||
MspBreakpoint breakpointToRemove = null;
|
|
||||||
for (MspBreakpoint breakpoint: breakpoints) {
|
|
||||||
if (breakpoint.getExecutableAddress().intValue() == address.intValue()) {
|
|
||||||
breakpointToRemove = breakpoint;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (breakpointToRemove == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
breakpointToRemove.unregisterBreakpoint();
|
|
||||||
breakpoints.remove(breakpointToRemove);
|
|
||||||
|
|
||||||
/* Notify listeners */
|
|
||||||
lastTriggeredBreakpoint = null;
|
|
||||||
for (ActionListener listener: listeners) {
|
|
||||||
listener.actionPerformed(null);
|
|
||||||
}
|
|
||||||
return breakpointToRemove;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a breakpoint exists at given address.
|
|
||||||
*
|
|
||||||
* @param address Executable address
|
|
||||||
* @return True if breakpoint exists, false otherwise
|
|
||||||
*/
|
|
||||||
public boolean breakpointExists(Integer address) {
|
|
||||||
if (address == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (MspBreakpoint breakpoint: breakpoints) {
|
|
||||||
if (breakpoint.getExecutableAddress().intValue() == address.intValue()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean breakpointExists(File file, int lineNr) {
|
|
||||||
for (MspBreakpoint breakpoint: breakpoints) {
|
|
||||||
if (breakpoint.getCodeFile() == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (breakpoint.getCodeFile().compareTo(file) != 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (breakpoint.getLineNumber().intValue() != lineNr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return All breakpoints
|
|
||||||
*/
|
|
||||||
public MspBreakpoint[] getBreakpoints() {
|
|
||||||
return breakpoints.toArray(new MspBreakpoint[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getBreakpointsCount() {
|
|
||||||
return breakpoints.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addWatchpointListener(ActionListener listener) {
|
|
||||||
listeners.add(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeWatchpointListener(ActionListener listener) {
|
|
||||||
listeners.remove(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActionListener[] getWatchpointListeners() {
|
|
||||||
return listeners.toArray(new ActionListener[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void signalBreakpointTrigger(MspBreakpoint b) {
|
|
||||||
if (b.stopsSimulation() && mspMote.getSimulation().isRunning()) {
|
|
||||||
/* Stop simulation immediately */
|
|
||||||
mspMote.stopNextInstruction();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Notify listeners */
|
|
||||||
lastTriggeredBreakpoint = b;
|
|
||||||
ActionListener[] arr = getWatchpointListeners();
|
|
||||||
for (ActionListener listener: arr) {
|
|
||||||
listener.actionPerformed(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public MspMote getMote() {
|
|
||||||
return mspMote;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MspBreakpoint getLastWatchpoint() {
|
|
||||||
return lastTriggeredBreakpoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to calculate the executable address of given file.
|
|
||||||
* Using debugging information from firmware file,
|
|
||||||
*
|
|
||||||
* @param file Source code file
|
|
||||||
* @param lineNr Source code file line number
|
|
||||||
* @return Executable address or null if not found
|
|
||||||
*/
|
|
||||||
public Integer getExecutableAddressOf(File file, int lineNr) {
|
|
||||||
if (file == null || lineNr < 0 || debuggingInfo == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Match file */
|
|
||||||
Hashtable<Integer, Integer> lineTable = debuggingInfo.get(file);
|
|
||||||
if (lineTable == null) {
|
|
||||||
Enumeration<File> fileEnum = debuggingInfo.keys();
|
|
||||||
while (fileEnum.hasMoreElements()) {
|
|
||||||
File f = fileEnum.nextElement();
|
|
||||||
if (f != null && f.getName().equals(file.getName())) {
|
|
||||||
lineTable = debuggingInfo.get(f);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (lineTable == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Match line number */
|
|
||||||
Integer address = lineTable.get(lineNr);
|
|
||||||
if (address != null) {
|
|
||||||
Enumeration<Integer> lineEnum = lineTable.keys();
|
|
||||||
while (lineEnum.hasMoreElements()) {
|
|
||||||
Integer l = lineEnum.nextElement();
|
|
||||||
if (l != null && l.intValue() == lineNr) {
|
|
||||||
/* Found line address */
|
|
||||||
return lineTable.get(l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<Element> getConfigXML() {
|
|
||||||
Vector<Element> config = new Vector<Element>();
|
|
||||||
Element element;
|
|
||||||
|
|
||||||
for (MspBreakpoint breakpoint: breakpoints) {
|
|
||||||
element = new Element("breakpoint");
|
|
||||||
element.addContent(breakpoint.getConfigXML());
|
|
||||||
config.add(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) {
|
|
||||||
for (Element element : configXML) {
|
|
||||||
if (element.getName().equals("breakpoint")) {
|
|
||||||
MspBreakpoint breakpoint = new MspBreakpoint(this, mspMote);
|
|
||||||
if (!breakpoint.setConfigXML(element.getChildren(), visAvailable)) {
|
|
||||||
logger.warn("Could not restore breakpoint: " + breakpoint);
|
|
||||||
} else {
|
|
||||||
breakpoints.add(breakpoint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue