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

View file

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

View file

@ -192,6 +192,16 @@ public interface DbgManager extends AutoCloseable, DbgBreakpointInsertions {
*/
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
*
@ -242,6 +252,21 @@ public interface DbgManager extends AutoCloseable, DbgBreakpointInsertions {
*/
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
*

View file

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

View file

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

View file

@ -15,8 +15,8 @@
*/
package agent.dbgeng.manager.cmd;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.Map.Entry;
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.impl.DbgManagerImpl;
import agent.dbgeng.manager.impl.DbgModuleMemoryImpl;
import ghidra.util.Msg;
public class DbgListMemoryRegionsCommand extends AbstractDbgCommand<List<DbgModuleMemory>> {
@ -38,6 +39,23 @@ public class DbgListMemoryRegionsCommand extends AbstractDbgCommand<List<DbgModu
@Override
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;
}
@ -83,10 +101,10 @@ public class DbgListMemoryRegionsCommand extends AbstractDbgCommand<List<DbgModu
isWrite |= protect.isWrite();
isExec |= protect.isExecute();
}
DbgModuleMemoryImpl section =
DbgModuleMemoryImpl region =
new DbgModuleMemoryImpl(Long.toHexString(vmaStart), vmaStart, vmaEnd,
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;
}

View file

@ -16,6 +16,7 @@
package agent.dbgeng.manager.cmd;
import agent.dbgeng.dbgeng.DebugProcessId;
import agent.dbgeng.dbgeng.DebugSystemObjects;
import agent.dbgeng.manager.DbgProcess;
import agent.dbgeng.manager.impl.DbgManagerImpl;
@ -39,7 +40,11 @@ public class DbgSetActiveProcessCommand extends AbstractDbgCommand<Void> {
if (process != null) {
DebugProcessId id = process.getId();
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());
result.add(frame);
}
//so.setCurrentThreadId(previous);
so.setCurrentThreadId(previous);
}
}

View file

@ -15,8 +15,7 @@
*/
package agent.dbgeng.manager.cmd;
import agent.dbgeng.dbgeng.DebugControl;
import agent.dbgeng.dbgeng.DebugThreadId;
import agent.dbgeng.dbgeng.*;
import agent.dbgeng.manager.DbgThread;
import agent.dbgeng.manager.impl.DbgManagerImpl;
@ -56,7 +55,9 @@ public class DbgThreadHoldCommand extends AbstractDbgCommand<Void> {
public void invoke() {
DebugThreadId id = thread.getId();
if (id != null) {
manager.getSystemObjects().setCurrentThreadId(id);
DebugSystemObjects so = manager.getSystemObjects();
DebugThreadId previous = so.getCurrentThreadId();
so.setCurrentThreadId(id);
if (!manager.isKernelMode()) {
DebugControl control = manager.getControl();
if (preferFreeze) {
@ -68,6 +69,7 @@ public class DbgThreadHoldCommand extends AbstractDbgCommand<Void> {
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);
//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.evt.*;
import agent.dbgeng.model.iface1.*;
import agent.dbgeng.model.iface2.DbgModelTargetObject;
import agent.dbgeng.model.iface2.DbgModelTargetThread;
import ghidra.async.*;
import ghidra.comm.util.BitmaskSet;
import ghidra.dbg.target.TargetObject;
@ -92,6 +94,10 @@ public class DbgManagerImpl implements DbgManager {
private final Map<Long, DbgBreakpointInfo> unmodifiableBreakpoints =
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 =
new AsyncReference<>(DbgState.NOT_STARTED);
private final HandlerMap<DbgEvent<?>, Void, DebugStatus> handlerMap = new HandlerMap<>();
@ -109,6 +115,7 @@ public class DbgManagerImpl implements DbgManager {
private DbgThread eventThread;
private volatile boolean waiting = false;
private boolean kernelMode = false;
private boolean ignoreEventThread = false;
private CompletableFuture<String> continuation;
private long processCount = 0;
@ -267,6 +274,11 @@ public class DbgManagerImpl implements DbgManager {
return unmodifiableBreakpoints;
}
@Override
public Map<Long, DbgModuleMemory> getKnownMemoryRegions() {
return unmodifiableMemory;
}
private DbgBreakpointInfo addKnownBreakpoint(DbgBreakpointInfo bkpt, boolean expectExisting) {
DbgBreakpointInfo old = breakpoints.put(bkpt.getNumber(), bkpt);
if (expectExisting && old == null) {
@ -606,8 +618,8 @@ public class DbgManagerImpl implements DbgManager {
DebugControl control = dbgeng.getControl();
int execType = WinNTExtra.Machine.IMAGE_FILE_MACHINE_AMD64.val;
try {
so.setCurrentProcessId(epid);
so.setCurrentThreadId(etid);
//so.setCurrentProcessId(epid);
//so.setCurrentThreadId(etid);
execType = control.getExecutingProcessorType();
}
catch (Exception e) {
@ -652,6 +664,7 @@ public class DbgManagerImpl implements DbgManager {
DebugBreakpoint bp = evt.getInfo();
DbgBreakpointInfo info = new DbgBreakpointInfo(bp, getEventProcess(), getEventThread());
getEventListeners().fire.threadSelected(eventThread, null, evt.getCause());
getEventListeners().fire.breakpointHit(info, evt.getCause());
String key = Integer.toHexString(bp.getId());
@ -670,6 +683,7 @@ public class DbgManagerImpl implements DbgManager {
*/
protected DebugStatus processException(DbgExceptionEvent evt, Void v) {
DebugThreadId eventId = updateState();
getEventListeners().fire.threadSelected(eventThread, null, evt.getCause());
DebugExceptionRecord64 info = evt.getInfo();
String key = Integer.toHexString(info.code);
@ -764,16 +778,17 @@ public class DbgManagerImpl implements DbgManager {
DebugProcessInfo info = evt.getInfo();
long handle = info.handle;
DebugProcessId id = so.getProcessIdByHandle(handle);
so.setCurrentProcessId(id);
//so.setCurrentProcessId(id);
int pid = so.getCurrentProcessSystemId();
DbgProcessImpl proc = getProcessComputeIfAbsent(id, pid);
getEventListeners().fire.processAdded(proc, DbgCause.Causes.UNCLAIMED);
getEventListeners().fire.processAdded(proc, evt.getCause());
getEventListeners().fire.processSelected(proc, evt.getCause());
handle = info.initialThreadInfo.handle;
DebugThreadId idt = so.getThreadIdByHandle(handle);
int tid = so.getCurrentThreadSystemId();
DbgThreadImpl thread = getThreadComputeIfAbsent(idt, proc, tid);
getEventListeners().fire.threadCreated(thread, evt.getCause());
getEventListeners().fire.threadSelected(thread, null, evt.getCause());
//proc.moduleLoaded(info.moduleInfo);
@ -1041,24 +1056,25 @@ public class DbgManagerImpl implements DbgManager {
if (bptId == DbgEngUtil.DEBUG_ANY_ID.longValue()) {
changeBreakpoints();
}
DebugBreakpoint bpt = getControl().getBreakpointById((int) bptId);
if (bpt == null) {
doBreakpointDeleted(bptId, evt.getCause());
return;
}
DbgBreakpointInfo knownBreakpoint = getKnownBreakpoint(bptId);
if (knownBreakpoint == null) {
breakpointInfo = new DbgBreakpointInfo(bpt, getCurrentProcess());
if (breakpointInfo.getOffset() != null) {
doBreakpointCreated(breakpointInfo, evt.getCause());
else {
DebugBreakpoint bpt = getControl().getBreakpointById((int) bptId);
if (bpt == null && bptId != DbgEngUtil.DEBUG_ANY_ID.longValue()) {
doBreakpointDeleted(bptId, evt.getCause());
return;
}
return;
DbgBreakpointInfo knownBreakpoint = getKnownBreakpoint(bptId);
if (knownBreakpoint == null) {
breakpointInfo = new DbgBreakpointInfo(bpt, getCurrentProcess());
if (breakpointInfo.getOffset() != null) {
doBreakpointCreated(breakpointInfo, evt.getCause());
}
return;
}
breakpointInfo = knownBreakpoint;
breakpointInfo.setBreakpoint(bpt);
doBreakpointModified(breakpointInfo, evt.getCause());
}
breakpointInfo = knownBreakpoint;
breakpointInfo.setBreakpoint(bpt);
}
doBreakpointModified(breakpointInfo, evt.getCause());
}
/**
@ -1274,6 +1290,18 @@ public class DbgManagerImpl implements DbgManager {
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
public CompletableFuture<?> launch(List<String> args) {
return execute(new DbgLaunchProcessCommand(this, args));
@ -1492,6 +1520,7 @@ public class DbgManagerImpl implements DbgManager {
//System.err.println("EXIT");
waiting = false;
updateState();
getEventListeners().fire.threadSelected(eventThread, null, Causes.UNCLAIMED);
return CompletableFuture.completedFuture(null);
}
@ -1511,6 +1540,18 @@ public class DbgManagerImpl implements DbgManager {
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) {
return null;
}

View file

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

View file

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

View file

@ -67,21 +67,11 @@ public interface DbgModelTargetBreakpointSpec extends //
@Override
public default TargetBreakpointKindSet getKinds() {
switch (getBreakpointInfo().getType()) {
case BREAKPOINT:
return TargetBreakpointKindSet.of(TargetBreakpointKind.SW_EXECUTE);
case HW_BREAKPOINT:
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);
default:
return TargetBreakpointKindSet.of();
}
return TargetBreakpointKindSet.of(
TargetBreakpointKind.SW_EXECUTE,
TargetBreakpointKind.HW_EXECUTE,
TargetBreakpointKind.READ,
TargetBreakpointKind.WRITE);
}
@Override

View file

@ -31,4 +31,6 @@ public interface DbgModelTargetMemoryContainer extends DbgModelTargetObject, Tar
@Override
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 DbgModelTargetMemoryContainer getMemory();
public void threadStateChangedSpecific(DbgThread thread, DbgState state);
public default DbgProcess getProcess() {

View file

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

View file

@ -59,6 +59,9 @@ public interface DbgModelTargetSession extends //
@Override
public default void consoleOutput(String output, int mask) {
if (!isValid()) {
return;
}
Channel chan = TargetConsole.Channel.STDOUT;
if (((mask & 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")) {
return;
}
if (!isValid()) {
return;
}
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.model.iface1.*;
import agent.dbgeng.model.impl.DbgModelTargetStackImpl;
import ghidra.dbg.target.*;
import ghidra.dbg.target.TargetThread;
import ghidra.dbg.util.PathUtils;
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
public default CompletableFuture<Void> setActive() {
DbgManagerImpl manager = getManager();
@ -75,4 +66,6 @@ public interface DbgModelTargetThread extends //
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.schema.*;
@TargetObjectSchemaInfo(name = "BreakpointContainer", elements = { //
@TargetElementType(type = DbgModelTargetBreakpointSpecImpl.class) //
}, attributes = { //
@TargetAttributeType(type = Void.class) //
}, canonicalContainer = true)
@TargetObjectSchemaInfo(
name = "BreakpointContainer",
elements = { //
@TargetElementType(type = DbgModelTargetBreakpointSpecImpl.class) //
},
attributes = { //
@TargetAttributeType(type = Void.class) //
},
canonicalContainer = true)
public class DbgModelTargetBreakpointContainerImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetBreakpointContainer {

View file

@ -28,19 +28,30 @@ import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
import ghidra.dbg.util.PathUtils;
import ghidra.util.datastruct.ListenerSet;
@TargetObjectSchemaInfo(name = "BreakpointSpec", attributes = { //
@TargetAttributeType( //
@TargetObjectSchemaInfo(
name = "BreakpointSpec",
attributes = { //
@TargetAttributeType( //
name = TargetBreakpointSpec.CONTAINER_ATTRIBUTE_NAME, //
type = DbgModelTargetBreakpointContainerImpl.class), //
@TargetAttributeType( //
@TargetAttributeType( //
name = TargetBreakpointLocation.SPEC_ATTRIBUTE_NAME, //
type = DbgModelTargetBreakpointSpecImpl.class), //
@TargetAttributeType(name = DbgModelTargetBreakpointSpecImpl.BPT_TYPE_ATTRIBUTE_NAME, type = String.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) //
}, canonicalContainer = true)
@TargetAttributeType(
name = DbgModelTargetBreakpointSpecImpl.BPT_TYPE_ATTRIBUTE_NAME,
type = String.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) //
},
canonicalContainer = true)
public class DbgModelTargetBreakpointSpecImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetBreakpointSpec {
@ -117,10 +128,9 @@ public class DbgModelTargetBreakpointSpecImpl extends DbgModelTargetObjectImpl
/**
* Update the enabled field
*
* This does not actually toggle the breakpoint. It just updates the field
* and calls the proper listeners. To actually toggle the breakpoint, use
* {@link #toggle(boolean)} instead, which if effective, should eventually
* cause this method to be called.
* This does not actually toggle the breakpoint. It just updates the field and calls the proper
* listeners. To actually toggle the breakpoint, use {@link #toggle(boolean)} instead, which if
* effective, should eventually cause this method to be called.
*
* @param enabled true if enabled, false if disabled
* @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.util.datastruct.WeakValueHashMap;
@TargetObjectSchemaInfo(name = "Memory", elements = {
@TargetElementType(type = DbgModelTargetMemoryRegionImpl.class) }, attributes = {
@TargetAttributeType(type = Void.class) }, canonicalContainer = true)
@TargetObjectSchemaInfo(
name = "Memory",
elements = {
@TargetElementType(type = DbgModelTargetMemoryRegionImpl.class) },
attributes = {
@TargetAttributeType(type = Void.class) },
canonicalContainer = true)
public class DbgModelTargetMemoryContainerImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetMemoryContainer {
@ -49,12 +53,13 @@ public class DbgModelTargetMemoryContainerImpl extends DbgModelTargetObjectImpl
public DbgModelTargetMemoryContainerImpl(DbgModelTargetProcess process) {
super(process.getModel(), process, "Memory", "MemoryContainer");
this.process = process;
requestElements(true);
}
@Override
public CompletableFuture<Void> requestElements(boolean refresh) {
DbgModelTargetProcess targetProcess = getParentProcess();
if (!targetProcess.getProcess().equals(getManager().getCurrentProcess())) {
if (!refresh || !targetProcess.getProcess().equals(getManager().getCurrentProcess())) {
return AsyncUtils.NIL;
}
return listMemory().thenAccept(byName -> {
@ -258,8 +263,4 @@ public class DbgModelTargetMemoryContainerImpl extends DbgModelTargetObjectImpl
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() {
setAccessible(true);
update();
}
public void onExit() {
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) {
TargetExecutionState exec = TargetExecutionState.INACTIVE;
switch (state) {

View file

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

View file

@ -29,13 +29,34 @@ import ghidra.dbg.target.TargetEventScope.TargetEventType;
import ghidra.dbg.target.schema.*;
import ghidra.dbg.util.PathUtils;
@TargetObjectSchemaInfo(name = "Process", elements = {
@TargetElementType(type = Void.class) }, attributes = {
@TargetAttributeType(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),
@TargetObjectSchemaInfo(
name = "Process",
elements = {
@TargetElementType(type = Void.class) },
attributes = {
@TargetAttributeType(
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) })
public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
implements DbgModelTargetProcess {
@ -219,6 +240,11 @@ public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
return modules;
}
@Override
public DbgModelTargetMemoryContainer getMemory() {
return memory;
}
@Override
public DbgProcess getProcess() {
return process;

View file

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

View file

@ -20,7 +20,7 @@ import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import agent.dbgeng.manager.DbgStackFrame;
import agent.dbgeng.manager.*;
import agent.dbgeng.model.iface2.*;
import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*;
@ -83,32 +83,12 @@ public class DbgModelTargetStackImpl extends DbgModelTargetObjectImpl
}
*/
@Override
public void onRunning() {
// 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();
public void threadStateChangedSpecific(DbgState state, DbgReason reason) {
if (!state.equals(DbgState.RUNNING)) {
requestElements(true).exceptionally(e -> {
Msg.error(this, "Could not update stack " + this + " on STOPPED");
return null;
});
}
}
/**
* 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 -> {
Msg.error(this, "Could not update stack " + this + " on STOPPED");
return null;
});
}
}

View file

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

View file

@ -15,6 +15,9 @@
*/
package agent.dbgeng.model.invm;
import org.junit.Ignore;
import org.junit.Test;
import agent.dbgeng.model.AbstractModelForDbgengRootAttacherTest;
public class InVmModelForDbgengRootAttacherTest extends AbstractModelForDbgengRootAttacherTest {
@ -22,4 +25,12 @@ public class InVmModelForDbgengRootAttacherTest extends AbstractModelForDbgengRo
public ModelHost modelHost() throws Throwable {
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
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) {
System.err.println("setCurrentThread");

View file

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

View file

@ -49,26 +49,32 @@ public class DbgListAttributesCommand extends AbstractDbgCommand<Map<String, ?>>
@Override
public void invoke() {
updatedAttributes = new TreeMap<>(TargetObjectKeyComparator.ATTRIBUTE);
Map<String, ModelObject> map = access.getAttributes(path);
Map<String, ?> existingAttributes = targetObject.getCachedAttributes();
for (String key : map.keySet()) {
DbgModel2TargetProxy proxyAttribute;
ModelObject obj = map.get(key);
String atKey = obj.getSearchKey();
Object object = existingAttributes.get(atKey);
if (object != null && (object instanceof DbgModelTargetObject)) {
proxyAttribute = (DbgModel2TargetProxy) object;
DelegateDbgModel2TargetObject delegate = proxyAttribute.getDelegate();
delegate.setModelObject(obj);
updatedAttributes.put(key, proxyAttribute);
}
else {
proxyAttribute = (DbgModel2TargetProxy) DelegateDbgModel2TargetObject
.makeProxy(targetObject.getModel(), targetObject, atKey, obj);
updatedAttributes.put(key, proxyAttribute);
try {
updatedAttributes = new TreeMap<>(TargetObjectKeyComparator.ATTRIBUTE);
Map<String, ModelObject> map = access.getAttributes(path);
Map<String, ?> existingAttributes = targetObject.getCachedAttributes();
for (String key : map.keySet()) {
DbgModel2TargetProxy proxyAttribute;
ModelObject obj = map.get(key);
String atKey = obj.getSearchKey();
Object object = existingAttributes.get(atKey);
if (object != null && (object instanceof DbgModelTargetObject)) {
proxyAttribute = (DbgModel2TargetProxy) object;
DelegateDbgModel2TargetObject delegate = proxyAttribute.getDelegate();
delegate.setModelObject(obj);
updatedAttributes.put(key, proxyAttribute);
}
else {
proxyAttribute = (DbgModel2TargetProxy) DelegateDbgModel2TargetObject
.makeProxy(targetObject.getModel(), targetObject, atKey, obj);
updatedAttributes.put(key, proxyAttribute);
}
}
updatedAttributes.putAll(targetObject.getIntrinsics());
}
catch (Exception e) {
System.err.println("Failure in ListAttributes " + targetObject);
e.printStackTrace();
}
updatedAttributes.putAll(targetObject.getIntrinsics());
}
}

View file

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

View file

@ -114,8 +114,8 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
TargetFocusScope.FOCUS_ATTRIBUTE_NAME, focus //
), "Focus changed");
intrinsics.put(TargetFocusScope.FOCUS_ATTRIBUTE_NAME, focus);
DbgModelTargetSession session = focus.getParentSession();
session.setActive();
//DbgModelTargetSession session = focus.getParentSession();
//session.setActive();
}
return doFire;
}
@ -179,7 +179,6 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
System.err.println("processAdded - null");
return;
}
System.err.println("SERVER:processAdded: " + proc);
getListeners().fire.event(getProxy(), null, TargetEventType.PROCESS_CREATED,
"Process " + proc.getId() + " started " + "notepad.exe" + " pid=" + proc.getPid(),
List.of(targetProcess));
@ -194,9 +193,11 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
System.err.println("threadCreated - null");
return;
}
System.err.println("SERVER:threadCreated: " + targetThread);
getListeners().fire.event(getProxy(), targetThread, TargetEventType.THREAD_CREATED,
"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,
"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,
"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)) {
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();
});
}
@ -344,10 +363,12 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
DbgModelTargetProcess targetProcess =
(DbgModelTargetProcess) getModel().getModelObject(proc);
if (targetProcess != null) {
targetProcess.changeAttributes(List.of(), Map.of( //
TargetExecutionStateful.STATE_ATTRIBUTE_NAME, TargetExecutionState.TERMINATED, //
DbgModelTargetProcessImpl.EXIT_CODE_ATTRIBUTE_NAME, proc.getExitCode() //
), "Exited");
if (targetProcess.isValid()) {
targetProcess.changeAttributes(List.of(), Map.of( //
TargetExecutionStateful.STATE_ATTRIBUTE_NAME, TargetExecutionState.TERMINATED, //
DbgModelTargetProcessImpl.EXIT_CODE_ATTRIBUTE_NAME, proc.getExitCode() //
), "Exited");
}
getListeners().fire.event(targetProcess.getProxy(), null,
TargetEventType.PROCESS_EXITED,
"Process " + proc.getId() + " exited code=" + proc.getExitCode(),
@ -382,7 +403,9 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
TargetEventType eventType = getEventType(state, cause, reason);
getListeners().fire.event(getProxy(), targetThread, eventType,
"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
public void breakpointCreated(DbgBreakpointInfo info, DbgCause cause) {
int id = info.getDebugBreakpoint().getId();
int id = info.getId();
bptInfoMap.put(id, info);
getObjectRevisited(info.getProc(), List.of("Debug", "Breakpoints"), info);
}
@ -425,7 +448,7 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
@Override
public void breakpointModified(DbgBreakpointInfo newInfo, DbgBreakpointInfo oldInfo,
DbgCause cause) {
int id = newInfo.getDebugBreakpoint().getId();
int id = newInfo.getId();
bptInfoMap.put(id, 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);
}
setModelObject(modelObject);
update0();
init();
}
public DelegateDbgModel2TargetObject clone(String key, ModelObject modelObject) {
@ -224,6 +224,12 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
return ret;
}
@Override
protected void doInvalidate(TargetObject branch, String reason) {
super.doInvalidate(branch, reason);
getManager().removeStateListener(accessListener);
}
protected void checkExited(DbgState state, DbgCause cause) {
TargetExecutionState exec = TargetExecutionState.INACTIVE;
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())) {
return;
}
@ -285,22 +291,11 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
return;
}
if (proxy instanceof DbgModelTargetRegisterContainer || //
proxy.getName().equals("Stack")) {
proxy.getName().equals("Stack") ||
proxy.getName().equals("Debug")) {
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 DbgModelTargetProcessContainer || //
proxy instanceof DbgModelTargetThreadContainer || //
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() {
invalidate();
setAccessible(false);
@ -356,7 +313,6 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
public void onStopped() {
setAccessible(true);
update();
}
public void onExit() {
@ -416,7 +372,6 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
@Override
public void setBreakpointEnabled(boolean enabled) {
update();
this.breakpointEnabled = enabled;
}
@ -425,4 +380,53 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
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="_type" schema="STRING" hidden="yes" />
<attribute name="_order" schema="INT" hidden="yes" />
<attribute name="_event_process" schema="STRING" hidden="yes" />
<attribute name="_event_thread" schema="STRING" hidden="yes" />
<attribute name="_event_process" schema="OBJECT" hidden="yes" />
<attribute name="_event_thread" schema="OBJECT" hidden="yes" />
<attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" hidden="yes" />
<attribute name="_focus" schema="OBJECT" required="yes" hidden="yes" />
<attribute name="_system" schema="OBJECT" hidden="yes" />

View file

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

View file

@ -1016,6 +1016,19 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
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
public void activateTrace(Trace trace) {
activate(DebuggerCoordinates.trace(trace));
@ -1028,7 +1041,7 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
@Override
public void activateSnap(long snap) {
activate(DebuggerCoordinates.snap(snap));
activateNoFocusChange(DebuggerCoordinates.snap(snap));
}
@Override