GP-740: Removed TargetObjectRef and cleaned up.

This commit is contained in:
Dan 2021-03-01 15:14:27 -05:00
parent b9f9c69be4
commit 6614b54248
328 changed files with 3177 additions and 4428 deletions

View file

@ -23,7 +23,6 @@ import agent.dbgeng.dbgeng.DebugProcessId;
import agent.dbgeng.dbgeng.DebugThreadId; import agent.dbgeng.dbgeng.DebugThreadId;
import agent.dbgeng.manager.DbgManager.ExecSuffix; import agent.dbgeng.manager.DbgManager.ExecSuffix;
import agent.dbgeng.manager.impl.DbgSectionImpl; import agent.dbgeng.manager.impl.DbgSectionImpl;
import ghidra.dbg.attributes.TypedTargetObjectRef;
import ghidra.dbg.target.TargetAttachable; import ghidra.dbg.target.TargetAttachable;
public interface DbgProcess extends DbgMemoryOperations { public interface DbgProcess extends DbgMemoryOperations {
@ -165,8 +164,7 @@ public interface DbgProcess extends DbgMemoryOperations {
* @param ref the target process * @param ref the target process
* @return a future that completes with a set of handles to all threads of the attached process * @return a future that completes with a set of handles to all threads of the attached process
*/ */
CompletableFuture<Set<DbgThread>> reattach( CompletableFuture<Set<DbgThread>> reattach(TargetAttachable attachable);
TypedTargetObjectRef<? extends TargetAttachable<?>> ref);
/** /**
* Execute an arbitrary kd command, capturing its console output * Execute an arbitrary kd command, capturing its console output
@ -187,8 +185,8 @@ public interface DbgProcess extends DbgMemoryOperations {
* Step the process * Step the process
* *
* Note that the command can complete before the process has finished stepping. The command * Note that the command can complete before the process has finished stepping. The command
* completes as soon as the process is running. A separate stop event is emitted when the step is * completes as soon as the process is running. A separate stop event is emitted when the step
* completed. * is completed.
* *
* @param suffix specifies how far to step, or on what conditions stepping ends. * @param suffix specifies how far to step, or on what conditions stepping ends.
* *
@ -200,8 +198,8 @@ public interface DbgProcess extends DbgMemoryOperations {
* Step the process * Step the process
* *
* Note that the command can complete before the process has finished stepping. The command * Note that the command can complete before the process has finished stepping. The command
* completes as soon as the process is running. A separate stop event is emitted when the step is * completes as soon as the process is running. A separate stop event is emitted when the step
* completed. * is completed.
* *
* @param args specifies how far to step, or on what conditions stepping ends. * @param args specifies how far to step, or on what conditions stepping ends.
* *

View file

@ -17,29 +17,29 @@ package agent.dbgeng.manager.cmd;
import agent.dbgeng.manager.impl.DbgManagerImpl; import agent.dbgeng.manager.impl.DbgManagerImpl;
import agent.dbgeng.model.iface1.DbgModelTargetFocusScope; import agent.dbgeng.model.iface1.DbgModelTargetFocusScope;
import ghidra.dbg.attributes.TargetObjectRef; import ghidra.dbg.target.TargetObject;
public class DbgRequestFocusCommand extends AbstractDbgCommand<Void> { public class DbgRequestFocusCommand extends AbstractDbgCommand<Void> {
private DbgModelTargetFocusScope<?> scope; private DbgModelTargetFocusScope scope;
private TargetObjectRef ref; private TargetObject obj;
/** /**
* Set focus for the current ref * Set focus for the current ref
* *
* @param manager the manager to execute the command * @param manager the manager to execute the command
* @param scope in most cases the root object (must be an ancestor for the ref) * @param scope in most cases the root object (must be an ancestor for the ref)
* @param ref the desired focus * @param obj the desired focus
*/ */
public DbgRequestFocusCommand(DbgManagerImpl manager, DbgModelTargetFocusScope<?> scope, public DbgRequestFocusCommand(DbgManagerImpl manager, DbgModelTargetFocusScope scope,
TargetObjectRef ref) { TargetObject obj) {
super(manager); super(manager);
this.scope = scope; this.scope = scope;
this.ref = ref; this.obj = obj;
} }
@Override @Override
public void invoke() { public void invoke() {
scope.doRequestFocus(ref); scope.doRequestFocus(obj);
} }
} }

View file

@ -15,7 +15,7 @@
*/ */
package agent.dbgeng.manager.impl; package agent.dbgeng.manager.impl;
import static ghidra.async.AsyncUtils.*; import static ghidra.async.AsyncUtils.sequence;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -44,7 +44,7 @@ import agent.dbgeng.model.iface1.DbgModelTargetFocusScope;
import ghidra.async.*; import ghidra.async.*;
import ghidra.async.seq.AsyncSequenceHandlerForRunner; import ghidra.async.seq.AsyncSequenceHandlerForRunner;
import ghidra.comm.util.BitmaskSet; import ghidra.comm.util.BitmaskSet;
import ghidra.dbg.attributes.TargetObjectRef; import ghidra.dbg.target.TargetObject;
import ghidra.dbg.util.HandlerMap; import ghidra.dbg.util.HandlerMap;
import ghidra.lifecycle.Internal; import ghidra.lifecycle.Internal;
import ghidra.util.Msg; import ghidra.util.Msg;
@ -1400,9 +1400,9 @@ public class DbgManagerImpl implements DbgManager {
return execute(new DbgSessionSelectCommand(this, session)); return execute(new DbgSessionSelectCommand(this, session));
} }
public CompletableFuture<Void> requestFocus(DbgModelTargetFocusScope<?> scope, public CompletableFuture<Void> requestFocus(DbgModelTargetFocusScope scope,
TargetObjectRef ref) { TargetObject obj) {
return execute(new DbgRequestFocusCommand(this, scope, ref)); return execute(new DbgRequestFocusCommand(this, scope, obj));
} }
@Override @Override

View file

@ -15,7 +15,7 @@
*/ */
package agent.dbgeng.manager.impl; package agent.dbgeng.manager.impl;
import static ghidra.async.AsyncUtils.*; import static ghidra.async.AsyncUtils.sequence;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.*; import java.util.*;
@ -32,7 +32,6 @@ import agent.dbgeng.manager.DbgManager.ExecSuffix;
import agent.dbgeng.manager.cmd.*; import agent.dbgeng.manager.cmd.*;
import ghidra.async.TypeSpec; import ghidra.async.TypeSpec;
import ghidra.comm.util.BitmaskSet; import ghidra.comm.util.BitmaskSet;
import ghidra.dbg.attributes.TypedTargetObjectRef;
import ghidra.dbg.target.TargetAttachable; import ghidra.dbg.target.TargetAttachable;
import ghidra.util.Msg; import ghidra.util.Msg;
@ -267,8 +266,7 @@ public class DbgProcessImpl implements DbgProcess {
} }
@Override @Override
public CompletableFuture<Set<DbgThread>> reattach( public CompletableFuture<Set<DbgThread>> reattach(TargetAttachable attachable) {
TypedTargetObjectRef<? extends TargetAttachable<?>> ref) {
return sequence(TypeSpec.cls(DbgThread.class).set()).then((seq) -> { return sequence(TypeSpec.cls(DbgThread.class).set()).then((seq) -> {
select().handle(seq::next); select().handle(seq::next);
}).then((seq) -> { }).then((seq) -> {

View file

@ -21,7 +21,7 @@ import agent.dbgeng.manager.DbgProcess;
import agent.dbgeng.manager.DbgThread; import agent.dbgeng.manager.DbgThread;
import agent.dbgeng.manager.impl.DbgManagerImpl; import agent.dbgeng.manager.impl.DbgManagerImpl;
import agent.dbgeng.model.iface2.*; import agent.dbgeng.model.iface2.*;
import ghidra.dbg.attributes.TargetObjectRef; import ghidra.dbg.target.TargetObject;
public interface DbgModelSelectableObject extends DbgModelTargetObject { public interface DbgModelSelectableObject extends DbgModelTargetObject {
@ -43,7 +43,7 @@ public interface DbgModelSelectableObject extends DbgModelTargetObject {
} }
if (this instanceof DbgModelTargetStackFrame) { if (this instanceof DbgModelTargetStackFrame) {
DbgModelTargetStackFrame tf = (DbgModelTargetStackFrame) this; DbgModelTargetStackFrame tf = (DbgModelTargetStackFrame) this;
TargetObjectRef ref = tf.getThread(); TargetObject ref = tf.getThread();
if (ref instanceof DbgModelTargetThread) { if (ref instanceof DbgModelTargetThread) {
DbgModelTargetThread tt = (DbgModelTargetThread) ref; DbgModelTargetThread tt = (DbgModelTargetThread) ref;
DbgThread thread = tt.getThread(); DbgThread thread = tt.getThread();

View file

@ -25,12 +25,12 @@ import ghidra.dbg.target.TargetAccessConditioned;
* *
* @param <T> type for this * @param <T> type for this
*/ */
public interface DbgModelTargetAccessConditioned<T extends TargetAccessConditioned<T>> public interface DbgModelTargetAccessConditioned
extends DbgModelTargetObject, TargetAccessConditioned<T> { extends DbgModelTargetObject, TargetAccessConditioned {
@Override @Override
public TargetAccessibility getAccessibility(); public boolean isAccessible();
public void setAccessibility(TargetAccessibility accessibility); public void setAccessible(boolean accessible);
} }

View file

@ -25,7 +25,6 @@ import ghidra.dbg.target.TargetAttachable;
* *
* @param <T> type for this * @param <T> type for this
*/ */
public interface DbgModelTargetAttachable<T extends TargetAttachable<T>> public interface DbgModelTargetAttachable extends DbgModelTargetObject, TargetAttachable {
extends DbgModelTargetObject, TargetAttachable<T> {
} }

View file

@ -15,9 +15,7 @@
*/ */
package agent.dbgeng.model.iface1; package agent.dbgeng.model.iface1;
import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
import agent.dbgeng.manager.DbgProcess; import agent.dbgeng.manager.DbgProcess;
import agent.dbgeng.manager.impl.DbgProcessImpl; import agent.dbgeng.manager.impl.DbgProcessImpl;
@ -25,10 +23,8 @@ import agent.dbgeng.model.iface2.DbgModelTargetAvailable;
import agent.dbgeng.model.iface2.DbgModelTargetObject; import agent.dbgeng.model.iface2.DbgModelTargetObject;
import ghidra.async.AsyncUtils; import ghidra.async.AsyncUtils;
import ghidra.async.TypeSpec; import ghidra.async.TypeSpec;
import ghidra.dbg.DebuggerObjectModel; import ghidra.dbg.target.TargetAttachable;
import ghidra.dbg.attributes.TargetObjectRef; import ghidra.dbg.target.TargetAttacher;
import ghidra.dbg.attributes.TypedTargetObjectRef;
import ghidra.dbg.target.*;
import ghidra.util.Msg; import ghidra.util.Msg;
/** /**
@ -38,25 +34,17 @@ import ghidra.util.Msg;
* *
* @param <T> type for this * @param <T> type for this
*/ */
public interface DbgModelTargetAttacher<T extends TargetAttacher<T>> public interface DbgModelTargetAttacher extends DbgModelTargetObject, TargetAttacher {
extends DbgModelTargetObject, TargetAttacher<T> {
@Override @Override
public default CompletableFuture<Void> attach( public default CompletableFuture<Void> attach(TargetAttachable attachable) {
TypedTargetObjectRef<? extends TargetAttachable<?>> ref) { DbgModelTargetAvailable available =
getModel().assertMine(TargetObjectRef.class, ref); getModel().assertMine(DbgModelTargetAvailable.class, attachable);
List<String> tPath = ref.getPath(); // TODO: This and the below new DbgProcessImpl seem to do the same thing
AtomicReference<DbgProcess> process = new AtomicReference<>(); // Both should be expressed the same way
AtomicReference<DbgModelTargetAvailable> attachable = new AtomicReference<>(); return getManager().addProcess().thenAccept(process -> {
return AsyncUtils.sequence(TypeSpec.VOID).then(seq -> { process.attach(available.getPid());
getModel().fetchModelObject(tPath).handle(seq::next); }).exceptionally((exc) -> {
}, TypeSpec.cls(TargetObject.class)).then((obj, seq) -> {
attachable.set((DbgModelTargetAvailable) DebuggerObjectModel.requireIface(
TargetAttachable.class, obj, tPath));
getManager().addProcess().handle(seq::next);
}, process).then(seq -> {
process.get().attach((int) attachable.get().getPid()).handle(seq::nextIgnore);
}).finish().exceptionally((exc) -> {
Msg.error(this, "attach failed"); Msg.error(this, "attach failed");
return null; return null;
}); });
@ -72,5 +60,4 @@ public interface DbgModelTargetAttacher<T extends TargetAttacher<T>>
return null; return null;
}); });
} }
} }

View file

@ -27,8 +27,7 @@ import ghidra.dbg.target.TargetDeletable;
* *
* @param <T> type for this * @param <T> type for this
*/ */
public interface DbgModelTargetDeletable<T extends TargetDeletable<T>> public interface DbgModelTargetDeletable extends DbgModelTargetObject, TargetDeletable {
extends DbgModelTargetObject, TargetDeletable<T> {
@Override @Override
public CompletableFuture<Void> delete(); public CompletableFuture<Void> delete();

View file

@ -28,8 +28,7 @@ import ghidra.dbg.target.TargetDetachable;
* *
* @param <T> type for this * @param <T> type for this
*/ */
public interface DbgModelTargetDetachable<T extends TargetDetachable<T>> public interface DbgModelTargetDetachable extends DbgModelTargetObject, TargetDetachable {
extends DbgModelTargetObject, TargetDetachable<T> {
@Override @Override
public default CompletableFuture<Void> detach() { public default CompletableFuture<Void> detach() {

View file

@ -18,8 +18,7 @@ package agent.dbgeng.model.iface1;
import agent.dbgeng.model.iface2.DbgModelTargetObject; import agent.dbgeng.model.iface2.DbgModelTargetObject;
import ghidra.dbg.target.TargetEnvironment; import ghidra.dbg.target.TargetEnvironment;
public interface DbgModelTargetEnvironment<T extends TargetEnvironment<T>> public interface DbgModelTargetEnvironment extends DbgModelTargetObject, TargetEnvironment {
extends DbgModelTargetObject, TargetEnvironment<T> {
public void refreshInternal(); public void refreshInternal();

View file

@ -23,7 +23,6 @@ import ghidra.dbg.target.TargetEventScope;
* *
* @param <T> type for this * @param <T> type for this
*/ */
public interface DbgModelTargetEventScope<T extends TargetEventScope<T>> public interface DbgModelTargetEventScope extends DbgModelTargetObject, TargetEventScope {
extends DbgModelTargetObject, TargetEventScope<T> {
} }

View file

@ -29,8 +29,8 @@ import ghidra.dbg.target.TargetExecutionStateful;
* *
* @param <T> type for this * @param <T> type for this
*/ */
public interface DbgModelTargetExecutionStateful<T extends TargetExecutionStateful<T>> public interface DbgModelTargetExecutionStateful
extends DbgModelTargetObject, TargetExecutionStateful<T> { extends DbgModelTargetObject, TargetExecutionStateful {
public default TargetExecutionState convertState(DbgState state) { public default TargetExecutionState convertState(DbgState state) {
switch (state) { switch (state) {

View file

@ -20,7 +20,6 @@ import java.util.concurrent.CompletableFuture;
import agent.dbgeng.model.iface2.DbgModelTargetObject; import agent.dbgeng.model.iface2.DbgModelTargetObject;
import ghidra.async.AsyncUtils; import ghidra.async.AsyncUtils;
import ghidra.dbg.agent.AbstractTargetObject; import ghidra.dbg.agent.AbstractTargetObject;
import ghidra.dbg.attributes.TargetObjectRef;
import ghidra.dbg.error.DebuggerIllegalArgumentException; import ghidra.dbg.error.DebuggerIllegalArgumentException;
import ghidra.dbg.target.TargetFocusScope; import ghidra.dbg.target.TargetFocusScope;
import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.TargetObject;
@ -33,8 +32,7 @@ import ghidra.dbg.util.PathUtils;
* *
* @param <T> type for this * @param <T> type for this
*/ */
public interface DbgModelTargetFocusScope<T extends TargetFocusScope<T>> public interface DbgModelTargetFocusScope extends DbgModelTargetObject, TargetFocusScope {
extends DbgModelTargetObject, TargetFocusScope<T> {
@Override @Override
public DbgModelSelectableObject getFocus(); public DbgModelSelectableObject getFocus();
@ -45,38 +43,36 @@ public interface DbgModelTargetFocusScope<T extends TargetFocusScope<T>>
// NB: requestFocus request change in active object - propagates down to manager // NB: requestFocus request change in active object - propagates down to manager
// (but, of course, may then cause change in state) // (but, of course, may then cause change in state)
@Override @Override
public default CompletableFuture<Void> requestFocus(TargetObjectRef ref) { public default CompletableFuture<Void> requestFocus(TargetObject obj) {
return getManager().requestFocus(this, ref); return getManager().requestFocus(this, obj);
} }
public default CompletableFuture<Void> doRequestFocus(TargetObjectRef ref) { public default CompletableFuture<Void> doRequestFocus(TargetObject obj) {
if (getManager().isWaiting()) { if (getManager().isWaiting()) {
return CompletableFuture.completedFuture(null); return CompletableFuture.completedFuture(null);
} }
getModel().assertMine(TargetObjectRef.class, ref); getModel().assertMine(TargetObject.class, obj);
if (ref.equals(getFocus())) { if (obj.equals(getFocus())) {
return CompletableFuture.completedFuture(null); return CompletableFuture.completedFuture(null);
} }
if (!PathUtils.isAncestor(this.getPath(), ref.getPath())) { if (!PathUtils.isAncestor(this.getPath(), obj.getPath())) {
throw new DebuggerIllegalArgumentException("Can only focus a successor of the scope"); throw new DebuggerIllegalArgumentException("Can only focus a successor of the scope");
} }
return ref.fetch().thenCompose(obj -> { TargetObject cur = obj;
TargetObject cur = obj; while (cur != null) {
while (cur != null) { if (cur instanceof DbgModelSelectableObject) {
if (cur instanceof DbgModelSelectableObject) { DbgModelSelectableObject sel = (DbgModelSelectableObject) cur;
DbgModelSelectableObject sel = (DbgModelSelectableObject) cur; setFocus(sel);
setFocus(sel); return sel.select();
return sel.select();
}
if (cur instanceof AbstractTargetObject) {
AbstractTargetObject<?> def = (AbstractTargetObject<?>) cur;
cur = def.getImplParent();
continue;
}
throw new AssertionError();
} }
return AsyncUtils.NIL; if (cur instanceof AbstractTargetObject) {
}); AbstractTargetObject<?> def = (AbstractTargetObject<?>) cur;
cur = def.getParent();
continue;
}
throw new AssertionError();
}
return AsyncUtils.NIL;
} }
} }

View file

@ -27,8 +27,7 @@ import ghidra.dbg.target.TargetInterpreter;
* *
* @param <T> type for this * @param <T> type for this
*/ */
public interface DbgModelTargetInterpreter<T extends TargetInterpreter<T>> public interface DbgModelTargetInterpreter extends DbgModelTargetObject, TargetInterpreter {
extends DbgModelTargetObject, TargetInterpreter<T> {
@Override @Override
public default CompletableFuture<Void> execute(String cmd) { public default CompletableFuture<Void> execute(String cmd) {

View file

@ -27,8 +27,7 @@ import ghidra.dbg.target.TargetInterruptible;
* *
* @param <T> type for this * @param <T> type for this
*/ */
public interface DbgModelTargetInterruptible<T extends TargetInterruptible<T>> public interface DbgModelTargetInterruptible extends DbgModelTargetObject, TargetInterruptible {
extends DbgModelTargetObject, TargetInterruptible<T> {
@Override @Override
public default CompletableFuture<Void> interrupt() { public default CompletableFuture<Void> interrupt() {

View file

@ -28,8 +28,7 @@ import ghidra.dbg.target.TargetKillable;
* *
* @param <T> type for this * @param <T> type for this
*/ */
public interface DbgModelTargetKillable<T extends TargetKillable<T>> public interface DbgModelTargetKillable extends DbgModelTargetObject, TargetKillable {
extends DbgModelTargetObject, TargetKillable<T> {
@Override @Override
public default CompletableFuture<Void> kill() { public default CompletableFuture<Void> kill() {

View file

@ -32,8 +32,7 @@ import ghidra.dbg.target.TargetLauncher.TargetCmdLineLauncher;
* *
* @param <T> type for this * @param <T> type for this
*/ */
public interface DbgModelTargetLauncher<T extends TargetCmdLineLauncher<T>> public interface DbgModelTargetLauncher extends DbgModelTargetObject, TargetCmdLineLauncher {
extends DbgModelTargetObject, TargetCmdLineLauncher<T> {
@Override @Override
public default CompletableFuture<Void> launch(List<String> args) { public default CompletableFuture<Void> launch(List<String> args) {

View file

@ -23,7 +23,6 @@ import ghidra.dbg.target.TargetMethod;
* *
* @param <T> type for this * @param <T> type for this
*/ */
public interface DbgModelTargetMethod<T extends TargetMethod<T>> public interface DbgModelTargetMethod extends DbgModelTargetObject, TargetMethod {
extends DbgModelTargetObject, TargetMethod<T> {
} }

View file

@ -28,8 +28,7 @@ import ghidra.dbg.target.TargetResumable;
* *
* @param <T> type for this * @param <T> type for this
*/ */
public interface DbgModelTargetResumable<T extends TargetResumable<T>> public interface DbgModelTargetResumable extends DbgModelTargetObject, TargetResumable {
extends DbgModelTargetObject, TargetResumable<T> {
@Override @Override
public default CompletableFuture<Void> resume() { public default CompletableFuture<Void> resume() {

View file

@ -30,8 +30,7 @@ import ghidra.dbg.target.TargetSteppable;
* *
* @param <T> type for this * @param <T> type for this
*/ */
public interface DbgModelTargetSteppable<T extends TargetSteppable<T>> public interface DbgModelTargetSteppable extends DbgModelTargetObject, TargetSteppable {
extends DbgModelTargetObject, TargetSteppable<T> {
default ExecSuffix convertToDbg(TargetStepKind kind) { default ExecSuffix convertToDbg(TargetStepKind kind) {
switch (kind) { switch (kind) {
@ -77,6 +76,7 @@ public interface DbgModelTargetSteppable<T extends TargetSteppable<T>>
} }
} }
@Override
default CompletableFuture<Void> step(Map<String, ?> args) { default CompletableFuture<Void> step(Map<String, ?> args) {
DbgThread thread = getManager().getCurrentThread(); DbgThread thread = getManager().getCurrentThread();
return thread.step(args); return thread.step(args);

View file

@ -17,8 +17,7 @@ package agent.dbgeng.model.iface2;
import ghidra.dbg.target.TargetAttachable; import ghidra.dbg.target.TargetAttachable;
public interface DbgModelTargetAvailable public interface DbgModelTargetAvailable extends DbgModelTargetObject, TargetAttachable {
extends DbgModelTargetObject, TargetAttachable<DbgModelTargetAvailable> {
public long getPid(); public long getPid();

View file

@ -27,11 +27,15 @@ import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointKind;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
import ghidra.program.model.address.AddressRange; import ghidra.program.model.address.AddressRange;
@TargetObjectSchemaInfo(name = "BreakpointContainer", elements = { @TargetObjectSchemaInfo(
@TargetElementType(type = DbgModelTargetBreakpointSpec.class) }, attributes = { name = "BreakpointContainer",
@TargetAttributeType(type = Void.class) }, canonicalContainer = true) elements = {
public interface DbgModelTargetBreakpointContainer extends DbgModelTargetObject, @TargetElementType(type = DbgModelTargetBreakpointSpec.class) },
TargetBreakpointContainer<DbgModelTargetBreakpointContainer>, DbgEventsListenerAdapter { attributes = {
@TargetAttributeType(type = Void.class) },
canonicalContainer = true)
public interface DbgModelTargetBreakpointContainer
extends DbgModelTargetObject, TargetBreakpointContainer, DbgEventsListenerAdapter {
/* /*
@Override @Override

View file

@ -15,17 +15,17 @@
*/ */
package agent.dbgeng.model.iface2; package agent.dbgeng.model.iface2;
import ghidra.dbg.attributes.TargetObjectRefList; import ghidra.dbg.attributes.TargetObjectList;
import ghidra.dbg.target.TargetBreakpointLocation; import ghidra.dbg.target.TargetBreakpointLocation;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
public interface DbgModelTargetBreakpointLocation public interface DbgModelTargetBreakpointLocation
extends DbgModelTargetObject, TargetBreakpointLocation<DbgModelTargetBreakpointLocation> { extends DbgModelTargetObject, TargetBreakpointLocation {
@Override @Override
public Address getAddress(); public Address getAddress();
@Override @Override
public TargetObjectRefList<?> getAffects(); public TargetObjectList<?> getAffects();
} }

View file

@ -21,16 +21,16 @@ import java.util.concurrent.CompletableFuture;
import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo; import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo;
import agent.dbgeng.model.iface1.DbgModelTargetBptHelper; import agent.dbgeng.model.iface1.DbgModelTargetBptHelper;
import ghidra.dbg.attributes.TargetObjectRefList; import ghidra.dbg.attributes.TargetObjectList;
import ghidra.dbg.target.*; import ghidra.dbg.target.*;
import ghidra.dbg.target.TargetBreakpointContainer.TargetBreakpointKindSet; import ghidra.dbg.target.TargetBreakpointContainer.TargetBreakpointKindSet;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
public interface DbgModelTargetBreakpointSpec extends // public interface DbgModelTargetBreakpointSpec extends //
DbgModelTargetObject, // DbgModelTargetObject, //
TargetBreakpointSpec<DbgModelTargetBreakpointSpec>, // TargetBreakpointSpec, //
TargetBreakpointLocation<DbgModelTargetBreakpointSpec>, // TargetBreakpointLocation, //
TargetDeletable<DbgModelTargetBreakpointSpec>, // TargetDeletable, //
DbgModelTargetBptHelper { DbgModelTargetBptHelper {
String BPT_ACCESS_ATTRIBUTE_NAME = "Access"; String BPT_ACCESS_ATTRIBUTE_NAME = "Access";
@ -129,9 +129,9 @@ public interface DbgModelTargetBreakpointSpec extends //
return getModel().getAddress("ram", info.addrAsLong()); return getModel().getAddress("ram", info.addrAsLong());
} }
public default TargetObjectRefList<?> doGetAffects() { public default TargetObjectList<?> doGetAffects() {
DbgModelTargetProcess process = getParentProcess(); DbgModelTargetProcess process = getParentProcess();
return TargetObjectRefList.of(process); return TargetObjectList.of(process);
} }
public default void updateInfo(DbgBreakpointInfo oldInfo, DbgBreakpointInfo newInfo, public default void updateInfo(DbgBreakpointInfo oldInfo, DbgBreakpointInfo newInfo,

View file

@ -23,7 +23,7 @@ import ghidra.dbg.target.TargetLauncher;
import ghidra.dbg.target.TargetMethod.TargetParameterMap; import ghidra.dbg.target.TargetMethod.TargetParameterMap;
public interface DbgModelTargetConnector public interface DbgModelTargetConnector
extends DbgModelSelectableObject, TargetLauncher<DbgModelTargetConnector> { extends DbgModelSelectableObject, TargetLauncher {
@Override @Override
public default String getDisplay() { public default String getDisplay() {

View file

@ -17,8 +17,7 @@ package agent.dbgeng.model.iface2;
import ghidra.dbg.target.TargetEnvironment; import ghidra.dbg.target.TargetEnvironment;
public interface DbgModelTargetEnvironmentEx public interface DbgModelTargetEnvironmentEx extends DbgModelTargetObject, TargetEnvironment {
extends DbgModelTargetObject, TargetEnvironment<DbgModelTargetEnvironmentEx> {
public void refreshInternal(); public void refreshInternal();

View file

@ -21,8 +21,7 @@ import agent.dbgeng.manager.DbgModuleMemory;
import ghidra.dbg.target.TargetMemory; import ghidra.dbg.target.TargetMemory;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
public interface DbgModelTargetMemoryContainer public interface DbgModelTargetMemoryContainer extends DbgModelTargetObject, TargetMemory {
extends DbgModelTargetObject, TargetMemory<DbgModelTargetMemoryContainer> {
public DbgModelTargetMemoryRegion getTargetMemory(DbgModuleMemory region); public DbgModelTargetMemoryRegion getTargetMemory(DbgModuleMemory region);

View file

@ -18,8 +18,7 @@ package agent.dbgeng.model.iface2;
import ghidra.dbg.target.TargetMemoryRegion; import ghidra.dbg.target.TargetMemoryRegion;
import ghidra.program.model.address.AddressRange; import ghidra.program.model.address.AddressRange;
public interface DbgModelTargetMemoryRegion public interface DbgModelTargetMemoryRegion extends DbgModelTargetObject, TargetMemoryRegion {
extends DbgModelTargetObject, TargetMemoryRegion<DbgModelTargetMemoryRegion> {
@Override @Override
public AddressRange getRange(); public AddressRange getRange();

View file

@ -23,9 +23,7 @@ import ghidra.dbg.target.TargetModule;
import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.TargetObject;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
public interface DbgModelTargetModule extends // public interface DbgModelTargetModule extends DbgModelTargetObject, TargetModule {
DbgModelTargetObject, //
TargetModule<DbgModelTargetModule> {
DbgModule getDbgModule(); DbgModule getDbgModule();

View file

@ -21,13 +21,11 @@ import agent.dbgeng.model.iface1.DbgModelTargetEventScope;
import ghidra.dbg.target.TargetModule; import ghidra.dbg.target.TargetModule;
import ghidra.dbg.target.TargetModuleContainer; import ghidra.dbg.target.TargetModuleContainer;
public interface DbgModelTargetModuleContainer extends // public interface DbgModelTargetModuleContainer
//DbgModelTargetObject, extends /*DbgModelTargetObject,*/ DbgModelTargetEventScope, TargetModuleContainer {
DbgModelTargetEventScope<DbgModelTargetModuleContainer>, //
TargetModuleContainer<DbgModelTargetModuleContainer> {
@Override @Override
public CompletableFuture<? extends TargetModule<?>> addSyntheticModule(String name); public CompletableFuture<? extends TargetModule> addSyntheticModule(String name);
public CompletableFuture<DbgModelTargetModule> getTargetModule(String name); public CompletableFuture<DbgModelTargetModule> getTargetModule(String name);

View file

@ -18,8 +18,7 @@ package agent.dbgeng.model.iface2;
import ghidra.dbg.target.TargetSection; import ghidra.dbg.target.TargetSection;
import ghidra.program.model.address.AddressRange; import ghidra.program.model.address.AddressRange;
public interface DbgModelTargetModuleSection public interface DbgModelTargetModuleSection extends DbgModelTargetObject, TargetSection {
extends DbgModelTargetObject, TargetSection<DbgModelTargetModuleSection> {
@Override @Override
public AddressRange getRange(); public AddressRange getRange();

View file

@ -25,7 +25,6 @@ import agent.dbgeng.model.AbstractDbgModel;
import ghidra.dbg.agent.InvalidatableTargetObjectIf; import ghidra.dbg.agent.InvalidatableTargetObjectIf;
import ghidra.dbg.agent.SpiTargetObject; import ghidra.dbg.agent.SpiTargetObject;
import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.TargetObject.TargetObjectListener;
import ghidra.dbg.util.CollectionUtils.Delta; import ghidra.dbg.util.CollectionUtils.Delta;
import ghidra.util.datastruct.ListenerSet; import ghidra.util.datastruct.ListenerSet;
@ -61,8 +60,6 @@ public interface DbgModelTargetObject extends SpiTargetObject, InvalidatableTarg
@Override @Override
public CompletableFuture<? extends Map<String, ?>> fetchAttributes(); public CompletableFuture<? extends Map<String, ?>> fetchAttributes();
public TargetObject getImplParent();
public Delta<?, ?> changeAttributes(List<String> remove, Map<String, ?> add, String reason); public Delta<?, ?> changeAttributes(List<String> remove, Map<String, ?> add, String reason);
public CompletableFuture<? extends Map<String, ?>> requestNativeAttributes(); public CompletableFuture<? extends Map<String, ?>> requestNativeAttributes();

View file

@ -29,18 +29,18 @@ import ghidra.dbg.util.PathUtils;
public interface DbgModelTargetProcess extends // public interface DbgModelTargetProcess extends //
TargetAggregate, // TargetAggregate, //
TargetProcess<DbgModelTargetProcess>, // TargetProcess, //
DbgModelTargetExecutionStateful<DbgModelTargetProcess>, // DbgModelTargetExecutionStateful, //
DbgModelTargetAccessConditioned<DbgModelTargetProcess>, // DbgModelTargetAccessConditioned, //
DbgModelTargetAttacher<DbgModelTargetProcess>, // DbgModelTargetAttacher, //
DbgModelTargetAttachable<DbgModelTargetProcess>, // DbgModelTargetAttachable, //
DbgModelTargetLauncher<DbgModelTargetProcess>, // DbgModelTargetLauncher, //
DbgModelTargetDeletable<DbgModelTargetProcess>, // DbgModelTargetDeletable, //
DbgModelTargetDetachable<DbgModelTargetProcess>, // DbgModelTargetDetachable, //
DbgModelTargetKillable<DbgModelTargetProcess>, // DbgModelTargetKillable, //
DbgModelTargetResumable<DbgModelTargetProcess>, // DbgModelTargetResumable, //
DbgModelTargetSteppable<DbgModelTargetProcess>, // DbgModelTargetSteppable, //
DbgModelTargetInterruptible<DbgModelTargetProcess>, // DbgModelTargetInterruptible, //
DbgEventsListenerAdapter, // DbgEventsListenerAdapter, //
DbgModelSelectableObject { DbgModelSelectableObject {

View file

@ -22,7 +22,7 @@ import agent.dbgeng.model.iface1.DbgModelTargetEventScope;
public interface DbgModelTargetProcessContainer extends // public interface DbgModelTargetProcessContainer extends //
//DbgModelTargetObject, //DbgModelTargetObject,
DbgModelTargetEventScope<DbgModelTargetProcessContainer>, // DbgModelTargetEventScope, //
DbgEventsListenerAdapter { DbgEventsListenerAdapter {
public DbgModelTargetProcess getTargetProcess(DebugProcessId id); public DbgModelTargetProcess getTargetProcess(DebugProcessId id);

View file

@ -18,8 +18,7 @@ package agent.dbgeng.model.iface2;
import agent.dbgeng.manager.impl.DbgRegister; import agent.dbgeng.manager.impl.DbgRegister;
import ghidra.dbg.target.TargetRegister; import ghidra.dbg.target.TargetRegister;
public interface DbgModelTargetRegister public interface DbgModelTargetRegister extends DbgModelTargetObject, TargetRegister {
extends DbgModelTargetObject, TargetRegister<DbgModelTargetRegister> {
@Override @Override
public int getBitLength(); public int getBitLength();

View file

@ -30,8 +30,7 @@ import ghidra.dbg.util.ConversionUtils;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.datastruct.ListenerSet; import ghidra.util.datastruct.ListenerSet;
public interface DbgModelTargetRegisterBank public interface DbgModelTargetRegisterBank extends DbgModelTargetObject, TargetRegisterBank {
extends DbgModelTargetObject, TargetRegisterBank<DbgModelTargetRegisterBank> {
public DbgModelTargetRegister getTargetRegister(DbgRegister register); public DbgModelTargetRegister getTargetRegister(DbgRegister register);

View file

@ -19,7 +19,7 @@ import agent.dbgeng.manager.impl.DbgRegister;
import ghidra.dbg.target.TargetRegisterContainer; import ghidra.dbg.target.TargetRegisterContainer;
public interface DbgModelTargetRegisterContainer public interface DbgModelTargetRegisterContainer
extends DbgModelTargetObject, TargetRegisterContainer<DbgModelTargetRegisterContainer> { extends DbgModelTargetObject, TargetRegisterContainer {
public DbgModelTargetRegister getTargetRegister(DbgRegister register); public DbgModelTargetRegister getTargetRegister(DbgRegister register);

View file

@ -19,9 +19,8 @@ import agent.dbgeng.manager.impl.DbgRegister;
import ghidra.dbg.target.TargetRegisterBank; import ghidra.dbg.target.TargetRegisterBank;
import ghidra.dbg.target.TargetRegisterContainer; import ghidra.dbg.target.TargetRegisterContainer;
public interface DbgModelTargetRegisterContainerAndBank extends DbgModelTargetObject, // public interface DbgModelTargetRegisterContainerAndBank
TargetRegisterContainer<DbgModelTargetRegisterContainerAndBank>, // extends DbgModelTargetObject, TargetRegisterContainer, TargetRegisterBank {
TargetRegisterBank<DbgModelTargetRegisterContainerAndBank> {
public DbgModelTargetRegister getTargetRegister(DbgRegister register); public DbgModelTargetRegister getTargetRegister(DbgRegister register);

View file

@ -20,11 +20,11 @@ import agent.dbgeng.model.iface1.*;
public interface DbgModelTargetRoot extends // public interface DbgModelTargetRoot extends //
///DbgModelTargetObject, ///DbgModelTargetObject,
DbgModelTargetAccessConditioned<DbgModelTargetRoot>, // DbgModelTargetAccessConditioned, //
DbgModelTargetAttacher<DbgModelTargetRoot>, // DbgModelTargetAttacher, //
DbgModelTargetEventScope<DbgModelTargetRoot>, // DbgModelTargetEventScope, //
DbgModelTargetLauncher<DbgModelTargetRoot>, // DbgModelTargetLauncher, //
DbgModelTargetFocusScope<DbgModelTargetRoot>, // DbgModelTargetFocusScope, //
DbgEventsListenerAdapter { DbgEventsListenerAdapter {
void setDefaultConnector(DbgModelTargetConnector defaultConnector); void setDefaultConnector(DbgModelTargetConnector defaultConnector);

View file

@ -30,12 +30,12 @@ import ghidra.dbg.target.TargetFocusScope.TargetFocusScopeListener;
import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils;
public interface DbgModelTargetSession extends // public interface DbgModelTargetSession extends //
DbgModelTargetAccessConditioned<DbgModelTargetSession>, // DbgModelTargetAccessConditioned, //
//DbgModelTargetFocusScope<DbgModelTargetSession>, // //DbgModelTargetFocusScope, //
DbgModelTargetExecutionStateful<DbgModelTargetSession>, // DbgModelTargetExecutionStateful, //
DbgModelTargetInterpreter<DbgModelTargetSession>, // DbgModelTargetInterpreter, //
DbgModelTargetInterruptible<DbgModelTargetSession>, // DbgModelTargetInterruptible, //
DbgModelTargetResumable<DbgModelTargetSession>, // DbgModelTargetResumable, //
DbgEventsListenerAdapter, // DbgEventsListenerAdapter, //
DbgModelSelectableObject, // DbgModelSelectableObject, //
TargetFocusScopeListener, // TargetFocusScopeListener, //

View file

@ -20,7 +20,7 @@ import agent.dbgeng.model.iface1.DbgModelTargetEnvironment;
public interface DbgModelTargetSessionAttributes extends public interface DbgModelTargetSessionAttributes extends
//DbgModelTargetObject, //DbgModelTargetObject,
DbgModelTargetEnvironment<DbgModelTargetSessionAttributes>, // DbgModelTargetEnvironment, //
DbgEventsListenerAdapter { DbgEventsListenerAdapter {
} }

View file

@ -19,7 +19,7 @@ import agent.dbgeng.manager.DbgStackFrame;
import ghidra.dbg.target.TargetStack; import ghidra.dbg.target.TargetStack;
public interface DbgModelTargetStack public interface DbgModelTargetStack
extends DbgModelTargetObject, TargetStack<DbgModelTargetStack> { extends DbgModelTargetObject, TargetStack {
public DbgModelTargetStackFrame getTargetFrame(DbgStackFrame frame); public DbgModelTargetStackFrame getTargetFrame(DbgStackFrame frame);

View file

@ -23,7 +23,6 @@ import agent.dbgeng.manager.DbgStackFrame;
import agent.dbgeng.manager.impl.DbgManagerImpl; import agent.dbgeng.manager.impl.DbgManagerImpl;
import agent.dbgeng.manager.impl.DbgThreadImpl; import agent.dbgeng.manager.impl.DbgThreadImpl;
import agent.dbgeng.model.iface1.DbgModelSelectableObject; import agent.dbgeng.model.iface1.DbgModelSelectableObject;
import ghidra.dbg.attributes.TargetObjectRef;
import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.TargetStackFrame; import ghidra.dbg.target.TargetStackFrame;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
@ -31,7 +30,7 @@ import ghidra.program.model.address.AddressSpace;
public interface DbgModelTargetStackFrame extends // public interface DbgModelTargetStackFrame extends //
//DbgModelTargetObject, //DbgModelTargetObject,
TargetStackFrame<DbgModelTargetStackFrame>, // TargetStackFrame, //
DbgEventsListenerAdapter, // DbgEventsListenerAdapter, //
DbgModelSelectableObject { DbgModelSelectableObject {
@ -90,7 +89,7 @@ public interface DbgModelTargetStackFrame extends //
public void setFrame(DbgStackFrame frame); public void setFrame(DbgStackFrame frame);
public TargetObjectRef getThread(); public TargetObject getThread();
public Address getPC(); public Address getPC();

View file

@ -18,8 +18,7 @@ package agent.dbgeng.model.iface2;
import ghidra.dbg.target.TargetSymbol; import ghidra.dbg.target.TargetSymbol;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
public interface DbgModelTargetSymbol public interface DbgModelTargetSymbol extends DbgModelTargetObject, TargetSymbol {
extends DbgModelTargetObject, TargetSymbol<DbgModelTargetSymbol> {
@Override @Override
public boolean isConstant(); public boolean isConstant();

View file

@ -19,8 +19,7 @@ import agent.dbgeng.manager.impl.DbgMinimalSymbol;
import agent.dbgeng.model.impl.DbgModelTargetSymbolImpl; import agent.dbgeng.model.impl.DbgModelTargetSymbolImpl;
import ghidra.dbg.target.TargetSymbolNamespace; import ghidra.dbg.target.TargetSymbolNamespace;
public interface DbgModelTargetSymbolContainer public interface DbgModelTargetSymbolContainer extends DbgModelTargetObject, TargetSymbolNamespace {
extends DbgModelTargetObject, TargetSymbolNamespace<DbgModelTargetSymbolContainer> {
public DbgModelTargetSymbolImpl getTargetSymbol(DbgMinimalSymbol symbol); public DbgModelTargetSymbolImpl getTargetSymbol(DbgMinimalSymbol symbol);

View file

@ -28,10 +28,10 @@ import ghidra.dbg.target.TargetThread;
import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils;
public interface DbgModelTargetThread extends // public interface DbgModelTargetThread extends //
TargetThread<DbgModelTargetThread>, // TargetThread, //
DbgModelTargetAccessConditioned<DbgModelTargetThread>, // DbgModelTargetAccessConditioned, //
DbgModelTargetExecutionStateful<DbgModelTargetThread>, // DbgModelTargetExecutionStateful, //
DbgModelTargetSteppable<DbgModelTargetThread>, // DbgModelTargetSteppable, //
DbgEventsListenerAdapter, // DbgEventsListenerAdapter, //
DbgModelSelectableObject { DbgModelSelectableObject {

View file

@ -22,7 +22,7 @@ import agent.dbgeng.model.iface1.DbgModelTargetEventScope;
public interface DbgModelTargetThreadContainer extends // public interface DbgModelTargetThreadContainer extends //
//DbgModelTargetObject, //DbgModelTargetObject,
DbgModelTargetEventScope<DbgModelTargetThreadContainer>, // DbgModelTargetEventScope, //
DbgEventsListenerAdapter { DbgEventsListenerAdapter {
public void threadCreated(DbgThread thread); public void threadCreated(DbgThread thread);

View file

@ -29,17 +29,20 @@ import agent.dbgeng.manager.impl.DbgManagerImpl;
import agent.dbgeng.model.iface2.*; import agent.dbgeng.model.iface2.*;
import ghidra.dbg.error.DebuggerMemoryAccessException; import ghidra.dbg.error.DebuggerMemoryAccessException;
import ghidra.dbg.error.DebuggerModelAccessException; import ghidra.dbg.error.DebuggerModelAccessException;
import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibility;
import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.util.datastruct.WeakValueHashMap; import ghidra.util.datastruct.WeakValueHashMap;
@TargetObjectSchemaInfo(name = "Memory", elements = { // @TargetObjectSchemaInfo(
@TargetElementType(type = DbgModelTargetMemoryRegionImpl.class) // name = "Memory",
}, attributes = { // elements = {
@TargetAttributeType(type = Void.class) // @TargetElementType(type = DbgModelTargetMemoryRegionImpl.class)
}, canonicalContainer = true) },
attributes = {
@TargetAttributeType(type = Void.class)
},
canonicalContainer = true)
public class DbgModelTargetMemoryContainerImpl extends DbgModelTargetObjectImpl public class DbgModelTargetMemoryContainerImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetMemoryContainer { implements DbgModelTargetMemoryContainer {
@ -256,12 +259,11 @@ public class DbgModelTargetMemoryContainerImpl extends DbgModelTargetObjectImpl
@Override @Override
public void onRunning() { public void onRunning() {
invalidateMemoryCaches(); invalidateMemoryCaches();
setAccessibility(TargetAccessibility.INACCESSIBLE); setAccessible(false);
} }
@Override @Override
protected void update() { protected void update() {
requestElements(true); requestElements(true);
} }
} }

View file

@ -30,11 +30,15 @@ import ghidra.dbg.target.schema.*;
import ghidra.lifecycle.Internal; import ghidra.lifecycle.Internal;
import ghidra.util.Msg; import ghidra.util.Msg;
@TargetObjectSchemaInfo(name = "ModuleContainer", elements = { // @TargetObjectSchemaInfo(
@TargetElementType(type = DbgModelTargetModuleImpl.class) // name = "ModuleContainer",
}, attributes = { // elements = { //
@TargetAttributeType(type = Void.class) // @TargetElementType(type = DbgModelTargetModuleImpl.class) //
}, canonicalContainer = true) },
attributes = { //
@TargetAttributeType(type = Void.class) //
},
canonicalContainer = true)
public class DbgModelTargetModuleContainerImpl extends DbgModelTargetObjectImpl public class DbgModelTargetModuleContainerImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetModuleContainer { implements DbgModelTargetModuleContainer {
// NOTE: -file-list-shared-libraries omits the main module and system-supplied DSO. // NOTE: -file-list-shared-libraries omits the main module and system-supplied DSO.
@ -97,7 +101,7 @@ public class DbgModelTargetModuleContainerImpl extends DbgModelTargetObjectImpl
} }
@Override @Override
public CompletableFuture<? extends TargetModule<?>> addSyntheticModule(String name) { public CompletableFuture<? extends TargetModule> addSyntheticModule(String name) {
throw new UnsupportedOperationException("Dbgeng Does not support synthetic modules"); throw new UnsupportedOperationException("Dbgeng Does not support synthetic modules");
} }

View file

@ -23,11 +23,14 @@ import agent.dbgeng.model.iface2.DbgModelTargetModuleSection;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
@TargetObjectSchemaInfo(name = "Section", elements = { // @TargetObjectSchemaInfo(
@TargetElementType(type = Void.class) // name = "Section",
}, attributes = { // elements = { //
@TargetAttributeType(type = Void.class) // @TargetElementType(type = Void.class) //
}) },
attributes = { //
@TargetAttributeType(type = Void.class) //
})
public class DbgModelTargetModuleSectionImpl extends DbgModelTargetObjectImpl public class DbgModelTargetModuleSectionImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetModuleSection { implements DbgModelTargetModuleSection {
protected static final String OBJFILE_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "objfile"; protected static final String OBJFILE_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "objfile";
@ -45,7 +48,7 @@ public class DbgModelTargetModuleSectionImpl extends DbgModelTargetObjectImpl
range = new AddressRangeImpl(min, max); range = new AddressRangeImpl(min, max);
changeAttributes(List.of(), List.of(), Map.of( // changeAttributes(List.of(), List.of(), Map.of( //
MODULE_ATTRIBUTE_NAME, sections.getImplParent(), // MODULE_ATTRIBUTE_NAME, sections.getParent(), //
RANGE_ATTRIBUTE_NAME, range, // RANGE_ATTRIBUTE_NAME, range, //
DISPLAY_ATTRIBUTE_NAME, section.getName(), // DISPLAY_ATTRIBUTE_NAME, section.getName(), //
UPDATE_MODE_ATTRIBUTE_NAME, TargetUpdateMode.FIXED // UPDATE_MODE_ATTRIBUTE_NAME, TargetUpdateMode.FIXED //

View file

@ -26,7 +26,6 @@ import agent.dbgeng.model.iface1.DbgModelTargetExecutionStateful;
import agent.dbgeng.model.iface2.*; import agent.dbgeng.model.iface2.*;
import ghidra.dbg.agent.DefaultTargetObject; import ghidra.dbg.agent.DefaultTargetObject;
import ghidra.dbg.target.*; import ghidra.dbg.target.*;
import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibility;
import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibilityListener; import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibilityListener;
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState; import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
import ghidra.dbg.target.schema.TargetObjectSchema; import ghidra.dbg.target.schema.TargetObjectSchema;
@ -34,7 +33,7 @@ import ghidra.dbg.target.schema.TargetObjectSchema;
public class DbgModelTargetObjectImpl extends DefaultTargetObject<TargetObject, TargetObject> public class DbgModelTargetObjectImpl extends DefaultTargetObject<TargetObject, TargetObject>
implements DbgModelTargetObject { implements DbgModelTargetObject {
protected TargetAccessibility accessibility = TargetAccessibility.ACCESSIBLE; protected boolean accessible = true;
protected final DbgStateListener accessListener = this::checkExited; protected final DbgStateListener accessListener = this::checkExited;
private boolean modified; private boolean modified;
@ -61,22 +60,21 @@ public class DbgModelTargetObjectImpl extends DefaultTargetObject<TargetObject,
getManager().removeStateListener(accessListener); getManager().removeStateListener(accessListener);
} }
public void setAccessibility(TargetAccessibility accessibility) { public void setAccessible(boolean accessible) {
synchronized (attributes) { synchronized (attributes) {
if (this.accessibility == accessibility) { if (this.accessible == accessible) {
return; return;
} }
this.accessibility = accessibility; this.accessible = accessible;
} }
if (this instanceof DbgModelTargetAccessConditioned<?>) { if (this instanceof DbgModelTargetAccessConditioned) {
changeAttributes(List.of(), List.of(), Map.of( // changeAttributes(List.of(), List.of(), Map.of( //
TargetAccessConditioned.ACCESSIBLE_ATTRIBUTE_NAME, TargetAccessConditioned.ACCESSIBLE_ATTRIBUTE_NAME, accessible //
accessibility == TargetAccessibility.ACCESSIBLE //
), "Accessibility changed"); ), "Accessibility changed");
DbgModelTargetAccessConditioned<?> accessConditioned = DbgModelTargetAccessConditioned accessConditioned =
(DbgModelTargetAccessConditioned<?>) this; (DbgModelTargetAccessConditioned) this;
listeners.fire(TargetAccessibilityListener.class) listeners.fire(TargetAccessibilityListener.class)
.accessibilityChanged(accessConditioned, accessibility); .accessibilityChanged(accessConditioned, accessible);
} }
} }
@ -86,16 +84,16 @@ public class DbgModelTargetObjectImpl extends DefaultTargetObject<TargetObject,
} }
public void onRunning() { public void onRunning() {
setAccessibility(TargetAccessibility.INACCESSIBLE); setAccessible(false);
} }
public void onStopped() { public void onStopped() {
setAccessibility(TargetAccessibility.ACCESSIBLE); setAccessible(true);
update(); update();
} }
public void onExit() { public void onExit() {
setAccessibility(TargetAccessibility.ACCESSIBLE); setAccessible(true);
} }
protected void update() { protected void update() {
@ -139,7 +137,7 @@ public class DbgModelTargetObjectImpl extends DefaultTargetObject<TargetObject,
} }
} }
if (this instanceof DbgModelTargetExecutionStateful) { if (this instanceof DbgModelTargetExecutionStateful) {
DbgModelTargetExecutionStateful<?> stateful = (DbgModelTargetExecutionStateful<?>) this; DbgModelTargetExecutionStateful stateful = (DbgModelTargetExecutionStateful) this;
stateful.setExecutionState(exec, "Refreshed"); stateful.setExecutionState(exec, "Refreshed");
} }
} }
@ -153,7 +151,7 @@ public class DbgModelTargetObjectImpl extends DefaultTargetObject<TargetObject,
public DbgModelTargetSession getParentSession() { public DbgModelTargetSession getParentSession() {
DbgModelTargetObject test = (DbgModelTargetObject) parent; DbgModelTargetObject test = (DbgModelTargetObject) parent;
while (test != null && !(test instanceof DbgModelTargetSession)) { while (test != null && !(test instanceof DbgModelTargetSession)) {
test = (DbgModelTargetObject) test.getImplParent(); test = (DbgModelTargetObject) test.getParent();
} }
return test == null ? null : (DbgModelTargetSession) test; return test == null ? null : (DbgModelTargetSession) test;
} }
@ -162,7 +160,7 @@ public class DbgModelTargetObjectImpl extends DefaultTargetObject<TargetObject,
public DbgModelTargetProcess getParentProcess() { public DbgModelTargetProcess getParentProcess() {
DbgModelTargetObject test = (DbgModelTargetObject) parent; DbgModelTargetObject test = (DbgModelTargetObject) parent;
while (test != null && !(test instanceof TargetProcess)) { while (test != null && !(test instanceof TargetProcess)) {
test = (DbgModelTargetObject) test.getImplParent(); test = (DbgModelTargetObject) test.getParent();
} }
return test == null ? null : (DbgModelTargetProcess) test; return test == null ? null : (DbgModelTargetProcess) test;
} }
@ -171,7 +169,7 @@ public class DbgModelTargetObjectImpl extends DefaultTargetObject<TargetObject,
public DbgModelTargetThread getParentThread() { public DbgModelTargetThread getParentThread() {
DbgModelTargetObject test = (DbgModelTargetObject) parent; DbgModelTargetObject test = (DbgModelTargetObject) parent;
while (test != null && !(test instanceof TargetThread)) { while (test != null && !(test instanceof TargetThread)) {
test = (DbgModelTargetObject) test.getImplParent(); test = (DbgModelTargetObject) test.getParent();
} }
return test == null ? null : (DbgModelTargetThread) test; return test == null ? null : (DbgModelTargetThread) test;
} }

View file

@ -23,16 +23,19 @@ import java.util.stream.Collectors;
import agent.dbgeng.dbgeng.*; import agent.dbgeng.dbgeng.*;
import agent.dbgeng.manager.*; import agent.dbgeng.manager.*;
import agent.dbgeng.model.iface2.*; import agent.dbgeng.model.iface2.*;
import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibility;
import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
import ghidra.util.datastruct.WeakValueHashMap; import ghidra.util.datastruct.WeakValueHashMap;
@TargetObjectSchemaInfo(name = "ProcessContainer", elements = { // @TargetObjectSchemaInfo(
@TargetElementType(type = DbgModelTargetProcessImpl.class) // name = "ProcessContainer",
}, attributes = { // elements = { //
@TargetAttributeType(type = Void.class) // @TargetElementType(type = DbgModelTargetProcessImpl.class) //
}, canonicalContainer = true) },
attributes = { //
@TargetAttributeType(type = Void.class) //
},
canonicalContainer = true)
public class DbgModelTargetProcessContainerImpl extends DbgModelTargetObjectImpl public class DbgModelTargetProcessContainerImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetProcessContainer { implements DbgModelTargetProcessContainer {
@ -47,8 +50,8 @@ public class DbgModelTargetProcessContainerImpl extends DbgModelTargetObjectImpl
@Override @Override
public void processAdded(DbgProcess proc, DbgCause cause) { public void processAdded(DbgProcess proc, DbgCause cause) {
DbgModelTargetSession session = (DbgModelTargetSession) getImplParent(); DbgModelTargetSession session = (DbgModelTargetSession) getParent();
session.setAccessibility(TargetAccessibility.ACCESSIBLE); session.setAccessible(true);
DbgModelTargetProcess process = getTargetProcess(proc); DbgModelTargetProcess process = getTargetProcess(proc);
changeElements(List.of(), List.of(process), Map.of(), "Added"); changeElements(List.of(), List.of(process), Map.of(), "Added");
process.processStarted(proc.getPid()); process.processStarted(proc.getPid());

View file

@ -28,22 +28,38 @@ import agent.dbgeng.model.iface2.*;
import ghidra.async.AsyncUtils; import ghidra.async.AsyncUtils;
import ghidra.async.TypeSpec; import ghidra.async.TypeSpec;
import ghidra.dbg.DebugModelConventions; import ghidra.dbg.DebugModelConventions;
import ghidra.dbg.DebuggerObjectModel;
import ghidra.dbg.attributes.TargetObjectRef;
import ghidra.dbg.attributes.TypedTargetObjectRef;
import ghidra.dbg.target.*; import ghidra.dbg.target.*;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils;
@TargetObjectSchemaInfo(name = "Process", elements = { // @TargetObjectSchemaInfo(
@TargetElementType(type = Void.class) // name = "Process",
}, attributes = { // elements = {
@TargetAttributeType(name = "Debug", type = DbgModelTargetDebugContainerImpl.class, required = true, fixed = true), // @TargetElementType(type = Void.class)
@TargetAttributeType(name = "Memory", type = DbgModelTargetMemoryContainerImpl.class, required = true, fixed = true), // },
@TargetAttributeType(name = "Modules", type = DbgModelTargetModuleContainerImpl.class, required = true, fixed = true), // attributes = {
@TargetAttributeType(name = "Threads", type = DbgModelTargetThreadContainerImpl.class, required = true, fixed = true), // @TargetAttributeType(
@TargetAttributeType(type = Void.class) // name = "Debug",
}) type = DbgModelTargetDebugContainerImpl.class,
required = true,
fixed = true),
@TargetAttributeType(
name = "Memory",
type = DbgModelTargetMemoryContainerImpl.class,
required = true,
fixed = true),
@TargetAttributeType(
name = "Modules",
type = DbgModelTargetModuleContainerImpl.class,
required = true,
fixed = true),
@TargetAttributeType(
name = "Threads",
type = DbgModelTargetThreadContainerImpl.class,
required = true,
fixed = true),
@TargetAttributeType(type = Void.class)
})
public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetProcess { implements DbgModelTargetProcess {
@ -113,7 +129,7 @@ public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
@Override @Override
public void processSelected(DbgProcess eventProcess, DbgCause cause) { public void processSelected(DbgProcess eventProcess, DbgCause cause) {
if (eventProcess.equals(process)) { if (eventProcess.equals(process)) {
AtomicReference<DbgModelTargetFocusScope<?>> scope = new AtomicReference<>(); AtomicReference<DbgModelTargetFocusScope> scope = new AtomicReference<>();
AsyncUtils.sequence(TypeSpec.VOID).then(seq -> { AsyncUtils.sequence(TypeSpec.VOID).then(seq -> {
DebugModelConventions.findSuitable(DbgModelTargetFocusScope.class, this) DebugModelConventions.findSuitable(DbgModelTargetFocusScope.class, this)
.handle(seq::next); .handle(seq::next);
@ -146,25 +162,16 @@ public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
} }
@Override @Override
public CompletableFuture<Void> attach(TypedTargetObjectRef<? extends TargetAttachable<?>> ref) { public CompletableFuture<Void> attach(TargetAttachable attachable) {
getModel().assertMine(TargetObjectRef.class, ref); getModel().assertMine(TargetObject.class, attachable);
// NOTE: Get the object and type check it myself. // NOTE: Get the object and type check it myself.
// The typed ref could have been unsafely cast // The typed ref could have been unsafely cast
List<String> tPath = ref.getPath(); return process.reattach(attachable).thenApply(set -> null);
return AsyncUtils.sequence(TypeSpec.VOID).then(seq -> {
getModel().fetchModelObject(tPath).handle(seq::next);
}, TypeSpec.cls(TargetObject.class)).then((obj, seq) -> {
TargetAttachable<?> attachable =
DebuggerObjectModel.requireIface(TargetAttachable.class, obj, tPath);
process.reattach(attachable);
}).finish();
} }
@Override @Override
public CompletableFuture<Void> attach(long pid) { public CompletableFuture<Void> attach(long pid) {
return AsyncUtils.sequence(TypeSpec.VOID).then(seq -> { return process.attach(pid).thenApply(set -> null);
process.attach(pid).handle(seq::nextIgnore);
}).finish();
} }
@Override @Override
@ -218,7 +225,7 @@ public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
@Override @Override
public void onExit() { public void onExit() {
super.onExit(); super.onExit();
DbgModelTargetProcessContainer processes = (DbgModelTargetProcessContainer) getImplParent(); DbgModelTargetProcessContainer processes = (DbgModelTargetProcessContainer) getParent();
processes.processRemoved(process.getId(), DbgCause.Causes.UNCLAIMED); processes.processRemoved(process.getId(), DbgCause.Causes.UNCLAIMED);
} }
@ -244,8 +251,7 @@ public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
} }
@Override @Override
public TargetAccessibility getAccessibility() { public boolean isAccessible() {
return accessibility; return accessible;
} }
} }

View file

@ -26,22 +26,24 @@ import agent.dbgeng.manager.impl.DbgRegisterSet;
import agent.dbgeng.model.iface2.*; import agent.dbgeng.model.iface2.*;
import ghidra.async.AsyncUtils; import ghidra.async.AsyncUtils;
import ghidra.async.TypeSpec; import ghidra.async.TypeSpec;
import ghidra.dbg.attributes.TargetObjectRef;
import ghidra.dbg.error.DebuggerRegisterAccessException; import ghidra.dbg.error.DebuggerRegisterAccessException;
import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibility;
import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.TargetRegisterBank; import ghidra.dbg.target.TargetRegisterBank;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.ConversionUtils; import ghidra.dbg.util.ConversionUtils;
@TargetObjectSchemaInfo(name = "RegisterContainer", elements = { // @TargetObjectSchemaInfo(
@TargetElementType(type = DbgModelTargetRegisterImpl.class) // name = "RegisterContainer",
}, attributes = { // elements = {
@TargetAttributeType( // @TargetElementType(type = DbgModelTargetRegisterImpl.class)
name = TargetRegisterBank.DESCRIPTIONS_ATTRIBUTE_NAME, // },
type=DbgModelTargetRegisterContainerImpl.class), attributes = {
@TargetAttributeType(type = Void.class) // @TargetAttributeType(
}, canonicalContainer = true) name = TargetRegisterBank.DESCRIPTIONS_ATTRIBUTE_NAME,
type = DbgModelTargetRegisterContainerImpl.class),
@TargetAttributeType(type = Void.class)
},
canonicalContainer = true)
public class DbgModelTargetRegisterContainerImpl extends DbgModelTargetObjectImpl public class DbgModelTargetRegisterContainerImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetRegisterContainerAndBank { implements DbgModelTargetRegisterContainerAndBank {
@ -139,7 +141,7 @@ public class DbgModelTargetRegisterContainerImpl extends DbgModelTargetObjectImp
}, TypeSpec.cls(DbgRegisterSet.class)).then((regs, seq) -> { }, TypeSpec.cls(DbgRegisterSet.class)).then((regs, seq) -> {
fetchElements().handle(seq::nextIgnore); fetchElements().handle(seq::nextIgnore);
}).then(seq -> { }).then(seq -> {
Map<String, ? extends TargetObjectRef> regs = getCachedElements(); Map<String, ? extends TargetObject> regs = getCachedElements();
Map<DbgRegister, BigInteger> toWrite = new LinkedHashMap<>(); Map<DbgRegister, BigInteger> toWrite = new LinkedHashMap<>();
for (Map.Entry<String, byte[]> ent : values.entrySet()) { for (Map.Entry<String, byte[]> ent : values.entrySet()) {
String regname = ent.getKey(); String regname = ent.getKey();
@ -168,12 +170,12 @@ public class DbgModelTargetRegisterContainerImpl extends DbgModelTargetObjectImp
public void onRunning() { public void onRunning() {
// NB: We don't want to do this apparently // NB: We don't want to do this apparently
//invalidateRegisterCaches(); //invalidateRegisterCaches();
setAccessibility(TargetAccessibility.INACCESSIBLE); setAccessible(false);
} }
@Override @Override
public void onStopped() { public void onStopped() {
setAccessibility(TargetAccessibility.ACCESSIBLE); setAccessible(true);
if (thread.equals(getManager().getEventThread())) { if (thread.equals(getManager().getEventThread())) {
readRegistersNamed(getCachedElements().keySet()); readRegistersNamed(getCachedElements().keySet());
} }

View file

@ -32,26 +32,26 @@ import ghidra.dbg.util.PathUtils;
@TargetObjectSchemaInfo( @TargetObjectSchemaInfo(
name = "Debugger", name = "Debugger",
elements = { // elements = {
@TargetElementType(type = Void.class) // @TargetElementType(type = Void.class)
}, },
attributes = { // attributes = {
@TargetAttributeType( @TargetAttributeType(
name = "Available", name = "Available",
type = DbgModelTargetAvailableContainerImpl.class, type = DbgModelTargetAvailableContainerImpl.class,
required = true, required = true,
fixed = true), // fixed = true),
@TargetAttributeType( @TargetAttributeType(
name = "Connectors", name = "Connectors",
type = DbgModelTargetConnectorContainerImpl.class, type = DbgModelTargetConnectorContainerImpl.class,
required = true, required = true,
fixed = true), // fixed = true),
@TargetAttributeType( @TargetAttributeType(
name = "Sessions", name = "Sessions",
type = DbgModelTargetSessionContainerImpl.class, type = DbgModelTargetSessionContainerImpl.class,
required = true, required = true,
fixed = true), // fixed = true),
@TargetAttributeType(type = Void.class) // @TargetAttributeType(type = Void.class)
}) })
public class DbgModelTargetRootImpl extends DbgModelDefaultTargetModelRoot public class DbgModelTargetRootImpl extends DbgModelDefaultTargetModelRoot
implements DbgModelTargetRoot { implements DbgModelTargetRoot {
@ -152,8 +152,8 @@ public class DbgModelTargetRootImpl extends DbgModelDefaultTargetModelRoot
} }
@Override @Override
public TargetAccessibility getAccessibility() { public boolean isAccessible() {
return accessibility; return accessible;
} }
} }

View file

@ -27,13 +27,23 @@ import agent.dbgeng.model.iface2.DbgModelTargetSession;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils;
@TargetObjectSchemaInfo(name = "Session", elements = { // @TargetObjectSchemaInfo(
@TargetElementType(type = Void.class) // name = "Session",
}, attributes = { // elements = {
@TargetAttributeType(name = "Attributes", type = DbgModelTargetSessionAttributesImpl.class, fixed = true), // @TargetElementType(type = Void.class)
@TargetAttributeType(name = "Processes", type = DbgModelTargetProcessContainerImpl.class, required = true, fixed = true), // },
@TargetAttributeType(type = Void.class) // attributes = {
}) @TargetAttributeType(
name = "Attributes",
type = DbgModelTargetSessionAttributesImpl.class,
fixed = true),
@TargetAttributeType(
name = "Processes",
type = DbgModelTargetProcessContainerImpl.class,
required = true,
fixed = true),
@TargetAttributeType(type = Void.class)
})
public class DbgModelTargetSessionImpl extends DbgModelTargetObjectImpl public class DbgModelTargetSessionImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetSession { implements DbgModelTargetSession {
@ -87,8 +97,8 @@ public class DbgModelTargetSessionImpl extends DbgModelTargetObjectImpl
} }
@Override @Override
public TargetAccessibility getAccessibility() { public boolean isAccessible() {
return accessibility; return accessible;
} }
@Override @Override

View file

@ -28,27 +28,52 @@ import agent.dbgeng.model.iface2.*;
import ghidra.async.AsyncUtils; import ghidra.async.AsyncUtils;
import ghidra.async.TypeSpec; import ghidra.async.TypeSpec;
import ghidra.dbg.DebugModelConventions; import ghidra.dbg.DebugModelConventions;
import ghidra.dbg.attributes.TargetObjectRef; import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
@TargetObjectSchemaInfo(name = "StackFrame", elements = { // @TargetObjectSchemaInfo(
@TargetElementType(type = Void.class) // name = "StackFrame",
}, attributes = { // elements = {
@TargetAttributeType(name = DbgModelTargetStackFrame.FUNC_ATTRIBUTE_NAME, type = String.class), // @TargetElementType(type = Void.class)
@TargetAttributeType(name = DbgModelTargetStackFrame.FUNC_TABLE_ENTRY_ATTRIBUTE_NAME, type = String.class), // },
@TargetAttributeType(name = DbgModelTargetStackFrame.INST_OFFSET_ATTRIBUTE_NAME, type = String.class), // attributes = {
@TargetAttributeType(name = DbgModelTargetStackFrame.FRAME_OFFSET_ATTRIBUTE_NAME, type = String.class), // @TargetAttributeType(
@TargetAttributeType(name = DbgModelTargetStackFrame.RETURN_OFFSET_ATTRIBUTE_NAME, type = String.class), // name = DbgModelTargetStackFrame.FUNC_ATTRIBUTE_NAME,
@TargetAttributeType(name = DbgModelTargetStackFrame.STACK_OFFSET_ATTRIBUTE_NAME, type = String.class), // type = String.class),
@TargetAttributeType(name = DbgModelTargetStackFrame.VIRTUAL_ATTRIBUTE_NAME, type = Boolean.class), // @TargetAttributeType(
@TargetAttributeType(name = DbgModelTargetStackFrame.PARAM0_ATTRIBUTE_NAME, type = String.class), // name = DbgModelTargetStackFrame.FUNC_TABLE_ENTRY_ATTRIBUTE_NAME,
@TargetAttributeType(name = DbgModelTargetStackFrame.PARAM1_ATTRIBUTE_NAME, type = String.class), // type = String.class),
@TargetAttributeType(name = DbgModelTargetStackFrame.PARAM2_ATTRIBUTE_NAME, type = String.class), // @TargetAttributeType(
@TargetAttributeType(name = DbgModelTargetStackFrame.PARAM3_ATTRIBUTE_NAME, type = String.class), // name = DbgModelTargetStackFrame.INST_OFFSET_ATTRIBUTE_NAME,
@TargetAttributeType(type = Void.class) // type = String.class),
}) @TargetAttributeType(
name = DbgModelTargetStackFrame.FRAME_OFFSET_ATTRIBUTE_NAME,
type = String.class),
@TargetAttributeType(
name = DbgModelTargetStackFrame.RETURN_OFFSET_ATTRIBUTE_NAME,
type = String.class),
@TargetAttributeType(
name = DbgModelTargetStackFrame.STACK_OFFSET_ATTRIBUTE_NAME,
type = String.class),
@TargetAttributeType(
name = DbgModelTargetStackFrame.VIRTUAL_ATTRIBUTE_NAME,
type = Boolean.class),
@TargetAttributeType(
name = DbgModelTargetStackFrame.PARAM0_ATTRIBUTE_NAME,
type = String.class),
@TargetAttributeType(
name = DbgModelTargetStackFrame.PARAM1_ATTRIBUTE_NAME,
type = String.class),
@TargetAttributeType(
name = DbgModelTargetStackFrame.PARAM2_ATTRIBUTE_NAME,
type = String.class),
@TargetAttributeType(
name = DbgModelTargetStackFrame.PARAM3_ATTRIBUTE_NAME,
type = String.class),
@TargetAttributeType(type = Void.class)
})
public class DbgModelTargetStackFrameImpl extends DbgModelTargetObjectImpl public class DbgModelTargetStackFrameImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetStackFrame { implements DbgModelTargetStackFrame {
@ -100,7 +125,7 @@ public class DbgModelTargetStackFrameImpl extends DbgModelTargetObjectImpl
@Override @Override
public void threadSelected(DbgThread eventThread, DbgStackFrame eventFrame, DbgCause cause) { public void threadSelected(DbgThread eventThread, DbgStackFrame eventFrame, DbgCause cause) {
if (eventFrame != null && eventFrame.equals(frame)) { if (eventFrame != null && eventFrame.equals(frame)) {
AtomicReference<DbgModelTargetFocusScope<?>> scope = new AtomicReference<>(); AtomicReference<DbgModelTargetFocusScope> scope = new AtomicReference<>();
AsyncUtils.sequence(TypeSpec.VOID).then(seq -> { AsyncUtils.sequence(TypeSpec.VOID).then(seq -> {
DebugModelConventions.findSuitable(DbgModelTargetFocusScope.class, this) DebugModelConventions.findSuitable(DbgModelTargetFocusScope.class, this)
.handle(seq::next); .handle(seq::next);
@ -154,7 +179,7 @@ public class DbgModelTargetStackFrameImpl extends DbgModelTargetObjectImpl
} }
@Override @Override
public TargetObjectRef getThread() { public TargetObject getThread() {
return thread.getParent(); return thread.getParent();
} }

View file

@ -22,17 +22,20 @@ import java.util.stream.Collectors;
import agent.dbgeng.manager.DbgStackFrame; import agent.dbgeng.manager.DbgStackFrame;
import agent.dbgeng.model.iface2.*; import agent.dbgeng.model.iface2.*;
import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibility;
import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.datastruct.WeakValueHashMap; import ghidra.util.datastruct.WeakValueHashMap;
@TargetObjectSchemaInfo(name = "Stack", elements = { // @TargetObjectSchemaInfo(
@TargetElementType(type = DbgModelTargetStackFrameImpl.class) // name = "Stack",
}, attributes = { // elements = {
@TargetAttributeType(type = Void.class) // @TargetElementType(type = DbgModelTargetStackFrameImpl.class)
}, canonicalContainer = true) },
attributes = {
@TargetAttributeType(type = Void.class)
},
canonicalContainer = true)
public class DbgModelTargetStackImpl extends DbgModelTargetObjectImpl public class DbgModelTargetStackImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetStack { implements DbgModelTargetStack {
@ -84,12 +87,12 @@ public class DbgModelTargetStackImpl extends DbgModelTargetObjectImpl
public void onRunning() { public void onRunning() {
// NB: We don't want to do this apparently // NB: We don't want to do this apparently
//invalidateRegisterCaches(); //invalidateRegisterCaches();
setAccessibility(TargetAccessibility.INACCESSIBLE); setAccessible(false);
} }
@Override @Override
public void onStopped() { public void onStopped() {
setAccessibility(TargetAccessibility.ACCESSIBLE); setAccessible(true);
if (thread.getThread().getId().equals(getManager().getEventThread().getId())) { if (thread.getThread().getId().equals(getManager().getEventThread().getId())) {
update(); update();
} }
@ -101,6 +104,7 @@ public class DbgModelTargetStackImpl extends DbgModelTargetObjectImpl
* GDB doesn't produce stack change events, but they should only ever happen by running a * GDB doesn't produce stack change events, but they should only ever happen by running a
* target. Thus, every time we're STOPPED, this method should be called. * target. Thus, every time we're STOPPED, this method should be called.
*/ */
@Override
public void update() { public void update() {
requestElements(true).exceptionally(e -> { requestElements(true).exceptionally(e -> {
Msg.error(this, "Could not update stack " + this + " on STOPPED"); Msg.error(this, "Could not update stack " + this + " on STOPPED");

View file

@ -33,14 +33,25 @@ import ghidra.dbg.target.TargetEnvironment;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils;
@TargetObjectSchemaInfo(name = "Thread", elements = { // @TargetObjectSchemaInfo(
@TargetElementType(type = Void.class) // name = "Thread",
}, attributes = { // elements = {
@TargetAttributeType(name = "Registers", type = DbgModelTargetRegisterContainerImpl.class, required = true, fixed = true), // @TargetElementType(type = Void.class)
@TargetAttributeType(name = "Stack", type = DbgModelTargetStackImpl.class, required = true, fixed = true), // },
@TargetAttributeType(name = TargetEnvironment.ARCH_ATTRIBUTE_NAME, type = String.class), // attributes = {
@TargetAttributeType(type = Void.class) // @TargetAttributeType(
}) name = "Registers",
type = DbgModelTargetRegisterContainerImpl.class,
required = true,
fixed = true),
@TargetAttributeType(
name = "Stack",
type = DbgModelTargetStackImpl.class,
required = true,
fixed = true),
@TargetAttributeType(name = TargetEnvironment.ARCH_ATTRIBUTE_NAME, type = String.class),
@TargetAttributeType(type = Void.class)
})
public class DbgModelTargetThreadImpl extends DbgModelTargetObjectImpl public class DbgModelTargetThreadImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetThread { implements DbgModelTargetThread {
@ -107,7 +118,7 @@ public class DbgModelTargetThreadImpl extends DbgModelTargetObjectImpl
@Override @Override
public void threadSelected(DbgThread eventThread, DbgStackFrame frame, DbgCause cause) { public void threadSelected(DbgThread eventThread, DbgStackFrame frame, DbgCause cause) {
if (eventThread.equals(thread)) { if (eventThread.equals(thread)) {
AtomicReference<DbgModelTargetFocusScope<?>> scope = new AtomicReference<>(); AtomicReference<DbgModelTargetFocusScope> scope = new AtomicReference<>();
AsyncUtils.sequence(TypeSpec.VOID).then(seq -> { AsyncUtils.sequence(TypeSpec.VOID).then(seq -> {
DebugModelConventions.findSuitable(DbgModelTargetFocusScope.class, this) DebugModelConventions.findSuitable(DbgModelTargetFocusScope.class, this)
.handle(seq::next); .handle(seq::next);
@ -170,8 +181,8 @@ public class DbgModelTargetThreadImpl extends DbgModelTargetObjectImpl
} }
@Override @Override
public TargetAccessibility getAccessibility() { public boolean isAccessible() {
return accessibility; return accessible;
} }
@Override @Override

View file

@ -16,6 +16,7 @@
package agent.dbgeng.model; package agent.dbgeng.model;
import static agent.dbgeng.testutil.DummyProc.runProc; import static agent.dbgeng.testutil.DummyProc.runProc;
import static ghidra.lifecycle.Unfinished.TODO;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.util.*; import java.util.*;
@ -33,12 +34,10 @@ import ghidra.async.*;
import ghidra.dbg.DebugModelConventions; import ghidra.dbg.DebugModelConventions;
import ghidra.dbg.DebugModelConventions.AllRequiredAccess; import ghidra.dbg.DebugModelConventions.AllRequiredAccess;
import ghidra.dbg.DebuggerObjectModel; import ghidra.dbg.DebuggerObjectModel;
import ghidra.dbg.attributes.TargetObjectRef; import ghidra.dbg.attributes.TargetObjectList;
import ghidra.dbg.attributes.TargetObjectRefList;
import ghidra.dbg.error.DebuggerModelNoSuchPathException; import ghidra.dbg.error.DebuggerModelNoSuchPathException;
import ghidra.dbg.error.DebuggerModelTypeException; import ghidra.dbg.error.DebuggerModelTypeException;
import ghidra.dbg.target.*; import ghidra.dbg.target.*;
import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibility;
import ghidra.dbg.target.TargetBreakpointContainer.TargetBreakpointKindSet; import ghidra.dbg.target.TargetBreakpointContainer.TargetBreakpointKindSet;
import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointKind; import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointKind;
import ghidra.dbg.target.TargetConsole.Channel; import ghidra.dbg.target.TargetConsole.Channel;
@ -139,7 +138,7 @@ public abstract class AbstractModelForDbgTest
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, access).then(seq -> { }, access).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
model.fetchModelObject("Doesn't exist").handle(seq::next); model.fetchModelObject("Doesn't exist").handle(seq::next);
}, TypeSpec.cls(TargetObject.class)).then((obj, seq) -> { }, TypeSpec.cls(TargetObject.class)).then((obj, seq) -> {
@ -156,7 +155,7 @@ public abstract class AbstractModelForDbgTest
AtomicReference<TargetObject> root = new AtomicReference<>(); AtomicReference<TargetObject> root = new AtomicReference<>();
AtomicReference<AllRequiredAccess> access = new AtomicReference<>(); AtomicReference<AllRequiredAccess> access = new AtomicReference<>();
AtomicReference<DbgModelTargetLauncher<?>> launcher = new AtomicReference<>(); AtomicReference<DbgModelTargetLauncher> launcher = new AtomicReference<>();
TypeSpec<Map<String, ? extends TargetObject>> t = TypeSpec.auto(); TypeSpec<Map<String, ? extends TargetObject>> t = TypeSpec.auto();
waitOn(AsyncUtils.sequence(TypeSpec.VOID).then(seq -> { waitOn(AsyncUtils.sequence(TypeSpec.VOID).then(seq -> {
@ -169,7 +168,7 @@ public abstract class AbstractModelForDbgTest
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, access).then(seq -> { }, access).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Finding TargetLauncher..."); Msg.debug(this, "Finding TargetLauncher...");
DebugModelConventions.findSuitable(DbgModelTargetLauncher.class, root.get()) DebugModelConventions.findSuitable(DbgModelTargetLauncher.class, root.get())
@ -179,11 +178,10 @@ public abstract class AbstractModelForDbgTest
launcher.get().launch("notepad", "junk.txt").handle(seq::nextIgnore); launcher.get().launch("notepad", "junk.txt").handle(seq::nextIgnore);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Getting Processes (after launch)..."); Msg.debug(this, "Getting Processes (after launch)...");
model.fetchObjectElements(List.of("Sessions", "[0]")) model.fetchObjectElements(List.of("Sessions", "[0]"))
.thenCompose(DebugModelConventions::fetchAll)
.handle(seq::next); .handle(seq::next);
}, t).then((children, seq) -> { }, t).then((children, seq) -> {
Msg.debug(this, "Processes after: " + children); Msg.debug(this, "Processes after: " + children);
@ -201,7 +199,7 @@ public abstract class AbstractModelForDbgTest
AtomicReference<TargetObject> root = new AtomicReference<>(); AtomicReference<TargetObject> root = new AtomicReference<>();
AtomicReference<TargetObject> session = new AtomicReference<>(); AtomicReference<TargetObject> session = new AtomicReference<>();
AtomicReference<AllRequiredAccess> rootAccess = new AtomicReference<>(); AtomicReference<AllRequiredAccess> rootAccess = new AtomicReference<>();
AtomicReference<DbgModelTargetLauncher<?>> launcher = new AtomicReference<>(); AtomicReference<DbgModelTargetLauncher> launcher = new AtomicReference<>();
AtomicReference<AllRequiredAccess> launcherAccess = new AtomicReference<>(); AtomicReference<AllRequiredAccess> launcherAccess = new AtomicReference<>();
TypeSpec<Map<String, ? extends TargetObject>> t = TypeSpec.auto(); TypeSpec<Map<String, ? extends TargetObject>> t = TypeSpec.auto();
@ -215,7 +213,7 @@ public abstract class AbstractModelForDbgTest
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, rootAccess).then(seq -> { }, rootAccess).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
rootAccess.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); rootAccess.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
model.fetchModelObject(List.of("Sessions", "[0]")).handle(seq::next); model.fetchModelObject(List.of("Sessions", "[0]")).handle(seq::next);
}, session).then(seq -> { }, session).then(seq -> {
@ -224,22 +222,21 @@ public abstract class AbstractModelForDbgTest
session.get()).handle(seq::next); session.get()).handle(seq::next);
}, TypeSpec.cls(TargetObject.class)).then((obj, seq) -> { }, TypeSpec.cls(TargetObject.class)).then((obj, seq) -> {
assertTrue(obj.getInterfaceNames().contains("Launcher")); assertTrue(obj.getInterfaceNames().contains("Launcher"));
launcher.set((DbgModelTargetLauncher<?>) obj); launcher.set((DbgModelTargetLauncher) obj);
Msg.debug(this, "Tracking process access..."); Msg.debug(this, "Tracking process access...");
DebugModelConventions.trackAccessibility(obj).handle(seq::next); DebugModelConventions.trackAccessibility(obj).handle(seq::next);
}, launcherAccess).then(seq -> { }, launcherAccess).then(seq -> {
Msg.debug(this, "Waiting for process access..."); Msg.debug(this, "Waiting for process access...");
launcherAccess.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); launcherAccess.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Launching..."); Msg.debug(this, "Launching...");
launcher.get().launch("notepad", "junk.txt").handle(seq::nextIgnore); launcher.get().launch("notepad", "junk.txt").handle(seq::nextIgnore);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Waiting for session access (again)..."); Msg.debug(this, "Waiting for session access (again)...");
rootAccess.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); rootAccess.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Getting Processes (after launch)..."); Msg.debug(this, "Getting Processes (after launch)...");
model.fetchObjectElements(List.of("Sessions", "[0]", "Processes")) model.fetchObjectElements(List.of("Sessions", "[0]", "Processes"))
.thenCompose(DebugModelConventions::fetchAll)
.handle(seq::next); .handle(seq::next);
}, t).then((elements, seq) -> { }, t).then((elements, seq) -> {
Msg.debug(this, "Processes after: " + elements); Msg.debug(this, "Processes after: " + elements);
@ -267,10 +264,9 @@ public abstract class AbstractModelForDbgTest
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, access).then(seq -> { }, access).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
model.fetchObjectElements(List.of("Sessions", "[0]", "Available")) model.fetchObjectElements(List.of("Sessions", "[0]", "Available"))
.thenCompose(DebugModelConventions::fetchAll)
.handle(seq::next); .handle(seq::next);
}, DebuggerObjectModel.ELEMENT_MAP_TYPE).then((available, seq) -> { }, DebuggerObjectModel.ELEMENT_MAP_TYPE).then((available, seq) -> {
assertTrue(available.containsKey(Long.toString(np.pid))); assertTrue(available.containsKey(Long.toString(np.pid)));
@ -298,7 +294,7 @@ public abstract class AbstractModelForDbgTest
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, access).then(seq -> { }, access).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Finding TargetLauncher..."); Msg.debug(this, "Finding TargetLauncher...");
DebugModelConventions.findSuitable(TargetAttacher.class, root.get()) DebugModelConventions.findSuitable(TargetAttacher.class, root.get())
@ -306,16 +302,11 @@ public abstract class AbstractModelForDbgTest
seq::next); seq::next);
}, proc).then(seq -> { }, proc).then(seq -> {
Msg.debug(this, "Attaching to bogus path..."); Msg.debug(this, "Attaching to bogus path...");
TargetAttacher<?> attacher = proc.get().as(TargetAttacher.tclass); TargetAttacher attacher = proc.get().as(TargetAttacher.class);
attacher.attach( TODO();
model.createRef("Sessions", "[0]", "Available", "[" + np.pid + "]") seq.next(null, null);
.as(
TargetAttachable.tclass))
.handle(
seq::nextIgnore);
}).then(seq -> { }).then(seq -> {
model.fetchObjectElements(List.of("Sessions", "[0]", "Processes")) model.fetchObjectElements(List.of("Sessions", "[0]", "Processes"))
.thenCompose(DebugModelConventions::fetchAll)
.handle(seq::next); .handle(seq::next);
// NB: listProcesses will fail if no process is being debugged // NB: listProcesses will fail if no process is being debugged
}, DebuggerObjectModel.ELEMENT_MAP_TYPE).then((processes, seq) -> { }, DebuggerObjectModel.ELEMENT_MAP_TYPE).then((processes, seq) -> {
@ -332,8 +323,8 @@ public abstract class AbstractModelForDbgTest
AtomicReference<TargetObject> root = new AtomicReference<>(); AtomicReference<TargetObject> root = new AtomicReference<>();
AtomicReference<AllRequiredAccess> access = new AtomicReference<>(); AtomicReference<AllRequiredAccess> access = new AtomicReference<>();
AtomicReference<TargetAttacher<?>> attacher = new AtomicReference<>(); AtomicReference<TargetAttacher> attacher = new AtomicReference<>();
AtomicReference<TargetAttachable<?>> attachable = new AtomicReference<>(); AtomicReference<TargetAttachable> attachable = new AtomicReference<>();
TypeSpec<Map<String, ? extends TargetObject>> t = TypeSpec.auto(); TypeSpec<Map<String, ? extends TargetObject>> t = TypeSpec.auto();
waitOn(AsyncUtils.sequence(TypeSpec.VOID).then(seq -> { waitOn(AsyncUtils.sequence(TypeSpec.VOID).then(seq -> {
@ -346,7 +337,7 @@ public abstract class AbstractModelForDbgTest
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, access).then(seq -> { }, access).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
// Msg.debug(this, "Getting Processes (before attach)..."); // Msg.debug(this, "Getting Processes (before attach)...");
// model.getObjectElements(List.of("Sessions", "[0]", "Processes")).handle(seq::next); // model.getObjectElements(List.of("Sessions", "[0]", "Processes")).handle(seq::next);
@ -366,7 +357,7 @@ public abstract class AbstractModelForDbgTest
.thenAccept(o -> { .thenAccept(o -> {
Msg.debug(this, " Got Attachable: " + o); Msg.debug(this, " Got Attachable: " + o);
assertTrue(o.getInterfaceNames().contains("Attachable")); assertTrue(o.getInterfaceNames().contains("Attachable"));
attachable.set((TargetAttachable<?>) o); attachable.set((TargetAttachable) o);
})); }));
fence.ready().handle(seq::next); fence.ready().handle(seq::next);
}).then(seq -> { }).then(seq -> {
@ -374,11 +365,10 @@ public abstract class AbstractModelForDbgTest
attacher.get().attach(attachable.get()).handle(seq::nextIgnore); attacher.get().attach(attachable.get()).handle(seq::nextIgnore);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Waiting for session access (again)..."); Msg.debug(this, "Waiting for session access (again)...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Getting Processes (after attach)..."); Msg.debug(this, "Getting Processes (after attach)...");
model.fetchObjectElements(List.of("Sessions", "[0]", "Processes")) model.fetchObjectElements(List.of("Sessions", "[0]", "Processes"))
.thenCompose(DebugModelConventions::fetchAll)
.handle(seq::next); .handle(seq::next);
}, t).then((elements, seq) -> { }, t).then((elements, seq) -> {
Msg.debug(this, "Processes after: " + elements); Msg.debug(this, "Processes after: " + elements);
@ -386,7 +376,7 @@ public abstract class AbstractModelForDbgTest
Msg.debug(this, "Killing..."); Msg.debug(this, "Killing...");
TargetObject attached = elements.get("0"); TargetObject attached = elements.get("0");
assertTrue(attached.getInterfaceNames().contains("Killable")); assertTrue(attached.getInterfaceNames().contains("Killable"));
TargetKillable<?> killable = (TargetKillable<?>) attached; TargetKillable killable = (TargetKillable) attached;
killable.kill().handle(seq::next); killable.kill().handle(seq::next);
}).finish()); }).finish());
} }
@ -412,7 +402,7 @@ public abstract class AbstractModelForDbgTest
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, access).then(seq -> { }, access).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Finding TargetLauncher..."); Msg.debug(this, "Finding TargetLauncher...");
DebugModelConventions.findSuitable(TargetAttacher.class, root.get()) DebugModelConventions.findSuitable(TargetAttacher.class, root.get())
@ -420,17 +410,15 @@ public abstract class AbstractModelForDbgTest
seq::next); seq::next);
}, obj).then(seq -> { }, obj).then(seq -> {
Msg.debug(this, "Attaching..."); Msg.debug(this, "Attaching...");
TargetAttacher<?> attacher = obj.get().as(TargetAttacher.tclass); TargetAttacher attacher = obj.get().as(TargetAttacher.class);
attacher.attach(model.createRef("Sessions", "[0]", "Available", "[" + np.pid + "]") attacher.attach(np.pid)
.as(TargetAttachable.tclass))
.handle(seq::nextIgnore); .handle(seq::nextIgnore);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Waiting for session access (again, again)..."); Msg.debug(this, "Waiting for session access (again, again)...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Getting Processes (after attach)..."); Msg.debug(this, "Getting Processes (after attach)...");
model.fetchObjectElements(List.of("Sessions", "[0]", "Processes")) model.fetchObjectElements(List.of("Sessions", "[0]", "Processes"))
.thenCompose(DebugModelConventions::fetchAll)
.handle(seq::next); .handle(seq::next);
}, t).then((elements, seq) -> { }, t).then((elements, seq) -> {
Msg.debug(this, "Processes after: " + elements); Msg.debug(this, "Processes after: " + elements);
@ -438,7 +426,7 @@ public abstract class AbstractModelForDbgTest
Msg.debug(this, "Killing..."); Msg.debug(this, "Killing...");
TargetObject attached = elements.get("0"); TargetObject attached = elements.get("0");
assertTrue(attached.getInterfaceNames().contains("Killable")); assertTrue(attached.getInterfaceNames().contains("Killable"));
TargetKillable<?> killable = (TargetKillable<?>) attached; TargetKillable killable = (TargetKillable) attached;
killable.kill().handle(seq::next); killable.kill().handle(seq::next);
}).finish()); }).finish());
} }
@ -464,7 +452,7 @@ public abstract class AbstractModelForDbgTest
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, access).then(seq -> { }, access).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Finding TargetLauncher..."); Msg.debug(this, "Finding TargetLauncher...");
DebugModelConventions.findSuitable(TargetAttacher.class, root.get()) DebugModelConventions.findSuitable(TargetAttacher.class, root.get())
@ -472,29 +460,25 @@ public abstract class AbstractModelForDbgTest
seq::next); seq::next);
}, obj).then(seq -> { }, obj).then(seq -> {
Msg.debug(this, "Attaching..."); Msg.debug(this, "Attaching...");
TargetAttacher<?> attacher = obj.get().as(TargetAttacher.tclass); TargetAttacher attacher = obj.get().as(TargetAttacher.class);
attacher.attach( attacher.attach(np.pid)
model.createRef("Sessions", "[0]", "Available", "[" + np.pid + "]")
.as(
TargetAttachable.tclass))
.handle(seq::nextIgnore); .handle(seq::nextIgnore);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Waiting for session access (again, again)..."); Msg.debug(this, "Waiting for session access (again, again)...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Getting Process 1..."); Msg.debug(this, "Getting Process 1...");
model.fetchModelObject("Sessions", "[0]", "Processes", "[0]").handle(seq::next); model.fetchModelObject("Sessions", "[0]", "Processes", "[0]").handle(seq::next);
}, obj).then(seq -> { }, obj).then(seq -> {
Msg.debug(this, "Resuming..."); Msg.debug(this, "Resuming...");
TargetResumable<?> resumable = obj.get().as(TargetResumable.tclass); TargetResumable resumable = obj.get().as(TargetResumable.class);
resumable.resume().handle(seq::next); resumable.resume().handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Waiting for session access (after resume)..."); Msg.debug(this, "Waiting for session access (after resume)...");
access.get().waitValue(TargetAccessibility.INACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Getting Processes (after attach)..."); Msg.debug(this, "Getting Processes (after attach)...");
model.fetchObjectElements(List.of("Sessions", "[0]", "Processes")) model.fetchObjectElements(List.of("Sessions", "[0]", "Processes"))
.thenCompose(DebugModelConventions::fetchAll)
.handle(seq::next); .handle(seq::next);
}, t).then((elements, seq) -> { }, t).then((elements, seq) -> {
Msg.debug(this, "Processes after: " + elements); Msg.debug(this, "Processes after: " + elements);
@ -502,7 +486,7 @@ public abstract class AbstractModelForDbgTest
Msg.debug(this, "Killing..."); Msg.debug(this, "Killing...");
TargetObject attached = elements.get("0"); TargetObject attached = elements.get("0");
assertTrue(attached.getInterfaceNames().contains("Killable")); assertTrue(attached.getInterfaceNames().contains("Killable"));
TargetKillable<?> killable = (TargetKillable<?>) attached; TargetKillable killable = (TargetKillable) attached;
killable.kill().handle(seq::nextIgnore); killable.kill().handle(seq::nextIgnore);
}).finish()); }).finish());
} }
@ -526,29 +510,29 @@ public abstract class AbstractModelForDbgTest
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, access).then(seq -> { }, access).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Finding TargetLauncher..."); Msg.debug(this, "Finding TargetLauncher...");
DebugModelConventions.findSuitable(DbgModelTargetLauncher.class, root.get()) DebugModelConventions.findSuitable(DbgModelTargetLauncher.class, root.get())
.handle(seq::next); .handle(seq::next);
}, obj).then(seq -> { }, obj).then(seq -> {
Msg.debug(this, "Launching..."); Msg.debug(this, "Launching...");
TargetLauncher<?> launcher = obj.get().as(TargetLauncher.tclass); TargetLauncher launcher = obj.get().as(TargetLauncher.class);
launcher.launch(Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, "notepad junk.txt")) launcher.launch(Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, "notepad junk.txt"))
.handle(seq::nextIgnore); .handle(seq::nextIgnore);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Waiting for session access (again)..."); Msg.debug(this, "Waiting for session access (again)...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Getting Process 1..."); Msg.debug(this, "Getting Process 1...");
model.fetchModelObject("Sessions", "[0]", "Processes", "[0]").handle(seq::next); model.fetchModelObject("Sessions", "[0]", "Processes", "[0]").handle(seq::next);
}, obj).then(seq -> { }, obj).then(seq -> {
Msg.debug(this, "Resuming..."); Msg.debug(this, "Resuming...");
TargetResumable<?> resumable = obj.get().as(TargetResumable.tclass); TargetResumable resumable = obj.get().as(TargetResumable.class);
resumable.resume().handle(seq::next); resumable.resume().handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Waiting for session access (after resume)..."); Msg.debug(this, "Waiting for session access (after resume)...");
access.get().waitValue(TargetAccessibility.INACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).finish()); }).finish());
} }
} }
@ -572,7 +556,7 @@ public abstract class AbstractModelForDbgTest
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, access).then(seq -> { }, access).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Finding TargetLauncher..."); Msg.debug(this, "Finding TargetLauncher...");
DebugModelConventions.findSuitable(TargetAttacher.class, root.get()) DebugModelConventions.findSuitable(TargetAttacher.class, root.get())
@ -580,10 +564,9 @@ public abstract class AbstractModelForDbgTest
seq::next); seq::next);
}, proc).then(seq -> { }, proc).then(seq -> {
Msg.debug(this, "Attaching to bogus path..."); Msg.debug(this, "Attaching to bogus path...");
TargetAttacher<?> attacher = proc.get().as(TargetAttacher.tclass); TargetAttacher attacher = proc.get().as(TargetAttacher.class);
attacher.attach(model.createRef("Sessions", "[0]", "Available", "Process -1") TODO();
.as(TargetAttachable.tclass)) seq.next(null, null);
.handle(seq::nextIgnore);
}).finish()); }).finish());
} }
} }
@ -607,7 +590,7 @@ public abstract class AbstractModelForDbgTest
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, access).then(seq -> { }, access).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Finding TargetLauncher..."); Msg.debug(this, "Finding TargetLauncher...");
DebugModelConventions.findSuitable(TargetAttacher.class, root.get()) DebugModelConventions.findSuitable(TargetAttacher.class, root.get())
@ -615,11 +598,9 @@ public abstract class AbstractModelForDbgTest
seq::next); seq::next);
}, proc).then(seq -> { }, proc).then(seq -> {
Msg.debug(this, "Attaching to bogus path..."); Msg.debug(this, "Attaching to bogus path...");
TargetAttacher<?> attacher = proc.get().as(TargetAttacher.tclass); TargetAttacher attacher = proc.get().as(TargetAttacher.class);
attacher.attach(model.createRef("Sessions", "[0]", "Available") TODO();
.as( seq.next(null, null);
TargetAttachable.tclass))
.handle(seq::nextIgnore);
}).finish()); }).finish());
fail("Exception expected"); fail("Exception expected");
} }
@ -662,10 +643,10 @@ public abstract class AbstractModelForDbgTest
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, access).then(seq -> { }, access).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Running command..."); Msg.debug(this, "Running command...");
TargetInterpreter<?> interpreter = root.get().as(TargetInterpreter.tclass); TargetInterpreter interpreter = root.get().as(TargetInterpreter.class);
interpreter.execute(".echo xyzzy").handle(seq::next); interpreter.execute(".echo xyzzy").handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Waiting for expected output..."); Msg.debug(this, "Waiting for expected output...");
@ -705,10 +686,10 @@ public abstract class AbstractModelForDbgTest
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, access).then(seq -> { }, access).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Running command with capture..."); Msg.debug(this, "Running command with capture...");
TargetInterpreter<?> interpreter = root.get().as(TargetInterpreter.tclass); TargetInterpreter interpreter = root.get().as(TargetInterpreter.class);
interpreter.executeCapture(".echo xyzzy").handle(seq::next); interpreter.executeCapture(".echo xyzzy").handle(seq::next);
}, TypeSpec.STRING).then((out, seq) -> { }, TypeSpec.STRING).then((out, seq) -> {
Msg.debug(this, "Captured: " + out); Msg.debug(this, "Captured: " + out);
@ -725,7 +706,7 @@ public abstract class AbstractModelForDbgTest
AtomicReference<TargetObject> root = new AtomicReference<>(); AtomicReference<TargetObject> root = new AtomicReference<>();
AtomicReference<AllRequiredAccess> access = new AtomicReference<>(); AtomicReference<AllRequiredAccess> access = new AtomicReference<>();
AtomicReference<TargetBreakpointContainer<?>> breaks = new AtomicReference<>(); AtomicReference<TargetBreakpointContainer> breaks = new AtomicReference<>();
waitOn(AsyncUtils.sequence(TypeSpec.VOID).then(seq -> { waitOn(AsyncUtils.sequence(TypeSpec.VOID).then(seq -> {
m.init().handle(seq::next); m.init().handle(seq::next);
@ -737,7 +718,7 @@ public abstract class AbstractModelForDbgTest
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, access).then(seq -> { }, access).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Finding breakpoint container..."); Msg.debug(this, "Finding breakpoint container...");
DebugModelConventions.findSuitable(TargetBreakpointContainer.class, root.get()) DebugModelConventions.findSuitable(TargetBreakpointContainer.class, root.get())
@ -752,7 +733,7 @@ public abstract class AbstractModelForDbgTest
} }
} }
public static final TypeSpec<Collection<? extends TargetBreakpointLocation<?>>> BL_COL_SPEC = public static final TypeSpec<Collection<? extends TargetBreakpointLocation>> BL_COL_SPEC =
null; null;
@Test @Test
@ -762,9 +743,9 @@ public abstract class AbstractModelForDbgTest
AtomicReference<TargetObject> root = new AtomicReference<>(); AtomicReference<TargetObject> root = new AtomicReference<>();
AtomicReference<AllRequiredAccess> access = new AtomicReference<>(); AtomicReference<AllRequiredAccess> access = new AtomicReference<>();
AtomicReference<DbgModelTargetLauncher<?>> launcher = new AtomicReference<>(); AtomicReference<DbgModelTargetLauncher> launcher = new AtomicReference<>();
AtomicReference<TargetBreakpointContainer<?>> breaks = new AtomicReference<>(); AtomicReference<TargetBreakpointContainer> breaks = new AtomicReference<>();
AtomicReference<TargetBreakpointLocation<?>> eff = new AtomicReference<>(); AtomicReference<TargetBreakpointLocation> loc = new AtomicReference<>();
waitOn(AsyncUtils.sequence(TypeSpec.VOID).then(seq -> { waitOn(AsyncUtils.sequence(TypeSpec.VOID).then(seq -> {
m.init().handle(seq::next); m.init().handle(seq::next);
@ -776,7 +757,7 @@ public abstract class AbstractModelForDbgTest
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, access).then(seq -> { }, access).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Finding TargetLauncher..."); Msg.debug(this, "Finding TargetLauncher...");
DebugModelConventions.findSuitable(DbgModelTargetLauncher.class, root.get()) DebugModelConventions.findSuitable(DbgModelTargetLauncher.class, root.get())
@ -801,20 +782,19 @@ public abstract class AbstractModelForDbgTest
Msg.debug(this, "Getting breakpoint specs..."); Msg.debug(this, "Getting breakpoint specs...");
breaks.get() breaks.get()
.fetchElements() .fetchElements()
.thenCompose(DebugModelConventions::fetchAll)
.handle(seq::next); .handle(seq::next);
}, DebuggerObjectModel.ELEMENT_MAP_TYPE).then((specs, seq) -> { }, DebuggerObjectModel.ELEMENT_MAP_TYPE).then((specs, seq) -> {
Msg.debug(this, "Got specs: " + specs); Msg.debug(this, "Got specs: " + specs);
assertEquals(1, specs.size()); assertEquals(1, specs.size());
TargetBreakpointSpec<?> spec = specs.get("0").as(TargetBreakpointSpec.tclass); TargetBreakpointSpec spec = specs.get("0").as(TargetBreakpointSpec.class);
spec.getLocations().handle(seq::next); spec.getLocations().handle(seq::next);
}, BL_COL_SPEC).then((es, seq) -> { }, BL_COL_SPEC).then((es, seq) -> {
Msg.debug(this, "Got effectives: " + es); Msg.debug(this, "Got effectives: " + es);
assertEquals(1, es.size()); assertEquals(1, es.size());
eff.set(es.iterator().next()); loc.set(es.iterator().next());
Address addr = eff.get().getAddress(); Address addr = loc.get().getAddress();
Msg.debug(this, "Got address: " + addr); Msg.debug(this, "Got address: " + addr);
TargetObjectRefList<?> list = eff.get().getAffects(); TargetObjectList<?> list = loc.get().getAffects();
Msg.debug(this, "Got affects: " + list); Msg.debug(this, "Got affects: " + list);
assertEquals(1, list.size()); assertEquals(1, list.size());
seq.exit(); seq.exit();
@ -829,8 +809,8 @@ public abstract class AbstractModelForDbgTest
AtomicReference<TargetObject> root = new AtomicReference<>(); AtomicReference<TargetObject> root = new AtomicReference<>();
AtomicReference<AllRequiredAccess> access = new AtomicReference<>(); AtomicReference<AllRequiredAccess> access = new AtomicReference<>();
AtomicReference<TargetBreakpointContainer<?>> breaks = new AtomicReference<>(); AtomicReference<TargetBreakpointContainer> breaks = new AtomicReference<>();
AtomicReference<DbgModelTargetLauncher<?>> launcher = new AtomicReference<>(); AtomicReference<TargetLauncher> launcher = new AtomicReference<>();
AtomicReference<TargetObject> obj = new AtomicReference<>(); AtomicReference<TargetObject> obj = new AtomicReference<>();
waitOn(AsyncUtils.sequence(TypeSpec.VOID).then(seq -> { waitOn(AsyncUtils.sequence(TypeSpec.VOID).then(seq -> {
m.init().handle(seq::next); m.init().handle(seq::next);
@ -842,18 +822,20 @@ public abstract class AbstractModelForDbgTest
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, access).then(seq -> { }, access).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Finding TargetLauncher..."); Msg.debug(this, "Finding TargetLauncher...");
DebugModelConventions.findSuitable(DbgModelTargetLauncher.class, root.get()) DebugModelConventions.findSuitable(TargetLauncher.class, root.get())
.handle( .handle(
seq::next); seq::next);
}, launcher).then(seq -> { }, launcher).then(seq -> {
Msg.debug(this, "Launching..."); Msg.debug(this, "Launching...");
launcher.get().launch("notepad", "junk.txt").handle(seq::nextIgnore); launcher.get()
.launch(Map.of("args", List.of("notepad", "junk.txt")))
.handle(seq::nextIgnore);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Waiting for session access (again)..."); Msg.debug(this, "Waiting for session access (again)...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Finding breakpoint container..."); Msg.debug(this, "Finding breakpoint container...");
DebugModelConventions.findSuitable(TargetBreakpointContainer.class, root.get()) DebugModelConventions.findSuitable(TargetBreakpointContainer.class, root.get())
@ -869,20 +851,17 @@ public abstract class AbstractModelForDbgTest
model.fetchModelObject("Sessions", "[0]", "Processes", "[0]").handle(seq::next); model.fetchModelObject("Sessions", "[0]", "Processes", "[0]").handle(seq::next);
}, obj).then(seq -> { }, obj).then(seq -> {
Msg.debug(this, "Resuming..."); Msg.debug(this, "Resuming...");
TargetResumable<?> resumable = obj.get().as(TargetResumable.tclass); TargetResumable resumable = obj.get().as(TargetResumable.class);
resumable.resume().handle(seq::next); resumable.resume().handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Waiting for session access (after resume)..."); Msg.debug(this, "Waiting for session access (after resume)...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
obj.get() obj.get().fetchSubElements("Threads", "[0]", "Stack").handle(seq::next);
.fetchSubElements("Threads", "[0]", "Stack")
.thenCompose(DebugModelConventions::fetchAll)
.handle(seq::next);
}, DebuggerObjectModel.ELEMENT_MAP_TYPE).then((frames, seq) -> { }, DebuggerObjectModel.ELEMENT_MAP_TYPE).then((frames, seq) -> {
Msg.debug(this, "Got stack:"); Msg.debug(this, "Got stack:");
for (Map.Entry<String, ? extends TargetObject> ent : frames.entrySet()) { for (Map.Entry<String, ? extends TargetObject> ent : frames.entrySet()) {
TargetStackFrame<?> frame = ent.getValue().as(TargetStackFrame.tclass); TargetStackFrame frame = ent.getValue().as(TargetStackFrame.class);
Msg.debug(this, ent.getKey() + ": " + frame.getProgramCounter()); Msg.debug(this, ent.getKey() + ": " + frame.getProgramCounter());
} }
long offset = frames.get("0") long offset = frames.get("0")
@ -904,10 +883,10 @@ public abstract class AbstractModelForDbgTest
AtomicReference<TargetObject> root = new AtomicReference<>(); AtomicReference<TargetObject> root = new AtomicReference<>();
AtomicReference<AllRequiredAccess> access = new AtomicReference<>(); AtomicReference<AllRequiredAccess> access = new AtomicReference<>();
AtomicReference<DbgModelTargetLauncher<?>> launcher = new AtomicReference<>(); AtomicReference<TargetLauncher> launcher = new AtomicReference<>();
AtomicReference<TargetObject> proc = new AtomicReference<>(); AtomicReference<TargetObject> proc = new AtomicReference<>();
AtomicReference<TargetRegisterBank<?>> bank = new AtomicReference<>(); AtomicReference<TargetRegisterBank> bank = new AtomicReference<>();
Set<TargetRegister<?>> descs = new LinkedHashSet<>(); Set<TargetRegister> descs = new LinkedHashSet<>();
waitOn(AsyncUtils.sequence(TypeSpec.VOID).then(seq -> { waitOn(AsyncUtils.sequence(TypeSpec.VOID).then(seq -> {
m.init().handle(seq::next); m.init().handle(seq::next);
@ -919,7 +898,7 @@ public abstract class AbstractModelForDbgTest
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, access).then(seq -> { }, access).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Finding TargetLauncher..."); Msg.debug(this, "Finding TargetLauncher...");
DebugModelConventions.findSuitable(DbgModelTargetLauncher.class, root.get()) DebugModelConventions.findSuitable(DbgModelTargetLauncher.class, root.get())
@ -927,10 +906,12 @@ public abstract class AbstractModelForDbgTest
seq::next); seq::next);
}, launcher).then(seq -> { }, launcher).then(seq -> {
Msg.debug(this, "Launching..."); Msg.debug(this, "Launching...");
launcher.get().launch("notepad", "junk.txt").handle(seq::nextIgnore); launcher.get()
.launch(Map.of("args", List.of("notepad", "junk.txt")))
.handle(seq::nextIgnore);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Waiting for session access (again)..."); Msg.debug(this, "Waiting for session access (again)...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Getting Process 1..."); Msg.debug(this, "Getting Process 1...");
model.fetchModelObject(List.of("Sessions", "[0]", "Processes", "[0]")) model.fetchModelObject(List.of("Sessions", "[0]", "Processes", "[0]"))
@ -938,18 +919,17 @@ public abstract class AbstractModelForDbgTest
seq::next); seq::next);
}, proc).then(seq -> { }, proc).then(seq -> {
proc.get().fetchSuccessor("Threads", "[0]", "Stack", "[0]").thenAccept(top -> { proc.get().fetchSuccessor("Threads", "[0]", "Stack", "[0]").thenAccept(top -> {
bank.set(top.as(TargetRegisterBank.tclass)); bank.set(top.as(TargetRegisterBank.class));
}).handle(seq::next); }).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Got bank: " + bank.get()); Msg.debug(this, "Got bank: " + bank.get());
Msg.debug(this, "Descriptions ref: " + bank.get().getDescriptions()); Msg.debug(this, "Descriptions ref: " + bank.get().getDescriptions());
bank.get().getDescriptions().fetch().handle(seq::next); TargetRegisterContainer cont = bank.get().getDescriptions();
}, TypeSpec.cls(TargetRegisterContainer.wclass)).then((cont, seq) -> {
Msg.debug(this, "Register descriptions: " + cont); Msg.debug(this, "Register descriptions: " + cont);
cont.getRegisters().thenAccept(descs::addAll).handle(seq::next); cont.getRegisters().thenAccept(descs::addAll).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Elements: "); Msg.debug(this, "Elements: ");
for (TargetRegister<?> reg : descs) { for (TargetRegister reg : descs) {
Msg.debug(this, " " + reg.getIndex() + ": " + reg.getBitLength()); Msg.debug(this, " " + reg.getIndex() + ": " + reg.getBitLength());
} }
bank.get().readRegisters(descs).handle(seq::next); bank.get().readRegisters(descs).handle(seq::next);
@ -982,7 +962,7 @@ public abstract class AbstractModelForDbgTest
DebuggerObjectModel model = m.getModel(); DebuggerObjectModel model = m.getModel();
AtomicReference<TargetObject> root = new AtomicReference<>(); AtomicReference<TargetObject> root = new AtomicReference<>();
AtomicReference<TargetFocusScope<?>> scope = new AtomicReference<>(); AtomicReference<TargetFocusScope> scope = new AtomicReference<>();
AtomicReference<AllRequiredAccess> access = new AtomicReference<>(); AtomicReference<AllRequiredAccess> access = new AtomicReference<>();
AtomicReference<TargetObject> processes = new AtomicReference<>(); AtomicReference<TargetObject> processes = new AtomicReference<>();
AtomicReference<TargetObject> obj1 = new AtomicReference<>(); AtomicReference<TargetObject> obj1 = new AtomicReference<>();
@ -993,13 +973,13 @@ public abstract class AbstractModelForDbgTest
TargetObjectListener procListener = new TargetObjectListener() { TargetObjectListener procListener = new TargetObjectListener() {
@Override @Override
public void elementsChanged(TargetObject parent, Collection<String> removed, public void elementsChanged(TargetObject parent, Collection<String> removed,
Map<String, ? extends TargetObjectRef> added) { Map<String, ? extends TargetObject> added) {
processCount.set(processes.get().getCachedElements().size(), null); processCount.set(processes.get().getCachedElements().size(), null);
} }
}; };
TargetFocusScopeListener focusListener = new TargetFocusScopeListener() { TargetFocusScopeListener focusListener = new TargetFocusScopeListener() {
@Override @Override
public void focusChanged(TargetFocusScope<?> object, TargetObjectRef focused) { public void focusChanged(TargetFocusScope object, TargetObject focused) {
// Truncate the path to the parent process // Truncate the path to the parent process
focusProcPath.set(focused.getPath().subList(0, 2), null); focusProcPath.set(focused.getPath().subList(0, 2), null);
} }
@ -1011,13 +991,13 @@ public abstract class AbstractModelForDbgTest
Msg.debug(this, "Getting session root object"); Msg.debug(this, "Getting session root object");
model.fetchModelObject("Sessions", "[0]").handle(seq::next); model.fetchModelObject("Sessions", "[0]").handle(seq::next);
}, root).then(seq -> { }, root).then(seq -> {
scope.set(root.get().as(TargetFocusScope.tclass)); scope.set(root.get().as(TargetFocusScope.class));
scope.get().addListener(focusListener); scope.get().addListener(focusListener);
Msg.debug(this, "Tracking session access..."); Msg.debug(this, "Tracking session access...");
DebugModelConventions.trackAccessibility(root.get()).handle(seq::next); DebugModelConventions.trackAccessibility(root.get()).handle(seq::next);
}, access).then(seq -> { }, access).then(seq -> {
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Finding TargetLauncher..."); Msg.debug(this, "Finding TargetLauncher...");
DebugModelConventions.findSuitable(DbgModelTargetLauncher.class, root.get()) DebugModelConventions.findSuitable(DbgModelTargetLauncher.class, root.get())
@ -1025,12 +1005,8 @@ public abstract class AbstractModelForDbgTest
seq::next); seq::next);
}, obj1).then(seq -> { }, obj1).then(seq -> {
Msg.debug(this, "Attaching..."); Msg.debug(this, "Attaching...");
TargetAttacher<?> attacher = obj1.get().as(TargetAttacher.tclass); TargetAttacher attacher = obj1.get().as(TargetAttacher.class);
attacher.attach( attacher.attach(np.pid).handle(seq::nextIgnore);
model.createRef("Sessions", "[0]", "Available", "[" + np.pid + "]")
.as(
TargetAttachable.tclass))
.handle(seq::nextIgnore);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Getting processes container"); Msg.debug(this, "Getting processes container");
model.fetchModelObject("Sessions", "[0]", "Processes").handle(seq::next); model.fetchModelObject("Sessions", "[0]", "Processes").handle(seq::next);
@ -1042,12 +1018,12 @@ public abstract class AbstractModelForDbgTest
seq::next); seq::next);
}, obj2).then(seq -> { }, obj2).then(seq -> {
Msg.debug(this, "Creating another process"); Msg.debug(this, "Creating another process");
TargetLauncher<?> launcher = obj2.get().as(TargetLauncher.tclass); TargetLauncher launcher = obj2.get().as(TargetLauncher.class);
launcher.launch(Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, "notepad junk.txt")) launcher.launch(Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, "notepad junk.txt"))
.handle(seq::nextIgnore); .handle(seq::nextIgnore);
}).then(seq -> { }).then(seq -> {
Msg.debug(this, "Waiting for session access (again)..."); Msg.debug(this, "Waiting for session access (again)...");
access.get().waitValue(TargetAccessibility.ACCESSIBLE).handle(seq::next); access.get().waitValue(true).handle(seq::next);
}).then(seq -> { }).then(seq -> {
assertTrue(PathUtils.isAncestor(List.of("Sessions", "[0]", "Processes", "[1]"), assertTrue(PathUtils.isAncestor(List.of("Sessions", "[0]", "Processes", "[1]"),
scope.get().getFocus().getPath())); scope.get().getFocus().getPath()));
@ -1056,9 +1032,9 @@ public abstract class AbstractModelForDbgTest
Msg.debug(this, "Requesting focus on process 0"); Msg.debug(this, "Requesting focus on process 0");
AsyncFence fence = new AsyncFence(); AsyncFence fence = new AsyncFence();
TargetObjectRef i2 = model.createRef("Sessions", "[0]", "Processes", "[0]"); TargetObject p2 = model.getModelObject("Sessions", "[0]", "Processes", "[0]");
fence.include(focusProcPath.waitValue(i2.getPath())); fence.include(focusProcPath.waitValue(p2.getPath()));
fence.include(scope.get().requestFocus(i2)); fence.include(scope.get().requestFocus(p2));
fence.ready().handle(seq::next); fence.ready().handle(seq::next);
}).then(seq -> { }).then(seq -> {
assertTrue(PathUtils.isAncestor(List.of("Sessions", "[0]", "Processes", "[0]"), assertTrue(PathUtils.isAncestor(List.of("Sessions", "[0]", "Processes", "[0]"),

View file

@ -1,4 +1,3 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* *
@ -162,13 +161,13 @@ public class PopulateTraceRemote extends GhidraScript {
Set<DebuggerObjectModel> models = targets.getModels(); Set<DebuggerObjectModel> models = targets.getModels();
DebuggerObjectModel model = (DebuggerObjectModel) models.toArray()[0]; DebuggerObjectModel model = (DebuggerObjectModel) models.toArray()[0];
TargetInterpreter<?> interpreter = TargetInterpreter interpreter =
DebugModelConventions.findSuitable(TargetInterpreter.tclass, model.createRef()).get(); DebugModelConventions.findSuitable(TargetInterpreter.class, model.getModelRoot()).get();
interpreter.execute(".opendump " + f.getAbsolutePath()).get(); interpreter.execute(".opendump " + f.getAbsolutePath()).get();
interpreter.execute("g"); interpreter.execute("g");
TargetAttacher<?> attacher = TargetAttacher attacher =
DebugModelConventions.findSuitable(TargetAttacher.tclass, model.createRef()).get(); DebugModelConventions.findSuitable(TargetAttacher.class, model.getModelRoot()).get();
// TODO: Is "Available" the correct path? // TODO: Is "Available" the correct path?
attacher.attach(model.createRef("Available", "[0]").as(TargetAttachable.tclass)).get(); attacher.attach(model.getModelObject("Available", "[0]").as(TargetAttachable.class)).get();
} }
} }

View file

@ -23,7 +23,6 @@ import agent.dbgmodel.dbgmodel.main.ModelObject;
import agent.dbgmodel.gadp.impl.WrappedDbgModel; import agent.dbgmodel.gadp.impl.WrappedDbgModel;
import agent.dbgmodel.manager.DbgManager2Impl; import agent.dbgmodel.manager.DbgManager2Impl;
import agent.dbgmodel.model.impl.*; import agent.dbgmodel.model.impl.*;
import ghidra.dbg.attributes.TargetObjectRef;
import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.TargetObject;
import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils;
@ -53,7 +52,7 @@ public class DbgListElementsCommand extends AbstractDbgCommand<List<TargetObject
synchronized (access) { synchronized (access) {
updatedElements = new ArrayList<>(); updatedElements = new ArrayList<>();
List<ModelObject> list = access.getElements(path); List<ModelObject> list = access.getElements(path);
Map<String, ? extends TargetObjectRef> existingElements = Map<String, ? extends TargetObject> existingElements =
targetObject.getCachedElements(); targetObject.getCachedElements();
for (ModelObject obj : list) { for (ModelObject obj : list) {

View file

@ -32,7 +32,6 @@ import agent.dbgmodel.jna.dbgmodel.DbgModelNative.TypeKind;
import agent.dbgmodel.manager.DbgManager2Impl; import agent.dbgmodel.manager.DbgManager2Impl;
import ghidra.dbg.agent.DefaultTargetObject; import ghidra.dbg.agent.DefaultTargetObject;
import ghidra.dbg.target.*; import ghidra.dbg.target.*;
import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibility;
import ghidra.dbg.target.TargetBreakpointContainer.TargetBreakpointKindSet; import ghidra.dbg.target.TargetBreakpointContainer.TargetBreakpointKindSet;
import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointKind; import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointKind;
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState; import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
@ -49,7 +48,7 @@ public class DbgModel2TargetObjectImpl extends DefaultTargetObject<TargetObject,
protected final Map<String, TargetObject> elementsByKey = new WeakValueHashMap<>(); protected final Map<String, TargetObject> elementsByKey = new WeakValueHashMap<>();
protected DbgModelSelectableObject focus; protected DbgModelSelectableObject focus;
public TargetAccessibility accessibility = TargetAccessibility.ACCESSIBLE; public boolean accessible = true;
private ModelObject modelObject = null; private ModelObject modelObject = null;
protected Map<String, Object> intrinsics = new TreeMap<>(TargetObjectKeyComparator.ATTRIBUTE); protected Map<String, Object> intrinsics = new TreeMap<>(TargetObjectKeyComparator.ATTRIBUTE);
@ -214,11 +213,10 @@ public class DbgModel2TargetObjectImpl extends DefaultTargetObject<TargetObject,
DelegateDbgModel2TargetObject delegate = (DelegateDbgModel2TargetObject) this; DelegateDbgModel2TargetObject delegate = (DelegateDbgModel2TargetObject) this;
TargetObject proxy = delegate.getProxy(); TargetObject proxy = delegate.getProxy();
if (proxy instanceof TargetAccessConditioned) { if (proxy instanceof TargetAccessConditioned) {
attrs.put(TargetAccessConditioned.ACCESSIBLE_ATTRIBUTE_NAME, attrs.put(TargetAccessConditioned.ACCESSIBLE_ATTRIBUTE_NAME, accessible);
accessibility == TargetAccessibility.ACCESSIBLE);
} }
if (proxy instanceof TargetExecutionStateful) { if (proxy instanceof TargetExecutionStateful) {
TargetExecutionStateful<?> stateful = (TargetExecutionStateful<?>) proxy; TargetExecutionStateful stateful = (TargetExecutionStateful) proxy;
TargetExecutionState state = stateful.getExecutionState(); TargetExecutionState state = stateful.getExecutionState();
attrs.put(TargetExecutionStateful.STATE_ATTRIBUTE_NAME, state); attrs.put(TargetExecutionStateful.STATE_ATTRIBUTE_NAME, state);
} }
@ -269,12 +267,12 @@ public class DbgModel2TargetObjectImpl extends DefaultTargetObject<TargetObject,
attrs.put(TargetEnvironment.ARCH_ATTRIBUTE_NAME, executionType); attrs.put(TargetEnvironment.ARCH_ATTRIBUTE_NAME, executionType);
} }
if (proxy instanceof TargetRegister) { if (proxy instanceof TargetRegister) {
DbgModelTargetObject bank = (DbgModelTargetObject) getImplParent(); DbgModelTargetObject bank = (DbgModelTargetObject) getParent();
TargetObject container = bank.getImplParent(); TargetObject container = bank.getParent();
attrs.put(TargetRegister.CONTAINER_ATTRIBUTE_NAME, container); attrs.put(TargetRegister.CONTAINER_ATTRIBUTE_NAME, container);
} }
if (proxy instanceof TargetRegisterBank) { if (proxy instanceof TargetRegisterBank) {
attrs.put(TargetRegisterBank.DESCRIPTIONS_ATTRIBUTE_NAME, getImplParent()); attrs.put(TargetRegisterBank.DESCRIPTIONS_ATTRIBUTE_NAME, getParent());
} }
if (proxy instanceof TargetStackFrame) { if (proxy instanceof TargetStackFrame) {
DbgModelTargetStackFrame frame = (DbgModelTargetStackFrame) proxy; DbgModelTargetStackFrame frame = (DbgModelTargetStackFrame) proxy;
@ -358,7 +356,7 @@ public class DbgModel2TargetObjectImpl extends DefaultTargetObject<TargetObject,
} }
DbgModelTargetObject test = (DbgModelTargetObject) parent; DbgModelTargetObject test = (DbgModelTargetObject) parent;
while (test != null && !(test.getProxy() instanceof DbgModelTargetSession)) { while (test != null && !(test.getProxy() instanceof DbgModelTargetSession)) {
test = (DbgModelTargetObject) test.getImplParent(); test = (DbgModelTargetObject) test.getParent();
} }
return test == null ? null : (DbgModelTargetSession) test.getProxy(); return test == null ? null : (DbgModelTargetSession) test.getProxy();
} }
@ -367,7 +365,7 @@ public class DbgModel2TargetObjectImpl extends DefaultTargetObject<TargetObject,
public DbgModelTargetProcess getParentProcess() { public DbgModelTargetProcess getParentProcess() {
DbgModelTargetObject test = (DbgModelTargetObject) parent; DbgModelTargetObject test = (DbgModelTargetObject) parent;
while (test != null && !(test.getProxy() instanceof TargetProcess)) { while (test != null && !(test.getProxy() instanceof TargetProcess)) {
test = (DbgModelTargetObject) test.getImplParent(); test = (DbgModelTargetObject) test.getParent();
} }
return test == null ? null : (DbgModelTargetProcess) test.getProxy(); return test == null ? null : (DbgModelTargetProcess) test.getProxy();
} }
@ -376,7 +374,7 @@ public class DbgModel2TargetObjectImpl extends DefaultTargetObject<TargetObject,
public DbgModelTargetThread getParentThread() { public DbgModelTargetThread getParentThread() {
DbgModelTargetObject test = (DbgModelTargetObject) parent; DbgModelTargetObject test = (DbgModelTargetObject) parent;
while (test != null && !(test.getProxy() instanceof TargetThread)) { while (test != null && !(test.getProxy() instanceof TargetThread)) {
test = (DbgModelTargetObject) test.getImplParent(); test = (DbgModelTargetObject) test.getParent();
} }
return test == null ? null : (DbgModelTargetThread) test.getProxy(); return test == null ? null : (DbgModelTargetThread) test.getProxy();
} }

View file

@ -336,8 +336,8 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
getModel().fetchModelValue(objPath).handle(seq::next); getModel().fetchModelValue(objPath).handle(seq::next);
}, TypeSpec.cls(Object.class)).then((obj, seq) -> { }, TypeSpec.cls(Object.class)).then((obj, seq) -> {
if (obj instanceof DbgModelTargetExecutionStateful) { if (obj instanceof DbgModelTargetExecutionStateful) {
DbgModelTargetExecutionStateful<?> stateful = DbgModelTargetExecutionStateful stateful =
(DbgModelTargetExecutionStateful<?>) obj; (DbgModelTargetExecutionStateful) obj;
TargetExecutionState execState = stateful.convertState(state); TargetExecutionState execState = stateful.convertState(state);
stateful.setExecutionState(execState, reason); stateful.setExecutionState(execState, reason);
} }
@ -379,7 +379,7 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
} }
listeners.fire(TargetBreakpointListener.class) listeners.fire(TargetBreakpointListener.class)
.breakpointHit((TargetBreakpointContainer<?>) bpt.getParent(), .breakpointHit((TargetBreakpointContainer) bpt.getParent(),
getParentProcess(), null, bpt, bpt); getParentProcess(), null, bpt, bpt);
bpt.breakpointHit(); bpt.breakpointHit();
}); });
@ -492,13 +492,12 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
} }
@Override @Override
public TargetAccessibility getAccessibility() { public boolean isAccessible() {
return accessibility; return accessible;
} }
@Override @Override
public void setAccessibility(TargetAccessibility accessibility) { public void setAccessible(boolean accessible) {
this.accessibility = accessibility; this.accessible = accessible;
} }
} }

View file

@ -23,7 +23,7 @@ import agent.dbgeng.model.iface1.DbgModelTargetInterruptible;
import agent.dbgeng.model.iface2.DbgModelTargetObject; import agent.dbgeng.model.iface2.DbgModelTargetObject;
public class DbgModel2TargetSystemMarkerImpl extends DbgModel2TargetObjectImpl public class DbgModel2TargetSystemMarkerImpl extends DbgModel2TargetObjectImpl
implements DbgModelTargetInterruptible<DbgModel2TargetSystemMarkerImpl> { implements DbgModelTargetInterruptible {
// NB: this is an invisible marker whose only purpose if to enable an // NB: this is an invisible marker whose only purpose if to enable an
// interrupt when connecting in kernel-mode to a running target // interrupt when connecting in kernel-mode to a running target

View file

@ -19,7 +19,6 @@ import java.lang.invoke.MethodHandles;
import java.lang.ref.Cleaner; import java.lang.ref.Cleaner;
import java.lang.ref.Cleaner.Cleanable; import java.lang.ref.Cleaner.Cleanable;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture;
import agent.dbgeng.manager.*; import agent.dbgeng.manager.*;
import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo; import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo;
@ -27,16 +26,14 @@ import agent.dbgeng.model.iface1.*;
import agent.dbgeng.model.iface2.*; import agent.dbgeng.model.iface2.*;
import agent.dbgmodel.dbgmodel.main.ModelObject; import agent.dbgmodel.dbgmodel.main.ModelObject;
import agent.dbgmodel.jna.dbgmodel.DbgModelNative.ModelObjectKind; import agent.dbgmodel.jna.dbgmodel.DbgModelNative.ModelObjectKind;
import ghidra.async.AsyncUtils;
import ghidra.dbg.attributes.TargetObjectRef;
import ghidra.dbg.target.*; import ghidra.dbg.target.*;
import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointAction; import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointAction;
import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils;
import ghidra.util.datastruct.ListenerSet; import ghidra.util.datastruct.ListenerSet;
public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl implements // public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl implements //
DbgModelTargetAccessConditioned<DelegateDbgModel2TargetObject>, // DbgModelTargetAccessConditioned, //
DbgModelTargetExecutionStateful<DelegateDbgModel2TargetObject>, // DbgModelTargetExecutionStateful, //
DbgModel2TargetProxy, DbgModelTargetBptHelper { DbgModel2TargetProxy, DbgModelTargetBptHelper {
// Probably don-t need any of the handler-map or annotation stuff // Probably don-t need any of the handler-map or annotation stuff
@ -198,7 +195,7 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
} }
public DelegateDbgModel2TargetObject clone(String key, ModelObject modelObject) { public DelegateDbgModel2TargetObject clone(String key, ModelObject modelObject) {
DbgModelTargetObject p = (DbgModelTargetObject) getImplParent(); DbgModelTargetObject p = (DbgModelTargetObject) getParent();
List<Class<? extends TargetObject>> mixins = new ArrayList<>(); List<Class<? extends TargetObject>> mixins = new ArrayList<>();
Class<? extends DbgModelTargetObject> mixin = lookupWrapperType(key, p.getName()); Class<? extends DbgModelTargetObject> mixin = lookupWrapperType(key, p.getName());
if (mixin != null) { if (mixin != null) {
@ -209,27 +206,11 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
return delegate; return delegate;
} }
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public CompletableFuture<? extends DelegateDbgModel2TargetObject> fetch() {
return (CompletableFuture) CompletableFuture.completedFuture(proxy);
}
@Override @Override
public DbgModelTargetObject getProxy() { public DbgModelTargetObject getProxy() {
return (DbgModelTargetObject) proxy; return (DbgModelTargetObject) proxy;
} }
@SuppressWarnings("unchecked")
@Override
public CompletableFuture<? extends DelegateDbgModel2TargetObject> fetchParent() {
TargetObjectRef p = getParent();
if (p == null) {
return AsyncUtils.nil();
}
return (CompletableFuture<? extends DelegateDbgModel2TargetObject>) p.fetch();
}
protected static String getHintForObject(ModelObject obj) { protected static String getHintForObject(ModelObject obj) {
ModelObjectKind kind = obj.getKind(); ModelObjectKind kind = obj.getKind();
String ret = kind == null ? "" : kind.name(); String ret = kind == null ? "" : kind.name();
@ -309,35 +290,34 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
public void onRunning() { public void onRunning() {
invalidate(); invalidate();
setAccessibility(TargetAccessibility.INACCESSIBLE); setAccessible(false);
} }
public void onStopped() { public void onStopped() {
setAccessibility(TargetAccessibility.ACCESSIBLE); setAccessible(true);
update(); update();
} }
public void onExit() { public void onExit() {
setAccessibility(TargetAccessibility.ACCESSIBLE); setAccessible(true);
} }
@Override @Override
public TargetAccessibility getAccessibility() { public boolean isAccessible() {
return accessibility; return accessible;
} }
@Override @Override
public void setAccessibility(TargetAccessibility accessibility) { public void setAccessible(boolean accessible) {
synchronized (attributes) { synchronized (attributes) {
if (this.accessibility == accessibility) { if (this.accessible == accessible) {
return; return;
} }
this.accessibility = accessibility; this.accessible = accessible;
} }
if (proxy instanceof TargetAccessConditioned) { if (proxy instanceof TargetAccessConditioned) {
changeAttributes(List.of(), List.of(), Map.of( // changeAttributes(List.of(), List.of(), Map.of( //
TargetAccessConditioned.ACCESSIBLE_ATTRIBUTE_NAME, TargetAccessConditioned.ACCESSIBLE_ATTRIBUTE_NAME, accessible //
accessibility == TargetAccessibility.ACCESSIBLE //
), "Accessibility changed"); ), "Accessibility changed");
} }
} }

View file

@ -26,7 +26,6 @@ import ghidra.async.AsyncUtils;
import ghidra.dbg.DebuggerModelClosedReason; import ghidra.dbg.DebuggerModelClosedReason;
import ghidra.dbg.agent.AbstractDebuggerObjectModel; import ghidra.dbg.agent.AbstractDebuggerObjectModel;
import ghidra.dbg.error.DebuggerUserException; import ghidra.dbg.error.DebuggerUserException;
import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibility;
import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.AnnotatedSchemaContext; import ghidra.dbg.target.schema.AnnotatedSchemaContext;
import ghidra.dbg.target.schema.TargetObjectSchema; import ghidra.dbg.target.schema.TargetObjectSchema;
@ -102,11 +101,11 @@ public class GdbModelImpl extends AbstractDebuggerObjectModel {
} }
case RUNNING: { case RUNNING: {
session.invalidateMemoryAndRegisterCaches(); session.invalidateMemoryAndRegisterCaches();
session.setAccessibility(TargetAccessibility.INACCESSIBLE); session.setAccessible(false);
break; break;
} }
case STOPPED: { case STOPPED: {
session.setAccessibility(TargetAccessibility.ACCESSIBLE); session.setAccessible(true);
break; break;
} }
case EXIT: { case EXIT: {

View file

@ -17,8 +17,8 @@ package agent.gdb.model.impl;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import ghidra.dbg.attributes.TargetObjectRef; import ghidra.dbg.target.TargetObject;
interface GdbModelSelectableObject extends TargetObjectRef { interface GdbModelSelectableObject extends TargetObject {
CompletableFuture<Void> select(); CompletableFuture<Void> select();
} }

View file

@ -25,14 +25,17 @@ import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils;
@TargetObjectSchemaInfo(name = "Attachable", elements = { @TargetObjectSchemaInfo(
@TargetElementType(type = Void.class) name = "Attachable",
}, attributes = { elements = {
@TargetAttributeType(type = Void.class) @TargetElementType(type = Void.class)
}) },
attributes = {
@TargetAttributeType(type = Void.class)
})
public class GdbModelTargetAttachable public class GdbModelTargetAttachable
extends DefaultTargetObject<TargetObject, GdbModelTargetAvailableContainer> extends DefaultTargetObject<TargetObject, GdbModelTargetAvailableContainer>
implements TargetAttachable<GdbModelTargetAttachable> { implements TargetAttachable {
protected static final String PID_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "pid"; protected static final String PID_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "pid";
// TODO: DESCRIPTION, TYPE, USER? // TODO: DESCRIPTION, TYPE, USER?

View file

@ -26,9 +26,12 @@ import ghidra.dbg.target.schema.TargetAttributeType;
import ghidra.dbg.target.schema.TargetObjectSchemaInfo; import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
import ghidra.util.datastruct.WeakValueHashMap; import ghidra.util.datastruct.WeakValueHashMap;
@TargetObjectSchemaInfo(name = "AvailableContainer", attributes = { @TargetObjectSchemaInfo(
@TargetAttributeType(type = Void.class) name = "AvailableContainer",
}, canonicalContainer = true) attributes = {
@TargetAttributeType(type = Void.class)
},
canonicalContainer = true)
public class GdbModelTargetAvailableContainer public class GdbModelTargetAvailableContainer
extends DefaultTargetObject<GdbModelTargetAttachable, GdbModelTargetSession> { extends DefaultTargetObject<GdbModelTargetAttachable, GdbModelTargetSession> {
public static final String NAME = "Available"; public static final String NAME = "Available";

View file

@ -34,13 +34,15 @@ import ghidra.program.model.address.AddressRange;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.datastruct.WeakValueHashMap; import ghidra.util.datastruct.WeakValueHashMap;
@TargetObjectSchemaInfo(name = "BreakpointContainer", attributes = { @TargetObjectSchemaInfo(
@TargetAttributeType(type = Void.class) name = "BreakpointContainer",
}, canonicalContainer = true) attributes = {
@TargetAttributeType(type = Void.class)
},
canonicalContainer = true)
public class GdbModelTargetBreakpointContainer public class GdbModelTargetBreakpointContainer
extends DefaultTargetObject<GdbModelTargetBreakpointSpec, GdbModelTargetSession> extends DefaultTargetObject<GdbModelTargetBreakpointSpec, GdbModelTargetSession>
implements TargetBreakpointContainer<GdbModelTargetBreakpointContainer>, implements TargetBreakpointContainer, GdbEventsListenerAdapter {
GdbEventsListenerAdapter {
public static final String NAME = "Breakpoints"; public static final String NAME = "Breakpoints";
protected static final TargetBreakpointKindSet SUPPORTED_KINDS = protected static final TargetBreakpointKindSet SUPPORTED_KINDS =

View file

@ -25,22 +25,25 @@ import agent.gdb.manager.parsing.GdbCValueParser;
import agent.gdb.manager.parsing.GdbParsingUtils.GdbParseError; import agent.gdb.manager.parsing.GdbParsingUtils.GdbParseError;
import generic.Unique; import generic.Unique;
import ghidra.dbg.agent.DefaultTargetObject; import ghidra.dbg.agent.DefaultTargetObject;
import ghidra.dbg.attributes.TargetObjectRefList; import ghidra.dbg.attributes.TargetObjectList;
import ghidra.dbg.attributes.TargetObjectRefList.DefaultTargetObjectRefList; import ghidra.dbg.attributes.TargetObjectList.DefaultTargetObjectList;
import ghidra.dbg.target.TargetBreakpointLocation; import ghidra.dbg.target.TargetBreakpointLocation;
import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
@TargetObjectSchemaInfo(name = "BreakpointLocation", elements = { @TargetObjectSchemaInfo(
@TargetElementType(type = Void.class) name = "BreakpointLocation",
}, attributes = { elements = {
@TargetAttributeType(type = Void.class) @TargetElementType(type = Void.class)
}) },
attributes = {
@TargetAttributeType(type = Void.class)
})
public class GdbModelTargetBreakpointLocation public class GdbModelTargetBreakpointLocation
extends DefaultTargetObject<TargetObject, GdbModelTargetBreakpointSpec> extends DefaultTargetObject<TargetObject, GdbModelTargetBreakpointSpec>
implements TargetBreakpointLocation<GdbModelTargetBreakpointLocation> { implements TargetBreakpointLocation {
protected static String indexLocation(GdbBreakpointLocation loc) { protected static String indexLocation(GdbBreakpointLocation loc) {
return PathUtils.makeIndex(loc.getSub()); return PathUtils.makeIndex(loc.getSub());
} }
@ -54,7 +57,7 @@ public class GdbModelTargetBreakpointLocation
protected Address address; protected Address address;
protected Integer length; protected Integer length;
protected final TargetObjectRefList<GdbModelTargetInferior> affects; protected final TargetObjectList<GdbModelTargetInferior> affects;
protected String display; protected String display;
public GdbModelTargetBreakpointLocation(GdbModelTargetBreakpointSpec spec, public GdbModelTargetBreakpointLocation(GdbModelTargetBreakpointSpec spec,
@ -133,15 +136,15 @@ public class GdbModelTargetBreakpointLocation
return length; return length;
} }
protected TargetObjectRefList<GdbModelTargetInferior> doGetAffects() { protected TargetObjectList<GdbModelTargetInferior> doGetAffects() {
return loc.getInferiorIds() return loc.getInferiorIds()
.stream() .stream()
.map(impl.session.inferiors::getTargetInferior) .map(impl.session.inferiors::getTargetInferior)
.collect(Collectors.toCollection(DefaultTargetObjectRefList::new)); .collect(Collectors.toCollection(DefaultTargetObjectList::new));
} }
@Override @Override
public TargetObjectRefList<GdbModelTargetInferior> getAffects() { public TargetObjectList<GdbModelTargetInferior> getAffects() {
return affects; return affects;
} }

View file

@ -34,13 +34,15 @@ import ghidra.util.Msg;
import ghidra.util.datastruct.ListenerSet; import ghidra.util.datastruct.ListenerSet;
import ghidra.util.datastruct.WeakValueHashMap; import ghidra.util.datastruct.WeakValueHashMap;
@TargetObjectSchemaInfo(name = "BreakpointSpec", attributes = { @TargetObjectSchemaInfo(
@TargetAttributeType(type = Void.class) name = "BreakpointSpec",
}, canonicalContainer = true) attributes = {
@TargetAttributeType(type = Void.class)
},
canonicalContainer = true)
public class GdbModelTargetBreakpointSpec extends public class GdbModelTargetBreakpointSpec extends
DefaultTargetObject<GdbModelTargetBreakpointLocation, GdbModelTargetBreakpointContainer> DefaultTargetObject<GdbModelTargetBreakpointLocation, GdbModelTargetBreakpointContainer>
implements TargetBreakpointSpec<GdbModelTargetBreakpointSpec>, implements TargetBreakpointSpec, TargetDeletable {
TargetDeletable<GdbModelTargetBreakpointSpec> {
protected static String indexBreakpoint(GdbBreakpointInfo info) { protected static String indexBreakpoint(GdbBreakpointInfo info) {
return PathUtils.makeIndex(info.getNumber()); return PathUtils.makeIndex(info.getNumber());

View file

@ -25,14 +25,17 @@ import ghidra.dbg.target.TargetEnvironment;
import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
@TargetObjectSchemaInfo(name = "Environment", elements = { @TargetObjectSchemaInfo(
@TargetElementType(type = Void.class) name = "Environment",
}, attributes = { elements = {
@TargetAttributeType(type = Void.class) @TargetElementType(type = Void.class)
}) },
attributes = {
@TargetAttributeType(type = Void.class)
})
public class GdbModelTargetEnvironment public class GdbModelTargetEnvironment
extends DefaultTargetObject<TargetObject, GdbModelTargetInferior> extends DefaultTargetObject<TargetObject, GdbModelTargetInferior>
implements TargetEnvironment<GdbModelTargetEnvironment> { implements TargetEnvironment {
public static final String NAME = "Environment"; public static final String NAME = "Environment";
public static final String VISIBLE_ARCH_ATTRIBUTE_NAME = "arch"; public static final String VISIBLE_ARCH_ATTRIBUTE_NAME = "arch";

View file

@ -22,8 +22,6 @@ import agent.gdb.manager.GdbInferior;
import agent.gdb.manager.GdbManager.ExecSuffix; import agent.gdb.manager.GdbManager.ExecSuffix;
import ghidra.async.AsyncFence; import ghidra.async.AsyncFence;
import ghidra.dbg.agent.DefaultTargetObject; import ghidra.dbg.agent.DefaultTargetObject;
import ghidra.dbg.attributes.TargetObjectRef;
import ghidra.dbg.attributes.TypedTargetObjectRef;
import ghidra.dbg.error.DebuggerModelNoSuchPathException; import ghidra.dbg.error.DebuggerModelNoSuchPathException;
import ghidra.dbg.error.DebuggerModelTypeException; import ghidra.dbg.error.DebuggerModelTypeException;
import ghidra.dbg.target.*; import ghidra.dbg.target.*;
@ -40,18 +38,10 @@ import ghidra.util.Msg;
attributes = { attributes = {
@TargetAttributeType(type = Void.class) }) @TargetAttributeType(type = Void.class) })
public class GdbModelTargetInferior public class GdbModelTargetInferior
extends DefaultTargetObject<TargetObject, GdbModelTargetInferiorContainer> implements // extends DefaultTargetObject<TargetObject, GdbModelTargetInferiorContainer>
TargetProcess<GdbModelTargetInferior>, // implements TargetProcess, TargetAggregate, TargetExecutionStateful, TargetAttacher,
TargetAggregate, // TargetDeletable, TargetDetachable, TargetKillable, TargetCmdLineLauncher, TargetResumable,
TargetExecutionStateful<GdbModelTargetInferior>, // TargetSteppable, GdbModelSelectableObject {
TargetAttacher<GdbModelTargetInferior>, //
TargetDeletable<GdbModelTargetInferior>, //
TargetDetachable<GdbModelTargetInferior>, //
TargetKillable<GdbModelTargetInferior>, //
TargetCmdLineLauncher<GdbModelTargetInferior>, //
TargetResumable<GdbModelTargetInferior>, //
TargetSteppable<GdbModelTargetInferior>, //
GdbModelSelectableObject {
public static final String EXIT_CODE_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "exit_code"; public static final String EXIT_CODE_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "exit_code";
@ -186,16 +176,17 @@ public class GdbModelTargetInferior
} }
@Override @Override
public CompletableFuture<Void> attach(TypedTargetObjectRef<? extends TargetAttachable<?>> ref) { public CompletableFuture<Void> attach(TargetAttachable attachable) {
impl.assertMine(TargetObjectRef.class, ref); impl.assertMine(TargetObject.class, attachable);
// NOTE: These can change at any time. Just use the path to derive the target PID // NOTE: These can change at any time. Just use the path to derive the target PID
if (!Objects.equals(PathUtils.parent(ref.getPath()), impl.session.available.getPath())) { if (!Objects.equals(PathUtils.parent(attachable.getPath()),
impl.session.available.getPath())) {
throw new DebuggerModelTypeException( throw new DebuggerModelTypeException(
"Target of attach must be a child of " + impl.session.available.getPath()); "Target of attach must be a child of " + impl.session.available.getPath());
} }
long pid; long pid;
try { try {
pid = Long.parseLong(ref.getIndex()); pid = Long.parseLong(attachable.getIndex());
} }
catch (IllegalArgumentException e) { catch (IllegalArgumentException e) {
throw new DebuggerModelNoSuchPathException("Badly-formatted PID", e); throw new DebuggerModelNoSuchPathException("Badly-formatted PID", e);

View file

@ -26,14 +26,17 @@ import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
@TargetObjectSchemaInfo(name = "MemoryRegion", elements = { @TargetObjectSchemaInfo(
@TargetElementType(type = Void.class) name = "MemoryRegion",
}, attributes = { elements = {
@TargetAttributeType(type = Void.class) @TargetElementType(type = Void.class)
}) },
attributes = {
@TargetAttributeType(type = Void.class)
})
public class GdbModelTargetMemoryRegion public class GdbModelTargetMemoryRegion
extends DefaultTargetObject<TargetObject, GdbModelTargetProcessMemory> extends DefaultTargetObject<TargetObject, GdbModelTargetProcessMemory>
implements TargetMemoryRegion<GdbModelTargetMemoryRegion> { implements TargetMemoryRegion {
protected static final String OBJFILE_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "objfile"; protected static final String OBJFILE_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "objfile";
protected static final String OFFSET_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "offset"; protected static final String OFFSET_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "offset";
@ -121,7 +124,11 @@ public class GdbModelTargetMemoryRegion
return true; // TODO return true; // TODO
} }
@TargetAttributeType(name = OBJFILE_ATTRIBUTE_NAME, required = true, fixed = true, hidden = true) @TargetAttributeType(
name = OBJFILE_ATTRIBUTE_NAME,
required = true,
fixed = true,
hidden = true)
public String getObjfile() { public String getObjfile() {
return objfile; return objfile;
} }

View file

@ -29,14 +29,17 @@ import ghidra.dbg.util.PathUtils;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.util.Msg; import ghidra.util.Msg;
@TargetObjectSchemaInfo(name = "Module", elements = { // @TargetObjectSchemaInfo(
@TargetElementType(type = Void.class) // name = "Module",
}, attributes = { // elements = { //
@TargetAttributeType(type = Void.class) // @TargetElementType(type = Void.class) //
}) },
attributes = { //
@TargetAttributeType(type = Void.class) //
})
public class GdbModelTargetModule public class GdbModelTargetModule
extends DefaultTargetObject<TargetObject, GdbModelTargetModuleContainer> extends DefaultTargetObject<TargetObject, GdbModelTargetModuleContainer>
implements TargetModule<GdbModelTargetModule> { implements TargetModule {
public static final String VISIBLE_RANGE_ATTRIBUTE_NAME = "range"; public static final String VISIBLE_RANGE_ATTRIBUTE_NAME = "range";
public static final String VISIBLE_MODULE_NAME_ATTRIBUTE_NAME = "module name"; public static final String VISIBLE_MODULE_NAME_ATTRIBUTE_NAME = "module name";

View file

@ -40,7 +40,7 @@ import ghidra.util.Msg;
canonicalContainer = true) canonicalContainer = true)
public class GdbModelTargetModuleContainer public class GdbModelTargetModuleContainer
extends DefaultTargetObject<GdbModelTargetModule, GdbModelTargetInferior> extends DefaultTargetObject<GdbModelTargetModule, GdbModelTargetInferior>
implements TargetModuleContainer<GdbModelTargetModuleContainer> { implements TargetModuleContainer {
// NOTE: -file-list-shared-libraries omits the main module and system-supplied DSO. // NOTE: -file-list-shared-libraries omits the main module and system-supplied DSO.
public static final String NAME = "Modules"; public static final String NAME = "Modules";
@ -78,7 +78,7 @@ public class GdbModelTargetModuleContainer
} }
@Override @Override
public CompletableFuture<? extends TargetModule<?>> addSyntheticModule(String name) { public CompletableFuture<? extends TargetModule> addSyntheticModule(String name) {
throw new DebuggerUserException("GDB Does not support synthetic modules"); throw new DebuggerUserException("GDB Does not support synthetic modules");
} }

View file

@ -38,12 +38,15 @@ import ghidra.program.model.address.*;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.datastruct.WeakValueHashMap; import ghidra.util.datastruct.WeakValueHashMap;
@TargetObjectSchemaInfo(name = "Memory", attributes = { @TargetObjectSchemaInfo(
@TargetAttributeType(type = Void.class) name = "Memory",
}, canonicalContainer = true) attributes = {
@TargetAttributeType(type = Void.class)
},
canonicalContainer = true)
public class GdbModelTargetProcessMemory public class GdbModelTargetProcessMemory
extends DefaultTargetObject<GdbModelTargetMemoryRegion, GdbModelTargetInferior> extends DefaultTargetObject<GdbModelTargetMemoryRegion, GdbModelTargetInferior>
implements TargetMemory<GdbModelTargetProcessMemory> { implements TargetMemory {
public static final String NAME = "Memory"; public static final String NAME = "Memory";
protected final GdbModelImpl impl; protected final GdbModelImpl impl;

View file

@ -25,14 +25,17 @@ import ghidra.dbg.target.TargetRegister;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils;
@TargetObjectSchemaInfo(name = "RegisterDescriptor", elements = { @TargetObjectSchemaInfo(
@TargetElementType(type = Void.class) name = "RegisterDescriptor",
}, attributes = { elements = {
@TargetAttributeType(type = Void.class) @TargetElementType(type = Void.class)
}) },
attributes = {
@TargetAttributeType(type = Void.class)
})
public class GdbModelTargetRegister public class GdbModelTargetRegister
extends DefaultTargetObject<TargetObject, GdbModelTargetRegisterContainer> extends DefaultTargetObject<TargetObject, GdbModelTargetRegisterContainer>
implements TargetRegister<GdbModelTargetRegister> { implements TargetRegister {
protected static String indexRegister(GdbRegister register) { protected static String indexRegister(GdbRegister register) {
String name = register.getName(); String name = register.getName();

View file

@ -29,12 +29,15 @@ import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.datastruct.WeakValueHashMap; import ghidra.util.datastruct.WeakValueHashMap;
@TargetObjectSchemaInfo(name = "RegisterContainer", attributes = { @TargetObjectSchemaInfo(
@TargetAttributeType(type = Void.class) name = "RegisterContainer",
}, canonicalContainer = true) attributes = {
@TargetAttributeType(type = Void.class)
},
canonicalContainer = true)
public class GdbModelTargetRegisterContainer public class GdbModelTargetRegisterContainer
extends DefaultTargetObject<GdbModelTargetRegister, GdbModelTargetInferior> extends DefaultTargetObject<GdbModelTargetRegister, GdbModelTargetInferior>
implements TargetRegisterContainer<GdbModelTargetRegisterContainer> { implements TargetRegisterContainer {
public static final String NAME = "Registers"; public static final String NAME = "Registers";
protected final GdbModelImpl impl; protected final GdbModelImpl impl;

View file

@ -26,14 +26,17 @@ import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
@TargetObjectSchemaInfo(name = "Section", elements = { @TargetObjectSchemaInfo(
@TargetElementType(type = Void.class) name = "Section",
}, attributes = { elements = {
@TargetAttributeType(type = Void.class) @TargetElementType(type = Void.class)
}) },
attributes = {
@TargetAttributeType(type = Void.class)
})
public class GdbModelTargetSection public class GdbModelTargetSection
extends DefaultTargetObject<TargetObject, GdbModelTargetSectionContainer> extends DefaultTargetObject<TargetObject, GdbModelTargetSectionContainer>
implements TargetSection<GdbModelTargetSection> { implements TargetSection {
public static final String VISIBLE_RANGE_ATTRIBUTE_NAME = "range"; public static final String VISIBLE_RANGE_ATTRIBUTE_NAME = "range";

View file

@ -26,9 +26,12 @@ import ghidra.dbg.target.schema.TargetAttributeType;
import ghidra.dbg.target.schema.TargetObjectSchemaInfo; import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
import ghidra.util.datastruct.WeakValueHashMap; import ghidra.util.datastruct.WeakValueHashMap;
@TargetObjectSchemaInfo(name = "SectionContainer", attributes = { @TargetObjectSchemaInfo(
@TargetAttributeType(type = Void.class) name = "SectionContainer",
}, canonicalContainer = true) attributes = {
@TargetAttributeType(type = Void.class)
},
canonicalContainer = true)
public class GdbModelTargetSectionContainer public class GdbModelTargetSectionContainer
extends DefaultTargetObject<GdbModelTargetSection, GdbModelTargetModule> { extends DefaultTargetObject<GdbModelTargetSection, GdbModelTargetModule> {
public static final String NAME = "Sections"; public static final String NAME = "Sections";

View file

@ -21,11 +21,7 @@ import java.util.concurrent.CompletableFuture;
import agent.gdb.manager.*; import agent.gdb.manager.*;
import ghidra.async.AsyncUtils; import ghidra.async.AsyncUtils;
import ghidra.dbg.DebuggerObjectModel;
import ghidra.dbg.agent.AbstractTargetObject;
import ghidra.dbg.agent.DefaultTargetModelRoot; import ghidra.dbg.agent.DefaultTargetModelRoot;
import ghidra.dbg.attributes.TargetObjectRef;
import ghidra.dbg.attributes.TypedTargetObjectRef;
import ghidra.dbg.error.DebuggerIllegalArgumentException; import ghidra.dbg.error.DebuggerIllegalArgumentException;
import ghidra.dbg.target.*; import ghidra.dbg.target.*;
import ghidra.dbg.target.TargetLauncher.TargetCmdLineLauncher; import ghidra.dbg.target.TargetLauncher.TargetCmdLineLauncher;
@ -41,16 +37,10 @@ import ghidra.util.Msg;
attributes = { attributes = {
@TargetAttributeType(type = Void.class) @TargetAttributeType(type = Void.class)
}) })
public class GdbModelTargetSession extends DefaultTargetModelRoot implements // public class GdbModelTargetSession extends DefaultTargetModelRoot implements
TargetAccessConditioned<GdbModelTargetSession>, TargetAccessConditioned, TargetAttacher, TargetFocusScope, TargetInterpreter,
TargetAttacher<GdbModelTargetSession>, TargetInterruptible, TargetCmdLineLauncher, TargetEventScope,
TargetFocusScope<GdbModelTargetSession>, GdbConsoleOutputListener, GdbEventsListenerAdapter {
TargetInterpreter<GdbModelTargetSession>,
TargetInterruptible<GdbModelTargetSession>,
TargetCmdLineLauncher<GdbModelTargetSession>,
TargetEventScope<GdbModelTargetSession>,
GdbConsoleOutputListener,
GdbEventsListenerAdapter {
protected static final String GDB_PROMPT = "(gdb)"; protected static final String GDB_PROMPT = "(gdb)";
protected final GdbModelImpl impl; protected final GdbModelImpl impl;
@ -60,7 +50,7 @@ public class GdbModelTargetSession extends DefaultTargetModelRoot implements //
protected final GdbModelTargetAvailableContainer available; protected final GdbModelTargetAvailableContainer available;
protected final GdbModelTargetBreakpointContainer breakpoints; protected final GdbModelTargetBreakpointContainer breakpoints;
private TargetAccessibility accessibility = TargetAccessibility.ACCESSIBLE; private boolean accessible = true;
protected GdbModelSelectableObject focus; protected GdbModelSelectableObject focus;
protected String debugger = "gdb"; // Used by GdbModelTargetEnvironment protected String debugger = "gdb"; // Used by GdbModelTargetEnvironment
@ -77,7 +67,7 @@ public class GdbModelTargetSession extends DefaultTargetModelRoot implements //
inferiors.getName(), inferiors, // inferiors.getName(), inferiors, //
available.getName(), available, // available.getName(), available, //
breakpoints.getName(), breakpoints, // breakpoints.getName(), breakpoints, //
ACCESSIBLE_ATTRIBUTE_NAME, accessibility == TargetAccessibility.ACCESSIBLE, // ACCESSIBLE_ATTRIBUTE_NAME, accessible, //
PROMPT_ATTRIBUTE_NAME, GDB_PROMPT, // PROMPT_ATTRIBUTE_NAME, GDB_PROMPT, //
DISPLAY_ATTRIBUTE_NAME, display, // DISPLAY_ATTRIBUTE_NAME, display, //
TargetMethod.PARAMETERS_ATTRIBUTE_NAME, TargetCmdLineLauncher.PARAMETERS, // TargetMethod.PARAMETERS_ATTRIBUTE_NAME, TargetCmdLineLauncher.PARAMETERS, //
@ -167,22 +157,22 @@ public class GdbModelTargetSession extends DefaultTargetModelRoot implements //
setFocus(f); setFocus(f);
} }
public void setAccessibility(TargetAccessibility accessibility) { public void setAccessible(boolean accessible) {
synchronized (attributes) { synchronized (attributes) {
if (this.accessibility == accessibility) { if (this.accessible == accessible) {
return; return;
} }
this.accessibility = accessibility; this.accessible = accessible;
changeAttributes(List.of(), Map.of( // changeAttributes(List.of(), Map.of( //
ACCESSIBLE_ATTRIBUTE_NAME, accessibility == TargetAccessibility.ACCESSIBLE // ACCESSIBLE_ATTRIBUTE_NAME, accessible //
), "Accessibility changed"); ), "Accessibility changed");
} }
listeners.fire(TargetAccessibilityListener.class).accessibilityChanged(this, accessibility); listeners.fire(TargetAccessibilityListener.class).accessibilityChanged(this, accessible);
} }
@Override @Override
public TargetAccessibility getAccessibility() { public boolean isAccessible() {
return accessibility; return accessible;
} }
@Override @Override
@ -194,17 +184,10 @@ public class GdbModelTargetSession extends DefaultTargetModelRoot implements //
} }
@Override @Override
public CompletableFuture<Void> attach(TypedTargetObjectRef<? extends TargetAttachable<?>> ref) { public CompletableFuture<Void> attach(TargetAttachable attachable) {
getModel().assertMine(TargetObjectRef.class, ref); GdbModelTargetAttachable mine =
List<String> tPath = ref.getPath(); getModel().assertMine(GdbModelTargetAttachable.class, attachable);
return impl.fetchModelObject(tPath).thenCompose(obj -> { return attach(mine.pid);
GdbModelTargetAttachable attachable = (GdbModelTargetAttachable) DebuggerObjectModel
.requireIface(TargetAttachable.class, obj, tPath);
// TODO: Find first unused inferior?
return impl.gdb.addInferior().thenCompose(inf -> {
return inf.attach(attachable.pid).thenApply(__ -> null);
});
});
} }
@Override @Override
@ -237,31 +220,24 @@ public class GdbModelTargetSession extends DefaultTargetModelRoot implements //
} }
@Override @Override
public CompletableFuture<Void> requestFocus(TargetObjectRef ref) { public CompletableFuture<Void> requestFocus(TargetObject obj) {
impl.assertMine(TargetObjectRef.class, ref); impl.assertMine(TargetObject.class, obj);
/** /**
* Yes, this is pointless, since I'm the root, but do it right (TM), since this may change * Yes, this is pointless, since I'm the root, but do it right (TM), since this may change
* or be used as an example for other implementations. * or be used as an example for other implementations.
*/ */
if (!PathUtils.isAncestor(this.getPath(), ref.getPath())) { if (!PathUtils.isAncestor(this.getPath(), obj.getPath())) {
throw new DebuggerIllegalArgumentException("Can only focus a successor of the scope"); throw new DebuggerIllegalArgumentException("Can only focus a successor of the scope");
} }
return ref.fetch().thenCompose(obj -> { TargetObject cur = obj;
TargetObject cur = obj; while (cur != null) {
while (cur != null) { if (cur instanceof GdbModelSelectableObject) {
if (cur instanceof GdbModelSelectableObject) { GdbModelSelectableObject sel = (GdbModelSelectableObject) cur;
GdbModelSelectableObject sel = (GdbModelSelectableObject) cur; return sel.select();
return sel.select();
}
if (cur instanceof AbstractTargetObject) {
AbstractTargetObject<?> def = (AbstractTargetObject<?>) cur;
cur = def.getImplParent();
continue;
}
throw new AssertionError();
} }
return AsyncUtils.NIL; cur = cur.getParent();
}); }
return AsyncUtils.NIL;
} }
protected void invalidateMemoryAndRegisterCaches() { protected void invalidateMemoryAndRegisterCaches() {

View file

@ -30,12 +30,15 @@ import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.datastruct.WeakValueHashMap; import ghidra.util.datastruct.WeakValueHashMap;
@TargetObjectSchemaInfo(name = "Stack", attributes = { @TargetObjectSchemaInfo(
@TargetAttributeType(type = Void.class) name = "Stack",
}, canonicalContainer = true) attributes = {
@TargetAttributeType(type = Void.class)
},
canonicalContainer = true)
public class GdbModelTargetStack public class GdbModelTargetStack
extends DefaultTargetObject<GdbModelTargetStackFrame, GdbModelTargetThread> extends DefaultTargetObject<GdbModelTargetStackFrame, GdbModelTargetThread>
implements TargetStack<GdbModelTargetStack> { implements TargetStack {
public static final String NAME = "Stack"; public static final String NAME = "Stack";
protected final GdbModelImpl impl; protected final GdbModelImpl impl;

View file

@ -31,14 +31,16 @@ import ghidra.lifecycle.Internal;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.util.Msg; import ghidra.util.Msg;
@TargetObjectSchemaInfo(name = "StackFrame", elements = { @TargetObjectSchemaInfo(
@TargetElementType(type = Void.class) name = "StackFrame",
}, attributes = { elements = {
@TargetAttributeType(type = Void.class) @TargetElementType(type = Void.class)
}) },
attributes = {
@TargetAttributeType(type = Void.class)
})
public class GdbModelTargetStackFrame extends DefaultTargetObject<TargetObject, GdbModelTargetStack> public class GdbModelTargetStackFrame extends DefaultTargetObject<TargetObject, GdbModelTargetStack>
implements TargetStackFrame<GdbModelTargetStackFrame>, implements TargetStackFrame, TargetRegisterBank, GdbModelSelectableObject {
TargetRegisterBank<GdbModelTargetStackFrame>, GdbModelSelectableObject {
public static final String FUNC_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "function"; public static final String FUNC_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "function";
public static final String FROM_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "from"; // TODO public static final String FROM_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "from"; // TODO
@ -87,7 +89,10 @@ public class GdbModelTargetStackFrame extends DefaultTargetObject<TargetObject,
setFrame(frame); setFrame(frame);
} }
@TargetAttributeType(name = GdbModelTargetStackFrameRegisterContainer.NAME, required = true, fixed = true) @TargetAttributeType(
name = GdbModelTargetStackFrameRegisterContainer.NAME,
required = true,
fixed = true)
public GdbModelTargetStackFrameRegisterContainer getRegisters() { public GdbModelTargetStackFrameRegisterContainer getRegisters() {
return registers; return registers;
} }

View file

@ -25,9 +25,12 @@ import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
import ghidra.util.datastruct.WeakValueHashMap; import ghidra.util.datastruct.WeakValueHashMap;
// NB. The canonical container, but of no recognized interface // NB. The canonical container, but of no recognized interface
@TargetObjectSchemaInfo(name = "RegisterValueContainer", attributes = { @TargetObjectSchemaInfo(
@TargetAttributeType(type = Void.class) name = "RegisterValueContainer",
}, canonicalContainer = true) attributes = {
@TargetAttributeType(type = Void.class)
},
canonicalContainer = true)
public class GdbModelTargetStackFrameRegisterContainer public class GdbModelTargetStackFrameRegisterContainer
extends DefaultTargetObject<GdbModelTargetStackFrameRegister, GdbModelTargetStackFrame> { extends DefaultTargetObject<GdbModelTargetStackFrameRegister, GdbModelTargetStackFrame> {
public static final String NAME = "Registers"; public static final String NAME = "Registers";

View file

@ -26,14 +26,17 @@ import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
@TargetObjectSchemaInfo(name = "Symbol", elements = { @TargetObjectSchemaInfo(
@TargetElementType(type = Void.class) name = "Symbol",
}, attributes = { elements = {
@TargetAttributeType(type = Void.class) @TargetElementType(type = Void.class)
}) },
attributes = {
@TargetAttributeType(type = Void.class)
})
public class GdbModelTargetSymbol public class GdbModelTargetSymbol
extends DefaultTargetObject<TargetObject, GdbModelTargetSymbolContainer> extends DefaultTargetObject<TargetObject, GdbModelTargetSymbolContainer>
implements TargetSymbol<GdbModelTargetSymbol> { implements TargetSymbol {
protected static String indexSymbol(GdbMinimalSymbol symbol) { protected static String indexSymbol(GdbMinimalSymbol symbol) {
return symbol.getName(); return symbol.getName();
} }

View file

@ -27,12 +27,15 @@ import ghidra.dbg.target.schema.TargetAttributeType;
import ghidra.dbg.target.schema.TargetObjectSchemaInfo; import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
import ghidra.util.datastruct.WeakValueHashMap; import ghidra.util.datastruct.WeakValueHashMap;
@TargetObjectSchemaInfo(name = "SymbolContainer", attributes = { @TargetObjectSchemaInfo(
@TargetAttributeType(type = Void.class) name = "SymbolContainer",
}, canonicalContainer = true) attributes = {
@TargetAttributeType(type = Void.class)
},
canonicalContainer = true)
public class GdbModelTargetSymbolContainer public class GdbModelTargetSymbolContainer
extends DefaultTargetObject<GdbModelTargetSymbol, GdbModelTargetModule> extends DefaultTargetObject<GdbModelTargetSymbol, GdbModelTargetModule>
implements TargetSymbolNamespace<GdbModelTargetSymbolContainer> { implements TargetSymbolNamespace {
public static final String NAME = "Symbols"; public static final String NAME = "Symbols";
protected final GdbModelImpl impl; protected final GdbModelImpl impl;

View file

@ -40,8 +40,7 @@ import ghidra.util.Msg;
@TargetAttributeType(type = Void.class) }) @TargetAttributeType(type = Void.class) })
public class GdbModelTargetThread public class GdbModelTargetThread
extends DefaultTargetObject<TargetObject, GdbModelTargetThreadContainer> implements extends DefaultTargetObject<TargetObject, GdbModelTargetThreadContainer> implements
TargetThread<GdbModelTargetThread>, TargetExecutionStateful<GdbModelTargetThread>, TargetThread, TargetExecutionStateful, TargetSteppable, GdbModelSelectableObject {
TargetSteppable<GdbModelTargetThread>, GdbModelSelectableObject {
protected static final TargetStepKindSet SUPPORTED_KINDS = TargetStepKindSet.of( // protected static final TargetStepKindSet SUPPORTED_KINDS = TargetStepKindSet.of( //
TargetStepKind.ADVANCE, // TargetStepKind.ADVANCE, //
TargetStepKind.FINISH, // TargetStepKind.FINISH, //

View file

@ -27,9 +27,12 @@ import ghidra.dbg.target.schema.TargetAttributeType;
import ghidra.dbg.target.schema.TargetObjectSchemaInfo; import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
import ghidra.util.datastruct.WeakValueHashMap; import ghidra.util.datastruct.WeakValueHashMap;
@TargetObjectSchemaInfo(name = "ThreadContainer", attributes = { @TargetObjectSchemaInfo(
@TargetAttributeType(type = Void.class) name = "ThreadContainer",
}, canonicalContainer = true) attributes = {
@TargetAttributeType(type = Void.class)
},
canonicalContainer = true)
public class GdbModelTargetThreadContainer public class GdbModelTargetThreadContainer
extends DefaultTargetObject<GdbModelTargetThread, GdbModelTargetInferior> { extends DefaultTargetObject<GdbModelTargetThread, GdbModelTargetInferior> {
public static final String NAME = "Threads"; public static final String NAME = "Threads";

View file

@ -17,6 +17,7 @@ package agent.gdb.model;
import static ghidra.dbg.testutil.DummyProc.run; import static ghidra.dbg.testutil.DummyProc.run;
import static ghidra.dbg.testutil.DummyProc.which; import static ghidra.dbg.testutil.DummyProc.which;
import static ghidra.lifecycle.Unfinished.TODO;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.util.*; import java.util.*;
@ -33,11 +34,9 @@ import agent.gdb.model.impl.GdbModelTargetInferior;
import agent.gdb.model.impl.GdbModelTargetStackFrame; import agent.gdb.model.impl.GdbModelTargetStackFrame;
import ghidra.async.AsyncReference; import ghidra.async.AsyncReference;
import ghidra.async.AsyncUtils; import ghidra.async.AsyncUtils;
import ghidra.dbg.DebugModelConventions;
import ghidra.dbg.DebugModelConventions.AllRequiredAccess; import ghidra.dbg.DebugModelConventions.AllRequiredAccess;
import ghidra.dbg.DebuggerObjectModel; import ghidra.dbg.DebuggerObjectModel;
import ghidra.dbg.attributes.TargetObjectRef; import ghidra.dbg.attributes.TargetObjectList;
import ghidra.dbg.attributes.TargetObjectRefList;
import ghidra.dbg.error.DebuggerModelNoSuchPathException; import ghidra.dbg.error.DebuggerModelNoSuchPathException;
import ghidra.dbg.error.DebuggerModelTypeException; import ghidra.dbg.error.DebuggerModelTypeException;
import ghidra.dbg.target.*; import ghidra.dbg.target.*;
@ -185,12 +184,12 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
waitAcc(access); waitAcc(access);
Msg.debug(this, "Getting Inferiors (before launch)..."); Msg.debug(this, "Getting Inferiors (before launch)...");
Map<String, ? extends TargetObjectRef> inferiors = Map<String, ? extends TargetObject> inferiors =
waitOn(model.fetchObjectElements(List.of("Inferiors"))); waitOn(model.fetchObjectElements(List.of("Inferiors")));
Msg.debug(this, "Inferiors before: " + inferiors); Msg.debug(this, "Inferiors before: " + inferiors);
assertEquals(1, inferiors.size()); assertEquals(1, inferiors.size());
Msg.debug(this, "Finding TargetLauncher..."); Msg.debug(this, "Finding TargetLauncher...");
TargetLauncher<?> launcher = suitable(TargetLauncher.tclass, root); TargetLauncher launcher = suitable(TargetLauncher.class, root);
Msg.debug(this, "Launching..."); Msg.debug(this, "Launching...");
waitOn(launcher.launch( waitOn(launcher.launch(
Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, "/bin/echo Hello, World!"))); Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, "/bin/echo Hello, World!")));
@ -221,8 +220,8 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Waiting for inferior access..."); Msg.debug(this, "Waiting for inferior access...");
waitAcc(infAccess); waitAcc(infAccess);
Msg.debug(this, "Reflecting parameters"); Msg.debug(this, "Reflecting parameters");
TargetLauncher<?> launcher = inferior.as(TargetLauncher.tclass); TargetLauncher launcher = inferior.as(TargetLauncher.class);
for (ParameterDescription<?> param : launcher.getParameters().values()) { for (ParameterDescription param : launcher.getParameters().values()) {
Msg.info(this, " Parameter: " + param); Msg.info(this, " Parameter: " + param);
} }
waitOn(launcher.launch(Map.of("args", "/bin/echo Hello, World!"))); waitOn(launcher.launch(Map.of("args", "/bin/echo Hello, World!")));
@ -230,7 +229,7 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Waiting for session access (again)..."); Msg.debug(this, "Waiting for session access (again)...");
waitAcc(rootAccess); waitAcc(rootAccess);
Msg.debug(this, "Getting Inferiors (after launch)..."); Msg.debug(this, "Getting Inferiors (after launch)...");
Map<String, ? extends TargetObjectRef> inferiors = Map<String, ? extends TargetObject> inferiors =
waitOn(model.fetchObjectElements(List.of("Inferiors"))); waitOn(model.fetchObjectElements(List.of("Inferiors")));
Msg.debug(this, "Inferiors after: " + inferiors); Msg.debug(this, "Inferiors after: " + inferiors);
assertEquals(1, inferiors.size()); assertEquals(1, inferiors.size());
@ -260,7 +259,7 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Waiting for session access (again)..."); Msg.debug(this, "Waiting for session access (again)...");
waitAcc(rootAccess); waitAcc(rootAccess);
Msg.debug(this, "Getting Inferiors (after launch)..."); Msg.debug(this, "Getting Inferiors (after launch)...");
Map<String, ? extends TargetObjectRef> inferiors = Map<String, ? extends TargetObject> inferiors =
waitOn(model.fetchObjectElements(List.of("Inferiors"))); waitOn(model.fetchObjectElements(List.of("Inferiors")));
Msg.debug(this, "Inferiors after: " + inferiors); Msg.debug(this, "Inferiors after: " + inferiors);
assertEquals(1, inferiors.size()); assertEquals(1, inferiors.size());
@ -278,7 +277,7 @@ public abstract class AbstractModelForGdbTest
AllRequiredAccess access = access(root); AllRequiredAccess access = access(root);
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
waitAcc(access); waitAcc(access);
Map<String, ? extends TargetObjectRef> available = Map<String, ? extends TargetObject> available =
waitOn(model.fetchObjectElements(List.of("Available"))); waitOn(model.fetchObjectElements(List.of("Available")));
assertTrue(available.containsKey(Long.toString(dd.pid))); assertTrue(available.containsKey(Long.toString(dd.pid)));
} }
@ -296,16 +295,16 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
waitAcc(access); waitAcc(access);
Msg.debug(this, "Getting Inferiors (before attach)..."); Msg.debug(this, "Getting Inferiors (before attach)...");
Map<String, ? extends TargetObjectRef> inferiors = Map<String, ? extends TargetObject> inferiors =
waitOn(model.fetchObjectElements(List.of("Inferiors"))); waitOn(model.fetchObjectElements(List.of("Inferiors")));
Msg.debug(this, "Inferiors before: " + inferiors); Msg.debug(this, "Inferiors before: " + inferiors);
assertEquals(1, inferiors.size()); assertEquals(1, inferiors.size());
Msg.debug(this, "Finding TargetAttacher..."); Msg.debug(this, "Finding TargetAttacher...");
TargetAttacher<?> attacher = suitable(TargetAttacher.tclass, root); TargetAttacher attacher = suitable(TargetAttacher.class, root);
Msg.debug(this, " Got TargetAttacher: " + attacher); Msg.debug(this, " Got TargetAttacher: " + attacher);
TargetAttachable<?> attachable = TargetAttachable attachable =
waitOn(model.fetchModelObject("Available", "[" + dd.pid + "]")) waitOn(model.fetchModelObject("Available", "[" + dd.pid + "]"))
.as(TargetAttachable.tclass); .as(TargetAttachable.class);
Msg.debug(this, " Got Attachable: " + attachable); Msg.debug(this, " Got Attachable: " + attachable);
Msg.debug(this, "Attaching..."); Msg.debug(this, "Attaching...");
waitOn(attacher.attach(attachable)); waitOn(attacher.attach(attachable));
@ -316,8 +315,7 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Inferiors after: " + inferiors); Msg.debug(this, "Inferiors after: " + inferiors);
assertEquals(2, inferiors.size()); assertEquals(2, inferiors.size());
Msg.debug(this, "Killing..."); Msg.debug(this, "Killing...");
TargetKillable<?> killable = TargetKillable killable = inferiors.get("2").as(TargetKillable.class);
waitOn(inferiors.get("2").as(TargetKillable.tclass).fetch());
waitOn(killable.kill()); waitOn(killable.kill());
} }
} }
@ -335,7 +333,7 @@ public abstract class AbstractModelForGdbTest
waitAcc(access); waitAcc(access);
Msg.debug(this, "Getting Inferior 1..."); Msg.debug(this, "Getting Inferior 1...");
TargetObject inferior = waitOn(model.fetchModelObject(List.of("Inferiors", "[1]"))); TargetObject inferior = waitOn(model.fetchModelObject(List.of("Inferiors", "[1]")));
TargetAttacher<?> attacher = inferior.as(TargetAttacher.tclass); TargetAttacher attacher = inferior.as(TargetAttacher.class);
Msg.debug(this, "Waiting for session access (again)..."); Msg.debug(this, "Waiting for session access (again)...");
waitAcc(access); waitAcc(access);
Msg.debug(this, "Attaching..."); Msg.debug(this, "Attaching...");
@ -343,13 +341,13 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Waiting for session access (again, again)..."); Msg.debug(this, "Waiting for session access (again, again)...");
waitAcc(access); waitAcc(access);
Msg.debug(this, "Getting Inferiors (after attach)..."); Msg.debug(this, "Getting Inferiors (after attach)...");
Map<String, ? extends TargetObjectRef> inferiors = Map<String, ? extends TargetObject> inferiors =
waitOn(model.fetchObjectElements(List.of("Inferiors"))); waitOn(model.fetchObjectElements(List.of("Inferiors")));
Msg.debug(this, "Inferiors after: " + inferiors); Msg.debug(this, "Inferiors after: " + inferiors);
assertEquals(1, inferiors.size()); assertEquals(1, inferiors.size());
Msg.debug(this, "Killing..."); Msg.debug(this, "Killing...");
TargetObject attached = waitOn(inferiors.get("1").fetch()); TargetObject attached = inferiors.get("1");
TargetKillable<?> killable = attached.as(TargetKillable.tclass); TargetKillable killable = attached.as(TargetKillable.class);
waitOn(killable.kill()); waitOn(killable.kill());
} }
} }
@ -392,9 +390,8 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Getting Inferior 1..."); Msg.debug(this, "Getting Inferior 1...");
TargetObject inferior = waitOn(model.fetchModelObject("Inferiors", "[1]")); TargetObject inferior = waitOn(model.fetchModelObject("Inferiors", "[1]"));
Msg.debug(this, "Attaching to bogus path..."); Msg.debug(this, "Attaching to bogus path...");
TargetAttacher<?> attacher = inferior.as(TargetAttacher.tclass); TargetAttacher attacher = inferior.as(TargetAttacher.class);
waitOn(attacher.attach(model.createRef("Available", "Process -1") TODO();
.as(TargetAttachable.tclass)));
} }
} }
@ -412,8 +409,9 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Getting Inferior 1..."); Msg.debug(this, "Getting Inferior 1...");
TargetObject inferior = waitOn(model.fetchModelObject("Inferiors", "[1]")); TargetObject inferior = waitOn(model.fetchModelObject("Inferiors", "[1]"));
Msg.debug(this, "Attaching to bogus path..."); Msg.debug(this, "Attaching to bogus path...");
TargetAttacher<?> attacher = inferior.as(TargetAttacher.tclass); TargetAttacher attacher = inferior.as(TargetAttacher.class);
waitOn(attacher.attach(model.createRef("Available").as(TargetAttachable.tclass))); // NOTE: Technically, the "as" call is causing it here.
waitOn(attacher.attach(model.getModelObject("Available").as(TargetAttachable.class)));
fail("Exception expected"); fail("Exception expected");
} }
} }
@ -524,7 +522,7 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
waitAcc(access); waitAcc(access);
Msg.debug(this, "Finding breakpoint container..."); Msg.debug(this, "Finding breakpoint container...");
TargetBreakpointContainer<?> breaks = suitable(TargetBreakpointContainer.tclass, root); TargetBreakpointContainer breaks = suitable(TargetBreakpointContainer.class, root);
Msg.debug(this, "Got: " + breaks); Msg.debug(this, "Got: " + breaks);
TargetBreakpointKindSet kinds = breaks.getSupportedBreakpointKinds(); TargetBreakpointKindSet kinds = breaks.getSupportedBreakpointKinds();
Msg.debug(this, "Supports: " + kinds); Msg.debug(this, "Supports: " + kinds);
@ -547,22 +545,21 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Setting file to " + specimen + "..."); Msg.debug(this, "Setting file to " + specimen + "...");
cli(root, "file " + specimen); cli(root, "file " + specimen);
Msg.debug(this, "Finding breakpoint container..."); Msg.debug(this, "Finding breakpoint container...");
TargetBreakpointContainer<?> breaks = suitable(TargetBreakpointContainer.tclass, root); TargetBreakpointContainer breaks = suitable(TargetBreakpointContainer.class, root);
Msg.debug(this, "Placing breakpoint..."); Msg.debug(this, "Placing breakpoint...");
waitOn(breaks.placeBreakpoint("func", Set.of(TargetBreakpointKind.SOFTWARE))); waitOn(breaks.placeBreakpoint("func", Set.of(TargetBreakpointKind.SOFTWARE)));
Msg.debug(this, "Getting breakpoint specs..."); Msg.debug(this, "Getting breakpoint specs...");
Map<String, ? extends TargetObjectRef> specs = waitOn(breaks.fetchElements()); Map<String, ? extends TargetObject> specs = waitOn(breaks.fetchElements());
Msg.debug(this, "Got specs: " + specs); Msg.debug(this, "Got specs: " + specs);
assertEquals(1, specs.size()); assertEquals(1, specs.size());
TargetBreakpointSpec<?> spec = TargetBreakpointSpec spec = specs.get("1").as(TargetBreakpointSpec.class);
waitOn(specs.get("1").as(TargetBreakpointSpec.tclass).fetch()); Collection<? extends TargetBreakpointLocation> ls = waitOn(spec.getLocations());
Collection<? extends TargetBreakpointLocation<?>> ls = waitOn(spec.getLocations());
Msg.debug(this, "Got locations: " + ls); Msg.debug(this, "Got locations: " + ls);
assertEquals(1, ls.size()); assertEquals(1, ls.size());
TargetBreakpointLocation<?> loc = ls.iterator().next(); TargetBreakpointLocation loc = ls.iterator().next();
Address addr = loc.getAddress(); Address addr = loc.getAddress();
Msg.debug(this, "Got address: " + addr); Msg.debug(this, "Got address: " + addr);
TargetObjectRefList<?> list = loc.getAffects(); TargetObjectList<?> list = loc.getAffects();
Msg.debug(this, "Got affects: " + list); Msg.debug(this, "Got affects: " + list);
assertEquals(1, list.size()); assertEquals(1, list.size());
} }
@ -583,24 +580,23 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Setting file to " + specimen + "..."); Msg.debug(this, "Setting file to " + specimen + "...");
cli(root, "file " + specimen); cli(root, "file " + specimen);
Msg.debug(this, "Finding breakpoint container..."); Msg.debug(this, "Finding breakpoint container...");
TargetBreakpointContainer<?> breaks = suitable(TargetBreakpointContainer.tclass, root); TargetBreakpointContainer breaks = suitable(TargetBreakpointContainer.class, root);
Msg.debug(this, "Placing breakpoint..."); Msg.debug(this, "Placing breakpoint...");
waitOn(breaks.placeBreakpoint("int_var", waitOn(breaks.placeBreakpoint("int_var",
Set.of(TargetBreakpointKind.READ, TargetBreakpointKind.WRITE))); Set.of(TargetBreakpointKind.READ, TargetBreakpointKind.WRITE)));
Msg.debug(this, "Getting breakpoint specs..."); Msg.debug(this, "Getting breakpoint specs...");
Map<String, ? extends TargetObjectRef> specs = waitOn(breaks.fetchElements()); Map<String, ? extends TargetObject> specs = waitOn(breaks.fetchElements());
Msg.debug(this, "Got specs: " + specs); Msg.debug(this, "Got specs: " + specs);
assertEquals(1, specs.size()); assertEquals(1, specs.size());
TargetBreakpointSpec<?> spec = TargetBreakpointSpec spec = specs.get("1").as(TargetBreakpointSpec.class);
waitOn(specs.get("1").as(TargetBreakpointSpec.tclass).fetch()); Collection<? extends TargetBreakpointLocation> ls = waitOn(spec.getLocations());
Collection<? extends TargetBreakpointLocation<?>> ls = waitOn(spec.getLocations());
Msg.debug(this, "Got locations: " + ls); Msg.debug(this, "Got locations: " + ls);
assertEquals(1, ls.size()); assertEquals(1, ls.size());
TargetBreakpointLocation<?> loc = ls.iterator().next(); TargetBreakpointLocation loc = ls.iterator().next();
Address addr = loc.getAddress(); Address addr = loc.getAddress();
Msg.debug(this, "Got address: " + addr); Msg.debug(this, "Got address: " + addr);
assertNotNull(addr); assertNotNull(addr);
TargetObjectRefList<?> list = loc.getAffects(); TargetObjectList<?> list = loc.getAffects();
Msg.debug(this, "Got affects: " + list); Msg.debug(this, "Got affects: " + list);
assertEquals(1, list.size()); assertEquals(1, list.size());
} }
@ -611,7 +607,7 @@ public abstract class AbstractModelForGdbTest
try (ModelHost m = modelHost()) { try (ModelHost m = modelHost()) {
DebuggerObjectModel model = m.getModel(); DebuggerObjectModel model = m.getModel();
Set<Address> locAddresses = new HashSet<>(); Set<Address> locAddresses = new HashSet<>();
Set<TargetObjectRef> locAffecteds = new HashSet<>(); Set<TargetObject> locAffecteds = new HashSet<>();
init(m); init(m);
Msg.debug(this, "Getting root object"); Msg.debug(this, "Getting root object");
@ -628,33 +624,32 @@ public abstract class AbstractModelForGdbTest
waitAcc(access); waitAcc(access);
Msg.debug(this, "Setting to stay attached to forks"); Msg.debug(this, "Setting to stay attached to forks");
cli(root, "set detach-on-fork off"); cli(root, "set detach-on-fork off");
TargetBreakpointContainer<?> breaks = TargetBreakpointContainer breaks =
suitable(TargetBreakpointContainer.tclass, inferior); suitable(TargetBreakpointContainer.class, inferior);
Msg.debug(this, "Setting break on func"); Msg.debug(this, "Setting break on func");
waitOn(breaks.placeBreakpoint("func", Set.of(TargetBreakpointKind.SOFTWARE))); waitOn(breaks.placeBreakpoint("func", Set.of(TargetBreakpointKind.SOFTWARE)));
Msg.debug(this, "Resuming execution (first time)"); Msg.debug(this, "Resuming execution (first time)");
resume(inferior); resume(inferior);
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
waitAcc(access); waitAcc(access);
Map<String, ? extends TargetObjectRef> inferiors = Map<String, ? extends TargetObject> inferiors =
waitOn(model.fetchObjectElements("Inferiors")); waitOn(model.fetchObjectElements("Inferiors"));
Msg.debug(this, "After first break, inferiors are: " + inferiors); Msg.debug(this, "After first break, inferiors are: " + inferiors);
assertEquals(2, inferiors.size()); assertEquals(2, inferiors.size());
// NOTE: Breakpoint 1 was the temporary one on 'main' // NOTE: Breakpoint 1 was the temporary one on 'main'
Map<String, ? extends TargetObjectRef> ls = Map<String, ? extends TargetObject> ls =
waitOn(model.fetchObjectElements("Breakpoints", "[2]")); waitOn(model.fetchObjectElements("Breakpoints", "[2]"));
Msg.debug(this, "Locations: " + ls); Msg.debug(this, "Locations: " + ls);
assertEquals(2, ls.size()); assertEquals(2, ls.size());
for (TargetObjectRef ref : ls.values()) { for (TargetObject obj : ls.values()) {
TargetBreakpointLocation<?> loc = TargetBreakpointLocation loc = obj.as(TargetBreakpointLocation.class);
waitOn(ref.as(TargetBreakpointLocation.tclass).fetch());
locAddresses.add(loc.getAddress()); locAddresses.add(loc.getAddress());
locAffecteds.addAll(loc.getAffects()); locAffecteds.addAll(loc.getAffects());
} }
Msg.debug(this, "Addresses: " + locAddresses + ", affected: " + locAffecteds); Msg.debug(this, "Addresses: " + locAddresses + ", affected: " + locAffecteds);
assertEquals(1, locAddresses.size()); assertEquals(1, locAddresses.size());
assertEquals(Set.of(List.of("Inferiors", "[1]"), List.of("Inferiors", "[2]")), assertEquals(Set.of(List.of("Inferiors", "[1]"), List.of("Inferiors", "[2]")),
locAffecteds.stream().map(TargetObjectRef::getPath).collect(Collectors.toSet())); locAffecteds.stream().map(TargetObject::getPath).collect(Collectors.toSet()));
} }
} }
@ -663,16 +658,16 @@ public abstract class AbstractModelForGdbTest
public void testExpForkWithListeners() throws Throwable { public void testExpForkWithListeners() throws Throwable {
ElementTrackingListener<TargetObject> infListener = ElementTrackingListener<TargetObject> infListener =
new ElementTrackingListener<>(TargetObject.class); new ElementTrackingListener<>(TargetObject.class);
ElementTrackingListener<? extends TargetBreakpointSpec<?>> bkListener = ElementTrackingListener<? extends TargetBreakpointSpec> bkListener =
new ElementTrackingListener<>(TargetBreakpointSpec.tclass); new ElementTrackingListener<>(TargetBreakpointSpec.class);
ElementTrackingListener<? extends TargetBreakpointLocation<?>> blListener = ElementTrackingListener<? extends TargetBreakpointLocation> blListener =
new ElementTrackingListener<>(TargetBreakpointLocation.tclass); new ElementTrackingListener<>(TargetBreakpointLocation.class);
EventSequenceListener evtListener = new EventSequenceListener(); EventSequenceListener evtListener = new EventSequenceListener();
try (ModelHost m = modelHost()) { try (ModelHost m = modelHost()) {
DebuggerObjectModel model = m.getModel(); DebuggerObjectModel model = m.getModel();
Set<Address> ebAddresses = new HashSet<>(); Set<Address> ebAddresses = new HashSet<>();
Set<TargetObjectRef> ebAffecteds = new HashSet<>(); Set<TargetObject> ebAffecteds = new HashSet<>();
init(m); init(m);
Msg.debug(this, "Getting root object"); Msg.debug(this, "Getting root object");
@ -687,8 +682,7 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Installing listener for inferiors"); Msg.debug(this, "Installing listener for inferiors");
infCont.addListener(infListener); infCont.addListener(infListener);
Msg.debug(this, "Getting inferiors"); Msg.debug(this, "Getting inferiors");
Map<String, ? extends TargetObject> inferiors = waitOn(infCont.fetchElements() Map<String, ? extends TargetObject> inferiors = waitOn(infCont.fetchElements());
.thenCompose(DebugModelConventions::fetchAll));
infListener.putAll(inferiors); infListener.putAll(inferiors);
Msg.debug(this, "Launching..."); Msg.debug(this, "Launching...");
launch(infListener.elements.get("1"), launch(infListener.elements.get("1"),
@ -697,24 +691,22 @@ public abstract class AbstractModelForGdbTest
waitAcc(access); waitAcc(access);
Msg.debug(this, "Setting to stay attached to forks"); Msg.debug(this, "Setting to stay attached to forks");
cli(root, "set detach-on-fork off"); cli(root, "set detach-on-fork off");
TargetBreakpointContainer<?> bkCont = TargetBreakpointContainer bkCont =
suitable(TargetBreakpointContainer.tclass, infCont); suitable(TargetBreakpointContainer.class, infCont);
Msg.debug(this, "Installing listener for breakpoints"); Msg.debug(this, "Installing listener for breakpoints");
bkCont.addListener(bkListener); bkCont.addListener(bkListener);
Msg.debug(this, "Getting breakpoints"); Msg.debug(this, "Getting breakpoints");
Map<String, ? extends TargetObject> bkElems = waitOn(bkCont.fetchElements() Map<String, ? extends TargetObject> bkElems = waitOn(bkCont.fetchElements());
.thenCompose(DebugModelConventions::fetchAll));
bkListener.putAll(bkElems); bkListener.putAll(bkElems);
Msg.debug(this, "Setting break on func"); Msg.debug(this, "Setting break on func");
waitOn(bkCont.placeBreakpoint("func", Set.of(TargetBreakpointKind.SOFTWARE))); waitOn(bkCont.placeBreakpoint("func", Set.of(TargetBreakpointKind.SOFTWARE)));
Msg.debug(this, "Breakpoint elements: " + bkListener.elements); Msg.debug(this, "Breakpoint elements: " + bkListener.elements);
TargetBreakpointSpec<?> bk2 = TargetBreakpointSpec bk2 =
waitOn(bkListener.refElement("2").waitUntil(t -> t != null)); waitOn(bkListener.refElement("2").waitUntil(t -> t != null));
Msg.debug(this, "Installing listener on Breakpoint 2"); Msg.debug(this, "Installing listener on Breakpoint 2");
bk2.addListener(blListener); bk2.addListener(blListener);
Msg.debug(this, "Getting locations for 2"); Msg.debug(this, "Getting locations for 2");
Map<String, ? extends TargetObject> bk2ls = waitOn(bk2.fetchElements() Map<String, ? extends TargetObject> bk2ls = waitOn(bk2.fetchElements());
.thenCompose(DebugModelConventions::fetchAll));
blListener.putAll(bk2ls); blListener.putAll(bk2ls);
Msg.debug(this, "Resuming execution (first time)"); Msg.debug(this, "Resuming execution (first time)");
resume(infListener.elements.get("1")); resume(infListener.elements.get("1"));
@ -727,14 +719,14 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Locations: " + blListener.elements); Msg.debug(this, "Locations: " + blListener.elements);
assertEquals(2, blListener.elements.size()); assertEquals(2, blListener.elements.size());
for (TargetObject obj : blListener.elements.values()) { for (TargetObject obj : blListener.elements.values()) {
TargetBreakpointLocation<?> eb = obj.as(TargetBreakpointLocation.tclass); TargetBreakpointLocation eb = obj.as(TargetBreakpointLocation.class);
ebAddresses.add(eb.getAddress()); ebAddresses.add(eb.getAddress());
ebAffecteds.addAll(eb.getAffects()); ebAffecteds.addAll(eb.getAffects());
} }
Msg.debug(this, "Addresses: " + ebAddresses + ", affected: " + ebAffecteds); Msg.debug(this, "Addresses: " + ebAddresses + ", affected: " + ebAffecteds);
assertEquals(1, ebAddresses.size()); assertEquals(1, ebAddresses.size());
assertEquals(Set.of(List.of("Inferiors", "[1]"), List.of("Inferiors", "[2]")), assertEquals(Set.of(List.of("Inferiors", "[1]"), List.of("Inferiors", "[2]")),
ebAffecteds.stream().map(TargetObjectRef::getPath).collect(Collectors.toSet())); ebAffecteds.stream().map(TargetObject::getPath).collect(Collectors.toSet()));
// Getting more precise than this could become fragile, as library paths vary // Getting more precise than this could become fragile, as library paths vary
TargetEventType lastType = null; TargetEventType lastType = null;
@ -779,7 +771,7 @@ public abstract class AbstractModelForGdbTest
Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, which("expCloneExit"))); Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, which("expCloneExit")));
Msg.debug(this, "Waiting for session access (again)..."); Msg.debug(this, "Waiting for session access (again)...");
waitAcc(access); waitAcc(access);
TargetBreakpointContainer<?> breaks = TargetBreakpointContainer breaks =
suitable(TargetBreakpointContainer.class, inferior); suitable(TargetBreakpointContainer.class, inferior);
Msg.debug(this, "Setting break on work"); Msg.debug(this, "Setting break on work");
waitOn(breaks.placeBreakpoint("work", Set.of(TargetBreakpointKind.SOFTWARE))); waitOn(breaks.placeBreakpoint("work", Set.of(TargetBreakpointKind.SOFTWARE)));
@ -787,7 +779,7 @@ public abstract class AbstractModelForGdbTest
resume(inferior); resume(inferior);
Msg.debug(this, "Waiting for session access..."); Msg.debug(this, "Waiting for session access...");
waitAcc(access); waitAcc(access);
Map<String, ? extends TargetObjectRef> threads = Map<String, ? extends TargetObject> threads =
waitOn(model.fetchObjectElements("Inferiors", "[1]", "Threads")); waitOn(model.fetchObjectElements("Inferiors", "[1]", "Threads"));
Msg.debug(this, "After first break, threads are: " + threads); Msg.debug(this, "After first break, threads are: " + threads);
assertEquals(2, threads.size()); assertEquals(2, threads.size());
@ -816,11 +808,11 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Waiting for session access (again)..."); Msg.debug(this, "Waiting for session access (again)...");
waitAcc(access); waitAcc(access);
Msg.debug(this, "Getting symbol to overwrite"); Msg.debug(this, "Getting symbol to overwrite");
TargetSymbol<?> overwrite = waitOn(inferior.fetchSuccessor( TargetSymbol overwrite = waitOn(inferior.fetchSuccessor(
"Modules", "[" + expPrint + "]", "Symbols", "[overwrite]")).as(TargetSymbol.tclass); "Modules", "[" + expPrint + "]", "Symbols", "[overwrite]")).as(TargetSymbol.class);
Msg.debug(this, "Symbol 'overwrite' is at addr: " + overwrite.getValue()); Msg.debug(this, "Symbol 'overwrite' is at addr: " + overwrite.getValue());
Msg.debug(this, "Getting Memory"); Msg.debug(this, "Getting Memory");
TargetMemory<?> memory = (TargetMemory<?>) waitOn(inferior.fetchSuccessor("Memory")); TargetMemory memory = (TargetMemory) waitOn(inferior.fetchSuccessor("Memory"));
Msg.debug(this, "Writing"); Msg.debug(this, "Writing");
waitOn(memory.writeMemory(overwrite.getValue(), toWrite.getBytes())); waitOn(memory.writeMemory(overwrite.getValue(), toWrite.getBytes()));
Msg.debug(this, "Getting thread (for stepping)"); Msg.debug(this, "Getting thread (for stepping)");
@ -864,7 +856,7 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Waiting for session access (again)..."); Msg.debug(this, "Waiting for session access (again)...");
waitAcc(access); waitAcc(access);
Msg.debug(this, "Finding breakpoint container..."); Msg.debug(this, "Finding breakpoint container...");
TargetBreakpointContainer<?> breaks = suitable(TargetBreakpointContainer.tclass, root); TargetBreakpointContainer breaks = suitable(TargetBreakpointContainer.class, root);
Msg.debug(this, "Placing breakpoint..."); Msg.debug(this, "Placing breakpoint...");
waitOn(breaks.placeBreakpoint("write", Set.of(TargetBreakpointKind.SOFTWARE))); waitOn(breaks.placeBreakpoint("write", Set.of(TargetBreakpointKind.SOFTWARE)));
Msg.debug(this, "Resuming..."); Msg.debug(this, "Resuming...");
@ -872,11 +864,10 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Waiting for session access (after resume)..."); Msg.debug(this, "Waiting for session access (after resume)...");
waitAcc(access); waitAcc(access);
Map<String, ? extends TargetObject> frames = Map<String, ? extends TargetObject> frames =
waitOn(inferior.fetchSubElements("Threads", "[1]", "Stack") waitOn(inferior.fetchSubElements("Threads", "[1]", "Stack"));
.thenCompose(DebugModelConventions::fetchAll));
Msg.debug(this, "Got stack:"); Msg.debug(this, "Got stack:");
for (Map.Entry<String, ? extends TargetObject> ent : frames.entrySet()) { for (Map.Entry<String, ? extends TargetObject> ent : frames.entrySet()) {
TargetStackFrame<?> frame = ent.getValue().as(TargetStackFrame.tclass); TargetStackFrame frame = ent.getValue().as(TargetStackFrame.class);
Msg.debug(this, ent.getKey() + ": " + frame.getProgramCounter()); Msg.debug(this, ent.getKey() + ": " + frame.getProgramCounter());
} }
assertEquals("write", frames.get("0") assertEquals("write", frames.get("0")
@ -892,7 +883,7 @@ public abstract class AbstractModelForGdbTest
public void testRegisters() throws Throwable { public void testRegisters() throws Throwable {
try (ModelHost m = modelHost()) { try (ModelHost m = modelHost()) {
DebuggerObjectModel model = m.getModel(); DebuggerObjectModel model = m.getModel();
Set<TargetRegister<?>> descs = new LinkedHashSet<>(); Set<TargetRegister> descs = new LinkedHashSet<>();
init(m); init(m);
Msg.debug(this, "Getting root object"); Msg.debug(this, "Getting root object");
@ -906,16 +897,15 @@ public abstract class AbstractModelForGdbTest
launch(inferior, Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, "echo Hello, World!")); launch(inferior, Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, "echo Hello, World!"));
Msg.debug(this, "Waiting for session access (again)..."); Msg.debug(this, "Waiting for session access (again)...");
waitAcc(access); waitAcc(access);
TargetRegisterBank<?> bank = TargetRegisterBank bank =
waitOn(inferior.fetchSuccessor("Threads", "[1]", "Stack", "[0]")) waitOn(inferior.fetchSuccessor("Threads", "[1]", "Stack", "[0]"))
.as(TargetRegisterBank.tclass); .as(TargetRegisterBank.class);
Msg.debug(this, "Got bank: " + bank); Msg.debug(this, "Got bank: " + bank);
Msg.debug(this, "Descriptions ref: " + bank.getDescriptions()); TargetRegisterContainer cont = bank.getDescriptions();
TargetRegisterContainer<?> cont = waitOn(bank.getDescriptions().fetch());
Msg.debug(this, "Register descriptions: " + cont); Msg.debug(this, "Register descriptions: " + cont);
descs.addAll(waitOn(cont.getRegisters())); descs.addAll(waitOn(cont.getRegisters()));
Msg.debug(this, "Elements: "); Msg.debug(this, "Elements: ");
for (TargetRegister<?> reg : descs) { for (TargetRegister reg : descs) {
Msg.debug(this, " " + reg.getIndex() + ": " + reg.getBitLength()); Msg.debug(this, " " + reg.getIndex() + ": " + reg.getBitLength());
} }
Map<String, byte[]> data = waitOn(bank.readRegisters(descs)); Map<String, byte[]> data = waitOn(bank.readRegisters(descs));
@ -941,12 +931,12 @@ public abstract class AbstractModelForGdbTest
try (ModelHost m = modelHost()) { try (ModelHost m = modelHost()) {
DebuggerObjectModel model = m.getModel(); DebuggerObjectModel model = m.getModel();
AsyncReference<TargetObjectRef, Void> focus = new AsyncReference<>(); AsyncReference<TargetObject, Void> focus = new AsyncReference<>();
AsyncReference<Integer, Void> inferiorCount = new AsyncReference<>(); AsyncReference<Integer, Void> inferiorCount = new AsyncReference<>();
TargetFocusScopeListener focusListener = new TargetFocusScopeListener() { TargetFocusScopeListener focusListener = new TargetFocusScopeListener() {
@Override @Override
public void focusChanged(TargetFocusScope<?> object, TargetObjectRef focused) { public void focusChanged(TargetFocusScope object, TargetObject focused) {
focus.set(focused, null); focus.set(focused, null);
} }
}; };
@ -965,7 +955,7 @@ public abstract class AbstractModelForGdbTest
TargetObjectListener infListener = new TargetObjectListener() { TargetObjectListener infListener = new TargetObjectListener() {
@Override @Override
public void elementsChanged(TargetObject parent, Collection<String> removed, public void elementsChanged(TargetObject parent, Collection<String> removed,
Map<String, ? extends TargetObjectRef> added) { Map<String, ? extends TargetObject> added) {
inferiorCount.set(infCont.getCachedElements().size(), null); inferiorCount.set(infCont.getCachedElements().size(), null);
} }
}; };
@ -974,9 +964,9 @@ public abstract class AbstractModelForGdbTest
Msg.debug(this, "Creating another inferior"); Msg.debug(this, "Creating another inferior");
cli(root, "add-inferior"); cli(root, "add-inferior");
waitOn(inferiorCount.waitValue(2)); waitOn(inferiorCount.waitValue(2));
assertEquals(model.createRef("Inferiors", "[1]"), getFocus(root)); assertSame(model.getModelObject("Inferiors", "[1]"), getFocus(root));
focus(root, model.createRef("Inferiors", "[2]")); focus(root, model.getModelObject("Inferiors", "[2]"));
assertEquals(model.createRef("Inferiors", "[2]"), getFocus(root)); assertSame(model.getModelObject("Inferiors", "[2]"), getFocus(root));
} }
} }
@ -985,12 +975,12 @@ public abstract class AbstractModelForGdbTest
try (ModelHost m = modelHost()) { try (ModelHost m = modelHost()) {
DebuggerObjectModel model = m.getModel(); DebuggerObjectModel model = m.getModel();
Deque<TargetObjectRef> focusSeq = new LinkedList<>(); Deque<TargetObject> focusSeq = new LinkedList<>();
AsyncReference<Integer, Void> focusSeqSize = new AsyncReference<>(); AsyncReference<Integer, Void> focusSeqSize = new AsyncReference<>();
TargetFocusScopeListener focusListener = new TargetFocusScopeListener() { TargetFocusScopeListener focusListener = new TargetFocusScopeListener() {
@Override @Override
public void focusChanged(TargetFocusScope<?> object, TargetObjectRef focused) { public void focusChanged(TargetFocusScope object, TargetObject focused) {
Msg.debug(this, "Focused: " + focused); Msg.debug(this, "Focused: " + focused);
if (focused instanceof TargetProcess) { if (focused instanceof TargetProcess) {
return; return;
@ -1016,7 +1006,7 @@ public abstract class AbstractModelForGdbTest
launch(inferior, launch(inferior,
Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, "/bin/echo Hello, World!")); Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, "/bin/echo Hello, World!"));
waitOn(focusSeqSize.waitValue(1)); waitOn(focusSeqSize.waitValue(1));
assertEquals(model.createRef(PathUtils.parse("Inferiors[1].Threads[1].Stack[0]")), assertEquals(model.getModelObject(PathUtils.parse("Inferiors[1].Threads[1].Stack[0]")),
focusSeq.peekLast()); focusSeq.peekLast());
} }
} }

View file

@ -17,7 +17,6 @@ package agent.gdb.model;
import java.util.*; import java.util.*;
import ghidra.dbg.attributes.TypedTargetObjectRef;
import ghidra.dbg.target.TargetEventScope; import ghidra.dbg.target.TargetEventScope;
import ghidra.dbg.target.TargetEventScope.TargetEventScopeListener; import ghidra.dbg.target.TargetEventScope.TargetEventScopeListener;
import ghidra.dbg.target.TargetEventScope.TargetEventType; import ghidra.dbg.target.TargetEventScope.TargetEventType;
@ -25,14 +24,13 @@ import ghidra.dbg.target.TargetThread;
public class EventSequenceListener implements TargetEventScopeListener { public class EventSequenceListener implements TargetEventScopeListener {
public static class EventRecord { public static class EventRecord {
public final TargetEventScope<?> object; public final TargetEventScope object;
public final TypedTargetObjectRef<? extends TargetThread<?>> eventThread; public final TargetThread eventThread;
public final TargetEventType type; public final TargetEventType type;
public final String description; public final String description;
public final List<Object> parameters; public final List<Object> parameters;
public EventRecord(TargetEventScope<?> object, public EventRecord(TargetEventScope object, TargetThread eventThread, TargetEventType type,
TypedTargetObjectRef<? extends TargetThread<?>> eventThread, TargetEventType type,
String description, List<Object> parameters) { String description, List<Object> parameters) {
this.object = object; this.object = object;
this.eventThread = eventThread; this.eventThread = eventThread;
@ -80,8 +78,7 @@ public class EventSequenceListener implements TargetEventScopeListener {
public final List<EventRecord> events = new ArrayList<>(); public final List<EventRecord> events = new ArrayList<>();
@Override @Override
public void event(TargetEventScope<?> object, public void event(TargetEventScope object, TargetThread eventThread, TargetEventType type,
TypedTargetObjectRef<? extends TargetThread<?>> eventThread, TargetEventType type,
String description, List<Object> parameters) { String description, List<Object> parameters) {
events.add(new EventRecord(object, eventThread, type, description, parameters)); events.add(new EventRecord(object, eventThread, type, description, parameters));
} }

View file

@ -30,7 +30,6 @@ import ghidra.dbg.gadp.protocol.Gadp;
import ghidra.dbg.gadp.protocol.Gadp.EventNotification.EvtCase; import ghidra.dbg.gadp.protocol.Gadp.EventNotification.EvtCase;
import ghidra.dbg.memory.CachedMemory; import ghidra.dbg.memory.CachedMemory;
import ghidra.dbg.target.TargetAccessConditioned; import ghidra.dbg.target.TargetAccessConditioned;
import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibility;
import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibilityListener; import ghidra.dbg.target.TargetAccessConditioned.TargetAccessibilityListener;
import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointAction; import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointAction;
import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.TargetObject;
@ -211,11 +210,6 @@ public class DelegateGadpClientTargetObject
return ifaces; return ifaces;
} }
@Override
public CompletableFuture<? extends TargetObject> fetch() {
return CompletableFuture.completedFuture(getProxy());
}
@Override @Override
public CompletableFuture<Void> resync(boolean attributes, boolean elements) { public CompletableFuture<Void> resync(boolean attributes, boolean elements) {
return client.sendChecked(Gadp.ResyncRequest.newBuilder() return client.sendChecked(Gadp.ResyncRequest.newBuilder()

View file

@ -34,7 +34,6 @@ import ghidra.async.*;
import ghidra.dbg.DebuggerModelClosedReason; import ghidra.dbg.DebuggerModelClosedReason;
import ghidra.dbg.agent.*; import ghidra.dbg.agent.*;
import ghidra.dbg.agent.AbstractTargetObject.ProxyFactory; import ghidra.dbg.agent.AbstractTargetObject.ProxyFactory;
import ghidra.dbg.attributes.TargetObjectRef;
import ghidra.dbg.error.*; import ghidra.dbg.error.*;
import ghidra.dbg.gadp.GadpVersion; import ghidra.dbg.gadp.GadpVersion;
import ghidra.dbg.gadp.error.*; import ghidra.dbg.gadp.error.*;
@ -575,17 +574,6 @@ public class GadpClient extends AbstractDebuggerObjectModel
return factory; return factory;
} }
@Override
public TargetObjectRef createRef(List<String> path) {
synchronized (lock) {
GadpClientTargetObject proxy = modelProxies.get(path);
if (proxy != null) {
return proxy;
}
}
return super.createRef(path);
}
@Override @Override
public TargetObject getModelObject(List<String> path) { public TargetObject getModelObject(List<String> path) {
return getProxy(path, false); return getProxy(path, false);

View file

@ -19,12 +19,12 @@ import ghidra.dbg.gadp.client.annot.GadpAttributeChangeCallback;
import ghidra.dbg.target.TargetAccessConditioned; import ghidra.dbg.target.TargetAccessConditioned;
public interface GadpClientTargetAccessConditioned public interface GadpClientTargetAccessConditioned
extends GadpClientTargetObject, TargetAccessConditioned<GadpClientTargetAccessConditioned> { extends GadpClientTargetObject, TargetAccessConditioned {
@GadpAttributeChangeCallback(ACCESSIBLE_ATTRIBUTE_NAME) @GadpAttributeChangeCallback(ACCESSIBLE_ATTRIBUTE_NAME)
default void handleAccessibleChanged(Object accessible) { default void handleAccessibleChanged(Object accessible) {
getDelegate().getListeners() getDelegate().getListeners()
.fire(TargetAccessibilityListener.class) .fire(TargetAccessibilityListener.class)
.accessibilityChanged(this, fromObj(accessible)); .accessibilityChanged(this, (Boolean) accessible);
} }
} }

View file

@ -17,7 +17,6 @@ package ghidra.dbg.gadp.client;
import ghidra.dbg.target.TargetAttachable; import ghidra.dbg.target.TargetAttachable;
public interface GadpClientTargetAttachable public interface GadpClientTargetAttachable extends GadpClientTargetObject, TargetAttachable {
extends GadpClientTargetObject, TargetAttachable<GadpClientTargetAttachable> {
// Nothing to add // Nothing to add
} }

View file

@ -17,31 +17,26 @@ package ghidra.dbg.gadp.client;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import ghidra.dbg.attributes.TargetObjectRef;
import ghidra.dbg.attributes.TypedTargetObjectRef;
import ghidra.dbg.gadp.protocol.Gadp; import ghidra.dbg.gadp.protocol.Gadp;
import ghidra.dbg.target.TargetAttachable; import ghidra.dbg.target.*;
import ghidra.dbg.target.TargetAttacher;
public interface GadpClientTargetAttacher public interface GadpClientTargetAttacher extends GadpClientTargetObject, TargetAttacher {
extends GadpClientTargetObject, TargetAttacher<GadpClientTargetAttacher> {
@Override @Override
default CompletableFuture<Void> attach( default CompletableFuture<Void> attach(TargetAttachable attachable) {
TypedTargetObjectRef<? extends TargetAttachable<?>> ref) {
getDelegate().assertValid(); getDelegate().assertValid();
getModel().assertMine(TargetObjectRef.class, ref); getModel().assertMine(TargetObject.class, attachable);
return getModel().sendChecked(Gadp.AttachRequest.newBuilder() return getModel().sendChecked(Gadp.AttachRequest.newBuilder()
.setPath(GadpValueUtils.makePath(getPath())) .setPath(GadpValueUtils.makePath(getPath()))
.setTarget(GadpValueUtils.makePath(ref.getPath())), .setTarget(GadpValueUtils.makePath(attachable.getPath())),
Gadp.AttachReply.getDefaultInstance()).thenApply(rep -> null); Gadp.AttachReply.getDefaultInstance()).thenApply(rep -> null);
} }
@Override @Override
default CompletableFuture<Void> attach(long id) { default CompletableFuture<Void> attach(long pid) {
getDelegate().assertValid(); getDelegate().assertValid();
return getModel().sendChecked(Gadp.AttachRequest.newBuilder() return getModel().sendChecked(Gadp.AttachRequest.newBuilder()
.setPath(GadpValueUtils.makePath(getPath())) .setPath(GadpValueUtils.makePath(getPath()))
.setPid(id), .setPid(pid),
Gadp.AttachReply.getDefaultInstance()).thenApply(rep -> null); Gadp.AttachReply.getDefaultInstance()).thenApply(rep -> null);
} }
} }

View file

@ -18,8 +18,6 @@ package ghidra.dbg.gadp.client;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import ghidra.dbg.attributes.TargetObjectRef;
import ghidra.dbg.attributes.TypedTargetObjectRef;
import ghidra.dbg.gadp.client.annot.GadpEventHandler; import ghidra.dbg.gadp.client.annot.GadpEventHandler;
import ghidra.dbg.gadp.protocol.Gadp; import ghidra.dbg.gadp.protocol.Gadp;
import ghidra.dbg.gadp.protocol.Gadp.Path; import ghidra.dbg.gadp.protocol.Gadp.Path;
@ -29,8 +27,8 @@ import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointKind;
import ghidra.program.model.address.AddressRange; import ghidra.program.model.address.AddressRange;
import ghidra.util.datastruct.ListenerSet; import ghidra.util.datastruct.ListenerSet;
public interface GadpClientTargetBreakpointContainer extends GadpClientTargetObject, public interface GadpClientTargetBreakpointContainer
TargetBreakpointContainer<GadpClientTargetBreakpointContainer> { extends GadpClientTargetObject, TargetBreakpointContainer {
@Override @Override
default CompletableFuture<Void> placeBreakpoint(AddressRange range, default CompletableFuture<Void> placeBreakpoint(AddressRange range,
@ -63,18 +61,16 @@ public interface GadpClientTargetBreakpointContainer extends GadpClientTargetObj
@GadpEventHandler(Gadp.EventNotification.EvtCase.BREAK_HIT_EVENT) @GadpEventHandler(Gadp.EventNotification.EvtCase.BREAK_HIT_EVENT)
default void handleBreakHitEvent(Gadp.EventNotification notification) { default void handleBreakHitEvent(Gadp.EventNotification notification) {
Gadp.BreakHitEvent evt = notification.getBreakHitEvent(); Gadp.BreakHitEvent evt = notification.getBreakHitEvent();
TargetObjectRef trapped = getModel().getProxy(evt.getTrapped().getEList(), true); TargetObject trapped = getModel().getProxy(evt.getTrapped().getEList(), true);
Path framePath = evt.getFrame(); Path framePath = evt.getFrame();
TypedTargetObjectRef<? extends TargetStackFrame<?>> frame = TargetStackFrame frame = framePath == null || framePath.getECount() == 0 ? null
framePath == null || framePath.getECount() == 0 ? null : getModel().getProxy(framePath.getEList(), true).as(TargetStackFrame.class);
: getModel().getProxy(framePath.getEList(), true).as(TargetStackFrame.tclass);
Path specPath = evt.getSpec(); Path specPath = evt.getSpec();
TypedTargetObjectRef<? extends TargetBreakpointSpec<?>> spec = specPath == null ? null TargetBreakpointSpec spec = specPath == null ? null
: getModel().getProxy(specPath.getEList(), true).as(TargetBreakpointSpec.tclass); : getModel().getProxy(specPath.getEList(), true).as(TargetBreakpointSpec.class);
Path bptPath = evt.getEffective(); Path bptPath = evt.getEffective();
TypedTargetObjectRef<? extends TargetBreakpointLocation<?>> breakpoint = bptPath == null TargetBreakpointLocation breakpoint = bptPath == null ? null
? null : getModel().getProxy(bptPath.getEList(), true).as(TargetBreakpointLocation.class);
: getModel().getProxy(bptPath.getEList(), true).as(TargetBreakpointLocation.tclass);
getDelegate().getListeners() getDelegate().getListeners()
.fire(TargetBreakpointListener.class) .fire(TargetBreakpointListener.class)
.breakpointHit(this, trapped, frame, spec, breakpoint); .breakpointHit(this, trapped, frame, spec, breakpoint);

Some files were not shown because too many files have changed in this diff Show more