GP-930: Various improvements and fixes for Windows debugging

This commit is contained in:
d-millar 2021-05-06 22:02:33 +00:00 committed by Dan
parent a1cfeebcc9
commit 10674175bb
39 changed files with 438 additions and 246 deletions

View file

@ -103,8 +103,8 @@ public class WrapCallbackIDebugEventCallbacks implements CallbackIDebugEventCall
try { try {
DebugBreakpoint bpt = DebugBreakpointInternal DebugBreakpoint bpt = DebugBreakpointInternal
.tryPreferredInterfaces(client.getControlInternal(), Bp::QueryInterface); .tryPreferredInterfaces(client.getControlInternal(), Bp::QueryInterface);
cb.breakpoint(bpt); DebugStatus status = cb.breakpoint(bpt);
return WinError.S_OK; return new HRESULT(status.ordinal());
} }
catch (Throwable e) { catch (Throwable e) {
Msg.error(this, "Error during callback", e); Msg.error(this, "Error during callback", e);
@ -125,8 +125,8 @@ public class WrapCallbackIDebugEventCallbacks implements CallbackIDebugEventCall
Exception.ExceptionFlags.intValue(), Exception.ExceptionRecord.longValue(), Exception.ExceptionFlags.intValue(), Exception.ExceptionRecord.longValue(),
Exception.ExceptionAddress.longValue(), information); Exception.ExceptionAddress.longValue(), information);
boolean firstChance = FirstChance.intValue() != 0; boolean firstChance = FirstChance.intValue() != 0;
cb.exception(exc, firstChance); DebugStatus status = cb.exception(exc, firstChance);
return WinError.S_OK; return new HRESULT(status.ordinal());
} }
catch (Throwable e) { catch (Throwable e) {
Msg.error(this, "Error during callback", e); Msg.error(this, "Error during callback", e);

View file

@ -105,8 +105,8 @@ public class WrapCallbackIDebugEventCallbacksWide implements CallbackIDebugEvent
try { try {
DebugBreakpoint bpt = DebugBreakpointInternal DebugBreakpoint bpt = DebugBreakpointInternal
.tryPreferredInterfaces(client.getControlInternal(), Bp::QueryInterface); .tryPreferredInterfaces(client.getControlInternal(), Bp::QueryInterface);
cb.breakpoint(bpt); DebugStatus status = cb.breakpoint(bpt);
return WinError.S_OK; return new HRESULT(status.ordinal());
} }
catch (Throwable e) { catch (Throwable e) {
Msg.error(this, "Error during callback", e); Msg.error(this, "Error during callback", e);
@ -127,8 +127,8 @@ public class WrapCallbackIDebugEventCallbacksWide implements CallbackIDebugEvent
Exception.ExceptionFlags.intValue(), Exception.ExceptionRecord.longValue(), Exception.ExceptionFlags.intValue(), Exception.ExceptionRecord.longValue(),
Exception.ExceptionAddress.longValue(), information); Exception.ExceptionAddress.longValue(), information);
boolean firstChance = FirstChance.intValue() != 0; boolean firstChance = FirstChance.intValue() != 0;
cb.exception(exc, firstChance); DebugStatus status = cb.exception(exc, firstChance);
return WinError.S_OK; return new HRESULT(status.ordinal());
} }
catch (Throwable e) { catch (Throwable e) {
Msg.error(this, "Error during callback", e); Msg.error(this, "Error during callback", e);

View file

@ -192,6 +192,16 @@ public interface DbgManager extends AutoCloseable, DbgBreakpointInsertions {
*/ */
Map<Long, DbgBreakpointInfo> getKnownBreakpoints(); Map<Long, DbgBreakpointInfo> getKnownBreakpoints();
/**
* Get all memory regions known to the manager
*
* This does not ask dbgeng to list its regions. Rather it returns a read-only view of the
* manager's understanding of the current ememory based on its tracking of dbgeng events.
*
* @return a map of dbgeng-assigned breakpoint IDs to corresponding breakpoint information
*/
Map<Long, DbgModuleMemory> getKnownMemoryRegions();
/** /**
* Send an interrupt to dbgeng regardless of other queued commands * Send an interrupt to dbgeng regardless of other queued commands
* *
@ -242,6 +252,21 @@ public interface DbgManager extends AutoCloseable, DbgBreakpointInsertions {
*/ */
CompletableFuture<Void> removeSession(DbgSession session); CompletableFuture<Void> removeSession(DbgSession session);
/**
* Add a memory region
*
* @return a future which completes with the handle to the new process
*/
CompletableFuture<Void> addMemory(DbgModuleMemory region);
/**
* Remove a memory region
*
* @param regionId the region to remove
* @return a future which completes then dbgeng has executed the command
*/
CompletableFuture<Void> removeMemory(Long regionId);
/** /**
* Execute an arbitrary CLI command, printing output to the CLI console * Execute an arbitrary CLI command, printing output to the CLI console
* *

View file

@ -21,6 +21,8 @@ public interface DbgModuleMemory {
String getName(); String getName();
Long getId();
long getVmaStart(); long getVmaStart();
long getVmaEnd(); long getVmaEnd();

View file

@ -85,6 +85,10 @@ public class DbgBreakpointInfo {
offset, expression); offset, expression);
} }
public int getId() {
return bpt.getId();
}
@Override @Override
public String toString() { public String toString() {
return Integer.toHexString(bpt.getId()); return Integer.toHexString(bpt.getId());

View file

@ -15,8 +15,8 @@
*/ */
package agent.dbgeng.manager.cmd; package agent.dbgeng.manager.cmd;
import java.util.ArrayList; import java.util.*;
import java.util.List; import java.util.Map.Entry;
import com.sun.jna.platform.win32.COM.COMException; import com.sun.jna.platform.win32.COM.COMException;
@ -27,6 +27,7 @@ import agent.dbgeng.dbgeng.DebugModule.DebugModuleName;
import agent.dbgeng.manager.DbgModuleMemory; import agent.dbgeng.manager.DbgModuleMemory;
import agent.dbgeng.manager.impl.DbgManagerImpl; import agent.dbgeng.manager.impl.DbgManagerImpl;
import agent.dbgeng.manager.impl.DbgModuleMemoryImpl; import agent.dbgeng.manager.impl.DbgModuleMemoryImpl;
import ghidra.util.Msg;
public class DbgListMemoryRegionsCommand extends AbstractDbgCommand<List<DbgModuleMemory>> { public class DbgListMemoryRegionsCommand extends AbstractDbgCommand<List<DbgModuleMemory>> {
@ -38,6 +39,23 @@ public class DbgListMemoryRegionsCommand extends AbstractDbgCommand<List<DbgModu
@Override @Override
public List<DbgModuleMemory> complete(DbgPendingCommand<?> pending) { public List<DbgModuleMemory> complete(DbgPendingCommand<?> pending) {
Map<Long, DbgModuleMemory> memory = manager.getKnownMemoryRegions();
for (DbgModuleMemory region : memoryRegions) {
if (memory.containsValue(region)) {
continue; // Do nothing, we're in sync
}
// Need to create the thread as if we receive =thread-created
if (!memory.isEmpty()) {
Msg.warn(this, "Resync: Was missing memory: " + region.getId());
}
manager.addMemory(region);
}
for (Entry<Long, DbgModuleMemory> entry : memory.entrySet()) {
if (memoryRegions.contains(entry.getValue())) {
continue; // Do nothing, we're in sync
}
manager.removeMemory(entry.getKey());
}
return memoryRegions; return memoryRegions;
} }
@ -83,10 +101,10 @@ public class DbgListMemoryRegionsCommand extends AbstractDbgCommand<List<DbgModu
isWrite |= protect.isWrite(); isWrite |= protect.isWrite();
isExec |= protect.isExecute(); isExec |= protect.isExecute();
} }
DbgModuleMemoryImpl section = DbgModuleMemoryImpl region =
new DbgModuleMemoryImpl(Long.toHexString(vmaStart), vmaStart, vmaEnd, new DbgModuleMemoryImpl(Long.toHexString(vmaStart), vmaStart, vmaEnd,
info.allocationBase, ap, ip, info.state, type, isRead, isWrite, isExec); info.allocationBase, ap, ip, info.state, type, isRead, isWrite, isExec);
memoryRegions.add(section); memoryRegions.add(region);
} }
} }

View file

@ -55,7 +55,7 @@ public class DbgReadRegistersCommand extends AbstractDbgCommand<Map<DbgRegister,
} }
} }
} }
//so.setCurrentThreadId(previous); so.setCurrentThreadId(previous);
return result; return result;
} }

View file

@ -16,6 +16,7 @@
package agent.dbgeng.manager.cmd; package agent.dbgeng.manager.cmd;
import agent.dbgeng.dbgeng.DebugProcessId; import agent.dbgeng.dbgeng.DebugProcessId;
import agent.dbgeng.dbgeng.DebugSystemObjects;
import agent.dbgeng.manager.DbgProcess; import agent.dbgeng.manager.DbgProcess;
import agent.dbgeng.manager.impl.DbgManagerImpl; import agent.dbgeng.manager.impl.DbgManagerImpl;
@ -39,7 +40,11 @@ public class DbgSetActiveProcessCommand extends AbstractDbgCommand<Void> {
if (process != null) { if (process != null) {
DebugProcessId id = process.getId(); DebugProcessId id = process.getId();
if (id != null) { if (id != null) {
manager.getSystemObjects().setCurrentProcessId(id); DebugSystemObjects so = manager.getSystemObjects();
DebugProcessId currentProcessId = so.getCurrentProcessId();
if (id.id != currentProcessId.id) {
so.setCurrentProcessId(id);
}
} }
} }
} }

View file

@ -63,6 +63,6 @@ public class DbgStackListFramesCommand extends AbstractDbgCommand<List<DbgStackF
tf.Params[3].longValue()); tf.Params[3].longValue());
result.add(frame); result.add(frame);
} }
//so.setCurrentThreadId(previous); so.setCurrentThreadId(previous);
} }
} }

View file

@ -15,8 +15,7 @@
*/ */
package agent.dbgeng.manager.cmd; package agent.dbgeng.manager.cmd;
import agent.dbgeng.dbgeng.DebugControl; import agent.dbgeng.dbgeng.*;
import agent.dbgeng.dbgeng.DebugThreadId;
import agent.dbgeng.manager.DbgThread; import agent.dbgeng.manager.DbgThread;
import agent.dbgeng.manager.impl.DbgManagerImpl; import agent.dbgeng.manager.impl.DbgManagerImpl;
@ -56,7 +55,9 @@ public class DbgThreadHoldCommand extends AbstractDbgCommand<Void> {
public void invoke() { public void invoke() {
DebugThreadId id = thread.getId(); DebugThreadId id = thread.getId();
if (id != null) { if (id != null) {
manager.getSystemObjects().setCurrentThreadId(id); DebugSystemObjects so = manager.getSystemObjects();
DebugThreadId previous = so.getCurrentThreadId();
so.setCurrentThreadId(id);
if (!manager.isKernelMode()) { if (!manager.isKernelMode()) {
DebugControl control = manager.getControl(); DebugControl control = manager.getControl();
if (preferFreeze) { if (preferFreeze) {
@ -68,6 +69,7 @@ public class DbgThreadHoldCommand extends AbstractDbgCommand<Void> {
set ? SUSPEND_CURRENT_THREAD_COMMAND : RESUME_CURRENT_THREAD_COMMAND); set ? SUSPEND_CURRENT_THREAD_COMMAND : RESUME_CURRENT_THREAD_COMMAND);
} }
} }
so.setCurrentThreadId(previous);
} }
} }
} }

View file

@ -66,6 +66,6 @@ public class DbgWriteRegistersCommand extends AbstractDbgCommand<Void> {
} }
} }
registers.setValues(DebugRegisterSource.DEBUG_REGSRC_DEBUGGEE, values); registers.setValues(DebugRegisterSource.DEBUG_REGSRC_DEBUGGEE, values);
//so.setCurrentThreadId(previous); so.setCurrentThreadId(previous);
} }
} }

View file

@ -42,6 +42,8 @@ import agent.dbgeng.manager.breakpoint.DbgBreakpointType;
import agent.dbgeng.manager.cmd.*; import agent.dbgeng.manager.cmd.*;
import agent.dbgeng.manager.evt.*; import agent.dbgeng.manager.evt.*;
import agent.dbgeng.model.iface1.*; import agent.dbgeng.model.iface1.*;
import agent.dbgeng.model.iface2.DbgModelTargetObject;
import agent.dbgeng.model.iface2.DbgModelTargetThread;
import ghidra.async.*; import ghidra.async.*;
import ghidra.comm.util.BitmaskSet; import ghidra.comm.util.BitmaskSet;
import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.TargetObject;
@ -92,6 +94,10 @@ public class DbgManagerImpl implements DbgManager {
private final Map<Long, DbgBreakpointInfo> unmodifiableBreakpoints = private final Map<Long, DbgBreakpointInfo> unmodifiableBreakpoints =
Collections.unmodifiableMap(breakpoints); Collections.unmodifiableMap(breakpoints);
private final NavigableMap<Long, DbgModuleMemory> memory = new TreeMap<>();
private final NavigableMap<Long, DbgModuleMemory> unmodifiableMemory =
Collections.unmodifiableNavigableMap(memory);
protected final AsyncReference<DbgState, DbgCause> state = protected final AsyncReference<DbgState, DbgCause> state =
new AsyncReference<>(DbgState.NOT_STARTED); new AsyncReference<>(DbgState.NOT_STARTED);
private final HandlerMap<DbgEvent<?>, Void, DebugStatus> handlerMap = new HandlerMap<>(); private final HandlerMap<DbgEvent<?>, Void, DebugStatus> handlerMap = new HandlerMap<>();
@ -109,6 +115,7 @@ public class DbgManagerImpl implements DbgManager {
private DbgThread eventThread; private DbgThread eventThread;
private volatile boolean waiting = false; private volatile boolean waiting = false;
private boolean kernelMode = false; private boolean kernelMode = false;
private boolean ignoreEventThread = false;
private CompletableFuture<String> continuation; private CompletableFuture<String> continuation;
private long processCount = 0; private long processCount = 0;
@ -267,6 +274,11 @@ public class DbgManagerImpl implements DbgManager {
return unmodifiableBreakpoints; return unmodifiableBreakpoints;
} }
@Override
public Map<Long, DbgModuleMemory> getKnownMemoryRegions() {
return unmodifiableMemory;
}
private DbgBreakpointInfo addKnownBreakpoint(DbgBreakpointInfo bkpt, boolean expectExisting) { private DbgBreakpointInfo addKnownBreakpoint(DbgBreakpointInfo bkpt, boolean expectExisting) {
DbgBreakpointInfo old = breakpoints.put(bkpt.getNumber(), bkpt); DbgBreakpointInfo old = breakpoints.put(bkpt.getNumber(), bkpt);
if (expectExisting && old == null) { if (expectExisting && old == null) {
@ -606,8 +618,8 @@ public class DbgManagerImpl implements DbgManager {
DebugControl control = dbgeng.getControl(); DebugControl control = dbgeng.getControl();
int execType = WinNTExtra.Machine.IMAGE_FILE_MACHINE_AMD64.val; int execType = WinNTExtra.Machine.IMAGE_FILE_MACHINE_AMD64.val;
try { try {
so.setCurrentProcessId(epid); //so.setCurrentProcessId(epid);
so.setCurrentThreadId(etid); //so.setCurrentThreadId(etid);
execType = control.getExecutingProcessorType(); execType = control.getExecutingProcessorType();
} }
catch (Exception e) { catch (Exception e) {
@ -652,6 +664,7 @@ public class DbgManagerImpl implements DbgManager {
DebugBreakpoint bp = evt.getInfo(); DebugBreakpoint bp = evt.getInfo();
DbgBreakpointInfo info = new DbgBreakpointInfo(bp, getEventProcess(), getEventThread()); DbgBreakpointInfo info = new DbgBreakpointInfo(bp, getEventProcess(), getEventThread());
getEventListeners().fire.threadSelected(eventThread, null, evt.getCause());
getEventListeners().fire.breakpointHit(info, evt.getCause()); getEventListeners().fire.breakpointHit(info, evt.getCause());
String key = Integer.toHexString(bp.getId()); String key = Integer.toHexString(bp.getId());
@ -670,6 +683,7 @@ public class DbgManagerImpl implements DbgManager {
*/ */
protected DebugStatus processException(DbgExceptionEvent evt, Void v) { protected DebugStatus processException(DbgExceptionEvent evt, Void v) {
DebugThreadId eventId = updateState(); DebugThreadId eventId = updateState();
getEventListeners().fire.threadSelected(eventThread, null, evt.getCause());
DebugExceptionRecord64 info = evt.getInfo(); DebugExceptionRecord64 info = evt.getInfo();
String key = Integer.toHexString(info.code); String key = Integer.toHexString(info.code);
@ -764,16 +778,17 @@ public class DbgManagerImpl implements DbgManager {
DebugProcessInfo info = evt.getInfo(); DebugProcessInfo info = evt.getInfo();
long handle = info.handle; long handle = info.handle;
DebugProcessId id = so.getProcessIdByHandle(handle); DebugProcessId id = so.getProcessIdByHandle(handle);
so.setCurrentProcessId(id); //so.setCurrentProcessId(id);
int pid = so.getCurrentProcessSystemId(); int pid = so.getCurrentProcessSystemId();
DbgProcessImpl proc = getProcessComputeIfAbsent(id, pid); DbgProcessImpl proc = getProcessComputeIfAbsent(id, pid);
getEventListeners().fire.processAdded(proc, DbgCause.Causes.UNCLAIMED); getEventListeners().fire.processAdded(proc, evt.getCause());
getEventListeners().fire.processSelected(proc, evt.getCause()); getEventListeners().fire.processSelected(proc, evt.getCause());
handle = info.initialThreadInfo.handle; handle = info.initialThreadInfo.handle;
DebugThreadId idt = so.getThreadIdByHandle(handle); DebugThreadId idt = so.getThreadIdByHandle(handle);
int tid = so.getCurrentThreadSystemId(); int tid = so.getCurrentThreadSystemId();
DbgThreadImpl thread = getThreadComputeIfAbsent(idt, proc, tid); DbgThreadImpl thread = getThreadComputeIfAbsent(idt, proc, tid);
getEventListeners().fire.threadCreated(thread, evt.getCause());
getEventListeners().fire.threadSelected(thread, null, evt.getCause()); getEventListeners().fire.threadSelected(thread, null, evt.getCause());
//proc.moduleLoaded(info.moduleInfo); //proc.moduleLoaded(info.moduleInfo);
@ -1041,8 +1056,9 @@ public class DbgManagerImpl implements DbgManager {
if (bptId == DbgEngUtil.DEBUG_ANY_ID.longValue()) { if (bptId == DbgEngUtil.DEBUG_ANY_ID.longValue()) {
changeBreakpoints(); changeBreakpoints();
} }
else {
DebugBreakpoint bpt = getControl().getBreakpointById((int) bptId); DebugBreakpoint bpt = getControl().getBreakpointById((int) bptId);
if (bpt == null) { if (bpt == null && bptId != DbgEngUtil.DEBUG_ANY_ID.longValue()) {
doBreakpointDeleted(bptId, evt.getCause()); doBreakpointDeleted(bptId, evt.getCause());
return; return;
} }
@ -1056,10 +1072,10 @@ public class DbgManagerImpl implements DbgManager {
} }
breakpointInfo = knownBreakpoint; breakpointInfo = knownBreakpoint;
breakpointInfo.setBreakpoint(bpt); breakpointInfo.setBreakpoint(bpt);
}
doBreakpointModified(breakpointInfo, evt.getCause()); doBreakpointModified(breakpointInfo, evt.getCause());
} }
}
}
/** /**
* Handler for breakpoint-deleted event * Handler for breakpoint-deleted event
@ -1274,6 +1290,18 @@ public class DbgManagerImpl implements DbgManager {
return execute(new DbgRemoveSessionCommand(this, session.getId())); return execute(new DbgRemoveSessionCommand(this, session.getId()));
} }
@Override
public CompletableFuture<Void> addMemory(DbgModuleMemory region) {
memory.put(region.getId(), region);
return AsyncUtils.NIL;
}
@Override
public CompletableFuture<Void> removeMemory(Long id) {
memory.remove(id);
return AsyncUtils.NIL;
}
@Override @Override
public CompletableFuture<?> launch(List<String> args) { public CompletableFuture<?> launch(List<String> args) {
return execute(new DbgLaunchProcessCommand(this, args)); return execute(new DbgLaunchProcessCommand(this, args));
@ -1492,6 +1520,7 @@ public class DbgManagerImpl implements DbgManager {
//System.err.println("EXIT"); //System.err.println("EXIT");
waiting = false; waiting = false;
updateState(); updateState();
getEventListeners().fire.threadSelected(eventThread, null, Causes.UNCLAIMED);
return CompletableFuture.completedFuture(null); return CompletableFuture.completedFuture(null);
} }
@ -1511,6 +1540,18 @@ public class DbgManagerImpl implements DbgManager {
return lastEventInformation; return lastEventInformation;
} }
public boolean shouldUpdate(TargetObject object) {
if (ignoreEventThread || !(object instanceof DbgModelTargetObject)) {
return true;
}
DbgModelTargetObject modelObject = (DbgModelTargetObject) object;
DbgModelTargetThread parentThread = modelObject.getParentThread();
if (parentThread == null) {
return true;
}
return parentThread.getThread().equals(eventThread);
}
public CompletableFuture<? extends Map<String, ?>> getRegisterMap(List<String> path) { public CompletableFuture<? extends Map<String, ?>> getRegisterMap(List<String> path) {
return null; return null;
} }

View file

@ -55,6 +55,11 @@ public class DbgModuleMemoryImpl implements DbgModuleMemory {
return index; return index;
} }
@Override
public Long getId() {
return vmaStart;
}
@Override @Override
public long getVmaStart() { public long getVmaStart() {
return vmaStart; return vmaStart;

View file

@ -43,9 +43,11 @@ public interface DbgModelTargetExecutionStateful
} }
public default void setExecutionState(TargetExecutionState state, String reason) { public default void setExecutionState(TargetExecutionState state, String reason) {
if (isValid()) {
changeAttributes(List.of(), Map.of( // changeAttributes(List.of(), Map.of( //
STATE_ATTRIBUTE_NAME, state // STATE_ATTRIBUTE_NAME, state //
), reason); ), reason);
} }
}
} }

View file

@ -67,21 +67,11 @@ public interface DbgModelTargetBreakpointSpec extends //
@Override @Override
public default TargetBreakpointKindSet getKinds() { public default TargetBreakpointKindSet getKinds() {
switch (getBreakpointInfo().getType()) { return TargetBreakpointKindSet.of(
case BREAKPOINT: TargetBreakpointKind.SW_EXECUTE,
return TargetBreakpointKindSet.of(TargetBreakpointKind.SW_EXECUTE); TargetBreakpointKind.HW_EXECUTE,
case HW_BREAKPOINT: TargetBreakpointKind.READ,
return TargetBreakpointKindSet.of(TargetBreakpointKind.HW_EXECUTE);
case HW_WATCHPOINT:
return TargetBreakpointKindSet.of(TargetBreakpointKind.WRITE);
case READ_WATCHPOINT:
return TargetBreakpointKindSet.of(TargetBreakpointKind.READ);
case ACCESS_WATCHPOINT:
return TargetBreakpointKindSet.of(TargetBreakpointKind.READ,
TargetBreakpointKind.WRITE); TargetBreakpointKind.WRITE);
default:
return TargetBreakpointKindSet.of();
}
} }
@Override @Override

View file

@ -31,4 +31,6 @@ public interface DbgModelTargetMemoryContainer extends DbgModelTargetObject, Tar
@Override @Override
public CompletableFuture<Void> writeMemory(Address address, byte[] data); public CompletableFuture<Void> writeMemory(Address address, byte[] data);
public CompletableFuture<Void> requestElements(boolean refresh);
} }

View file

@ -49,6 +49,8 @@ public interface DbgModelTargetProcess extends //
public DbgModelTargetModuleContainer getModules(); public DbgModelTargetModuleContainer getModules();
public DbgModelTargetMemoryContainer getMemory();
public void threadStateChangedSpecific(DbgThread thread, DbgState state); public void threadStateChangedSpecific(DbgThread thread, DbgState state);
public default DbgProcess getProcess() { public default DbgProcess getProcess() {

View file

@ -21,7 +21,7 @@ import java.util.Map.Entry;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import agent.dbgeng.manager.*; import agent.dbgeng.manager.DbgThread;
import agent.dbgeng.manager.impl.*; import agent.dbgeng.manager.impl.*;
import ghidra.async.AsyncUtils; import ghidra.async.AsyncUtils;
import ghidra.async.TypeSpec; import ghidra.async.TypeSpec;
@ -36,10 +36,6 @@ public interface DbgModelTargetRegisterBank extends DbgModelTargetObject, Target
public DbgModelTargetRegister getTargetRegister(DbgRegister register); public DbgModelTargetRegister getTargetRegister(DbgRegister register);
public default void threadStateChangedSpecific(DbgState state, DbgReason reason) {
readRegistersNamed(getCachedElements().keySet());
}
@Override @Override
public default CompletableFuture<? extends Map<String, byte[]>> readRegistersNamed( public default CompletableFuture<? extends Map<String, byte[]>> readRegistersNamed(
Collection<String> names) { Collection<String> names) {

View file

@ -59,6 +59,9 @@ public interface DbgModelTargetSession extends //
@Override @Override
public default void consoleOutput(String output, int mask) { public default void consoleOutput(String output, int mask) {
if (!isValid()) {
return;
}
Channel chan = TargetConsole.Channel.STDOUT; Channel chan = TargetConsole.Channel.STDOUT;
if (((mask & DebugOutputFlags.DEBUG_OUTPUT_ERROR.getValue()) // if (((mask & DebugOutputFlags.DEBUG_OUTPUT_ERROR.getValue()) //
== DebugOutputFlags.DEBUG_OUTPUT_ERROR.getValue()) || // == DebugOutputFlags.DEBUG_OUTPUT_ERROR.getValue()) || //
@ -69,6 +72,9 @@ public interface DbgModelTargetSession extends //
if (output.contains("loaded *kernel* extension dll for usermode")) { if (output.contains("loaded *kernel* extension dll for usermode")) {
return; return;
} }
if (!isValid()) {
return;
}
getListeners().fire.consoleOutput(getProxy(), chan, output); getListeners().fire.consoleOutput(getProxy(), chan, output);
} }

View file

@ -24,7 +24,7 @@ import agent.dbgeng.manager.cmd.DbgSetActiveThreadCommand;
import agent.dbgeng.manager.impl.*; import agent.dbgeng.manager.impl.*;
import agent.dbgeng.model.iface1.*; import agent.dbgeng.model.iface1.*;
import agent.dbgeng.model.impl.DbgModelTargetStackImpl; import agent.dbgeng.model.impl.DbgModelTargetStackImpl;
import ghidra.dbg.target.*; import ghidra.dbg.target.TargetThread;
import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils;
public interface DbgModelTargetThread extends // public interface DbgModelTargetThread extends //
@ -55,15 +55,6 @@ public interface DbgModelTargetThread extends //
} }
} }
public default void threadStateChangedSpecific(DbgState state, DbgReason reason) {
TargetRegisterContainer container =
(TargetRegisterContainer) getCachedAttribute("Registers");
TargetRegisterBank bank = (TargetRegisterBank) container.getCachedAttribute("User");
if (state.equals(DbgState.STOPPED)) {
bank.readRegistersNamed(getCachedElements().keySet());
}
}
@Override @Override
public default CompletableFuture<Void> setActive() { public default CompletableFuture<Void> setActive() {
DbgManagerImpl manager = getManager(); DbgManagerImpl manager = getManager();
@ -75,4 +66,6 @@ public interface DbgModelTargetThread extends //
public String getExecutingProcessorType(); public String getExecutingProcessorType();
public void threadStateChangedSpecific(DbgState state, DbgReason reason);
} }

View file

@ -28,11 +28,15 @@ import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointKind;
import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
@TargetObjectSchemaInfo(name = "BreakpointContainer", elements = { // @TargetObjectSchemaInfo(
name = "BreakpointContainer",
elements = { //
@TargetElementType(type = DbgModelTargetBreakpointSpecImpl.class) // @TargetElementType(type = DbgModelTargetBreakpointSpecImpl.class) //
}, attributes = { // },
attributes = { //
@TargetAttributeType(type = Void.class) // @TargetAttributeType(type = Void.class) //
}, canonicalContainer = true) },
canonicalContainer = true)
public class DbgModelTargetBreakpointContainerImpl extends DbgModelTargetObjectImpl public class DbgModelTargetBreakpointContainerImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetBreakpointContainer { implements DbgModelTargetBreakpointContainer {

View file

@ -28,19 +28,30 @@ import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils;
import ghidra.util.datastruct.ListenerSet; import ghidra.util.datastruct.ListenerSet;
@TargetObjectSchemaInfo(name = "BreakpointSpec", attributes = { // @TargetObjectSchemaInfo(
name = "BreakpointSpec",
attributes = { //
@TargetAttributeType( // @TargetAttributeType( //
name = TargetBreakpointSpec.CONTAINER_ATTRIBUTE_NAME, // name = TargetBreakpointSpec.CONTAINER_ATTRIBUTE_NAME, //
type = DbgModelTargetBreakpointContainerImpl.class), // type = DbgModelTargetBreakpointContainerImpl.class), //
@TargetAttributeType( // @TargetAttributeType( //
name = TargetBreakpointLocation.SPEC_ATTRIBUTE_NAME, // name = TargetBreakpointLocation.SPEC_ATTRIBUTE_NAME, //
type = DbgModelTargetBreakpointSpecImpl.class), // type = DbgModelTargetBreakpointSpecImpl.class), //
@TargetAttributeType(name = DbgModelTargetBreakpointSpecImpl.BPT_TYPE_ATTRIBUTE_NAME, type = String.class), // @TargetAttributeType(
@TargetAttributeType(name = DbgModelTargetBreakpointSpecImpl.BPT_DISP_ATTRIBUTE_NAME, type = String.class), // name = DbgModelTargetBreakpointSpecImpl.BPT_TYPE_ATTRIBUTE_NAME,
@TargetAttributeType(name = DbgModelTargetBreakpointSpecImpl.BPT_PENDING_ATTRIBUTE_NAME, type = String.class), // type = String.class), //
@TargetAttributeType(name = DbgModelTargetBreakpointSpecImpl.BPT_TIMES_ATTRIBUTE_NAME, type = Integer.class), // @TargetAttributeType(
name = DbgModelTargetBreakpointSpecImpl.BPT_DISP_ATTRIBUTE_NAME,
type = String.class), //
@TargetAttributeType(
name = DbgModelTargetBreakpointSpecImpl.BPT_PENDING_ATTRIBUTE_NAME,
type = String.class), //
@TargetAttributeType(
name = DbgModelTargetBreakpointSpecImpl.BPT_TIMES_ATTRIBUTE_NAME,
type = Integer.class), //
@TargetAttributeType(type = Void.class) // @TargetAttributeType(type = Void.class) //
}, canonicalContainer = true) },
canonicalContainer = true)
public class DbgModelTargetBreakpointSpecImpl extends DbgModelTargetObjectImpl public class DbgModelTargetBreakpointSpecImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetBreakpointSpec { implements DbgModelTargetBreakpointSpec {
@ -117,10 +128,9 @@ public class DbgModelTargetBreakpointSpecImpl extends DbgModelTargetObjectImpl
/** /**
* Update the enabled field * Update the enabled field
* *
* This does not actually toggle the breakpoint. It just updates the field * This does not actually toggle the breakpoint. It just updates the field and calls the proper
* and calls the proper listeners. To actually toggle the breakpoint, use * listeners. To actually toggle the breakpoint, use {@link #toggle(boolean)} instead, which if
* {@link #toggle(boolean)} instead, which if effective, should eventually * effective, should eventually cause this method to be called.
* cause this method to be called.
* *
* @param enabled true if enabled, false if disabled * @param enabled true if enabled, false if disabled
* @param reason a description of the cause (not really used, yet) * @param reason a description of the cause (not really used, yet)

View file

@ -35,9 +35,13 @@ import ghidra.dbg.target.schema.*;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.util.datastruct.WeakValueHashMap; import ghidra.util.datastruct.WeakValueHashMap;
@TargetObjectSchemaInfo(name = "Memory", elements = { @TargetObjectSchemaInfo(
@TargetElementType(type = DbgModelTargetMemoryRegionImpl.class) }, attributes = { name = "Memory",
@TargetAttributeType(type = Void.class) }, canonicalContainer = true) elements = {
@TargetElementType(type = DbgModelTargetMemoryRegionImpl.class) },
attributes = {
@TargetAttributeType(type = Void.class) },
canonicalContainer = true)
public class DbgModelTargetMemoryContainerImpl extends DbgModelTargetObjectImpl public class DbgModelTargetMemoryContainerImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetMemoryContainer { implements DbgModelTargetMemoryContainer {
@ -49,12 +53,13 @@ public class DbgModelTargetMemoryContainerImpl extends DbgModelTargetObjectImpl
public DbgModelTargetMemoryContainerImpl(DbgModelTargetProcess process) { public DbgModelTargetMemoryContainerImpl(DbgModelTargetProcess process) {
super(process.getModel(), process, "Memory", "MemoryContainer"); super(process.getModel(), process, "Memory", "MemoryContainer");
this.process = process; this.process = process;
requestElements(true);
} }
@Override @Override
public CompletableFuture<Void> requestElements(boolean refresh) { public CompletableFuture<Void> requestElements(boolean refresh) {
DbgModelTargetProcess targetProcess = getParentProcess(); DbgModelTargetProcess targetProcess = getParentProcess();
if (!targetProcess.getProcess().equals(getManager().getCurrentProcess())) { if (!refresh || !targetProcess.getProcess().equals(getManager().getCurrentProcess())) {
return AsyncUtils.NIL; return AsyncUtils.NIL;
} }
return listMemory().thenAccept(byName -> { return listMemory().thenAccept(byName -> {
@ -258,8 +263,4 @@ public class DbgModelTargetMemoryContainerImpl extends DbgModelTargetObjectImpl
return CompletableFuture.completedFuture(null); return CompletableFuture.completedFuture(null);
} }
@Override
protected void update() {
requestElements(true);
}
} }

View file

@ -84,22 +84,12 @@ public class DbgModelTargetObjectImpl extends DefaultTargetObject<TargetObject,
public void onStopped() { public void onStopped() {
setAccessible(true); setAccessible(true);
update();
} }
public void onExit() { public void onExit() {
setAccessible(true); setAccessible(true);
} }
protected void update() {
Map<String, ?> existingAttributes = getCachedAttributes();
Boolean autoupdate = (Boolean) existingAttributes.get("autoupdate");
if (autoupdate != null && autoupdate) {
requestAttributes(true);
requestElements(true);
}
}
protected void checkExited(DbgState state, DbgCause cause) { protected void checkExited(DbgState state, DbgCause cause) {
TargetExecutionState exec = TargetExecutionState.INACTIVE; TargetExecutionState exec = TargetExecutionState.INACTIVE;
switch (state) { switch (state) {

View file

@ -30,12 +30,16 @@ import ghidra.dbg.target.TargetConfigurable;
import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
@TargetObjectSchemaInfo(name = "ProcessContainer", elements = { // @TargetObjectSchemaInfo(
name = "ProcessContainer",
elements = { //
@TargetElementType(type = DbgModelTargetProcessImpl.class) // @TargetElementType(type = DbgModelTargetProcessImpl.class) //
}, attributes = { // },
attributes = { //
@TargetAttributeType(name = TargetConfigurable.BASE_ATTRIBUTE_NAME, type = Integer.class), // @TargetAttributeType(name = TargetConfigurable.BASE_ATTRIBUTE_NAME, type = Integer.class), //
@TargetAttributeType(type = Void.class) // @TargetAttributeType(type = Void.class) //
}, canonicalContainer = true) },
canonicalContainer = true)
public class DbgModelTargetProcessContainerImpl extends DbgModelTargetObjectImpl public class DbgModelTargetProcessContainerImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetProcessContainer, DbgModelTargetConfigurable { implements DbgModelTargetProcessContainer, DbgModelTargetConfigurable {
@ -99,12 +103,20 @@ public class DbgModelTargetProcessContainerImpl extends DbgModelTargetObjectImpl
if (modules != null) { if (modules != null) {
modules.libraryLoaded(info.toString()); modules.libraryLoaded(info.toString());
} }
DbgModelTargetMemoryContainer memory = process.getMemory();
if (memory != null) {
memory.requestElements(false);
}
} }
@Override @Override
public void moduleUnloaded(DbgProcess proc, DebugModuleInfo info, DbgCause cause) { public void moduleUnloaded(DbgProcess proc, DebugModuleInfo info, DbgCause cause) {
DbgModelTargetProcess process = getTargetProcess(proc); DbgModelTargetProcess process = getTargetProcess(proc);
process.getModules().libraryUnloaded(info.toString()); process.getModules().libraryUnloaded(info.toString());
DbgModelTargetMemoryContainer memory = process.getMemory();
if (memory != null) {
memory.requestElements(false);
}
} }
@Override @Override

View file

@ -29,13 +29,34 @@ import ghidra.dbg.target.TargetEventScope.TargetEventType;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils;
@TargetObjectSchemaInfo(name = "Process", elements = { @TargetObjectSchemaInfo(
@TargetElementType(type = Void.class) }, attributes = { name = "Process",
@TargetAttributeType(name = "Debug", type = DbgModelTargetDebugContainerImpl.class, required = true, fixed = true), elements = {
@TargetAttributeType(name = "Memory", type = DbgModelTargetMemoryContainerImpl.class, required = true, fixed = true), @TargetElementType(type = Void.class) },
@TargetAttributeType(name = "Modules", type = DbgModelTargetModuleContainerImpl.class, required = true, fixed = true), attributes = {
@TargetAttributeType(name = "Threads", type = DbgModelTargetThreadContainerImpl.class, required = true, fixed = true), @TargetAttributeType(
@TargetAttributeType(name = DbgModelTargetProcessImpl.EXIT_CODE_ATTRIBUTE_NAME, type = Long.class), name = "Debug",
type = DbgModelTargetDebugContainerImpl.class,
required = true,
fixed = true),
@TargetAttributeType(
name = "Memory",
type = DbgModelTargetMemoryContainerImpl.class,
required = true,
fixed = true),
@TargetAttributeType(
name = "Modules",
type = DbgModelTargetModuleContainerImpl.class,
required = true,
fixed = true),
@TargetAttributeType(
name = "Threads",
type = DbgModelTargetThreadContainerImpl.class,
required = true,
fixed = true),
@TargetAttributeType(
name = DbgModelTargetProcessImpl.EXIT_CODE_ATTRIBUTE_NAME,
type = Long.class),
@TargetAttributeType(type = Void.class) }) @TargetAttributeType(type = Void.class) })
public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetProcess { implements DbgModelTargetProcess {
@ -219,6 +240,11 @@ public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
return modules; return modules;
} }
@Override
public DbgModelTargetMemoryContainer getMemory() {
return memory;
}
@Override @Override
public DbgProcess getProcess() { public DbgProcess getProcess() {
return process; return process;

View file

@ -31,11 +31,17 @@ import ghidra.dbg.target.schema.*;
import ghidra.dbg.target.schema.TargetObjectSchema.ResyncMode; import ghidra.dbg.target.schema.TargetObjectSchema.ResyncMode;
import ghidra.dbg.util.ConversionUtils; import ghidra.dbg.util.ConversionUtils;
@TargetObjectSchemaInfo(name = "RegisterContainer", elements = { @TargetObjectSchemaInfo(
@TargetElementType(type = DbgModelTargetRegisterImpl.class) }, elementResync = ResyncMode.ONCE, // name = "RegisterContainer",
elements = {
@TargetElementType(type = DbgModelTargetRegisterImpl.class) },
elementResync = ResyncMode.ONCE, //
attributes = { attributes = {
@TargetAttributeType(name = TargetRegisterBank.DESCRIPTIONS_ATTRIBUTE_NAME, type = DbgModelTargetRegisterContainerImpl.class), @TargetAttributeType(
@TargetAttributeType(type = Void.class) }, canonicalContainer = true) name = TargetRegisterBank.DESCRIPTIONS_ATTRIBUTE_NAME,
type = DbgModelTargetRegisterContainerImpl.class),
@TargetAttributeType(type = Void.class) },
canonicalContainer = true)
public class DbgModelTargetRegisterContainerImpl extends DbgModelTargetObjectImpl public class DbgModelTargetRegisterContainerImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetRegisterContainerAndBank { implements DbgModelTargetRegisterContainerAndBank {
@ -78,7 +84,7 @@ public class DbgModelTargetRegisterContainerImpl extends DbgModelTargetObjectImp
} }
public void threadStateChangedSpecific(DbgState state, DbgReason reason) { public void threadStateChangedSpecific(DbgState state, DbgReason reason) {
if (state.equals(DbgState.STOPPED)) { if (!state.equals(DbgState.RUNNING)) {
readRegistersNamed(getCachedElements().keySet()); readRegistersNamed(getCachedElements().keySet());
} }
} }

View file

@ -20,7 +20,7 @@ import java.util.Map;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import agent.dbgeng.manager.DbgStackFrame; import agent.dbgeng.manager.*;
import agent.dbgeng.model.iface2.*; import agent.dbgeng.model.iface2.*;
import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*; import ghidra.dbg.target.schema.*;
@ -83,32 +83,12 @@ public class DbgModelTargetStackImpl extends DbgModelTargetObjectImpl
} }
*/ */
@Override public void threadStateChangedSpecific(DbgState state, DbgReason reason) {
public void onRunning() { if (!state.equals(DbgState.RUNNING)) {
// NB: We don't want to do this apparently
//invalidateRegisterCaches();
setAccessible(false);
}
@Override
public void onStopped() {
setAccessible(true);
if (thread.getThread().getId().equals(getManager().getEventThread().getId())) {
update();
}
}
/**
* Re-fetch the stack frames, generating events for updates
*
* GDB doesn't produce stack change events, but they should only ever happen by running a
* target. Thus, every time we're STOPPED, this method should be called.
*/
@Override
public void update() {
requestElements(true).exceptionally(e -> { requestElements(true).exceptionally(e -> {
Msg.error(this, "Could not update stack " + this + " on STOPPED"); Msg.error(this, "Could not update stack " + this + " on STOPPED");
return null; return null;
}); });
} }
}
} }

View file

@ -123,6 +123,7 @@ public class DbgModelTargetThreadImpl extends DbgModelTargetObjectImpl
), reason.desc()); ), reason.desc());
//setExecutionState(targetState, reason.desc()); //setExecutionState(targetState, reason.desc());
registers.threadStateChangedSpecific(state, reason); registers.threadStateChangedSpecific(state, reason);
stack.threadStateChangedSpecific(state, reason);
} }
@Override @Override

View file

@ -15,6 +15,9 @@
*/ */
package agent.dbgeng.model.invm; package agent.dbgeng.model.invm;
import org.junit.Ignore;
import org.junit.Test;
import agent.dbgeng.model.AbstractModelForDbgengRootAttacherTest; import agent.dbgeng.model.AbstractModelForDbgengRootAttacherTest;
public class InVmModelForDbgengRootAttacherTest extends AbstractModelForDbgengRootAttacherTest { public class InVmModelForDbgengRootAttacherTest extends AbstractModelForDbgengRootAttacherTest {
@ -22,4 +25,12 @@ public class InVmModelForDbgengRootAttacherTest extends AbstractModelForDbgengRo
public ModelHost modelHost() throws Throwable { public ModelHost modelHost() throws Throwable {
return new InVmDbgengModelHost(); return new InVmDbgengModelHost();
} }
@Override
@Ignore
@Test
// Takes forever - passes w/ OTE on Memory in tear down
public void testAttachByPidThenResumeInterrupt() throws Throwable {
super.testAttachByPidThenResumeInterrupt();
}
} }

View file

@ -580,7 +580,11 @@ public class WrappedDbgModel
@Override @Override
public void setCurrentThreadId(DebugThreadId dti) { public void setCurrentThreadId(DebugThreadId dti) {
client.getSystemObjects().setCurrentThreadId(dti); DebugSystemObjects so = client.getSystemObjects();
DebugThreadId currentThreadId = so.getCurrentThreadId();
if (dti.id != currentThreadId.id) {
so.setCurrentThreadId(dti);
}
/* /*
if (USE_CLIENT) { if (USE_CLIENT) {
System.err.println("setCurrentThread"); System.err.println("setCurrentThread");

View file

@ -94,7 +94,10 @@ public class HDMAUtil {
if (kind.equals(ModelObjectKind.OBJECT_INTRINSIC) || if (kind.equals(ModelObjectKind.OBJECT_INTRINSIC) ||
kind.equals(ModelObjectKind.OBJECT_TARGET_OBJECT) || kind.equals(ModelObjectKind.OBJECT_TARGET_OBJECT) ||
kind.equals(ModelObjectKind.OBJECT_TARGET_OBJECT_REFERENCE)) { kind.equals(ModelObjectKind.OBJECT_TARGET_OBJECT_REFERENCE)) {
return target.getRawValueMap(); Map<String, ModelObject> map = target.getRawValueMap();
if (!map.isEmpty()) {
return map;
}
} }
return target.getKeyValueMap(); return target.getKeyValueMap();
} }

View file

@ -49,6 +49,7 @@ public class DbgListAttributesCommand extends AbstractDbgCommand<Map<String, ?>>
@Override @Override
public void invoke() { public void invoke() {
try {
updatedAttributes = new TreeMap<>(TargetObjectKeyComparator.ATTRIBUTE); updatedAttributes = new TreeMap<>(TargetObjectKeyComparator.ATTRIBUTE);
Map<String, ModelObject> map = access.getAttributes(path); Map<String, ModelObject> map = access.getAttributes(path);
Map<String, ?> existingAttributes = targetObject.getCachedAttributes(); Map<String, ?> existingAttributes = targetObject.getCachedAttributes();
@ -71,4 +72,9 @@ public class DbgListAttributesCommand extends AbstractDbgCommand<Map<String, ?>>
} }
updatedAttributes.putAll(targetObject.getIntrinsics()); updatedAttributes.putAll(targetObject.getIntrinsics());
} }
catch (Exception e) {
System.err.println("Failure in ListAttributes " + targetObject);
e.printStackTrace();
}
}
} }

View file

@ -227,10 +227,12 @@ public class DbgModel2TargetObjectImpl extends DefaultTargetObject<TargetObject,
attrs.put(TargetAccessConditioned.ACCESSIBLE_ATTRIBUTE_NAME, accessible); attrs.put(TargetAccessConditioned.ACCESSIBLE_ATTRIBUTE_NAME, accessible);
} }
if (proxy instanceof TargetExecutionStateful) { if (proxy instanceof TargetExecutionStateful) {
if (isValid()) {
TargetExecutionStateful stateful = (TargetExecutionStateful) proxy; TargetExecutionStateful stateful = (TargetExecutionStateful) proxy;
TargetExecutionState state = stateful.getExecutionState(); TargetExecutionState state = stateful.getExecutionState();
attrs.put(TargetExecutionStateful.STATE_ATTRIBUTE_NAME, state); attrs.put(TargetExecutionStateful.STATE_ATTRIBUTE_NAME, state);
} }
}
if (proxy instanceof TargetAttacher) { if (proxy instanceof TargetAttacher) {
attrs.put(TargetAttacher.SUPPORTED_ATTACH_KINDS_ATTRIBUTE_NAME, attrs.put(TargetAttacher.SUPPORTED_ATTACH_KINDS_ATTRIBUTE_NAME,
DbgModelTargetProcessImpl.SUPPORTED_KINDS); DbgModelTargetProcessImpl.SUPPORTED_KINDS);
@ -271,6 +273,7 @@ public class DbgModel2TargetObjectImpl extends DefaultTargetObject<TargetObject,
memory = new DbgModelTargetMemoryContainerImpl((DbgModelTargetProcess) proxy); memory = new DbgModelTargetMemoryContainerImpl((DbgModelTargetProcess) proxy);
} }
attrs.put(memory.getName(), memory); attrs.put(memory.getName(), memory);
memory.requestElements(true);
} }
if (proxy instanceof TargetThread) { if (proxy instanceof TargetThread) {
DbgModelTargetThread targetThread = (DbgModelTargetThread) proxy; DbgModelTargetThread targetThread = (DbgModelTargetThread) proxy;

View file

@ -114,8 +114,8 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
TargetFocusScope.FOCUS_ATTRIBUTE_NAME, focus // TargetFocusScope.FOCUS_ATTRIBUTE_NAME, focus //
), "Focus changed"); ), "Focus changed");
intrinsics.put(TargetFocusScope.FOCUS_ATTRIBUTE_NAME, focus); intrinsics.put(TargetFocusScope.FOCUS_ATTRIBUTE_NAME, focus);
DbgModelTargetSession session = focus.getParentSession(); //DbgModelTargetSession session = focus.getParentSession();
session.setActive(); //session.setActive();
} }
return doFire; return doFire;
} }
@ -179,7 +179,6 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
System.err.println("processAdded - null"); System.err.println("processAdded - null");
return; return;
} }
System.err.println("SERVER:processAdded: " + proc);
getListeners().fire.event(getProxy(), null, TargetEventType.PROCESS_CREATED, getListeners().fire.event(getProxy(), null, TargetEventType.PROCESS_CREATED,
"Process " + proc.getId() + " started " + "notepad.exe" + " pid=" + proc.getPid(), "Process " + proc.getId() + " started " + "notepad.exe" + " pid=" + proc.getPid(),
List.of(targetProcess)); List.of(targetProcess));
@ -194,9 +193,11 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
System.err.println("threadCreated - null"); System.err.println("threadCreated - null");
return; return;
} }
System.err.println("SERVER:threadCreated: " + targetThread);
getListeners().fire.event(getProxy(), targetThread, TargetEventType.THREAD_CREATED, getListeners().fire.event(getProxy(), targetThread, TargetEventType.THREAD_CREATED,
"Thread " + thread.getId() + " started", List.of(targetThread)); "Thread " + thread.getId() + " started", List.of(targetThread));
DelegateDbgModel2TargetObject delegate =
(DelegateDbgModel2TargetObject) targetThread.getDelegate();
delegate.threadStateChangedSpecific(DbgState.STARTING, DbgReason.Reasons.UNKNOWN);
}); });
} }
@ -212,6 +213,12 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
getListeners().fire.event(getProxy(), eventThread, TargetEventType.MODULE_LOADED, getListeners().fire.event(getProxy(), eventThread, TargetEventType.MODULE_LOADED,
"Library " + info.getModuleName() + " loaded", List.of(mod)); "Library " + info.getModuleName() + " loaded", List.of(mod));
}); });
getObject(getManager().getEventProcess()).thenAccept(p -> {
DbgModelTargetProcess eventProcess = (DbgModelTargetProcess) p;
DbgModel2TargetObjectImpl memory =
(DbgModel2TargetObjectImpl) eventProcess.getCachedAttribute("Memory");
memory.requestElements(false);
});
}); });
} }
@ -227,6 +234,12 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
getListeners().fire.event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED, getListeners().fire.event(getProxy(), eventThread, TargetEventType.MODULE_UNLOADED,
"Library " + info.getModuleName() + " unloaded", List.of(mod)); "Library " + info.getModuleName() + " unloaded", List.of(mod));
}); });
getObject(getManager().getEventProcess()).thenAccept(p -> {
DbgModelTargetProcess eventProcess = (DbgModelTargetProcess) p;
DbgModel2TargetObjectImpl memory =
(DbgModel2TargetObjectImpl) eventProcess.getCachedAttribute("Memory");
memory.requestElements(false);
});
}); });
} }
@ -335,6 +348,12 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
if (!process.getExecutionState().equals(TargetExecutionState.TERMINATED)) { if (!process.getExecutionState().equals(TargetExecutionState.TERMINATED)) {
process.setExecutionState(TargetExecutionState.INACTIVE, "Detached"); process.setExecutionState(TargetExecutionState.INACTIVE, "Detached");
} }
DbgModelTargetObject container = (DbgModelTargetObject) process.getParent();
DelegateDbgModel2TargetObject delegate =
(DelegateDbgModel2TargetObject) container.getDelegate();
delegate.changeElements(List.of( //
process.getIndex() //
), List.of(), Map.of(), "Removed");
process.getParent().resync(); process.getParent().resync();
}); });
} }
@ -344,10 +363,12 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
DbgModelTargetProcess targetProcess = DbgModelTargetProcess targetProcess =
(DbgModelTargetProcess) getModel().getModelObject(proc); (DbgModelTargetProcess) getModel().getModelObject(proc);
if (targetProcess != null) { if (targetProcess != null) {
if (targetProcess.isValid()) {
targetProcess.changeAttributes(List.of(), Map.of( // targetProcess.changeAttributes(List.of(), Map.of( //
TargetExecutionStateful.STATE_ATTRIBUTE_NAME, TargetExecutionState.TERMINATED, // TargetExecutionStateful.STATE_ATTRIBUTE_NAME, TargetExecutionState.TERMINATED, //
DbgModelTargetProcessImpl.EXIT_CODE_ATTRIBUTE_NAME, proc.getExitCode() // DbgModelTargetProcessImpl.EXIT_CODE_ATTRIBUTE_NAME, proc.getExitCode() //
), "Exited"); ), "Exited");
}
getListeners().fire.event(targetProcess.getProxy(), null, getListeners().fire.event(targetProcess.getProxy(), null,
TargetEventType.PROCESS_EXITED, TargetEventType.PROCESS_EXITED,
"Process " + proc.getId() + " exited code=" + proc.getExitCode(), "Process " + proc.getId() + " exited code=" + proc.getExitCode(),
@ -382,7 +403,9 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
TargetEventType eventType = getEventType(state, cause, reason); TargetEventType eventType = getEventType(state, cause, reason);
getListeners().fire.event(getProxy(), targetThread, eventType, getListeners().fire.event(getProxy(), targetThread, eventType,
"Thread " + thread.getId() + " state changed", List.of(targetThread)); "Thread " + thread.getId() + " state changed", List.of(targetThread));
targetThread.threadStateChangedSpecific(state, reason); DelegateDbgModel2TargetObject delegate =
(DelegateDbgModel2TargetObject) targetThread.getDelegate();
delegate.threadStateChangedSpecific(state, reason);
}); });
} }
@ -417,7 +440,7 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
@Override @Override
public void breakpointCreated(DbgBreakpointInfo info, DbgCause cause) { public void breakpointCreated(DbgBreakpointInfo info, DbgCause cause) {
int id = info.getDebugBreakpoint().getId(); int id = info.getId();
bptInfoMap.put(id, info); bptInfoMap.put(id, info);
getObjectRevisited(info.getProc(), List.of("Debug", "Breakpoints"), info); getObjectRevisited(info.getProc(), List.of("Debug", "Breakpoints"), info);
} }
@ -425,7 +448,7 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
@Override @Override
public void breakpointModified(DbgBreakpointInfo newInfo, DbgBreakpointInfo oldInfo, public void breakpointModified(DbgBreakpointInfo newInfo, DbgBreakpointInfo oldInfo,
DbgCause cause) { DbgCause cause) {
int id = newInfo.getDebugBreakpoint().getId(); int id = newInfo.getId();
bptInfoMap.put(id, newInfo); bptInfoMap.put(id, newInfo);
getObjectRevisited(newInfo.getProc(), List.of("Debug", "Breakpoints"), newInfo); getObjectRevisited(newInfo.getProc(), List.of("Debug", "Breakpoints"), newInfo);
} }

View file

@ -195,7 +195,7 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
model.getManager().addEventsListener((DbgEventsListener) proxy); model.getManager().addEventsListener((DbgEventsListener) proxy);
} }
setModelObject(modelObject); setModelObject(modelObject);
update0(); init();
} }
public DelegateDbgModel2TargetObject clone(String key, ModelObject modelObject) { public DelegateDbgModel2TargetObject clone(String key, ModelObject modelObject) {
@ -224,6 +224,12 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
return ret; return ret;
} }
@Override
protected void doInvalidate(TargetObject branch, String reason) {
super.doInvalidate(branch, reason);
getManager().removeStateListener(accessListener);
}
protected void checkExited(DbgState state, DbgCause cause) { protected void checkExited(DbgState state, DbgCause cause) {
TargetExecutionState exec = TargetExecutionState.INACTIVE; TargetExecutionState exec = TargetExecutionState.INACTIVE;
switch (state) { switch (state) {
@ -274,7 +280,7 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
} }
} }
public void update0() { public void init() {
if (PathUtils.isLink(parent.getPath(), proxy.getName(), proxy.getPath())) { if (PathUtils.isLink(parent.getPath(), proxy.getName(), proxy.getPath())) {
return; return;
} }
@ -285,22 +291,11 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
return; return;
} }
if (proxy instanceof DbgModelTargetRegisterContainer || // if (proxy instanceof DbgModelTargetRegisterContainer || //
proxy.getName().equals("Stack")) { proxy.getName().equals("Stack") ||
proxy.getName().equals("Debug")) {
requestAttributes(false); requestAttributes(false);
return; return;
} }
/*
if (proxy instanceof DbgModelTargetRegisterBank) {
requestAttributes(false).thenAccept(__ -> {
DbgModelTargetRegisterBank bank = (DbgModelTargetRegisterBank) proxy;
Map<String, byte[]> result = bank.getValues();
System.err.println("SERVER:fire.registersUpdated " + bank);
listeners.fire.registersUpdated(bank, result);
});
return;
}
*/
if (proxy instanceof DbgModelTargetProcessContainer || // if (proxy instanceof DbgModelTargetProcessContainer || //
proxy instanceof DbgModelTargetThreadContainer || // proxy instanceof DbgModelTargetThreadContainer || //
proxy instanceof DbgModelTargetModuleContainer || // proxy instanceof DbgModelTargetModuleContainer || //
@ -311,44 +306,6 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
} }
} }
private void update() {
if (PathUtils.isLink(parent.getPath(), proxy.getName(), proxy.getPath())) {
return;
}
if (proxy instanceof DbgModelTargetProcessContainer || //
proxy instanceof DbgModelTargetThreadContainer || //
proxy instanceof DbgModelTargetModuleContainer || //
proxy instanceof DbgModelTargetBreakpointContainer || //
proxy instanceof DbgModelTargetRegisterContainer || //
proxy instanceof DbgModelTargetRegisterBank || //
proxy instanceof DbgModelTargetStack || //
proxy instanceof DbgModelTargetTTD) {
requestElements(false);
requestAttributes(false);
return;
}
/*
if (proxy instanceof DbgModelTargetRegisterBank) {
requestAttributes(false).thenAccept(__ -> {
DbgModelTargetRegisterBank bank = (DbgModelTargetRegisterBank) proxy;
Map<String, byte[]> result = bank.getValues();
System.err.println("SERVER:fire.registersUpdated " + bank);
listeners.fire.registersUpdated(bank, result);
});
return;
}
*/
if (proxy instanceof DbgModelTargetRegister || //
proxy instanceof DbgModelTargetStackFrame) {
requestAttributes(false);
return;
}
if (proxy.getName().equals("Debug")) {
requestAttributes(false);
return;
}
}
public void onRunning() { public void onRunning() {
invalidate(); invalidate();
setAccessible(false); setAccessible(false);
@ -356,7 +313,6 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
public void onStopped() { public void onStopped() {
setAccessible(true); setAccessible(true);
update();
} }
public void onExit() { public void onExit() {
@ -416,7 +372,6 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
@Override @Override
public void setBreakpointEnabled(boolean enabled) { public void setBreakpointEnabled(boolean enabled) {
update();
this.breakpointEnabled = enabled; this.breakpointEnabled = enabled;
} }
@ -425,4 +380,53 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
return breakpointActions; return breakpointActions;
} }
public void threadStateChangedSpecific(DbgState state, DbgReason reason) {
if (state.equals(DbgState.RUNNING)) {
return;
}
if (proxy instanceof TargetThread) {
List<DelegateDbgModel2TargetObject> delegates = new ArrayList<>();
TargetObject stack =
(TargetObject) getCachedAttribute("Stack");
DbgModelTargetStack frames =
(DbgModelTargetStack) stack.getCachedAttribute("Frames");
delegates.add((DelegateDbgModel2TargetObject) frames.getDelegate());
DbgModelTargetRegisterContainer container =
(DbgModelTargetRegisterContainer) getCachedAttribute("Registers");
delegates.add((DelegateDbgModel2TargetObject) container.getDelegate());
DbgModelTargetRegisterBank bank =
(DbgModelTargetRegisterBank) container.getCachedAttribute("User");
delegates.add((DelegateDbgModel2TargetObject) bank.getDelegate());
for (DelegateDbgModel2TargetObject delegate : delegates) {
delegate.threadStateChangedSpecific(state, reason);
}
}
if (proxy instanceof TargetRegisterContainer) {
requestElements(false);
requestAttributes(false);
}
if (proxy instanceof TargetRegisterBank) {
TargetRegisterBank bank = (TargetRegisterBank) proxy;
//requestElements(false);
requestAttributes(false).thenAccept(__ -> {
bank.readRegistersNamed(getCachedAttributes().keySet());
});
}
if (proxy instanceof TargetStack) {
requestAttributes(false);
requestElements(false).thenAccept(__ -> {
for (TargetObject obj : getCachedElements().values()) {
if (obj instanceof TargetStackFrame) {
DbgModelTargetObject frame = (DbgModelTargetObject) obj;
DelegateDbgModel2TargetObject delegate =
(DelegateDbgModel2TargetObject) frame.getDelegate();
delegate.threadStateChangedSpecific(state, reason);
}
}
});
}
if (proxy instanceof TargetStackFrame) {
requestAttributes(false);
}
}
} }

View file

@ -18,8 +18,8 @@
<attribute name="_value" schema="ANY" hidden="yes" /> <attribute name="_value" schema="ANY" hidden="yes" />
<attribute name="_type" schema="STRING" hidden="yes" /> <attribute name="_type" schema="STRING" hidden="yes" />
<attribute name="_order" schema="INT" hidden="yes" /> <attribute name="_order" schema="INT" hidden="yes" />
<attribute name="_event_process" schema="STRING" hidden="yes" /> <attribute name="_event_process" schema="OBJECT" hidden="yes" />
<attribute name="_event_thread" schema="STRING" hidden="yes" /> <attribute name="_event_thread" schema="OBJECT" hidden="yes" />
<attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" hidden="yes" /> <attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" hidden="yes" />
<attribute name="_focus" schema="OBJECT" required="yes" hidden="yes" /> <attribute name="_focus" schema="OBJECT" required="yes" hidden="yes" />
<attribute name="_system" schema="OBJECT" hidden="yes" /> <attribute name="_system" schema="OBJECT" hidden="yes" />

View file

@ -1622,6 +1622,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
if (visibleChange) { if (visibleChange) {
container.propagateProvider(DebuggerObjectsProvider.this); container.propagateProvider(DebuggerObjectsProvider.this);
update(container); update(container);
getComponent().repaint();
} }
} }
} }
@ -1645,6 +1646,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
if (visibleChange) { if (visibleChange) {
container.propagateProvider(DebuggerObjectsProvider.this); container.propagateProvider(DebuggerObjectsProvider.this);
update(container); update(container);
getComponent().repaint();
} }
} }
if (parent != null && isAutorecord() && if (parent != null && isAutorecord() &&

View file

@ -1016,6 +1016,19 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
recorder.requestFocus(focus); recorder.requestFocus(focus);
} }
public void activateNoFocusChange(DebuggerCoordinates coordinates) {
DebuggerCoordinates prev;
DebuggerCoordinates resolved;
synchronized (listenersByTrace) {
prev = current;
resolved = doSetCurrent(coordinates);
}
if (resolved == null) {
return;
}
prepareViewAndFireEvent(resolved);
}
@Override @Override
public void activateTrace(Trace trace) { public void activateTrace(Trace trace) {
activate(DebuggerCoordinates.trace(trace)); activate(DebuggerCoordinates.trace(trace));
@ -1028,7 +1041,7 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
@Override @Override
public void activateSnap(long snap) { public void activateSnap(long snap) {
activate(DebuggerCoordinates.snap(snap)); activateNoFocusChange(DebuggerCoordinates.snap(snap));
} }
@Override @Override