mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
GP-740: Removed TargetObjectRef and cleaned up.
This commit is contained in:
parent
b9f9c69be4
commit
6614b54248
328 changed files with 3177 additions and 4428 deletions
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) -> {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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> {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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> {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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> {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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, //
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 //
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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]"),
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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?
|
||||||
|
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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";
|
||||||
|
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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, //
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue