Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugene Tarassov2015-08-19 18:58:12 -0400
committerEugene Tarassov2015-08-19 18:58:12 -0400
commit1c6bd1396e529492d84fd40ea4a9292a894e3c1b (patch)
tree14405ef45b338d99910f084564657ab0574c02cd /plugins
parent3b1f240e0fbaf2e60e0efc998c084f53ac90de2e (diff)
downloadorg.eclipse.tcf-1c6bd1396e529492d84fd40ea4a9292a894e3c1b.tar.gz
org.eclipse.tcf-1c6bd1396e529492d84fd40ea4a9292a894e3c1b.tar.xz
org.eclipse.tcf-1c6bd1396e529492d84fd40ea4a9292a894e3c1b.zip
TCF Debugger: fixed: memory monitors disappear if a context exits and then re-created.
Diffstat (limited to 'plugins')
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/plugin.xml2
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFMemoryBlock.java (renamed from plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFMemoryBlockRetrieval.java)990
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java168
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModelManager.java2
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeExecContext.java2
5 files changed, 588 insertions, 576 deletions
diff --git a/plugins/org.eclipse.tcf.debug.ui/plugin.xml b/plugins/org.eclipse.tcf.debug.ui/plugin.xml
index 0894ffbf2..766d4a2e8 100644
--- a/plugins/org.eclipse.tcf.debug.ui/plugin.xml
+++ b/plugins/org.eclipse.tcf.debug.ui/plugin.xml
@@ -752,7 +752,7 @@
primaryId="org.eclipse.debug.ui.rendering.hexint"
renderingIds="org.eclipse.debug.ui.rendering.hexint,org.eclipse.debug.ui.rendering.signedint,org.eclipse.debug.ui.rendering.unsignedint,org.eclipse.debug.ui.rendering.ascii,org.eclipse.debug.ui.rendering.raw_memory">
<enablement>
- <instanceof value="org.eclipse.tcf.internal.debug.ui.model.TCFMemoryBlockRetrieval$MemoryBlock"/>
+ <instanceof value="org.eclipse.tcf.internal.debug.ui.model.TCFMemoryBlock"/>
</enablement>
</renderingBindings>
</extension>
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFMemoryBlockRetrieval.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFMemoryBlock.java
index ae950a886..860aa42f2 100644
--- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFMemoryBlockRetrieval.java
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFMemoryBlock.java
@@ -81,16 +81,13 @@ import org.w3c.dom.Node;
import org.xml.sax.helpers.DefaultHandler;
/**
- * A memory block retrieval allows the user interface to request a memory block from a debugger when needed.
- * TCF memory block retrieval is based on TCF Memory service.
+ * A memory block allows the user interface to request a memory block data from the debugger when needed.
+ * TCF memory block is based on TCF Memory service.
*/
-class TCFMemoryBlockRetrieval implements IMemoryBlockRetrievalExtension {
-
- private final TCFNodeExecContext exec_ctx;
- private final HashSet<MemoryBlock> mem_blocks = new HashSet<MemoryBlock>();
- private final LinkedList<ModelProxy> model_proxies = new LinkedList<ModelProxy>();
+class TCFMemoryBlock extends PlatformObject implements IMemoryBlockExtension, IModelProxyFactory {
private static class MemData {
+
final BigInteger addr;
final MemoryByte[] data;
final byte[] bytes;
@@ -104,589 +101,548 @@ class TCFMemoryBlockRetrieval implements IMemoryBlockRetrievalExtension {
}
}
- private class MemoryBlock extends PlatformObject implements IMemoryBlockExtension, IModelProxyFactory {
+ private static class ModelProxy extends AbstractModelProxy implements Runnable {
- private final String ctx_id;
- private final String expression;
- private final long length;
- private final Set<Object> connections = new HashSet<Object>();
- private final TCFDataCache<IExpressions.Expression> remote_expression;
- private final TCFDataCache<IExpressions.Value> expression_value;
+ final TCFMemoryBlock mem_block;
+ final Display display;
- private boolean disposed;
+ ModelDelta delta;
- private MemData mem_data; // current memory block data
- private MemData mem_prev; // previous data - before last suspend
- private MemData mem_last; // last retrieved memory block data
+ public ModelProxy(TCFMemoryBlock mem_block, Display display) {
+ this.mem_block = mem_block;
+ this.display = display;
+ }
- MemoryBlock(final String expression, long length) {
- this.ctx_id = exec_ctx.id;
- this.expression = expression;
- this.length = length;
- mem_blocks.add(this);
- final TCFLaunch launch = exec_ctx.model.getLaunch();
- final IChannel channel = launch.getChannel();
- remote_expression = new TCFDataCache<IExpressions.Expression>(channel) {
- @Override
- protected boolean startDataRetrieval() {
- IExpressions exps = launch.getService(IExpressions.class);
- if (exps == null) {
- set(null, new Exception("Expressions service not available"), null);
- return true;
- }
- command = exps.create(ctx_id, null, expression, new IExpressions.DoneCreate() {
- @Override
- public void doneCreate(IToken token, Exception error, IExpressions.Expression context) {
- if (disposed) {
- if (context != null) {
- IExpressions exps = channel.getRemoteService(IExpressions.class);
- exps.dispose(context.getID(), new IExpressions.DoneDispose() {
- @Override
- public void doneDispose(IToken token, Exception error) {
- if (error == null) return;
- if (channel.getState() != IChannel.STATE_OPEN) return;
- Activator.log("Error disposing remote expression evaluator", error);
- }
- });
- }
- return;
- }
- set(token, error, context);
- }
- });
- return false;
- }
- };
- expression_value = new TCFDataCache<IExpressions.Value>(channel) {
- @Override
- protected boolean startDataRetrieval() {
- if (!remote_expression.validate(this)) return false;
- final IExpressions.Expression ctx = remote_expression.getData();
- if (ctx == null) {
- set(null, null, null);
- return true;
- }
- IExpressions exps = launch.getService(IExpressions.class);
- command = exps.evaluate(ctx.getID(), new IExpressions.DoneEvaluate() {
- @Override
- public void doneEvaluate(IToken token, Exception error, IExpressions.Value value) {
- set(token, error, value);
- }
- });
- return false;
- }
- };
+ @Override
+ public void installed(Viewer viewer) {
+ synchronized (mem_block.model_proxies) {
+ if (isDisposed()) return;
+ setInstalled(true);
+ super.installed(viewer);
+ mem_block.model_proxies.add(this);
+ }
+ }
+
+ @Override
+ public void dispose() {
+ synchronized (mem_block.model_proxies) {
+ if (isDisposed()) return;
+ mem_block.model_proxies.remove(this);
+ super.dispose();
+ }
}
- private void close() {
+ void onMemoryChanged(boolean suspended) {
assert Protocol.isDispatchThread();
- assert !disposed;
- disposed = true;
- expression_value.dispose();
- if (remote_expression.isValid() && remote_expression.getData() != null) {
- final IChannel channel = exec_ctx.channel;
- if (channel.getState() == IChannel.STATE_OPEN) {
- IExpressions exps = channel.getRemoteService(IExpressions.class);
- exps.dispose(remote_expression.getData().getID(), new IExpressions.DoneDispose() {
+ int flags = IModelDelta.CONTENT;
+ if (suspended) flags |= IModelDelta.STATE;
+ if (delta != null) {
+ delta.setFlags(delta.getFlags() | flags);
+ }
+ else {
+ delta = new ModelDelta(mem_block, flags);
+ Protocol.invokeLater(this);
+ }
+ }
+
+ @Override
+ public void run() {
+ // Note: double posting is necessary to avoid deadlocks
+ assert Protocol.isDispatchThread();
+ final ModelDelta d = delta;
+ delta = null;
+ synchronized (Device.class) {
+ if (!display.isDisposed()) {
+ display.asyncExec(new Runnable() {
@Override
- public void doneDispose(IToken token, Exception error) {
- if (error == null) return;
- if (channel.getState() != IChannel.STATE_OPEN) return;
- Activator.log("Error disposing remote expression evaluator", error);
+ public void run() {
+ fireModelChanged(d);
}
});
}
}
- remote_expression.dispose();
- mem_blocks.remove(MemoryBlock.this);
}
+ }
- @Override
- public synchronized void connect(Object client) {
- connections.add(client);
- }
+ private final TCFModel model;
+ private final IMemoryBlockRetrieval block_retrieval;
+ private final String ctx_id;
+ private final String expression;
+ private final long length;
+ private final Set<Object> connections = new HashSet<Object>();
+ private final TCFDataCache<IExpressions.Expression> remote_expression;
+ private final TCFDataCache<IExpressions.Value> expression_value;
+ private final LinkedList<ModelProxy> model_proxies = new LinkedList<ModelProxy>();
- @Override
- public synchronized void disconnect(Object client) {
- connections.remove(client);
- }
+ private MemData mem_data; // current memory block data
+ private MemData mem_prev; // previous data - before last suspend
+ private MemData mem_last; // last retrieved memory block data
- @Override
- public synchronized Object[] getConnections() {
- return connections.toArray(new Object[connections.size()]);
- }
+ private boolean disposed;
- @Override
- public void dispose() throws DebugException {
- if (disposed) return;
- new TCFDebugTask<Boolean>(exec_ctx.getChannel()) {
- @Override
- public void run() {
- if (!disposed) close();
- done(Boolean.TRUE);
+ TCFMemoryBlock(final TCFModel model, IMemoryBlockRetrieval block_retrieval, final String ctx_id, final String expression, long length) {
+ assert Protocol.isDispatchThread();
+ this.model = model;
+ this.block_retrieval = block_retrieval;
+ this.ctx_id = ctx_id;
+ this.expression = expression;
+ this.length = length;
+ final TCFLaunch launch = model.getLaunch();
+ final IChannel channel = launch.getChannel();
+ remote_expression = new TCFDataCache<IExpressions.Expression>(channel) {
+ @Override
+ protected boolean startDataRetrieval() {
+ IExpressions exps = launch.getService(IExpressions.class);
+ if (exps == null) {
+ set(null, new Exception("Expressions service not available"), null);
+ return true;
}
- }.getD();
- }
+ command = exps.create(ctx_id, null, expression, new IExpressions.DoneCreate() {
+ @Override
+ public void doneCreate(IToken token, Exception error, IExpressions.Expression context) {
+ TCFNode node = model.getNode(ctx_id);
+ if (node == null) {
+ if (context != null) {
+ IExpressions exps = channel.getRemoteService(IExpressions.class);
+ exps.dispose(context.getID(), new IExpressions.DoneDispose() {
+ @Override
+ public void doneDispose(IToken token, Exception error) {
+ if (error == null) return;
+ if (channel.getState() != IChannel.STATE_OPEN) return;
+ Activator.log("Error disposing remote expression evaluator", error);
+ }
+ });
+ }
+ return;
+ }
+ set(token, error, context);
+ }
+ });
+ return false;
+ }
+ };
+ expression_value = new TCFDataCache<IExpressions.Value>(channel) {
+ @Override
+ protected boolean startDataRetrieval() {
+ if (!remote_expression.validate(this)) return false;
+ final IExpressions.Expression ctx = remote_expression.getData();
+ if (ctx == null) {
+ set(null, null, null);
+ return true;
+ }
+ IExpressions exps = launch.getService(IExpressions.class);
+ command = exps.evaluate(ctx.getID(), new IExpressions.DoneEvaluate() {
+ @Override
+ public void doneEvaluate(IToken token, Exception error, IExpressions.Value value) {
+ set(token, error, value);
+ }
+ });
+ return false;
+ }
+ };
+ }
- @Override
- public int getAddressSize() throws DebugException {
- return new TCFDebugTask<Integer>(exec_ctx.getChannel()) {
- @Override
- public void run() {
- if (exec_ctx.isDisposed()) {
- error("Context is disposed");
+ @Override
+ public synchronized void connect(Object client) {
+ connections.add(client);
+ }
+
+ @Override
+ public synchronized void disconnect(Object client) {
+ connections.remove(client);
+ }
+
+ @Override
+ public synchronized Object[] getConnections() {
+ return connections.toArray(new Object[connections.size()]);
+ }
+
+ @Override
+ public void dispose() throws DebugException {
+ if (disposed) return;
+ new TCFDebugTask<Boolean>() {
+ @Override
+ public void run() {
+ if (!disposed) {
+ onContextExited(ctx_id);
+ expression_value.dispose();
+ remote_expression.dispose();
+ disposed = true;
+ }
+ done(Boolean.TRUE);
+ }
+ }.getD();
+ }
+
+ @Override
+ public int getAddressSize() throws DebugException {
+ return new TCFDebugTask<Integer>(model.getChannel()) {
+ @Override
+ public void run() {
+ TCFNode node = model.getNode(ctx_id);
+ if (node == null) {
+ error("Context is disposed");
+ }
+ else if (node instanceof TCFNodeExecContext) {
+ TCFDataCache<IMemory.MemoryContext> cache = ((TCFNodeExecContext)node).getMemoryContext();
+ if (!cache.validate(this)) return;
+ if (cache.getError() != null) {
+ error(cache.getError());
}
else {
- TCFDataCache<IMemory.MemoryContext> cache = exec_ctx.getMemoryContext();
- if (!cache.validate(this)) return;
- if (cache.getError() != null) {
- error(cache.getError());
+ IMemory.MemoryContext mem = cache.getData();
+ if (mem == null) {
+ error("Context does not provide memory access");
}
else {
- IMemory.MemoryContext mem = cache.getData();
- if (mem == null) {
- error("Context does not provide memory access");
- }
- else {
- done(mem.getAddressSize());
- }
+ done(mem.getAddressSize());
}
}
}
- }.getD();
- }
+ else {
+ error("Context does not provide memory access");
+ }
+ }
+ }.getD();
+ }
- @Override
- public int getAddressableSize() throws DebugException {
- return new TCFDebugTask<Integer>(exec_ctx.getChannel()) {
- @Override
- public void run() {
- if (exec_ctx.isDisposed()) {
- error("Context is disposed");
+ @Override
+ public int getAddressableSize() throws DebugException {
+ return new TCFDebugTask<Integer>(model.getChannel()) {
+ @Override
+ public void run() {
+ TCFNode node = model.getNode(ctx_id);
+ if (node == null) {
+ error("Context is disposed");
+ }
+ else if (node instanceof TCFNodeExecContext) {
+ TCFDataCache<IMemory.MemoryContext> cache = ((TCFNodeExecContext)node).getMemoryContext();
+ if (!cache.validate(this)) return;
+ if (cache.getError() != null) {
+ error(cache.getError());
}
else {
- TCFDataCache<IMemory.MemoryContext> cache = exec_ctx.getMemoryContext();
- if (!cache.validate(this)) return;
- if (cache.getError() != null) {
- error(cache.getError());
+ IMemory.MemoryContext mem = cache.getData();
+ if (mem == null) {
+ error("Context does not provide memory access");
}
else {
- IMemory.MemoryContext mem = cache.getData();
- if (mem == null) {
- error("Context does not provide memory access");
- }
- else {
- done(mem.getAddressableUnitSize());
- }
+ done(mem.getAddressableUnitSize());
}
}
}
- }.getD();
- }
+ else {
+ error("Context does not provide memory access");
+ }
+ }
+ }.getD();
+ }
- @Override
- public BigInteger getBigBaseAddress() throws DebugException {
- return new TCFDebugTask<BigInteger>(exec_ctx.getChannel()) {
- @Override
- public void run() {
- if (!expression_value.validate()) {
- expression_value.wait(this);
- }
- else if (expression_value.getError() != null) {
- error(expression_value.getError());
- }
- else if (expression_value.getData() == null) {
- error("Address expression evaluation failed");
+ @Override
+ public BigInteger getBigBaseAddress() throws DebugException {
+ return new TCFDebugTask<BigInteger>(model.getChannel()) {
+ @Override
+ public void run() {
+ if (!expression_value.validate()) {
+ expression_value.wait(this);
+ }
+ else if (expression_value.getError() != null) {
+ error(expression_value.getError());
+ }
+ else if (expression_value.getData() == null) {
+ error("Address expression evaluation failed");
+ }
+ else {
+ IExpressions.Value value = expression_value.getData();
+ if (value.getTypeClass() == ISymbols.TypeClass.array) {
+ BigInteger addr = JSON.toBigInteger(value.getAddress());
+ if (addr == null) {
+ error("Invalid expression: array without memory address");
+ }
+ else {
+ done(addr);
+ }
}
else {
- IExpressions.Value value = expression_value.getData();
- if (value.getTypeClass() == ISymbols.TypeClass.array) {
- BigInteger addr = JSON.toBigInteger(value.getAddress());
- if (addr == null) {
- error("Invalid expression: array without memory address");
- }
- else {
- done(addr);
- }
+ byte[] data = value.getValue();
+ if (data == null || data.length == 0) {
+ error("Address expression value is empty (void)");
}
else {
- byte[] data = value.getValue();
- if (data == null || data.length == 0) {
- error("Address expression value is empty (void)");
- }
- else {
- boolean signed = value.getTypeClass() == ISymbols.TypeClass.integer;
- done(TCFNumberFormat.toBigInteger(data, value.isBigEndian(), signed));
- }
+ boolean signed = value.getTypeClass() == ISymbols.TypeClass.integer;
+ done(TCFNumberFormat.toBigInteger(data, value.isBigEndian(), signed));
}
}
}
- }.getD();
- }
+ }
+ }.getD();
+ }
- @Override
- public MemoryByte[] getBytesFromAddress(final BigInteger address, final long units) throws DebugException {
- return new TCFDebugTask<MemoryByte[]>(exec_ctx.getChannel()) {
- int offs = 0;
- @Override
- public void run() {
- if (mem_data != null &&
- address.compareTo(mem_data.addr) >= 0 &&
- address.add(BigInteger.valueOf(units)).compareTo(
- mem_data.addr.add(BigInteger.valueOf(mem_data.data.length))) <= 0) {
- offs = address.subtract(mem_data.addr).intValue();
- MemoryByte[] res = mem_data.data;
- if (units < mem_data.data.length) {
- res = new MemoryByte[(int)units];
- System.arraycopy(mem_data.data, offs, res, 0, res.length);
- }
- setHistoryFlags();
- done(res);
- return;
- }
- if (exec_ctx.isDisposed()) {
- error("Context is disposed");
- return;
- }
- TCFDataCache<IMemory.MemoryContext> cache = exec_ctx.getMemoryContext();
- if (!cache.validate(this)) return;
- if (cache.getError() != null) {
- error(cache.getError());
- return;
- }
- final IMemory.MemoryContext mem = cache.getData();
- if (mem == null) {
- error("Context does not provide memory access");
- return;
+ @Override
+ public MemoryByte[] getBytesFromAddress(final BigInteger address, final long units) throws DebugException {
+ return new TCFDebugTask<MemoryByte[]>(model.getChannel()) {
+ int offs = 0;
+ @Override
+ public void run() {
+ if (mem_data != null &&
+ address.compareTo(mem_data.addr) >= 0 &&
+ address.add(BigInteger.valueOf(units)).compareTo(
+ mem_data.addr.add(BigInteger.valueOf(mem_data.data.length))) <= 0) {
+ offs = address.subtract(mem_data.addr).intValue();
+ MemoryByte[] res = mem_data.data;
+ if (units < mem_data.data.length) {
+ res = new MemoryByte[(int)units];
+ System.arraycopy(mem_data.data, offs, res, 0, res.length);
}
- final int size = (int)units;
- final int mode = IMemory.MODE_CONTINUEONERROR | IMemory.MODE_VERIFY;
- final byte[] buf = new byte[size];
- final MemoryByte[] res = new MemoryByte[size];
- mem.get(address, 1, buf, 0, size, mode, new IMemory.DoneMemory() {
- @Override
- public void doneMemory(IToken token, MemoryError error) {
- int big_endian = 0;
- if (mem.getProperties().get(IMemory.PROP_BIG_ENDIAN) != null) {
- big_endian |= MemoryByte.ENDIANESS_KNOWN;
- if (mem.isBigEndian()) big_endian |= MemoryByte.BIG_ENDIAN;
- }
- int cnt = 0;
- while (offs < size) {
- int flags = big_endian;
- if (error instanceof IMemory.ErrorOffset) {
- IMemory.ErrorOffset ofs = (IMemory.ErrorOffset)error;
- int status = ofs.getStatus(cnt);
- if (status == IMemory.ErrorOffset.BYTE_VALID) {
- flags |= MemoryByte.READABLE | MemoryByte.WRITABLE;
- }
- else if ((status & IMemory.ErrorOffset.BYTE_UNKNOWN) != 0) {
- if (cnt > 0) break;
- }
- }
- else if (error == null) {
+ setHistoryFlags();
+ done(res);
+ return;
+ }
+ TCFNode node = model.getNode(ctx_id);
+ if (node == null) {
+ error("Context is disposed");
+ return;
+ }
+ if (!(node instanceof TCFNodeExecContext)) {
+ error("Context does not provide memory access");
+ return;
+ }
+ TCFDataCache<IMemory.MemoryContext> cache = ((TCFNodeExecContext)node).getMemoryContext();
+ if (!cache.validate(this)) return;
+ if (cache.getError() != null) {
+ error(cache.getError());
+ return;
+ }
+ final IMemory.MemoryContext mem = cache.getData();
+ if (mem == null) {
+ error("Context does not provide memory access");
+ return;
+ }
+ final int size = (int)units;
+ final int mode = IMemory.MODE_CONTINUEONERROR | IMemory.MODE_VERIFY;
+ final byte[] buf = new byte[size];
+ final MemoryByte[] res = new MemoryByte[size];
+ mem.get(address, 1, buf, 0, size, mode, new IMemory.DoneMemory() {
+ @Override
+ public void doneMemory(IToken token, MemoryError error) {
+ int big_endian = 0;
+ if (mem.getProperties().get(IMemory.PROP_BIG_ENDIAN) != null) {
+ big_endian |= MemoryByte.ENDIANESS_KNOWN;
+ if (mem.isBigEndian()) big_endian |= MemoryByte.BIG_ENDIAN;
+ }
+ int cnt = 0;
+ while (offs < size) {
+ int flags = big_endian;
+ if (error instanceof IMemory.ErrorOffset) {
+ IMemory.ErrorOffset ofs = (IMemory.ErrorOffset)error;
+ int status = ofs.getStatus(cnt);
+ if (status == IMemory.ErrorOffset.BYTE_VALID) {
flags |= MemoryByte.READABLE | MemoryByte.WRITABLE;
}
- res[offs] = new MemoryByte(buf[offs], (byte)flags);
- offs++;
- cnt++;
- }
- if (offs < size) {
- mem.get(address.add(BigInteger.valueOf(offs)), 1, buf, offs, size - offs, mode, this);
+ else if ((status & IMemory.ErrorOffset.BYTE_UNKNOWN) != 0) {
+ if (cnt > 0) break;
+ }
}
- else {
- mem_last = mem_data = new MemData(address, res);
- setHistoryFlags();
- done(res);
+ else if (error == null) {
+ flags |= MemoryByte.READABLE | MemoryByte.WRITABLE;
}
+ res[offs] = new MemoryByte(buf[offs], (byte)flags);
+ offs++;
+ cnt++;
+ }
+ if (offs < size) {
+ mem.get(address.add(BigInteger.valueOf(offs)), 1, buf, offs, size - offs, mode, this);
+ }
+ else {
+ mem_last = mem_data = new MemData(address, res);
+ setHistoryFlags();
+ done(res);
}
- });
- }
- }.getD();
- }
-
- private void setHistoryFlags() {
- if (mem_data == null) return;
- BigInteger addr = mem_data.addr;
- BigInteger his_start = null;
- BigInteger his_end = null;
- if (mem_prev != null) {
- his_start = mem_prev.addr;
- his_end = mem_prev.addr.add(BigInteger.valueOf(mem_prev.data.length));
- }
- for (MemoryByte b : mem_data.data) {
- int flags = b.getFlags();
- if (mem_prev != null && addr.compareTo(his_start) >= 0 && addr.compareTo(his_end) < 0) {
- flags |= MemoryByte.HISTORY_KNOWN;
- int offs = addr.subtract(his_start).intValue();
- if (b.getValue() != mem_prev.data[offs].getValue()) {
- flags |= MemoryByte.CHANGED;
}
- }
- else {
- flags &= ~(MemoryByte.HISTORY_KNOWN | MemoryByte.CHANGED);
- }
- b.setFlags((byte)flags);
- addr = addr.add(BigInteger.valueOf(1));
+ });
}
- }
-
- @Override
- public MemoryByte[] getBytesFromOffset(BigInteger offset, long units) throws DebugException {
- return getBytesFromAddress(getBigBaseAddress().add(offset), units);
- }
-
- @Override
- public String getExpression() {
- return expression;
- }
-
- @Override
- public IMemoryBlockRetrieval getMemoryBlockRetrieval() {
- return TCFMemoryBlockRetrieval.this;
- }
-
- @Override
- public long getStartAddress() {
- return 0; // Unbounded
- }
-
- @Override
- public long getLength() {
- return length;
- }
-
- @Override
- public BigInteger getMemoryBlockStartAddress() throws DebugException {
- return null; // Unbounded
- }
-
- @Override
- public BigInteger getMemoryBlockEndAddress() throws DebugException {
- return null; // Unbounded
- }
-
- @Override
- public BigInteger getBigLength() throws DebugException {
- return BigInteger.valueOf(length);
- }
-
- @Override
- public void setBaseAddress(BigInteger address) throws DebugException {
- }
+ }.getD();
+ }
- @Override
- public void setValue(BigInteger offset, final byte[] bytes) throws DebugException {
- final BigInteger address = getBigBaseAddress().add(offset);
- new TCFDebugTask<Object>(exec_ctx.getChannel()) {
- @Override
- public void run() {
- if (exec_ctx.isDisposed()) {
- error("Context is disposed");
- return;
- }
- TCFDataCache<IMemory.MemoryContext> cache = exec_ctx.getMemoryContext();
- if (!cache.validate(this)) return;
- if (cache.getError() != null) {
- error(cache.getError());
- return;
- }
- final IMemory.MemoryContext mem = cache.getData();
- if (mem == null) {
- error("Context does not provide memory access");
- return;
- }
- final int mode = IMemory.MODE_CONTINUEONERROR | IMemory.MODE_VERIFY;
- mem.set(address, 1, bytes, 0, bytes.length, mode, new IMemory.DoneMemory() {
- @Override
- public void doneMemory(IToken token, MemoryError error) {
- if (error != null) {
- error(error);
- }
- else {
- done(null);
- }
- }
- });
+ private void setHistoryFlags() {
+ if (mem_data == null) return;
+ BigInteger addr = mem_data.addr;
+ BigInteger his_start = null;
+ BigInteger his_end = null;
+ if (mem_prev != null) {
+ his_start = mem_prev.addr;
+ his_end = mem_prev.addr.add(BigInteger.valueOf(mem_prev.data.length));
+ }
+ for (MemoryByte b : mem_data.data) {
+ int flags = b.getFlags();
+ if (mem_prev != null && addr.compareTo(his_start) >= 0 && addr.compareTo(his_end) < 0) {
+ flags |= MemoryByte.HISTORY_KNOWN;
+ int offs = addr.subtract(his_start).intValue();
+ if (b.getValue() != mem_prev.data[offs].getValue()) {
+ flags |= MemoryByte.CHANGED;
}
- }.getD();
- }
-
- @Override
- public boolean supportBaseAddressModification() throws DebugException {
- return false;
- }
-
- @Override
- public boolean supportsChangeManagement() {
- return true;
+ }
+ else {
+ flags &= ~(MemoryByte.HISTORY_KNOWN | MemoryByte.CHANGED);
+ }
+ b.setFlags((byte)flags);
+ addr = addr.add(BigInteger.valueOf(1));
}
+ }
- @Override
- public byte[] getBytes() throws DebugException {
- if (mem_data == null) return null;
- return mem_data.bytes;
- }
+ @Override
+ public MemoryByte[] getBytesFromOffset(BigInteger offset, long units) throws DebugException {
+ return getBytesFromAddress(getBigBaseAddress().add(offset), units);
+ }
- @Override
- public void setValue(long offset, byte[] bytes) throws DebugException {
- setValue(BigInteger.valueOf(offset), bytes);
- }
+ @Override
+ public String getExpression() {
+ return expression;
+ }
- @Override
- public boolean supportsValueModification() {
- return true;
- }
+ @Override
+ public IMemoryBlockRetrieval getMemoryBlockRetrieval() {
+ return block_retrieval;
+ }
- @Override
- public IDebugTarget getDebugTarget() {
- return null;
- }
+ @Override
+ public long getStartAddress() {
+ return 0; // Unbounded
+ }
- @Override
- public ILaunch getLaunch() {
- return exec_ctx.model.getLaunch();
- }
+ @Override
+ public long getLength() {
+ return length;
+ }
- @Override
- public String getModelIdentifier() {
- return ITCFConstants.ID_TCF_DEBUG_MODEL;
- }
+ @Override
+ public BigInteger getMemoryBlockStartAddress() throws DebugException {
+ return null; // Unbounded
+ }
- @Override
- public IModelProxy createModelProxy(Object element, IPresentationContext context) {
- assert element == this;
- return new ModelProxy(this, context.getWindow().getShell().getDisplay());
- }
+ @Override
+ public BigInteger getMemoryBlockEndAddress() throws DebugException {
+ return null; // Unbounded
+ }
- @Override
- @SuppressWarnings("rawtypes")
- public Object getAdapter(Class adapter) {
- if (adapter == IMemoryBlockRetrieval.class) return TCFMemoryBlockRetrieval.this;
- if (adapter == IMemoryBlockRetrievalExtension.class) return TCFMemoryBlockRetrieval.this;
- return super.getAdapter(adapter);
- }
+ @Override
+ public BigInteger getBigLength() throws DebugException {
+ return BigInteger.valueOf(length);
}
- private class ModelProxy extends AbstractModelProxy implements Runnable {
+ @Override
+ public void setBaseAddress(BigInteger address) throws DebugException {
+ }
- final MemoryBlock mem_block;
- final Display display;
+ @Override
+ public void setValue(BigInteger offset, final byte[] bytes) throws DebugException {
+ final BigInteger address = getBigBaseAddress().add(offset);
+ new TCFDebugTask<Object>(model.getChannel()) {
+ @Override
+ public void run() {
+ TCFNode node = model.getNode(ctx_id);
+ if (node == null) {
+ error("Context is disposed");
+ return;
+ }
+ if (!(node instanceof TCFNodeExecContext)) {
+ error("Context does not provide memory access");
+ return;
+ }
+ TCFDataCache<IMemory.MemoryContext> cache = ((TCFNodeExecContext)node).getMemoryContext();
+ if (!cache.validate(this)) return;
+ if (cache.getError() != null) {
+ error(cache.getError());
+ return;
+ }
+ final IMemory.MemoryContext mem = cache.getData();
+ if (mem == null) {
+ error("Context does not provide memory access");
+ return;
+ }
+ final int mode = IMemory.MODE_CONTINUEONERROR | IMemory.MODE_VERIFY;
+ mem.set(address, 1, bytes, 0, bytes.length, mode, new IMemory.DoneMemory() {
+ @Override
+ public void doneMemory(IToken token, MemoryError error) {
+ if (error != null) {
+ error(error);
+ }
+ else {
+ done(null);
+ }
+ }
+ });
+ }
+ }.getD();
+ }
- ModelDelta delta;
+ @Override
+ public boolean supportBaseAddressModification() throws DebugException {
+ return false;
+ }
- public ModelProxy(MemoryBlock mem_block, Display display) {
- this.mem_block = mem_block;
- this.display = display;
- }
+ @Override
+ public boolean supportsChangeManagement() {
+ return true;
+ }
- @Override
- public void installed(Viewer viewer) {
- synchronized (model_proxies) {
- if (isDisposed()) return;
- setInstalled(true);
- super.installed(viewer);
- model_proxies.add(this);
- }
- }
+ @Override
+ public byte[] getBytes() throws DebugException {
+ if (mem_data == null) return null;
+ return mem_data.bytes;
+ }
- @Override
- public void dispose() {
- synchronized (model_proxies) {
- if (isDisposed()) return;
- model_proxies.remove(this);
- super.dispose();
- }
- }
+ @Override
+ public void setValue(long offset, byte[] bytes) throws DebugException {
+ setValue(BigInteger.valueOf(offset), bytes);
+ }
- void onMemoryChanged(boolean suspended) {
- assert Protocol.isDispatchThread();
- int flags = IModelDelta.CONTENT;
- if (suspended) flags |= IModelDelta.STATE;
- if (delta != null) {
- delta.setFlags(delta.getFlags() | flags);
- }
- else {
- delta = new ModelDelta(mem_block, flags);
- Protocol.invokeLater(this);
- }
- }
+ @Override
+ public boolean supportsValueModification() {
+ return true;
+ }
- @Override
- public void run() {
- // Note: double posting is necessary to avoid deadlocks
- assert Protocol.isDispatchThread();
- final ModelDelta d = delta;
- delta = null;
- synchronized (Device.class) {
- if (!display.isDisposed()) {
- display.asyncExec(new Runnable() {
- @Override
- public void run() {
- fireModelChanged(d);
- }
- });
- }
- }
- }
+ @Override
+ public IDebugTarget getDebugTarget() {
+ return null;
}
- TCFMemoryBlockRetrieval(TCFNodeExecContext exec_ctx) {
- this.exec_ctx = exec_ctx;
+ @Override
+ public ILaunch getLaunch() {
+ return model.getLaunch();
}
@Override
- public IMemoryBlockExtension getExtendedMemoryBlock(final String expression, Object context) throws DebugException {
- return new TCFDebugTask<IMemoryBlockExtension>() {
- @Override
- public void run() {
- if (!exec_ctx.getMemoryContext().validate(this)) return;
- if (exec_ctx.getMemoryContext().getError() != null) {
- error(exec_ctx.getMemoryContext().getError());
- }
- else {
- done(new MemoryBlock(expression, -1));
- }
- }
- }.getD();
+ public String getModelIdentifier() {
+ return ITCFConstants.ID_TCF_DEBUG_MODEL;
}
@Override
- public IMemoryBlock getMemoryBlock(final long address, final long length) throws DebugException {
- return new TCFDebugTask<IMemoryBlockExtension>() {
- @Override
- public void run() {
- if (!exec_ctx.getMemoryContext().validate(this)) return;
- if (exec_ctx.getMemoryContext().getError() != null) {
- error(exec_ctx.getMemoryContext().getError());
- }
- else {
- done(new MemoryBlock("0x" + Long.toHexString(address), length));
- }
- }
- }.getD();
+ public IModelProxy createModelProxy(Object element, IPresentationContext context) {
+ assert element == this;
+ return new ModelProxy(this, context.getWindow().getShell().getDisplay());
}
@Override
- public boolean supportsStorageRetrieval() {
- return true;
+ @SuppressWarnings("rawtypes")
+ public Object getAdapter(Class adapter) {
+ if (adapter == IMemoryBlockRetrieval.class) return block_retrieval;
+ if (adapter == IMemoryBlockRetrievalExtension.class) return block_retrieval;
+ return super.getAdapter(adapter);
}
String getMemoryID() {
- return exec_ctx.id;
+ return ctx_id;
}
void flushAllCaches() {
- for (MemoryBlock b : mem_blocks) b.mem_data = null;
+ mem_data = null;
}
void onMemoryChanged(boolean suspended) {
assert Protocol.isDispatchThread();
- if (mem_blocks.size() == 0) return;
- for (MemoryBlock b : mem_blocks) {
- if (suspended) b.mem_prev = b.mem_last;
- b.mem_data = null;
- }
+ if (suspended) mem_prev = mem_last;
+ mem_data = null;
synchronized (model_proxies) {
for (ModelProxy p : model_proxies) {
p.onMemoryChanged(suspended);
@@ -694,9 +650,25 @@ class TCFMemoryBlockRetrieval implements IMemoryBlockRetrievalExtension {
}
}
- void dispose() {
- MemoryBlock[] list = mem_blocks.toArray(new MemoryBlock[mem_blocks.size()]);
- for (MemoryBlock b : list) b.close();
+ void onContextExited(String id) {
+ assert Protocol.isDispatchThread();
+ if (!id.equals(ctx_id)) return;
+ expression_value.reset();
+ if (remote_expression.isValid() && remote_expression.getData() != null) {
+ final IChannel channel = model.getChannel();
+ if (channel.getState() == IChannel.STATE_OPEN) {
+ IExpressions exps = channel.getRemoteService(IExpressions.class);
+ exps.dispose(remote_expression.getData().getID(), new IExpressions.DoneDispose() {
+ @Override
+ public void doneDispose(IToken token, Exception error) {
+ if (error == null) return;
+ if (channel.getState() != IChannel.STATE_OPEN) return;
+ Activator.log("Error disposing remote expression evaluator", error);
+ }
+ });
+ }
+ remote_expression.reset();
+ }
}
/************************** Persistence ***************************************************/
@@ -717,7 +689,7 @@ class TCFMemoryBlockRetrieval implements IMemoryBlockRetrievalExtension {
private static final Map<String,List<Element>> blocks_memento = new HashMap<String,List<Element>>();
private static final Set<Runnable> pending_updates = new HashSet<Runnable>();
- static boolean memento_loaded;
+ private static boolean memento_loaded;
private static void asyncExec(TCFModel model, Runnable r) {
synchronized (pending_updates) {
@@ -791,18 +763,17 @@ class TCFMemoryBlockRetrieval implements IMemoryBlockRetrievalExtension {
}
}
- static void onMemoryNodeCreated(TCFNodeExecContext exe_ctx) {
+ static void onMemoryNodeCreated(final TCFNodeExecContext exe_ctx) {
assert Protocol.isDispatchThread();
synchronized (blocks_memento) {
// Restore memory monitors associated with the node
final List<Element> memento = blocks_memento.remove(exe_ctx.id);
if (memento == null || memento.size() == 0) return;
ArrayList<IMemoryBlock> list = new ArrayList<IMemoryBlock>();
- TCFMemoryBlockRetrieval r = exe_ctx.model.getMemoryBlockRetrieval(exe_ctx);
for (Element xml_block : memento) {
String expr = xml_block.getAttribute(XML_ATTR_ADDR);
long length = Long.parseLong(xml_block.getAttribute(XML_ATTR_SIZE));
- list.add(r.new MemoryBlock(expr, length));
+ list.add(exe_ctx.model.getMemoryBlock(exe_ctx.id, expr, length));
}
final IMemoryBlock[] blks = list.toArray(new IMemoryBlock[list.size()]);
asyncExec(exe_ctx.model, new Runnable() {
@@ -861,12 +832,9 @@ class TCFMemoryBlockRetrieval implements IMemoryBlockRetrievalExtension {
Map<IMemoryBlock,Element> mb_to_xml = new HashMap<IMemoryBlock,Element>();
Element xml_memory = document.createElement(XML_NODE_MEMORY);
for (IMemoryBlock mb : manager.getMemoryBlocks()) {
- if (mb instanceof MemoryBlock) {
- MemoryBlock m = (MemoryBlock)mb;
- TCFMemoryBlockRetrieval r = (TCFMemoryBlockRetrieval)m.getMemoryBlockRetrieval();
- if (r.exec_ctx.model != model) continue;
- assert r.exec_ctx.isDisposed();
- assert m.disposed;
+ if (mb instanceof TCFMemoryBlock) {
+ TCFMemoryBlock m = (TCFMemoryBlock)mb;
+ if (m.model != model) continue;
Element xml_block = document.createElement(XML_NODE_BLOCK);
xml_block.setAttribute(XML_ATTR_CTX, m.ctx_id);
xml_block.setAttribute(XML_ATTR_ADDR, m.expression);
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java
index f705aa4a7..5ac93be60 100644
--- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java
@@ -22,6 +22,7 @@ import java.util.Set;
import java.util.WeakHashMap;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IExpressionManager;
import org.eclipse.debug.core.IExpressionsListener;
@@ -37,6 +38,8 @@ import org.eclipse.debug.core.commands.ISuspendHandler;
import org.eclipse.debug.core.commands.ITerminateHandler;
import org.eclipse.debug.core.model.IDebugModelProvider;
import org.eclipse.debug.core.model.IExpression;
+import org.eclipse.debug.core.model.IMemoryBlock;
+import org.eclipse.debug.core.model.IMemoryBlockExtension;
import org.eclipse.debug.core.model.IMemoryBlockRetrieval;
import org.eclipse.debug.core.model.IMemoryBlockRetrievalExtension;
import org.eclipse.debug.core.model.ISourceLocator;
@@ -246,26 +249,36 @@ public class TCFModel implements ITCFModel, IElementContentProvider, IElementLab
private final Map<Class<?>,Object> adapters = new HashMap<Class<?>,Object>();
- private class MemoryBlocksUpdate extends TCFDataCache<Map<String,TCFMemoryBlockRetrieval>> {
+ private final List<TCFMemoryBlock> mem_blocks = new ArrayList<TCFMemoryBlock>();
+ private final Map<String,IMemoryBlockRetrievalExtension> mem_retrieval = new HashMap<String,IMemoryBlockRetrievalExtension>();
+ private final IMemoryBlockRetrievalExtension mem_not_supported = new IMemoryBlockRetrievalExtension() {
+ @Override
+ public boolean supportsStorageRetrieval() {
+ return false;
+ }
+ @Override
+ public IMemoryBlock getMemoryBlock(long startAddress, long length) throws DebugException {
+ return null;
+ }
+
+ @Override
+ public IMemoryBlockExtension getExtendedMemoryBlock(String expression, Object context) throws DebugException {
+ return null;
+ }
+ };
+
+
+ private class MemoryBlocksUpdate implements Runnable {
final Set<String> changeset = new HashSet<String>();
final Set<String> suspended = new HashSet<String>();
- MemoryBlocksUpdate(IChannel channel) {
- super(channel);
- Protocol.invokeLater(new Runnable() {
- public void run() {
- if (!validate(this)) return;
- Map<String,TCFMemoryBlockRetrieval> map = getData();
- if (map != null) { // map can be null if, for example, the channel was closed
- for (TCFMemoryBlockRetrieval r : map.values()) {
- r.onMemoryChanged(suspended.contains(r.getMemoryID()));
- }
- }
- launch.removePendingClient(mem_blocks_update);
- mem_blocks_update = null;
- }
- });
+ MemoryBlocksUpdate() {
+ mem_blocks_update = this;
+ Protocol.invokeLater(this);
+ if (wait_for_views_update_after_step) {
+ launch.addPendingClient(this);
+ }
}
void add(String id, boolean suspended) {
@@ -273,39 +286,34 @@ public class TCFModel implements ITCFModel, IElementContentProvider, IElementLab
if (suspended) this.suspended.add(id);
}
- public boolean startDataRetrieval() {
- // Map changed contexts to memory nodes, and then to memory block retrieval objects
- Map<String,TCFMemoryBlockRetrieval> map = new HashMap<String,TCFMemoryBlockRetrieval>();
- for (String id : changeset) {
- if (map.get(id) != null) continue;
- TCFNode node = id2node.get(id);
- if (node == null) {
- if (!createNode(id, this)) return false;
- if (isValid()) {
- Activator.log("Cannot create debug model node", getError());
- reset();
- continue;
- }
- node = id2node.get(id);
- }
- if (node instanceof TCFNodeExecContext) {
- TCFDataCache<TCFNodeExecContext> c = ((TCFNodeExecContext)node).getMemoryNode();
- if (!c.validate(this)) return false;
- node = c.getData();
- if (node == null) continue;
- TCFMemoryBlockRetrieval r = mem_retrieval.get(node.id);
- if (r != null) {
- map.put(node.id, r);
- if (suspended.contains(id)) suspended.add(node.id);
+ public void run() {
+ assert mem_blocks_update == this;
+ if (channel.getState() == IChannel.STATE_OPEN && mem_blocks.size() > 0) {
+ // Map changed contexts to memory nodes, and then to memory block objects
+ Set<TCFMemoryBlock> set = new HashSet<TCFMemoryBlock>();
+ for (String id : changeset) {
+ if (!createNode(id, this)) return;
+ TCFNode node = id2node.get(id);
+ if (node instanceof TCFNodeExecContext) {
+ TCFDataCache<TCFNodeExecContext> c = ((TCFNodeExecContext)node).getMemoryNode();
+ if (!c.validate(this)) return;
+ node = c.getData();
+ if (node == null) continue;
+ for (TCFMemoryBlock b : mem_blocks) {
+ if (b.getMemoryID().equals(node.id)) {
+ if (suspended.contains(id)) suspended.add(node.id);
+ set.add(b);
+ }
+ }
}
}
+ for (TCFMemoryBlock b : set) b.onMemoryChanged(suspended.contains(b.getMemoryID()));
}
- set(null, null, map);
- return true;
+ launch.removePendingClient(this);
+ mem_blocks_update = null;
}
}
- private final Map<String,TCFMemoryBlockRetrieval> mem_retrieval = new HashMap<String,TCFMemoryBlockRetrieval>();
private MemoryBlocksUpdate mem_blocks_update;
private final Map<String,String> cast_to_type_map = new HashMap<String,String>();
@@ -798,7 +806,7 @@ public class TCFModel implements ITCFModel, IElementContentProvider, IElementLab
}
}
view_request_listeners = l.size() > 0 ? l : null;
- TCFMemoryBlockRetrieval.onModelCreated(this);
+ TCFMemoryBlock.onModelCreated(this);
}
/**
@@ -830,11 +838,12 @@ public class TCFModel implements ITCFModel, IElementContentProvider, IElementLab
TCFNodeExecContext ctx = cache.getData();
if (!ctx.getMemoryContext().validate(this)) return;
if (ctx.getMemoryContext().getError() == null) {
- o = getMemoryBlockRetrieval(ctx);
+ o = getMemoryBlockRetrieval(ctx.id);
}
}
}
- assert o == null || adapter.isInstance(o);
+ if (o == null) o = mem_not_supported;
+ assert adapter.isInstance(o);
done(o);
}
}.getE();
@@ -842,11 +851,53 @@ public class TCFModel implements ITCFModel, IElementContentProvider, IElementLab
return null;
}
- TCFMemoryBlockRetrieval getMemoryBlockRetrieval(TCFNodeExecContext node) {
- TCFMemoryBlockRetrieval r = mem_retrieval.get(node.id);
+ TCFMemoryBlock getMemoryBlock(String id, String expression, long length) {
+ assert Protocol.isDispatchThread();
+ IMemoryBlockRetrievalExtension r = getMemoryBlockRetrieval(id);
+ TCFMemoryBlock b = new TCFMemoryBlock(this, r, id, expression, length);
+ mem_blocks.add(b);
+ return b;
+ }
+
+ private IMemoryBlockRetrievalExtension getMemoryBlockRetrieval(final String id) {
+ /*
+ * Note: platform uses MemoryBlockRetrieval objects to link memory blocks with selection in the Debug view.
+ * We need to maintain 1 to 1 mapping between memory context IDs and MemoryBlockRetrieval objects.
+ */
+ assert Protocol.isDispatchThread();
+ IMemoryBlockRetrievalExtension r = mem_retrieval.get(id);
if (r == null) {
- r = new TCFMemoryBlockRetrieval(node);
- mem_retrieval.put(node.id, r);
+ r = new IMemoryBlockRetrievalExtension() {
+ @Override
+ public IMemoryBlockExtension getExtendedMemoryBlock(final String expression, Object context) throws DebugException {
+ final IMemoryBlockRetrieval r = this;
+ return new TCFDebugTask<IMemoryBlockExtension>() {
+ @Override
+ public void run() {
+ TCFMemoryBlock b = new TCFMemoryBlock(TCFModel.this, r, id, expression, -1);
+ mem_blocks.add(b);
+ done(b);
+ }
+ }.getD();
+ }
+ @Override
+ public IMemoryBlock getMemoryBlock(final long address, final long length) throws DebugException {
+ final IMemoryBlockRetrieval r = this;
+ return new TCFDebugTask<IMemoryBlock>() {
+ @Override
+ public void run() {
+ TCFMemoryBlock b = new TCFMemoryBlock(TCFModel.this, r, id, "0x" + Long.toHexString(address), length);
+ mem_blocks.add(b);
+ done(b);
+ }
+ }.getD();
+ }
+ @Override
+ public boolean supportsStorageRetrieval() {
+ return true;
+ }
+ };
+ mem_retrieval.put(id, r);
}
return r;
}
@@ -912,12 +963,12 @@ public class TCFModel implements ITCFModel, IElementContentProvider, IElementLab
launch_node = null;
}
// Dispose memory monitors
- for (TCFMemoryBlockRetrieval r : mem_retrieval.values()) r.dispose();
+ TCFMemoryBlock.onModelDisconnected(this);
mem_retrieval.clear();
+ mem_blocks.clear();
// Refresh the Debug view - cannot be done through ModelProxy since it is disposed
refreshLaunchView();
assert id2node.size() == 0;
- TCFMemoryBlockRetrieval.onModelDisconnected(this);
}
void onProcessOutput(String ctx_id, int stream_id, byte[] data) {
@@ -988,13 +1039,7 @@ public class TCFModel implements ITCFModel, IElementContentProvider, IElementLab
}
}
}
- if (mem_retrieval.size() == 0) return;
- if (mem_blocks_update == null) {
- mem_blocks_update = new MemoryBlocksUpdate(channel);
- if (wait_for_views_update_after_step) {
- launch.addPendingClient(mem_blocks_update);
- }
- }
+ if (mem_blocks_update == null) new MemoryBlocksUpdate();
mem_blocks_update.add(id, context_suspended);
}
@@ -1210,9 +1255,8 @@ public class TCFModel implements ITCFModel, IElementContentProvider, IElementLab
void removeNode(String id) {
assert id != null;
assert Protocol.isDispatchThread();
+ for (TCFMemoryBlock b : mem_blocks) b.onContextExited(id);
id2node.remove(id);
- TCFMemoryBlockRetrieval r = mem_retrieval.remove(id);
- if (r != null) r.dispose();
}
void flushAllCaches() {
@@ -1225,7 +1269,7 @@ public class TCFModel implements ITCFModel, IElementContentProvider, IElementLab
participant.sourceContainersChanged(d);
}
}
- for (TCFMemoryBlockRetrieval b : mem_retrieval.values()) b.flushAllCaches();
+ for (TCFMemoryBlock b : mem_blocks) b.flushAllCaches();
for (TCFNode n : id2node.values()) n.flushAllCaches();
launch_node.flushAllCaches();
}
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModelManager.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModelManager.java
index 1df6f12b6..9c363a9ce 100644
--- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModelManager.java
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModelManager.java
@@ -143,7 +143,7 @@ public class TCFModelManager {
}
}
}
- TCFMemoryBlockRetrieval.onWorkbenchShutdown();
+ TCFMemoryBlock.onWorkbenchShutdown();
return true;
}
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeExecContext.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeExecContext.java
index 5147366fe..cc59d41b5 100644
--- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeExecContext.java
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeExecContext.java
@@ -501,7 +501,7 @@ public class TCFNodeExecContext extends TCFNode implements ISymbolOwner, ITCFExe
return true;
}
};
- TCFMemoryBlockRetrieval.onMemoryNodeCreated(this);
+ TCFMemoryBlock.onMemoryNodeCreated(this);
updateTerminal();
}

Back to the top