Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java')
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java368
1 files changed, 298 insertions, 70 deletions
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java
index 6f55564fad2..036fd2f30d9 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java
@@ -7,8 +7,9 @@
*
* Contributors:
* Wind River Systems - initial API and implementation
- * Ericsson - Modified for handling of multiple execution contexts
+ * Ericsson - Modified for handling of multiple execution contexts
* Axel Mueller - Bug 306555 - Add support for cast to type / view as array (IExpressions2)
+ * Jens Elmenthaler (Verigy) - Added Full GDB pretty-printing support (bug 302121)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service;
@@ -26,7 +27,6 @@ import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.ICachingService;
import org.eclipse.cdt.dsf.debug.service.IExpressions;
import org.eclipse.cdt.dsf.debug.service.IExpressions2;
-import org.eclipse.cdt.dsf.debug.service.IExpressions3;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryChangedEvent;
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext;
@@ -68,7 +68,7 @@ import org.osgi.framework.BundleContext;
*
* @since 2.0
*/
-public class MIExpressions extends AbstractDsfService implements IExpressions3, ICachingService {
+public class MIExpressions extends AbstractDsfService implements IMIExpressions, ICachingService {
/**
* A format that gives more details about an expression and supports pretty-printing
@@ -93,12 +93,28 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
public static class ExpressionInfo {
private final String fullExpression;
private final String relativeExpression;
-
+ private boolean isDynamic = false;
+ private ExpressionInfo parent;
+ private int indexInParent = -1;
+ private int childCountLimit = IMIExpressions.CHILD_COUNT_LIMIT_UNSPECIFIED;
+
public ExpressionInfo(String full, String relative) {
fullExpression = full;
relativeExpression = relative;
}
-
+
+ /**
+ * @since 4.0
+ */
+ public ExpressionInfo(String full, String relative, boolean isDynamic,
+ ExpressionInfo parent, int indexInParent) {
+ fullExpression = full;
+ relativeExpression = relative;
+ this.isDynamic = isDynamic;
+ this.parent = parent;
+ this.indexInParent = indexInParent;
+ }
+
public String getFullExpr() { return fullExpression; }
public String getRelExpr() { return relativeExpression; }
@@ -109,6 +125,7 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
fullExpression.equals(((ExpressionInfo) other).fullExpression)) {
if (relativeExpression == null ? ((ExpressionInfo) other).relativeExpression == null :
relativeExpression.equals(((ExpressionInfo) other).relativeExpression)) {
+ // The other members don't play any role for equality.
return true;
}
}
@@ -120,13 +137,98 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
public int hashCode() {
return (fullExpression == null ? 0 : fullExpression.hashCode()) ^
(relativeExpression == null ? 0 : relativeExpression.hashCode());
+ // The other members don't play any role for equality.
}
@Override
public String toString() {
- return "[" + fullExpression +", " + relativeExpression + "]"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
+ return "[" + fullExpression +", " + relativeExpression + ", isDynamic=" + isDynamic + "]"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
}
+
+ /**
+ * @return The parent expression info, if existing.
+ * @since 4.0
+ */
+ public ExpressionInfo getParent() {
+ return parent;
+ }
+
+ /**
+ * @return The index in the child array of the parent. Only valid if
+ * {@link #getParent()} returns not null.
+ * @since 4.0
+ */
+ public int getIndexInParentExpression() {
+ return indexInParent;
+ }
+
+ /**
+ * @return Whether the corresponding variable object is dynamic,
+ * i.e. it's value and children are provided by a pretty printer.
+ * @since 4.0
+ */
+ public boolean isDynamic() {
+ return isDynamic;
+ }
+
+ /**
+ * @return Whether the expression info has any ancestor that is dynamic.
+ * @since 4.0
+ */
+ public boolean hasDynamicAncestor() {
+ for (ExpressionInfo parent = getParent(); parent != null; parent = parent.getParent()) {
+ if (parent.isDynamic()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * @param isDynamic
+ * Whether the value and children of this expression is
+ * currently provided by a pretty printer or not.
+ * @since 4.0
+ */
+ public void setDynamic(boolean isDynamic) {
+ this.isDynamic = isDynamic;
+ }
+
+ /**
+ * @param parent The new parent expression info.
+ * @since 4.0
+ */
+ public void setParent(ExpressionInfo parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * @param index The index in the children array of the parent.
+ * @since 4.0
+ */
+ public void setIndexInParent(int index) {
+ this.indexInParent = index;
+ }
+
+ /**
+ * @return The current limit on the number of children to be fetched.
+ * @since 4.0
+ */
+ public int getChildCountLimit() {
+ return childCountLimit;
+ }
+
+ /**
+ * @param newLimit
+ * The new limit on the number of children to be fetched.
+ * @since 4.0
+ */
+ public void setChildCountLimit(int newLimit) {
+ this.childCountLimit = newLimit;
+ }
}
+
/**
* This class represents an expression.
*/
@@ -188,8 +290,32 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
}
private MIExpressionDMC(String sessionId, String expr, String relExpr, IDMContext parent) {
+ this(sessionId, new ExpressionInfo(expr, relExpr), parent);
+ }
+
+ /**
+ * ExpressionDMC Constructor for expression to be evaluated in context
+ * of a stack frame.
+ *
+ * @param sessionId
+ * The session ID in which this context is created.
+ * @param info
+ * The expression info that this expression is to use.
+ * @param frameCtx
+ * The parent stack frame context for this ExpressionDMC.
+ *
+ * @since 4.0
+ */
+ public MIExpressionDMC(String sessionId, ExpressionInfo info, IFrameDMContext frameCtx) {
+ this(sessionId, info, (IDMContext)frameCtx);
+ }
+
+ /**
+ * @since 4.0
+ */
+ private MIExpressionDMC(String sessionId, ExpressionInfo info, IDMContext parent) {
super(sessionId, new IDMContext[] { parent });
- exprInfo = new ExpressionInfo(expr, relExpr);
+ exprInfo = info;
}
/**
@@ -232,6 +358,26 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
public String getRelativeExpression() {
return exprInfo.getRelExpr();
}
+
+ /**
+ * @return Get the expression info for this context.
+ * @since 4.0
+ */
+ public ExpressionInfo getExpressionInfo() {
+ return exprInfo;
+ }
+
+ /**
+ * @param info
+ *
+ * @since 4.0
+ */
+ public void setExpressionInfo(ExpressionInfo info) {
+ assert (this.exprInfo.getFullExpr().equals(info.getFullExpr()));
+ assert (this.exprInfo.getRelExpr().equals(info.getRelExpr()));
+
+ this.exprInfo = info;
+ }
}
protected static class InvalidContextExpressionDMC extends AbstractDMContext
@@ -313,7 +459,27 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
return (fAddr == null ? "null" : "(" + fAddr.toHexAddressString()) + ", " + fSize + ")"; //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
}
}
+
+ /**
+ * If an expressions doesn't have an address, or it cannot be determined,
+ * use this class.
+ * @since 4.0
+ */
+ protected class InvalidDMAddress implements IExpressionDMLocation {
+ public IAddress getAddress() {
+ return IExpressions.IExpressionDMLocation.INVALID_ADDRESS;
+ }
+
+ public int getSize() {
+ return 0;
+ }
+
+ public String getLocation() {
+ return ""; //$NON-NLS-1$
+ }
+ }
+
/**
* This class represents the static data referenced by an instance of ExpressionDMC,
* such as its type and number of children; it does not contain the value or format
@@ -552,8 +718,6 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
* This method shuts down this service. It unregisters the service, stops
* receiving service events, and calls the superclass shutdown() method to
* finish the shutdown process.
- *
- * @return void
*/
@Override
public void shutdown(RequestMonitor requestMonitor) {
@@ -582,9 +746,18 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
* Create an expression context.
*/
public IExpressionDMContext createExpression(IDMContext ctx, String expression, String relExpr) {
+ return createExpression(ctx, new ExpressionInfo(expression, relExpr));
+ }
+
+ /**
+ * Create an expression context from a given expression info.
+ * @since 4.0
+ */
+ private IExpressionDMContext createExpression(IDMContext ctx, ExpressionInfo info) {
+ String expression = info.getFullExpr();
IFrameDMContext frameDmc = DMContexts.getAncestorOfType(ctx, IFrameDMContext.class);
if (frameDmc != null) {
- return new MIExpressionDMC(getSession().getId(), expression, relExpr, frameDmc);
+ return new MIExpressionDMC(getSession().getId(), info, frameDmc);
}
IMIExecutionDMContext execCtx = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class);
@@ -595,7 +768,7 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
MIStack stackService = getServicesTracker().getService(MIStack.class);
if (stackService != null) {
frameDmc = stackService.createFrameDMContext(execCtx, 0);
- return new MIExpressionDMC(getSession().getId(), expression, relExpr, frameDmc);
+ return new MIExpressionDMC(getSession().getId(), info, frameDmc);
}
return new InvalidContextExpressionDMC(getSession().getId(), expression, execCtx);
@@ -603,7 +776,7 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
IMemoryDMContext memoryCtx = DMContexts.getAncestorOfType(ctx, IMemoryDMContext.class);
if (memoryCtx != null) {
- return new MIExpressionDMC(getSession().getId(), expression, relExpr, memoryCtx);
+ return new MIExpressionDMC(getSession().getId(), info, memoryCtx);
}
// Don't care about the relative expression at this point
@@ -662,7 +835,8 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
fExpressionCache.execute(
new ExprMetaGetVar(dmc),
new DataRequestMonitor<ExprMetaGetVarInfo>(getExecutor(), rm) {
- @Override
+
+ @Override
protected void handleSuccess() {
IExpressionDMData.BasicType basicType = null;
@@ -682,7 +856,10 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
break;
case GDBType.GENERIC:
default:
- if (getData().getNumChildren() > 0) {
+ // The interesting question is not hasChildren,
+ // but canHaveChildren. E.g. an empty
+ // collection still is a composite.
+ if (getData().hasChildren() || getData().getCollectionHint()) {
basicType = IExpressionDMData.BasicType.composite;
} else {
basicType = IExpressionDMData.BasicType.basic;
@@ -718,6 +895,17 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
IExpressionDMContext dmc,
final DataRequestMonitor<IExpressionDMAddress> rm) {
+ if (dmc instanceof MIExpressionDMC) {
+ MIExpressionDMC miDMC = (MIExpressionDMC) dmc;
+ if (miDMC.getExpressionInfo().hasDynamicAncestor()) {
+ // For children of dynamic varobjs, there is no full expression that gdb
+ // could evaluate in order to provide address and size.
+ rm.setData(new InvalidDMAddress());
+ rm.done();
+ return;
+ }
+ }
+
// First create an address expression and a size expression
// to be used in back-end calls
final IExpressionDMContext addressDmc =
@@ -778,37 +966,45 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
{
// We need to make sure the FormattedValueDMContext also holds an ExpressionContext,
// or else this method cannot do its work.
- // Note that we look for MIExpressionDMC and not IExpressionDMC, because getting
+ // Note that we look for MIExpressionDMC and not IExpressionDMC, because
// looking for IExpressionDMC could yield InvalidContextExpressionDMC which is still
- // not what we need to have.
+ // not what we need.
MIExpressionDMC exprDmc = DMContexts.getAncestorOfType(dmc, MIExpressionDMC.class);
if (exprDmc == null ) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context for evaluating expressions.", null)); //$NON-NLS-1$
rm.done();
} else {
if (DETAILS_FORMAT.equals(dmc.getFormatID())) {
- // This format is obtained through a different GDB command.
- // It yields more details than the variableObject output.
- // Starting with GDB 7.0, this format automatically supports pretty-printing, as long as
- // GDB has been configured to support it.
- fExpressionCache.execute(
- fCommandFactory.createMIDataEvaluateExpression(exprDmc),
- new DataRequestMonitor<MIDataEvaluateExpressionInfo>(getExecutor(), rm) {
- @Override
- protected void handleSuccess() {
- rm.setData(new FormattedValueDMData(getData().getValue()));
- rm.done();
- }
- @Override
- protected void handleError() {
- if (fTraceVisualization) {
- rm.setData(new FormattedValueDMData("")); //$NON-NLS-1$
- rm.done();
- } else {
- super.handleError();
- }
- }
- });
+ if (exprDmc.getExpressionInfo().hasDynamicAncestor()) {
+ // -data-evaluate-expression does not work for children of
+ // dynamic varobjs, since there is no full expression
+ // that gdb could evaluate.
+ rm.setData(new FormattedValueDMData(Messages.MIExpressions_NotAvailableBecauseChildOfDynamicVarobj));
+ rm.done();
+ } else {
+ // This format is obtained through a different GDB command.
+ // It yields more details than the variableObject output.
+ // Starting with GDB 7.0, this format automatically supports pretty-printing, as long as
+ // GDB has been configured to support it.
+ fExpressionCache.execute(
+ fCommandFactory.createMIDataEvaluateExpression(exprDmc),
+ new DataRequestMonitor<MIDataEvaluateExpressionInfo>(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ rm.setData(new FormattedValueDMData(getData().getValue()));
+ rm.done();
+ }
+ @Override
+ protected void handleError() {
+ if (fTraceVisualization) {
+ rm.setData(new FormattedValueDMData("")); //$NON-NLS-1$
+ rm.done();
+ } else {
+ super.handleError();
+ }
+ }
+ });
+ }
} else {
fExpressionCache.execute(
new ExprMetaGetValue(dmc),
@@ -838,7 +1034,7 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
/**
* Retrieves the children expressions of the specified expression
*
- * @param exprCtx
+ * @param dmc
* The context for the expression for which the children
* should be retrieved.
* @param rm
@@ -857,9 +1053,7 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
IExpressionDMContext[] childArray = new IExpressionDMContext[childrenExpr.length];
for (int i=0; i<childArray.length; i++) {
childArray[i] = createExpression(
- dmc.getParents()[0],
- childrenExpr[i].getFullExpr(),
- childrenExpr[i].getRelExpr());
+ dmc.getParents()[0], childrenExpr[i]);
}
rm.setData(childArray);
@@ -890,7 +1084,7 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
* @param rm
* The data request monitor that will contain the requested data
*/
- public void getSubExpressions(IExpressionDMContext exprCtx, final int startIndex,
+ public void getSubExpressions(final IExpressionDMContext exprCtx, final int startIndex,
final int length, final DataRequestMonitor<IExpressionDMContext[]> rm) {
if (startIndex < 0 || length < 0) {
@@ -900,28 +1094,27 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
}
if (exprCtx instanceof MIExpressionDMC) {
- getSubExpressions(
- exprCtx,
- new DataRequestMonitor<IExpressionDMContext[]>(getExecutor(), rm) {
+ fExpressionCache.execute(
+ new ExprMetaGetChildren(exprCtx, startIndex + length),
+ new DataRequestMonitor<ExprMetaGetChildrenInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
- IExpressionDMContext[] subExpressions = getData();
+ ExpressionInfo[] childrenExpr = getData().getChildrenExpressions();
- if (startIndex >= subExpressions.length) {
+ if (startIndex >= childrenExpr.length) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, "Invalid range for evaluating sub expressions.", null)); //$NON-NLS-1$
rm.done();
return;
}
-
- int realLength = length;
- if (startIndex + length > subExpressions.length) {
- realLength = subExpressions.length - startIndex;
- }
-
- IExpressionDMContext[] subRange = new IExpressionDMContext[realLength];
- System.arraycopy(subExpressions, startIndex, subRange, 0, realLength);
- rm.setData(subRange);
+ int numChildren = childrenExpr.length - startIndex;
+ numChildren = Math.min(length, numChildren);
+ IExpressionDMContext[] childrenArray = new IExpressionDMContext[numChildren];
+ for (int i=0; i < numChildren; i++) {
+ childrenArray[i] = createExpression(
+ exprCtx.getParents()[0], childrenExpr[startIndex + i]);
+ }
+ rm.setData(childrenArray);
rm.done();
}
});
@@ -935,20 +1128,40 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
}
/**
- * Retrieves the count of children expressions of the specified expression
- *
- * @param exprCtx
- * The context for the expression for which the children count
- * should be retrieved.
- * @param rm
- * The data request monitor that will contain the requested data
+ * @since 4.0
+ */
+ public void safeToAskForAllSubExpressions(IExpressionDMContext dmc,
+ final DataRequestMonitor<Boolean> rm) {
+ if (dmc instanceof MIExpressionDMC) {
+ fExpressionCache.execute(
+ new ExprMetaGetVar(dmc),
+ new DataRequestMonitor<ExprMetaGetVarInfo>(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ boolean safe = getData().isSafeToAskForAllChildren();
+
+ rm.setData(safe);
+ rm.done();
+ }
+ });
+ } else if (dmc instanceof InvalidContextExpressionDMC) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context for evaluating expressions.", null)); //$NON-NLS-1$
+ rm.done();
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid expression context.", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ /**
+ * @since 4.0
*/
public void getSubExpressionCount(IExpressionDMContext dmc,
- final DataRequestMonitor<Integer> rm)
- {
+ final int numChildLimit, final DataRequestMonitor<Integer> rm) {
+
if (dmc instanceof MIExpressionDMC) {
fExpressionCache.execute(
- new ExprMetaGetChildCount(dmc),
+ new ExprMetaGetChildCount(dmc, numChildLimit),
new DataRequestMonitor<ExprMetaGetChildCountInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
@@ -964,13 +1177,28 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
rm.done();
}
}
+
+ /**
+ * Retrieves the count of children expressions of the specified expression
+ *
+ * @param dmc
+ * The context for the expression for which the children count
+ * should be retrieved.
+ * @param rm
+ * The data request monitor that will contain the requested data
+ */
+ public void getSubExpressionCount(IExpressionDMContext dmc,
+ final DataRequestMonitor<Integer> rm)
+ {
+ getSubExpressionCount(dmc, IMIExpressions.CHILD_COUNT_LIMIT_UNSPECIFIED, rm);
+ }
/**
* This method indicates if an expression can be written to.
*
- * @param dmc: The data model context representing an expression.
+ * @param dmc The data model context representing an expression.
*
- * @param rm: Data Request monitor containing True if this expression's value can be edited. False otherwise.
+ * @param rm Data Request monitor containing True if this expression's value can be edited. False otherwise.
*/
public void canWriteExpression(IExpressionDMContext dmc, final DataRequestMonitor<Boolean> rm) {
@@ -997,7 +1225,7 @@ public class MIExpressions extends AbstractDsfService implements IExpressions3,
/**
* Changes the value of the specified expression based on the new value and format.
*
- * @param expressionContext
+ * @param dmc
* The context for the expression for which the value
* should be changed.
* @param expressionValue

Back to the top