mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
Merge remote-tracking branch 'origin/GP-5425_Dan_fixRefreshToggleInModelView--SQUASHED'
This commit is contained in:
commit
9cca167f77
12 changed files with 205 additions and 206 deletions
|
@ -183,6 +183,7 @@ public record ActionName(String name, Show show, Enabler enabler, String display
|
||||||
|
|
||||||
public static final ActionName REFRESH =
|
public static final ActionName REFRESH =
|
||||||
create("refresh", Show.EXTENDED, Enabler.ALWAYS, "Refresh", ICON_REFRESH, "Refresh");
|
create("refresh", Show.EXTENDED, Enabler.ALWAYS, "Refresh", ICON_REFRESH, "Refresh");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activate a given object and optionally a time
|
* Activate a given object and optionally a time
|
||||||
*
|
*
|
||||||
|
@ -191,6 +192,7 @@ public record ActionName(String name, Show show, Enabler enabler, String display
|
||||||
*/
|
*/
|
||||||
public static final ActionName ACTIVATE =
|
public static final ActionName ACTIVATE =
|
||||||
create("activate", Show.BUILTIN, Enabler.ALWAYS, "Activate", null, "Activate");
|
create("activate", Show.BUILTIN, Enabler.ALWAYS, "Activate", null, "Activate");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A weaker form of activate.
|
* A weaker form of activate.
|
||||||
*
|
*
|
||||||
|
@ -262,6 +264,7 @@ public record ActionName(String name, Show show, Enabler enabler, String display
|
||||||
create("step_over", Show.BUILTIN, Enabler.NOT_RUNNING, "Step Over", ICON_STEP_OVER, "Step");
|
create("step_over", Show.BUILTIN, Enabler.NOT_RUNNING, "Step Over", ICON_STEP_OVER, "Step");
|
||||||
public static final ActionName STEP_OUT =
|
public static final ActionName STEP_OUT =
|
||||||
create("step_out", Show.BUILTIN, Enabler.NOT_RUNNING, "Step Out", ICON_STEP_OUT, "Step");
|
create("step_out", Show.BUILTIN, Enabler.NOT_RUNNING, "Step Out", ICON_STEP_OUT, "Step");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Skip is not typically available, except in emulators. If the back-end debugger does not have
|
* Skip is not typically available, except in emulators. If the back-end debugger does not have
|
||||||
* a command for this action out-of-the-box, we do not recommend trying to implement it
|
* a command for this action out-of-the-box, we do not recommend trying to implement it
|
||||||
|
@ -270,12 +273,14 @@ public record ActionName(String name, Show show, Enabler enabler, String display
|
||||||
*/
|
*/
|
||||||
public static final ActionName STEP_SKIP =
|
public static final ActionName STEP_SKIP =
|
||||||
create("step_skip", Show.BUILTIN, Enabler.NOT_RUNNING, "Skip Over", ICON_SKIP_OVER, "Skip");
|
create("step_skip", Show.BUILTIN, Enabler.NOT_RUNNING, "Skip Over", ICON_SKIP_OVER, "Skip");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Step back is not typically available, except in emulators and timeless (or time-travel)
|
* Step back is not typically available, except in emulators and timeless (or time-travel)
|
||||||
* debuggers.
|
* debuggers.
|
||||||
*/
|
*/
|
||||||
public static final ActionName STEP_BACK =
|
public static final ActionName STEP_BACK =
|
||||||
create("step_back", Show.BUILTIN, Enabler.NOT_RUNNING, "Step Back", ICON_STEP_BACK, "Back");
|
create("step_back", Show.BUILTIN, Enabler.NOT_RUNNING, "Step Back", ICON_STEP_BACK, "Back");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The action for steps that don't fit one of the common stepping actions.
|
* The action for steps that don't fit one of the common stepping actions.
|
||||||
*/
|
*/
|
||||||
|
@ -315,6 +320,7 @@ public record ActionName(String name, Show show, Enabler enabler, String display
|
||||||
*/
|
*/
|
||||||
public static final ActionName READ_MEM =
|
public static final ActionName READ_MEM =
|
||||||
create("read_mem", Show.BUILTIN, Enabler.ALWAYS, "Read Memory", null, "Read");
|
create("read_mem", Show.BUILTIN, Enabler.ALWAYS, "Read Memory", null, "Read");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forms: (addr:ADDRESS,data:BYTES)
|
* Forms: (addr:ADDRESS,data:BYTES)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -181,6 +181,78 @@ public interface Target {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies how object arguments are derived
|
||||||
|
*/
|
||||||
|
public enum ObjectArgumentPolicy {
|
||||||
|
/**
|
||||||
|
* The object should be taken exactly from the action context, if applicable, present, and
|
||||||
|
* matching in schema.
|
||||||
|
*/
|
||||||
|
CONTEXT_ONLY {
|
||||||
|
@Override
|
||||||
|
public boolean allowContextObject() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allowCoordsObject() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allowSuitableRelative() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* The object should be taken from the current (active) object in the tool, or a suitable
|
||||||
|
* relative having the correct schema.
|
||||||
|
*/
|
||||||
|
CURRENT_AND_RELATED {
|
||||||
|
@Override
|
||||||
|
public boolean allowContextObject() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allowCoordsObject() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allowSuitableRelative() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* The object can be taken from the given context, or the current (active) object in the
|
||||||
|
* tool, or a suitable relative having the correct schema.
|
||||||
|
*/
|
||||||
|
EITHER_AND_RELATED {
|
||||||
|
@Override
|
||||||
|
public boolean allowContextObject() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allowCoordsObject() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allowSuitableRelative() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public abstract boolean allowContextObject();
|
||||||
|
|
||||||
|
public abstract boolean allowCoordsObject();
|
||||||
|
|
||||||
|
public abstract boolean allowSuitableRelative();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe the target for display in the UI
|
* Describe the target for display in the UI
|
||||||
*
|
*
|
||||||
|
@ -216,11 +288,17 @@ public interface Target {
|
||||||
/**
|
/**
|
||||||
* Collect all actions that implement the given common debugger command
|
* Collect all actions that implement the given common debugger command
|
||||||
*
|
*
|
||||||
|
* <p>
|
||||||
|
* Note that if the context provides a program location (i.e., address), the object policy is
|
||||||
|
* ignored. It will use current and related objects.
|
||||||
|
*
|
||||||
* @param name the action name
|
* @param name the action name
|
||||||
* @param context applicable context from the UI
|
* @param context applicable context from the UI
|
||||||
|
* @param policy determines how objects may be found
|
||||||
* @return the collected actions
|
* @return the collected actions
|
||||||
*/
|
*/
|
||||||
Map<String, ActionEntry> collectActions(ActionName name, ActionContext context);
|
Map<String, ActionEntry> collectActions(ActionName name, ActionContext context,
|
||||||
|
ObjectArgumentPolicy policy);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #execute(String, boolean)
|
* @see #execute(String, boolean)
|
||||||
|
|
|
@ -34,6 +34,7 @@ import ghidra.debug.api.model.DebuggerSingleObjectPathActionContext;
|
||||||
import ghidra.debug.api.target.ActionName;
|
import ghidra.debug.api.target.ActionName;
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
import ghidra.debug.api.target.Target.ActionEntry;
|
import ghidra.debug.api.target.Target.ActionEntry;
|
||||||
|
import ghidra.debug.api.target.Target.ObjectArgumentPolicy;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.framework.model.DomainObjectChangedEvent;
|
import ghidra.framework.model.DomainObjectChangedEvent;
|
||||||
import ghidra.framework.model.DomainObjectListener;
|
import ghidra.framework.model.DomainObjectListener;
|
||||||
|
@ -1473,7 +1474,7 @@ public interface FlatDebuggerAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
default ActionEntry findAction(Target target, ActionName action, ActionContext context) {
|
default ActionEntry findAction(Target target, ActionName action, ActionContext context) {
|
||||||
return target.collectActions(action, context)
|
return target.collectActions(action, context, ObjectArgumentPolicy.EITHER_AND_RELATED)
|
||||||
.values()
|
.values()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(e -> !e.requiresPrompt())
|
.filter(e -> !e.requiresPrompt())
|
||||||
|
|
|
@ -56,6 +56,7 @@ import ghidra.trace.model.target.info.TraceObjectInterfaceUtils;
|
||||||
import ghidra.trace.model.target.path.*;
|
import ghidra.trace.model.target.path.*;
|
||||||
import ghidra.trace.model.target.path.PathFilter.Align;
|
import ghidra.trace.model.target.path.PathFilter.Align;
|
||||||
import ghidra.trace.model.target.schema.*;
|
import ghidra.trace.model.target.schema.*;
|
||||||
|
import ghidra.trace.model.target.schema.PrimitiveTraceObjectSchema.MinimalSchemaContext;
|
||||||
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
import ghidra.trace.model.thread.*;
|
import ghidra.trace.model.thread.*;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
@ -75,7 +76,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
||||||
this.args = args;
|
this.args = args;
|
||||||
|
|
||||||
this.requiresPrompt = args.values().contains(Missing.MISSING);
|
this.requiresPrompt = args.values().contains(Missing.MISSING);
|
||||||
this.specificity = computeSpecificity(args);
|
this.specificity = computeSpecificity(method, args);
|
||||||
this.first = getFirstObjectArgument(method, args);
|
this.first = getFirstObjectArgument(method, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,9 +198,8 @@ public class TraceRmiTarget extends AbstractTarget {
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TraceObject findObject(ActionContext context, boolean allowContextObject,
|
protected TraceObject findObject(ActionContext context, ObjectArgumentPolicy policy) {
|
||||||
boolean allowCoordsObject) {
|
if (policy.allowContextObject()) {
|
||||||
if (allowContextObject) {
|
|
||||||
if (context instanceof DebuggerObjectActionContext ctx) {
|
if (context instanceof DebuggerObjectActionContext ctx) {
|
||||||
List<TraceObjectValue> values = ctx.getObjectValues();
|
List<TraceObjectValue> values = ctx.getObjectValues();
|
||||||
if (values.size() == 1) {
|
if (values.size() == 1) {
|
||||||
|
@ -224,7 +224,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (allowCoordsObject) {
|
if (policy.allowCoordsObject()) {
|
||||||
DebuggerTraceManagerService traceManager =
|
DebuggerTraceManagerService traceManager =
|
||||||
tool.getService(DebuggerTraceManagerService.class);
|
tool.getService(DebuggerTraceManagerService.class);
|
||||||
if (traceManager == null) {
|
if (traceManager == null) {
|
||||||
|
@ -246,16 +246,15 @@ public class TraceRmiTarget extends AbstractTarget {
|
||||||
* @param action the action name, so this is only applied to {@link ActionName#TOGGLE}
|
* @param action the action name, so this is only applied to {@link ActionName#TOGGLE}
|
||||||
* @param context the context in which to find the object whose current state is to be
|
* @param context the context in which to find the object whose current state is to be
|
||||||
* considered
|
* considered
|
||||||
* @param allowContextObject true to allow the object to come from context
|
* @param policy how object arguments can be found
|
||||||
* @param allowCoordsObject true to allow the object to come from the current coordinates
|
|
||||||
* @return a value if found, null if not
|
* @return a value if found, null if not
|
||||||
*/
|
*/
|
||||||
protected Boolean findBool(ActionName action, ActionContext context, boolean allowContextObject,
|
protected Boolean findBool(ActionName action, ActionContext context,
|
||||||
boolean allowCoordsObject) {
|
ObjectArgumentPolicy policy) {
|
||||||
if (!Objects.equals(action, ActionName.TOGGLE)) {
|
if (!Objects.equals(action, ActionName.TOGGLE)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
TraceObject object = findObject(context, allowContextObject, allowCoordsObject);
|
TraceObject object = findObject(context, policy);
|
||||||
if (object == null) {
|
if (object == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -266,22 +265,21 @@ public class TraceRmiTarget extends AbstractTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object findArgumentForSchema(ActionName action, ActionContext context,
|
protected Object findArgumentForSchema(ActionName action, ActionContext context,
|
||||||
TraceObjectSchema schema, boolean allowContextObject, boolean allowCoordsObject,
|
TraceObjectSchema schema, ObjectArgumentPolicy policy) {
|
||||||
boolean allowSuitableObject) {
|
|
||||||
if (schema instanceof PrimitiveTraceObjectSchema prim) {
|
if (schema instanceof PrimitiveTraceObjectSchema prim) {
|
||||||
return switch (prim) {
|
return switch (prim) {
|
||||||
case OBJECT -> findObject(context, allowContextObject, allowCoordsObject);
|
case OBJECT -> findObject(context, policy);
|
||||||
case ADDRESS -> findAddress(context);
|
case ADDRESS -> findAddress(context);
|
||||||
case RANGE -> findRange(context);
|
case RANGE -> findRange(context);
|
||||||
case BOOL -> findBool(action, context, allowContextObject, allowCoordsObject);
|
case BOOL -> findBool(action, context, policy);
|
||||||
default -> null;
|
default -> null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
TraceObject object = findObject(context, allowContextObject, allowCoordsObject);
|
TraceObject object = findObject(context, policy);
|
||||||
if (object == null) {
|
if (object == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (allowSuitableObject) {
|
if (policy.allowSuitableRelative()) {
|
||||||
return object.findSuitableSchema(schema);
|
return object.findSuitableSchema(schema);
|
||||||
}
|
}
|
||||||
if (object.getSchema() == schema) {
|
if (object.getSchema() == schema) {
|
||||||
|
@ -299,8 +297,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object findArgument(ActionName action, RemoteParameter parameter,
|
protected Object findArgument(ActionName action, RemoteParameter parameter,
|
||||||
ActionContext context, boolean allowContextObject, boolean allowCoordsObject,
|
ActionContext context, ObjectArgumentPolicy policy) {
|
||||||
boolean allowSuitableObject) {
|
|
||||||
SchemaName type = parameter.type();
|
SchemaName type = parameter.type();
|
||||||
SchemaContext ctx = getSchemaContext();
|
SchemaContext ctx = getSchemaContext();
|
||||||
if (ctx == null) {
|
if (ctx == null) {
|
||||||
|
@ -312,8 +309,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
||||||
Msg.error(this, "Schema " + type + " not in trace! " + trace);
|
Msg.error(this, "Schema " + type + " not in trace! " + trace);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Object arg = findArgumentForSchema(action, context, schema, allowContextObject,
|
Object arg = findArgumentForSchema(action, context, schema, policy);
|
||||||
allowCoordsObject, allowSuitableObject);
|
|
||||||
if (arg != null) {
|
if (arg != null) {
|
||||||
return arg;
|
return arg;
|
||||||
}
|
}
|
||||||
|
@ -324,11 +320,10 @@ public class TraceRmiTarget extends AbstractTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map<String, Object> collectArguments(RemoteMethod method, ActionContext context,
|
protected Map<String, Object> collectArguments(RemoteMethod method, ActionContext context,
|
||||||
boolean allowContextObject, boolean allowCoordsObject, boolean allowSuitableObject) {
|
ObjectArgumentPolicy policy) {
|
||||||
Map<String, Object> args = new HashMap<>();
|
Map<String, Object> args = new HashMap<>();
|
||||||
for (RemoteParameter param : method.parameters().values()) {
|
for (RemoteParameter param : method.parameters().values()) {
|
||||||
Object found = findArgument(method.action(), param, context, allowContextObject,
|
Object found = findArgument(method.action(), param, context, policy);
|
||||||
allowCoordsObject, allowSuitableObject);
|
|
||||||
if (found != null) {
|
if (found != null) {
|
||||||
args.put(param.name(), found);
|
args.put(param.name(), found);
|
||||||
}
|
}
|
||||||
|
@ -336,8 +331,36 @@ public class TraceRmiTarget extends AbstractTarget {
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static long computeSpecificity(Map<String, Object> args) {
|
/**
|
||||||
|
* Compute the specificity of the entry.
|
||||||
|
*
|
||||||
|
* More specific is generally preferred. There are two sorts of specificity here. 1) The
|
||||||
|
* specificity of the methods formal parameters. A parameter having a non-primitive schema is
|
||||||
|
* more specific than one having an ANY or OBJECT schema. 2) The specificity of the objects
|
||||||
|
* selected as arguments. This is crudely computed as the length of the canonical path.
|
||||||
|
*
|
||||||
|
* @param method the method
|
||||||
|
* @param args the arguments
|
||||||
|
* @return the specificity
|
||||||
|
*/
|
||||||
|
protected static long computeSpecificity(RemoteMethod method, Map<String, Object> args) {
|
||||||
long score = 0;
|
long score = 0;
|
||||||
|
for (RemoteParameter param : method.parameters().values()) {
|
||||||
|
score += switch (MinimalSchemaContext.INSTANCE.getSchemaOrNull(param.type())) {
|
||||||
|
case PrimitiveTraceObjectSchema prim -> switch (prim) {
|
||||||
|
case ANY -> 0; // Absolutely not specific
|
||||||
|
case OBJECT -> 1; // well, it is better than ANY
|
||||||
|
default -> 2; // real primitives
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Because we're using the "minimal" schema, not the actual one, anything
|
||||||
|
* user-defined will be null.
|
||||||
|
*/
|
||||||
|
case null -> 100;
|
||||||
|
default -> 100;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
score *= 1000;
|
||||||
for (Object o : args.values()) {
|
for (Object o : args.values()) {
|
||||||
if (o instanceof TraceObject obj) {
|
if (o instanceof TraceObject obj) {
|
||||||
score += obj.getCanonicalPath().size();
|
score += obj.getCanonicalPath().size();
|
||||||
|
@ -408,19 +431,16 @@ public class TraceRmiTarget extends AbstractTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ActionEntry createEntry(RemoteMethod method, ActionContext context,
|
protected ActionEntry createEntry(RemoteMethod method, ActionContext context,
|
||||||
boolean allowContextObject, boolean allowCoordsObject, boolean allowSuitableObject) {
|
ObjectArgumentPolicy policy) {
|
||||||
Map<String, Object> args = collectArguments(method, context, allowContextObject,
|
Map<String, Object> args = collectArguments(method, context, policy);
|
||||||
allowCoordsObject, allowSuitableObject);
|
|
||||||
return new TraceRmiActionEntry(method, args);
|
return new TraceRmiActionEntry(method, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map<String, ActionEntry> collectFromMethods(Collection<RemoteMethod> methods,
|
protected Map<String, ActionEntry> collectFromMethods(Collection<RemoteMethod> methods,
|
||||||
ActionContext context, boolean allowContextObject, boolean allowCoordsObject,
|
ActionContext context, ObjectArgumentPolicy policy) {
|
||||||
boolean allowSuitableObject) {
|
|
||||||
Map<String, ActionEntry> result = new HashMap<>();
|
Map<String, ActionEntry> result = new HashMap<>();
|
||||||
for (RemoteMethod m : methods) {
|
for (RemoteMethod m : methods) {
|
||||||
ActionEntry entry = createEntry(m, context, allowContextObject, allowCoordsObject,
|
ActionEntry entry = createEntry(m, context, policy);
|
||||||
allowSuitableObject);
|
|
||||||
result.put(m.name(), entry);
|
result.put(m.name(), entry);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -442,7 +462,6 @@ public class TraceRmiTarget extends AbstractTarget {
|
||||||
.count() == 1;
|
.count() == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, ActionEntry> collectAddressActions(ProgramLocationActionContext context) {
|
protected Map<String, ActionEntry> collectAddressActions(ProgramLocationActionContext context) {
|
||||||
SchemaContext ctx = getSchemaContext();
|
SchemaContext ctx = getSchemaContext();
|
||||||
Map<String, ActionEntry> result = new HashMap<>();
|
Map<String, ActionEntry> result = new HashMap<>();
|
||||||
|
@ -450,78 +469,31 @@ public class TraceRmiTarget extends AbstractTarget {
|
||||||
if (!isAddressMethod(m, ctx)) {
|
if (!isAddressMethod(m, ctx)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
result.put(m.name(), createEntry(m, context, true, true, true));
|
result.put(m.name(), createEntry(m, context, ObjectArgumentPolicy.CURRENT_AND_RELATED));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
protected Map<String, ActionEntry> collectAllActions(ActionContext context,
|
||||||
protected Map<String, ActionEntry> collectAllActions(ActionContext context) {
|
ObjectArgumentPolicy policy) {
|
||||||
return collectFromMethods(connection.getMethods().all().values(), context, true, false,
|
return collectFromMethods(connection.getMethods().all().values(), context, policy);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map<String, ActionEntry> collectByName(ActionName name, ActionContext context) {
|
protected Map<String, ActionEntry> collectByName(ActionName name, ActionContext context,
|
||||||
return collectFromMethods(connection.getMethods().getByAction(name), context, false, true,
|
ObjectArgumentPolicy policy) {
|
||||||
true);
|
return collectFromMethods(connection.getMethods().getByAction(name), context, policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, ActionEntry> collectActions(ActionName name, ActionContext context) {
|
public Map<String, ActionEntry> collectActions(ActionName name, ActionContext context,
|
||||||
|
ObjectArgumentPolicy policy) {
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
if (context instanceof ProgramLocationActionContext ctx) {
|
if (context instanceof ProgramLocationActionContext ctx) {
|
||||||
return collectAddressActions(ctx);
|
return collectAddressActions(ctx);
|
||||||
}
|
}
|
||||||
return collectAllActions(context);
|
return collectAllActions(context, policy);
|
||||||
}
|
}
|
||||||
return collectByName(name, context);
|
return collectByName(name, context, policy);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, ActionEntry> collectResumeActions(ActionContext context) {
|
|
||||||
return collectByName(ActionName.RESUME, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, ActionEntry> collectInterruptActions(ActionContext context) {
|
|
||||||
return collectByName(ActionName.INTERRUPT, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, ActionEntry> collectKillActions(ActionContext context) {
|
|
||||||
return collectByName(ActionName.KILL, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, ActionEntry> collectStepIntoActions(ActionContext context) {
|
|
||||||
return collectByName(ActionName.STEP_INTO, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, ActionEntry> collectStepOverActions(ActionContext context) {
|
|
||||||
return collectByName(ActionName.STEP_OVER, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, ActionEntry> collectStepOutActions(ActionContext context) {
|
|
||||||
return collectByName(ActionName.STEP_OUT, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, ActionEntry> collectStepExtActions(ActionContext context) {
|
|
||||||
return collectByName(ActionName.STEP_EXT, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, ActionEntry> collectRefreshActions(ActionContext context) {
|
|
||||||
return collectFromMethods(connection.getMethods().getByAction(ActionName.REFRESH), context,
|
|
||||||
true, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, ActionEntry> collectToggleActions(ActionContext context) {
|
|
||||||
return collectFromMethods(connection.getMethods().getByAction(ActionName.TOGGLE), context,
|
|
||||||
true, false, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1420,7 +1392,8 @@ public class TraceRmiTarget extends AbstractTarget {
|
||||||
RemoteParameter paramProc = brk.params.get("process");
|
RemoteParameter paramProc = brk.params.get("process");
|
||||||
if (paramProc != null) {
|
if (paramProc != null) {
|
||||||
Object proc = findArgumentForSchema(null, null,
|
Object proc = findArgumentForSchema(null, null,
|
||||||
getSchemaContext().getSchema(paramProc.type()), true, true, true);
|
getSchemaContext().getSchema(paramProc.type()),
|
||||||
|
ObjectArgumentPolicy.CURRENT_AND_RELATED);
|
||||||
if (proc == null) {
|
if (proc == null) {
|
||||||
Msg.error(this, "Cannot find required process argument for " + brk.method);
|
Msg.error(this, "Cannot find required process argument for " + brk.method);
|
||||||
}
|
}
|
||||||
|
@ -1675,7 +1648,8 @@ public class TraceRmiTarget extends AbstractTarget {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Void> forceTerminateAsync() {
|
public CompletableFuture<Void> forceTerminateAsync() {
|
||||||
Map<String, ActionEntry> kills = collectKillActions(null);
|
Map<String, ActionEntry> kills =
|
||||||
|
collectByName(ActionName.KILL, null, ObjectArgumentPolicy.CURRENT_AND_RELATED);
|
||||||
for (ActionEntry kill : kills.values()) {
|
for (ActionEntry kill : kills.values()) {
|
||||||
if (kill.requiresPrompt()) {
|
if (kill.requiresPrompt()) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -46,6 +46,7 @@ import ghidra.debug.api.control.ControlMode;
|
||||||
import ghidra.debug.api.target.ActionName;
|
import ghidra.debug.api.target.ActionName;
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
import ghidra.debug.api.target.Target.ActionEntry;
|
import ghidra.debug.api.target.Target.ActionEntry;
|
||||||
|
import ghidra.debug.api.target.Target.ObjectArgumentPolicy;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.framework.model.DomainObjectEvent;
|
import ghidra.framework.model.DomainObjectEvent;
|
||||||
import ghidra.framework.plugintool.*;
|
import ghidra.framework.plugintool.*;
|
||||||
|
@ -327,7 +328,9 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter
|
||||||
return stub;
|
return stub;
|
||||||
}
|
}
|
||||||
List<DockingActionIf> result = new ArrayList<>();
|
List<DockingActionIf> result = new ArrayList<>();
|
||||||
for (ActionEntry entry : target.collectActions(ActionName.BREAK_EXT, context)
|
for (ActionEntry entry : target
|
||||||
|
.collectActions(ActionName.BREAK_EXT, context,
|
||||||
|
ObjectArgumentPolicy.CURRENT_AND_RELATED)
|
||||||
.values()) {
|
.values()) {
|
||||||
result.add(new GenericSetBreakpointAction(entry));
|
result.add(new GenericSetBreakpointAction(entry));
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ import ghidra.debug.api.model.DebuggerObjectActionContext;
|
||||||
import ghidra.debug.api.target.ActionName;
|
import ghidra.debug.api.target.ActionName;
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
import ghidra.debug.api.target.Target.ActionEntry;
|
import ghidra.debug.api.target.Target.ActionEntry;
|
||||||
|
import ghidra.debug.api.target.Target.ObjectArgumentPolicy;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.framework.plugintool.*;
|
import ghidra.framework.plugintool.*;
|
||||||
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
||||||
|
@ -282,7 +283,10 @@ public class DebuggerControlPlugin extends AbstractDebuggerPlugin
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addTargetStepExtActions(Target target) {
|
protected void addTargetStepExtActions(Target target) {
|
||||||
for (ActionEntry entry : target.collectActions(ActionName.STEP_EXT, context).values()) {
|
for (ActionEntry entry : target
|
||||||
|
.collectActions(ActionName.STEP_EXT, context,
|
||||||
|
ObjectArgumentPolicy.CURRENT_AND_RELATED)
|
||||||
|
.values()) {
|
||||||
if (entry.requiresPrompt()) {
|
if (entry.requiresPrompt()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ import ghidra.debug.api.control.ControlMode;
|
||||||
import ghidra.debug.api.model.DebuggerObjectActionContext;
|
import ghidra.debug.api.model.DebuggerObjectActionContext;
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
import ghidra.debug.api.target.Target.ActionEntry;
|
import ghidra.debug.api.target.Target.ActionEntry;
|
||||||
|
import ghidra.debug.api.target.Target.ObjectArgumentPolicy;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.framework.plugintool.*;
|
import ghidra.framework.plugintool.*;
|
||||||
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
||||||
|
@ -119,7 +120,9 @@ public class DebuggerMethodActionsPlugin extends Plugin implements PopupActionPr
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DockingActionIf> result = new ArrayList<>();
|
List<DockingActionIf> result = new ArrayList<>();
|
||||||
for (ActionEntry entry : target.collectActions(null, context).values()) {
|
for (ActionEntry entry : target
|
||||||
|
.collectActions(null, context, ObjectArgumentPolicy.CONTEXT_ONLY)
|
||||||
|
.values()) {
|
||||||
//if (entry.requiresPrompt() || entry.builtIn()) {
|
//if (entry.requiresPrompt() || entry.builtIn()) {
|
||||||
if (!entry.isEnabled() || !entry.getShow().isShowing(context)) {
|
if (!entry.isEnabled() || !entry.getShow().isShowing(context)) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -24,6 +24,7 @@ import ghidra.app.services.DebuggerTraceManagerService;
|
||||||
import ghidra.debug.api.target.ActionName;
|
import ghidra.debug.api.target.ActionName;
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
import ghidra.debug.api.target.Target.ActionEntry;
|
import ghidra.debug.api.target.Target.ActionEntry;
|
||||||
|
import ghidra.debug.api.target.Target.ObjectArgumentPolicy;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
|
|
||||||
class TargetDockingAction extends DockingAction {
|
class TargetDockingAction extends DockingAction {
|
||||||
|
@ -51,7 +52,7 @@ class TargetDockingAction extends DockingAction {
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return target.collectActions(action, context)
|
return target.collectActions(action, context, ObjectArgumentPolicy.CURRENT_AND_RELATED)
|
||||||
.values()
|
.values()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(e -> !e.requiresPrompt())
|
.filter(e -> !e.requiresPrompt())
|
||||||
|
|
|
@ -55,6 +55,7 @@ import ghidra.debug.api.model.DebuggerObjectActionContext;
|
||||||
import ghidra.debug.api.target.ActionName;
|
import ghidra.debug.api.target.ActionName;
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
import ghidra.debug.api.target.Target.ActionEntry;
|
import ghidra.debug.api.target.Target.ActionEntry;
|
||||||
|
import ghidra.debug.api.target.Target.ObjectArgumentPolicy;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.framework.options.SaveState;
|
import ghidra.framework.options.SaveState;
|
||||||
import ghidra.framework.plugintool.*;
|
import ghidra.framework.plugintool.*;
|
||||||
|
@ -767,30 +768,34 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Map<String, ActionEntry> actions = target.collectActions(ActionName.REFRESH,
|
ActionEntry ent = target.collectActions(ActionName.REFRESH,
|
||||||
new DebuggerObjectActionContext(List.of(value), this, objectsTreePanel,
|
new DebuggerObjectActionContext(List.of(value), this, objectsTreePanel,
|
||||||
current.getSnap()));
|
current.getSnap()),
|
||||||
for (ActionEntry ent : actions.values()) {
|
ObjectArgumentPolicy.CONTEXT_ONLY)
|
||||||
if (ent.requiresPrompt()) {
|
.values()
|
||||||
continue;
|
.stream()
|
||||||
}
|
.filter(e -> !e.requiresPrompt())
|
||||||
if (path.getLastPathComponent() instanceof AbstractNode node) {
|
.sorted(Comparator.comparing(e -> -e.specificity()))
|
||||||
/**
|
.findFirst()
|
||||||
* This pending node does not duplicate what the lazy node already does. For all
|
.orElse(null);
|
||||||
* it's concerned, once it has loaded the entries from the database, it is done.
|
if (ent == null) {
|
||||||
* This task asks the target to update that database, so it needs its own indicator.
|
// Fail silently. It's common for nodes to not have a refresh action.
|
||||||
*/
|
return;
|
||||||
PendingNode pending = new PendingNode();
|
|
||||||
node.addNode(0, pending);
|
|
||||||
CompletableFuture<Void> future =
|
|
||||||
TargetActionTask.runAction(plugin.getTool(), ent.display(), ent);
|
|
||||||
future.handle((__, ex) -> {
|
|
||||||
node.removeNode(pending);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
AbstractNode node = (AbstractNode) path.getLastPathComponent();
|
||||||
|
/**
|
||||||
|
* This pending node does not duplicate what the lazy node already does. For all it's
|
||||||
|
* concerned, once it has loaded the entries from the database, it is done. This task asks
|
||||||
|
* the target to update that database, so it needs its own indicator.
|
||||||
|
*/
|
||||||
|
PendingNode pending = new PendingNode();
|
||||||
|
node.addNode(0, pending);
|
||||||
|
CompletableFuture<Void> future =
|
||||||
|
TargetActionTask.runAction(plugin.getTool(), ent.display(), ent);
|
||||||
|
future.handle((__, ex) -> {
|
||||||
|
node.removeNode(pending);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -28,13 +28,15 @@ import ghidra.debug.api.model.DebuggerSingleObjectPathActionContext;
|
||||||
import ghidra.debug.api.target.ActionName;
|
import ghidra.debug.api.target.ActionName;
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
import ghidra.debug.api.target.Target.ActionEntry;
|
import ghidra.debug.api.target.Target.ActionEntry;
|
||||||
|
import ghidra.debug.api.target.Target.ObjectArgumentPolicy;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressRange;
|
import ghidra.program.model.address.AddressRange;
|
||||||
import ghidra.program.util.ProgramLocation;
|
import ghidra.program.util.ProgramLocation;
|
||||||
import ghidra.program.util.ProgramSelection;
|
import ghidra.program.util.ProgramSelection;
|
||||||
import ghidra.trace.model.target.*;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
|
import ghidra.trace.model.target.TraceObjectValue;
|
||||||
import ghidra.trace.model.target.iface.*;
|
import ghidra.trace.model.target.iface.*;
|
||||||
import ghidra.trace.model.target.path.KeyPath;
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
@ -53,7 +55,8 @@ public interface ObjectDefaultActionsMixin {
|
||||||
}
|
}
|
||||||
Target target = getCurrent().getTarget();
|
Target target = getCurrent().getTarget();
|
||||||
Map<String, ActionEntry> actions = target.collectActions(ActionName.TOGGLE,
|
Map<String, ActionEntry> actions = target.collectActions(ActionName.TOGGLE,
|
||||||
new DebuggerSingleObjectPathActionContext(object.getCanonicalPath()));
|
new DebuggerSingleObjectPathActionContext(object.getCanonicalPath()),
|
||||||
|
ObjectArgumentPolicy.CONTEXT_ONLY);
|
||||||
ActionEntry action = actions.values()
|
ActionEntry action = actions.values()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(e -> !e.requiresPrompt())
|
.filter(e -> !e.requiresPrompt())
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -19,17 +19,13 @@ import java.util.*;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import ghidra.app.context.NavigatableActionContext;
|
import ghidra.app.context.NavigatableActionContext;
|
||||||
import ghidra.app.context.ProgramLocationActionContext;
|
|
||||||
import ghidra.app.nav.Navigatable;
|
import ghidra.app.nav.Navigatable;
|
||||||
import ghidra.app.services.*;
|
import ghidra.app.services.*;
|
||||||
import ghidra.app.services.DebuggerStaticMappingService.MappedAddressRange;
|
import ghidra.app.services.DebuggerStaticMappingService.MappedAddressRange;
|
||||||
import ghidra.async.AsyncUtils;
|
import ghidra.async.AsyncUtils;
|
||||||
import ghidra.debug.api.target.ActionName;
|
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
|
@ -46,7 +42,6 @@ import ghidra.trace.model.guest.TracePlatform;
|
||||||
import ghidra.trace.model.program.TraceProgramView;
|
import ghidra.trace.model.program.TraceProgramView;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.trace.util.TraceRegisterUtils;
|
import ghidra.trace.util.TraceRegisterUtils;
|
||||||
import ghidra.util.Msg;
|
|
||||||
import ghidra.util.Swing;
|
import ghidra.util.Swing;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
@ -186,81 +181,6 @@ public abstract class AbstractTarget implements Target {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract Map<String, ActionEntry> collectAddressActions(
|
|
||||||
ProgramLocationActionContext context);
|
|
||||||
|
|
||||||
protected Map<String, ActionEntry> collectAllActions(ActionContext context) {
|
|
||||||
return Stream.of(
|
|
||||||
collectResumeActions(context),
|
|
||||||
collectInterruptActions(context),
|
|
||||||
collectKillActions(context),
|
|
||||||
collectStepIntoActions(context),
|
|
||||||
collectStepOverActions(context),
|
|
||||||
collectStepOutActions(context),
|
|
||||||
collectStepExtActions(context),
|
|
||||||
collectRefreshActions(context),
|
|
||||||
collectToggleActions(context))
|
|
||||||
.flatMap(m -> m.entrySet().stream())
|
|
||||||
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Map<String, ActionEntry> collectResumeActions(ActionContext context);
|
|
||||||
|
|
||||||
protected abstract Map<String, ActionEntry> collectInterruptActions(ActionContext context);
|
|
||||||
|
|
||||||
protected abstract Map<String, ActionEntry> collectKillActions(ActionContext context);
|
|
||||||
|
|
||||||
protected abstract Map<String, ActionEntry> collectStepIntoActions(ActionContext context);
|
|
||||||
|
|
||||||
protected abstract Map<String, ActionEntry> collectStepOverActions(ActionContext context);
|
|
||||||
|
|
||||||
protected abstract Map<String, ActionEntry> collectStepOutActions(ActionContext context);
|
|
||||||
|
|
||||||
protected abstract Map<String, ActionEntry> collectStepExtActions(ActionContext context);
|
|
||||||
|
|
||||||
protected abstract Map<String, ActionEntry> collectRefreshActions(ActionContext context);
|
|
||||||
|
|
||||||
protected abstract Map<String, ActionEntry> collectToggleActions(ActionContext context);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, ActionEntry> collectActions(ActionName name, ActionContext context) {
|
|
||||||
if (name == null) {
|
|
||||||
if (context instanceof ProgramLocationActionContext ctx) {
|
|
||||||
return collectAddressActions(ctx);
|
|
||||||
}
|
|
||||||
return collectAllActions(context);
|
|
||||||
}
|
|
||||||
else if (ActionName.RESUME.equals(name)) {
|
|
||||||
return collectResumeActions(context);
|
|
||||||
}
|
|
||||||
else if (ActionName.INTERRUPT.equals(name)) {
|
|
||||||
return collectInterruptActions(context);
|
|
||||||
}
|
|
||||||
else if (ActionName.KILL.equals(name)) {
|
|
||||||
return collectKillActions(context);
|
|
||||||
}
|
|
||||||
else if (ActionName.STEP_INTO.equals(name)) {
|
|
||||||
return collectStepIntoActions(context);
|
|
||||||
}
|
|
||||||
else if (ActionName.STEP_OVER.equals(name)) {
|
|
||||||
return collectStepOverActions(context);
|
|
||||||
}
|
|
||||||
else if (ActionName.STEP_OUT.equals(name)) {
|
|
||||||
return collectStepOutActions(context);
|
|
||||||
}
|
|
||||||
else if (ActionName.STEP_EXT.equals(name)) {
|
|
||||||
return collectStepExtActions(context);
|
|
||||||
}
|
|
||||||
else if (ActionName.REFRESH.equals(name)) {
|
|
||||||
return collectRefreshActions(context);
|
|
||||||
}
|
|
||||||
else if (ActionName.TOGGLE.equals(name)) {
|
|
||||||
return collectToggleActions(context);
|
|
||||||
}
|
|
||||||
Msg.warn(this, "Unrecognized action name: " + name);
|
|
||||||
return Map.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static <T> T doSync(String name, Supplier<CompletableFuture<T>> supplier)
|
protected static <T> T doSync(String name, Supplier<CompletableFuture<T>> supplier)
|
||||||
throws InterruptedException, ExecutionException {
|
throws InterruptedException, ExecutionException {
|
||||||
if (Swing.isSwingThread()) {
|
if (Swing.isSwingThread()) {
|
||||||
|
|
|
@ -27,8 +27,8 @@ import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
import ghidra.program.model.lang.RegisterValue;
|
import ghidra.program.model.lang.RegisterValue;
|
||||||
import ghidra.trace.model.TraceExecutionState;
|
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.TraceExecutionState;
|
||||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||||
import ghidra.trace.model.guest.TracePlatform;
|
import ghidra.trace.model.guest.TracePlatform;
|
||||||
|
@ -71,7 +71,8 @@ public class MockTarget implements Target {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, ActionEntry> collectActions(ActionName name, ActionContext context) {
|
public Map<String, ActionEntry> collectActions(ActionName name, ActionContext context,
|
||||||
|
ObjectArgumentPolicy policy) {
|
||||||
return Map.of();
|
return Map.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue