mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GP-930: Various improvements and fixes for Windows debugging
This commit is contained in:
parent
a1cfeebcc9
commit
10674175bb
39 changed files with 438 additions and 246 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -21,6 +21,8 @@ public interface DbgModuleMemory {
|
|||
|
||||
String getName();
|
||||
|
||||
Long getId();
|
||||
|
||||
long getVmaStart();
|
||||
|
||||
long getVmaEnd();
|
||||
|
|
|
@ -85,6 +85,10 @@ public class DbgBreakpointInfo {
|
|||
offset, expression);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return bpt.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Integer.toHexString(bpt.getId());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ public class DbgReadRegistersCommand extends AbstractDbgCommand<Map<DbgRegister,
|
|||
}
|
||||
}
|
||||
}
|
||||
//so.setCurrentThreadId(previous);
|
||||
so.setCurrentThreadId(previous);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,6 @@ public class DbgStackListFramesCommand extends AbstractDbgCommand<List<DbgStackF
|
|||
tf.Params[3].longValue());
|
||||
result.add(frame);
|
||||
}
|
||||
//so.setCurrentThreadId(previous);
|
||||
so.setCurrentThreadId(previous);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,6 +66,6 @@ public class DbgWriteRegistersCommand extends AbstractDbgCommand<Void> {
|
|||
}
|
||||
}
|
||||
registers.setValues(DebugRegisterSource.DEBUG_REGSRC_DEBUGGEE, values);
|
||||
//so.setCurrentThreadId(previous);
|
||||
so.setCurrentThreadId(previous);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -55,6 +55,11 @@ public class DbgModuleMemoryImpl implements DbgModuleMemory {
|
|||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getId() {
|
||||
return vmaStart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getVmaStart() {
|
||||
return vmaStart;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,6 +123,7 @@ public class DbgModelTargetThreadImpl extends DbgModelTargetObjectImpl
|
|||
), reason.desc());
|
||||
//setExecutionState(targetState, reason.desc());
|
||||
registers.threadStateChangedSpecific(state, reason);
|
||||
stack.threadStateChangedSpecific(state, reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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() &&
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue