msp430 specific plugins
This commit is contained in:
parent
52cacb7947
commit
749c0aa639
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 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: BreakpointsUI.java,v 1.1 2008/02/07 14:55:18 fros4943 Exp $
|
||||
*/
|
||||
|
||||
package se.sics.cooja.mspmote.plugins;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.io.File;
|
||||
import java.util.Vector;
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import se.sics.cooja.mspmote.plugins.MspCodeWatcher.Breakpoints;
|
||||
import se.sics.cooja.mspmote.plugins.MspCodeWatcher.Breakpoints.Breakpoint;
|
||||
|
||||
public class BreakpointsUI extends JPanel {
|
||||
private static Logger logger = Logger.getLogger(BreakpointsUI.class);
|
||||
|
||||
private JTable breakpointsTable = null;
|
||||
private Breakpoints breakpoints = null;
|
||||
|
||||
private AbstractTableModel tableModel = new AbstractTableModel() {
|
||||
private String[] tableColumnNames = {
|
||||
"Address",
|
||||
"File",
|
||||
"Line",
|
||||
"Remove"
|
||||
};
|
||||
|
||||
public String getColumnName(int col) { return tableColumnNames[col].toString(); }
|
||||
public int getRowCount() { return breakpoints.getBreakpoints().size(); }
|
||||
public int getColumnCount() { return tableColumnNames.length; }
|
||||
public Object getValueAt(int row, int col) {
|
||||
// Display executable address in hexadecimal
|
||||
if (col == 0) {
|
||||
Integer address = breakpoints.getBreakpoints().get(row).getExecutableAddress();
|
||||
return "0x" + Integer.toHexString(address.intValue());
|
||||
}
|
||||
|
||||
// Display only name of file
|
||||
if (col == 1) {
|
||||
File file = breakpoints.getBreakpoints().get(row).getCodeFile();
|
||||
if (file == null) {
|
||||
return "";
|
||||
}
|
||||
return file.getName();
|
||||
}
|
||||
|
||||
// Display line number
|
||||
if (col == 2) {
|
||||
Integer line = breakpoints.getBreakpoints().get(row).getLineNumber();
|
||||
if (line == null) {
|
||||
return "";
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
return new Boolean(false);
|
||||
}
|
||||
public boolean isCellEditable(int row, int col){
|
||||
return getColumnClass(col) == Boolean.class;
|
||||
}
|
||||
public void setValueAt(Object value, int row, int col) {
|
||||
fireTableCellUpdated(row, col);
|
||||
Integer address = breakpoints.getBreakpoints().get(row).getExecutableAddress();
|
||||
breakpoints.removeBreakpoint(address);
|
||||
}
|
||||
public Class getColumnClass(int c) {
|
||||
return getValueAt(0, c).getClass();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public BreakpointsUI(Breakpoints breakpoints) {
|
||||
this.breakpoints = breakpoints;
|
||||
breakpoints.addBreakpointListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Breakpoint triggered = BreakpointsUI.this.breakpoints.getLastTriggered();
|
||||
if (triggered != null) {
|
||||
flashBreakpoint(triggered);
|
||||
}
|
||||
|
||||
breakpointsTable.repaint();
|
||||
}
|
||||
});
|
||||
|
||||
breakpointsTable = new JTable(tableModel) {
|
||||
public String getToolTipText(MouseEvent e) {
|
||||
String tip = null;
|
||||
java.awt.Point p = e.getPoint();
|
||||
int rowIndex = breakpointsTable.rowAtPoint(p);
|
||||
int colIndex = breakpointsTable.columnAtPoint(p);
|
||||
int realColumnIndex = breakpointsTable.convertColumnIndexToModel(colIndex);
|
||||
|
||||
if (realColumnIndex == 1) {
|
||||
Vector<Breakpoint> allBreakpoints = BreakpointsUI.this.breakpoints.getBreakpoints();
|
||||
if (rowIndex < 0 || rowIndex >= allBreakpoints.size()) {
|
||||
return "";
|
||||
}
|
||||
File file = allBreakpoints.get(rowIndex).getCodeFile();
|
||||
if (file == null) {
|
||||
return "";
|
||||
} else {
|
||||
tip = file.getPath();
|
||||
}
|
||||
}
|
||||
return tip;
|
||||
}
|
||||
};
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
add(breakpointsTable.getTableHeader(), BorderLayout.PAGE_START);
|
||||
add(breakpointsTable, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
private int flashCounter = 0;
|
||||
private void flashBreakpoint(Breakpoint breakpoint) {
|
||||
int index = breakpoints.getBreakpoints().indexOf(breakpoint);
|
||||
breakpointsTable.setRowSelectionInterval(index, index);
|
||||
breakpointsTable.setSelectionBackground(Color.RED);
|
||||
|
||||
flashCounter = 8;
|
||||
|
||||
final Timer timer = new Timer(100, null);
|
||||
timer.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (flashCounter-- <= 0) {
|
||||
timer.stop();
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
breakpointsTable.setSelectionBackground(Color.WHITE);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Toggle background color
|
||||
if (breakpointsTable.getSelectionBackground() != Color.RED) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
breakpointsTable.setSelectionBackground(Color.RED);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
breakpointsTable.setSelectionBackground(Color.WHITE);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
timer.start();
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,299 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 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: CodeUI.java,v 1.1 2008/02/07 14:55:18 fros4943 Exp $
|
||||
*/
|
||||
|
||||
package se.sics.cooja.mspmote.plugins;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.io.File;
|
||||
import java.util.Vector;
|
||||
import javax.swing.*;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import se.sics.cooja.mspmote.plugins.MspCodeWatcher.Breakpoints;
|
||||
|
||||
/**
|
||||
* Displays source code and allows a user to add and remove breakpoints.
|
||||
*
|
||||
* @author Fredrik Österlind
|
||||
*/
|
||||
public class CodeUI extends JPanel {
|
||||
private static Logger logger = Logger.getLogger(CodeUI.class);
|
||||
|
||||
private JPanel panel = null;
|
||||
private JList codeList = null;
|
||||
private File currentFile = null;
|
||||
|
||||
private Breakpoints breakpoints = null;
|
||||
|
||||
/**
|
||||
* @param breakpoints Breakpoints
|
||||
*/
|
||||
public CodeUI(Breakpoints breakpoints) {
|
||||
this.breakpoints = breakpoints;
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
panel = new JPanel(new BorderLayout());
|
||||
add(panel, BorderLayout.CENTER);
|
||||
displayNoCode();
|
||||
|
||||
breakpoints.addBreakpointListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (codeList != null) {
|
||||
codeList.updateUI();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any shown source code.
|
||||
*/
|
||||
public void displayNoCode() {
|
||||
// Display "no code" message
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
panel.removeAll();
|
||||
panel.repaint();
|
||||
}
|
||||
});
|
||||
currentFile = null;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display given source code and mark given line.
|
||||
*
|
||||
* @param codeFile Source code file
|
||||
* @param codeData Source code
|
||||
* @param lineNr Line numer
|
||||
*/
|
||||
public void displayNewCode(final File codeFile, final Vector<String> codeData, final int lineNr) {
|
||||
currentFile = codeFile;
|
||||
|
||||
if (codeData == null || codeData.size() == 0) {
|
||||
displayNoCode();
|
||||
return;
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
// Display code
|
||||
codeList = new JList(new CodeListModel(codeData));
|
||||
codeList.setFont(new Font("courier", 0, 12));
|
||||
codeList.setCellRenderer(new CodeCellRenderer(lineNr));
|
||||
codeList.addMouseListener(new MouseListener() {
|
||||
public void mousePressed(MouseEvent e) {
|
||||
handleMouseEvent(e);
|
||||
}
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
handleMouseEvent(e);
|
||||
}
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
handleMouseEvent(e);
|
||||
}
|
||||
public void mouseExited(MouseEvent e) {
|
||||
handleMouseEvent(e);
|
||||
}
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
handleMouseEvent(e);
|
||||
}
|
||||
});
|
||||
panel.removeAll();
|
||||
panel.add(codeList);
|
||||
displayLine(lineNr);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark given line number in shown source code.
|
||||
*
|
||||
* @param lineNumber Line number
|
||||
*/
|
||||
public void displayLine(final int lineNumber) {
|
||||
if (codeList == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
if (lineNumber > 0) {
|
||||
((CodeCellRenderer) codeList.getCellRenderer()).changeCurrentLine(lineNumber);
|
||||
int index = lineNumber - 1;
|
||||
codeList.setSelectedIndex(index);
|
||||
|
||||
codeList.ensureIndexIsVisible(Math.max(0, index-3));
|
||||
codeList.ensureIndexIsVisible(Math.min(index+3, codeList.getModel().getSize()));
|
||||
codeList.ensureIndexIsVisible(index);
|
||||
}
|
||||
codeList.updateUI();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleMouseEvent(MouseEvent event) {
|
||||
if (event.isPopupTrigger()) {
|
||||
Point menuLocation = codeList.getPopupLocation(event);
|
||||
if (menuLocation == null) {
|
||||
menuLocation = new Point(
|
||||
codeList.getLocationOnScreen().x + event.getX(),
|
||||
codeList.getLocationOnScreen().y + event.getY());
|
||||
}
|
||||
|
||||
final int currentLine = codeList.locationToIndex(new Point(event.getX(), event.getY())) + 1;
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
codeList.setSelectedIndex(currentLine - 1);
|
||||
}
|
||||
});
|
||||
JPopupMenu popupMenu = createPopupMenu(currentFile, currentLine);
|
||||
|
||||
popupMenu.setLocation(menuLocation);
|
||||
popupMenu.setInvoker(codeList);
|
||||
popupMenu.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
private JPopupMenu createPopupMenu(final File codeFile, final int lineNr) {
|
||||
final Integer executableAddress = breakpoints.getExecutableAddressOf(codeFile, lineNr);
|
||||
boolean breakpointExists = false;
|
||||
if (executableAddress != null) {
|
||||
breakpointExists = breakpoints.breakpointExists(executableAddress);
|
||||
}
|
||||
|
||||
JPopupMenu menuMotePlugins = new JPopupMenu();
|
||||
JMenuItem headerMenuItem = new JMenuItem("Breakpoints:");
|
||||
headerMenuItem.setEnabled(false);
|
||||
menuMotePlugins.add(headerMenuItem);
|
||||
menuMotePlugins.add(new JSeparator());
|
||||
|
||||
JMenuItem addBreakpointMenuItem = new JMenuItem("Add breakpoint on line " + lineNr);
|
||||
if (executableAddress == null || breakpointExists) {
|
||||
addBreakpointMenuItem.setEnabled(false);
|
||||
} else {
|
||||
addBreakpointMenuItem.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
breakpoints.addBreakpoint(codeFile, lineNr, executableAddress);
|
||||
}
|
||||
});
|
||||
}
|
||||
menuMotePlugins.add(addBreakpointMenuItem);
|
||||
|
||||
JMenuItem delBreakpointMenuItem = new JMenuItem("Delete breakpoint on line " + lineNr);
|
||||
if (executableAddress == null || !breakpointExists) {
|
||||
delBreakpointMenuItem.setEnabled(false);
|
||||
} else {
|
||||
delBreakpointMenuItem.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
breakpoints.removeBreakpoint(executableAddress);
|
||||
}
|
||||
});
|
||||
}
|
||||
menuMotePlugins.add(delBreakpointMenuItem);
|
||||
|
||||
return menuMotePlugins;
|
||||
}
|
||||
|
||||
private class CodeListModel extends AbstractListModel {
|
||||
private Vector<String> codeData;
|
||||
|
||||
public CodeListModel(Vector<String> codeData) {
|
||||
super();
|
||||
this.codeData = codeData;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
if (codeData == null || codeData.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return codeData.size();
|
||||
}
|
||||
|
||||
public Object getElementAt(int index) {
|
||||
if (codeData == null || codeData.isEmpty()) {
|
||||
return "No code to display";
|
||||
}
|
||||
|
||||
return codeData.get(index);
|
||||
}
|
||||
}
|
||||
|
||||
private class CodeCellRenderer extends JLabel implements ListCellRenderer {
|
||||
private int currentIndex;
|
||||
|
||||
public CodeCellRenderer(int currentLineNr) {
|
||||
this.currentIndex = currentLineNr - 1;
|
||||
}
|
||||
|
||||
public void changeCurrentLine(int currentLineNr) {
|
||||
this.currentIndex = currentLineNr - 1;
|
||||
}
|
||||
|
||||
public Component getListCellRendererComponent(
|
||||
JList list,
|
||||
Object value,
|
||||
int index,
|
||||
boolean isSelected,
|
||||
boolean cellHasFocus)
|
||||
{
|
||||
int lineNr = index + 1;
|
||||
|
||||
setText(lineNr + ": " + value);
|
||||
if (index == currentIndex) {
|
||||
setBackground(Color.green);
|
||||
} else if (isSelected) {
|
||||
setBackground(list.getSelectionBackground());
|
||||
setForeground(list.getSelectionForeground());
|
||||
} else {
|
||||
setBackground(list.getBackground());
|
||||
setForeground(list.getForeground());
|
||||
}
|
||||
setEnabled(list.isEnabled());
|
||||
|
||||
Integer executableAddress = breakpoints.getExecutableAddressOf(currentFile, lineNr);
|
||||
if (breakpoints.breakpointExists(executableAddress)) {
|
||||
setFont(list.getFont().deriveFont(Font.BOLD));
|
||||
} else {
|
||||
setFont(list.getFont());
|
||||
}
|
||||
setOpaque(true);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,751 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 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: MspCodeWatcher.java,v 1.1 2008/02/07 14:55:18 fros4943 Exp $
|
||||
*/
|
||||
|
||||
package se.sics.cooja.mspmote.plugins;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.event.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.plaf.basic.BasicComboBoxRenderer;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jdom.Element;
|
||||
|
||||
import se.sics.cooja.*;
|
||||
import se.sics.cooja.mspmote.MspMote;
|
||||
import se.sics.cooja.mspmote.MspMoteType;
|
||||
import se.sics.mspsim.core.CPUMonitor;
|
||||
import se.sics.mspsim.core.MSP430;
|
||||
import se.sics.mspsim.util.DebugUI;
|
||||
import se.sics.mspsim.util.Utils;
|
||||
|
||||
@ClassDescription("Msp Code Watcher")
|
||||
@PluginType(PluginType.MOTE_PLUGIN)
|
||||
public class MspCodeWatcher extends VisPlugin {
|
||||
private static Logger logger = Logger.getLogger(MspCodeWatcher.class);
|
||||
private Simulation mySimulation;
|
||||
private Observer simObserver;
|
||||
private MspMote mspMote;
|
||||
private MspMoteType moteType;
|
||||
private JButton stepButton;
|
||||
|
||||
private File codeFile = null;
|
||||
private int lineNumber = -1;
|
||||
|
||||
private DebugUI instructionsUI;
|
||||
private CodeUI codeUI;
|
||||
private BreakpointsUI breakpointsUI;
|
||||
|
||||
private Breakpoints breakpoints = null;
|
||||
|
||||
private JLabel filenameLabel;
|
||||
|
||||
/**
|
||||
* Mini-debugger for MSP Motes.
|
||||
* Visualizes instructions, source code and allows a user to manipulate breakpoints.
|
||||
*
|
||||
* @param mote MSP Mote
|
||||
* @param simulationToVisualize Simulation
|
||||
* @param gui Simulator
|
||||
*/
|
||||
public MspCodeWatcher(Mote mote, Simulation simulationToVisualize, GUI gui) {
|
||||
super("Msp Code Watcher", gui);
|
||||
this.mspMote = (MspMote) mote;
|
||||
this.moteType = (MspMoteType) mote.getType();
|
||||
mySimulation = simulationToVisualize;
|
||||
|
||||
Hashtable<File, Hashtable<Integer, Integer>> debuggingInfo = getFirmwareDebugInfo();
|
||||
breakpoints = new Breakpoints(debuggingInfo, mspMote);
|
||||
|
||||
getContentPane().setLayout(new BorderLayout());
|
||||
|
||||
instructionsUI = new DebugUI(this.mspMote.getCPU(), true);
|
||||
breakpointsUI = new BreakpointsUI(breakpoints);
|
||||
codeUI = new CodeUI(breakpoints);
|
||||
|
||||
JSplitPane leftPanel = new JSplitPane(
|
||||
JSplitPane.VERTICAL_SPLIT,
|
||||
new JScrollPane(instructionsUI, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED),
|
||||
new JScrollPane(breakpointsUI, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED)
|
||||
);
|
||||
|
||||
JPanel controlPanel = new JPanel();
|
||||
|
||||
// Extract files found in debugging info
|
||||
final Vector<File> files = new Vector<File>();
|
||||
Enumeration fileEnum = debuggingInfo.keys();
|
||||
while (fileEnum.hasMoreElements()) {
|
||||
File file = (File) fileEnum.nextElement();
|
||||
|
||||
// Insert file on correct position
|
||||
int index = 0;
|
||||
for (index=0; index < files.size(); index++) {
|
||||
if (file.getName().compareToIgnoreCase(files.get(index).getName()) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
files.add(index, file);
|
||||
}
|
||||
String[] fileNames = new String[files.size() + 1];
|
||||
fileNames[0] = "[select file]";
|
||||
for (int i=0; i < files.size(); i++) {
|
||||
fileNames[i+1] = files.get(i).getName();
|
||||
}
|
||||
JComboBox fileComboBox = new JComboBox(fileNames);
|
||||
fileComboBox.setSelectedIndex(0);
|
||||
fileComboBox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
JComboBox source = (JComboBox)e.getSource();
|
||||
int index = source.getSelectedIndex();
|
||||
if (index == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
File selectedFile = files.get(index-1);
|
||||
Vector<String> codeData = readTextFile(selectedFile);
|
||||
codeUI.displayNewCode(selectedFile, codeData, -1);
|
||||
codeFile = null;
|
||||
}
|
||||
});
|
||||
fileComboBox.setRenderer(new BasicComboBoxRenderer() {
|
||||
public Component getListCellRendererComponent(JList list, Object value,
|
||||
int index, boolean isSelected, boolean cellHasFocus) {
|
||||
if (isSelected) {
|
||||
setBackground(list.getSelectionBackground());
|
||||
setForeground(list.getSelectionForeground());
|
||||
if (index > 0) {
|
||||
list.setToolTipText(files.get(index-1).getPath());
|
||||
}
|
||||
} else {
|
||||
setBackground(list.getBackground());
|
||||
setForeground(list.getForeground());
|
||||
}
|
||||
setFont(list.getFont());
|
||||
setText((value == null) ? "" : value.toString());
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
JPanel topPanel = new JPanel();
|
||||
topPanel.setLayout(new BorderLayout());
|
||||
topPanel.add(BorderLayout.EAST, fileComboBox);
|
||||
topPanel.add(BorderLayout.CENTER, filenameLabel = new JLabel(""));
|
||||
|
||||
|
||||
|
||||
// Add single step button
|
||||
stepButton = new JButton("Single step");
|
||||
stepButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
// TODO Perform single step here
|
||||
mspMote.getCPU().step();
|
||||
updateInfo();
|
||||
}
|
||||
});
|
||||
controlPanel.add(stepButton);
|
||||
|
||||
add(BorderLayout.CENTER, new JSplitPane(
|
||||
JSplitPane.HORIZONTAL_SPLIT,
|
||||
leftPanel,
|
||||
new JScrollPane(codeUI)
|
||||
));
|
||||
add(BorderLayout.SOUTH, controlPanel);
|
||||
add(BorderLayout.NORTH, topPanel);
|
||||
|
||||
// Register as tickobserver
|
||||
mySimulation.addObserver(simObserver = new Observer() {
|
||||
public void update(Observable obs, Object obj) {
|
||||
if (!mySimulation.isRunning()) {
|
||||
stepButton.setEnabled(true);
|
||||
updateInfo();
|
||||
} else {
|
||||
stepButton.setEnabled(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setSize(350, 250);
|
||||
pack();
|
||||
|
||||
// Tries to select this plugin
|
||||
try {
|
||||
setSelected(true);
|
||||
} catch (java.beans.PropertyVetoException e) {
|
||||
// Could not select
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains currently active breakpoints.
|
||||
*
|
||||
* @author Fredrik Österlind
|
||||
*/
|
||||
static class Breakpoints {
|
||||
private Hashtable<File, Hashtable<Integer, Integer>> debuggingInfo = null;
|
||||
private Vector<Breakpoint> breakpoints = new Vector<Breakpoint>();
|
||||
private Vector<ActionListener> listeners = new Vector<ActionListener>();
|
||||
private Breakpoint lastBreakpoint = null;
|
||||
private MspMote mspMote = null;
|
||||
private boolean stopOnBreakpointTriggered = true;
|
||||
|
||||
/**
|
||||
* @param debuggingInfo Debugging information read from firmware file
|
||||
* @param mote MspMote
|
||||
*/
|
||||
public Breakpoints(Hashtable<File, Hashtable<Integer, Integer>> debuggingInfo, MspMote mote) {
|
||||
this.debuggingInfo = debuggingInfo;
|
||||
this.mspMote = mote;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param debuggingInfo Debugging information read from firmware file
|
||||
* @param mote MspMote
|
||||
*/
|
||||
public Breakpoints(Hashtable<File, Hashtable<Integer, Integer>> debuggingInfo, MspMote mote, boolean stopOnBreakpointTriggered) {
|
||||
this(debuggingInfo, mote);
|
||||
this.stopOnBreakpointTriggered = stopOnBreakpointTriggered;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Breakpoint addBreakpoint(File codeFile, int lineNr, Integer address) {
|
||||
Breakpoint bp = new Breakpoint(codeFile, new Integer(lineNr), address, mspMote);
|
||||
breakpoints.add(bp);
|
||||
lastBreakpoint = null;
|
||||
for (ActionListener listener: listeners) {
|
||||
listener.actionPerformed(null);
|
||||
}
|
||||
return bp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove breakpoint at given address.
|
||||
*
|
||||
* @param address Executable address
|
||||
*/
|
||||
public void removeBreakpoint(Integer address) {
|
||||
Breakpoint breakpointToRemove = null;
|
||||
for (Breakpoint breakpoint: breakpoints) {
|
||||
if (breakpoint.getExecutableAddress().intValue() == address.intValue()) {
|
||||
breakpointToRemove = breakpoint;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (breakpointToRemove == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
breakpointToRemove.unregisterBreakpoint();
|
||||
breakpoints.remove(breakpointToRemove);
|
||||
|
||||
// Notify listeners
|
||||
lastBreakpoint = null;
|
||||
for (ActionListener listener: listeners) {
|
||||
listener.actionPerformed(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (Breakpoint breakpoint: breakpoints) {
|
||||
if (breakpoint.getExecutableAddress().intValue() == address.intValue()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return All breakpoints
|
||||
*/
|
||||
public Vector<Breakpoint> getBreakpoints() {
|
||||
return breakpoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a breakpoint listener.
|
||||
* The listener will be notified when breakpoints are added are removed.
|
||||
*
|
||||
* @param listener Breakpoint listener
|
||||
*/
|
||||
public void addBreakpointListener(ActionListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
private void breakpointReached(Breakpoint b) {
|
||||
if (stopOnBreakpointTriggered) {
|
||||
mspMote.getSimulation().stopSimulation();
|
||||
mspMote.stopNextInstruction();
|
||||
}
|
||||
|
||||
// Notify listeners
|
||||
lastBreakpoint = b;
|
||||
for (ActionListener listener: listeners) {
|
||||
listener.actionPerformed(null);
|
||||
}
|
||||
}
|
||||
|
||||
public MspMote getMote() {
|
||||
return mspMote;
|
||||
}
|
||||
|
||||
public Breakpoint getLastTriggered() {
|
||||
return lastBreakpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Breakpoint wrapper class.
|
||||
* May contain breakpoint meta data such source code file and line number.
|
||||
*
|
||||
* @author Fredrik Österlind
|
||||
*/
|
||||
class Breakpoint {
|
||||
private CPUMonitor cpuMonitor = null;
|
||||
private File codeFile = null;
|
||||
private Integer lineNr = null;
|
||||
private Integer address = null;
|
||||
private MspMote mspMote = null;
|
||||
|
||||
/**
|
||||
* Create new uninitialized breakpoint. Used with setConfigXML().
|
||||
*/
|
||||
public Breakpoint(MspMote mote) {
|
||||
this.mspMote = mote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new breakpoint wrapper at given address.
|
||||
*
|
||||
* @param address Executable address
|
||||
* @param mote MSP mote
|
||||
*/
|
||||
public Breakpoint(Integer address, MspMote mote) {
|
||||
this.mspMote = mote;
|
||||
|
||||
cpuMonitor = new CPUMonitor() {
|
||||
public void cpuAction(int type, int adr, int data) {
|
||||
breakpointReached(Breakpoint.this);
|
||||
}
|
||||
};
|
||||
|
||||
mspMote.getCPU().setBreakPoint(address, cpuMonitor);
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new breakpoint wrapper at given address with given meta data.
|
||||
*
|
||||
* @param codeFile Source code file
|
||||
* @param lineNr Source code file line number
|
||||
* @param address Executable address
|
||||
* @param mote MSP mote
|
||||
*/
|
||||
public Breakpoint(File codeFile, Integer lineNr, Integer address, MspMote mote) {
|
||||
this(address, mote);
|
||||
this.codeFile = codeFile;
|
||||
this.lineNr = lineNr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MSP mote
|
||||
*/
|
||||
public MspMote getMote() {
|
||||
return mspMote;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Source code file
|
||||
*/
|
||||
public File getCodeFile() {
|
||||
return codeFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Source code file line number
|
||||
*/
|
||||
public Integer getLineNumber() {
|
||||
return lineNr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Executable address
|
||||
*/
|
||||
public Integer getExecutableAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
private void unregisterBreakpoint() {
|
||||
mspMote.getCPU().setBreakPoint(address, null);
|
||||
}
|
||||
|
||||
public Collection<Element> getConfigXML() {
|
||||
Vector<Element> config = new Vector<Element>();
|
||||
Element element;
|
||||
|
||||
element = new Element("address");
|
||||
element.setText(address.toString());
|
||||
config.add(element);
|
||||
|
||||
if (codeFile != null) {
|
||||
element = new Element("codefile");
|
||||
element.setText(codeFile.getAbsolutePath());
|
||||
config.add(element);
|
||||
}
|
||||
|
||||
if (lineNr != null) {
|
||||
element = new Element("line");
|
||||
element.setText(lineNr.toString());
|
||||
config.add(element);
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) {
|
||||
for (Element element : configXML) {
|
||||
if (element.getName().equals("codefile")) {
|
||||
codeFile = new File(element.getText());
|
||||
if (!codeFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
} else if (element.getName().equals("line")) {
|
||||
lineNr = Integer.parseInt(element.getText());
|
||||
} else if (element.getName().equals("address")) {
|
||||
address = Integer.parseInt(element.getText());
|
||||
}
|
||||
}
|
||||
|
||||
if (address == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cpuMonitor = new CPUMonitor() {
|
||||
public void cpuAction(int type, int adr, int data) {
|
||||
breakpointReached(Breakpoint.this);
|
||||
}
|
||||
};
|
||||
|
||||
mspMote.getCPU().setBreakPoint(address, cpuMonitor);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to, using debugging information from firmware file, calculate the executable address of given meta data.
|
||||
*
|
||||
* @param codeFile Source code file
|
||||
* @param lineNr Source code file line number
|
||||
* @return Executable address or null if not found
|
||||
*/
|
||||
public Integer getExecutableAddressOf(File codeFile, int lineNr) {
|
||||
if (codeFile == null || lineNr < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Match file names
|
||||
Enumeration fileEnum = debuggingInfo.keys();
|
||||
while (fileEnum.hasMoreElements()) {
|
||||
File file = (File) fileEnum.nextElement();
|
||||
if (file != null && file.getName().equals(codeFile.getName())) {
|
||||
/* Found source code file */
|
||||
Hashtable<Integer, Integer> lineTable = debuggingInfo.get(file);
|
||||
Enumeration lineEnum = lineTable.keys();
|
||||
while (lineEnum.hasMoreElements()) {
|
||||
Integer line = (Integer) lineEnum.nextElement();
|
||||
if (line != null && line.intValue() == lineNr) {
|
||||
/* Found line address */
|
||||
return lineTable.get(line);
|
||||
}
|
||||
}
|
||||
// TODO Return null here to only allow unique source files
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Collection<Element> getConfigXML() {
|
||||
Vector<Element> config = new Vector<Element>();
|
||||
Element element;
|
||||
|
||||
for (Breakpoint breakpoint: breakpoints) {
|
||||
element = new Element("breakpoint");
|
||||
|
||||
Collection breakpointXML = breakpoint.getConfigXML();
|
||||
if (breakpointXML != null) {
|
||||
element.addContent(breakpointXML);
|
||||
config.add(element);
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) {
|
||||
for (Element element : configXML) {
|
||||
if (element.getName().equals("breakpoint")) {
|
||||
Breakpoint breakpoint = new Breakpoint(mspMote);
|
||||
boolean ret = breakpoint.setConfigXML(element.getChildren(), visAvailable);
|
||||
if (!ret) {
|
||||
return false;
|
||||
}
|
||||
|
||||
breakpoints.add(breakpoint);
|
||||
lastBreakpoint = null;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void updateInfo() {
|
||||
// Update instructions view
|
||||
instructionsUI.updateRegs();
|
||||
instructionsUI.repaint();
|
||||
|
||||
// Try locate source file
|
||||
File oldCodeFile = codeFile;
|
||||
updateCurrentSourceCodeFile();
|
||||
|
||||
// If found and not already loaded, load source file
|
||||
if (oldCodeFile == null || !oldCodeFile.getPath().equals(codeFile.getPath())) {
|
||||
Vector<String> codeData = readTextFile(codeFile);
|
||||
codeUI.displayNewCode(codeFile, codeData, lineNumber);
|
||||
} else {
|
||||
codeUI.displayLine(lineNumber);
|
||||
}
|
||||
|
||||
codeUI.repaint();
|
||||
|
||||
if (codeFile != null) {
|
||||
filenameLabel.setText(codeFile.getName() + ":" + lineNumber);
|
||||
} else {
|
||||
filenameLabel.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
public void closePlugin() {
|
||||
mySimulation.deleteObserver(simObserver);
|
||||
while (breakpoints.getBreakpoints().size() > 0) {
|
||||
breakpoints.removeBreakpoint(breakpoints.getBreakpoints().firstElement().getExecutableAddress());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void updateCurrentSourceCodeFile() {
|
||||
codeFile = null;
|
||||
|
||||
try {
|
||||
String[] cmd = new String[]{
|
||||
"addr2line",
|
||||
"-e",
|
||||
moteType.getELFFile().getPath(),
|
||||
Utils.hex16(mspMote.getCPU().reg[MSP430.PC])
|
||||
};
|
||||
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
|
||||
BufferedReader input =
|
||||
new BufferedReader(
|
||||
new InputStreamReader(
|
||||
p.getInputStream()));
|
||||
|
||||
String output = input.readLine();
|
||||
input.close();
|
||||
|
||||
if (output == null || output.startsWith("?")) {
|
||||
return;
|
||||
}
|
||||
|
||||
String[] fileInfo = output.split(":");
|
||||
if (fileInfo.length != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO Ugly Cygwin-Windows support
|
||||
fileInfo[0] = fileInfo[0].replace("/cygdrive/c/", "c:/");
|
||||
|
||||
codeFile = new File(fileInfo[0]);
|
||||
lineNumber = Integer.parseInt(fileInfo[1]);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.fatal("Error while calling addr2line: " + e);
|
||||
codeFile = null;
|
||||
lineNumber = -1;
|
||||
}
|
||||
}
|
||||
|
||||
private Hashtable<File, Hashtable<Integer, Integer>> getFirmwareDebugInfo() {
|
||||
return getFirmwareDebugInfo(moteType.getELFFile());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to read debugging information from firmware file using objdump.
|
||||
*
|
||||
* @return Hashtable with debugging information
|
||||
*/
|
||||
public static Hashtable<File, Hashtable<Integer, Integer>> getFirmwareDebugInfo(File firmware) {
|
||||
Hashtable<File, Hashtable<Integer, Integer>> debuggingInfo =
|
||||
new Hashtable<File, Hashtable<Integer, Integer>>();
|
||||
|
||||
Hashtable<Integer, Integer> currentHashtable = null;
|
||||
try {
|
||||
String[] cmd = new String[]{
|
||||
"objdump",
|
||||
"-g",
|
||||
firmware.getPath()
|
||||
};
|
||||
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
|
||||
BufferedReader input =
|
||||
new BufferedReader(
|
||||
new InputStreamReader(
|
||||
p.getInputStream()));
|
||||
|
||||
String line = null;
|
||||
while ((line = input.readLine()) != null) {
|
||||
line = line.trim();
|
||||
|
||||
/* Check for new source file */
|
||||
if (line.endsWith(":")) {
|
||||
String fileName = line.substring(0, line.length()-1);
|
||||
fileName = fileName.replace("/cygdrive/c/", "c:/");
|
||||
currentHashtable = null;
|
||||
|
||||
// Try path unchanged
|
||||
File file = new File(fileName);
|
||||
if (currentHashtable == null && file.exists()) {
|
||||
currentHashtable = new Hashtable<Integer, Integer>();
|
||||
debuggingInfo.put(file, currentHashtable);
|
||||
}
|
||||
|
||||
// Try adding firmwarepath
|
||||
file = new File(firmware.getParent(), fileName);
|
||||
if (currentHashtable == null && file.exists()) {
|
||||
currentHashtable = new Hashtable<Integer, Integer>();
|
||||
debuggingInfo.put(file, currentHashtable);
|
||||
}
|
||||
|
||||
if (currentHashtable == null) { // TODO Currently always true
|
||||
logger.warn("Can't locate file: " + fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for source file line info */
|
||||
if (currentHashtable != null && line.startsWith("/* file ")) {
|
||||
String[] lineInfo = line.split(" ");
|
||||
|
||||
String lineNrString = lineInfo[lineInfo.length-4];
|
||||
String addressString = lineInfo[lineInfo.length-2];
|
||||
|
||||
int lineNr = Integer.parseInt(lineNrString);
|
||||
int address = Integer.parseInt(addressString.substring(2), 16);
|
||||
|
||||
currentHashtable.put(new Integer(lineNr), new Integer(address));
|
||||
}
|
||||
}
|
||||
|
||||
input.close();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.fatal("Error while calling objdump: " + e);
|
||||
}
|
||||
return debuggingInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to open and read given text file.
|
||||
*
|
||||
* @param textFile File
|
||||
* @return Line-by-line text in file
|
||||
*/
|
||||
public static Vector<String> readTextFile(File textFile) {
|
||||
try {
|
||||
BufferedReader in =
|
||||
new BufferedReader(
|
||||
new FileReader(textFile));
|
||||
|
||||
String line;
|
||||
Vector<String> textData = new Vector<String>();
|
||||
while ((line = in.readLine()) != null) {
|
||||
textData.add(line);
|
||||
}
|
||||
|
||||
in.close();
|
||||
|
||||
return textData;
|
||||
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<Element> getConfigXML() {
|
||||
return breakpoints.getConfigXML();
|
||||
}
|
||||
|
||||
public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) {
|
||||
return breakpoints.setConfigXML(configXML, visAvailable);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 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: MspCycleWatcher.java,v 1.1 2008/02/07 14:55:18 fros4943 Exp $
|
||||
*/
|
||||
|
||||
package se.sics.cooja.mspmote.plugins;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import se.sics.cooja.*;
|
||||
import se.sics.cooja.mspmote.MspMote;
|
||||
import se.sics.mspsim.core.MSP430;
|
||||
|
||||
@ClassDescription("Msp Cycle Watcher")
|
||||
@PluginType(PluginType.MOTE_PLUGIN)
|
||||
public class MspCycleWatcher extends VisPlugin {
|
||||
private static Logger logger = Logger.getLogger(MspStackWatcher.class);
|
||||
private MspMote mspMote;
|
||||
private MSP430 cpu;
|
||||
private Simulation simulation;
|
||||
private Observer simObserver = null;
|
||||
private JTextField cycleTextField = new JTextField("");
|
||||
private JTextField resetTextField = new JTextField("");
|
||||
private long cycleReset = 0;
|
||||
|
||||
public MspCycleWatcher(Mote mote, Simulation simulationToVisualize, GUI gui) {
|
||||
super("Msp Cycle Watcher", gui);
|
||||
this.mspMote = (MspMote) mote;
|
||||
cpu = mspMote.getCPU();
|
||||
simulation = simulationToVisualize;
|
||||
|
||||
cycleTextField.setEditable(false);
|
||||
resetTextField.setEditable(false);
|
||||
|
||||
getContentPane().setLayout(new BorderLayout());
|
||||
|
||||
JButton updateButton = new JButton("Update");
|
||||
updateButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
updateLabels();
|
||||
}
|
||||
});
|
||||
|
||||
JButton resetButton = new JButton("Reset");
|
||||
resetButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
cycleReset = cpu.cycles;
|
||||
updateLabels();
|
||||
}
|
||||
});
|
||||
|
||||
JPanel controlPanel = new JPanel(new GridLayout(2,3,5,5));
|
||||
controlPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
controlPanel.add(new JLabel("Total cycles:"));
|
||||
controlPanel.add(cycleTextField);
|
||||
controlPanel.add(updateButton);
|
||||
controlPanel.add(new JLabel("Since reset:"));
|
||||
controlPanel.add(resetTextField);
|
||||
controlPanel.add(resetButton);
|
||||
|
||||
add(BorderLayout.CENTER, controlPanel);
|
||||
|
||||
setSize(370, 100);
|
||||
|
||||
simulation.addObserver(simObserver = new Observer() {
|
||||
public void update(Observable obs, Object obj) {
|
||||
updateLabels();
|
||||
}
|
||||
});
|
||||
|
||||
updateLabels();
|
||||
|
||||
// Tries to select this plugin
|
||||
try {
|
||||
setSelected(true);
|
||||
} catch (java.beans.PropertyVetoException e) {
|
||||
// Could not select
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLabels() {
|
||||
cycleTextField.setText("" + cpu.cycles);
|
||||
resetTextField.setText("" + (cpu.cycles - cycleReset));
|
||||
}
|
||||
|
||||
public void closePlugin() {
|
||||
simulation.deleteObserver(simObserver);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 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: MspStackWatcher.java,v 1.1 2008/02/07 14:55:18 fros4943 Exp $
|
||||
*/
|
||||
|
||||
package se.sics.cooja.mspmote.plugins;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.event.*;
|
||||
import java.util.*;
|
||||
import javax.swing.*;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import se.sics.cooja.*;
|
||||
import se.sics.cooja.mspmote.MspMote;
|
||||
import se.sics.mspsim.core.MSP430;
|
||||
import se.sics.mspsim.util.StackUI;
|
||||
import se.sics.mspsim.util.Utils;
|
||||
|
||||
@ClassDescription("Msp Stack Watcher")
|
||||
@PluginType(PluginType.MOTE_PLUGIN)
|
||||
public class MspStackWatcher extends VisPlugin {
|
||||
private static Logger logger = Logger.getLogger(MspStackWatcher.class);
|
||||
private MspMote mspMote;
|
||||
private MSP430 cpu;
|
||||
private Simulation simulation;
|
||||
private Observer stackObserver = null;
|
||||
private Observer logObserver = null;
|
||||
private JButton startButton;
|
||||
private JButton stopButton;
|
||||
|
||||
public MspStackWatcher(Mote mote, Simulation simulationToVisualize, GUI gui) {
|
||||
super("Msp Stack Watcher", gui);
|
||||
this.mspMote = (MspMote) mote;
|
||||
cpu = mspMote.getCPU();
|
||||
simulation = simulationToVisualize;
|
||||
|
||||
getContentPane().setLayout(new BorderLayout());
|
||||
|
||||
// Register as stack observable
|
||||
if (stackObserver == null) {
|
||||
mspMote.getStackOverflowObservable().addObserver(stackObserver = new Observer() {
|
||||
public void update(Observable obs, Object obj) {
|
||||
simulation.stopSimulation();
|
||||
JOptionPane.showMessageDialog(
|
||||
MspStackWatcher.this,
|
||||
"Bad memory access!\nSimulation stopped.\n" +
|
||||
"\nCurrent stack pointer = 0x" + Utils.hex16(cpu.reg[MSP430.SP]) +
|
||||
"\nStart of heap = 0x" + Utils.hex16(cpu.getDisAsm().getMap().heapStartAddress),
|
||||
"Stack overflow", JOptionPane.ERROR_MESSAGE
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Create stack overflow controls
|
||||
startButton = new JButton("Stop simulation on stack overflow");
|
||||
startButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
startButton.setEnabled(false);
|
||||
stopButton.setEnabled(true);
|
||||
|
||||
mspMote.monitorStack(true);
|
||||
}
|
||||
});
|
||||
|
||||
stopButton = new JButton("Cancel");
|
||||
stopButton.setEnabled(false);
|
||||
stopButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
startButton.setEnabled(true);
|
||||
stopButton.setEnabled(false);
|
||||
|
||||
mspMote.monitorStack(false);
|
||||
}
|
||||
});
|
||||
|
||||
// Create nfi's stack viewer
|
||||
final StackUI stackUI = new StackUI(cpu, MspMote.NR_CYCLES_PER_MSEC);
|
||||
|
||||
// Register as log listener
|
||||
if (logObserver == null && mspMote.getInterfaces().getLog() != null) {
|
||||
mspMote.getInterfaces().getLog().addObserver(logObserver = new Observer() {
|
||||
public void update(Observable obs, Object obj) {
|
||||
stackUI.addNote(mspMote.getInterfaces().getLog().getLastLogMessages());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
JPanel controlPanel = new JPanel(new GridLayout(2,1));
|
||||
controlPanel.add(startButton);
|
||||
controlPanel.add(stopButton);
|
||||
|
||||
add(BorderLayout.CENTER, stackUI);
|
||||
add(BorderLayout.SOUTH, controlPanel);
|
||||
|
||||
setSize(240, 300);
|
||||
|
||||
// Tries to select this plugin
|
||||
try {
|
||||
setSelected(true);
|
||||
} catch (java.beans.PropertyVetoException e) {
|
||||
// Could not select
|
||||
}
|
||||
}
|
||||
|
||||
public void closePlugin() {
|
||||
mspMote.getStackOverflowObservable().deleteObserver(stackObserver);
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in a new issue