mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-26 16:45:41 +08:00
Merge remote-tracking branch 'origin/GP-2752_Dan_removePerTargetObjectListeners--SQUASHED'
This commit is contained in:
-4
@@ -23,11 +23,9 @@ import agent.dbgeng.dbgeng.DebugClient.DebugStatus;
|
||||
import agent.dbgeng.manager.impl.DbgManagerImpl;
|
||||
import agent.dbgeng.model.AbstractDbgModel;
|
||||
import ghidra.async.AsyncUtils;
|
||||
import ghidra.dbg.DebuggerModelListener;
|
||||
import ghidra.dbg.agent.SpiTargetObject;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.util.CollectionUtils.Delta;
|
||||
import ghidra.util.datastruct.ListenerSet;
|
||||
|
||||
public interface DbgModelTargetObject extends SpiTargetObject {
|
||||
|
||||
@@ -65,8 +63,6 @@ public interface DbgModelTargetObject extends SpiTargetObject {
|
||||
|
||||
public CompletableFuture<List<TargetObject>> requestNativeElements();
|
||||
|
||||
public ListenerSet<DebuggerModelListener> getListeners();
|
||||
|
||||
public DbgModelTargetSession getParentSession();
|
||||
|
||||
public DbgModelTargetProcess getParentProcess();
|
||||
|
||||
+3
-7
@@ -25,12 +25,10 @@ import agent.dbgeng.manager.DbgThread;
|
||||
import agent.dbgeng.manager.impl.*;
|
||||
import ghidra.async.AsyncUtils;
|
||||
import ghidra.async.TypeSpec;
|
||||
import ghidra.dbg.DebuggerModelListener;
|
||||
import ghidra.dbg.error.DebuggerRegisterAccessException;
|
||||
import ghidra.dbg.target.TargetRegisterBank;
|
||||
import ghidra.dbg.util.ConversionUtils;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.datastruct.ListenerSet;
|
||||
|
||||
public interface DbgModelTargetRegisterBank extends DbgModelTargetObject, TargetRegisterBank {
|
||||
|
||||
@@ -91,10 +89,8 @@ public interface DbgModelTargetRegisterBank extends DbgModelTargetObject, Target
|
||||
reg.setModified(value.toString(16).equals(oldval));
|
||||
}
|
||||
}
|
||||
ListenerSet<DebuggerModelListener> listeners = getListeners();
|
||||
if (listeners != null) {
|
||||
listeners.fire.registersUpdated(getProxy(), result);
|
||||
}
|
||||
|
||||
broadcast().registersUpdated(getProxy(), result);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
@@ -126,7 +122,7 @@ public interface DbgModelTargetRegisterBank extends DbgModelTargetObject, Target
|
||||
getParentThread().getThread().writeRegisters(toWrite).handle(seq::next);
|
||||
// TODO: Should probably filter only effective and normalized writes in the callback
|
||||
}).then(seq -> {
|
||||
getListeners().fire.registersUpdated(getProxy(), values);
|
||||
broadcast().registersUpdated(getProxy(), values);
|
||||
seq.exit();
|
||||
}).finish();
|
||||
}
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ public interface DbgModelTargetSession extends //
|
||||
if (!isValid()) {
|
||||
return;
|
||||
}
|
||||
getListeners().fire.consoleOutput(getProxy(), chan, output);
|
||||
broadcast().consoleOutput(getProxy(), chan, output);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ public class DbgModelTargetBreakpointContainerImpl extends DbgModelTargetObjectI
|
||||
DbgModelTargetThread targetThread =
|
||||
getParentProcess().getThreads().getTargetThread(getManager().getEventThread());
|
||||
DbgModelTargetBreakpointSpec spec = getTargetBreakpointSpec(info);
|
||||
listeners.fire.breakpointHit(getProxy(), targetThread, null, spec, spec);
|
||||
broadcast().breakpointHit(getProxy(), targetThread, null, spec, spec);
|
||||
spec.breakpointHit();
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -121,7 +121,7 @@ public class DbgModelTargetMemoryContainerImpl extends DbgModelTargetObjectImpl
|
||||
if (span == null) {
|
||||
throw new DebuggerMemoryAccessException("Cannot read at " + address);
|
||||
}
|
||||
listeners.fire.memoryUpdated(getProxy(), address, buf.array());
|
||||
broadcast().memoryUpdated(getProxy(), address, buf.array());
|
||||
return Arrays.copyOf(buf.array(), (int) span.length());
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ public class DbgModelTargetMemoryContainerImpl extends DbgModelTargetObjectImpl
|
||||
}
|
||||
|
||||
private void writeAssist(Address address, byte[] data) {
|
||||
listeners.fire.memoryUpdated(getProxy(), address, data);
|
||||
broadcast().memoryUpdated(getProxy(), address, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+13
-9
@@ -27,13 +27,16 @@ import ghidra.dbg.target.schema.*;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema.ResyncMode;
|
||||
import ghidra.lifecycle.Internal;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "ModuleContainer", elements = { //
|
||||
@TargetElementType(type = DbgModelTargetModuleImpl.class) //
|
||||
}, //
|
||||
elementResync = ResyncMode.ONCE, //
|
||||
attributes = { //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
}, canonicalContainer = true)
|
||||
@TargetObjectSchemaInfo(
|
||||
name = "ModuleContainer",
|
||||
elements = {
|
||||
@TargetElementType(type = DbgModelTargetModuleImpl.class)
|
||||
},
|
||||
elementResync = ResyncMode.ONCE,
|
||||
attributes = {
|
||||
@TargetAttributeType(type = Void.class)
|
||||
},
|
||||
canonicalContainer = true)
|
||||
public class DbgModelTargetModuleContainerImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetModuleContainer {
|
||||
// NOTE: -file-list-shared-libraries omits the main module and system-supplied DSO.
|
||||
@@ -66,7 +69,7 @@ public class DbgModelTargetModuleContainerImpl extends DbgModelTargetObjectImpl
|
||||
TargetThread eventThread =
|
||||
(TargetThread) getModel().getModelObject(getManager().getEventThread());
|
||||
changeElements(List.of(), List.of(module), Map.of(), "Loaded");
|
||||
getListeners().fire.event(getProxy(), eventThread, TargetEventType.MODULE_LOADED,
|
||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_LOADED,
|
||||
"Library " + name + " loaded", List.of(module));
|
||||
}
|
||||
|
||||
@@ -77,7 +80,7 @@ public class DbgModelTargetModuleContainerImpl extends DbgModelTargetObjectImpl
|
||||
if (targetModule != null) {
|
||||
TargetThread eventThread =
|
||||
(TargetThread) getModel().getModelObject(getManager().getEventThread());
|
||||
getListeners().fire.event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED,
|
||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED,
|
||||
"Library " + name + " unloaded", List.of(targetModule));
|
||||
DbgModelImpl impl = (DbgModelImpl) model;
|
||||
impl.deleteModelObject(targetModule.getDbgModule());
|
||||
@@ -108,6 +111,7 @@ public class DbgModelTargetModuleContainerImpl extends DbgModelTargetObjectImpl
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public DbgModelTargetModule getTargetModule(String name) {
|
||||
// Only get here from libraryLoaded or getElements. The known list should be fresh.
|
||||
DbgModule module = process.getKnownModules().get(name);
|
||||
|
||||
+6
-6
@@ -33,12 +33,12 @@ import ghidra.dbg.target.schema.*;
|
||||
|
||||
@TargetObjectSchemaInfo(
|
||||
name = "ProcessContainer",
|
||||
elements = { //
|
||||
@TargetElementType(type = DbgModelTargetProcessImpl.class) //
|
||||
elements = {
|
||||
@TargetElementType(type = DbgModelTargetProcessImpl.class)
|
||||
},
|
||||
attributes = { //
|
||||
@TargetAttributeType(name = TargetConfigurable.BASE_ATTRIBUTE_NAME, type = Integer.class), //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
attributes = {
|
||||
@TargetAttributeType(name = TargetConfigurable.BASE_ATTRIBUTE_NAME, type = Integer.class),
|
||||
@TargetAttributeType(type = Void.class)
|
||||
},
|
||||
canonicalContainer = true)
|
||||
public class DbgModelTargetProcessContainerImpl extends DbgModelTargetObjectImpl
|
||||
@@ -58,7 +58,7 @@ public class DbgModelTargetProcessContainerImpl extends DbgModelTargetObjectImpl
|
||||
DbgModelTargetProcess process = getTargetProcess(proc);
|
||||
changeElements(List.of(), List.of(process), Map.of(), "Added");
|
||||
process.processStarted(proc.getPid());
|
||||
getListeners().fire.event(getProxy(), null, TargetEventType.PROCESS_CREATED,
|
||||
broadcast().event(getProxy(), null, TargetEventType.PROCESS_CREATED,
|
||||
"Process " + proc.getId() + " started " + process.getName() + "pid=" + proc.getPid(),
|
||||
List.of(process));
|
||||
}
|
||||
|
||||
+3
-2
@@ -139,6 +139,7 @@ public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void threadStateChangedSpecific(DbgThread thread, DbgState state) {
|
||||
TargetExecutionState targetState = convertState(state);
|
||||
setExecutionState(targetState, "ThreadStateChanged");
|
||||
@@ -212,7 +213,7 @@ public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
|
||||
STATE_ATTRIBUTE_NAME, TargetExecutionState.TERMINATED, //
|
||||
EXIT_CODE_ATTRIBUTE_NAME, proc.getExitCode() //
|
||||
), "Exited");
|
||||
getListeners().fire.event(getProxy(), null, TargetEventType.PROCESS_EXITED,
|
||||
broadcast().event(getProxy(), null, TargetEventType.PROCESS_EXITED,
|
||||
"Process " + proc.getId() + " exited code=" + proc.getExitCode(),
|
||||
List.of(getProxy()));
|
||||
}
|
||||
@@ -221,7 +222,7 @@ public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
|
||||
@Override
|
||||
public void memoryChanged(DbgProcess proc, long addr, int len, DbgCause cause) {
|
||||
if (proc.equals(this.process)) {
|
||||
listeners.fire.invalidateCacheRequested(memory);
|
||||
broadcast().invalidateCacheRequested(memory);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -134,7 +134,7 @@ public class DbgModelTargetRegisterContainerImpl extends DbgModelTargetObjectImp
|
||||
changeAttrs(reg, value);
|
||||
}
|
||||
this.values = result;
|
||||
listeners.fire.registersUpdated(getProxy(), result);
|
||||
broadcast().registersUpdated(getProxy(), result);
|
||||
return result;
|
||||
}));
|
||||
}
|
||||
@@ -159,7 +159,7 @@ public class DbgModelTargetRegisterContainerImpl extends DbgModelTargetObjectImp
|
||||
return thread.writeRegisters(toWrite);
|
||||
// TODO: Should probably filter only effective and normalized writes in the callback
|
||||
}).thenAccept(__ -> {
|
||||
listeners.fire.registersUpdated(getProxy(), values);
|
||||
broadcast().registersUpdated(getProxy(), values);
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
+13
-9
@@ -31,12 +31,16 @@ import ghidra.dbg.target.TargetConfigurable;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
|
||||
@TargetObjectSchemaInfo(name = "ThreadContainer", elements = { //
|
||||
@TargetElementType(type = DbgModelTargetThreadImpl.class) //
|
||||
}, attributes = { //
|
||||
@TargetAttributeType(name = TargetConfigurable.BASE_ATTRIBUTE_NAME, type = Integer.class), //
|
||||
@TargetAttributeType(type = Void.class) //
|
||||
}, canonicalContainer = true)
|
||||
@TargetObjectSchemaInfo(
|
||||
name = "ThreadContainer",
|
||||
elements = {
|
||||
@TargetElementType(type = DbgModelTargetThreadImpl.class)
|
||||
},
|
||||
attributes = {
|
||||
@TargetAttributeType(name = TargetConfigurable.BASE_ATTRIBUTE_NAME, type = Integer.class),
|
||||
@TargetAttributeType(type = Void.class)
|
||||
},
|
||||
canonicalContainer = true)
|
||||
public class DbgModelTargetThreadContainerImpl extends DbgModelTargetObjectImpl
|
||||
implements DbgModelTargetThreadContainer, DbgModelTargetConfigurable {
|
||||
|
||||
@@ -59,7 +63,7 @@ public class DbgModelTargetThreadContainerImpl extends DbgModelTargetObjectImpl
|
||||
DbgModelTargetThread targetThread = getTargetThread(thread);
|
||||
changeElements(List.of(), List.of(targetThread), Map.of(), "Created");
|
||||
targetThread.threadStateChangedSpecific(DbgState.STARTING, DbgReason.getReason(null));
|
||||
getListeners().fire.event(getProxy(), targetThread, TargetEventType.THREAD_CREATED,
|
||||
broadcast().event(getProxy(), targetThread, TargetEventType.THREAD_CREATED,
|
||||
"Thread " + thread.getId() + " started", List.of(targetThread));
|
||||
}
|
||||
|
||||
@@ -68,7 +72,7 @@ public class DbgModelTargetThreadContainerImpl extends DbgModelTargetObjectImpl
|
||||
DbgReason reason) {
|
||||
DbgModelTargetThread targetThread = getTargetThread(thread);
|
||||
TargetEventType eventType = getEventType(state, cause, reason);
|
||||
getListeners().fire.event(getProxy(), targetThread, eventType,
|
||||
broadcast().event(getProxy(), targetThread, eventType,
|
||||
"Thread " + thread.getId() + " state changed", List.of(targetThread));
|
||||
targetThread.threadStateChangedSpecific(state, reason);
|
||||
}
|
||||
@@ -78,7 +82,7 @@ public class DbgModelTargetThreadContainerImpl extends DbgModelTargetObjectImpl
|
||||
DbgModelImpl impl = (DbgModelImpl) model;
|
||||
DbgModelTargetThread targetThread = (DbgModelTargetThread) impl.getModelObject(threadId);
|
||||
if (targetThread != null) {
|
||||
getListeners().fire.event(getProxy(), targetThread, TargetEventType.THREAD_EXITED,
|
||||
broadcast().event(getProxy(), targetThread, TargetEventType.THREAD_EXITED,
|
||||
"Thread " + threadId + " exited", List.of(targetThread));
|
||||
}
|
||||
//synchronized (this) {
|
||||
|
||||
+2
-7
@@ -32,7 +32,6 @@ import agent.dbgmodel.jna.dbgmodel.DbgModelNative.ModelObjectKind;
|
||||
import agent.dbgmodel.jna.dbgmodel.DbgModelNative.TypeKind;
|
||||
import agent.dbgmodel.manager.DbgManager2Impl;
|
||||
import ghidra.async.AsyncUtils;
|
||||
import ghidra.dbg.DebuggerModelListener;
|
||||
import ghidra.dbg.agent.DefaultTargetObject;
|
||||
import ghidra.dbg.target.*;
|
||||
import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointKind;
|
||||
@@ -254,7 +253,8 @@ public class DbgModel2TargetObjectImpl extends DefaultTargetObject<TargetObject,
|
||||
TargetExecutionStateful stateful = (TargetExecutionStateful) proxy;
|
||||
TargetExecutionState state = stateful.getExecutionState();
|
||||
attrs.put(TargetExecutionStateful.STATE_ATTRIBUTE_NAME, state);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
attrs.put(TargetExecutionStateful.STATE_ATTRIBUTE_NAME,
|
||||
TargetExecutionState.INACTIVE);
|
||||
}
|
||||
@@ -412,11 +412,6 @@ public class DbgModel2TargetObjectImpl extends DefaultTargetObject<TargetObject,
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(DebuggerModelListener l) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DbgModelTargetSession getParentSession() {
|
||||
DbgModelTargetObject test = (DbgModelTargetObject) parent;
|
||||
|
||||
+8
-8
@@ -179,7 +179,7 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
|
||||
System.err.println("processAdded - null");
|
||||
return;
|
||||
}
|
||||
getListeners().fire.event(getProxy(), null, TargetEventType.PROCESS_CREATED,
|
||||
broadcast().event(getProxy(), null, TargetEventType.PROCESS_CREATED,
|
||||
"Process " + proc.getId() + " started " + "notepad.exe" + " pid=" + proc.getPid(),
|
||||
List.of(targetProcess));
|
||||
});
|
||||
@@ -193,7 +193,7 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
|
||||
System.err.println("threadCreated - null");
|
||||
return;
|
||||
}
|
||||
getListeners().fire.event(getProxy(), targetThread, TargetEventType.THREAD_CREATED,
|
||||
broadcast().event(getProxy(), targetThread, TargetEventType.THREAD_CREATED,
|
||||
"Thread " + thread.getId() + " started", List.of(targetThread));
|
||||
DelegateDbgModel2TargetObject delegate =
|
||||
(DelegateDbgModel2TargetObject) targetThread.getDelegate();
|
||||
@@ -210,7 +210,7 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
|
||||
}
|
||||
getObject(getManager().getEventThread()).thenAccept(t -> {
|
||||
TargetThread eventThread = (TargetThread) t;
|
||||
getListeners().fire.event(getProxy(), eventThread, TargetEventType.MODULE_LOADED,
|
||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_LOADED,
|
||||
"Library " + info.getModuleName() + " loaded", List.of(mod));
|
||||
});
|
||||
getObject(getManager().getEventProcess()).thenAccept(p -> {
|
||||
@@ -231,7 +231,7 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
|
||||
}
|
||||
getObject(getManager().getEventThread()).thenAccept(t -> {
|
||||
TargetThread eventThread = (TargetThread) t;
|
||||
getListeners().fire.event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED,
|
||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED,
|
||||
"Library " + info.getModuleName() + " unloaded", List.of(mod));
|
||||
});
|
||||
getObject(getManager().getEventProcess()).thenAccept(p -> {
|
||||
@@ -369,7 +369,7 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
|
||||
DbgModelTargetProcessImpl.EXIT_CODE_ATTRIBUTE_NAME, proc.getExitCode() //
|
||||
), "Exited");
|
||||
}
|
||||
getListeners().fire.event(targetProcess.getProxy(), null,
|
||||
broadcast().event(targetProcess.getProxy(), null,
|
||||
TargetEventType.PROCESS_EXITED,
|
||||
"Process " + proc.getId() + " exited code=" + proc.getExitCode(),
|
||||
List.of(getProxy()));
|
||||
@@ -383,7 +383,7 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
|
||||
return;
|
||||
}
|
||||
DbgModelTargetThread targetThread = (DbgModelTargetThread) thread.getProxy();
|
||||
getListeners().fire.event(getProxy(), targetThread, TargetEventType.THREAD_EXITED,
|
||||
broadcast().event(getProxy(), targetThread, TargetEventType.THREAD_EXITED,
|
||||
"Thread " + threadId + " exited", List.of(targetThread));
|
||||
});
|
||||
}
|
||||
@@ -401,7 +401,7 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
|
||||
), reason.desc());
|
||||
intrinsics.put(TargetEventScope.EVENT_OBJECT_ATTRIBUTE_NAME, targetThread);
|
||||
TargetEventType eventType = getEventType(state, cause, reason);
|
||||
getListeners().fire.event(getProxy(), targetThread, eventType,
|
||||
broadcast().event(getProxy(), targetThread, eventType,
|
||||
"Thread " + thread.getId() + " state changed", List.of(targetThread));
|
||||
DelegateDbgModel2TargetObject delegate =
|
||||
(DelegateDbgModel2TargetObject) targetThread.getDelegate();
|
||||
@@ -472,7 +472,7 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
|
||||
|
||||
DbgThread thread = info.getEventThread();
|
||||
TargetObject targetThread = getModel().getModelObject(thread);
|
||||
listeners.fire.breakpointHit(bpt.getParent(), targetThread, null, bpt, bpt);
|
||||
broadcast().breakpointHit(bpt.getParent(), targetThread, null, bpt, bpt);
|
||||
bpt.breakpointHit();
|
||||
});
|
||||
}
|
||||
|
||||
-4
@@ -22,11 +22,9 @@ import java.util.concurrent.CompletableFuture;
|
||||
import agent.frida.manager.impl.FridaManagerImpl;
|
||||
import agent.frida.model.AbstractFridaModel;
|
||||
import ghidra.async.AsyncUtils;
|
||||
import ghidra.dbg.DebuggerModelListener;
|
||||
import ghidra.dbg.agent.SpiTargetObject;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.util.CollectionUtils.Delta;
|
||||
import ghidra.util.datastruct.ListenerSet;
|
||||
|
||||
public interface FridaModelTargetObject extends SpiTargetObject {
|
||||
|
||||
@@ -59,8 +57,6 @@ public interface FridaModelTargetObject extends SpiTargetObject {
|
||||
|
||||
public CompletableFuture<List<TargetObject>> requestNativeElements();
|
||||
|
||||
public ListenerSet<DebuggerModelListener> getListeners();
|
||||
|
||||
public FridaModelTargetSession getParentSession();
|
||||
|
||||
public FridaModelTargetProcess getParentProcess();
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ public interface FridaModelTargetSession extends //
|
||||
== DebugOutputFlags.DEBUG_OUTPUT_WARNING.getValue())) {
|
||||
chan = TargetConsole.Channel.STDERR;
|
||||
}
|
||||
getListeners().fire.consoleOutput(getProxy(), chan, output);
|
||||
broadcast().consoleOutput(getProxy(), chan, output);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-3
@@ -80,7 +80,7 @@ public class FridaModelTargetKernelMemoryContainerImpl extends FridaModelTargetO
|
||||
@Override
|
||||
public CompletableFuture<Void> requestElements(boolean refresh) {
|
||||
if (refresh) {
|
||||
listeners.fire.invalidateCacheRequested(this);
|
||||
broadcast().invalidateCacheRequested(this);
|
||||
}
|
||||
return getManager().listKernelMemory();
|
||||
}
|
||||
@@ -104,12 +104,12 @@ public class FridaModelTargetKernelMemoryContainerImpl extends FridaModelTargetO
|
||||
if (range == null) {
|
||||
throw new DebuggerMemoryAccessException("Cannot read at " + address);
|
||||
}
|
||||
listeners.fire.memoryUpdated(getProxy(), address, buf.array());
|
||||
broadcast().memoryUpdated(getProxy(), address, buf.array());
|
||||
return Arrays.copyOf(buf.array(), (int) range.getLength());
|
||||
}
|
||||
|
||||
private void writeAssist(Address address, byte[] data) {
|
||||
listeners.fire.memoryUpdated(getProxy(), address, data);
|
||||
broadcast().memoryUpdated(getProxy(), address, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+11
-8
@@ -72,12 +72,13 @@ public class FridaModelTargetKernelModuleContainerImpl extends FridaModelTargetO
|
||||
TargetThread eventThread =
|
||||
(TargetThread) getModel().getModelObject(thread);
|
||||
changeElements(List.of(), List.of(targetModule), Map.of(), "Loaded");
|
||||
getListeners().fire.event(getProxy(), eventThread, TargetEventType.MODULE_LOADED,
|
||||
"Library " + info.getModuleName(index) + " loaded", List.of(targetModule));
|
||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_LOADED,
|
||||
"Library " + info.getModuleName(index) + " loaded", List.of(targetModule));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moduleReplaced(FridaProcess proc, FridaModuleInfo info, int index, FridaCause cause) {
|
||||
public void moduleReplaced(FridaProcess proc, FridaModuleInfo info, int index,
|
||||
FridaCause cause) {
|
||||
FridaModule module = info.getModule(index);
|
||||
changeElements(List.of(), List.of(getTargetModule(module)), Map.of(), "Replaced");
|
||||
FridaModelTargetModule targetModule = getTargetModule(module);
|
||||
@@ -85,14 +86,15 @@ public class FridaModelTargetKernelModuleContainerImpl extends FridaModelTargetO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moduleUnloaded(FridaProcess proc, FridaModuleInfo info, int index, FridaCause cause) {
|
||||
public void moduleUnloaded(FridaProcess proc, FridaModuleInfo info, int index,
|
||||
FridaCause cause) {
|
||||
FridaModelTargetModule targetModule = getTargetModule(info.getModule(index));
|
||||
if (targetModule != null) {
|
||||
FridaThread thread = getManager().getCurrentThread();
|
||||
TargetThread eventThread =
|
||||
(TargetThread) getModel().getModelObject(thread);
|
||||
getListeners().fire.event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED,
|
||||
"Library " + info.getModuleName(index) + " unloaded", List.of(targetModule));
|
||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED,
|
||||
"Library " + info.getModuleName(index) + " unloaded", List.of(targetModule));
|
||||
FridaModelImpl impl = (FridaModelImpl) model;
|
||||
impl.deleteModelObject(targetModule.getModule());
|
||||
}
|
||||
@@ -112,7 +114,7 @@ public class FridaModelTargetKernelModuleContainerImpl extends FridaModelTargetO
|
||||
@Override
|
||||
public CompletableFuture<Void> requestElements(boolean refresh) {
|
||||
if (refresh) {
|
||||
listeners.fire.invalidateCacheRequested(this);
|
||||
broadcast().invalidateCacheRequested(this);
|
||||
}
|
||||
return getManager().listKernelModules();
|
||||
}
|
||||
@@ -121,7 +123,8 @@ public class FridaModelTargetKernelModuleContainerImpl extends FridaModelTargetO
|
||||
public FridaModelTargetKernelModuleImpl getTargetModule(FridaModule module) {
|
||||
TargetObject targetObject = getMapObject(module);
|
||||
if (targetObject != null) {
|
||||
FridaModelTargetKernelModuleImpl targetModule = (FridaModelTargetKernelModuleImpl) targetObject;
|
||||
FridaModelTargetKernelModuleImpl targetModule =
|
||||
(FridaModelTargetKernelModuleImpl) targetObject;
|
||||
targetModule.setModelObject(module);
|
||||
return targetModule;
|
||||
}
|
||||
|
||||
+3
-3
@@ -102,7 +102,7 @@ public class FridaModelTargetMemoryContainerImpl extends FridaModelTargetObjectI
|
||||
@Override
|
||||
public CompletableFuture<Void> requestElements(boolean refresh) {
|
||||
if (refresh) {
|
||||
listeners.fire.invalidateCacheRequested(this);
|
||||
broadcast().invalidateCacheRequested(this);
|
||||
}
|
||||
return getManager().listMemory(process.getProcess());
|
||||
}
|
||||
@@ -126,12 +126,12 @@ public class FridaModelTargetMemoryContainerImpl extends FridaModelTargetObjectI
|
||||
if (range == null) {
|
||||
throw new DebuggerMemoryAccessException("Cannot read at " + address);
|
||||
}
|
||||
listeners.fire.memoryUpdated(getProxy(), address, buf.array());
|
||||
broadcast().memoryUpdated(getProxy(), address, buf.array());
|
||||
return Arrays.copyOf(buf.array(), (int) range.getLength());
|
||||
}
|
||||
|
||||
private void writeAssist(Address address, byte[] data) {
|
||||
listeners.fire.memoryUpdated(getProxy(), address, data);
|
||||
broadcast().memoryUpdated(getProxy(), address, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+15
-26
@@ -20,25 +20,12 @@ import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import agent.frida.frida.FridaModuleInfo;
|
||||
import agent.frida.manager.FridaCause;
|
||||
import agent.frida.manager.FridaModule;
|
||||
import agent.frida.manager.FridaProcess;
|
||||
import agent.frida.manager.FridaSession;
|
||||
import agent.frida.manager.FridaThread;
|
||||
import agent.frida.model.iface2.FridaModelTargetModule;
|
||||
import agent.frida.model.iface2.FridaModelTargetModuleContainer;
|
||||
import agent.frida.model.iface2.FridaModelTargetSession;
|
||||
import agent.frida.model.methods.FridaModelTargetModuleInitImpl;
|
||||
import agent.frida.model.methods.FridaModelTargetModuleInterceptorImpl;
|
||||
import agent.frida.model.methods.FridaModelTargetModuleLoadImpl;
|
||||
import agent.frida.model.methods.FridaModelTargetUnloadScriptImpl;
|
||||
import ghidra.dbg.target.TargetModule;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.TargetThread;
|
||||
import ghidra.dbg.target.schema.TargetAttributeType;
|
||||
import ghidra.dbg.target.schema.TargetElementType;
|
||||
import agent.frida.manager.*;
|
||||
import agent.frida.model.iface2.*;
|
||||
import agent.frida.model.methods.*;
|
||||
import ghidra.dbg.target.*;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema.ResyncMode;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
@TargetObjectSchemaInfo(
|
||||
@@ -77,7 +64,7 @@ public class FridaModelTargetModuleContainerImpl extends FridaModelTargetObjectI
|
||||
unload //
|
||||
), Map.of( //
|
||||
), "Initialized");
|
||||
|
||||
|
||||
getManager().addEventsListener(this);
|
||||
requestElements(true);
|
||||
}
|
||||
@@ -103,12 +90,13 @@ public class FridaModelTargetModuleContainerImpl extends FridaModelTargetObjectI
|
||||
TargetThread eventThread =
|
||||
(TargetThread) getModel().getModelObject(thread);
|
||||
changeElements(List.of(), List.of(targetModule), Map.of(), "Loaded");
|
||||
getListeners().fire.event(getProxy(), eventThread, TargetEventType.MODULE_LOADED,
|
||||
"Library " + info.getModuleName(index) + " loaded", List.of(targetModule));
|
||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_LOADED,
|
||||
"Library " + info.getModuleName(index) + " loaded", List.of(targetModule));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moduleReplaced(FridaProcess proc, FridaModuleInfo info, int index, FridaCause cause) {
|
||||
public void moduleReplaced(FridaProcess proc, FridaModuleInfo info, int index,
|
||||
FridaCause cause) {
|
||||
FridaModule module = info.getModule(index);
|
||||
changeElements(List.of(), List.of(getTargetModule(module)), Map.of(), "Replaced");
|
||||
FridaModelTargetModule targetModule = getTargetModule(module);
|
||||
@@ -116,14 +104,15 @@ public class FridaModelTargetModuleContainerImpl extends FridaModelTargetObjectI
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moduleUnloaded(FridaProcess proc, FridaModuleInfo info, int index, FridaCause cause) {
|
||||
public void moduleUnloaded(FridaProcess proc, FridaModuleInfo info, int index,
|
||||
FridaCause cause) {
|
||||
FridaModelTargetModule targetModule = getTargetModule(info.getModule(index));
|
||||
if (targetModule != null) {
|
||||
FridaThread thread = getManager().getCurrentThread();
|
||||
TargetThread eventThread =
|
||||
(TargetThread) getModel().getModelObject(thread);
|
||||
getListeners().fire.event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED,
|
||||
"Library " + info.getModuleName(index) + " unloaded", List.of(targetModule));
|
||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED,
|
||||
"Library " + info.getModuleName(index) + " unloaded", List.of(targetModule));
|
||||
FridaModelImpl impl = (FridaModelImpl) model;
|
||||
impl.deleteModelObject(targetModule.getModule());
|
||||
}
|
||||
@@ -143,7 +132,7 @@ public class FridaModelTargetModuleContainerImpl extends FridaModelTargetObjectI
|
||||
@Override
|
||||
public CompletableFuture<Void> requestElements(boolean refresh) {
|
||||
if (refresh) {
|
||||
listeners.fire.invalidateCacheRequested(this);
|
||||
broadcast().invalidateCacheRequested(this);
|
||||
}
|
||||
return getManager().listModules(session.getProcess());
|
||||
}
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ public class FridaModelTargetProcessContainerImpl extends FridaModelTargetObject
|
||||
FridaModelTargetProcess process = getTargetProcess(proc);
|
||||
changeElements(List.of(), List.of(process), Map.of(), "Added");
|
||||
process.processStarted(proc);
|
||||
getListeners().fire.event(getProxy(), null, TargetEventType.PROCESS_CREATED,
|
||||
broadcast().event(getProxy(), null, TargetEventType.PROCESS_CREATED,
|
||||
"Process " + FridaClient.getId(proc) + " started " + process.getName(),
|
||||
List.of(process));
|
||||
}
|
||||
|
||||
+1
-1
@@ -236,7 +236,7 @@ public class FridaModelTargetProcessImpl extends FridaModelTargetObjectImpl
|
||||
STATE_ATTRIBUTE_NAME, TargetExecutionState.TERMINATED, //
|
||||
EXIT_CODE_ATTRIBUTE_NAME, exitDesc //
|
||||
), "Exited");
|
||||
getListeners().fire.event(getProxy(), null, TargetEventType.PROCESS_EXITED,
|
||||
broadcast().event(getProxy(), null, TargetEventType.PROCESS_EXITED,
|
||||
"Process " + FridaClient.getId(getProcess()) + " exited code=" + exitDesc,
|
||||
List.of(getProxy()));
|
||||
}
|
||||
|
||||
+19
-32
@@ -16,42 +16,31 @@
|
||||
package agent.frida.model.impl;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import agent.frida.manager.FridaReason;
|
||||
import agent.frida.manager.FridaState;
|
||||
import agent.frida.manager.FridaValue;
|
||||
import agent.frida.model.iface2.FridaModelTargetRegister;
|
||||
import agent.frida.model.iface2.FridaModelTargetRegisterBank;
|
||||
import agent.frida.model.iface2.FridaModelTargetRegisterContainerAndBank;
|
||||
import agent.frida.manager.*;
|
||||
import agent.frida.model.iface2.*;
|
||||
import ghidra.async.AsyncUtils;
|
||||
import ghidra.dbg.DebuggerModelListener;
|
||||
import ghidra.dbg.error.DebuggerRegisterAccessException;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.TargetRegisterBank;
|
||||
import ghidra.dbg.target.schema.TargetAttributeType;
|
||||
import ghidra.dbg.target.schema.TargetElementType;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema.ResyncMode;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
|
||||
import ghidra.util.datastruct.ListenerSet;
|
||||
|
||||
@TargetObjectSchemaInfo(
|
||||
name = "RegisterContainer",
|
||||
attributeResync = ResyncMode.ALWAYS,
|
||||
elements = { //
|
||||
@TargetElementType(type = FridaModelTargetRegisterImpl.class) //
|
||||
@TargetElementType(type = FridaModelTargetRegisterImpl.class) //
|
||||
},
|
||||
attributes = {
|
||||
@TargetAttributeType(
|
||||
name = TargetRegisterBank.DESCRIPTIONS_ATTRIBUTE_NAME,
|
||||
type = FridaModelTargetRegisterContainerImpl.class),
|
||||
@TargetAttributeType(type = Void.class)
|
||||
@TargetAttributeType(
|
||||
name = TargetRegisterBank.DESCRIPTIONS_ATTRIBUTE_NAME,
|
||||
type = FridaModelTargetRegisterContainerImpl.class),
|
||||
@TargetAttributeType(type = Void.class)
|
||||
},
|
||||
canonicalContainer = true)
|
||||
public class FridaModelTargetRegisterContainerImpl
|
||||
@@ -64,10 +53,10 @@ public class FridaModelTargetRegisterContainerImpl
|
||||
public FridaModelTargetRegisterContainerImpl(FridaModelTargetThreadImpl thread) {
|
||||
super(thread.getModel(), thread, NAME, "RegisterContainer");
|
||||
this.thread = thread;
|
||||
|
||||
|
||||
changeAttributes(List.of(), List.of(), Map.of(
|
||||
DISPLAY_ATTRIBUTE_NAME, getName(),
|
||||
DESCRIPTIONS_ATTRIBUTE_NAME, this), "Initialized");
|
||||
DISPLAY_ATTRIBUTE_NAME, getName(),
|
||||
DESCRIPTIONS_ATTRIBUTE_NAME, this), "Initialized");
|
||||
|
||||
requestElements(false);
|
||||
}
|
||||
@@ -78,7 +67,7 @@ public class FridaModelTargetRegisterContainerImpl
|
||||
@Override
|
||||
public CompletableFuture<Void> requestElements(boolean refresh) {
|
||||
if (refresh) {
|
||||
listeners.fire.invalidateCacheRequested(this);
|
||||
broadcast().invalidateCacheRequested(this);
|
||||
}
|
||||
return getManager().listRegisters(thread.getThread()).thenAccept(registers -> {
|
||||
List<TargetObject> targetRegisters;
|
||||
@@ -114,7 +103,8 @@ public class FridaModelTargetRegisterContainerImpl
|
||||
requestAttributes(false).thenAccept(__ -> {
|
||||
for (Object attribute : getCachedAttributes().values()) {
|
||||
if (attribute instanceof FridaModelTargetRegisterBank) {
|
||||
FridaModelTargetRegisterBank bank = (FridaModelTargetRegisterBank) attribute;
|
||||
FridaModelTargetRegisterBank bank =
|
||||
(FridaModelTargetRegisterBank) attribute;
|
||||
bank.threadStateChangedSpecific(state, reason);
|
||||
}
|
||||
}
|
||||
@@ -136,12 +126,9 @@ public class FridaModelTargetRegisterContainerImpl
|
||||
byte[] bytes = register.getBytes();
|
||||
result.put(regname, bytes);
|
||||
}
|
||||
ListenerSet<DebuggerModelListener> ls = getListeners();
|
||||
if (ls != null) {
|
||||
//if (getName().contains("General")) {
|
||||
ls.fire.registersUpdated(this, result);
|
||||
//}
|
||||
}
|
||||
//if (getName().contains("General")) {
|
||||
broadcast().registersUpdated(this, result);
|
||||
//}
|
||||
return CompletableFuture.completedFuture(result);
|
||||
}
|
||||
|
||||
@@ -158,7 +145,7 @@ public class FridaModelTargetRegisterContainerImpl
|
||||
BigInteger val = new BigInteger(1, ent.getValue());
|
||||
reg.getRegister().setValue(val.toString());
|
||||
}
|
||||
getListeners().fire.registersUpdated(getProxy(), values);
|
||||
broadcast().registersUpdated(getProxy(), values);
|
||||
return AsyncUtils.NIL;
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -76,7 +76,7 @@ public class FridaModelTargetThreadContainerImpl extends FridaModelTargetObjectI
|
||||
changeElements(List.of(), List.of(targetThread), Map.of(), "Created");
|
||||
targetThread.threadStateChangedSpecific(FridaState.FRIDA_THREAD_UNINTERRUPTIBLE,
|
||||
FridaReason.getReason(null));
|
||||
getListeners().fire.event(getProxy(), targetThread, TargetEventType.THREAD_CREATED,
|
||||
broadcast().event(getProxy(), targetThread, TargetEventType.THREAD_CREATED,
|
||||
"Thread " + FridaClient.getId(thread) + " started", List.of(targetThread));
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ public class FridaModelTargetThreadContainerImpl extends FridaModelTargetObjectI
|
||||
String threadId = FridaModelTargetThreadImpl.indexThread(thread);
|
||||
FridaModelTargetThread targetThread = (FridaModelTargetThread) getMapObject(thread);
|
||||
if (targetThread != null) {
|
||||
getListeners().fire.event(getProxy(), targetThread, TargetEventType.THREAD_EXITED,
|
||||
broadcast().event(getProxy(), targetThread, TargetEventType.THREAD_EXITED,
|
||||
"Thread " + threadId + " exited", List.of(targetThread));
|
||||
}
|
||||
changeElements(List.of( //
|
||||
@@ -108,7 +108,7 @@ public class FridaModelTargetThreadContainerImpl extends FridaModelTargetObjectI
|
||||
FridaReason reason) {
|
||||
FridaModelTargetThread targetThread = getTargetThread(thread);
|
||||
TargetEventType eventType = getEventType(state, cause, reason);
|
||||
getListeners().fire.event(getProxy(), targetThread, eventType,
|
||||
broadcast().event(getProxy(), targetThread, eventType,
|
||||
"Thread " + FridaClient.getId(thread) + " state changed", List.of(targetThread));
|
||||
targetThread.threadStateChangedSpecific(state, reason);
|
||||
}
|
||||
@@ -133,7 +133,7 @@ public class FridaModelTargetThreadContainerImpl extends FridaModelTargetObjectI
|
||||
@Override
|
||||
public CompletableFuture<Void> requestElements(boolean refresh) {
|
||||
if (refresh) {
|
||||
listeners.fire.invalidateCacheRequested(this);
|
||||
broadcast().invalidateCacheRequested(this);
|
||||
}
|
||||
return getManager().listThreads(process);
|
||||
}
|
||||
|
||||
+1
-1
@@ -102,7 +102,7 @@ public class GdbModelTargetBreakpointContainer
|
||||
spec + " (pc=" + frame.getProgramCounter() + ")");
|
||||
//return; // Not ideal, but eb == null should be fine, since the spec holds the actions
|
||||
}
|
||||
listeners.fire.breakpointHit(this, frame.thread, frame, spec, loc);
|
||||
broadcast().breakpointHit(this, frame.thread, frame, spec, loc);
|
||||
spec.breakpointHit(frame, loc);
|
||||
return loc;
|
||||
}
|
||||
|
||||
+12
-13
@@ -186,7 +186,6 @@ public class GdbModelTargetInferior
|
||||
return impl.gateFuture(inferior.cont());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> step(TargetStepKind kind) {
|
||||
switch (kind) {
|
||||
@@ -210,7 +209,7 @@ public class GdbModelTargetInferior
|
||||
public CompletableFuture<Void> interrupt() {
|
||||
return impl.session.interrupt();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> attach(TargetAttachable attachable) {
|
||||
GdbModelTargetAttachable mine = impl.assertMine(GdbModelTargetAttachable.class, attachable);
|
||||
@@ -233,7 +232,7 @@ public class GdbModelTargetInferior
|
||||
}
|
||||
|
||||
protected CompletableFuture<Void> inferiorStarted(Long pid) {
|
||||
parent.getListeners().fire.event(parent, null, TargetEventType.PROCESS_CREATED,
|
||||
broadcast().event(parent, null, TargetEventType.PROCESS_CREATED,
|
||||
"Inferior " + inferior.getId() + " started " + inferior.getExecutable() + " pid=" + pid,
|
||||
List.of(this));
|
||||
/*System.err.println("inferiorStarted: realState = " + realState);
|
||||
@@ -315,28 +314,28 @@ public class GdbModelTargetInferior
|
||||
params.add(loc);
|
||||
}
|
||||
gatherThreads(params, sco.getAffectedThreads());
|
||||
impl.session.getListeners().fire.event(impl.session, targetEventThread,
|
||||
TargetEventType.BREAKPOINT_HIT, bpHit.desc(), params);
|
||||
broadcast().event(impl.session, targetEventThread, TargetEventType.BREAKPOINT_HIT,
|
||||
bpHit.desc(), params);
|
||||
}
|
||||
else if (reason instanceof GdbEndSteppingRangeReason) {
|
||||
List<Object> params = new ArrayList<>();
|
||||
gatherThreads(params, sco.getAffectedThreads());
|
||||
impl.session.getListeners().fire.event(impl.session, targetEventThread,
|
||||
TargetEventType.STEP_COMPLETED, reason.desc(), params);
|
||||
broadcast().event(impl.session, targetEventThread, TargetEventType.STEP_COMPLETED,
|
||||
reason.desc(), params);
|
||||
}
|
||||
else if (reason instanceof GdbSignalReceivedReason) {
|
||||
GdbSignalReceivedReason signal = (GdbSignalReceivedReason) reason;
|
||||
List<Object> params = new ArrayList<>();
|
||||
params.add(signal.getSignalName());
|
||||
gatherThreads(params, sco.getAffectedThreads());
|
||||
impl.session.getListeners().fire.event(impl.session, targetEventThread,
|
||||
TargetEventType.SIGNAL, reason.desc(), params);
|
||||
broadcast().event(impl.session, targetEventThread, TargetEventType.SIGNAL,
|
||||
reason.desc(), params);
|
||||
}
|
||||
else {
|
||||
List<Object> params = new ArrayList<>();
|
||||
gatherThreads(params, sco.getAffectedThreads());
|
||||
impl.session.getListeners().fire.event(impl.session, targetEventThread,
|
||||
TargetEventType.STOPPED, reason.desc(), params);
|
||||
broadcast().event(impl.session, targetEventThread, TargetEventType.STOPPED,
|
||||
reason.desc(), params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,8 +444,8 @@ public class GdbModelTargetInferior
|
||||
threads.getTargetThread(sco.getAffectedThreads().iterator().next());
|
||||
}
|
||||
if (targetEventThread != null) {
|
||||
impl.session.getListeners().fire.event(impl.session, targetEventThread,
|
||||
TargetEventType.RUNNING, "Running", params);
|
||||
broadcast().event(impl.session, targetEventThread, TargetEventType.RUNNING,
|
||||
"Running", params);
|
||||
invalidateMemoryAndRegisterCaches();
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -71,7 +71,7 @@ public class GdbModelTargetInferiorContainer
|
||||
@Override
|
||||
public void inferiorExited(GdbInferior inf, GdbCause cause) {
|
||||
GdbModelTargetInferior inferior = getTargetInferior(inf);
|
||||
parent.getListeners().fire.event(parent, null, TargetEventType.PROCESS_EXITED,
|
||||
broadcast().event(parent, null, TargetEventType.PROCESS_EXITED,
|
||||
"Inferior " + inf.getId() + " exited code=" + inf.getExitCode(), List.of(inferior));
|
||||
inferior.inferiorExited(inf.getExitCode());
|
||||
}
|
||||
@@ -89,7 +89,7 @@ public class GdbModelTargetInferiorContainer
|
||||
public void threadCreated(GdbThread thread, GdbCause cause) {
|
||||
GdbModelTargetInferior inferior = getTargetInferior(thread.getInferior());
|
||||
GdbModelTargetThread targetThread = inferior.threads.threadCreated(thread);
|
||||
parent.getListeners().fire.event(parent, targetThread, TargetEventType.THREAD_CREATED,
|
||||
broadcast().event(parent, targetThread, TargetEventType.THREAD_CREATED,
|
||||
"Thread " + thread.getId() + " started", List.of(targetThread));
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public class GdbModelTargetInferiorContainer
|
||||
GdbModelTargetInferior inferior = getTargetInferior(inf);
|
||||
GdbModelTargetThread targetThread =
|
||||
inferior.threads.getCachedElements().get(GdbModelTargetThread.indexThread(threadId));
|
||||
parent.getListeners().fire.event(parent, targetThread, TargetEventType.THREAD_EXITED,
|
||||
broadcast().event(parent, targetThread, TargetEventType.THREAD_EXITED,
|
||||
"Thread " + threadId + " exited", List.of(targetThread));
|
||||
inferior.threads.threadExited(threadId);
|
||||
}
|
||||
@@ -107,7 +107,7 @@ public class GdbModelTargetInferiorContainer
|
||||
public void libraryLoaded(GdbInferior inf, String name, GdbCause cause) {
|
||||
GdbModelTargetInferior inferior = getTargetInferior(inf);
|
||||
GdbModelTargetModule module = inferior.modules.libraryLoaded(name);
|
||||
parent.getListeners().fire.event(parent, null, TargetEventType.MODULE_LOADED,
|
||||
broadcast().event(parent, null, TargetEventType.MODULE_LOADED,
|
||||
"Library " + name + " loaded", List.of(module));
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ public class GdbModelTargetInferiorContainer
|
||||
public void libraryUnloaded(GdbInferior inf, String name, GdbCause cause) {
|
||||
GdbModelTargetInferior inferior = getTargetInferior(inf);
|
||||
GdbModelTargetModule module = inferior.modules.getTargetModuleIfPresent(name);
|
||||
parent.getListeners().fire.event(parent, null, TargetEventType.MODULE_UNLOADED,
|
||||
broadcast().event(parent, null, TargetEventType.MODULE_UNLOADED,
|
||||
"Library " + name + " unloaded", List.of(module));
|
||||
inferior.modules.libraryUnloaded(name);
|
||||
}
|
||||
|
||||
+5
-5
@@ -159,7 +159,7 @@ public class GdbModelTargetProcessMemory
|
||||
throw new DebuggerMemoryAccessException("Cannot read at " + address);
|
||||
}
|
||||
byte[] content = Arrays.copyOf(buf.array(), (int) s.length());
|
||||
listeners.fire.memoryUpdated(this, address, content);
|
||||
broadcast().memoryUpdated(this, address, content);
|
||||
return content;
|
||||
}).exceptionally(e -> {
|
||||
e = AsyncUtils.unwrapThrowable(e);
|
||||
@@ -167,10 +167,10 @@ public class GdbModelTargetProcessMemory
|
||||
GdbCommandError gce = (GdbCommandError) e;
|
||||
e = new DebuggerMemoryAccessException(
|
||||
"Cannot read at " + address + ": " + gce.getInfo().getString("msg"));
|
||||
listeners.fire.memoryReadError(this, range, (DebuggerMemoryAccessException) e);
|
||||
broadcast().memoryReadError(this, range, (DebuggerMemoryAccessException) e);
|
||||
}
|
||||
if (e instanceof DebuggerMemoryAccessException) {
|
||||
listeners.fire.memoryReadError(this, range, (DebuggerMemoryAccessException) e);
|
||||
broadcast().memoryReadError(this, range, (DebuggerMemoryAccessException) e);
|
||||
}
|
||||
return ExceptionUtils.rethrow(e);
|
||||
});
|
||||
@@ -186,12 +186,12 @@ public class GdbModelTargetProcessMemory
|
||||
CompletableFuture<Void> future =
|
||||
inferior.writeMemory(address.getOffset(), ByteBuffer.wrap(data));
|
||||
return impl.gateFuture(future.thenAccept(__ -> {
|
||||
listeners.fire.memoryUpdated(this, address, data);
|
||||
broadcast().memoryUpdated(this, address, data);
|
||||
}));
|
||||
}
|
||||
|
||||
protected void invalidateMemoryCaches() {
|
||||
listeners.fire.invalidateCacheRequested(this);
|
||||
broadcast().invalidateCacheRequested(this);
|
||||
}
|
||||
|
||||
public void memoryChanged(long offset, int len) {
|
||||
|
||||
+1
-1
@@ -147,7 +147,7 @@ public class GdbModelTargetSession extends DefaultTargetModelRoot
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
listeners.fire.consoleOutput(this, dbgChannel, out);
|
||||
broadcast().consoleOutput(this, dbgChannel, out);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -110,7 +110,7 @@ public class GdbModelTargetStackFrame
|
||||
}
|
||||
|
||||
protected void invalidateRegisterCaches() {
|
||||
listeners.fire.invalidateCacheRequested(this);
|
||||
broadcast().invalidateCacheRequested(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -117,7 +117,7 @@ public class GdbModelTargetStackFrameRegisterContainer
|
||||
elements.get(regName).stateChanged(bytes);
|
||||
}
|
||||
this.regValues = result;
|
||||
listeners.fire.registersUpdated(this, result);
|
||||
broadcast().registersUpdated(this, result);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
-4
@@ -22,11 +22,9 @@ import java.util.concurrent.CompletableFuture;
|
||||
import agent.lldb.manager.impl.LldbManagerImpl;
|
||||
import agent.lldb.model.AbstractLldbModel;
|
||||
import ghidra.async.AsyncUtils;
|
||||
import ghidra.dbg.DebuggerModelListener;
|
||||
import ghidra.dbg.agent.SpiTargetObject;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.util.CollectionUtils.Delta;
|
||||
import ghidra.util.datastruct.ListenerSet;
|
||||
|
||||
public interface LldbModelTargetObject extends SpiTargetObject {
|
||||
|
||||
@@ -59,8 +57,6 @@ public interface LldbModelTargetObject extends SpiTargetObject {
|
||||
|
||||
public CompletableFuture<List<TargetObject>> requestNativeElements();
|
||||
|
||||
public ListenerSet<DebuggerModelListener> getListeners();
|
||||
|
||||
public LldbModelTargetSession getParentSession();
|
||||
|
||||
public LldbModelTargetProcess getParentProcess();
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ public interface LldbModelTargetSession extends //
|
||||
if (output.contains("loaded *kernel* extension dll for usermode")) {
|
||||
return;
|
||||
}
|
||||
getListeners().fire.consoleOutput(getProxy(), chan, output);
|
||||
broadcast().consoleOutput(getProxy(), chan, output);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+11
-8
@@ -47,8 +47,7 @@ public class LldbModelTargetBreakpointContainerImpl extends LldbModelTargetObjec
|
||||
TargetBreakpointKind.SW_EXECUTE,
|
||||
//TargetBreakpointKind.HW_EXECUTE,
|
||||
TargetBreakpointKind.READ,
|
||||
TargetBreakpointKind.WRITE
|
||||
);
|
||||
TargetBreakpointKind.WRITE);
|
||||
|
||||
private final SBTarget session;
|
||||
|
||||
@@ -98,22 +97,25 @@ public class LldbModelTargetBreakpointContainerImpl extends LldbModelTargetObjec
|
||||
BigInteger bptId = t.GetStopReasonDataAtIndex(0);
|
||||
BigInteger locId = t.GetStopReasonDataAtIndex(1);
|
||||
if (bpt.GetID() == bptId.intValue()) {
|
||||
LldbModelTargetProcess targetProcess = (LldbModelTargetProcess) getModel().getModelObject(eventProcess);
|
||||
LldbModelTargetProcess targetProcess =
|
||||
(LldbModelTargetProcess) getModel().getModelObject(eventProcess);
|
||||
LldbModelTargetThread targetThread =
|
||||
targetProcess.getThreads().getTargetThread(t);
|
||||
targetProcess.getThreads().getTargetThread(t);
|
||||
LldbModelTargetBreakpointSpec spec = getTargetBreakpointSpec(bpt);
|
||||
if (spec == null) {
|
||||
Msg.error(this, "Stopped for breakpoint unknown to the agent: " + bpt + " (pc=" +
|
||||
targetThread + ")");
|
||||
Msg.error(this,
|
||||
"Stopped for breakpoint unknown to the agent: " + bpt + " (pc=" +
|
||||
targetThread + ")");
|
||||
return;
|
||||
}
|
||||
|
||||
LldbModelTargetBreakpointLocation loc = spec.findLocation(locId);
|
||||
if (loc == null) {
|
||||
Msg.warn(this,
|
||||
"Stopped for a breakpoint whose location is unknown to the agent: " + spec);
|
||||
"Stopped for a breakpoint whose location is unknown to the agent: " +
|
||||
spec);
|
||||
}
|
||||
listeners.fire.breakpointHit(this, targetThread, null, spec, loc);
|
||||
broadcast().breakpointHit(this, targetThread, null, spec, loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,6 +150,7 @@ public class LldbModelTargetBreakpointContainerImpl extends LldbModelTargetObjec
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public SBTarget getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
+2
-2
@@ -87,12 +87,12 @@ public class LldbModelTargetMemoryContainerImpl extends LldbModelTargetObjectImp
|
||||
if (range == null) {
|
||||
throw new DebuggerMemoryAccessException("Cannot read at " + address);
|
||||
}
|
||||
listeners.fire.memoryUpdated(getProxy(), address, buf.array());
|
||||
broadcast().memoryUpdated(getProxy(), address, buf.array());
|
||||
return Arrays.copyOf(buf.array(), (int) range.getLength());
|
||||
}
|
||||
|
||||
private void writeAssist(Address address, byte[] data) {
|
||||
listeners.fire.memoryUpdated(getProxy(), address, data);
|
||||
broadcast().memoryUpdated(getProxy(), address, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-4
@@ -72,8 +72,8 @@ public class LldbModelTargetModuleContainerImpl extends LldbModelTargetObjectImp
|
||||
TargetThread eventThread =
|
||||
(TargetThread) getModel().getModelObject(thread);
|
||||
changeElements(List.of(), List.of(targetModule), Map.of(), "Loaded");
|
||||
getListeners().fire.event(getProxy(), eventThread, TargetEventType.MODULE_LOADED,
|
||||
"Library " + info.getModuleName(index) + " loaded", List.of(targetModule));
|
||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_LOADED,
|
||||
"Library " + info.getModuleName(index) + " loaded", List.of(targetModule));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,8 +84,8 @@ public class LldbModelTargetModuleContainerImpl extends LldbModelTargetObjectImp
|
||||
SBThread thread = getManager().getEventThread();
|
||||
TargetThread eventThread =
|
||||
(TargetThread) getModel().getModelObject(thread);
|
||||
getListeners().fire.event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED,
|
||||
"Library " + info.getModuleName(index) + " unloaded", List.of(targetModule));
|
||||
broadcast().event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED,
|
||||
"Library " + info.getModuleName(index) + " unloaded", List.of(targetModule));
|
||||
LldbModelImpl impl = (LldbModelImpl) model;
|
||||
impl.deleteModelObject(targetModule.getModule());
|
||||
}
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ public class LldbModelTargetProcessContainerImpl extends LldbModelTargetObjectIm
|
||||
LldbModelTargetProcess process = getTargetProcess(proc);
|
||||
changeElements(List.of(), List.of(process), Map.of(), "Added");
|
||||
process.processStarted(proc);
|
||||
getListeners().fire.event(getProxy(), null, TargetEventType.PROCESS_CREATED,
|
||||
broadcast().event(getProxy(), null, TargetEventType.PROCESS_CREATED,
|
||||
"Process " + DebugClient.getId(proc) + " started " + process.getName(),
|
||||
List.of(process));
|
||||
}
|
||||
|
||||
+2
-2
@@ -153,7 +153,7 @@ public class LldbModelTargetProcessImpl extends LldbModelTargetObjectImpl
|
||||
threads.requestElements(true);
|
||||
StopReason stopReason = getManager().getCurrentThread().GetStopReason();
|
||||
if (!stopReason.equals(StopReason.eStopReasonPlanComplete)) {
|
||||
memory.requestElements(true);
|
||||
memory.requestElements(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -245,7 +245,7 @@ public class LldbModelTargetProcessImpl extends LldbModelTargetObjectImpl
|
||||
STATE_ATTRIBUTE_NAME, TargetExecutionState.TERMINATED, //
|
||||
EXIT_CODE_ATTRIBUTE_NAME, exitDesc //
|
||||
), "Exited");
|
||||
getListeners().fire.event(getProxy(), null, TargetEventType.PROCESS_EXITED,
|
||||
broadcast().event(getProxy(), null, TargetEventType.PROCESS_EXITED,
|
||||
"Process " + DebugClient.getId(getProcess()) + " exited code=" + exitDesc,
|
||||
List.of(getProxy()));
|
||||
}
|
||||
|
||||
+6
-9
@@ -25,13 +25,11 @@ import agent.lldb.manager.LldbReason;
|
||||
import agent.lldb.model.iface2.LldbModelTargetRegister;
|
||||
import agent.lldb.model.iface2.LldbModelTargetStackFrameRegisterBank;
|
||||
import ghidra.async.AsyncUtils;
|
||||
import ghidra.dbg.DebuggerModelListener;
|
||||
import ghidra.dbg.error.DebuggerRegisterAccessException;
|
||||
import ghidra.dbg.target.TargetObject;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.dbg.target.schema.TargetObjectSchema.ResyncMode;
|
||||
import ghidra.dbg.util.PathUtils;
|
||||
import ghidra.util.datastruct.ListenerSet;
|
||||
|
||||
@TargetObjectSchemaInfo(
|
||||
name = "RegisterValueBank",
|
||||
@@ -66,6 +64,7 @@ public class LldbModelTargetStackFrameRegisterBankImpl
|
||||
requestElements(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription(int level) {
|
||||
SBStream stream = new SBStream();
|
||||
SBValue val = (SBValue) getModelObject();
|
||||
@@ -105,6 +104,7 @@ public class LldbModelTargetStackFrameRegisterBankImpl
|
||||
return new LldbModelTargetStackFrameRegisterImpl(this, register);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void threadStateChangedSpecific(StateType state, LldbReason reason) {
|
||||
if (state.equals(StateType.eStateStopped)) {
|
||||
requestElements(false).thenAccept(__ -> {
|
||||
@@ -127,12 +127,9 @@ public class LldbModelTargetStackFrameRegisterBankImpl
|
||||
byte[] bytes = register.getBytes();
|
||||
result.put(regname, bytes);
|
||||
}
|
||||
ListenerSet<DebuggerModelListener> listeners = getListeners();
|
||||
if (listeners != null) {
|
||||
//if (getName().contains("General")) {
|
||||
listeners.fire.registersUpdated(this, result);
|
||||
//}
|
||||
}
|
||||
//if (getName().contains("General")) {
|
||||
broadcast().registersUpdated(this, result);
|
||||
//}
|
||||
return CompletableFuture.completedFuture(result);
|
||||
}
|
||||
|
||||
@@ -149,7 +146,7 @@ public class LldbModelTargetStackFrameRegisterBankImpl
|
||||
BigInteger val = new BigInteger(1, ent.getValue());
|
||||
reg.getRegister().SetValueFromCString(val.toString());
|
||||
}
|
||||
getListeners().fire.registersUpdated(getProxy(), values);
|
||||
broadcast().registersUpdated(getProxy(), values);
|
||||
return AsyncUtils.NIL;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -65,7 +65,7 @@ public class LldbModelTargetThreadContainerImpl extends LldbModelTargetObjectImp
|
||||
changeElements(List.of(), List.of(targetThread), Map.of(), "Created");
|
||||
targetThread.threadStateChangedSpecific(StateType.eStateConnected,
|
||||
LldbReason.getReason(null));
|
||||
getListeners().fire.event(getProxy(), targetThread, TargetEventType.THREAD_CREATED,
|
||||
broadcast().event(getProxy(), targetThread, TargetEventType.THREAD_CREATED,
|
||||
"Thread " + DebugClient.getId(thread) + " started", List.of(targetThread));
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public class LldbModelTargetThreadContainerImpl extends LldbModelTargetObjectImp
|
||||
LldbReason reason) {
|
||||
LldbModelTargetThread targetThread = getTargetThread(thread);
|
||||
TargetEventType eventType = getEventType(state, cause, reason);
|
||||
getListeners().fire.event(getProxy(), targetThread, eventType,
|
||||
broadcast().event(getProxy(), targetThread, eventType,
|
||||
"Thread " + DebugClient.getId(thread) + " state changed", List.of(targetThread));
|
||||
targetThread.threadStateChangedSpecific(state, reason);
|
||||
}
|
||||
@@ -94,7 +94,7 @@ public class LldbModelTargetThreadContainerImpl extends LldbModelTargetObjectImp
|
||||
String threadId = LldbModelTargetThreadImpl.indexThread(thread);
|
||||
LldbModelTargetThread targetThread = (LldbModelTargetThread) getMapObject(thread);
|
||||
if (targetThread != null) {
|
||||
getListeners().fire.event(getProxy(), targetThread, TargetEventType.THREAD_EXITED,
|
||||
broadcast().event(getProxy(), targetThread, TargetEventType.THREAD_EXITED,
|
||||
"Thread " + threadId + " exited", List.of(targetThread));
|
||||
}
|
||||
changeElements(List.of( //
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ public interface GadpClientTargetBreakpointSpecContainer
|
||||
Path bptPath = evt.getEffective();
|
||||
TargetBreakpointLocation breakpoint = bptPath == null ? null
|
||||
: getModel().getProxy(bptPath.getEList(), true).as(TargetBreakpointLocation.class);
|
||||
getDelegate().getListeners().fire.breakpointHit(this, trapped, frame, spec, breakpoint);
|
||||
broadcast().breakpointHit(this, trapped, frame, spec, breakpoint);
|
||||
if (spec instanceof GadpClientTargetBreakpointSpec) {
|
||||
// If I don't have a cached proxy, then I don't have any listeners
|
||||
GadpClientTargetBreakpointSpec specObj = (GadpClientTargetBreakpointSpec) spec;
|
||||
|
||||
+1
-1
@@ -33,6 +33,6 @@ public interface GadpClientTargetEventScope extends GadpClientTargetObject, Targ
|
||||
String description = evt.getDescription();
|
||||
List<Object> parameters =
|
||||
GadpValueUtils.getValues(getModel(), evt.getParametersList());
|
||||
getDelegate().getListeners().fire.event(this, thread, type, description, parameters);
|
||||
broadcast().event(this, thread, type, description, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -89,7 +89,7 @@ public interface GadpClientTargetMemory extends GadpClientTargetObject, TargetMe
|
||||
byte[] data = evt.getContent().toByteArray();
|
||||
DelegateGadpClientTargetObject delegate = getDelegate();
|
||||
delegate.getMemoryCache(address.getAddressSpace()).updateMemory(address.getOffset(), data);
|
||||
delegate.getListeners().fire.memoryUpdated(this, address, data);
|
||||
broadcast().memoryUpdated(this, address, data);
|
||||
}
|
||||
|
||||
@GadpEventHandler(Gadp.EventNotification.EvtCase.MEMORY_ERROR_EVENT)
|
||||
@@ -98,7 +98,6 @@ public interface GadpClientTargetMemory extends GadpClientTargetObject, TargetMe
|
||||
AddressRange range = GadpValueUtils.getAddressRange(getModel(), evt.getRange());
|
||||
String message = evt.getMessage();
|
||||
// Errors are not cached, but recorded in trace
|
||||
getDelegate().getListeners().fire.memoryReadError(this, range,
|
||||
new DebuggerMemoryAccessException(message));
|
||||
broadcast().memoryReadError(this, range, new DebuggerMemoryAccessException(message));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -56,8 +56,7 @@ public interface GadpClientTargetObject extends SpiTargetObject {
|
||||
int channelIndex = evt.getChannel();
|
||||
Channel[] allChannels = Channel.values();
|
||||
if (0 <= channelIndex && channelIndex < allChannels.length) {
|
||||
getDelegate().getListeners().fire.consoleOutput(this, allChannels[channelIndex],
|
||||
evt.getData().toByteArray());
|
||||
broadcast().consoleOutput(this, allChannels[channelIndex], evt.getData().toByteArray());
|
||||
}
|
||||
else {
|
||||
Msg.error(this, "Received output for unknown channel " + channelIndex + ": " +
|
||||
|
||||
+1
-1
@@ -82,6 +82,6 @@ public interface GadpClientTargetRegisterBank extends GadpClientTargetObject, Ta
|
||||
Map<String, byte[]> updates = GadpValueUtils.getRegisterValueMap(evt.getValueList());
|
||||
DelegateGadpClientTargetObject delegate = getDelegate();
|
||||
delegate.getRegisterCache().putAll(updates);
|
||||
delegate.getListeners().fire.registersUpdated(this, updates);
|
||||
broadcast().registersUpdated(this, updates);
|
||||
}
|
||||
}
|
||||
|
||||
+51
-19
@@ -926,6 +926,9 @@ public class GadpClientServerTest implements AsyncTestUtils {
|
||||
|
||||
@Test
|
||||
public void testGetAvailableWithObjectGettingListener() throws Throwable {
|
||||
var l = new Object() {
|
||||
TargetObject avail;
|
||||
};
|
||||
List<ElementsChangedInvocation> invocations = new ArrayList<>();
|
||||
// Any listener which calls .get on a child ref would do....
|
||||
// This object-getting listener is the pattern that revealed this problem, though.
|
||||
@@ -933,18 +936,21 @@ public class GadpClientServerTest implements AsyncTestUtils {
|
||||
@Override
|
||||
public void elementsChanged(TargetObject parent, Collection<String> removed,
|
||||
Map<String, ? extends TargetObject> added) {
|
||||
if (parent != l.avail) {
|
||||
return;
|
||||
}
|
||||
invocations.add(new ElementsChangedInvocation(parent, removed, added));
|
||||
}
|
||||
};
|
||||
AsynchronousSocketChannel socket = socketChannel();
|
||||
try (ServerRunner runner = new ServerRunner()) {
|
||||
GadpClient client = new GadpClient("Test", socket);
|
||||
client.addModelListener(listener);
|
||||
waitOn(AsyncUtils.completable(TypeSpec.VOID, socket::connect,
|
||||
runner.server.getLocalAddress()));
|
||||
waitOn(client.connect());
|
||||
TargetObject avail = waitOn(client.fetchModelObject(List.of("Available")));
|
||||
avail.addListener(listener);
|
||||
Map<String, ? extends TargetObject> elements = waitOn(avail.fetchElements());
|
||||
l.avail = waitOn(client.fetchModelObject(List.of("Available")));
|
||||
Map<String, ? extends TargetObject> elements = waitOn(l.avail.fetchElements());
|
||||
Msg.debug(this, "Elements: " + elements);
|
||||
waitOn(client.close());
|
||||
}
|
||||
@@ -957,13 +963,18 @@ public class GadpClientServerTest implements AsyncTestUtils {
|
||||
public void testFocus() throws Throwable {
|
||||
// Interesting because it involves a non-object-valued attribute (link)
|
||||
// Need to check callback as well as getAttributes
|
||||
|
||||
var l = new Object() {
|
||||
TargetObject session;
|
||||
};
|
||||
CompletableFuture<List<String>> focusPath = new CompletableFuture<>();
|
||||
AtomicBoolean failed = new AtomicBoolean();
|
||||
DebuggerModelListener focusListener =
|
||||
new AnnotatedDebuggerAttributeListener(MethodHandles.lookup()) {
|
||||
@AttributeCallback(TargetFocusScope.FOCUS_ATTRIBUTE_NAME)
|
||||
public void focusChanged(TargetObject object, TargetObject focused) {
|
||||
if (object != l.session) {
|
||||
return;
|
||||
}
|
||||
Msg.info(this, "Focus changed to " + focused);
|
||||
if (!focusPath.complete(focused.getPath())) {
|
||||
failed.set(true);
|
||||
@@ -976,8 +987,7 @@ public class GadpClientServerTest implements AsyncTestUtils {
|
||||
waitOn(AsyncUtils.completable(TypeSpec.VOID, socket::connect,
|
||||
runner.server.getLocalAddress()));
|
||||
waitOn(client.connect());
|
||||
TargetObject session = waitOn(client.fetchModelObject(List.of()));
|
||||
session.addListener(focusListener);
|
||||
l.session = waitOn(client.fetchModelObject(List.of()));
|
||||
TargetObject procCont = waitOn(client.fetchModelObject(List.of("Processes")));
|
||||
assertTrue(procCont.getInterfaceNames().contains("Launcher"));
|
||||
TargetLauncher launcher = procCont.as(TargetLauncher.class);
|
||||
@@ -1017,7 +1027,19 @@ public class GadpClientServerTest implements AsyncTestUtils {
|
||||
|
||||
@Test
|
||||
public void testSubscribeLaunchForChildrenChanged() throws Throwable {
|
||||
ElementsChangedListener elemL = new ElementsChangedListener();
|
||||
var l = new Object() {
|
||||
TargetObject procContainer;
|
||||
};
|
||||
ElementsChangedListener elemL = new ElementsChangedListener() {
|
||||
@Override
|
||||
public void elementsChanged(TargetObject parent, Collection<String> removed,
|
||||
Map<String, ? extends TargetObject> added) {
|
||||
if (parent != l.procContainer) {
|
||||
return;
|
||||
}
|
||||
super.elementsChanged(parent, removed, added);
|
||||
}
|
||||
};
|
||||
|
||||
AsynchronousSocketChannel socket = socketChannel();
|
||||
try (ServerRunner runner = new ServerRunner()) {
|
||||
@@ -1026,10 +1048,9 @@ public class GadpClientServerTest implements AsyncTestUtils {
|
||||
waitOn(AsyncUtils.completable(TypeSpec.VOID, socket::connect,
|
||||
runner.server.getLocalAddress()));
|
||||
waitOn(client.connect());
|
||||
TargetObject procContainer = waitOn(client.fetchModelObject(List.of("Processes")));
|
||||
assertTrue(procContainer.getInterfaceNames().contains("Launcher"));
|
||||
procContainer.addListener(elemL);
|
||||
TargetLauncher launcher = procContainer.as(TargetLauncher.class);
|
||||
l.procContainer = waitOn(client.fetchModelObject(List.of("Processes")));
|
||||
assertTrue(l.procContainer.getInterfaceNames().contains("Launcher"));
|
||||
TargetLauncher launcher = l.procContainer.as(TargetLauncher.class);
|
||||
waitOn(launcher.launch(
|
||||
Map.of(TargetCmdLineLauncher.CMDLINE_ARGS_NAME, "/bin/echo Hello, World!")));
|
||||
waitOn(elemL.count.waitValue(1));
|
||||
@@ -1038,7 +1059,7 @@ public class GadpClientServerTest implements AsyncTestUtils {
|
||||
|
||||
assertEquals(1, elemL.invocations.size());
|
||||
ElementsChangedInvocation eci = elemL.invocations.get(0);
|
||||
assertEquals(procContainer, eci.parent);
|
||||
assertEquals(l.procContainer, eci.parent);
|
||||
assertEquals(List.of(), List.copyOf(eci.removed));
|
||||
assertEquals(1, eci.added.size());
|
||||
Entry<String, ? extends TargetObject> ent = eci.added.entrySet().iterator().next();
|
||||
@@ -1107,20 +1128,31 @@ public class GadpClientServerTest implements AsyncTestUtils {
|
||||
|
||||
@Test
|
||||
public void testReplaceAttribute() throws Throwable {
|
||||
AttributesChangedListener attrL = new AttributesChangedListener();
|
||||
var l = new Object() {
|
||||
TargetObject echoAvail;
|
||||
};
|
||||
AttributesChangedListener attrL = new AttributesChangedListener() {
|
||||
@Override
|
||||
public void attributesChanged(TargetObject parent, Collection<String> removed,
|
||||
Map<String, ?> added) {
|
||||
if (parent != l.echoAvail) {
|
||||
return;
|
||||
}
|
||||
super.attributesChanged(parent, removed, added);
|
||||
}
|
||||
};
|
||||
|
||||
try (AsynchronousSocketChannel socket = socketChannel();
|
||||
ServerRunner runner = new ServerRunner()) {
|
||||
GadpClient client = new GadpClient("Test", socket);
|
||||
client.addModelListener(attrL);
|
||||
waitOn(AsyncUtils.completable(TypeSpec.VOID, socket::connect,
|
||||
runner.server.getLocalAddress()));
|
||||
waitOn(client.connect());
|
||||
|
||||
TargetObject echoAvail =
|
||||
waitOn(client.fetchModelObject(PathUtils.parse("Available[1]")));
|
||||
echoAvail.addListener(attrL);
|
||||
l.echoAvail = waitOn(client.fetchModelObject(PathUtils.parse("Available[1]")));
|
||||
assertEquals(Map.ofEntries(Map.entry("pid", 1), Map.entry("cmd", "echo"),
|
||||
Map.entry("_display", "[1]")), waitOn(echoAvail.fetchAttributes()));
|
||||
Map.entry("_display", "[1]")), waitOn(l.echoAvail.fetchAttributes()));
|
||||
|
||||
TestGadpTargetAvailable ssEchoAvail =
|
||||
runner.server.model.session.available.getCachedElements().get("1");
|
||||
@@ -1132,10 +1164,10 @@ public class GadpClientServerTest implements AsyncTestUtils {
|
||||
waitOn(attrL.count.waitValue(1));
|
||||
|
||||
assertEquals(Map.ofEntries(Map.entry("cmd", "echo"), Map.entry("args", "Hello, World!"),
|
||||
Map.entry("_display", "[1]")), echoAvail.getCachedAttributes());
|
||||
Map.entry("_display", "[1]")), l.echoAvail.getCachedAttributes());
|
||||
|
||||
AttributesChangedInvocation changed = Unique.assertOne(attrL.invocations);
|
||||
assertSame(echoAvail, changed.parent);
|
||||
assertSame(l.echoAvail, changed.parent);
|
||||
assertEquals(Set.of("pid"), Set.copyOf(changed.removed));
|
||||
assertEquals(Map.ofEntries(Map.entry("args", "Hello, World!")), changed.added);
|
||||
}
|
||||
|
||||
-4
@@ -22,7 +22,6 @@ import java.util.stream.Collectors;
|
||||
import com.sun.jdi.ReferenceType;
|
||||
|
||||
import ghidra.async.AsyncFence;
|
||||
import ghidra.async.AsyncUtils;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
@@ -90,9 +89,6 @@ public class JdiModelTargetClassContainer extends JdiModelTargetObjectImpl {
|
||||
}
|
||||
|
||||
public CompletableFuture<?> refreshInternal() {
|
||||
if (!isObserved()) {
|
||||
return AsyncUtils.NIL;
|
||||
}
|
||||
return doRefresh().exceptionally(ex -> {
|
||||
Msg.error(this, "Problem refreshing vm's classes", ex);
|
||||
return null;
|
||||
|
||||
-4
@@ -23,7 +23,6 @@ import com.sun.jdi.VirtualMachineManager;
|
||||
import com.sun.jdi.connect.Connector;
|
||||
|
||||
import ghidra.async.AsyncFence;
|
||||
import ghidra.async.AsyncUtils;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
@@ -96,9 +95,6 @@ public class JdiModelTargetConnectorContainer extends JdiModelTargetObjectImpl {
|
||||
}
|
||||
|
||||
public CompletableFuture<?> refreshInternal() {
|
||||
if (!isObserved()) {
|
||||
return AsyncUtils.NIL;
|
||||
}
|
||||
return doRefresh().exceptionally(ex -> {
|
||||
Msg.error(this, "Problem refreshing inferior's modules", ex);
|
||||
return null;
|
||||
|
||||
-4
@@ -22,7 +22,6 @@ import java.util.stream.Collectors;
|
||||
import com.sun.jdi.ModuleReference;
|
||||
|
||||
import ghidra.async.AsyncFence;
|
||||
import ghidra.async.AsyncUtils;
|
||||
import ghidra.dbg.error.DebuggerUserException;
|
||||
import ghidra.dbg.target.TargetModule;
|
||||
import ghidra.dbg.target.TargetModuleContainer;
|
||||
@@ -136,9 +135,6 @@ public class JdiModelTargetModuleContainer extends JdiModelTargetObjectImpl
|
||||
}
|
||||
|
||||
public CompletableFuture<?> refreshInternal() {
|
||||
if (!isObserved()) {
|
||||
return AsyncUtils.NIL;
|
||||
}
|
||||
return doRefresh().exceptionally(ex -> {
|
||||
Msg.error(this, "Problem refreshing inferior's modules", ex);
|
||||
return null;
|
||||
|
||||
+1
-1
@@ -106,7 +106,7 @@ public class JdiModelTargetProcess extends JdiModelTargetObjectImpl
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
listeners.fire.consoleOutput(this, channel, out);
|
||||
broadcast().consoleOutput(this, channel, out);
|
||||
}
|
||||
|
||||
private void readStream(InputStream in, TargetConsole.Channel channel) {
|
||||
|
||||
+2
-6
@@ -20,7 +20,6 @@ import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import com.sun.jdi.Location;
|
||||
|
||||
import ghidra.async.AsyncUtils;
|
||||
import ghidra.dbg.target.TargetRegisterBank;
|
||||
import ghidra.dbg.target.TargetRegisterContainer;
|
||||
import ghidra.dbg.target.schema.*;
|
||||
@@ -121,7 +120,7 @@ public class JdiModelTargetRegisterContainer extends JdiModelTargetObjectImpl
|
||||
map.put(retAddr.getIndex(), bytes);
|
||||
}
|
||||
if (!map.isEmpty()) {
|
||||
listeners.fire.registersUpdated(this, map);
|
||||
broadcast().registersUpdated(this, map);
|
||||
}
|
||||
return CompletableFuture.completedFuture(map);
|
||||
}
|
||||
@@ -133,13 +132,10 @@ public class JdiModelTargetRegisterContainer extends JdiModelTargetObjectImpl
|
||||
}
|
||||
|
||||
public void invalidateRegisterCaches() {
|
||||
listeners.fire.invalidateCacheRequested(this);
|
||||
broadcast().invalidateCacheRequested(this);
|
||||
}
|
||||
|
||||
protected CompletableFuture<?> update() {
|
||||
if (!isObserved()) {
|
||||
return AsyncUtils.NIL;
|
||||
}
|
||||
return fetchElements(true).exceptionally(e -> {
|
||||
Msg.error(this, "Could not update registers " + this + " on STOPPED");
|
||||
return null;
|
||||
|
||||
+2
-2
@@ -125,12 +125,12 @@ public class JdiModelTargetSectionContainer extends JdiModelTargetObjectImpl
|
||||
bytes[i] = (byte) 0xFF;
|
||||
}
|
||||
}
|
||||
listeners.fire.memoryUpdated(this, address, bytes);
|
||||
broadcast().memoryUpdated(this, address, bytes);
|
||||
return CompletableFuture.completedFuture(bytes);
|
||||
}
|
||||
if (addressSpace.equals(impl.getAddressSpace("constantPool"))) {
|
||||
byte[] bytes = constantPool.getPool();
|
||||
listeners.fire.memoryUpdated(this, address, bytes);
|
||||
broadcast().memoryUpdated(this, address, bytes);
|
||||
return CompletableFuture.completedFuture(bytes);
|
||||
}
|
||||
throw new RuntimeException();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user