diff options
7 files changed, 420 insertions, 6 deletions
diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/plugin.properties b/plugins/org.eclipse.tm.tcf.debug.ui/plugin.properties index 0affb61aa..d635b2bd3 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/plugin.properties +++ b/plugins/org.eclipse.tm.tcf.debug.ui/plugin.properties @@ -17,6 +17,7 @@ debugCallStack = Debug Call Stack DebuggerActionSet.label = TCF Debugger SignalsCommand.label = Signals... +MemoryMapCommand.label = Memory Map... CastToTypeAction.label=Cast To Type... CastToTypeAction.tooltip=Cast Expression To Type diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/plugin.xml b/plugins/org.eclipse.tm.tcf.debug.ui/plugin.xml index 2212f406f..83ea360ec 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/plugin.xml +++ b/plugins/org.eclipse.tm.tcf.debug.ui/plugin.xml @@ -223,6 +223,12 @@ label="%SignalsCommand.label" menubarPath="additions"> </action> + <action + id="org.eclipse.tm.tcf.debug.ui.actions.MemoryMap" + class="org.eclipse.tm.internal.tcf.debug.ui.commands.MemoryMapCommand" + label="%MemoryMapCommand.label" + menubarPath="additions"> + </action> </objectContribution> <!-- ICastToType popup menu contributions --> diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/MemoryMapCommand.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/MemoryMapCommand.java new file mode 100644 index 000000000..a2c1ea6c7 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/MemoryMapCommand.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems, Inc. 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.tm.internal.tcf.debug.ui.commands; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeLaunch; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeStackFrame; + +public class MemoryMapCommand extends AbstractActionDelegate { + + private static boolean isValidNode(TCFNode n) { + if (n instanceof TCFNodeLaunch) return true; + if (n instanceof TCFNodeExecContext) return true; + if (n instanceof TCFNodeStackFrame) return true; + return false; + } + + protected void selectionChanged() { + TCFNode n = getSelectedNode(); + getAction().setEnabled(isValidNode(n)); + } + + protected void run() { + TCFNode n = getSelectedNode(); + if (isValidNode(n)) { + Shell shell = getWindow().getShell(); + try { + new MemoryMapDialog(shell, n).open(); + } + catch (Throwable x) { + MessageBox mb = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK); + mb.setText("Cannot open Memory Map dialog"); + mb.setMessage(TCFModel.getErrorMessage(x, true)); + mb.open(); + } + } + } +} diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/MemoryMapDialog.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/MemoryMapDialog.java new file mode 100644 index 000000000..9a629890c --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/MemoryMapDialog.java @@ -0,0 +1,332 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems, Inc. 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.tm.internal.tcf.debug.ui.commands; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Map; + +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.tm.internal.tcf.debug.launch.TCFLaunchDelegate; +import org.eclipse.tm.internal.tcf.debug.model.TCFLaunch; +import org.eclipse.tm.internal.tcf.debug.ui.Activator; +import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.JSON; +import org.eclipse.tm.tcf.services.IMemory; +import org.eclipse.tm.tcf.services.IMemoryMap; +import org.eclipse.tm.tcf.services.IMemoryMap.MemoryRegion; +import org.eclipse.tm.tcf.util.TCFDataCache; +import org.eclipse.tm.tcf.util.TCFTask; + +class MemoryMapDialog extends Dialog { + + private static final int + SIZING_TABLE_WIDTH = 800, + SIZING_TABLE_HEIGHT = 300; + + private static final String[] column_names = { + "Address", + "Size", + "Flags", + "File Offset", + "File Name" + }; + + private final TCFModel model; + private final IChannel channel; + private final TCFNode selection; + + private Table map_table; + private TableViewer table_viewer; + private IMemoryMap.MemoryRegion[] org_map; + private IMemoryMap.MemoryRegion[] cur_map; + + private TCFNodeExecContext node; + private IMemory.MemoryContext mem_ctx; + + private static class Region implements MemoryRegion, Comparable<Region> { + + final Map<String,Object> props; + final BigInteger addr; + final BigInteger size; + + Region(Map<String,Object> props) { + this.props = props; + Number addr = (Number)props.get(IMemoryMap.PROP_ADDRESS); + Number size = (Number)props.get(IMemoryMap.PROP_SIZE); + this.addr = addr instanceof BigInteger ? (BigInteger)addr : new BigInteger(addr.toString()); + this.size = size instanceof BigInteger ? (BigInteger)size : new BigInteger(size.toString()); + } + + public Number getAddress() { + return addr; + } + + public Number getSize() { + return size; + } + + public Number getOffset() { + return (Number)props.get(IMemoryMap.PROP_OFFSET); + } + + public String getFileName() { + return (String)props.get(IMemoryMap.PROP_FILE_NAME); + } + + public int getFlags() { + Number n = (Number)props.get(IMemoryMap.PROP_FLAGS); + if (n != null) return n.intValue(); + return 0; + } + + public Map<String,Object> getProperties() { + return props; + } + + public int compareTo(Region r) { + return addr.compareTo(r.addr); + } + } + + private final IStructuredContentProvider content_provider = new IStructuredContentProvider() { + + public Object[] getElements(Object input) { + return cur_map; + } + + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + }; + + private class MapLabelProvider extends LabelProvider implements ITableLabelProvider { + + public Image getColumnImage(Object element, int column) { + return null; + } + + public String getColumnText(Object element, int column) { + Region r = (Region)element; + switch (column) { + case 0: + case 1: + { + BigInteger x = column == 0 ? r.addr : r.size; + String s = x.toString(16); + int sz = mem_ctx.getAddressSize() * 2; + int l = sz - s.length(); + if (l < 0) l = 0; + if (l > 16) l = 16; + return "0x0000000000000000".substring(0, 2 + l) + s; + } + case 2: + { + int n = r.getFlags(); + StringBuffer bf = new StringBuffer(); + if ((n & IMemoryMap.FLAG_READ) != 0) bf.append('r'); + if ((n & IMemoryMap.FLAG_WRITE) != 0) bf.append('w'); + if ((n & IMemoryMap.FLAG_EXECUTE) != 0) bf.append('x'); + return bf.toString(); + } + case 3: + { + Number n = r.getOffset(); + if (n == null) return ""; + BigInteger x = n instanceof BigInteger ? (BigInteger)n : new BigInteger(n.toString()); + String s = x.toString(16); + int l = 16 - s.length(); + if (l < 0) l = 0; + if (l > 16) l = 16; + return "0x0000000000000000".substring(0, 2 + l) + s; + } + case 4: + return r.getFileName(); + } + return ""; + } + + public String getText(Object element) { + return element.toString(); + } + } + + MemoryMapDialog(Shell parent, TCFNode node) { + super(parent); + model = node.getModel(); + channel = node.getChannel(); + selection = node; + } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText("Memory Map"); + shell.setImage(ImageCache.getImage(ImageCache.IMG_SIGNALS)); + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + createButton(parent, IDialogConstants.OK_ID, "&OK", true); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite)super.createDialogArea(parent); + + createMemoryMapTable(composite); + + composite.setSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + return composite; + } + + private void createMemoryMapTable(Composite parent) { + Font font = parent.getFont(); + Label props_label = new Label(parent, SWT.WRAP); + props_label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + props_label.setFont(font); + props_label.setText("&Memory Map:"); + + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1)); + + map_table = new Table(composite, + SWT.SINGLE | SWT.BORDER | + SWT.H_SCROLL | SWT.V_SCROLL); + map_table.setFont(font); + GridData data = new GridData(GridData.FILL_BOTH); + data.widthHint = SIZING_TABLE_WIDTH; + data.heightHint = SIZING_TABLE_HEIGHT; + map_table.setLayoutData(data); + + int w = SIZING_TABLE_WIDTH / (column_names.length + 5); + for (int i = 0; i < column_names.length; i++) { + final TableColumn column = new TableColumn(map_table, SWT.LEAD, i); + column.setMoveable(false); + column.setText(column_names[i]); + switch (i) { + case 0: + case 1: + case 3: + column.setWidth(w * 2); + break; + case 4: + column.setWidth(w * 4); + break; + default: + column.setWidth(w); + break; + } + } + map_table.setHeaderVisible(true); + map_table.setLinesVisible(true); + map_table.addMouseListener(new MouseListener() { + + public void mouseDoubleClick(MouseEvent e) { + } + + public void mouseDown(MouseEvent e) { + } + + public void mouseUp(MouseEvent e) { + } + }); + + table_viewer = new TableViewer(map_table); + table_viewer.setUseHashlookup(true); + table_viewer.setColumnProperties(column_names); + + cur_map = new TCFTask<IMemoryMap.MemoryRegion[]>(channel) { + public void run() { + TCFNode n = selection; + while (n != null) { + if (n instanceof TCFNodeExecContext) { + TCFDataCache<IMemory.MemoryContext> dc = ((TCFNodeExecContext)n).getMemoryContext(); + if (!dc.validate(this)) return; + if (dc.getError() != null) { + error(dc.getError()); + return; + } + if (dc.getData() != null) { + mem_ctx = dc.getData(); + break; + } + } + n = n.getParent(); + } + node = (TCFNodeExecContext)n; + ArrayList<IMemoryMap.MemoryRegion> lst = new ArrayList<IMemoryMap.MemoryRegion>(); + if (node != null) { + TCFDataCache<TCFNodeExecContext.MemoryRegion[]> dc = node.getMemoryMap(); + if (!dc.validate(this)) return; + if (dc.getError() != null) { + error(dc.getError()); + return; + } + if (dc.getData() != null) { + for (TCFNodeExecContext.MemoryRegion m : dc.getData()) { + lst.add(new Region(m.region.getProperties())); + } + } + } + try { + TCFLaunch launch = model.getLaunch(); + ILaunchConfiguration cfg = launch.getLaunchConfiguration(); + String map = cfg.getAttribute(TCFLaunchDelegate.ATTR_MEMORY_MAP, ""); + if (map.length() > 0) { + JSON.parseOne(map.getBytes("UTF-8")); + } + } + catch (Throwable x) { + Activator.log("Invalid launch cofiguration attribute", x); + } + done(lst.toArray(new IMemoryMap.MemoryRegion[lst.size()])); + } + }.getE(); + Arrays.sort(cur_map); + org_map = new IMemoryMap.MemoryRegion[cur_map.length]; + System.arraycopy(cur_map, 0, org_map, 0, cur_map.length); + table_viewer.setContentProvider(content_provider); + + table_viewer.setLabelProvider(new MapLabelProvider()); + table_viewer.setInput(this); + } +} diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/SignalsCommand.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/SignalsCommand.java index c41371a73..f7725f467 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/SignalsCommand.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/SignalsCommand.java @@ -10,6 +10,10 @@ *******************************************************************************/ package org.eclipse.tm.internal.tcf.debug.ui.commands; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeLaunch; @@ -31,6 +35,17 @@ public class SignalsCommand extends AbstractActionDelegate { protected void run() { TCFNode n = getSelectedNode(); - if (isValidNode(n)) new SignalsDialog(getWindow().getShell(), n).open(); + if (isValidNode(n)) { + Shell shell = getWindow().getShell(); + try { + new SignalsDialog(shell, n).open(); + } + catch (Throwable x) { + MessageBox mb = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK); + mb.setText("Cannot open Signals dialog"); + mb.setMessage(TCFModel.getErrorMessage(x, true)); + mb.open(); + } + } } } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/SignalsDialog.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/SignalsDialog.java index 03eab61e4..7824a51e5 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/SignalsDialog.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/SignalsDialog.java @@ -60,7 +60,14 @@ class SignalsDialog extends Dialog { SIZING_TABLE_WIDTH = 800, SIZING_TABLE_HEIGHT = 300; - private static final String[] column_names = { "Code", "Name", "Description", "Don't stop", "Don't pass", "Pending" }; + private static final String[] column_names = { + "Code", + "Name", + "Description", + "Don't stop", + "Don't pass", + "Pending" + }; private static class Signal extends SignalMask { @@ -196,7 +203,8 @@ class SignalsDialog extends Dialog { composite.setLayout(layout); composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1)); - signal_table = new Table(composite, SWT.SINGLE | SWT.BORDER | + signal_table = new Table(composite, + SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); signal_table.setFont(font); GridData data = new GridData(GridData.FILL_BOTH); @@ -275,7 +283,7 @@ class SignalsDialog extends Dialog { while (n != null && !(n instanceof TCFNodeExecContext)) n = n.getParent(); node = (TCFNodeExecContext)n; if (node == null) { - TCFLaunch launch = selection.getModel().getLaunch(); + TCFLaunch launch = model.getLaunch(); Collection<Map<String,Object>> sigs = launch.getSignalList(); if (sigs == null) { done(new Signal[0]); @@ -347,7 +355,7 @@ class SignalsDialog extends Dialog { if ((x == null || !x.isPending()) && s.isPending()) send_list.add(s.getCode()); } if (set_mask) { - TCFLaunch launch = selection.getModel().getLaunch(); + TCFLaunch launch = model.getLaunch(); ILaunchConfigurationWorkingCopy cfg = launch.getLaunchConfiguration().getWorkingCopy(); cfg.setAttribute(TCFLaunchDelegate.ATTR_SIGNALS_DONT_STOP, Integer.toHexString(dont_stop_set)); cfg.setAttribute(TCFLaunchDelegate.ATTR_SIGNALS_DONT_PASS, Integer.toHexString(dont_pass_set)); diff --git a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/launch/TCFLaunchDelegate.java b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/launch/TCFLaunchDelegate.java index 4f5533117..87d3829bd 100644 --- a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/launch/TCFLaunchDelegate.java +++ b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/launch/TCFLaunchDelegate.java @@ -49,7 +49,8 @@ public class TCFLaunchDelegate extends LaunchConfigurationDelegate { ATTR_USE_LOCAL_AGENT = ITCFConstants.ID_TCF_DEBUG_MODEL + ".UseLocalAgent", ATTR_SIGNALS_DONT_STOP = ITCFConstants.ID_TCF_DEBUG_MODEL + ".SignalsDontStop", ATTR_SIGNALS_DONT_PASS = ITCFConstants.ID_TCF_DEBUG_MODEL + ".SignalsDontPath", - ATTR_PATH_MAP = ITCFConstants.ID_TCF_DEBUG_MODEL + ".PathMap"; + ATTR_PATH_MAP = ITCFConstants.ID_TCF_DEBUG_MODEL + ".PathMap", + ATTR_MEMORY_MAP = ITCFConstants.ID_TCF_DEBUG_MODEL + ".MemoryMap"; public static class PathMapRule implements IPathMap.PathMapRule { |