mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
GP-3872: Port scripting API to Trace RMI
This commit is contained in:
parent
77923fa693
commit
ad6cb5892d
32 changed files with 3135 additions and 2063 deletions
|
@ -146,6 +146,15 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer
|
|||
this.terminalService = Objects.requireNonNull(tool.getService(TerminalService.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this.getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
AbstractTraceRmiLaunchOffer other = (AbstractTraceRmiLaunchOffer) obj;
|
||||
return this.getConfigName().equals(other.getConfigName());
|
||||
}
|
||||
|
||||
protected int getTimeoutMillis() {
|
||||
return DEFAULT_TIMEOUT_MILLIS;
|
||||
}
|
||||
|
|
|
@ -192,6 +192,15 @@ public class TraceRmiLauncherServicePlugin extends Plugin
|
|||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TraceRmiLaunchOffer> getSavedOffers(Program program) {
|
||||
Map<String, Long> savedConfigs = loadSavedConfigs(program);
|
||||
return getOffers(program).stream()
|
||||
.filter(o -> savedConfigs.containsKey(o.getConfigName()))
|
||||
.sorted(Comparator.comparing(o -> -savedConfigs.get(o.getConfigName())))
|
||||
.toList();
|
||||
}
|
||||
|
||||
protected void executeTask(Task task) {
|
||||
ProgressService progressService = tool.getService(ProgressService.class);
|
||||
if (progressService != null) {
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.apache.commons.lang3.exception.ExceptionUtils;
|
|||
|
||||
import docking.ActionContext;
|
||||
import ghidra.app.context.ProgramLocationActionContext;
|
||||
import ghidra.app.plugin.core.debug.gui.model.DebuggerObjectActionContext;
|
||||
import ghidra.app.plugin.core.debug.gui.tracermi.RemoteMethodInvocationDialog;
|
||||
import ghidra.app.plugin.core.debug.service.target.AbstractTarget;
|
||||
import ghidra.app.services.DebuggerConsoleService;
|
||||
|
@ -38,6 +37,7 @@ import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|||
import ghidra.dbg.util.PathMatcher;
|
||||
import ghidra.dbg.util.PathPredicates;
|
||||
import ghidra.dbg.util.PathPredicates.Align;
|
||||
import ghidra.debug.api.model.DebuggerObjectActionContext;
|
||||
import ghidra.debug.api.target.ActionName;
|
||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.debug.api.tracermi.*;
|
||||
|
@ -51,6 +51,7 @@ import ghidra.trace.model.Trace;
|
|||
import ghidra.trace.model.breakpoint.*;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
||||
import ghidra.trace.model.stack.*;
|
||||
import ghidra.trace.model.target.*;
|
||||
|
@ -611,6 +612,13 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
}
|
||||
}
|
||||
|
||||
record ExecuteMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||
static final ExecuteMatcher HAS_CMD_TOSTRING = new ExecuteMatcher(2, List.of(
|
||||
new TypeParamSpec("command", String.class),
|
||||
new TypeParamSpec("toString", Boolean.class)));
|
||||
static final List<ExecuteMatcher> ALL = matchers(HAS_CMD_TOSTRING);
|
||||
}
|
||||
|
||||
record ReadMemMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||
static final ReadMemMatcher HAS_PROC_RANGE = new ReadMemMatcher(2, List.of(
|
||||
new TypeParamSpec("process", TargetProcess.class),
|
||||
|
@ -841,6 +849,18 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<String> executeAsync(String command, boolean toString) {
|
||||
MatchedMethod execute = matches.getBest("execute", ActionName.EXECUTE, ExecuteMatcher.ALL);
|
||||
if (execute == null) {
|
||||
return CompletableFuture.failedFuture(new NoSuchElementException());
|
||||
}
|
||||
Map<String, Object> args = new HashMap<>();
|
||||
args.put(execute.params.get("command").name(), command);
|
||||
args.put(execute.params.get("toString").name(), toString);
|
||||
return execute.method.invokeAsync(args).toCompletableFuture().thenApply(v -> (String) v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> activateAsync(DebuggerCoordinates prev,
|
||||
DebuggerCoordinates coords) {
|
||||
|
@ -906,15 +926,11 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||
}
|
||||
|
||||
protected TraceObject getProcessForSpace(AddressSpace space) {
|
||||
for (TraceObjectValue objVal : trace.getObjectManager()
|
||||
.getValuesIntersecting(
|
||||
for (TraceMemoryRegion region : trace.getMemoryManager()
|
||||
.getRegionsIntersecting(
|
||||
Lifespan.at(getSnap()),
|
||||
new AddressRangeImpl(space.getMinAddress(), space.getMaxAddress()),
|
||||
TargetMemoryRegion.RANGE_ATTRIBUTE_NAME)) {
|
||||
TraceObject obj = objVal.getParent();
|
||||
if (!obj.getInterfaces().contains(TraceObjectMemoryRegion.class)) {
|
||||
continue;
|
||||
}
|
||||
new AddressRangeImpl(space.getMinAddress(), space.getMaxAddress()))) {
|
||||
TraceObject obj = ((TraceObjectMemoryRegion) region).getObject();
|
||||
return obj.queryCanonicalAncestorsTargetInterface(TargetProcess.class)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
|
|
@ -20,12 +20,14 @@ import java.net.InetSocketAddress;
|
|||
import java.net.SocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import ghidra.app.services.DebuggerTargetService;
|
||||
import ghidra.async.AsyncPairingQueue;
|
||||
import ghidra.async.AsyncUtils;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
||||
import ghidra.debug.api.target.ActionName;
|
||||
import ghidra.debug.api.target.Target;
|
||||
|
@ -65,6 +67,19 @@ public class TestTraceRmiConnection implements TraceRmiConnection {
|
|||
retType);
|
||||
}
|
||||
|
||||
public TestRemoteMethod(String name, ActionName action, String display, String description,
|
||||
Map<String, RemoteParameter> parameters, TargetObjectSchema retType) {
|
||||
this(name, action, display, description, parameters, retType.getName(),
|
||||
new AsyncPairingQueue<>(), new AsyncPairingQueue<>());
|
||||
}
|
||||
|
||||
public TestRemoteMethod(String name, ActionName action, String display, String description,
|
||||
TargetObjectSchema retType, RemoteParameter... parameters) {
|
||||
this(name, action, display, description, Stream.of(parameters)
|
||||
.collect(Collectors.toMap(RemoteParameter::name, p -> p)),
|
||||
retType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteAsyncResult invokeAsync(Map<String, Object> arguments) {
|
||||
argQueue.give().complete(arguments);
|
||||
|
@ -80,10 +95,24 @@ public class TestTraceRmiConnection implements TraceRmiConnection {
|
|||
public void result(Object ret) {
|
||||
retQueue.give().complete(ret);
|
||||
}
|
||||
|
||||
public CompletableFuture<Map<String, Object>> expect(
|
||||
Function<Map<String, Object>, Object> impl) {
|
||||
record ArgsRet(Map<String, Object> args, Object ret) {
|
||||
}
|
||||
var result = argQueue().take().thenApply(a -> new ArgsRet(a, impl.apply(a)));
|
||||
result.thenApply(ar -> ar.ret).handle(AsyncUtils.copyTo(retQueue().give()));
|
||||
return result.thenApply(ar -> ar.args);
|
||||
}
|
||||
}
|
||||
|
||||
public record TestRemoteParameter(String name, SchemaName type, boolean required,
|
||||
Object defaultValue, String display, String description) implements RemoteParameter {
|
||||
public TestRemoteParameter(String name, TargetObjectSchema type, boolean required,
|
||||
Object defaultValue, String display, String description) {
|
||||
this(name, type.getName(), required, defaultValue, display, description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getDefaultValue() {
|
||||
return defaultValue;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue