Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreutarass2011-09-26 16:57:02 +0000
committereutarass2011-09-26 16:57:02 +0000
commit43bd0e13f016c93594cfaa025cadf6e7861b97dd (patch)
treee886138594485baa031f895843a8694c4d8e2298 /plugins
parent3d9a9333017719e7c39fdc9a94ca45f3b8c3814d (diff)
downloadorg.eclipse.tcf-43bd0e13f016c93594cfaa025cadf6e7861b97dd.tar.gz
org.eclipse.tcf-43bd0e13f016c93594cfaa025cadf6e7861b97dd.tar.xz
org.eclipse.tcf-43bd0e13f016c93594cfaa025cadf6e7861b97dd.zip
TCF Debugger: lost revisions (2094..) re-applied to TCFDisassemblyBackend.java
Diffstat (limited to 'plugins')
-rw-r--r--plugins/org.eclipse.tm.tcf.cdt.ui/src/org/eclipse/tm/internal/tcf/cdt/ui/disassembly/TCFDisassemblyBackend.java1984
1 files changed, 985 insertions, 999 deletions
diff --git a/plugins/org.eclipse.tm.tcf.cdt.ui/src/org/eclipse/tm/internal/tcf/cdt/ui/disassembly/TCFDisassemblyBackend.java b/plugins/org.eclipse.tm.tcf.cdt.ui/src/org/eclipse/tm/internal/tcf/cdt/ui/disassembly/TCFDisassemblyBackend.java
index 596bfc3e9..efcc2812c 100644
--- a/plugins/org.eclipse.tm.tcf.cdt.ui/src/org/eclipse/tm/internal/tcf/cdt/ui/disassembly/TCFDisassemblyBackend.java
+++ b/plugins/org.eclipse.tm.tcf.cdt.ui/src/org/eclipse/tm/internal/tcf/cdt/ui/disassembly/TCFDisassemblyBackend.java
@@ -1,999 +1,985 @@
-/*******************************************************************************
- * Copyright (c) 2010, 2011 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.cdt.ui.disassembly;
-
-import static org.eclipse.cdt.debug.internal.ui.disassembly.dsf.DisassemblyUtils.DEBUG;
-
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.eclipse.cdt.debug.internal.ui.disassembly.dsf.AbstractDisassemblyBackend;
-import org.eclipse.cdt.debug.internal.ui.disassembly.dsf.AddressRangePosition;
-import org.eclipse.cdt.debug.internal.ui.disassembly.dsf.DisassemblyUtils;
-import org.eclipse.cdt.debug.internal.ui.disassembly.dsf.ErrorPosition;
-import org.eclipse.cdt.debug.internal.ui.disassembly.dsf.IDisassemblyPartCallback;
-import org.eclipse.core.runtime.IAdaptable;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.debug.core.DebugPlugin;
-import org.eclipse.debug.core.ILaunch;
-import org.eclipse.debug.core.ILaunchesListener;
-import org.eclipse.debug.core.model.ISourceLocator;
-import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
-import org.eclipse.jface.dialogs.ErrorDialog;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.jface.text.IDocumentExtension4;
-import org.eclipse.jface.text.Position;
-import org.eclipse.tm.internal.tcf.cdt.ui.Activator;
-import org.eclipse.tm.internal.tcf.debug.model.TCFContextState;
-import org.eclipse.tm.internal.tcf.debug.model.TCFSourceRef;
-import org.eclipse.tm.internal.tcf.debug.ui.model.TCFChildrenStackTrace;
-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.TCFNodeStackFrame;
-import org.eclipse.tm.tcf.protocol.IChannel;
-import org.eclipse.tm.tcf.protocol.IChannel.IChannelListener;
-import org.eclipse.tm.tcf.protocol.IToken;
-import org.eclipse.tm.tcf.protocol.Protocol;
-import org.eclipse.tm.tcf.services.IDisassembly;
-import org.eclipse.tm.tcf.services.IDisassembly.DoneDisassemble;
-import org.eclipse.tm.tcf.services.IDisassembly.IDisassemblyLine;
-import org.eclipse.tm.tcf.services.IExpressions;
-import org.eclipse.tm.tcf.services.IExpressions.DoneCreate;
-import org.eclipse.tm.tcf.services.IExpressions.DoneDispose;
-import org.eclipse.tm.tcf.services.IExpressions.DoneEvaluate;
-import org.eclipse.tm.tcf.services.IExpressions.Expression;
-import org.eclipse.tm.tcf.services.IExpressions.Value;
-import org.eclipse.tm.tcf.services.ILineNumbers;
-import org.eclipse.tm.tcf.services.ILineNumbers.CodeArea;
-import org.eclipse.tm.tcf.services.ILineNumbers.DoneMapToSource;
-import org.eclipse.tm.tcf.services.IMemory;
-import org.eclipse.tm.tcf.services.IRunControl;
-import org.eclipse.tm.tcf.services.IRunControl.RunControlContext;
-import org.eclipse.tm.tcf.services.IRunControl.RunControlListener;
-import org.eclipse.tm.tcf.services.ISymbols;
-import org.eclipse.tm.tcf.util.TCFDataCache;
-import org.eclipse.tm.tcf.util.TCFTask;
-import org.eclipse.ui.PlatformUI;
-
-@SuppressWarnings("restriction")
-public class TCFDisassemblyBackend extends AbstractDisassemblyBackend {
-
- private static class AddressRange {
- BigInteger start;
- BigInteger end;
- }
- private static class FunctionOffset {
- static final FunctionOffset NONE = new FunctionOffset(null, null);
- String name;
- BigInteger offset;
- FunctionOffset(String name, BigInteger offset) {
- this.name = name;
- this.offset = offset;
- }
- @Override
- public String toString() {
- if (name == null || name.length() == 0) {
- return "";
- }
- if (isZeroOffset()) {
- return name;
- }
- return name + '+' + offset.toString();
- }
- boolean isZeroOffset() {
- return offset == null || offset.compareTo(BigInteger.ZERO) == 0;
- }
- }
- private class TCFLaunchListener implements ILaunchesListener {
-
- public void launchesRemoved(ILaunch[] launches) {
- }
-
- public void launchesAdded(ILaunch[] launches) {
- }
-
- public void launchesChanged(ILaunch[] launches) {
- if(fExecContext == null) {
- return;
- }
- for (ILaunch launch : launches) {
- if (launch == fExecContext.getModel().getLaunch()) {
- if (launch.isTerminated()) {
- handleSessionEnded();
- }
- break;
- }
- }
- }
- }
-
- private class TCFChannelListener implements IChannelListener {
-
- public void onChannelOpened() {
- }
-
- public void onChannelClosed(Throwable error) {
- handleSessionEnded();
- }
-
- public void congestionLevel(int level) {
- }
- }
-
- private class TCFRunControlListener implements RunControlListener {
-
- public void contextAdded(RunControlContext[] contexts) {
- }
-
- public void contextChanged(RunControlContext[] contexts) {
- }
-
- public void contextRemoved(String[] context_ids) {
- String id = fExecContext.getID();
- for (String contextId : context_ids) {
- if (id.equals(contextId)) {
- fCallback.handleTargetEnded();
- return;
- }
- }
- }
-
- public void contextSuspended(String context, String pc, String reason,
- Map<String, Object> params) {
- if (fExecContext.getID().equals(context)) {
- handleContextSuspended(pc != null ? new BigInteger(pc) : null);
- }
- }
-
- public void contextResumed(String context) {
- if (fExecContext.getID().equals(context)) {
- fCallback.handleTargetResumed();
- }
- }
-
- public void containerSuspended(String context, String pc,
- String reason, Map<String, Object> params,
- String[] suspended_ids) {
- String id = fExecContext.getID();
- if (id.equals(context)) {
- handleContextSuspended(pc != null ? new BigInteger(pc) : null);
- return;
- }
- for (String contextId : suspended_ids) {
- if (id.equals(contextId)) {
- handleContextSuspended(null);
- return;
- }
- }
- }
-
- public void containerResumed(String[] context_ids) {
- String id = fExecContext.getID();
- for (String contextId : context_ids) {
- if (id.equals(contextId)) {
- fCallback.handleTargetResumed();
- return;
- }
- }
- }
-
- public void contextException(String context, String msg) {
- }
-
- }
-
- private IDisassemblyPartCallback fCallback;
- private volatile TCFNodeExecContext fExecContext;
- private volatile TCFNodeStackFrame fActiveFrame;
- private volatile BigInteger fSuspendAddress;
- private volatile int fSuspendCount;
-
- private final IRunControl.RunControlListener fRunControlListener = new TCFRunControlListener();
- private final IChannelListener fChannelListener = new TCFChannelListener();
- private final ILaunchesListener fLaunchesListener = new TCFLaunchListener();
-
- @Override
- public void init(IDisassemblyPartCallback callback) {
- fCallback = callback;
- }
-
- public boolean supportsDebugContext(IAdaptable context) {
- return (context instanceof TCFNodeExecContext || context instanceof TCFNodeStackFrame)
- && hasDisassemblyService((TCFNode) context);
- }
-
- private boolean hasDisassemblyService(final TCFNode context) {
- Boolean hasService = new TCFTask<Boolean>() {
- public void run() {
- IDisassembly disass = null;
- IChannel channel = context.getChannel();
- if (channel != null && channel.getState() != IChannel.STATE_CLOSED) {
- disass = channel.getRemoteService(IDisassembly.class);
- }
- done(disass != null);
- }
- }.getE();
- return hasService != null && hasService.booleanValue();
- }
-
- public boolean hasDebugContext() {
- return fExecContext != null;
- }
-
- public SetDebugContextResult setDebugContext(IAdaptable context) {
- TCFNodeExecContext newContext = null;
- TCFNodeStackFrame frame = null;
- SetDebugContextResult result = new SetDebugContextResult();
- if (context instanceof TCFNodeExecContext) {
- newContext = (TCFNodeExecContext) context;
- final TCFNodeExecContext _execContext = newContext;
- frame = new TCFTask<TCFNodeStackFrame>(_execContext.getChannel()) {
- public void run() {
- TCFChildrenStackTrace stack = _execContext.getStackTrace();
- if (!stack.validate(this)) {
- return;
- }
- done(stack.getTopFrame());
- }
- }.getE();
- if (frame == null) {
- newContext = null;
- }
- } else if (context instanceof TCFNodeStackFrame) {
- final TCFNodeStackFrame _frame = frame = (TCFNodeStackFrame) context;
- newContext = new TCFTask<TCFNodeExecContext>(_frame.getChannel()) {
- public void run() {
- TCFNode parent = _frame.getParent();
- if (parent instanceof TCFNodeExecContext) {
- done((TCFNodeExecContext) parent);
- } else {
- done(null);
- }
- }
- }.getE();
- }
- TCFNodeExecContext oldContext = fExecContext;
- if (oldContext == null || newContext == null || oldContext.compareTo(newContext) != 0) {
- result.contextChanged = true;
- fSuspendCount++;
- if (oldContext != null) {
- removeListeners(oldContext);
- }
- }
- fExecContext = newContext;
- if (newContext != null && result.contextChanged) {
- addListeners(newContext);
- }
- fActiveFrame = frame;
- result.sessionId = newContext != null ? newContext.getID() : null;
-
- if (!result.contextChanged && fActiveFrame != null) {
- fCallback.asyncExec(new Runnable() {
- public void run() {
- fCallback.gotoFrameIfActive(getFrameLevel());
- }
- });
- }
-
- return result;
- }
-
- private void addListeners(final TCFNodeExecContext context) {
- assert context != null;
- Protocol.invokeAndWait(new Runnable() {
- public void run() {
- IChannel channel = context.getChannel();
- IRunControl rctl = channel.getRemoteService(IRunControl.class);
- if (rctl != null) {
- rctl.addListener(fRunControlListener);
- }
- channel.addChannelListener(fChannelListener);
- }
- });
- DebugPlugin.getDefault().getLaunchManager().addLaunchListener(fLaunchesListener );
- }
-
- private void removeListeners(final TCFNodeExecContext context) {
- assert context != null;
- DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(fLaunchesListener);
- Protocol.invokeAndWait(new Runnable() {
- public void run() {
- IChannel channel = context.getChannel();
- IRunControl rctl = channel.getRemoteService(IRunControl.class);
- if (rctl != null) {
- rctl.removeListener(fRunControlListener);
- }
- channel.removeChannelListener(fChannelListener);
- }
- });
- }
-
- private void handleContextSuspended(BigInteger pc) {
- ++fSuspendCount;
- fSuspendAddress = pc;
- fCallback.handleTargetSuspended();
- }
- private void handleSessionEnded() {
- clearDebugContext();
- fCallback.handleTargetEnded();
- }
-
- public void clearDebugContext() {
- if (fExecContext != null) {
- removeListeners(fExecContext);
- }
- fExecContext = null;
- fActiveFrame = null;
- }
-
- public void retrieveFrameAddress(final int targetFrame) {
- final TCFNodeExecContext execContext = fExecContext;
- if (execContext == null) {
- fCallback.setUpdatePending(false);
- return;
- }
- BigInteger address;
- if (targetFrame == 0 && fSuspendAddress != null) {
- // shortcut for goto frame on suspend
- address = fSuspendAddress;
- fSuspendAddress = null;
- } else {
- final int suspendCount = fSuspendCount;
- final TCFChildrenStackTrace stack = execContext.getStackTrace();
- address = new TCFTask<BigInteger>(execContext.getChannel()) {
- public void run() {
- if (suspendCount != fSuspendCount || execContext != fExecContext) {
- done(null);
- return;
- }
- if (!stack.validate(this)) {
- return;
- }
- TCFNodeStackFrame frame = null;
- if (targetFrame == 0) {
- frame = stack.getTopFrame();
- } else {
- Map<String,TCFNode> frameData = stack.getData();
- for (TCFNode node : frameData.values()) {
- if (node instanceof TCFNodeStackFrame) {
- TCFNodeStackFrame cand = (TCFNodeStackFrame) node;
- if (cand.getFrameNo() == targetFrame) {
- frame = cand;
- break;
- }
- }
- }
- }
- if (frame != null) {
- TCFDataCache<BigInteger> addressCache = frame.getAddress();
- if (!addressCache.validate(this)) {
- return;
- }
- done(addressCache.getData());
- return;
- }
- done(null);
- }
- }.getE();
- }
-
- if (execContext == fExecContext) {
- fCallback.setUpdatePending(false);
- if (address != null) {
- if (targetFrame == 0) {
- fCallback.updatePC(address);
- } else {
- fCallback.gotoFrame(targetFrame, address);
- }
- }
- }
- }
-
- public int getFrameLevel() {
- if (fActiveFrame == null) {
- return -1;
- }
- Integer level = new TCFTask<Integer>() {
- public void run() {
- done(fActiveFrame != null ? fActiveFrame.getFrameNo() : -1);
- }
- }.getE();
- return level != null ? level.intValue() : -1;
- }
-
- public boolean isSuspended() {
- if (fExecContext == null) {
- return false;
- }
- Boolean suspended = new TCFTask<Boolean>(fExecContext.getChannel()) {
- public void run() {
- if (fExecContext == null) {
- done(null);
- return;
- }
- TCFDataCache<TCFContextState> stateCache = fExecContext.getState();
- if (!stateCache.validate(this)) {
- return;
- }
- TCFContextState state = stateCache.getData();
- if (state != null) {
- done(state.is_suspended);
- return;
- }
- done(null);
- }
- }.getE();
- return suspended != null ? suspended.booleanValue() : false;
- }
-
- public boolean hasFrameContext() {
- return fActiveFrame != null;
- }
-
- public String getFrameFile() {
- final TCFNodeStackFrame frame = fActiveFrame;
- if (frame == null) {
- return null;
- }
- String file = new TCFTask<String>(frame.getChannel()) {
- public void run() {
- if (frame != fActiveFrame) {
- done(null);
- return;
- }
- TCFDataCache<TCFSourceRef> sourceRefCache = frame.getLineInfo();
- if (!sourceRefCache.validate(this)) {
- return;
- }
- TCFSourceRef sourceRef = sourceRefCache.getData();
- String file = sourceRef.area.file;
- if (file != null) {
- IPath filePath = new Path(file);
- if (!filePath.isAbsolute()) {
- String dir = sourceRef.area.directory;
- if (dir != null) {
- filePath = new Path(dir).append(filePath);
- }
- }
- done(filePath.toString());
- }
- done(null);
- }
- }.getE();
- return file;
- }
-
- public int getFrameLine() {
- final TCFNodeStackFrame frame = fActiveFrame;
- if (frame == null) {
- return -1;
- }
- Integer line = new TCFTask<Integer>(frame.getChannel()) {
- public void run() {
- if (frame != fActiveFrame) {
- done(null);
- return;
- }
- TCFDataCache<TCFSourceRef> sourceRefCache = frame.getLineInfo();
- if (!sourceRefCache.validate(this)) {
- return;
- }
- TCFSourceRef sourceRef = sourceRefCache.getData();
- done(sourceRef.area.start_line);
- }
- }.getE();
- return line != null ? line.intValue() : -1;
- }
-
- public void retrieveDisassembly(final BigInteger startAddress,
- BigInteger endAddress, String file, int lineNumber, int lines,
- final boolean mixed, final boolean showSymbols, boolean showDisassembly,
- final int linesHint) {
- final TCFNodeExecContext execContext = fExecContext;
- if (execContext == null || execContext.isDisposed()) {
- fCallback.setUpdatePending(false);
- return;
- }
- final int suspendCount = fSuspendCount;
- final long modCount = getModCount();
- Protocol.invokeLater(new Runnable() {
- public void run() {
- if (execContext != fExecContext) {
- return;
- }
- if (suspendCount != fSuspendCount) {
- fCallback.setUpdatePending(false);
- return;
- }
- final IChannel channel = execContext.getChannel();
- IDisassembly disass = channel.getRemoteService(IDisassembly.class);
- if (disass == null) {
- fCallback.setUpdatePending(false);
- return;
- }
- TCFDataCache<TCFNodeExecContext> mem_node_cache = execContext.getModel().searchMemoryContext(execContext);
- if (!mem_node_cache.validate(this)) return;
- TCFNodeExecContext memContext = mem_node_cache.getData();
- if (memContext == null) {
- fCallback.setUpdatePending(false);
- return;
- }
- TCFDataCache<IMemory.MemoryContext> cache = memContext.getMemoryContext();
- if (!cache.validate(this)) return;
- final IMemory.MemoryContext mem = cache.getData();
- if (mem == null) {
- fCallback.setUpdatePending(false);
- return;
- }
- final String contextId = mem.getID();
- Map<String, Object> params = new HashMap<String, Object>();
- disass.disassemble(contextId, startAddress, linesHint*4, params, new DoneDisassemble() {
- public void doneDisassemble(IToken token, final Throwable error,
- final IDisassemblyLine[] disassembly) {
- if (execContext != fExecContext) {
- return;
- }
- if (error != null) {
- fCallback.asyncExec(new Runnable() {
- public void run() {
- if (execContext != fExecContext) {
- return;
- }
- if (modCount == getModCount()) {
- fCallback.insertError(startAddress, TCFModel.getErrorMessage(error, false));
- fCallback.setUpdatePending(false);
- }
- }
- });
- return;
- }
- doneGetDisassembly(disassembly);
- }
-
- private void doneGetDisassembly(final IDisassemblyLine[] disassembly) {
- if (!showSymbols) {
- doneGetSymbols(disassembly, null);
- return;
- }
- final ISymbols symbols = channel.getRemoteService(ISymbols.class);
- if (symbols == null) {
- doneGetSymbols(disassembly, null);
- return;
- }
- final ArrayList<ISymbols.Symbol> symbolList = new ArrayList<ISymbols.Symbol>();
- final int[] idx = { 0 };
- IDisassemblyLine line = disassembly[idx[0]];
- Number address = line.getAddress();
- symbols.findByAddr(contextId, address, new ISymbols.DoneFind() {
- ISymbols.DoneFind doneFind = this;
- public void doneFind(IToken token, Exception error, String symbol_id) {
- if (error == null && symbol_id != null) {
- symbols.getContext(symbol_id, new ISymbols.DoneGetContext() {
- public void doneGetContext(IToken token, Exception error, ISymbols.Symbol context) {
- BigInteger nextAddress = null;
- if (error == null && context != null) {
- if (context.getTypeClass().equals(ISymbols.TypeClass.function)) {
- symbolList.add(context);
- nextAddress = toBigInteger(context.getAddress()).add(BigInteger.valueOf(context.getSize()));
- }
- }
- findNextSymbol(nextAddress);
- }
- });
- return;
- }
- findNextSymbol(null);
- }
- private void findNextSymbol(BigInteger nextAddress) {
- while (++idx[0] < disassembly.length) {
- BigInteger instrAddress = toBigInteger(disassembly[idx[0]].getAddress());
- if (nextAddress == null) {
- nextAddress = instrAddress;
- } else if (instrAddress.compareTo(nextAddress) < 0) {
- continue;
- }
- symbols.findByAddr(contextId, instrAddress, doneFind);
- return;
- }
- ISymbols.Symbol[] functionSymbols =
- symbolList.toArray(new ISymbols.Symbol[symbolList.size()]);
- doneGetSymbols(disassembly, functionSymbols);
- }
- });
- }
-
- private void doneGetSymbols(final IDisassemblyLine[] disassembly, final ISymbols.Symbol[] symbols) {
- ILineNumbers lineNumbers = null;
- if (mixed) {
- lineNumbers = channel.getRemoteService(ILineNumbers.class);
- }
- if (lineNumbers == null) {
- doneGetLineNumbers(disassembly, symbols, null);
- } else {
- AddressRange range = getAddressRange(disassembly);
- lineNumbers.mapToSource(contextId, range.start, range.end, new DoneMapToSource() {
- public void doneMapToSource(IToken token, Exception error, final CodeArea[] areas) {
- if (error != null) {
- Activator.log(error);
- doneGetLineNumbers(disassembly, symbols, null);
- } else {
- doneGetLineNumbers(disassembly, symbols, areas);
- }
- }
- });
- }
- }
-
- private void doneGetLineNumbers( final IDisassemblyLine[] disassembly, final ISymbols.Symbol[] symbols, final CodeArea[] areas) {
- fCallback.asyncExec(new Runnable() {
- public void run() {
- insertDisassembly(modCount, startAddress, disassembly, symbols, areas);
- }
- });
- }
-
- private AddressRange getAddressRange(IDisassemblyLine[] lines) {
- AddressRange range = new AddressRange();
- range.start = toBigInteger(lines[0].getAddress());
- IDisassemblyLine lastLine = lines[lines.length-1];
- range.end = toBigInteger(lastLine.getAddress()).add(BigInteger.valueOf(lastLine.getSize()));
- return range;
- }
- });
- }
- });
- }
-
- private long getModCount() {
- return ((IDocumentExtension4) fCallback.getDocument()).getModificationStamp();
- }
-
- protected final void insertDisassembly(long modCount, BigInteger startAddress, IDisassemblyLine[] instructions, ISymbols.Symbol[] symbols, CodeArea[] codeAreas) {
- if (!fCallback.hasViewer() || fExecContext == null) {
- return;
- }
- if (modCount != getModCount()) {
- return;
- }
- if (DEBUG) System.out.println("insertDisassembly "+ DisassemblyUtils.getAddressText(startAddress)); //$NON-NLS-1$
- boolean updatePending = fCallback.getUpdatePending();
- assert updatePending;
- if (!updatePending) {
- // safe-guard in case something weird is going on
- return;
- }
-
- boolean insertedAnyAddress = false;
- try {
- fCallback.lockScroller();
-
- AddressRangePosition p= null;
- for (IDisassemblyLine instruction : instructions) {
- BigInteger address;
- if (instruction.getAddress() instanceof BigInteger) {
- address = (BigInteger) instruction.getAddress();
- } else {
- address = BigInteger.valueOf(instruction.getAddress().longValue());
- }
- if (startAddress == null) {
- startAddress = address;
- fCallback.setGotoAddressPending(address);
- }
- if (p == null || !p.containsAddress(address)) {
- p = fCallback.getPositionOfAddress(address);
- }
- if (p instanceof ErrorPosition && p.fValid) {
- p.fValid = false;
- fCallback.getDocument().addInvalidAddressRange(p);
- } else if (p == null /* || address.compareTo(endAddress) > 0 */) {
- if (DEBUG) System.out.println("Excess disassembly lines at " + DisassemblyUtils.getAddressText(address)); //$NON-NLS-1$
- return;
- } else if (p.fValid) {
- if (DEBUG) System.out.println("Excess disassembly lines at " + DisassemblyUtils.getAddressText(address)); //$NON-NLS-1$
-// if (!p.fAddressOffset.equals(address)) {
-// // override probably unaligned disassembly
-// p.fValid = false;
-// fCallback.getDocument().addInvalidAddressRange(p);
-// } else {
- continue;
-// }
- }
-
- // insert source
- String sourceFile = null;
- int firstLine = -1;
- int lastLine = -1;
- CodeArea area = findCodeArea(address, codeAreas);
- if (area != null) {
- if (area.file != null) {
- IPath filePath = new Path(area.file);
- if (!filePath.isAbsolute() && area.directory != null) {
- filePath = new Path(area.directory).append(filePath);
- }
- sourceFile = filePath.toString();
- firstLine = area.start_line - 1;
- lastLine = area.end_line - 2;
- }
- }
- if (sourceFile != null && firstLine >= 0) {
- try {
- p = fCallback.insertSource(p, address, sourceFile, firstLine, lastLine);
- } catch (NoSuchMethodError nsme) {
- // use fallback
- p = fCallback.insertSource(p, address, sourceFile, firstLine);
- }
- }
-
- // insert symbol label
- FunctionOffset functionOffset = getFunctionOffset(address, symbols);
- if (functionOffset.name != null && functionOffset.isZeroOffset()) {
- p = fCallback.getDocument().insertLabel(p, address, functionOffset.name, true);
- }
-
- // insert instruction
- int instrLength= instruction.getSize();
- Map<String, Object>[] instrAttrs = instruction.getInstruction();
- String instr = formatInstruction(instrAttrs);
-
- p = fCallback.getDocument().insertDisassemblyLine(p, address, instrLength, functionOffset.toString(), instr, sourceFile, firstLine);
- if (p == null) {
- break;
- }
- insertedAnyAddress = true;
- }
- } catch (BadLocationException e) {
- // should not happen
- DisassemblyUtils.internalError(e);
- } finally {
- fCallback.setUpdatePending(false);
- if (insertedAnyAddress) {
- fCallback.updateInvalidSource();
- fCallback.unlockScroller();
- fCallback.doPending();
- fCallback.updateVisibleArea();
- } else {
- fCallback.unlockScroller();
- }
- }
- return;
- }
-
- private FunctionOffset getFunctionOffset(BigInteger address, ISymbols.Symbol[] symbols) {
- if (symbols != null) {
- for (ISymbols.Symbol symbol : symbols) {
- BigInteger symbolAddress = toBigInteger(symbol.getAddress());
- BigInteger offset = address.subtract(symbolAddress);
- switch (offset.compareTo(BigInteger.ZERO)) {
- case 0:
- return new FunctionOffset(symbol.getName(), BigInteger.ZERO);
- case 1:
- if (offset.compareTo(BigInteger.valueOf(symbol.getSize())) < 0) {
- return new FunctionOffset(symbol.getName(), offset);
- }
- break;
- default:
- break;
- }
- }
- }
- return FunctionOffset.NONE;
- }
-
- private CodeArea findCodeArea(BigInteger address, CodeArea[] codeAreas) {
- if (codeAreas != null) {
- for (CodeArea codeArea : codeAreas) {
- if (address.equals(toBigInteger(codeArea.start_address))) {
- return codeArea;
- }
- }
- }
- return null;
- }
-
- /**
- * Format an instruction.
- *
- * @param instrAttrs
- * @return string representation
- */
- private String formatInstruction(Map<String, Object>[] instrAttrs) {
- StringBuilder buf = new StringBuilder(20);
- for (Map<String, Object> attrs : instrAttrs) {
- Object type = attrs.get(IDisassembly.FIELD_TYPE);
- if (IDisassembly.FTYPE_STRING.equals(type) || IDisassembly.FTYPE_Register.equals(type)) {
- Object text = attrs.get(IDisassembly.FIELD_TEXT);
- buf.append(text);
- } else {
- Object value = attrs.get(IDisassembly.FIELD_VALUE);
- BigInteger bigValue = new BigInteger(value.toString());
- // TODO number format
- buf.append("0x").append(bigValue.toString(16)).append(' ');
- }
- }
- return buf.toString();
- }
-
- public void gotoSymbol(final String symbol) {
- final TCFNodeStackFrame activeFrame = fActiveFrame;
- if (activeFrame == null) {
- return;
- }
- Protocol.invokeLater(new Runnable() {
- public void run() {
- if (activeFrame != fActiveFrame) {
- return;
- }
- IChannel channel = activeFrame.getChannel();
- final IExpressions exprSvc = channel.getRemoteService(IExpressions.class);
- if (exprSvc != null) {
- TCFNode evalContext = activeFrame.isEmulated() ? activeFrame.getParent() : activeFrame;
- exprSvc.create(evalContext.getID(), null, symbol, new DoneCreate() {
- public void doneCreate(IToken token, Exception error, final Expression context) {
- if (error == null) {
- exprSvc.evaluate(context.getID(), new DoneEvaluate() {
- public void doneEvaluate(IToken token, Exception error, Value value) {
- if (error == null) {
- final BigInteger address = toBigInteger(value.getValue(), value.isBigEndian(), false);
- fCallback.asyncExec(new Runnable() {
- public void run() {
- fCallback.gotoAddress(address);
- }
- });
- } else {
- handleError(error);
- }
- exprSvc.dispose(context.getID(), new DoneDispose() {
- public void doneDispose(IToken token, Exception error) {
- // no-op
- }
- });
- }
- });
- } else {
- handleError(error);
- }
- }
- });
- }
- }
- protected void handleError(final Exception error) {
- fCallback.asyncExec(new Runnable() {
- public void run() {
- Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, error.getLocalizedMessage(), error);
- ErrorDialog.openError(fCallback.getSite().getShell(), "Error", null, status); //$NON-NLS-1$
- }
- });
- }
- });
- }
-
- public void retrieveDisassembly(String file, int lines,
- BigInteger endAddress, boolean mixed, boolean showSymbols,
- boolean showDisassembly) {
- // TODO disassembly for source file
- fCallback.setUpdatePending(false);
- }
-
- public String evaluateExpression(final String expression) {
- final TCFNodeStackFrame activeFrame = fActiveFrame;
- if (activeFrame == null) {
- return null;
- }
- String value = new TCFTask<String>(activeFrame.getChannel()) {
- public void run() {
- if (activeFrame != fActiveFrame) {
- done(null);
- return;
- }
- IChannel channel = activeFrame.getChannel();
- final IExpressions exprSvc = channel.getRemoteService(IExpressions.class);
- if (exprSvc != null) {
- TCFNode evalContext = activeFrame.isEmulated() ? activeFrame.getParent() : activeFrame;
- exprSvc.create(evalContext.getID(), null, expression, new DoneCreate() {
- public void doneCreate(IToken token, Exception error, final Expression context) {
- if (error == null) {
- exprSvc.evaluate(context.getID(), new DoneEvaluate() {
- public void doneEvaluate(IToken token, Exception error, Value value) {
- if (error == null) {
- final BigInteger address = toBigInteger(value.getValue(), value.isBigEndian(), false);
- done("0x"+address.toString(16));
- }
- else {
- done(null);
- }
- exprSvc.dispose(context.getID(), new DoneDispose() {
- public void doneDispose(IToken token, Exception error) {
- // no-op
- }
- });
- }
- });
- }
- else {
- done(null);
- }
- }
- });
- } else {
- done(null);
- }
- }
- }.getE();
- return value;
- }
-
- public void dispose() {
- }
-
- public Object insertSource(Position pos, BigInteger address, String file, int lineNumber) {
- TCFNodeExecContext execContext = fExecContext;
- if (execContext != null) {
- ISourceLocator locator = fExecContext.getModel().getLaunch().getSourceLocator();
- if (locator instanceof ISourceLookupDirector) {
- return ((ISourceLookupDirector)locator).getSourceElement(file);
- }
- }
- return null;
- }
-
- private static BigInteger toBigInteger(byte[] data, boolean big_endian, boolean sign_extension) {
- byte[] temp = null;
- if (sign_extension) {
- temp = new byte[data.length];
- }
- else {
- temp = new byte[data.length + 1];
- temp[0] = 0; // Extra byte to avoid sign extension by BigInteger
- }
- if (big_endian) {
- System.arraycopy(data, 0, temp, sign_extension ? 0 : 1, data.length);
- }
- else {
- for (int i = 0; i < data.length; i++) {
- temp[temp.length - i - 1] = data[i];
- }
- }
- return new BigInteger(temp);
- }
-
- private static BigInteger toBigInteger(Number address) {
- if (address instanceof BigInteger) {
- return (BigInteger) address;
- }
- return new BigInteger(address.toString());
- }
-
- /*
- * @see org.eclipse.cdt.debug.internal.ui.disassembly.dsf.AbstractDisassemblyBackend#evaluateAddressExpression(java.lang.String, boolean)
- */
- @Override
- public BigInteger evaluateAddressExpression(String expression, boolean suppressError) {
- String value = evaluateExpression(expression);
- if (value != null) {
- try {
- return DisassemblyUtils.decodeAddress(value);
- } catch (NumberFormatException e) {
- if (!suppressError) {
- MessageDialog.openError(PlatformUI.getWorkbench().getDisplay().getActiveShell(), "Error", "Expression does not evaluate to an address");
- }
- }
- }
- return null;
- }
-
-}
+/*******************************************************************************
+ * Copyright (c) 2010, 2011 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.cdt.ui.disassembly;
+
+import static org.eclipse.cdt.debug.internal.ui.disassembly.dsf.DisassemblyUtils.DEBUG;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.cdt.debug.internal.ui.disassembly.dsf.AbstractDisassemblyBackend;
+import org.eclipse.cdt.debug.internal.ui.disassembly.dsf.AddressRangePosition;
+import org.eclipse.cdt.debug.internal.ui.disassembly.dsf.DisassemblyUtils;
+import org.eclipse.cdt.debug.internal.ui.disassembly.dsf.ErrorPosition;
+import org.eclipse.cdt.debug.internal.ui.disassembly.dsf.IDisassemblyPartCallback;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchesListener;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocumentExtension4;
+import org.eclipse.jface.text.Position;
+import org.eclipse.tm.internal.tcf.cdt.ui.Activator;
+import org.eclipse.tm.internal.tcf.debug.launch.TCFSourceLookupDirector;
+import org.eclipse.tm.internal.tcf.debug.model.TCFContextState;
+import org.eclipse.tm.internal.tcf.debug.model.TCFSourceRef;
+import org.eclipse.tm.internal.tcf.debug.ui.model.TCFChildrenStackTrace;
+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.TCFNodeStackFrame;
+import org.eclipse.tm.tcf.protocol.IChannel;
+import org.eclipse.tm.tcf.protocol.IChannel.IChannelListener;
+import org.eclipse.tm.tcf.protocol.IToken;
+import org.eclipse.tm.tcf.protocol.JSON;
+import org.eclipse.tm.tcf.protocol.Protocol;
+import org.eclipse.tm.tcf.services.IDisassembly;
+import org.eclipse.tm.tcf.services.IDisassembly.DoneDisassemble;
+import org.eclipse.tm.tcf.services.IDisassembly.IDisassemblyLine;
+import org.eclipse.tm.tcf.services.IExpressions;
+import org.eclipse.tm.tcf.services.IExpressions.DoneCreate;
+import org.eclipse.tm.tcf.services.IExpressions.DoneDispose;
+import org.eclipse.tm.tcf.services.IExpressions.DoneEvaluate;
+import org.eclipse.tm.tcf.services.IExpressions.Expression;
+import org.eclipse.tm.tcf.services.IExpressions.Value;
+import org.eclipse.tm.tcf.services.ILineNumbers;
+import org.eclipse.tm.tcf.services.ILineNumbers.CodeArea;
+import org.eclipse.tm.tcf.services.ILineNumbers.DoneMapToSource;
+import org.eclipse.tm.tcf.services.IMemory;
+import org.eclipse.tm.tcf.services.IRunControl;
+import org.eclipse.tm.tcf.services.IRunControl.RunControlContext;
+import org.eclipse.tm.tcf.services.IRunControl.RunControlListener;
+import org.eclipse.tm.tcf.services.ISymbols;
+import org.eclipse.tm.tcf.util.TCFDataCache;
+import org.eclipse.tm.tcf.util.TCFTask;
+import org.eclipse.ui.PlatformUI;
+
+@SuppressWarnings("restriction")
+public class TCFDisassemblyBackend extends AbstractDisassemblyBackend {
+
+ private static class AddressRange {
+ BigInteger start;
+ BigInteger end;
+ }
+ private static class FunctionOffset {
+ static final FunctionOffset NONE = new FunctionOffset(null, null);
+ String name;
+ BigInteger offset;
+ FunctionOffset(String name, BigInteger offset) {
+ this.name = name;
+ this.offset = offset;
+ }
+ @Override
+ public String toString() {
+ if (name == null || name.length() == 0) {
+ return "";
+ }
+ if (isZeroOffset()) {
+ return name;
+ }
+ return name + '+' + offset.toString();
+ }
+ boolean isZeroOffset() {
+ return offset == null || offset.compareTo(BigInteger.ZERO) == 0;
+ }
+ }
+ private class TCFLaunchListener implements ILaunchesListener {
+
+ public void launchesRemoved(ILaunch[] launches) {
+ }
+
+ public void launchesAdded(ILaunch[] launches) {
+ }
+
+ public void launchesChanged(ILaunch[] launches) {
+ if(fExecContext == null) {
+ return;
+ }
+ for (ILaunch launch : launches) {
+ if (launch == fExecContext.getModel().getLaunch()) {
+ if (launch.isTerminated()) {
+ handleSessionEnded();
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ private class TCFChannelListener implements IChannelListener {
+
+ public void onChannelOpened() {
+ }
+
+ public void onChannelClosed(Throwable error) {
+ handleSessionEnded();
+ }
+
+ public void congestionLevel(int level) {
+ }
+ }
+
+ private class TCFRunControlListener implements RunControlListener {
+
+ public void contextAdded(RunControlContext[] contexts) {
+ }
+
+ public void contextChanged(RunControlContext[] contexts) {
+ }
+
+ public void contextRemoved(String[] context_ids) {
+ String id = fExecContext.getID();
+ for (String contextId : context_ids) {
+ if (id.equals(contextId)) {
+ fCallback.handleTargetEnded();
+ return;
+ }
+ }
+ }
+
+ public void contextSuspended(String context, String pc, String reason,
+ Map<String, Object> params) {
+ if (fExecContext.getID().equals(context)) {
+ handleContextSuspended(pc != null ? new BigInteger(pc) : null);
+ }
+ }
+
+ public void contextResumed(String context) {
+ if (fExecContext.getID().equals(context)) {
+ fCallback.handleTargetResumed();
+ }
+ }
+
+ public void containerSuspended(String context, String pc,
+ String reason, Map<String, Object> params,
+ String[] suspended_ids) {
+ String id = fExecContext.getID();
+ if (id.equals(context)) {
+ handleContextSuspended(pc != null ? new BigInteger(pc) : null);
+ return;
+ }
+ for (String contextId : suspended_ids) {
+ if (id.equals(contextId)) {
+ handleContextSuspended(null);
+ return;
+ }
+ }
+ }
+
+ public void containerResumed(String[] context_ids) {
+ String id = fExecContext.getID();
+ for (String contextId : context_ids) {
+ if (id.equals(contextId)) {
+ fCallback.handleTargetResumed();
+ return;
+ }
+ }
+ }
+
+ public void contextException(String context, String msg) {
+ }
+
+ }
+
+ private IDisassemblyPartCallback fCallback;
+ private volatile TCFNodeExecContext fExecContext;
+ private volatile TCFNodeStackFrame fActiveFrame;
+ private volatile BigInteger fSuspendAddress;
+ private volatile int fSuspendCount;
+
+ private final IRunControl.RunControlListener fRunControlListener = new TCFRunControlListener();
+ private final IChannelListener fChannelListener = new TCFChannelListener();
+ private final ILaunchesListener fLaunchesListener = new TCFLaunchListener();
+
+ @Override
+ public void init(IDisassemblyPartCallback callback) {
+ fCallback = callback;
+ }
+
+ public boolean supportsDebugContext(IAdaptable context) {
+ return (context instanceof TCFNodeExecContext || context instanceof TCFNodeStackFrame)
+ && hasDisassemblyService((TCFNode) context);
+ }
+
+ private boolean hasDisassemblyService(final TCFNode context) {
+ Boolean hasService = new TCFTask<Boolean>() {
+ public void run() {
+ IDisassembly disass = null;
+ IChannel channel = context.getChannel();
+ if (channel != null && channel.getState() != IChannel.STATE_CLOSED) {
+ disass = channel.getRemoteService(IDisassembly.class);
+ }
+ done(disass != null);
+ }
+ }.getE();
+ return hasService != null && hasService.booleanValue();
+ }
+
+ public boolean hasDebugContext() {
+ return fExecContext != null;
+ }
+
+ public SetDebugContextResult setDebugContext(IAdaptable context) {
+ TCFNodeExecContext newContext = null;
+ TCFNodeStackFrame frame = null;
+ SetDebugContextResult result = new SetDebugContextResult();
+ if (context instanceof TCFNodeExecContext) {
+ newContext = (TCFNodeExecContext) context;
+ final TCFNodeExecContext _execContext = newContext;
+ frame = new TCFTask<TCFNodeStackFrame>(_execContext.getChannel()) {
+ public void run() {
+ TCFChildrenStackTrace stack = _execContext.getStackTrace();
+ if (!stack.validate(this)) {
+ return;
+ }
+ done(stack.getTopFrame());
+ }
+ }.getE();
+ if (frame == null) {
+ newContext = null;
+ }
+ } else if (context instanceof TCFNodeStackFrame) {
+ final TCFNodeStackFrame _frame = frame = (TCFNodeStackFrame) context;
+ newContext = new TCFTask<TCFNodeExecContext>(_frame.getChannel()) {
+ public void run() {
+ TCFNode parent = _frame.getParent();
+ if (parent instanceof TCFNodeExecContext) {
+ done((TCFNodeExecContext) parent);
+ } else {
+ done(null);
+ }
+ }
+ }.getE();
+ }
+ TCFNodeExecContext oldContext = fExecContext;
+ if (oldContext == null || newContext == null || oldContext.compareTo(newContext) != 0) {
+ result.contextChanged = true;
+ fSuspendCount++;
+ if (oldContext != null) {
+ removeListeners(oldContext);
+ }
+ }
+ fExecContext = newContext;
+ if (newContext != null && result.contextChanged) {
+ addListeners(newContext);
+ }
+ fActiveFrame = frame;
+ result.sessionId = newContext != null ? newContext.getID() : null;
+
+ if (!result.contextChanged && fActiveFrame != null) {
+ fCallback.asyncExec(new Runnable() {
+ public void run() {
+ fCallback.gotoFrameIfActive(getFrameLevel());
+ }
+ });
+ }
+
+ return result;
+ }
+
+ private void addListeners(final TCFNodeExecContext context) {
+ assert context != null;
+ Protocol.invokeAndWait(new Runnable() {
+ public void run() {
+ IChannel channel = context.getChannel();
+ IRunControl rctl = channel.getRemoteService(IRunControl.class);
+ if (rctl != null) {
+ rctl.addListener(fRunControlListener);
+ }
+ channel.addChannelListener(fChannelListener);
+ }
+ });
+ DebugPlugin.getDefault().getLaunchManager().addLaunchListener(fLaunchesListener );
+ }
+
+ private void removeListeners(final TCFNodeExecContext context) {
+ assert context != null;
+ DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(fLaunchesListener);
+ Protocol.invokeAndWait(new Runnable() {
+ public void run() {
+ IChannel channel = context.getChannel();
+ IRunControl rctl = channel.getRemoteService(IRunControl.class);
+ if (rctl != null) {
+ rctl.removeListener(fRunControlListener);
+ }
+ channel.removeChannelListener(fChannelListener);
+ }
+ });
+ }
+
+ private void handleContextSuspended(BigInteger pc) {
+ ++fSuspendCount;
+ fSuspendAddress = pc;
+ fCallback.handleTargetSuspended();
+ }
+ private void handleSessionEnded() {
+ clearDebugContext();
+ fCallback.handleTargetEnded();
+ }
+
+ public void clearDebugContext() {
+ if (fExecContext != null) {
+ removeListeners(fExecContext);
+ }
+ fExecContext = null;
+ fActiveFrame = null;
+ }
+
+ public void retrieveFrameAddress(final int targetFrame) {
+ final TCFNodeExecContext execContext = fExecContext;
+ if (execContext == null) {
+ fCallback.setUpdatePending(false);
+ return;
+ }
+ BigInteger address;
+ if (targetFrame == 0 && fSuspendAddress != null) {
+ // shortcut for goto frame on suspend
+ address = fSuspendAddress;
+ fSuspendAddress = null;
+ } else {
+ final int suspendCount = fSuspendCount;
+ final TCFChildrenStackTrace stack = execContext.getStackTrace();
+ address = new TCFTask<BigInteger>(execContext.getChannel()) {
+ public void run() {
+ if (suspendCount != fSuspendCount || execContext != fExecContext) {
+ done(null);
+ return;
+ }
+ if (!stack.validate(this)) {
+ return;
+ }
+ TCFNodeStackFrame frame = null;
+ if (targetFrame == 0) {
+ frame = stack.getTopFrame();
+ } else {
+ Map<String,TCFNode> frameData = stack.getData();
+ for (TCFNode node : frameData.values()) {
+ if (node instanceof TCFNodeStackFrame) {
+ TCFNodeStackFrame cand = (TCFNodeStackFrame) node;
+ if (cand.getFrameNo() == targetFrame) {
+ frame = cand;
+ break;
+ }
+ }
+ }
+ }
+ if (frame != null) {
+ TCFDataCache<BigInteger> addressCache = frame.getAddress();
+ if (!addressCache.validate(this)) {
+ return;
+ }
+ done(addressCache.getData());
+ return;
+ }
+ done(null);
+ }
+ }.getE();
+ }
+
+ if (execContext == fExecContext) {
+ fCallback.setUpdatePending(false);
+ if (address == null) address = BigInteger.valueOf(-2);
+ if (targetFrame == 0) {
+ fCallback.updatePC(address);
+ }
+ else {
+ fCallback.gotoFrame(targetFrame, address);
+ }
+ }
+ }
+
+ public int getFrameLevel() {
+ if (fActiveFrame == null) {
+ return -1;
+ }
+ Integer level = new TCFTask<Integer>() {
+ public void run() {
+ done(fActiveFrame != null ? fActiveFrame.getFrameNo() : -1);
+ }
+ }.getE();
+ return level != null ? level.intValue() : -1;
+ }
+
+ public boolean isSuspended() {
+ if (fExecContext == null) {
+ return false;
+ }
+ Boolean suspended = new TCFTask<Boolean>(fExecContext.getChannel()) {
+ public void run() {
+ if (fExecContext == null) {
+ done(null);
+ return;
+ }
+ TCFDataCache<TCFContextState> stateCache = fExecContext.getState();
+ if (!stateCache.validate(this)) {
+ return;
+ }
+ TCFContextState state = stateCache.getData();
+ if (state != null) {
+ done(state.is_suspended);
+ return;
+ }
+ done(null);
+ }
+ }.getE();
+ return suspended != null ? suspended.booleanValue() : false;
+ }
+
+ public boolean hasFrameContext() {
+ return fActiveFrame != null;
+ }
+
+ public String getFrameFile() {
+ final TCFNodeStackFrame frame = fActiveFrame;
+ if (frame == null) {
+ return null;
+ }
+ String file = new TCFTask<String>(frame.getChannel()) {
+ public void run() {
+ if (frame != fActiveFrame) {
+ done(null);
+ return;
+ }
+ TCFDataCache<TCFSourceRef> sourceRefCache = frame.getLineInfo();
+ if (!sourceRefCache.validate(this)) {
+ return;
+ }
+ TCFSourceRef sourceRef = sourceRefCache.getData();
+ String file = sourceRef.area.file;
+ if (file != null) {
+ IPath filePath = new Path(file);
+ if (!filePath.isAbsolute()) {
+ String dir = sourceRef.area.directory;
+ if (dir != null) {
+ filePath = new Path(dir).append(filePath);
+ }
+ }
+ done(filePath.toString());
+ }
+ done(null);
+ }
+ }.getE();
+ return file;
+ }
+
+ public int getFrameLine() {
+ final TCFNodeStackFrame frame = fActiveFrame;
+ if (frame == null) {
+ return -1;
+ }
+ Integer line = new TCFTask<Integer>(frame.getChannel()) {
+ public void run() {
+ if (frame != fActiveFrame) {
+ done(null);
+ return;
+ }
+ TCFDataCache<TCFSourceRef> sourceRefCache = frame.getLineInfo();
+ if (!sourceRefCache.validate(this)) {
+ return;
+ }
+ TCFSourceRef sourceRef = sourceRefCache.getData();
+ done(sourceRef.area.start_line);
+ }
+ }.getE();
+ return line != null ? line.intValue() : -1;
+ }
+
+ public void retrieveDisassembly(final BigInteger startAddress,
+ BigInteger endAddress, String file, int lineNumber, int lines,
+ final boolean mixed, final boolean showSymbols, boolean showDisassembly,
+ final int linesHint) {
+ final TCFNodeExecContext execContext = fExecContext;
+ if (execContext == null || execContext.isDisposed()) {
+ fCallback.setUpdatePending(false);
+ return;
+ }
+ final int suspendCount = fSuspendCount;
+ final long modCount = getModCount();
+ Protocol.invokeLater(new Runnable() {
+ public void run() {
+ if (execContext != fExecContext) {
+ return;
+ }
+ if (suspendCount != fSuspendCount) {
+ fCallback.setUpdatePending(false);
+ return;
+ }
+ final IChannel channel = execContext.getChannel();
+ IDisassembly disass = channel.getRemoteService(IDisassembly.class);
+ if (disass == null) {
+ fCallback.setUpdatePending(false);
+ return;
+ }
+ TCFDataCache<TCFNodeExecContext> mem_node_cache = execContext.getModel().searchMemoryContext(execContext);
+ if (!mem_node_cache.validate(this)) return;
+ TCFNodeExecContext memContext = mem_node_cache.getData();
+ if (memContext == null) {
+ fCallback.setUpdatePending(false);
+ return;
+ }
+ TCFDataCache<IMemory.MemoryContext> cache = memContext.getMemoryContext();
+ if (!cache.validate(this)) return;
+ final IMemory.MemoryContext mem = cache.getData();
+ if (mem == null) {
+ fCallback.setUpdatePending(false);
+ return;
+ }
+ final String contextId = mem.getID();
+ Map<String, Object> params = new HashMap<String, Object>();
+ disass.disassemble(contextId, startAddress, linesHint*4, params, new DoneDisassemble() {
+ public void doneDisassemble(IToken token, final Throwable error,
+ final IDisassemblyLine[] disassembly) {
+ if (execContext != fExecContext) {
+ return;
+ }
+ if (error != null) {
+ fCallback.asyncExec(new Runnable() {
+ public void run() {
+ if (execContext != fExecContext) {
+ return;
+ }
+ if (modCount == getModCount()) {
+ fCallback.insertError(startAddress, TCFModel.getErrorMessage(error, false));
+ fCallback.setUpdatePending(false);
+ int addr_bits = mem.getAddressSize() * 8;
+ if (fCallback.getAddressSize() < addr_bits) fCallback.addressSizeChanged(addr_bits);
+ }
+ }
+ });
+ return;
+ }
+ doneGetDisassembly(disassembly);
+ }
+
+ private void doneGetDisassembly(final IDisassemblyLine[] disassembly) {
+ if (!showSymbols) {
+ doneGetSymbols(disassembly, null);
+ return;
+ }
+ final ISymbols symbols = channel.getRemoteService(ISymbols.class);
+ if (symbols == null) {
+ doneGetSymbols(disassembly, null);
+ return;
+ }
+ final ArrayList<ISymbols.Symbol> symbolList = new ArrayList<ISymbols.Symbol>();
+ final int[] idx = { 0 };
+ IDisassemblyLine line = disassembly[idx[0]];
+ Number address = line.getAddress();
+ symbols.findByAddr(contextId, address, new ISymbols.DoneFind() {
+ ISymbols.DoneFind doneFind = this;
+ public void doneFind(IToken token, Exception error, String symbol_id) {
+ if (error == null && symbol_id != null) {
+ symbols.getContext(symbol_id, new ISymbols.DoneGetContext() {
+ public void doneGetContext(IToken token, Exception error, ISymbols.Symbol context) {
+ BigInteger nextAddress = null;
+ if (error == null && context != null) {
+ if (context.getTypeClass().equals(ISymbols.TypeClass.function)) {
+ symbolList.add(context);
+ nextAddress = JSON.toBigInteger(context.getAddress()).add(BigInteger.valueOf(context.getSize()));
+ }
+ }
+ findNextSymbol(nextAddress);
+ }
+ });
+ return;
+ }
+ findNextSymbol(null);
+ }
+ private void findNextSymbol(BigInteger nextAddress) {
+ while (++idx[0] < disassembly.length) {
+ BigInteger instrAddress = JSON.toBigInteger(disassembly[idx[0]].getAddress());
+ if (nextAddress == null) {
+ nextAddress = instrAddress;
+ } else if (instrAddress.compareTo(nextAddress) < 0) {
+ continue;
+ }
+ symbols.findByAddr(contextId, instrAddress, doneFind);
+ return;
+ }
+ ISymbols.Symbol[] functionSymbols =
+ symbolList.toArray(new ISymbols.Symbol[symbolList.size()]);
+ doneGetSymbols(disassembly, functionSymbols);
+ }
+ });
+ }
+
+ private void doneGetSymbols(final IDisassemblyLine[] disassembly, final ISymbols.Symbol[] symbols) {
+ ILineNumbers lineNumbers = null;
+ if (mixed) {
+ lineNumbers = channel.getRemoteService(ILineNumbers.class);
+ }
+ if (lineNumbers == null) {
+ doneGetLineNumbers(disassembly, symbols, null);
+ } else {
+ AddressRange range = getAddressRange(disassembly);
+ lineNumbers.mapToSource(contextId, range.start, range.end, new DoneMapToSource() {
+ public void doneMapToSource(IToken token, Exception error, final CodeArea[] areas) {
+ if (error != null) {
+ Activator.log(error);
+ doneGetLineNumbers(disassembly, symbols, null);
+ } else {
+ doneGetLineNumbers(disassembly, symbols, areas);
+ }
+ }
+ });
+ }
+ }
+
+ private void doneGetLineNumbers( final IDisassemblyLine[] disassembly, final ISymbols.Symbol[] symbols, final CodeArea[] areas) {
+ fCallback.asyncExec(new Runnable() {
+ public void run() {
+ insertDisassembly(modCount, startAddress, disassembly, symbols, areas);
+ int addr_bits = mem.getAddressSize() * 8;
+ if (fCallback.getAddressSize() < addr_bits) fCallback.addressSizeChanged(addr_bits);
+ }
+ });
+ }
+
+ private AddressRange getAddressRange(IDisassemblyLine[] lines) {
+ AddressRange range = new AddressRange();
+ range.start = JSON.toBigInteger(lines[0].getAddress());
+ IDisassemblyLine lastLine = lines[lines.length-1];
+ range.end = JSON.toBigInteger(lastLine.getAddress()).add(BigInteger.valueOf(lastLine.getSize()));
+ return range;
+ }
+ });
+ }
+ });
+ }
+
+ private long getModCount() {
+ return ((IDocumentExtension4) fCallback.getDocument()).getModificationStamp();
+ }
+
+ protected final void insertDisassembly(long modCount, BigInteger startAddress, IDisassemblyLine[] instructions, ISymbols.Symbol[] symbols, CodeArea[] codeAreas) {
+ if (!fCallback.hasViewer() || fExecContext == null) {
+ return;
+ }
+ if (modCount != getModCount()) {
+ return;
+ }
+ if (DEBUG) System.out.println("insertDisassembly "+ DisassemblyUtils.getAddressText(startAddress)); //$NON-NLS-1$
+ boolean updatePending = fCallback.getUpdatePending();
+ assert updatePending;
+ if (!updatePending) {
+ // safe-guard in case something weird is going on
+ return;
+ }
+
+ boolean insertedAnyAddress = false;
+ try {
+ fCallback.lockScroller();
+
+ AddressRangePosition p= null;
+ for (IDisassemblyLine instruction : instructions) {
+ BigInteger address = JSON.toBigInteger(instruction.getAddress());
+ if (startAddress == null) {
+ startAddress = address;
+ fCallback.setGotoAddressPending(address);
+ }
+ if (p == null || !p.containsAddress(address)) {
+ p = fCallback.getPositionOfAddress(address);
+ }
+ if (p instanceof ErrorPosition && p.fValid) {
+ p.fValid = false;
+ fCallback.getDocument().addInvalidAddressRange(p);
+ } else if (p == null /* || address.compareTo(endAddress) > 0 */) {
+ if (DEBUG) System.out.println("Excess disassembly lines at " + DisassemblyUtils.getAddressText(address)); //$NON-NLS-1$
+ return;
+ } else if (p.fValid) {
+ if (DEBUG) System.out.println("Excess disassembly lines at " + DisassemblyUtils.getAddressText(address)); //$NON-NLS-1$
+// if (!p.fAddressOffset.equals(address)) {
+// // override probably unaligned disassembly
+// p.fValid = false;
+// fCallback.getDocument().addInvalidAddressRange(p);
+// } else {
+ continue;
+// }
+ }
+
+ // insert source
+ String sourceFile = null;
+ int firstLine = -1;
+ int lastLine = -1;
+ CodeArea area = findCodeArea(address, codeAreas);
+ if (area != null) {
+ if (area.file != null) {
+ IPath filePath = new Path(area.file);
+ if (!filePath.isAbsolute() && area.directory != null) {
+ filePath = new Path(area.directory).append(filePath);
+ }
+ sourceFile = filePath.toString();
+ firstLine = area.start_line - 1;
+ lastLine = area.end_line - 2;
+ }
+ }
+ if (sourceFile != null && firstLine >= 0) {
+ try {
+ p = fCallback.insertSource(p, address, sourceFile, firstLine, lastLine);
+ } catch (NoSuchMethodError nsme) {
+ // use fallback
+ p = fCallback.insertSource(p, address, sourceFile, firstLine);
+ }
+ }
+
+ // insert symbol label
+ FunctionOffset functionOffset = getFunctionOffset(address, symbols);
+ if (functionOffset.name != null && functionOffset.isZeroOffset()) {
+ p = fCallback.getDocument().insertLabel(p, address, functionOffset.name, true);
+ }
+
+ // insert instruction
+ int instrLength= instruction.getSize();
+ Map<String, Object>[] instrAttrs = instruction.getInstruction();
+ String instr = formatInstruction(instrAttrs);
+
+ p = fCallback.getDocument().insertDisassemblyLine(p, address, instrLength, functionOffset.toString(), instr, sourceFile, firstLine);
+ if (p == null) {
+ break;
+ }
+ insertedAnyAddress = true;
+ }
+ } catch (BadLocationException e) {
+ // should not happen
+ DisassemblyUtils.internalError(e);
+ } finally {
+ fCallback.setUpdatePending(false);
+ if (insertedAnyAddress) {
+ fCallback.updateInvalidSource();
+ fCallback.unlockScroller();
+ fCallback.doPending();
+ fCallback.updateVisibleArea();
+ } else {
+ fCallback.unlockScroller();
+ }
+ }
+ }
+
+ private FunctionOffset getFunctionOffset(BigInteger address, ISymbols.Symbol[] symbols) {
+ if (symbols != null) {
+ for (ISymbols.Symbol symbol : symbols) {
+ BigInteger symbolAddress = JSON.toBigInteger(symbol.getAddress());
+ BigInteger offset = address.subtract(symbolAddress);
+ switch (offset.compareTo(BigInteger.ZERO)) {
+ case 0:
+ return new FunctionOffset(symbol.getName(), BigInteger.ZERO);
+ case 1:
+ if (offset.compareTo(BigInteger.valueOf(symbol.getSize())) < 0) {
+ return new FunctionOffset(symbol.getName(), offset);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return FunctionOffset.NONE;
+ }
+
+ private CodeArea findCodeArea(BigInteger address, CodeArea[] codeAreas) {
+ if (codeAreas != null) {
+ for (CodeArea codeArea : codeAreas) {
+ if (address.equals(JSON.toBigInteger(codeArea.start_address))) {
+ return codeArea;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Format an instruction.
+ *
+ * @param instrAttrs
+ * @return string representation
+ */
+ private String formatInstruction(Map<String, Object>[] instrAttrs) {
+ StringBuilder buf = new StringBuilder(20);
+ for (Map<String, Object> attrs : instrAttrs) {
+ Object type = attrs.get(IDisassembly.FIELD_TYPE);
+ if (IDisassembly.FTYPE_STRING.equals(type) || IDisassembly.FTYPE_Register.equals(type)) {
+ Object text = attrs.get(IDisassembly.FIELD_TEXT);
+ buf.append(text);
+ }
+ else {
+ Object value = attrs.get(IDisassembly.FIELD_VALUE);
+ BigInteger bigValue = new BigInteger(value.toString());
+ // TODO number format
+ buf.append("0x").append(bigValue.toString(16)).append(' ');
+ }
+ }
+ return buf.toString();
+ }
+
+ public void gotoSymbol(final String symbol) {
+ final TCFNodeStackFrame activeFrame = fActiveFrame;
+ if (activeFrame == null) {
+ return;
+ }
+ Protocol.invokeLater(new Runnable() {
+ public void run() {
+ if (activeFrame != fActiveFrame) {
+ return;
+ }
+ IChannel channel = activeFrame.getChannel();
+ final IExpressions exprSvc = channel.getRemoteService(IExpressions.class);
+ if (exprSvc != null) {
+ TCFNode evalContext = activeFrame.isEmulated() ? activeFrame.getParent() : activeFrame;
+ exprSvc.create(evalContext.getID(), null, symbol, new DoneCreate() {
+ public void doneCreate(IToken token, Exception error, final Expression context) {
+ if (error == null) {
+ exprSvc.evaluate(context.getID(), new DoneEvaluate() {
+ public void doneEvaluate(IToken token, Exception error, Value value) {
+ if (error == null) {
+ final BigInteger address = toBigInteger(value.getValue(), value.isBigEndian(), false);
+ fCallback.asyncExec(new Runnable() {
+ public void run() {
+ fCallback.gotoAddress(address);
+ }
+ });
+ } else {
+ handleError(error);
+ }
+ exprSvc.dispose(context.getID(), new DoneDispose() {
+ public void doneDispose(IToken token, Exception error) {
+ // no-op
+ }
+ });
+ }
+ });
+ } else {
+ handleError(error);
+ }
+ }
+ });
+ }
+ }
+ protected void handleError(final Exception error) {
+ fCallback.asyncExec(new Runnable() {
+ public void run() {
+ Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, error.getLocalizedMessage(), error);
+ ErrorDialog.openError(fCallback.getSite().getShell(), "Error", null, status); //$NON-NLS-1$
+ }
+ });
+ }
+ });
+ }
+
+ public void retrieveDisassembly(String file, int lines,
+ BigInteger endAddress, boolean mixed, boolean showSymbols,
+ boolean showDisassembly) {
+ // TODO disassembly for source file
+ fCallback.setUpdatePending(false);
+ }
+
+ public String evaluateExpression(final String expression) {
+ final TCFNodeStackFrame activeFrame = fActiveFrame;
+ if (activeFrame == null) {
+ return null;
+ }
+ String value = new TCFTask<String>(activeFrame.getChannel()) {
+ public void run() {
+ if (activeFrame != fActiveFrame) {
+ done(null);
+ return;
+ }
+ IChannel channel = activeFrame.getChannel();
+ final IExpressions exprSvc = channel.getRemoteService(IExpressions.class);
+ if (exprSvc != null) {
+ TCFNode evalContext = activeFrame.isEmulated() ? activeFrame.getParent() : activeFrame;
+ exprSvc.create(evalContext.getID(), null, expression, new DoneCreate() {
+ public void doneCreate(IToken token, Exception error, final Expression context) {
+ if (error == null) {
+ exprSvc.evaluate(context.getID(), new DoneEvaluate() {
+ public void doneEvaluate(IToken token, Exception error, Value value) {
+ if (error == null) {
+ final BigInteger address = toBigInteger(value.getValue(), value.isBigEndian(), false);
+ done("0x" + address.toString(16));
+ }
+ else {
+ done(null);
+ }
+ exprSvc.dispose(context.getID(), new DoneDispose() {
+ public void doneDispose(IToken token, Exception error) {
+ // no-op
+ }
+ });
+ }
+ });
+ }
+ else {
+ done(null);
+ }
+ }
+ });
+ } else {
+ done(null);
+ }
+ }
+ }.getE();
+ return value;
+ }
+
+ public void dispose() {
+ }
+
+ public Object insertSource(Position pos, BigInteger address, String file, int lineNumber) {
+ TCFNodeExecContext execContext = fExecContext;
+ if (execContext == null) return null;
+ return TCFSourceLookupDirector.lookup(execContext.getModel().getLaunch().getSourceLocator(), file);
+ }
+
+ private static BigInteger toBigInteger(byte[] data, boolean big_endian, boolean sign_extension) {
+ byte[] temp = null;
+ if (sign_extension) {
+ temp = new byte[data.length];
+ }
+ else {
+ temp = new byte[data.length + 1];
+ temp[0] = 0; // Extra byte to avoid sign extension by BigInteger
+ }
+ if (big_endian) {
+ System.arraycopy(data, 0, temp, sign_extension ? 0 : 1, data.length);
+ }
+ else {
+ for (int i = 0; i < data.length; i++) {
+ temp[temp.length - i - 1] = data[i];
+ }
+ }
+ return new BigInteger(temp);
+ }
+ /*
+ * @see org.eclipse.cdt.debug.internal.ui.disassembly.dsf.AbstractDisassemblyBackend#evaluateAddressExpression(java.lang.String, boolean)
+ */
+ @Override
+ public BigInteger evaluateAddressExpression(String expression, boolean suppressError) {
+ String value = evaluateExpression(expression);
+ if (value != null) {
+ try {
+ return DisassemblyUtils.decodeAddress(value);
+ } catch (NumberFormatException e) {
+ if (!suppressError) {
+ MessageDialog.openError(PlatformUI.getWorkbench().getDisplay().getActiveShell(), "Error", "Expression does not evaluate to an address");
+ }
+ }
+ }
+ return null;
+ }
+
+}

Back to the top