GP-1978: Port tests to TraceRmi and delete more stuff.

This commit is contained in:
Dan 2024-12-12 11:43:47 -05:00
parent dadfc465df
commit 5813548a84
110 changed files with 1762 additions and 17529 deletions

View file

@ -664,7 +664,7 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer
trace = connection.waitForTrace(getTimeoutMillis());
traceManager.openTrace(trace);
traceManager.activate(traceManager.resolveTrace(trace),
ActivationCause.START_RECORDING);
ActivationCause.TARGET_UPDATED);
monitor.increment();
waitForModuleMapping(monitor, connection, trace);

View file

@ -0,0 +1,72 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.plugin.core.debug.service.tracermi;
import ghidra.app.services.DebuggerControlService;
import ghidra.app.services.DebuggerTraceManagerService;
import ghidra.app.services.DebuggerTraceManagerService.ActivationCause;
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
import ghidra.debug.api.tracermi.TraceRmiConnection;
import ghidra.trace.model.Trace;
import ghidra.trace.model.target.TraceObject;
import ghidra.trace.model.time.TraceSnapshot;
import ghidra.util.Swing;
public abstract class AbstractTraceRmiConnection implements TraceRmiConnection {
protected abstract DebuggerTraceManagerService getTraceManager();
protected abstract DebuggerControlService getControlService();
protected abstract boolean ownsTrace(Trace trace);
protected boolean followsPresent(Trace trace) {
DebuggerControlService controlService = getControlService();
if (controlService == null) {
return true;
}
return controlService.getCurrentMode(trace).followsPresent();
}
protected void doActivate(TraceObject object, Trace trace, TraceSnapshot snapshot) {
DebuggerCoordinates coords = getTraceManager().getCurrent();
if (coords.getTrace() != trace) {
coords = DebuggerCoordinates.NOWHERE;
}
if (snapshot != null && followsPresent(trace)) {
coords = coords.snap(snapshot.getKey());
}
DebuggerCoordinates finalCoords = object == null ? coords : coords.object(object);
Swing.runLater(() -> {
DebuggerTraceManagerService traceManager = getTraceManager();
if (traceManager == null) {
// Can happen during tear down.
return;
}
if (!traceManager.getOpenTraces().contains(trace)) {
traceManager.openTrace(trace);
traceManager.activate(finalCoords, ActivationCause.SYNC_MODEL);
}
else {
Trace currentTrace = traceManager.getCurrentTrace();
if (currentTrace == null || ownsTrace(currentTrace)) {
traceManager.activate(finalCoords, ActivationCause.SYNC_MODEL);
}
}
});
}
}

View file

@ -35,7 +35,6 @@ import ghidra.app.plugin.core.debug.disassemble.DebuggerDisassemblerPlugin;
import ghidra.app.plugin.core.debug.disassemble.TraceDisassembleCommand;
import ghidra.app.services.DebuggerControlService;
import ghidra.app.services.DebuggerTraceManagerService;
import ghidra.app.services.DebuggerTraceManagerService.ActivationCause;
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
import ghidra.dbg.target.schema.XmlSchemaContext;
import ghidra.dbg.util.PathPattern;
@ -43,7 +42,6 @@ import ghidra.dbg.util.PathUtils;
import ghidra.debug.api.progress.CloseableTaskMonitor;
import ghidra.debug.api.target.ActionName;
import ghidra.debug.api.target.Target;
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
import ghidra.debug.api.tracermi.*;
import ghidra.framework.Application;
import ghidra.framework.model.*;
@ -67,7 +65,7 @@ import ghidra.util.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.DuplicateFileException;
public class TraceRmiHandler implements TraceRmiConnection {
public class TraceRmiHandler extends AbstractTraceRmiConnection {
public static final String VERSION = "11.2";
protected static class VersionMismatchError extends TraceRmiError {
@ -817,42 +815,25 @@ public class TraceRmiHandler implements TraceRmiConnection {
return makeArgument(ent.getKey(), ent.getValue());
}
protected boolean followsPresent(Trace trace) {
DebuggerControlService controlService = this.controlService;
if (controlService == null) {
return true;
}
return controlService.getCurrentMode(trace).followsPresent();
@Override
protected DebuggerTraceManagerService getTraceManager() {
return this.traceManager;
}
@Override
protected DebuggerControlService getControlService() {
return this.controlService;
}
@Override
protected boolean ownsTrace(Trace trace) {
return openTraces.getByTrace(trace) != null;
}
protected ReplyActivate handleActivate(RequestActivate req) {
OpenTrace open = requireOpenTrace(req.getOid());
TraceObject object = open.getObject(req.getObject(), false);
DebuggerCoordinates coords = traceManager.getCurrent();
if (coords.getTrace() != open.trace) {
coords = DebuggerCoordinates.NOWHERE;
}
if (open.lastSnapshot != null && followsPresent(open.trace)) {
coords = coords.snap(open.lastSnapshot.getKey());
}
DebuggerCoordinates finalCoords = object == null ? coords : coords.object(object);
Swing.runLater(() -> {
DebuggerTraceManagerService traceManager = this.traceManager;
if (traceManager == null) {
// Can happen during tear down.
return;
}
if (!traceManager.getOpenTraces().contains(open.trace)) {
traceManager.openTrace(open.trace);
traceManager.activate(finalCoords, ActivationCause.SYNC_MODEL);
}
else {
Trace currentTrace = traceManager.getCurrentTrace();
if (currentTrace == null || openTraces.getByTrace(currentTrace) != null) {
traceManager.activate(finalCoords, ActivationCause.SYNC_MODEL);
}
}
});
doActivate(object, open.trace, open.lastSnapshot);
return ReplyActivate.getDefaultInstance();
}

View file

@ -334,10 +334,12 @@ public class TraceRmiTarget extends AbstractTarget {
ActionName.STEP_OUT.equals(name) ||
ActionName.STEP_OVER.equals(name) ||
ActionName.STEP_SKIP.equals(name)) {
return () -> whenState(obj, state -> state != null && (state.isStopped() || state.isUnknown()));
return () -> whenState(obj,
state -> state != null && (state.isStopped() || state.isUnknown()));
}
else if (ActionName.INTERRUPT.equals(name)) {
return () -> whenState(obj, state -> state == null || state.isRunning() || state.isUnknown());
return () -> whenState(obj,
state -> state == null || state.isRunning() || state.isUnknown());
}
else if (ActionName.KILL.equals(name)) {
return () -> whenState(obj, state -> state == null || !state.isTerminated());
@ -1211,13 +1213,13 @@ public class TraceRmiTarget extends AbstractTarget {
.thenApply(__ -> null);
}
protected boolean isMemorySpaceValid(AddressSpace space) {
return trace.getBaseAddressFactory().getAddressSpace(space.getSpaceID()) == space;
protected boolean isMemorySpaceValid(TracePlatform platform, AddressSpace space) {
return platform.getAddressFactory().getAddressSpace(space.getSpaceID()) == space;
}
protected boolean isRegisterValid(TracePlatform platform, TraceThread thread, int frame,
Address address, int length) {
if (!isMemorySpaceValid(address.getAddressSpace())) {
if (!isMemorySpaceValid(platform, address.getAddressSpace())) {
return false;
}
Register register =
@ -1239,7 +1241,7 @@ public class TraceRmiTarget extends AbstractTarget {
public boolean isVariableExists(TracePlatform platform, TraceThread thread, int frame,
Address address, int length) {
if (address.isMemoryAddress()) {
return isMemorySpaceValid(address.getAddressSpace());
return isMemorySpaceValid(platform, address.getAddressSpace());
}
if (address.isRegisterAddress()) {
return isRegisterValid(platform, thread, frame, address, length);

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -24,9 +24,9 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import db.Transaction;
import ghidra.app.services.DebuggerTargetService;
import ghidra.async.AsyncPairingQueue;
import ghidra.async.AsyncUtils;
import ghidra.async.*;
import ghidra.dbg.target.schema.TargetObjectSchema;
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
import ghidra.debug.api.target.ActionName;
@ -34,12 +34,14 @@ import ghidra.debug.api.target.Target;
import ghidra.debug.api.tracermi.*;
import ghidra.framework.plugintool.PluginTool;
import ghidra.trace.model.Trace;
import ghidra.trace.model.target.TraceObject;
import ghidra.trace.model.time.TraceSnapshot;
public class TestTraceRmiConnection implements TraceRmiConnection {
public abstract class TestTraceRmiConnection extends AbstractTraceRmiConnection {
protected final TestRemoteMethodRegistry registry = new TestRemoteMethodRegistry();
protected final CompletableFuture<Trace> firstTrace = new CompletableFuture<>();
protected final Map<Trace, Long> snapshots = new HashMap<>();
protected final Map<Trace, TraceSnapshot> snapshots = new HashMap<>();
protected final CompletableFuture<Void> closed = new CompletableFuture<>();
protected final Map<Trace, TraceRmiTarget> targets = new HashMap<>();
@ -88,8 +90,9 @@ public class TestTraceRmiConnection implements TraceRmiConnection {
return result;
}
public Map<String, Object> expect() throws InterruptedException, ExecutionException {
return argQueue.take().get();
public Map<String, Object> expect()
throws InterruptedException, ExecutionException, TimeoutException {
return argQueue.take().get(AsyncTestUtils.TIMEOUT_MS, TimeUnit.MILLISECONDS);
}
public void result(Object ret) {
@ -98,8 +101,7 @@ public class TestTraceRmiConnection implements TraceRmiConnection {
public CompletableFuture<Map<String, Object>> expect(
Function<Map<String, Object>, Object> impl) {
record ArgsRet(Map<String, Object> args, Object ret) {
}
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);
@ -149,6 +151,15 @@ public class TestTraceRmiConnection implements TraceRmiConnection {
return target;
}
public void withdrawTarget(PluginTool tool, Trace trace) {
Target target;
synchronized (targets) {
target = targets.remove(trace);
}
DebuggerTargetService targetService = tool.getService(DebuggerTargetService.class);
targetService.withdrawTarget(target);
}
@Override
public Trace waitForTrace(long timeoutMillis) throws TimeoutException {
try {
@ -159,17 +170,21 @@ public class TestTraceRmiConnection implements TraceRmiConnection {
}
}
public void setLastSnapshot(Trace trace, long snap) {
public TraceSnapshot setLastSnapshot(Trace trace, long snap) {
synchronized (snapshots) {
snapshots.put(trace, snap);
try (Transaction tx = trace.openTransaction("Add snapshot")) {
TraceSnapshot snapshot = trace.getTimeManager().getSnapshot(snap, true);
snapshots.put(trace, snapshot);
return snapshot;
}
}
}
@Override
public long getLastSnapshot(Trace trace) {
synchronized (snapshots) {
Long snap = snapshots.get(trace);
return snap == null ? 0 : snap;
TraceSnapshot snap = snapshots.get(trace);
return snap == null ? 0 : snap.getKey();
}
}
@ -225,4 +240,14 @@ public class TestTraceRmiConnection implements TraceRmiConnection {
public Collection<Target> getTargets() {
return List.copyOf(targets.values());
}
@Override
protected boolean ownsTrace(Trace trace) {
return targets.containsKey(trace);
}
public void synthActivate(TraceObject object) {
Trace trace = object.getTrace();
doActivate(object, trace, snapshots.get(trace));
}
}