Merge remote-tracking branch 'origin/GP-2752_Dan_removePerTargetObjectListeners--SQUASHED'

This commit is contained in:
Ryan Kurtz
2022-11-12 01:36:31 -05:00
78 changed files with 384 additions and 1261 deletions
@@ -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();
@@ -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();
}
@@ -79,7 +79,7 @@ public interface DbgModelTargetSession extends //
if (!isValid()) {
return;
}
getListeners().fire.consoleOutput(getProxy(), chan, output);
broadcast().consoleOutput(getProxy(), chan, output);
}
@Override
@@ -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();
}
@@ -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
@@ -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);
@@ -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));
}
@@ -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);
}
}
@@ -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);
}));
}
@@ -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) {
@@ -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;
@@ -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();
});
}
@@ -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();
@@ -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
@@ -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
@@ -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;
}
@@ -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
@@ -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());
}
@@ -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));
}
@@ -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()));
}
@@ -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;
}
@@ -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);
}
@@ -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;
}
@@ -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();
}
}
@@ -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);
}
@@ -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) {
@@ -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
@@ -110,7 +110,7 @@ public class GdbModelTargetStackFrame
}
protected void invalidateRegisterCaches() {
listeners.fire.invalidateCacheRequested(this);
broadcast().invalidateCacheRequested(this);
}
@Override
@@ -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;
});
}
@@ -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();
@@ -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
@@ -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;
}
@@ -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
@@ -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());
}
@@ -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));
}
@@ -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()));
}
@@ -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;
}
@@ -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( //
@@ -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;
@@ -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);
}
}
@@ -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));
}
}
@@ -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 + ": " +
@@ -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);
}
}
@@ -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);
}
@@ -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;
@@ -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;
@@ -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;
@@ -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) {
@@ -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;
@@ -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