mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-29 03:55:53 +08:00
GP-1768A: limits on initial loads; fix for possible id/pid/tid mismatch
GP-1768A: check for symbols; misc fixes GP-1768A: suppress descent for kernel mode GP-1768A: undoing a few things GP-1768A: undoing a few things again GP-1768A: added data offset methods intending to replace pids/tids for kernel lookups GP-1768A: resorting to CLI for state GP-1768A: resorting to CLI for state GP-1768A: add ability to set implicit thread/process GP-1768A: cleanup GP-1768A: default to ALIVE ofr kernel GP-1768A: better setActive implementations GP-1768B: new faster utility methods for model GP-1768B: one more use GP-1768A: NPE fix GP-1768: faster SetCurrentState; minimize calls GP-1768B: better autorecord GP-1768B: reverting a few things GP-1768C: first pass at offset/pid resolution GP-1768C: paired proc/thread logic in place GP-1768C: make only selected items ACTIVE; update only !INACTIVE GP-1768C: activate process/thread on event
This commit is contained in:
@@ -236,4 +236,9 @@ public interface DbgProcess extends DbgMemoryOperations {
|
|||||||
*/
|
*/
|
||||||
CompletableFuture<Void> remove();
|
CompletableFuture<Void> remove();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the address of the associated process structure
|
||||||
|
*/
|
||||||
|
Long getOffset();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-3
@@ -158,9 +158,12 @@ public interface DbgThread
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the effective architecture for the executing thread
|
* Get the effective architecture for the executing thread
|
||||||
*
|
|
||||||
* @return a future that completes when GDB has executed the command
|
|
||||||
*/
|
*/
|
||||||
Machine getExecutingProcessorType();
|
Machine getExecutingProcessorType();
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* Get the address of the associated thread structure
|
||||||
|
*/
|
||||||
|
Long getOffset();
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
+104
@@ -0,0 +1,104 @@
|
|||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package agent.dbgeng.manager.cmd;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import agent.dbgeng.dbgeng.DebugControl;
|
||||||
|
import agent.dbgeng.dbgeng.DebugProcessId;
|
||||||
|
import agent.dbgeng.manager.DbgEvent;
|
||||||
|
import agent.dbgeng.manager.DbgProcess;
|
||||||
|
import agent.dbgeng.manager.evt.AbstractDbgCompletedCommandEvent;
|
||||||
|
import agent.dbgeng.manager.evt.DbgConsoleOutputEvent;
|
||||||
|
import agent.dbgeng.manager.impl.DbgManagerImpl;
|
||||||
|
import agent.dbgeng.manager.impl.DbgProcessImpl;
|
||||||
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
|
public class DbgResolveProcessCommand extends AbstractDbgCommand<DbgProcess> {
|
||||||
|
|
||||||
|
private DbgProcessImpl process;
|
||||||
|
private Long offset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjust the process contents to include both pid and offset
|
||||||
|
* NB: should only be used in kernel-mode against the current process (i.e. id==offset)
|
||||||
|
*
|
||||||
|
* @param manager the manager to execute the command
|
||||||
|
* @param process the desired process
|
||||||
|
*/
|
||||||
|
public DbgResolveProcessCommand(DbgManagerImpl manager, DbgProcess process) {
|
||||||
|
super(manager);
|
||||||
|
this.process = (DbgProcessImpl) process;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(DbgEvent<?> evt, DbgPendingCommand<?> pending) {
|
||||||
|
if (evt instanceof AbstractDbgCompletedCommandEvent && pending.getCommand().equals(this)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (evt instanceof DbgConsoleOutputEvent) {
|
||||||
|
pending.steal(evt);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DbgProcess complete(DbgPendingCommand<?> pending) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (DbgConsoleOutputEvent out : pending.findAllOf(DbgConsoleOutputEvent.class)) {
|
||||||
|
builder.append(out.getOutput());
|
||||||
|
}
|
||||||
|
parse(builder.toString());
|
||||||
|
return process;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parse(String result) {
|
||||||
|
String[] lines = result.split("\n");
|
||||||
|
for (int i = 0; i < lines.length; i++) {
|
||||||
|
String line = lines[i];
|
||||||
|
if (line.contains("PROCESS")) {
|
||||||
|
String[] fields = line.trim().split("\\s+");
|
||||||
|
if (fields.length > 1 && fields[0].equals("PROCESS")) {
|
||||||
|
BigInteger val = new BigInteger(fields[1], 16);
|
||||||
|
offset = val.longValue();
|
||||||
|
process.setOffset(offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (line.contains("Cid:")) {
|
||||||
|
String[] fields = line.trim().split("\\s+");
|
||||||
|
if (fields.length > 3 && fields[2].equals("Cid:")) {
|
||||||
|
Long pid = Long.parseLong(fields[3], 16);
|
||||||
|
process.setPid(pid);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (offset == null) {
|
||||||
|
Msg.error(this, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke() {
|
||||||
|
if (process != null) {
|
||||||
|
DebugProcessId id = process.getId();
|
||||||
|
if (id != null) {
|
||||||
|
DebugControl control = manager.getControl();
|
||||||
|
control.execute("!process "+Long.toHexString(id.id)+" 0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+102
@@ -0,0 +1,102 @@
|
|||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package agent.dbgeng.manager.cmd;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import agent.dbgeng.dbgeng.DebugControl;
|
||||||
|
import agent.dbgeng.dbgeng.DebugThreadId;
|
||||||
|
import agent.dbgeng.manager.DbgEvent;
|
||||||
|
import agent.dbgeng.manager.DbgThread;
|
||||||
|
import agent.dbgeng.manager.evt.AbstractDbgCompletedCommandEvent;
|
||||||
|
import agent.dbgeng.manager.evt.DbgConsoleOutputEvent;
|
||||||
|
import agent.dbgeng.manager.impl.DbgManagerImpl;
|
||||||
|
import agent.dbgeng.manager.impl.DbgThreadImpl;
|
||||||
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
|
public class DbgResolveThreadCommand extends AbstractDbgCommand<DbgThread> {
|
||||||
|
|
||||||
|
private DbgThreadImpl thread;
|
||||||
|
private Long offset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjust the thread contents to include both tid and offset
|
||||||
|
* NB: should only be used in kernel-mode against the current thread (i.e. id==offset)
|
||||||
|
*
|
||||||
|
* @param manager the manager to execute the command
|
||||||
|
* @param thread the desired thread
|
||||||
|
* @param frameId the desired frame level
|
||||||
|
*/
|
||||||
|
public DbgResolveThreadCommand(DbgManagerImpl manager, DbgThread thread) {
|
||||||
|
super(manager);
|
||||||
|
this.thread = (DbgThreadImpl) thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(DbgEvent<?> evt, DbgPendingCommand<?> pending) {
|
||||||
|
if (evt instanceof AbstractDbgCompletedCommandEvent && pending.getCommand().equals(this)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (evt instanceof DbgConsoleOutputEvent) {
|
||||||
|
pending.steal(evt);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DbgThread complete(DbgPendingCommand<?> pending) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (DbgConsoleOutputEvent out : pending.findAllOf(DbgConsoleOutputEvent.class)) {
|
||||||
|
builder.append(out.getOutput());
|
||||||
|
}
|
||||||
|
parse(builder.toString());
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parse(String result) {
|
||||||
|
String[] lines = result.split("\n");
|
||||||
|
for (int i = 0; i < lines.length; i++) {
|
||||||
|
String line = lines[i];
|
||||||
|
if (line.contains("THREAD")) {
|
||||||
|
String[] fields = line.trim().split("\\s+");
|
||||||
|
if (fields.length > 4 && fields[0].equals("THREAD")) {
|
||||||
|
BigInteger val = new BigInteger(fields[1], 16);
|
||||||
|
offset = val.longValue();
|
||||||
|
thread.setOffset(offset);
|
||||||
|
String[] split = fields[3].split("\\.");
|
||||||
|
if (split.length == 2) {
|
||||||
|
//Long pid = Long.parseLong(split[0], 16);
|
||||||
|
Long tid = Long.parseLong(split[1], 16);
|
||||||
|
thread.setTid(tid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (offset == null) {
|
||||||
|
Msg.error(this, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke() {
|
||||||
|
DebugThreadId id = thread.getId();
|
||||||
|
if (id != null) {
|
||||||
|
DebugControl control = manager.getControl();
|
||||||
|
control.execute("!thread "+Long.toHexString(id.id)+" 0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-3
@@ -93,10 +93,9 @@ public class DbgSetActiveProcessCommand extends AbstractDbgCommand<Void> {
|
|||||||
offset = process.getOffset();
|
offset = process.getOffset();
|
||||||
if (offset == null || offset == 0L) {
|
if (offset == null || offset == 0L) {
|
||||||
DebugControl control = manager.getControl();
|
DebugControl control = manager.getControl();
|
||||||
control.execute("!process "+Long.toHexString(process.getPid()));
|
control.execute("!process "+Long.toHexString(process.getPid())+" 0");
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
so.setCurrentProcessId(id);
|
so.setCurrentProcessId(id);
|
||||||
DebugProcessId currentProcessId = so.getCurrentProcessId();
|
DebugProcessId currentProcessId = so.getCurrentProcessId();
|
||||||
if (id.id != currentProcessId.id) {
|
if (id.id != currentProcessId.id) {
|
||||||
|
|||||||
+2
-3
@@ -91,12 +91,11 @@ public class DbgSetActiveThreadCommand extends AbstractDbgCommand<Void> {
|
|||||||
if (id != null) {
|
if (id != null) {
|
||||||
if (!manager.isKernelMode()) {
|
if (!manager.isKernelMode()) {
|
||||||
manager.getSystemObjects().setCurrentThreadId(id);
|
manager.getSystemObjects().setCurrentThreadId(id);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
offset = thread.getOffset();
|
offset = thread.getOffset();
|
||||||
if (offset == null || offset == 0L) {
|
if (offset == null || offset == 0L) {
|
||||||
DebugControl control = manager.getControl();
|
DebugControl control = manager.getControl();
|
||||||
control.execute("!thread -t "+Long.toHexString(thread.getTid()));
|
control.execute("!thread -t "+Long.toHexString(thread.getTid())+" 0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (frameId != null) {
|
if (frameId != null) {
|
||||||
|
|||||||
+45
-74
@@ -103,10 +103,11 @@ import agent.dbgeng.manager.cmd.DbgRemoveProcessCommand;
|
|||||||
import agent.dbgeng.manager.cmd.DbgRemoveSessionCommand;
|
import agent.dbgeng.manager.cmd.DbgRemoveSessionCommand;
|
||||||
import agent.dbgeng.manager.cmd.DbgRequestActivationCommand;
|
import agent.dbgeng.manager.cmd.DbgRequestActivationCommand;
|
||||||
import agent.dbgeng.manager.cmd.DbgRequestFocusCommand;
|
import agent.dbgeng.manager.cmd.DbgRequestFocusCommand;
|
||||||
|
import agent.dbgeng.manager.cmd.DbgResolveProcessCommand;
|
||||||
|
import agent.dbgeng.manager.cmd.DbgResolveThreadCommand;
|
||||||
import agent.dbgeng.manager.cmd.DbgSetActiveProcessCommand;
|
import agent.dbgeng.manager.cmd.DbgSetActiveProcessCommand;
|
||||||
import agent.dbgeng.manager.cmd.DbgSetActiveSessionCommand;
|
import agent.dbgeng.manager.cmd.DbgSetActiveSessionCommand;
|
||||||
import agent.dbgeng.manager.cmd.DbgSetActiveThreadCommand;
|
import agent.dbgeng.manager.cmd.DbgSetActiveThreadCommand;
|
||||||
import agent.dbgeng.manager.cmd.DbgSetCurrentState;
|
|
||||||
import agent.dbgeng.manager.evt.AbstractDbgEvent;
|
import agent.dbgeng.manager.evt.AbstractDbgEvent;
|
||||||
import agent.dbgeng.manager.evt.DbgBreakpointCreatedEvent;
|
import agent.dbgeng.manager.evt.DbgBreakpointCreatedEvent;
|
||||||
import agent.dbgeng.manager.evt.DbgBreakpointDeletedEvent;
|
import agent.dbgeng.manager.evt.DbgBreakpointDeletedEvent;
|
||||||
@@ -251,9 +252,7 @@ public class DbgManagerImpl implements DbgManager {
|
|||||||
synchronized (threads) {
|
synchronized (threads) {
|
||||||
if (threads.containsKey(id)) {
|
if (threads.containsKey(id)) {
|
||||||
DbgThreadImpl existingThread = threads.get(id);
|
DbgThreadImpl existingThread = threads.get(id);
|
||||||
if (existingThread.getTid() == tid) {
|
return existingThread;
|
||||||
return existingThread;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
DbgThreadImpl thread = new DbgThreadImpl(this, process, id, tid);
|
DbgThreadImpl thread = new DbgThreadImpl(this, process, id, tid);
|
||||||
thread.add();
|
thread.add();
|
||||||
@@ -325,24 +324,11 @@ public class DbgManagerImpl implements DbgManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DbgProcessImpl getProcessComputeIfAbsent(String key, boolean fire) {
|
|
||||||
String index = PathUtils.parseIndex(key);
|
|
||||||
Integer pid = Integer.decode(index);
|
|
||||||
DebugProcessId id = getSystemObjects().getProcessIdBySystemId(pid);
|
|
||||||
if (id == null) {
|
|
||||||
id = new DebugProcessId(pid);
|
|
||||||
return getProcessComputeIfAbsent(id, pid, fire);
|
|
||||||
}
|
|
||||||
return getProcessComputeIfAbsent(id, pid, fire);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DbgProcessImpl getProcessComputeIfAbsent(DebugProcessId id, long pid, boolean fire) {
|
public DbgProcessImpl getProcessComputeIfAbsent(DebugProcessId id, long pid, boolean fire) {
|
||||||
synchronized (processes) {
|
synchronized (processes) {
|
||||||
if (processes.containsKey(id)) {
|
if (processes.containsKey(id)) {
|
||||||
DbgProcessImpl existingProc = processes.get(id);
|
DbgProcessImpl existingProc = processes.get(id);
|
||||||
if (existingProc.getPid() == pid) {
|
return existingProc;
|
||||||
return existingProc;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
DbgProcessImpl process = new DbgProcessImpl(this, id, pid);
|
DbgProcessImpl process = new DbgProcessImpl(this, id, pid);
|
||||||
process.add();
|
process.add();
|
||||||
@@ -598,7 +584,7 @@ public class DbgManagerImpl implements DbgManager {
|
|||||||
}
|
}
|
||||||
return pcmd;
|
return pcmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> void addCommand(DbgCommand<? extends T> cmd, DbgPendingCommand<T> pcmd) {
|
private <T> void addCommand(DbgCommand<? extends T> cmd, DbgPendingCommand<T> pcmd) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (!cmd.validInState(state.get())) {
|
if (!cmd.validInState(state.get())) {
|
||||||
@@ -610,42 +596,6 @@ public class DbgManagerImpl implements DbgManager {
|
|||||||
processEvent(new DbgCommandDoneEvent(cmd));
|
processEvent(new DbgCommandDoneEvent(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*@Override
|
|
||||||
public <T> DbgPendingCommand<T> execute1(DbgCommand<? extends T> cmd) {
|
|
||||||
assert cmd != null;
|
|
||||||
checkStarted();
|
|
||||||
DbgPendingCommand<T> pcmd = new DbgPendingCommand<>(cmd);
|
|
||||||
sequence(TypeSpec.VOID).then((seq) -> {
|
|
||||||
Msg.debug(this, "WAITING cmdLock: " + pcmd);
|
|
||||||
cmdLock.acquire(null).handle(seq::next);
|
|
||||||
}, cmdLockHold).then((seq) -> {
|
|
||||||
Msg.debug(this, "ACQUIRED cmdLock: " + pcmd);
|
|
||||||
synchronized (this) {
|
|
||||||
if (curCmd != null) {
|
|
||||||
throw new AssertionError("Cannot execute more than one command at a time");
|
|
||||||
}
|
|
||||||
if (!cmd.validInState(state.get())) {
|
|
||||||
throw new DbgCommandError(
|
|
||||||
"Command " + cmd + " is not valid while " + state.get());
|
|
||||||
}
|
|
||||||
curCmd = pcmd;
|
|
||||||
}
|
|
||||||
cmd.invoke();
|
|
||||||
processEvent(new DbgCommandDoneEvent(cmd.toString()));
|
|
||||||
seq.exit();
|
|
||||||
}).finish().exceptionally((exc) -> {
|
|
||||||
pcmd.completeExceptionally(exc);
|
|
||||||
Msg.debug(this, "ON_EXCEPTION: CURCMD = " + curCmd);
|
|
||||||
curCmd = null;
|
|
||||||
Msg.debug(this, "SET CURCMD = null");
|
|
||||||
Msg.debug(this, "RELEASING cmdLock");
|
|
||||||
cmdLockHold.getAndSet(null).release();
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
return pcmd;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
public DebugStatus processEvent(DbgEvent<?> evt) {
|
public DebugStatus processEvent(DbgEvent<?> evt) {
|
||||||
if (state.get() == DbgState.STARTING) {
|
if (state.get() == DbgState.STARTING) {
|
||||||
state.set(DbgState.STOPPED, Causes.UNCLAIMED);
|
state.set(DbgState.STOPPED, Causes.UNCLAIMED);
|
||||||
@@ -777,7 +727,7 @@ public class DbgManagerImpl implements DbgManager {
|
|||||||
if (eventThread != null) {
|
if (eventThread != null) {
|
||||||
((DbgThreadImpl) eventThread).setInfo(lastEventInformation);
|
((DbgThreadImpl) eventThread).setInfo(lastEventInformation);
|
||||||
}
|
}
|
||||||
return currentThread.getId();
|
return currentThread == null ? new DebugThreadId(-1) : currentThread.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -889,6 +839,11 @@ public class DbgManagerImpl implements DbgManager {
|
|||||||
* @return retval handling/break status
|
* @return retval handling/break status
|
||||||
*/
|
*/
|
||||||
protected DebugStatus processThreadSelected(DbgThreadSelectedEvent evt, Void v) {
|
protected DebugStatus processThreadSelected(DbgThreadSelectedEvent evt, Void v) {
|
||||||
|
if (evt.getState() == DbgState.RUNNING) {
|
||||||
|
currentThread = evt.getThread();
|
||||||
|
currentThread.setState(evt.getState(), evt.getCause(), evt.getReason());
|
||||||
|
return statusMap.get(evt.getClass());
|
||||||
|
}
|
||||||
DebugThreadId eventId = updateState();
|
DebugThreadId eventId = updateState();
|
||||||
|
|
||||||
currentThread = evt.getThread();
|
currentThread = evt.getThread();
|
||||||
@@ -1627,6 +1582,10 @@ public class DbgManagerImpl implements DbgManager {
|
|||||||
return (DbgProcessImpl) (currentProcess != null ? currentProcess : eventProcess);
|
return (DbgProcessImpl) (currentProcess != null ? currentProcess : eventProcess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCurrentProcess(DbgProcessImpl process) {
|
||||||
|
currentProcess = process;
|
||||||
|
}
|
||||||
|
|
||||||
public DbgSessionImpl getCurrentSession() {
|
public DbgSessionImpl getCurrentSession() {
|
||||||
return (DbgSessionImpl) (currentSession != null ? currentSession : eventSession);
|
return (DbgSessionImpl) (currentSession != null ? currentSession : eventSession);
|
||||||
}
|
}
|
||||||
@@ -1650,7 +1609,7 @@ public class DbgManagerImpl implements DbgManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<Void> setActiveThread(DbgThread thread) {
|
public CompletableFuture<Void> setActiveThread(DbgThread thread) {
|
||||||
if (thread == null) {
|
if (thread == null || thread.getTid().equals(currentThread.getTid())) {
|
||||||
return CompletableFuture.completedFuture(null);
|
return CompletableFuture.completedFuture(null);
|
||||||
}
|
}
|
||||||
currentThread = thread;
|
currentThread = thread;
|
||||||
@@ -1659,7 +1618,7 @@ public class DbgManagerImpl implements DbgManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<Void> setActiveProcess(DbgProcess process) {
|
public CompletableFuture<Void> setActiveProcess(DbgProcess process) {
|
||||||
if (process == null) {
|
if (process == null || process.getPid().equals(currentProcess.getPid())) {
|
||||||
return CompletableFuture.completedFuture(null);
|
return CompletableFuture.completedFuture(null);
|
||||||
}
|
}
|
||||||
currentProcess = process;
|
currentProcess = process;
|
||||||
@@ -1799,12 +1758,7 @@ public class DbgManagerImpl implements DbgManager {
|
|||||||
DebugSystemObjects so = getSystemObjects();
|
DebugSystemObjects so = getSystemObjects();
|
||||||
DebugProcessId id = so.getProcessIdByHandle(info.handle);
|
DebugProcessId id = so.getProcessIdByHandle(info.handle);
|
||||||
if (kernelMode) {
|
if (kernelMode) {
|
||||||
// try {
|
// Unnecessary? Are these events transmitted in kernel-mode?
|
||||||
// return (DbgProcessImpl) execute(new DbgSetCurrentState(this)).get().getProcess();
|
|
||||||
// } catch (Exception e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
int pid = so.getCurrentProcessSystemId();
|
int pid = so.getCurrentProcessSystemId();
|
||||||
@@ -1816,12 +1770,7 @@ public class DbgManagerImpl implements DbgManager {
|
|||||||
DebugSystemObjects so = getSystemObjects();
|
DebugSystemObjects so = getSystemObjects();
|
||||||
DebugThreadId id = so.getThreadIdByHandle(info.handle);
|
DebugThreadId id = so.getThreadIdByHandle(info.handle);
|
||||||
if (kernelMode) {
|
if (kernelMode) {
|
||||||
// try {
|
// Unnecessary? Are these events transmitted in kernel-mode?
|
||||||
// return (DbgThreadImpl) execute(new DbgSetCurrentState(this)).get();
|
|
||||||
// } catch (Exception e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
int pid = so.getCurrentThreadSystemId();
|
int pid = so.getCurrentThreadSystemId();
|
||||||
@@ -1833,10 +1782,32 @@ public class DbgManagerImpl implements DbgManager {
|
|||||||
DebugSystemObjects so = getSystemObjects();
|
DebugSystemObjects so = getSystemObjects();
|
||||||
currentSession = eventSession = getSessionComputeIfAbsent(esid, true);
|
currentSession = eventSession = getSessionComputeIfAbsent(esid, true);
|
||||||
if (kernelMode) {
|
if (kernelMode) {
|
||||||
execute(new DbgSetCurrentState(this)).thenAccept(thread -> {
|
long poffset = so.getCurrentProcessDataOffset();
|
||||||
currentThread = eventThread = thread;
|
currentProcess = eventProcess = getProcessComputeIfAbsent(new DebugProcessId(poffset), -1, true);
|
||||||
currentProcess = eventProcess = thread.getProcess();
|
if (currentProcess.getPid() < 0) {
|
||||||
});
|
execute(new DbgResolveProcessCommand(this, currentProcess)).thenAccept(proc -> {
|
||||||
|
currentProcess = eventProcess = proc;
|
||||||
|
// As you now have both pid & offset, update the id==pid version
|
||||||
|
DbgProcessImpl mirror = getProcessComputeIfAbsent(new DebugProcessId(proc.getPid()), -1, false);
|
||||||
|
if (mirror != null) {
|
||||||
|
mirror.setOffset(currentProcess.getOffset());
|
||||||
|
getEventListeners().fire.processSelected(eventProcess, Causes.UNCLAIMED);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
long toffset = so.getCurrentThreadDataOffset();
|
||||||
|
currentThread = eventThread = getThreadComputeIfAbsent(new DebugThreadId(toffset), (DbgProcessImpl) eventProcess, -1, false);
|
||||||
|
if (currentThread.getTid() < 0) {
|
||||||
|
execute(new DbgResolveThreadCommand(this, currentThread)).thenAccept(thread -> {
|
||||||
|
currentThread = eventThread = thread;
|
||||||
|
// As you now have both tid & offset, update the id==tid version
|
||||||
|
DbgThreadImpl mirror = getThreadComputeIfAbsent(new DebugThreadId(thread.getTid()), (DbgProcessImpl) eventProcess, -1, false);
|
||||||
|
if (mirror != null) {
|
||||||
|
mirror.setOffset(currentThread.getOffset());
|
||||||
|
getEventListeners().fire.threadSelected(eventThread, null, Causes.UNCLAIMED);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
currentProcess =
|
currentProcess =
|
||||||
eventProcess = getProcessComputeIfAbsent(epid, so.getCurrentProcessSystemId(), true);
|
eventProcess = getProcessComputeIfAbsent(epid, so.getCurrentProcessSystemId(), true);
|
||||||
|
|||||||
+4
@@ -383,4 +383,8 @@ public class DbgProcessImpl implements DbgProcess {
|
|||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPid(Long pid) {
|
||||||
|
this.pid = pid;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -294,4 +294,8 @@ public class DbgThreadImpl implements DbgThread {
|
|||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setTid(Long tid) {
|
||||||
|
this.tid = tid;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-4
@@ -18,10 +18,22 @@ package agent.dbgeng.model.iface2;
|
|||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import agent.dbgeng.dbgeng.DebugProcessId;
|
import agent.dbgeng.dbgeng.DebugProcessId;
|
||||||
import agent.dbgeng.dbgeng.DebugSystemObjects;
|
import agent.dbgeng.manager.DbgEventsListenerAdapter;
|
||||||
import agent.dbgeng.manager.*;
|
import agent.dbgeng.manager.DbgProcess;
|
||||||
|
import agent.dbgeng.manager.DbgState;
|
||||||
|
import agent.dbgeng.manager.DbgThread;
|
||||||
import agent.dbgeng.manager.impl.DbgManagerImpl;
|
import agent.dbgeng.manager.impl.DbgManagerImpl;
|
||||||
import agent.dbgeng.model.iface1.*;
|
import agent.dbgeng.model.iface1.DbgModelSelectableObject;
|
||||||
|
import agent.dbgeng.model.iface1.DbgModelTargetAccessConditioned;
|
||||||
|
import agent.dbgeng.model.iface1.DbgModelTargetAttachable;
|
||||||
|
import agent.dbgeng.model.iface1.DbgModelTargetAttacher;
|
||||||
|
import agent.dbgeng.model.iface1.DbgModelTargetDeletable;
|
||||||
|
import agent.dbgeng.model.iface1.DbgModelTargetDetachable;
|
||||||
|
import agent.dbgeng.model.iface1.DbgModelTargetExecutionStateful;
|
||||||
|
import agent.dbgeng.model.iface1.DbgModelTargetInterruptible;
|
||||||
|
import agent.dbgeng.model.iface1.DbgModelTargetKillable;
|
||||||
|
import agent.dbgeng.model.iface1.DbgModelTargetResumable;
|
||||||
|
import agent.dbgeng.model.iface1.DbgModelTargetSteppable;
|
||||||
import ghidra.dbg.target.TargetAggregate;
|
import ghidra.dbg.target.TargetAggregate;
|
||||||
import ghidra.dbg.target.TargetProcess;
|
import ghidra.dbg.target.TargetProcess;
|
||||||
import ghidra.dbg.util.PathUtils;
|
import ghidra.dbg.util.PathUtils;
|
||||||
@@ -59,7 +71,10 @@ public interface DbgModelTargetProcess extends //
|
|||||||
public default DbgProcess getProcess(boolean fire) {
|
public default DbgProcess getProcess(boolean fire) {
|
||||||
DbgManagerImpl manager = getManager();
|
DbgManagerImpl manager = getManager();
|
||||||
try {
|
try {
|
||||||
return manager.getProcessComputeIfAbsent(getName(), fire);
|
String index = PathUtils.parseIndex(getName());
|
||||||
|
Long pid = Long.decode(index);
|
||||||
|
DebugProcessId id = new DebugProcessId(pid);
|
||||||
|
return manager.getProcessComputeIfAbsent(id, pid, fire);
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException e) {
|
catch (IllegalArgumentException e) {
|
||||||
return manager.getCurrentProcess();
|
return manager.getCurrentProcess();
|
||||||
|
|||||||
+15
-5
@@ -17,11 +17,18 @@ package agent.dbgeng.model.iface2;
|
|||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import agent.dbgeng.dbgeng.DebugSystemObjects;
|
|
||||||
import agent.dbgeng.dbgeng.DebugThreadId;
|
import agent.dbgeng.dbgeng.DebugThreadId;
|
||||||
import agent.dbgeng.manager.*;
|
import agent.dbgeng.manager.DbgEventsListenerAdapter;
|
||||||
import agent.dbgeng.manager.impl.*;
|
import agent.dbgeng.manager.DbgReason;
|
||||||
import agent.dbgeng.model.iface1.*;
|
import agent.dbgeng.manager.DbgState;
|
||||||
|
import agent.dbgeng.manager.DbgThread;
|
||||||
|
import agent.dbgeng.manager.impl.DbgManagerImpl;
|
||||||
|
import agent.dbgeng.manager.impl.DbgProcessImpl;
|
||||||
|
import agent.dbgeng.manager.impl.DbgThreadImpl;
|
||||||
|
import agent.dbgeng.model.iface1.DbgModelSelectableObject;
|
||||||
|
import agent.dbgeng.model.iface1.DbgModelTargetAccessConditioned;
|
||||||
|
import agent.dbgeng.model.iface1.DbgModelTargetExecutionStateful;
|
||||||
|
import agent.dbgeng.model.iface1.DbgModelTargetSteppable;
|
||||||
import agent.dbgeng.model.impl.DbgModelTargetStackImpl;
|
import agent.dbgeng.model.impl.DbgModelTargetStackImpl;
|
||||||
import ghidra.dbg.target.*;
|
import ghidra.dbg.target.*;
|
||||||
import ghidra.dbg.util.PathUtils;
|
import ghidra.dbg.util.PathUtils;
|
||||||
@@ -45,7 +52,10 @@ public interface DbgModelTargetThread extends //
|
|||||||
try {
|
try {
|
||||||
DbgModelTargetProcess parentProcess = getParentProcess();
|
DbgModelTargetProcess parentProcess = getParentProcess();
|
||||||
DbgProcessImpl process = parentProcess == null ? null : (DbgProcessImpl) parentProcess.getProcess();
|
DbgProcessImpl process = parentProcess == null ? null : (DbgProcessImpl) parentProcess.getProcess();
|
||||||
DbgThreadImpl thread = manager.getThreadComputeIfAbsent(getName(), process, fire);
|
String index = PathUtils.parseIndex(getName());
|
||||||
|
Long tid = Long.decode(index);
|
||||||
|
DebugThreadId id = new DebugThreadId(tid);
|
||||||
|
DbgThreadImpl thread = manager.getThreadComputeIfAbsent(id, process, tid, fire);
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException e) {
|
catch (IllegalArgumentException e) {
|
||||||
|
|||||||
+3
@@ -113,12 +113,15 @@ public interface ModelObject extends UnknownEx {
|
|||||||
void setIndexer(ModelObject indexer);
|
void setIndexer(ModelObject indexer);
|
||||||
|
|
||||||
List<ModelObject> getElements();
|
List<ModelObject> getElements();
|
||||||
|
ModelObject getElement(String key);
|
||||||
|
|
||||||
ModelObject getChild(DataModelManager1 manager, VARIANT v);
|
ModelObject getChild(DataModelManager1 manager, VARIANT v);
|
||||||
|
|
||||||
Map<String, ModelObject> getKeyValueMap();
|
Map<String, ModelObject> getKeyValueMap();
|
||||||
|
ModelObject getKeyValueByEnum(String key);
|
||||||
|
|
||||||
Map<String, ModelObject> getRawValueMap();
|
Map<String, ModelObject> getRawValueMap();
|
||||||
|
ModelObject getRawValueByEnum(String key);
|
||||||
|
|
||||||
Object getValue();
|
Object getValue();
|
||||||
|
|
||||||
|
|||||||
+17
-22
@@ -130,11 +130,8 @@ public class HDMAUtil {
|
|||||||
public ModelObject getTerminalModelObject(List<String> path) {
|
public ModelObject getTerminalModelObject(List<String> path) {
|
||||||
//System.err.println(path);
|
//System.err.println(path);
|
||||||
ModelObject target = getRootNamespace();
|
ModelObject target = getRootNamespace();
|
||||||
boolean found;
|
|
||||||
for (String str : path) {
|
for (String str : path) {
|
||||||
//System.err.println(":" + str);
|
|
||||||
String indexStr = null;
|
String indexStr = null;
|
||||||
found = false;
|
|
||||||
if (str.endsWith(")")) {
|
if (str.endsWith(")")) {
|
||||||
target = evaluatePredicate(target, str);
|
target = evaluatePredicate(target, str);
|
||||||
if (target.getKind().equals(ModelObjectKind.OBJECT_ERROR)) {
|
if (target.getKind().equals(ModelObjectKind.OBJECT_ERROR)) {
|
||||||
@@ -145,30 +142,28 @@ public class HDMAUtil {
|
|||||||
indexStr = str.substring(str.indexOf("[") + 1, str.indexOf("]"));
|
indexStr = str.substring(str.indexOf("[") + 1, str.indexOf("]"));
|
||||||
str = str.substring(0, str.indexOf("["));
|
str = str.substring(0, str.indexOf("["));
|
||||||
}
|
}
|
||||||
Map<String, ModelObject> keyMap = target.getKeyValueMap();
|
if (!str.equals("")) {
|
||||||
if (keyMap.containsKey(str)) {
|
ModelObject keyValue = target.getKeyValueByEnum(str);
|
||||||
target = keyMap.get(str);
|
if (keyValue != null) {
|
||||||
found = true;
|
target = keyValue;
|
||||||
}
|
continue;
|
||||||
else {
|
|
||||||
Map<String, ModelObject> rawMap = target.getRawValueMap();
|
|
||||||
if (rawMap.containsKey(str)) {
|
|
||||||
target = rawMap.get(str);
|
|
||||||
found = true;
|
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
if (indexStr != null) {
|
ModelObject rawValue = target.getRawValueByEnum(str);
|
||||||
List<ModelObject> children = target.getElements();
|
if (rawValue != null) {
|
||||||
for (ModelObject child : children) {
|
target = rawValue;
|
||||||
if (indexStr.equals(child.getSearchKey())) {
|
continue;
|
||||||
target = child;
|
|
||||||
found = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (found == false) {
|
if (indexStr != null) {
|
||||||
return null;
|
ModelObject element = target.getElement(indexStr);
|
||||||
|
if (element != null) {
|
||||||
|
target = element;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|||||||
+93
-7
@@ -723,6 +723,39 @@ public class ModelObjectImpl implements ModelObjectInternal {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelObject getElement(String key) {
|
||||||
|
REFIID ref = new REFIID(IIterableConcept.IID_IITERABLE_CONCEPT);
|
||||||
|
IterableConcept concept = (IterableConcept) this.getConcept(ref);
|
||||||
|
if (concept == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelIterator iterator = concept.getIterator(this);
|
||||||
|
//long dim = concept.getDefaultIndexDimensionality(this);
|
||||||
|
if (iterator != null) {
|
||||||
|
ModelObject next;
|
||||||
|
int i = 0;
|
||||||
|
while ((next = iterator.getNext(1)) != null) {
|
||||||
|
ModelObject index = iterator.getIndexers();
|
||||||
|
if (index != null) {
|
||||||
|
next.setIndexer(index);
|
||||||
|
if (next.getSearchKey().equals(key)) {
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
next.setSearchKey(Integer.toHexString(i));
|
||||||
|
if (Integer.toHexString(i).equals(key)) {
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ModelObject getChild(DataModelManager1 manager, VARIANT v) {
|
public ModelObject getChild(DataModelManager1 manager, VARIANT v) {
|
||||||
REFIID ref = new REFIID(IIndexableConcept.IID_IINDEXABLE_CONCEPT);
|
REFIID ref = new REFIID(IIndexableConcept.IID_IINDEXABLE_CONCEPT);
|
||||||
@@ -820,6 +853,22 @@ public class ModelObjectImpl implements ModelObjectInternal {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized ModelObject getKeyValueByEnum(String key) {
|
||||||
|
String kstr;
|
||||||
|
KeyEnumerator enumerator = this.enumerateKeys();
|
||||||
|
while ((kstr = enumerator.getNext()) != null) {
|
||||||
|
if (kstr.equals(key)) {
|
||||||
|
ModelObject value = this.getKeyValue(kstr);
|
||||||
|
if (value != null) {
|
||||||
|
value.setSearchKey(kstr);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Map<String, ModelObject> getRawValueMap() {
|
public synchronized Map<String, ModelObject> getRawValueMap() {
|
||||||
TreeMap<String, ModelObject> map = new TreeMap<String, ModelObject>();
|
TreeMap<String, ModelObject> map = new TreeMap<String, ModelObject>();
|
||||||
@@ -863,6 +912,43 @@ public class ModelObjectImpl implements ModelObjectInternal {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized ModelObject getRawValueByEnum(String key) {
|
||||||
|
TypeKind typeKind = getTypeKind();
|
||||||
|
if (typeKind == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
SymbolKind kind = null;
|
||||||
|
switch (typeKind) {
|
||||||
|
case TYPE_UDT:
|
||||||
|
kind = SymbolKind.SYMBOL_FIELD;
|
||||||
|
break;
|
||||||
|
case TYPE_POINTER:
|
||||||
|
kind = SymbolKind.SYMBOL_BASE_CLASS;
|
||||||
|
try {
|
||||||
|
ModelObject dereference = this.dereference();
|
||||||
|
return dereference.getRawValueByEnum(key);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
kind = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TYPE_INTRINSIC:
|
||||||
|
case TYPE_ARRAY:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
System.err.println(this.getSearchKey() + ":" + typeKind);
|
||||||
|
break;
|
||||||
|
} String kstr;
|
||||||
|
RawEnumerator enumerator = this.enumerateRawValues(kind.ordinal(), 0);
|
||||||
|
while ((kstr = enumerator.getNext()) != null) {
|
||||||
|
ModelObject value = enumerator.getValue();
|
||||||
|
value.setSearchKey(kstr);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeKind getTypeKind() {
|
public TypeKind getTypeKind() {
|
||||||
ModelObjectKind modelKind = getKind();
|
ModelObjectKind modelKind = getKind();
|
||||||
@@ -909,14 +995,14 @@ public class ModelObjectImpl implements ModelObjectInternal {
|
|||||||
if (key == null) {
|
if (key == null) {
|
||||||
throw new RuntimeException("null key for " + this);
|
throw new RuntimeException("null key for " + this);
|
||||||
}
|
}
|
||||||
Map<String, ModelObject> map = getKeyValueMap();
|
ModelObject keyValue = getKeyValueByEnum("BaseAddress");
|
||||||
if (map.containsKey("BaseAddress")) {
|
if (keyValue != null) {
|
||||||
String valueString = map.get("BaseAddress").getValueString();
|
return keyValue.getValueString();
|
||||||
return valueString;
|
|
||||||
}
|
}
|
||||||
if (map.containsKey("UniqueID") && map.containsKey("Id")) {
|
keyValue = getKeyValueByEnum("Id");
|
||||||
String valueString = map.get("Id").getValueString();
|
ModelObject keyValue2 = getKeyValueByEnum("UniqueID");
|
||||||
return valueString;
|
if (keyValue != null && keyValue2 != null) {
|
||||||
|
return keyValue.getValueString();
|
||||||
}
|
}
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-9
@@ -15,8 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package agent.dbgmodel.model.impl;
|
package agent.dbgmodel.model.impl;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.TreeMap;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -24,18 +30,47 @@ import agent.dbgeng.manager.*;
|
|||||||
import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo;
|
import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo;
|
||||||
import agent.dbgeng.model.AbstractDbgModel;
|
import agent.dbgeng.model.AbstractDbgModel;
|
||||||
import agent.dbgeng.model.iface1.DbgModelSelectableObject;
|
import agent.dbgeng.model.iface1.DbgModelSelectableObject;
|
||||||
import agent.dbgeng.model.iface2.*;
|
import agent.dbgeng.model.iface2.DbgModelTargetBreakpointSpec;
|
||||||
import agent.dbgeng.model.impl.*;
|
import agent.dbgeng.model.iface2.DbgModelTargetDebugContainer;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetEventContainer;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetExceptionContainer;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetMemoryContainer;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetModule;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetObject;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetProcess;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetSession;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetStackFrame;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetTTD;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetThread;
|
||||||
|
import agent.dbgeng.model.impl.DbgModelTargetEventContainerImpl;
|
||||||
|
import agent.dbgeng.model.impl.DbgModelTargetExceptionContainerImpl;
|
||||||
|
import agent.dbgeng.model.impl.DbgModelTargetMemoryContainerImpl;
|
||||||
|
import agent.dbgeng.model.impl.DbgModelTargetProcessImpl;
|
||||||
|
import agent.dbgeng.model.impl.DbgModelTargetThreadImpl;
|
||||||
import agent.dbgmodel.dbgmodel.main.ModelObject;
|
import agent.dbgmodel.dbgmodel.main.ModelObject;
|
||||||
import agent.dbgmodel.jna.dbgmodel.DbgModelNative.ModelObjectKind;
|
import agent.dbgmodel.jna.dbgmodel.DbgModelNative.ModelObjectKind;
|
||||||
import agent.dbgmodel.jna.dbgmodel.DbgModelNative.TypeKind;
|
import agent.dbgmodel.jna.dbgmodel.DbgModelNative.TypeKind;
|
||||||
import agent.dbgmodel.manager.DbgManager2Impl;
|
import agent.dbgmodel.manager.DbgManager2Impl;
|
||||||
import ghidra.async.AsyncUtils;
|
import ghidra.async.AsyncUtils;
|
||||||
import ghidra.dbg.agent.DefaultTargetObject;
|
import ghidra.dbg.agent.DefaultTargetObject;
|
||||||
import ghidra.dbg.target.*;
|
import ghidra.dbg.target.TargetAccessConditioned;
|
||||||
|
import ghidra.dbg.target.TargetAttacher;
|
||||||
|
import ghidra.dbg.target.TargetBreakpointSpec;
|
||||||
import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointKind;
|
import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointKind;
|
||||||
|
import ghidra.dbg.target.TargetBreakpointSpecContainer;
|
||||||
import ghidra.dbg.target.TargetBreakpointSpecContainer.TargetBreakpointKindSet;
|
import ghidra.dbg.target.TargetBreakpointSpecContainer.TargetBreakpointKindSet;
|
||||||
|
import ghidra.dbg.target.TargetEnvironment;
|
||||||
|
import ghidra.dbg.target.TargetExecutionStateful;
|
||||||
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
||||||
|
import ghidra.dbg.target.TargetInterpreter;
|
||||||
|
import ghidra.dbg.target.TargetModule;
|
||||||
|
import ghidra.dbg.target.TargetObject;
|
||||||
|
import ghidra.dbg.target.TargetProcess;
|
||||||
|
import ghidra.dbg.target.TargetRegister;
|
||||||
|
import ghidra.dbg.target.TargetRegisterBank;
|
||||||
|
import ghidra.dbg.target.TargetStackFrame;
|
||||||
|
import ghidra.dbg.target.TargetSteppable;
|
||||||
|
import ghidra.dbg.target.TargetThread;
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
import ghidra.dbg.target.schema.TargetObjectSchema;
|
||||||
import ghidra.dbg.util.PathUtils;
|
import ghidra.dbg.util.PathUtils;
|
||||||
import ghidra.dbg.util.PathUtils.TargetObjectKeyComparator;
|
import ghidra.dbg.util.PathUtils.TargetObjectKeyComparator;
|
||||||
@@ -250,11 +285,6 @@ public class DbgModel2TargetObjectImpl extends DefaultTargetObject<TargetObject,
|
|||||||
if (isValid()) {
|
if (isValid()) {
|
||||||
TargetExecutionStateful stateful = (TargetExecutionStateful) proxy;
|
TargetExecutionStateful stateful = (TargetExecutionStateful) proxy;
|
||||||
TargetExecutionState state = stateful.getExecutionState();
|
TargetExecutionState state = stateful.getExecutionState();
|
||||||
if (getManager().isKernelMode()) {
|
|
||||||
if (state.equals(TargetExecutionState.INACTIVE)) {
|
|
||||||
state = TargetExecutionState.ALIVE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
attrs.put(TargetExecutionStateful.STATE_ATTRIBUTE_NAME, state);
|
attrs.put(TargetExecutionStateful.STATE_ATTRIBUTE_NAME, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+78
-16
@@ -15,24 +15,53 @@
|
|||||||
*/
|
*/
|
||||||
package agent.dbgmodel.model.impl;
|
package agent.dbgmodel.model.impl;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import agent.dbgeng.dbgeng.*;
|
import agent.dbgeng.dbgeng.DebugModuleInfo;
|
||||||
import agent.dbgeng.manager.*;
|
import agent.dbgeng.dbgeng.DebugProcessId;
|
||||||
|
import agent.dbgeng.dbgeng.DebugSessionId;
|
||||||
|
import agent.dbgeng.dbgeng.DebugSystemObjects;
|
||||||
|
import agent.dbgeng.dbgeng.DebugThreadId;
|
||||||
|
import agent.dbgeng.manager.DbgCause;
|
||||||
|
import agent.dbgeng.manager.DbgProcess;
|
||||||
|
import agent.dbgeng.manager.DbgReason;
|
||||||
|
import agent.dbgeng.manager.DbgSession;
|
||||||
|
import agent.dbgeng.manager.DbgStackFrame;
|
||||||
|
import agent.dbgeng.manager.DbgState;
|
||||||
|
import agent.dbgeng.manager.DbgThread;
|
||||||
import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo;
|
import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo;
|
||||||
import agent.dbgeng.manager.reason.*;
|
import agent.dbgeng.manager.reason.DbgEndSteppingRangeReason;
|
||||||
|
import agent.dbgeng.manager.reason.DbgExitNormallyReason;
|
||||||
|
import agent.dbgeng.manager.reason.DbgExitedReason;
|
||||||
|
import agent.dbgeng.manager.reason.DbgSignalReceivedReason;
|
||||||
import agent.dbgeng.model.iface1.DbgModelSelectableObject;
|
import agent.dbgeng.model.iface1.DbgModelSelectableObject;
|
||||||
import agent.dbgeng.model.iface1.DbgModelTargetExecutionStateful;
|
import agent.dbgeng.model.iface1.DbgModelTargetExecutionStateful;
|
||||||
import agent.dbgeng.model.iface2.*;
|
import agent.dbgeng.model.iface2.DbgModelTargetBreakpointSpec;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetConnector;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetModule;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetObject;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetProcess;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetProcessContainer;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetRoot;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetThread;
|
||||||
|
import agent.dbgeng.model.iface2.DbgModelTargetThreadContainer;
|
||||||
import agent.dbgeng.model.impl.DbgModelTargetConnectorContainerImpl;
|
import agent.dbgeng.model.impl.DbgModelTargetConnectorContainerImpl;
|
||||||
import agent.dbgeng.model.impl.DbgModelTargetProcessImpl;
|
import agent.dbgeng.model.impl.DbgModelTargetProcessImpl;
|
||||||
import agent.dbgmodel.dbgmodel.main.ModelObject;
|
import agent.dbgmodel.dbgmodel.main.ModelObject;
|
||||||
import agent.dbgmodel.manager.DbgManager2Impl;
|
import agent.dbgmodel.manager.DbgManager2Impl;
|
||||||
import ghidra.async.AsyncUtils;
|
import ghidra.async.AsyncUtils;
|
||||||
import ghidra.async.TypeSpec;
|
import ghidra.async.TypeSpec;
|
||||||
import ghidra.dbg.target.*;
|
import ghidra.dbg.target.TargetEventScope;
|
||||||
|
import ghidra.dbg.target.TargetExecutionStateful;
|
||||||
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
||||||
|
import ghidra.dbg.target.TargetFocusScope;
|
||||||
|
import ghidra.dbg.target.TargetMethod;
|
||||||
|
import ghidra.dbg.target.TargetObject;
|
||||||
|
import ghidra.dbg.target.TargetThread;
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
import ghidra.dbg.target.schema.TargetObjectSchema;
|
||||||
import ghidra.dbg.util.PathUtils;
|
import ghidra.dbg.util.PathUtils;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
@@ -135,11 +164,18 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
|
|||||||
@Override
|
@Override
|
||||||
public void processSelected(DbgProcess process, DbgCause cause) {
|
public void processSelected(DbgProcess process, DbgCause cause) {
|
||||||
objectSelected(process);
|
objectSelected(process);
|
||||||
|
if (getManager().isKernelMode()) {
|
||||||
|
processActivated(process);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void threadSelected(DbgThread thread, DbgStackFrame frame, DbgCause cause) {
|
public void threadSelected(DbgThread thread, DbgStackFrame frame, DbgCause cause) {
|
||||||
objectSelected(thread);
|
objectSelected(thread);
|
||||||
|
if (getManager().isKernelMode() && thread != null) {
|
||||||
|
processActivated(thread.getProcess());
|
||||||
|
threadActivated(thread);
|
||||||
|
}
|
||||||
if (frame != null) {
|
if (frame != null) {
|
||||||
objectSelected(frame);
|
objectSelected(frame);
|
||||||
}
|
}
|
||||||
@@ -151,16 +187,6 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
|
|||||||
if (obj instanceof DbgModelSelectableObject) {
|
if (obj instanceof DbgModelSelectableObject) {
|
||||||
setFocus((DbgModelSelectableObject) obj);
|
setFocus((DbgModelSelectableObject) obj);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
getModel().fetchModelValue(objPath, true).thenAccept(obj -> {
|
|
||||||
if (obj instanceof DbgModelSelectableObject) {
|
|
||||||
setFocus((DbgModelSelectableObject) obj);
|
|
||||||
}
|
|
||||||
}).exceptionally(ex -> {
|
|
||||||
Msg.error("Could not set focus on selected object: " + PathUtils.toString(objPath), ex);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -190,6 +216,21 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void processActivated(DbgProcess proc) {
|
||||||
|
List<String> objPath = findObject(proc);
|
||||||
|
DbgModelTargetExecutionStateful stateful = (DbgModelTargetExecutionStateful) getModel().getModelObject(objPath);
|
||||||
|
if (stateful == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TargetExecutionState state = stateful.getExecutionState();
|
||||||
|
if (state.equals(TargetExecutionState.INACTIVE)) {
|
||||||
|
stateful.changeAttributes(List.of(), Map.of( //
|
||||||
|
TargetExecutionStateful.STATE_ATTRIBUTE_NAME, TargetExecutionState.ALIVE //
|
||||||
|
), "Selected");
|
||||||
|
stateful.fetchAttributes(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void threadCreated(DbgThread thread, DbgCause cause) {
|
public void threadCreated(DbgThread thread, DbgCause cause) {
|
||||||
getObject(thread).thenAccept(obj -> {
|
getObject(thread).thenAccept(obj -> {
|
||||||
@@ -211,6 +252,21 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void threadActivated(DbgThread thread) {
|
||||||
|
List<String> objPath = findObject(thread);
|
||||||
|
DbgModelTargetExecutionStateful stateful = (DbgModelTargetExecutionStateful) getModel().getModelObject(objPath);
|
||||||
|
if (stateful == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TargetExecutionState state = stateful.getExecutionState();
|
||||||
|
if (state.equals(TargetExecutionState.INACTIVE)) {
|
||||||
|
stateful.changeAttributes(List.of(), Map.of( //
|
||||||
|
TargetExecutionStateful.STATE_ATTRIBUTE_NAME, TargetExecutionState.ALIVE //
|
||||||
|
), "Selected");
|
||||||
|
stateful.fetchAttributes(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void moduleLoaded(DbgProcess proc, DebugModuleInfo info, DbgCause cause) {
|
public void moduleLoaded(DbgProcess proc, DebugModuleInfo info, DbgCause cause) {
|
||||||
getObjectRevisited(proc, List.of("Modules"), info).thenAccept(obj -> {
|
getObjectRevisited(proc, List.of("Modules"), info).thenAccept(obj -> {
|
||||||
@@ -534,6 +590,12 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
|
|||||||
DbgProcess process = thread.getProcess();
|
DbgProcess process = thread.getProcess();
|
||||||
tkey = PathUtils.makeKey("0x" + Long.toHexString(thread.getTid()));
|
tkey = PathUtils.makeKey("0x" + Long.toHexString(thread.getTid()));
|
||||||
pkey = PathUtils.makeKey("0x" + Long.toHexString(process.getPid()));
|
pkey = PathUtils.makeKey("0x" + Long.toHexString(process.getPid()));
|
||||||
|
if (getManager().isKernelMode()) {
|
||||||
|
if (tkey.equals("[0x0]")) {
|
||||||
|
// Weird, but necessary...
|
||||||
|
pkey = "[0x0]";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (obj instanceof DbgStackFrame) {
|
if (obj instanceof DbgStackFrame) {
|
||||||
DbgStackFrame frame = (DbgStackFrame) obj;
|
DbgStackFrame frame = (DbgStackFrame) obj;
|
||||||
|
|||||||
+144
-140
@@ -26,10 +26,13 @@ import java.util.Map;
|
|||||||
|
|
||||||
import agent.dbgeng.manager.DbgCause;
|
import agent.dbgeng.manager.DbgCause;
|
||||||
import agent.dbgeng.manager.DbgEventsListener;
|
import agent.dbgeng.manager.DbgEventsListener;
|
||||||
|
import agent.dbgeng.manager.DbgProcess;
|
||||||
import agent.dbgeng.manager.DbgReason;
|
import agent.dbgeng.manager.DbgReason;
|
||||||
import agent.dbgeng.manager.DbgState;
|
import agent.dbgeng.manager.DbgState;
|
||||||
import agent.dbgeng.manager.DbgStateListener;
|
import agent.dbgeng.manager.DbgStateListener;
|
||||||
|
import agent.dbgeng.manager.DbgThread;
|
||||||
import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo;
|
import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo;
|
||||||
|
import agent.dbgeng.manager.impl.DbgManagerImpl;
|
||||||
import agent.dbgeng.model.iface1.DbgModelTargetAccessConditioned;
|
import agent.dbgeng.model.iface1.DbgModelTargetAccessConditioned;
|
||||||
import agent.dbgeng.model.iface1.DbgModelTargetBptHelper;
|
import agent.dbgeng.model.iface1.DbgModelTargetBptHelper;
|
||||||
import agent.dbgeng.model.iface1.DbgModelTargetExecutionStateful;
|
import agent.dbgeng.model.iface1.DbgModelTargetExecutionStateful;
|
||||||
@@ -105,92 +108,87 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static Class<? extends DbgModelTargetObject> lookupWrapperType(String type,
|
protected static Class<? extends DbgModelTargetObject> lookupWrapperType(String type, String parentName) {
|
||||||
String parentName) {
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "Available":
|
case "Available":
|
||||||
return DbgModelTargetAvailableContainer.class;
|
return DbgModelTargetAvailableContainer.class;
|
||||||
case "Sessions":
|
case "Sessions":
|
||||||
return DbgModelTargetSessionContainer.class;
|
return DbgModelTargetSessionContainer.class;
|
||||||
case "Processes":
|
case "Processes":
|
||||||
return DbgModelTargetProcessContainer.class;
|
return DbgModelTargetProcessContainer.class;
|
||||||
case "Threads":
|
case "Threads":
|
||||||
return DbgModelTargetThreadContainer.class;
|
return DbgModelTargetThreadContainer.class;
|
||||||
case "Modules":
|
case "Modules":
|
||||||
return DbgModelTargetModuleContainer.class;
|
return DbgModelTargetModuleContainer.class;
|
||||||
case "Frames":
|
case "Frames":
|
||||||
return DbgModelTargetStack.class;
|
return DbgModelTargetStack.class;
|
||||||
case "Registers":
|
case "Registers":
|
||||||
return DbgModelTargetRegisterContainer.class;
|
return DbgModelTargetRegisterContainer.class;
|
||||||
case "Attributes":
|
case "Attributes":
|
||||||
return DbgModelTargetSessionAttributes.class;
|
return DbgModelTargetSessionAttributes.class;
|
||||||
case "Breakpoints":
|
case "Breakpoints":
|
||||||
return DbgModelTargetBreakpointContainer.class;
|
return DbgModelTargetBreakpointContainer.class;
|
||||||
case "cursession":
|
case "cursession":
|
||||||
return DbgModelTargetSession.class;
|
return DbgModelTargetSession.class;
|
||||||
case "curprocess":
|
case "curprocess":
|
||||||
return DbgModelTargetProcess.class;
|
return DbgModelTargetProcess.class;
|
||||||
case "curthread":
|
case "curthread":
|
||||||
return DbgModelTargetThread.class;
|
return DbgModelTargetThread.class;
|
||||||
case "curframe":
|
case "curframe":
|
||||||
return DbgModelTargetStackFrame.class;
|
return DbgModelTargetStackFrame.class;
|
||||||
case "User":
|
case "User":
|
||||||
return DbgModelTargetRegisterBank.class;
|
return DbgModelTargetRegisterBank.class;
|
||||||
case "TTD":
|
case "TTD":
|
||||||
return DbgModelTargetTTD.class;
|
return DbgModelTargetTTD.class;
|
||||||
case "Debug":
|
case "Debug":
|
||||||
return DbgModelTargetDebugContainer.class;
|
return DbgModelTargetDebugContainer.class;
|
||||||
}
|
}
|
||||||
if (parentName != null) {
|
if (parentName != null) {
|
||||||
switch (parentName) {
|
switch (parentName) {
|
||||||
case "Available":
|
case "Available":
|
||||||
return DbgModelTargetAvailable.class;
|
return DbgModelTargetAvailable.class;
|
||||||
case "Sessions":
|
case "Sessions":
|
||||||
return DbgModelTargetSession.class;
|
return DbgModelTargetSession.class;
|
||||||
case "Processes":
|
case "Processes":
|
||||||
return DbgModelTargetProcess.class;
|
return DbgModelTargetProcess.class;
|
||||||
case "Threads":
|
case "Threads":
|
||||||
return DbgModelTargetThread.class;
|
return DbgModelTargetThread.class;
|
||||||
case "Modules":
|
case "Modules":
|
||||||
return DbgModelTargetModule.class;
|
return DbgModelTargetModule.class;
|
||||||
case "Frames":
|
case "Frames":
|
||||||
return DbgModelTargetStackFrame.class;
|
return DbgModelTargetStackFrame.class;
|
||||||
case "Breakpoints":
|
case "Breakpoints":
|
||||||
return DbgModelTargetBreakpointSpec.class;
|
return DbgModelTargetBreakpointSpec.class;
|
||||||
//case "Registers":
|
// case "Registers":
|
||||||
// return DbgModelTargetRegisterBank.class;
|
// return DbgModelTargetRegisterBank.class;
|
||||||
case "FloatingPoint":
|
case "FloatingPoint":
|
||||||
case "Kernel":
|
case "Kernel":
|
||||||
case "SIMD":
|
case "SIMD":
|
||||||
case "VFP":
|
case "VFP":
|
||||||
case "User":
|
case "User":
|
||||||
return DbgModelTargetRegister.class;
|
return DbgModelTargetRegister.class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DbgModelTargetObject makeProxy(DbgModel2Impl model, DbgModelTargetObject parent,
|
public static DbgModelTargetObject makeProxy(DbgModel2Impl model, DbgModelTargetObject parent, String key,
|
||||||
String key, ModelObject object) {
|
ModelObject object) {
|
||||||
List<Class<? extends TargetObject>> mixins = new ArrayList<>();
|
List<Class<? extends TargetObject>> mixins = new ArrayList<>();
|
||||||
String lkey = key;
|
String lkey = key;
|
||||||
String pname = parent.getName();
|
String pname = parent.getName();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (object.getKind().equals(ModelObjectKind.OBJECT_METHOD) || lkey.contains(")")) {
|
* if (object.getKind().equals(ModelObjectKind.OBJECT_METHOD) ||
|
||||||
mixins.add(DbgModelTargetMethod.class);
|
* lkey.contains(")")) { mixins.add(DbgModelTargetMethod.class); // NB: We're
|
||||||
// NB: We're passing the parent's mixin model to the method on the assumption
|
* passing the parent's mixin model to the method on the assumption // the init
|
||||||
// the init methods will need to know that the method's children have various
|
* methods will need to know that the method's children have various //
|
||||||
// properties.
|
* properties. lkey = pname; pname = ""; }
|
||||||
lkey = pname;
|
*/
|
||||||
pname = "";
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (object.getKind().equals(ModelObjectKind.OBJECT_METHOD)) {
|
if (object.getKind().equals(ModelObjectKind.OBJECT_METHOD)) {
|
||||||
mixins.add(DbgModelTargetMethod.class);
|
mixins.add(DbgModelTargetMethod.class);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
Class<? extends DbgModelTargetObject> mixin = lookupWrapperType(lkey, pname);
|
Class<? extends DbgModelTargetObject> mixin = lookupWrapperType(lkey, pname);
|
||||||
if (mixin != null) {
|
if (mixin != null) {
|
||||||
mixins.add(mixin);
|
mixins.add(mixin);
|
||||||
@@ -201,30 +199,32 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
|
|||||||
|
|
||||||
protected static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
|
protected static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
|
||||||
|
|
||||||
// NOTE: The Cleanable stuff is the replacement for overriding Object.finalize(), which
|
// NOTE: The Cleanable stuff is the replacement for overriding
|
||||||
|
// Object.finalize(), which
|
||||||
// is now deprecated.
|
// is now deprecated.
|
||||||
protected final ProxyState state;
|
protected final ProxyState state;
|
||||||
protected final Cleanable cleanable;
|
protected final Cleanable cleanable;
|
||||||
|
|
||||||
private boolean breakpointEnabled;
|
private boolean breakpointEnabled;
|
||||||
private final ListenerSet<TargetBreakpointAction> breakpointActions =
|
private final ListenerSet<TargetBreakpointAction> breakpointActions = new ListenerSet<>(
|
||||||
new ListenerSet<>(TargetBreakpointAction.class) {
|
TargetBreakpointAction.class) {
|
||||||
// Use strong references on actions
|
// Use strong references on actions
|
||||||
protected Map<TargetBreakpointAction, TargetBreakpointAction> createMap() {
|
protected Map<TargetBreakpointAction, TargetBreakpointAction> createMap() {
|
||||||
return Collections.synchronizedMap(new LinkedHashMap<>());
|
return Collections.synchronizedMap(new LinkedHashMap<>());
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// Extending DefaultTargetObject may spare you from listeners, elements, and attributes
|
// Extending DefaultTargetObject may spare you from listeners, elements, and
|
||||||
//protected final ListenerSet<TargetObjectListener> listeners =
|
// attributes
|
||||||
// new ListenerSet<>(TargetObjectListener.class);
|
// protected final ListenerSet<TargetObjectListener> listeners =
|
||||||
|
// new ListenerSet<>(TargetObjectListener.class);
|
||||||
|
|
||||||
// any other fields you need to support your impl
|
// any other fields you need to support your impl
|
||||||
|
|
||||||
public DelegateDbgModel2TargetObject(DbgModel2Impl model, DbgModelTargetObject parent,
|
public DelegateDbgModel2TargetObject(DbgModel2Impl model, DbgModelTargetObject parent, String key,
|
||||||
String key, ModelObject modelObject, List<Class<? extends TargetObject>> mixins) {
|
ModelObject modelObject, List<Class<? extends TargetObject>> mixins) {
|
||||||
super(model, mixins, model, parent.getProxy(), key, getHintForObject(modelObject));
|
super(model, mixins, model, parent.getProxy(), key, getHintForObject(modelObject));
|
||||||
//System.err.println(this);
|
// System.err.println(this);
|
||||||
this.state = new ProxyState(model, modelObject);
|
this.state = new ProxyState(model, modelObject);
|
||||||
this.cleanable = CLEANER.register(this, state);
|
this.cleanable = CLEANER.register(this, state);
|
||||||
|
|
||||||
@@ -244,8 +244,8 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
|
|||||||
if (mixin != null) {
|
if (mixin != null) {
|
||||||
mixins.add(mixin);
|
mixins.add(mixin);
|
||||||
}
|
}
|
||||||
DelegateDbgModel2TargetObject delegate =
|
DelegateDbgModel2TargetObject delegate = new DelegateDbgModel2TargetObject(getModel(), p, key, modelObject,
|
||||||
new DelegateDbgModel2TargetObject(getModel(), p, key, modelObject, mixins);
|
mixins);
|
||||||
return delegate;
|
return delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,43 +272,45 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
|
|||||||
protected void checkExited(DbgState state, DbgCause cause) {
|
protected void checkExited(DbgState state, DbgCause cause) {
|
||||||
TargetExecutionState exec = TargetExecutionState.INACTIVE;
|
TargetExecutionState exec = TargetExecutionState.INACTIVE;
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case NOT_STARTED: {
|
case NOT_STARTED: {
|
||||||
exec = TargetExecutionState.INACTIVE;
|
exec = TargetExecutionState.INACTIVE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case STARTING: {
|
case STARTING: {
|
||||||
exec = TargetExecutionState.ALIVE;
|
exec = TargetExecutionState.ALIVE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case RUNNING: {
|
case RUNNING: {
|
||||||
exec = TargetExecutionState.RUNNING;
|
exec = TargetExecutionState.RUNNING;
|
||||||
resetModified();
|
resetModified();
|
||||||
onRunning();
|
onRunning();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case STOPPED: {
|
case STOPPED: {
|
||||||
exec = TargetExecutionState.STOPPED;
|
exec = TargetExecutionState.STOPPED;
|
||||||
onStopped();
|
onStopped();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EXIT: {
|
case EXIT: {
|
||||||
exec = TargetExecutionState.TERMINATED;
|
exec = TargetExecutionState.TERMINATED;
|
||||||
onExit();
|
onExit();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SESSION_EXIT: {
|
case SESSION_EXIT: {
|
||||||
getModel().close();
|
getModel().close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (proxy instanceof TargetExecutionStateful) {
|
if (proxy instanceof TargetExecutionStateful) {
|
||||||
if (proxy instanceof DbgModelTargetSession) {
|
if (proxy instanceof DbgModelTargetSession) {
|
||||||
if (state != DbgState.EXIT) {
|
if (state != DbgState.EXIT) {
|
||||||
setExecutionState(exec, "Refreshed");
|
setExecutionState(exec, "Refreshed");
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
TargetExecutionState previous = this.getExecutionState();
|
||||||
setExecutionState(exec, "Refreshed");
|
if (!previous.equals(TargetExecutionState.INACTIVE)) {
|
||||||
|
setExecutionState(exec, "Refreshed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -321,7 +323,7 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
|
|||||||
proxy instanceof DbgModelTargetStackFrame || //
|
proxy instanceof DbgModelTargetStackFrame || //
|
||||||
proxy instanceof DbgModelTargetStack || //
|
proxy instanceof DbgModelTargetStack || //
|
||||||
proxy instanceof DbgModelTargetTTD) {
|
proxy instanceof DbgModelTargetTTD) {
|
||||||
//listeners.fire.invalidateCacheRequested(proxy);
|
// listeners.fire.invalidateCacheRequested(proxy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -330,30 +332,37 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
|
|||||||
if (PathUtils.isLink(parent.getPath(), proxy.getName(), proxy.getPath())) {
|
if (PathUtils.isLink(parent.getPath(), proxy.getName(), proxy.getPath())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
DbgManagerImpl manager = getModel().getManager();
|
||||||
|
boolean kernelMode = manager.isKernelMode();
|
||||||
if (proxy instanceof DbgModelTargetSession) {
|
if (proxy instanceof DbgModelTargetSession) {
|
||||||
DbgModelTargetSession targetSession = (DbgModelTargetSession) proxy;
|
DbgModelTargetSession targetSession = (DbgModelTargetSession) proxy;
|
||||||
targetSession.getSession(false);
|
targetSession.getSession(false);
|
||||||
}
|
}
|
||||||
if (proxy instanceof DbgModelTargetProcess) {
|
if (proxy instanceof DbgModelTargetProcess) {
|
||||||
DbgModelTargetProcess targetProcess = (DbgModelTargetProcess) proxy;
|
DbgModelTargetProcess targetProcess = (DbgModelTargetProcess) proxy;
|
||||||
targetProcess.getProcess(false);
|
DbgProcess process = targetProcess.getProcess(false);
|
||||||
|
if (kernelMode) {
|
||||||
|
Long offset = process.getOffset();
|
||||||
|
if (offset == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (proxy instanceof DbgModelTargetThread) {
|
if (proxy instanceof DbgModelTargetThread) {
|
||||||
DbgModelTargetThread targetThread = (DbgModelTargetThread) proxy;
|
DbgModelTargetThread targetThread = (DbgModelTargetThread) proxy;
|
||||||
targetThread.getThread(false);
|
DbgThread thread = targetThread.getThread(false);
|
||||||
}
|
if (kernelMode) {
|
||||||
|
Long offset = thread.getOffset();
|
||||||
boolean kernelMode = getModel().getManager().isKernelMode();
|
if (offset == null) {
|
||||||
if (kernelMode) {
|
return;
|
||||||
if (proxy instanceof DbgModelTargetProcess || //
|
}
|
||||||
proxy instanceof DbgModelTargetThread) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getModel().isSuppressDescent()) {
|
if (getModel().isSuppressDescent()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proxy instanceof DbgModelTargetSession || //
|
if (proxy instanceof DbgModelTargetSession || //
|
||||||
proxy instanceof DbgModelTargetProcess || //
|
proxy instanceof DbgModelTargetProcess || //
|
||||||
proxy instanceof DbgModelTargetThread) {
|
proxy instanceof DbgModelTargetThread) {
|
||||||
@@ -362,8 +371,7 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
|
|||||||
}
|
}
|
||||||
if (proxy instanceof DbgModelTargetRegisterContainer || //
|
if (proxy instanceof DbgModelTargetRegisterContainer || //
|
||||||
proxy instanceof DbgModelTargetRegisterBank || //
|
proxy instanceof DbgModelTargetRegisterBank || //
|
||||||
proxy.getName().equals("Stack") ||
|
proxy.getName().equals("Stack") || proxy.getName().equals("Debug")) {
|
||||||
proxy.getName().equals("Debug")) {
|
|
||||||
requestAttributes(false);
|
requestAttributes(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -405,7 +413,7 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
|
|||||||
}
|
}
|
||||||
if (proxy instanceof TargetAccessConditioned) {
|
if (proxy instanceof TargetAccessConditioned) {
|
||||||
changeAttributes(List.of(), List.of(), Map.of( //
|
changeAttributes(List.of(), List.of(), Map.of( //
|
||||||
TargetAccessConditioned.ACCESSIBLE_ATTRIBUTE_NAME, accessible //
|
TargetAccessConditioned.ACCESSIBLE_ATTRIBUTE_NAME, accessible //
|
||||||
), "Accessibility changed");
|
), "Accessibility changed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -455,21 +463,18 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
|
|||||||
}
|
}
|
||||||
if (proxy instanceof TargetThread) {
|
if (proxy instanceof TargetThread) {
|
||||||
List<DelegateDbgModel2TargetObject> delegates = new ArrayList<>();
|
List<DelegateDbgModel2TargetObject> delegates = new ArrayList<>();
|
||||||
TargetObject stack =
|
TargetObject stack = (TargetObject) getCachedAttribute("Stack");
|
||||||
(TargetObject) getCachedAttribute("Stack");
|
|
||||||
if (stack != null) {
|
if (stack != null) {
|
||||||
DbgModelTargetStack frames =
|
DbgModelTargetStack frames = (DbgModelTargetStack) stack.getCachedAttribute("Frames");
|
||||||
(DbgModelTargetStack) stack.getCachedAttribute("Frames");
|
|
||||||
delegates.add((DelegateDbgModel2TargetObject) frames.getDelegate());
|
delegates.add((DelegateDbgModel2TargetObject) frames.getDelegate());
|
||||||
}
|
}
|
||||||
DbgModelTargetRegisterContainer container =
|
DbgModelTargetRegisterContainer container = (DbgModelTargetRegisterContainer) getCachedAttribute(
|
||||||
(DbgModelTargetRegisterContainer) getCachedAttribute("Registers");
|
"Registers");
|
||||||
if (container == null) {
|
if (container == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
delegates.add((DelegateDbgModel2TargetObject) container.getDelegate());
|
delegates.add((DelegateDbgModel2TargetObject) container.getDelegate());
|
||||||
DbgModelTargetRegisterBank bank =
|
DbgModelTargetRegisterBank bank = (DbgModelTargetRegisterBank) container.getCachedAttribute("User");
|
||||||
(DbgModelTargetRegisterBank) container.getCachedAttribute("User");
|
|
||||||
if (bank == null) {
|
if (bank == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -486,7 +491,7 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
|
|||||||
}
|
}
|
||||||
if (proxy instanceof TargetRegisterBank) {
|
if (proxy instanceof TargetRegisterBank) {
|
||||||
TargetRegisterBank bank = (TargetRegisterBank) proxy;
|
TargetRegisterBank bank = (TargetRegisterBank) proxy;
|
||||||
//requestElements(false);
|
// requestElements(false);
|
||||||
requestAttributes(false).thenAccept(__ -> {
|
requestAttributes(false).thenAccept(__ -> {
|
||||||
bank.readRegistersNamed(getCachedAttributes().keySet());
|
bank.readRegistersNamed(getCachedAttributes().keySet());
|
||||||
});
|
});
|
||||||
@@ -497,8 +502,7 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp
|
|||||||
for (TargetObject obj : getCachedElements().values()) {
|
for (TargetObject obj : getCachedElements().values()) {
|
||||||
if (obj instanceof TargetStackFrame) {
|
if (obj instanceof TargetStackFrame) {
|
||||||
DbgModelTargetObject frame = (DbgModelTargetObject) obj;
|
DbgModelTargetObject frame = (DbgModelTargetObject) obj;
|
||||||
DelegateDbgModel2TargetObject delegate =
|
DelegateDbgModel2TargetObject delegate = (DelegateDbgModel2TargetObject) frame.getDelegate();
|
||||||
(DelegateDbgModel2TargetObject) frame.getDelegate();
|
|
||||||
delegate.threadStateChangedSpecific(state, reason);
|
delegate.threadStateChangedSpecific(state, reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public interface TargetThread extends TargetObject {
|
|||||||
String TID_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "tid";
|
String TID_ATTRIBUTE_NAME = PREFIX_INVISIBLE + "tid";
|
||||||
|
|
||||||
@TargetAttributeType(name = TID_ATTRIBUTE_NAME, hidden = true)
|
@TargetAttributeType(name = TID_ATTRIBUTE_NAME, hidden = true)
|
||||||
public default Integer getTid() {
|
public default Long getTid() {
|
||||||
return getTypedAttributeNowByName(TID_ATTRIBUTE_NAME, Integer.class, null);
|
return getTypedAttributeNowByName(TID_ATTRIBUTE_NAME, Long.class, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user