GP-3142: fix for read registers

GP-3142: adding Populate to schema
GP-3142: adding session id to the records
GP-3142: post-review id->record
GP-3142: post-review id->record
GP-3142: post-review adds to interface
GP-3142: post-review try-finally (missed two)
GP-3142: post-review try-finally (missed one)
GP-3142: post-review try-finally; clearer reset logic
GP-3142: post-review better use of TargetMethod.Export
GP-3142: minor fixes
GP-3142: first pass at dbgeng kernel mods
GP-3142: temp holdGP-3142: mods to differentiate system and engine idsGP-3142: fixes for bad system/engine differentationGP-3142: fixes for bad pid/tid <0 testGP-3142: fixes for selection logicGP-3142: attempting to mininize work done, esp. by expensive callsGP-3142: fix for stack framesGP-3142: minor bug fix for sys threadsGP-3142: better register/stack reads for non-system threadsGP-3142: warningsGP-3142: post-squash and rebaseGP-3142: missed a few RefreshBehavior candidatesGP-3142: miscellaneous fixesGP-3142: minimize workloadGP-3142: display fixes; refresh==true for resolved process/threadGP-3142: added re-populate methodsGP-3142: better kernel/user code re-useGP-3142: re-fix for fact that thread 0 belongs to process 0
This commit is contained in:
d-millar 2023-03-21 10:54:40 -04:00
parent 18bf2fbe30
commit 9690254616
56 changed files with 1469 additions and 494 deletions

View File

@ -27,8 +27,8 @@ public class DebugEventInformation {
public DebugEventInformation(int type, int pid, int tid) {
this.type = type;
this.pid = new DebugProcessId(pid);
this.tid = new DebugThreadId(tid);
this.pid = new DebugProcessRecord(pid);
this.tid = new DebugThreadRecord(tid);
}
public int getType() {

View File

@ -25,37 +25,14 @@ package agent.dbgeng.dbgeng;
* with other integral values. In particular, this prevents confusion of engine PIDs with system
* PIDs.
*/
public class DebugProcessId implements Comparable<DebugProcessId> {
public final long id;
public DebugProcessId(long id) {
this.id = id;
}
public interface DebugProcessId extends Comparable<DebugProcessId> {
public String id();
public long value();
public boolean isSystem();
@Override
public int hashCode() {
return Long.hashCode(id);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof DebugProcessId)) {
return false;
}
DebugProcessId that = (DebugProcessId) obj;
if (this.id != that.id) {
return false;
}
return true;
}
@Override
public int compareTo(DebugProcessId that) {
return Long.compare(this.id, that.id);
}
@Override
public String toString() {
return "<dbgeng.dll Engine PID " + id + ">";
public default int compareTo(DebugProcessId that) {
return this.id().compareTo(that.id());
}
}

View File

@ -0,0 +1,34 @@
/* ###
* 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.dbgeng;
public record DebugProcessRecord(long value) implements DebugProcessId {
@Override
public boolean isSystem() {
return false;
}
@Override
public String id() {
return Long.toHexString(value);
}
@Override
public String toString() {
return "<dbgeng.dll Engine PID " + Long.toHexString(value) + ">";
}
}

View File

@ -25,37 +25,14 @@ package agent.dbgeng.dbgeng;
* with other integral values. In particular, this prevents confusion of engine PIDs with system
* PIDs.
*/
public class DebugSessionId implements Comparable<DebugSessionId> {
public final int id;
public DebugSessionId(int id) {
this.id = id;
}
public interface DebugSessionId extends Comparable<DebugSessionId> {
public String id();
public long value();
public boolean isSystem();
@Override
public int hashCode() {
return Integer.hashCode(id);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof DebugSessionId)) {
return false;
}
DebugSessionId that = (DebugSessionId) obj;
if (this.id != that.id) {
return false;
}
return true;
}
@Override
public int compareTo(DebugSessionId that) {
return Integer.compare(this.id, that.id);
}
@Override
public String toString() {
return "<dbgeng.dll Engine SYSID " + id + ">";
public default int compareTo(DebugSessionId that) {
return this.id().compareTo(that.id());
}
}

View File

@ -0,0 +1,34 @@
/* ###
* 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.dbgeng;
public record DebugSessionRecord(long value) implements DebugSessionId {
@Override
public boolean isSystem() {
return false;
}
@Override
public String id() {
return Long.toHexString(value);
}
@Override
public String toString() {
return "<dbgeng.dll Engine SYSID " + Long.toHexString(value) + ">";
}
}

View File

@ -0,0 +1,34 @@
/* ###
* 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.dbgeng;
public record DebugSystemProcessRecord(long value) implements DebugProcessId {
@Override
public boolean isSystem() {
return true;
}
@Override
public String id() {
return "SYS"+Long.toHexString(value);
}
@Override
public String toString() {
return "<dbgeng.dll System PID " + Long.toHexString(value) + ">";
}
}

View File

@ -0,0 +1,34 @@
/* ###
* 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.dbgeng;
public record DebugSystemSessionRecord(long value) implements DebugSessionId {
@Override
public boolean isSystem() {
return true;
}
@Override
public String id() {
return "SYS"+Long.toHexString(value);
}
@Override
public String toString() {
return "<dbgeng.dll System SYSID " + Long.toHexString(value) + ">";
}
}

View File

@ -0,0 +1,34 @@
/* ###
* 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.dbgeng;
public record DebugSystemThreadRecord(long value) implements DebugThreadId {
@Override
public boolean isSystem() {
return true;
}
@Override
public String id() {
return "PCR"+Long.toHexString(value);
}
@Override
public String toString() {
return "<dbgeng.dll System TID " + Long.toHexString(value) + ">";
}
}

View File

@ -25,37 +25,15 @@ package agent.dbgeng.dbgeng;
* with other integral values. In particular, this prevents confusion of engine TIDs with system
* TIDs.
*/
public class DebugThreadId implements Comparable<DebugThreadId> {
public final long id;
public DebugThreadId(long id) {
this.id = id;
}
public interface DebugThreadId extends Comparable<DebugThreadId> {
public String id();
public long value();
public boolean isSystem();
@Override
public int hashCode() {
return Long.hashCode(id);
public default int compareTo(DebugThreadId that) {
return this.id().compareTo(that.id());
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof DebugThreadId)) {
return false;
}
DebugThreadId that = (DebugThreadId) obj;
if (this.id != that.id) {
return false;
}
return true;
}
@Override
public int compareTo(DebugThreadId that) {
return Long.compare(this.id, that.id);
}
@Override
public String toString() {
return "<dbgeng.dll Engine TID " + id + ">";
}
}

View File

@ -0,0 +1,34 @@
/* ###
* 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.dbgeng;
public record DebugThreadRecord(long value) implements DebugThreadId {
@Override
public boolean isSystem() {
return false;
}
@Override
public String id() {
return Long.toHexString(value);
}
@Override
public String toString() {
return "<dbgeng.dll Engine TID " + Long.toHexString(value) + ">";
}
}

View File

@ -38,7 +38,7 @@ public class DebugAdvancedImpl2 extends DebugAdvancedImpl1 {
public DebugThreadBasicInformation getThreadBasicInformation(DebugThreadId tid) {
ULONG ulWhich = new ULONG(WhichSystemObjectInformation.THREAD_BASIC_INFORMATION.ordinal());
ULONGLONG ullUnused = new ULONGLONG(0);
ULONG ulThreadId = new ULONG(tid.id);
ULONG ulThreadId = new ULONG(tid.value());
DEBUG_THREAD_BASIC_INFORMATION sInfo = new DEBUG_THREAD_BASIC_INFORMATION();
ULONG ulBufferSize = new ULONG(sInfo.size());
COMUtils.checkRC(jnaAdvanced.GetSystemObjectInformation(ulWhich, ullUnused, ulThreadId,

View File

@ -15,14 +15,25 @@
*/
package agent.dbgeng.impl.dbgeng.sysobj;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.sun.jna.platform.win32.WinDef.*;
import com.sun.jna.platform.win32.WinDef.ULONG;
import com.sun.jna.platform.win32.WinDef.ULONGByReference;
import com.sun.jna.platform.win32.WinDef.ULONGLONG;
import com.sun.jna.platform.win32.WinDef.ULONGLONGByReference;
import com.sun.jna.platform.win32.WinNT.HRESULT;
import com.sun.jna.platform.win32.COM.COMUtils;
import agent.dbgeng.dbgeng.*;
import agent.dbgeng.dbgeng.COMUtilsExtra;
import agent.dbgeng.dbgeng.DbgEng;
import agent.dbgeng.dbgeng.DbgEng.OpaqueCleanable;
import agent.dbgeng.dbgeng.DebugProcessId;
import agent.dbgeng.dbgeng.DebugProcessRecord;
import agent.dbgeng.dbgeng.DebugSessionId;
import agent.dbgeng.dbgeng.DebugThreadId;
import agent.dbgeng.dbgeng.DebugThreadRecord;
import agent.dbgeng.jna.dbgeng.sysobj.IDebugSystemObjects;
public class DebugSystemObjectsImpl1 implements DebugSystemObjectsInternal {
@ -40,10 +51,10 @@ public class DebugSystemObjectsImpl1 implements DebugSystemObjectsInternal {
ULONGByReference pulId = new ULONGByReference();
HRESULT hr = jnaSysobj.GetEventThread(pulId);
if (hr.equals(COMUtilsExtra.E_UNEXPECTED)) {
return new DebugThreadId(-1);
return new DebugThreadRecord(-1);
}
COMUtils.checkRC(hr);
return new DebugThreadId(pulId.getValue().intValue());
return new DebugThreadRecord(pulId.getValue().intValue());
}
@Override
@ -51,10 +62,10 @@ public class DebugSystemObjectsImpl1 implements DebugSystemObjectsInternal {
ULONGByReference pulId = new ULONGByReference();
HRESULT hr = jnaSysobj.GetEventProcess(pulId);
if (hr.equals(COMUtilsExtra.E_UNEXPECTED)) {
return new DebugProcessId(-1);
return new DebugProcessRecord(-1);
}
COMUtils.checkRC(hr);
return new DebugProcessId(pulId.getValue().intValue());
return new DebugProcessRecord(pulId.getValue().intValue());
}
@Override
@ -62,15 +73,15 @@ public class DebugSystemObjectsImpl1 implements DebugSystemObjectsInternal {
ULONGByReference pulId = new ULONGByReference();
HRESULT hr = jnaSysobj.GetCurrentThreadId(pulId);
if (hr.equals(COMUtilsExtra.E_UNEXPECTED)) {
return new DebugThreadId(-1);
return new DebugThreadRecord(-1);
}
COMUtils.checkRC(hr);
return new DebugThreadId(pulId.getValue().intValue());
return new DebugThreadRecord(pulId.getValue().intValue());
}
@Override
public void setCurrentThreadId(DebugThreadId id) {
HRESULT hr = jnaSysobj.SetCurrentThreadId(new ULONG(id.id));
HRESULT hr = jnaSysobj.SetCurrentThreadId(new ULONG(id.value()));
if (!hr.equals(COMUtilsExtra.E_UNEXPECTED) && !hr.equals(COMUtilsExtra.E_NOINTERFACE)) {
COMUtils.checkRC(hr);
}
@ -81,15 +92,15 @@ public class DebugSystemObjectsImpl1 implements DebugSystemObjectsInternal {
ULONGByReference pulId = new ULONGByReference();
HRESULT hr = jnaSysobj.GetCurrentProcessId(pulId);
if (hr.equals(COMUtilsExtra.E_UNEXPECTED)) {
return new DebugProcessId(-1);
return new DebugProcessRecord(-1);
}
COMUtils.checkRC(hr);
return new DebugProcessId(pulId.getValue().intValue());
return new DebugProcessRecord(pulId.getValue().intValue());
}
@Override
public void setCurrentProcessId(DebugProcessId id) {
HRESULT hr = jnaSysobj.SetCurrentProcessId(new ULONG(id.id));
HRESULT hr = jnaSysobj.SetCurrentProcessId(new ULONG(id.value()));
if (hr.equals(COMUtilsExtra.E_UNEXPECTED)) {
//System.err.println("Failure on setCurrentProcessId(" + id + ")");
return;
@ -131,7 +142,7 @@ public class DebugSystemObjectsImpl1 implements DebugSystemObjectsInternal {
COMUtils.checkRC(jnaSysobj.GetThreadIdsByIndex(ulStart, ulCount, aulIds, null));
List<DebugThreadId> result = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
result.add(new DebugThreadId(aulIds[i].intValue()));
result.add(new DebugThreadRecord(aulIds[i].intValue()));
}
return result;
}
@ -141,7 +152,7 @@ public class DebugSystemObjectsImpl1 implements DebugSystemObjectsInternal {
ULONGLONG ullHandle = new ULONGLONG(handle);
ULONGByReference pulId = new ULONGByReference();
COMUtils.checkRC(jnaSysobj.GetThreadIdByHandle(ullHandle, pulId));
return new DebugThreadId(pulId.getValue().intValue());
return new DebugThreadRecord(pulId.getValue().intValue());
}
@Override
@ -154,7 +165,7 @@ public class DebugSystemObjectsImpl1 implements DebugSystemObjectsInternal {
return null;
}
COMUtils.checkRC(hr);
return new DebugThreadId(pulId.getValue().intValue());
return new DebugThreadRecord(pulId.getValue().intValue());
}
@Override
@ -162,7 +173,7 @@ public class DebugSystemObjectsImpl1 implements DebugSystemObjectsInternal {
ULONGLONG ullHandle = new ULONGLONG(handle);
ULONGByReference pulId = new ULONGByReference();
COMUtils.checkRC(jnaSysobj.GetProcessIdByHandle(ullHandle, pulId));
return new DebugProcessId(pulId.getValue().intValue());
return new DebugProcessRecord(pulId.getValue().intValue());
}
@Override
@ -175,7 +186,7 @@ public class DebugSystemObjectsImpl1 implements DebugSystemObjectsInternal {
return null;
}
COMUtils.checkRC(hr);
return new DebugProcessId(pulId.getValue().intValue());
return new DebugProcessRecord(pulId.getValue().intValue());
}
@Override
@ -201,7 +212,7 @@ public class DebugSystemObjectsImpl1 implements DebugSystemObjectsInternal {
COMUtils.checkRC(jnaSysobj.GetProcessIdsByIndex(ulStart, ulCount, aulIds, null));
List<DebugProcessId> result = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
result.add(new DebugProcessId(aulIds[i].intValue()));
result.add(new DebugProcessRecord(aulIds[i].intValue()));
}
return result;
}

View File

@ -15,7 +15,9 @@
*/
package agent.dbgeng.impl.dbgeng.sysobj;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.sun.jna.platform.win32.WinDef.ULONG;
import com.sun.jna.platform.win32.WinDef.ULONGByReference;
@ -24,6 +26,7 @@ import com.sun.jna.platform.win32.COM.COMUtils;
import agent.dbgeng.dbgeng.COMUtilsExtra;
import agent.dbgeng.dbgeng.DebugSessionId;
import agent.dbgeng.dbgeng.DebugSessionRecord;
import agent.dbgeng.jna.dbgeng.sysobj.IDebugSystemObjects3;
public class DebugSystemObjectsImpl3 extends DebugSystemObjectsImpl2 {
@ -40,10 +43,10 @@ public class DebugSystemObjectsImpl3 extends DebugSystemObjectsImpl2 {
ULONGByReference pulId = new ULONGByReference();
HRESULT hr = jnaSysobj.GetEventSystem(pulId);
if (hr.equals(COMUtilsExtra.E_UNEXPECTED)) {
return new DebugSessionId(-1);
return new DebugSessionRecord(-1);
}
COMUtils.checkRC(hr);
return new DebugSessionId(pulId.getValue().intValue());
return new DebugSessionRecord(pulId.getValue().intValue());
}
@Override
@ -51,15 +54,15 @@ public class DebugSystemObjectsImpl3 extends DebugSystemObjectsImpl2 {
ULONGByReference pulId = new ULONGByReference();
HRESULT hr = jnaSysobj.GetCurrentSystemId(pulId);
if (hr.equals(COMUtilsExtra.E_UNEXPECTED)) {
return new DebugSessionId(-1);
return new DebugSessionRecord(-1);
}
COMUtils.checkRC(hr);
return new DebugSessionId(pulId.getValue().intValue());
return new DebugSessionRecord(pulId.getValue().intValue());
}
@Override
public void setCurrentSystemId(DebugSessionId id) {
HRESULT hr = jnaSysobj.SetCurrentSystemId(new ULONG(id.id));
HRESULT hr = jnaSysobj.SetCurrentSystemId(new ULONG(id.value()));
if (!hr.equals(COMUtilsExtra.E_UNEXPECTED)) {
COMUtils.checkRC(hr);
}
@ -88,7 +91,7 @@ public class DebugSystemObjectsImpl3 extends DebugSystemObjectsImpl2 {
COMUtils.checkRC(jnaSysobj.GetSystemIdsByIndex(ulStart, ulCount, aulIds, null));
List<DebugSessionId> result = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
result.add(new DebugSessionId(aulIds[i].intValue()));
result.add(new DebugSessionRecord(aulIds[i].intValue()));
}
return result;
}

View File

@ -24,7 +24,10 @@ import org.apache.commons.lang3.tuple.Pair;
import agent.dbgeng.dbgeng.*;
import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo;
import agent.dbgeng.manager.breakpoint.DbgBreakpointInsertions;
import agent.dbgeng.manager.cmd.DbgListOSMemoryRegionsCommand;
import agent.dbgeng.manager.cmd.DbgListOSProcessesCommand;
import agent.dbgeng.manager.impl.DbgManagerImpl;
import agent.dbgeng.manager.impl.DbgProcessImpl;
public interface DbgManager extends AutoCloseable, DbgBreakpointInsertions {
@ -297,6 +300,27 @@ public interface DbgManager extends AutoCloseable, DbgBreakpointInsertions {
*/
CompletableFuture<Map<DebugProcessId, DbgProcess>> listProcesses();
/**
* List dbgeng's processes
*
* @return a future that completes with a kernel-mode map of process IDs to process handles
*/
CompletableFuture<Map<DebugProcessId, DbgProcess>> listOSProcesses();
/**
* List dbgeng's processes
*
* @return a future that completes with a kernel-mode list of process memory
*/
CompletableFuture<List<DbgModuleMemory>> listOSMemory();
/**
* List dbgeng's threads
*
* @return a future that completes with a kernel-mode map of thread IDs to thread handles
*/
CompletableFuture<Map<DebugThreadId, DbgThread>> listOSThreads(DbgProcessImpl proc);
/**
* List the available processes on target
*

View File

@ -15,7 +15,14 @@
*/
package agent.dbgeng.manager.cmd;
import agent.dbgeng.manager.*;
import agent.dbgeng.dbgeng.DebugProcessId;
import agent.dbgeng.dbgeng.DebugSystemObjects;
import agent.dbgeng.dbgeng.DebugThreadId;
import agent.dbgeng.manager.DbgCommand;
import agent.dbgeng.manager.DbgEvent;
import agent.dbgeng.manager.DbgProcess;
import agent.dbgeng.manager.DbgState;
import agent.dbgeng.manager.DbgThread;
import agent.dbgeng.manager.evt.DbgCommandDoneEvent;
import agent.dbgeng.manager.impl.DbgManagerImpl;
@ -26,6 +33,12 @@ import agent.dbgeng.manager.impl.DbgManagerImpl;
*/
public abstract class AbstractDbgCommand<T> implements DbgCommand<T> {
protected final DbgManagerImpl manager;
DbgProcess previousProcess;
Long previousProcessOffset;
DebugProcessId previousProcessId;
DbgThread previousThread;
Long previousThreadOffset;
DebugThreadId previousThreadId;
/**
* Construct a new command to be executed by the given manager
@ -60,4 +73,52 @@ public abstract class AbstractDbgCommand<T> implements DbgCommand<T> {
public void invoke() {
// Nothing
}
public void setProcess(DbgProcess process) {
DebugSystemObjects so = manager.getSystemObjects();
previousProcess = process;
if (manager.isKernelMode() && !process.getId().isSystem()) {
previousProcessOffset = so.getCurrentProcessDataOffset();
so.setImplicitProcessDataOffset(process.getOffset());
}
else {
previousProcessId = so.getCurrentProcessId();
so.setCurrentProcessId(process.getId());
}
}
public void resetProcess() {
DebugSystemObjects so = manager.getSystemObjects();
if (manager.isKernelMode() && !previousProcess.getId().isSystem()) {
so.setImplicitProcessDataOffset(previousProcessOffset);
}
else {
so.setCurrentProcessId(previousProcessId);
}
}
public void setThread(DbgThread thread) {
DebugSystemObjects so = manager.getSystemObjects();
previousThread = thread;
if (manager.isKernelMode() && !thread.getId().isSystem()) {
previousThreadOffset = so.getCurrentThreadDataOffset();
so.setImplicitThreadDataOffset(thread.getOffset());
}
else {
previousThreadId = so.getCurrentThreadId();
so.setCurrentThreadId(thread.getId());
}
}
public void resetThread() {
DebugSystemObjects so = manager.getSystemObjects();
if (manager.isKernelMode() && !previousThread.getId().isSystem()) {
so.setImplicitThreadDataOffset(previousThreadOffset);
}
else {
so.setCurrentThreadId((DebugThreadId) previousThreadId);
}
}
}

View File

@ -54,7 +54,7 @@ public abstract class AbstractDbgExecToAddressCommand extends AbstractDbgCommand
@Override
public void invoke() {
String cmd = generateCommand(address);
String prefix = id == null ? "" : "~" + id.id + " ";
String prefix = id == null ? "" : "~" + id.id() + " ";
DebugControl control = manager.getControl();
DbgThreadImpl eventThread = manager.getEventThread();
if (eventThread != null && eventThread.getId().equals(id)) {

View File

@ -58,17 +58,27 @@ public class DbgListModulesCommand extends AbstractDbgCommand<Map<String, DbgMod
@Override
public void invoke() {
DebugSystemObjects so = manager.getSystemObjects();
so.setCurrentProcessId(process.getId());
DebugSymbols symbols = manager.getSymbols();
for (DebugModule module : symbols.iterateModules(0)) {
DebugModuleInfo info = symbols.getModuleParameters(1, module.getIndex());
String imageName = module.getName(DebugModuleName.IMAGE);
String moduleName = module.getName(DebugModuleName.MODULE);
info.setImageName(imageName);
info.setModuleName(moduleName);
updatedModules.put(info.toString(), module);
moduleInfo.put(module, info);
try {
setProcess(process);
DebugSymbols symbols = manager.getSymbols();
for (DebugModule module : symbols.iterateModules(0)) {
DebugModuleInfo info = symbols.getModuleParameters(1, module.getIndex());
String imageName = "UNKNOWN";
String moduleName = "UNKNOWN";
try {
imageName = module.getName(DebugModuleName.IMAGE);
moduleName = module.getName(DebugModuleName.MODULE);
} catch (UnsupportedOperationException uoe) {
//Skip
}
info.setImageName(imageName);
info.setModuleName(moduleName);
updatedModules.put(info.toString(), module);
moduleInfo.put(module, info);
}
}
finally {
resetProcess();
}
}

View File

@ -28,11 +28,11 @@ import agent.dbgeng.manager.impl.DbgManagerImpl;
import agent.dbgeng.manager.impl.DbgModuleMemoryImpl;
import ghidra.util.Msg;
public class DbgListMemoryRegionsCommandAlt extends AbstractDbgCommand<List<DbgModuleMemory>> {
public class DbgListOSMemoryRegionsCommand extends AbstractDbgCommand<List<DbgModuleMemory>> {
private List<DbgModuleMemory> memoryRegions = new ArrayList<>();
public DbgListMemoryRegionsCommandAlt(DbgManagerImpl manager) {
public DbgListOSMemoryRegionsCommand(DbgManagerImpl manager) {
super(manager);
}

View File

@ -0,0 +1,100 @@
/* ###
* 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 java.util.ArrayList;
import java.util.List;
import java.util.Map;
import agent.dbgeng.dbgeng.DebugControl;
import agent.dbgeng.dbgeng.DebugProcessId;
import agent.dbgeng.dbgeng.DebugProcessRecord;
import agent.dbgeng.manager.DbgEvent;
import agent.dbgeng.manager.DbgManager;
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;
/**
* Implementation of {@link DbgManager#listProcesses()}
*/
public class DbgListOSProcessesCommand extends AbstractDbgCommand<Map<DebugProcessId, DbgProcess>> {
private List<DebugProcessId> updatedProcessIds = new ArrayList<>();
public DbgListOSProcessesCommand(DbgManagerImpl manager) {
super(manager);
}
@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 Map<DebugProcessId, DbgProcess> complete(DbgPendingCommand<?> pending) {
StringBuilder builder = new StringBuilder();
for (DbgConsoleOutputEvent out : pending.findAllOf(DbgConsoleOutputEvent.class)) {
builder.append(out.getOutput());
}
parse(builder.toString());
Msg.warn(this, "Completed OS process list");
return manager.getKnownProcesses();
}
private void parse(String result) {
String[] lines = result.split("\n");
Long offset = null;
for (int i = 0; i < lines.length; i++) {
String line = lines[i];
if (line.contains("PROCESS")) {
offset = null;
String[] fields = line.trim().split("\\s+");
if (fields.length > 1 && fields[0].equals("PROCESS")) {
BigInteger val = new BigInteger(fields[1], 16);
offset = val.longValue();
}
}
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);
DbgProcessImpl mirror = manager.getProcessComputeIfAbsent(new DebugProcessRecord(pid), pid, false);
if (offset != null) {
mirror.setOffset(offset);
updatedProcessIds.add(mirror.getId());
}
}
}
}
}
@Override
public void invoke() {
Msg.warn(this, "Retrieving OS process list");
DebugControl control = manager.getControl();
control.execute("!process 0 0");
}
}

View File

@ -15,10 +15,14 @@
*/
package agent.dbgeng.manager.cmd;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import agent.dbgeng.dbgeng.DebugControl;
import agent.dbgeng.dbgeng.DebugProcessId;
import agent.dbgeng.dbgeng.DebugSystemObjects;
import agent.dbgeng.dbgeng.DebugThreadId;
import agent.dbgeng.dbgeng.DebugThreadRecord;
import agent.dbgeng.manager.DbgEvent;
import agent.dbgeng.manager.DbgThread;
import agent.dbgeng.manager.evt.AbstractDbgCompletedCommandEvent;
@ -28,15 +32,13 @@ import agent.dbgeng.manager.impl.DbgProcessImpl;
import agent.dbgeng.manager.impl.DbgThreadImpl;
import ghidra.util.Msg;
public class DbgSetCurrentState extends AbstractDbgCommand<DbgThread> {
public class DbgListOSThreadsCommand extends AbstractDbgCommand<Map<DebugThreadId, DbgThread>> {
protected final DbgProcessImpl process;
private List<DebugThreadId> updatedThreadIds = new ArrayList<>();;
private long pid;
private long tid;
private DebugProcessId pID;
private DebugThreadId tID;
public DbgSetCurrentState(DbgManagerImpl manager) {
public DbgListOSThreadsCommand(DbgManagerImpl manager, DbgProcessImpl process) {
super(manager);
this.process = process;
}
@Override
@ -51,52 +53,46 @@ public class DbgSetCurrentState extends AbstractDbgCommand<DbgThread> {
}
@Override
public DbgThread complete(DbgPendingCommand<?> pending) {
public Map<DebugThreadId, DbgThread> complete(DbgPendingCommand<?> pending) {
StringBuilder builder = new StringBuilder();
for (DbgConsoleOutputEvent out : pending.findAllOf(DbgConsoleOutputEvent.class)) {
builder.append(out.getOutput());
}
parse(builder.toString());
if (pID == null) {
return null;
}
DbgProcessImpl proc = manager.getProcessComputeIfAbsent(pID, pid, true);
DbgThreadImpl thread = manager.getThreadComputeIfAbsent(tID, proc, tid, true);
try {
DebugSystemObjects so = manager.getSystemObjects();
proc.setOffset(so.getCurrentProcessDataOffset());
thread.setOffset(so.getCurrentThreadDataOffset());
} catch (Exception e) {
Msg.error(this, e.getMessage());
}
return thread;
Msg.warn(this, "Completed OS thread list for pid="+Long.toHexString(process.getPid()));
Map<DebugThreadId, DbgThread> threads = process.getKnownThreads();
return threads;
}
private void parse(String result) {
String[] lines = result.split("\n");
Long offset = null;
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 > 3 && fields[2].equals("Cid")) {
if (fields.length > 4 && fields[0].equals("THREAD")) {
BigInteger val = new BigInteger(fields[1], 16);
offset = val.longValue();
String[] split = fields[3].split("\\.");
if (split.length == 2) {
pid = Long.parseLong(split[0], 16);
tid = Long.parseLong(split[1], 16);
pID = new DebugProcessId(pid);
tID = new DebugThreadId(tid);
Long tid = Long.parseLong(split[1], 16);
DbgThreadImpl mirror = manager.getThreadComputeIfAbsent(new DebugThreadRecord(tid), process, tid, false);
if (offset != null) {
mirror.setOffset(offset);
updatedThreadIds.add(mirror.getId());
}
}
}
break;
}
}
}
}
@Override
public void invoke() {
Msg.warn(this, "Retrieving OS thread list for pid="+Long.toHexString(process.getPid()));
DebugControl control = manager.getControl();
control.execute("!thread");
control.execute("!process "+Long.toHexString(process.getOffset())+" 2");
}
}

View File

@ -15,14 +15,19 @@
*/
package agent.dbgeng.manager.cmd;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import agent.dbgeng.dbgeng.DebugProcessId;
import agent.dbgeng.dbgeng.DebugSystemObjects;
import agent.dbgeng.dbgeng.DebugSystemProcessRecord;
import agent.dbgeng.manager.DbgCause.Causes;
import agent.dbgeng.manager.DbgManager;
import agent.dbgeng.manager.DbgProcess;
import agent.dbgeng.manager.impl.DbgManagerImpl;
import agent.dbgeng.manager.impl.DbgProcessImpl;
import ghidra.util.Msg;
/**
@ -44,19 +49,29 @@ public class DbgListProcessesCommand extends AbstractDbgCommand<Map<DebugProcess
continue; // Do nothing, we're in sync
}
// Need to create the inferior as if we received =thread-group-created
Msg.warn(this, "Resync: Was missing group: i" + id);
DebugSystemObjects so = manager.getSystemObjects();
so.setCurrentProcessId(id);
int pid = so.getCurrentProcessSystemId();
manager.getProcessComputeIfAbsent(id, pid, true);
long pid;
if (!manager.isKernelMode()) {
Msg.warn(this, "Resync: Was missing group: i" + id);
so.setCurrentProcessId(id);
pid = so.getCurrentProcessSystemId();
}
else {
id = new DebugSystemProcessRecord(id.value());
pid = -1;
}
DbgProcessImpl proc = manager.getProcessComputeIfAbsent(id, pid, true);
Long offset = so.getCurrentProcessDataOffset();
proc.setOffset(offset);
}
for (DebugProcessId id : new ArrayList<>(cur)) {
if (updatedProcessIds.contains(id)) {
continue; // Do nothing, we're in sync
}
// Need to remove the inferior as if we received =thread-group-removed
Msg.warn(this, "Resync: Had extra group: i" + id);
manager.removeProcess(id, Causes.UNCLAIMED);
if (!manager.isKernelMode()) {
Msg.warn(this, "Resync: Had extra group: i" + id);
manager.removeProcess(id, Causes.UNCLAIMED);
}
}
return allProcesses;
}

View File

@ -48,16 +48,20 @@ public class DbgListSymbolsCommand extends AbstractDbgCommand<Map<String, DbgMin
@Override
public void invoke() {
DebugSystemObjects so = manager.getSystemObjects();
so.setCurrentProcessId(process.getId());
DebugSymbols symbols = manager.getSymbols();
for (DebugSymbolName symbol : symbols.iterateSymbolMatches(module.getName() + "!*")) {
List<DebugSymbolId> symbolIdsByName = symbols.getSymbolIdsByName(symbol.name);
for (DebugSymbolId symbolId : symbolIdsByName) {
DebugSymbolEntry symbolEntry = symbols.getSymbolEntry(symbolId);
symbolEntries.put(symbolId, symbolEntry);
try {
setProcess(process);
DebugSymbols symbols = manager.getSymbols();
for (DebugSymbolName symbol : symbols.iterateSymbolMatches(module.getName() + "!*")) {
List<DebugSymbolId> symbolIdsByName = symbols.getSymbolIdsByName(symbol.name);
for (DebugSymbolId symbolId : symbolIdsByName) {
DebugSymbolEntry symbolEntry = symbols.getSymbolEntry(symbolId);
symbolEntries.put(symbolId, symbolEntry);
}
}
}
finally {
resetProcess();
}
}
}

View File

@ -15,13 +15,18 @@
*/
package agent.dbgeng.manager.cmd;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import agent.dbgeng.dbgeng.DebugSystemObjects;
import agent.dbgeng.dbgeng.DebugSystemThreadRecord;
import agent.dbgeng.dbgeng.DebugThreadId;
import agent.dbgeng.manager.DbgThread;
import agent.dbgeng.manager.impl.DbgManagerImpl;
import agent.dbgeng.manager.impl.DbgProcessImpl;
import agent.dbgeng.manager.impl.DbgThreadImpl;
import ghidra.util.Msg;
public class DbgListThreadsCommand extends AbstractDbgCommand<Map<DebugThreadId, DbgThread>> {
@ -41,30 +46,44 @@ public class DbgListThreadsCommand extends AbstractDbgCommand<Map<DebugThreadId,
if (cur.contains(id)) {
continue; // Do nothing, we're in sync
}
// Need to create the thread as if we receive =thread-created
Msg.warn(this, "Resync: Was missing thread: " + id);
DebugSystemObjects so = manager.getSystemObjects();
so.setCurrentThreadId(id);
int tid = so.getCurrentThreadSystemId();
manager.getThreadComputeIfAbsent(id, process, tid, false);
long tid;
if (!manager.isKernelMode()) {
Msg.warn(this, "Resync: Was missing thread: " + id);
so.setCurrentThreadId(id);
tid = (long) so.getCurrentThreadSystemId();
}
else {
id = new DebugSystemThreadRecord(id.value());
tid = -1;
}
DbgThreadImpl thread = manager.getThreadComputeIfAbsent(id, process, tid, false);
Long offset = so.getCurrentThreadDataOffset();
thread.setOffset(offset);
}
for (DebugThreadId id : new ArrayList<>(cur)) {
if (updatedThreadIds.contains(id)) {
continue; // Do nothing, we're in sync
}
// Need to remove the thread as if we received =thread-exited
Msg.warn(this, "Resync: Had extra thread: " + id);
process.removeThread(id);
manager.removeThread(id);
if (!manager.isKernelMode()) {
Msg.warn(this, "Resync: Had extra thread: " + id);
process.removeThread(id);
manager.removeThread(id);
}
}
return process.getKnownThreads();
}
@Override
public void invoke() {
DebugSystemObjects so = manager.getSystemObjects();
so.setCurrentProcessId(process.getId());
updatedThreadIds = so.getThreads();
try {
setProcess(process);
DebugSystemObjects so = manager.getSystemObjects();
updatedThreadIds = so.getThreads();
}
finally {
resetProcess();
}
}
}

View File

@ -30,7 +30,7 @@ public class DbgReadRegistersCommand extends AbstractDbgCommand<Map<DbgRegister,
private final DbgThreadImpl thread;
private final Set<DbgRegister> regs;
private DebugRegisters registers;
private DebugThreadId previous;
private Map<DbgRegister, BigInteger> result = new LinkedHashMap<>();
public DbgReadRegistersCommand(DbgManagerImpl manager, DbgThreadImpl thread, Integer frameId,
Set<DbgRegister> regs) {
@ -41,31 +41,31 @@ public class DbgReadRegistersCommand extends AbstractDbgCommand<Map<DbgRegister,
@Override
public Map<DbgRegister, BigInteger> complete(DbgPendingCommand<?> pending) {
DebugSystemObjects so = manager.getSystemObjects();
if (regs.isEmpty()) {
return Collections.emptyMap();
}
Map<DbgRegister, BigInteger> result = new LinkedHashMap<>();
if (registers != null) {
for (DbgRegister r : regs) {
if (r.isBaseRegister()) {
DebugValue value = registers.getValueByName(r.getName());
if (value != null) {
BigInteger bval = new BigInteger(value.encodeAsBytes());
result.put(r, bval);
}
}
}
}
so.setCurrentThreadId(previous);
return result;
}
@Override
public void invoke() {
DebugSystemObjects so = manager.getSystemObjects();
previous = so.getCurrentThreadId();
so.setCurrentThreadId(thread.getId());
registers = manager.getClient().getRegisters();
try {
setThread(thread);
registers = manager.getClient().getRegisters();
if (registers != null) {
for (DbgRegister r : regs) {
if (r.isBaseRegister()) {
DebugValue value = registers.getValueByName(r.getName());
if (value != null) {
BigInteger bval = new BigInteger(value.encodeAsBytes());
result.put(r, bval);
}
}
}
}
}
finally {
resetThread();
}
}
}

View File

@ -18,7 +18,6 @@ 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;
@ -94,11 +93,9 @@ public class DbgResolveProcessCommand extends AbstractDbgCommand<DbgProcess> {
@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");
}
DebugControl control = manager.getControl();
Long key = process.getOffset() != null ? process.getOffset() : process.getPid();
control.execute("!process "+Long.toHexString(key)+" 0");
}
}
}

View File

@ -93,10 +93,8 @@ public class DbgResolveThreadCommand extends AbstractDbgCommand<DbgThread> {
@Override
public void invoke() {
DebugThreadId id = thread.getId();
if (id != null) {
DebugControl control = manager.getControl();
control.execute("!thread "+Long.toHexString(id.id)+" 0");
}
DebugControl control = manager.getControl();
Long key = thread.getOffset() != null ? thread.getOffset() : thread.getTid();
control.execute("!thread "+Long.toHexString(key)+" 0");
}
}

View File

@ -98,7 +98,7 @@ public class DbgSetActiveProcessCommand extends AbstractDbgCommand<Void> {
} else {
so.setCurrentProcessId(id);
DebugProcessId currentProcessId = so.getCurrentProcessId();
if (id.id != currentProcessId.id) {
if (!id.id().equals(currentProcessId.id())) {
so.setCurrentProcessId(id);
}
}

View File

@ -41,28 +41,30 @@ public class DbgStackListFramesCommand extends AbstractDbgCommand<List<DbgStackF
@Override
public void invoke() {
result = new ArrayList<>();
DebugSystemObjects so = manager.getSystemObjects();
DebugThreadId previous = so.getCurrentThreadId();
so.setCurrentThreadId(thread.getId());
DebugStackInformation stackTrace = manager.getControl().getStackTrace(0L, 0L, 0L);
for (int i = 0; i < stackTrace.getNumberOfFrames(); i++) {
DEBUG_STACK_FRAME tf = stackTrace.getFrame(i);
//DbgStackFrame frame = new DbgStackFrameImpl(thread, tf.FrameNumber.intValue(),
// new BigInteger(Long.toHexString(tf.InstructionOffset.longValue()), 16), null);
DbgStackFrame frame = new DbgStackFrameImpl(thread, //
tf.FrameNumber.intValue(), //
new BigInteger(Long.toHexString(tf.InstructionOffset.longValue()), 16), //
tf.FuncTableEntry.longValue(), //
tf.FrameOffset.longValue(), //
tf.ReturnOffset.longValue(), //
tf.StackOffset.longValue(), //
tf.Virtual.booleanValue(), //
tf.Params[0].longValue(), //
tf.Params[1].longValue(), //
tf.Params[2].longValue(), //
tf.Params[3].longValue());
result.add(frame);
try {
setThread(thread);
DebugStackInformation stackTrace = manager.getControl().getStackTrace(0L, 0L, 0L);
for (int i = 0; i < stackTrace.getNumberOfFrames(); i++) {
DEBUG_STACK_FRAME tf = stackTrace.getFrame(i);
//DbgStackFrame frame = new DbgStackFrameImpl(thread, tf.FrameNumber.intValue(),
// new BigInteger(Long.toHexString(tf.InstructionOffset.longValue()), 16), null);
DbgStackFrame frame = new DbgStackFrameImpl(thread, //
tf.FrameNumber.intValue(), //
new BigInteger(Long.toHexString(tf.InstructionOffset.longValue()), 16), //
tf.FuncTableEntry.longValue(), //
tf.FrameOffset.longValue(), //
tf.ReturnOffset.longValue(), //
tf.StackOffset.longValue(), //
tf.Virtual.booleanValue(), //
tf.Params[0].longValue(), //
tf.Params[1].longValue(), //
tf.Params[2].longValue(), //
tf.Params[3].longValue());
result.add(frame);
}
}
finally {
resetThread();
}
so.setCurrentThreadId(previous);
}
}

View File

@ -0,0 +1,119 @@
/* ###
* 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 java.util.ArrayList;
import java.util.List;
import agent.dbgeng.dbgeng.DebugControl;
import agent.dbgeng.manager.DbgEvent;
import agent.dbgeng.manager.DbgStackFrame;
import agent.dbgeng.manager.evt.AbstractDbgCompletedCommandEvent;
import agent.dbgeng.manager.evt.DbgConsoleOutputEvent;
import agent.dbgeng.manager.impl.DbgManagerImpl;
import agent.dbgeng.manager.impl.DbgStackFrameImpl;
import agent.dbgeng.manager.impl.DbgThreadImpl;
public class DbgStackListOSFramesCommand extends AbstractDbgCommand<List<DbgStackFrame>> {
protected final DbgThreadImpl thread;
private List<DbgStackFrame> result = new ArrayList<>();
public DbgStackListOSFramesCommand(DbgManagerImpl manager, DbgThreadImpl thread) {
super(manager);
this.thread = 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 List<DbgStackFrame> complete(DbgPendingCommand<?> pending) {
StringBuilder builder = new StringBuilder();
for (DbgConsoleOutputEvent out : pending.findAllOf(DbgConsoleOutputEvent.class)) {
builder.append(out.getOutput());
}
parse(builder.toString());
return result;
}
private void parse(String output) {
String[] lines = output.split("\n");
int fcount = 0;
for (int i = 0; i < lines.length; i++) {
String line = lines[i];
if (line.contains(" : ") && !line.startsWith("Child") && !line.startsWith("THREAD")) {
String[] fields = line.trim().split("\\s+");
DbgStackFrame frame = new DbgStackFrameImpl(thread, //
fcount++, //
parseToBig(fields[1]), // return
fields.length > 8 ? fields[8] : ""
);
result.add(frame);
}
}
}
private BigInteger parseToBig(String lval) {
if (lval.contains("`")) {
lval = lval.replaceAll("`", "");
}
return new BigInteger(lval, 16);
}
@Override
public void invoke() {
DebugControl control = manager.getControl();
control.execute("!thread "+Long.toHexString(thread.getOffset())+" 6");
}
// @Override
// public void invoke() {
// result = new ArrayList<>();
// DebugSystemObjects so = manager.getSystemObjects();
// DebugThreadId previous = so.getCurrentThreadId();
// so.setCurrentThreadId(thread.getId());
// DebugStackInformation stackTrace = manager.getControl().getStackTrace(0L, 0L, 0L);
// for (int i = 0; i < stackTrace.getNumberOfFrames(); i++) {
// DEBUG_STACK_FRAME tf = stackTrace.getFrame(i);
// //DbgStackFrame frame = new DbgStackFrameImpl(thread, tf.FrameNumber.intValue(),
// // new BigInteger(Long.toHexString(tf.InstructionOffset.longValue()), 16), null);
// DbgStackFrame frame = new DbgStackFrameImpl(thread, //
// tf.FrameNumber.intValue(), //
// new BigInteger(Long.toHexString(tf.InstructionOffset.longValue()), 16), //
// tf.FuncTableEntry.longValue(), //
// tf.FrameOffset.longValue(), //
// tf.ReturnOffset.longValue(), //
// tf.StackOffset.longValue(), //
// tf.Virtual.booleanValue(), //
// tf.Params[0].longValue(), //
// tf.Params[1].longValue(), //
// tf.Params[2].longValue(), //
// tf.Params[3].longValue());
// result.add(frame);
// }
// so.setCurrentThreadId(previous);
// }
}

View File

@ -73,7 +73,7 @@ public class DbgStepCommand extends AbstractDbgCommand<Void> {
@Override
public void invoke() {
String cmd = "";
String prefix = id == null ? "" : "~" + id.id + " ";
String prefix = id == null ? "" : "~" + id.id() + " ";
DebugControl control = manager.getControl();
if (suffix.equals(ExecSuffix.STEP_INSTRUCTION)) {
cmd = "t";

View File

@ -60,12 +60,16 @@ import agent.dbgeng.dbgeng.DebugExceptionRecord64;
import agent.dbgeng.dbgeng.DebugModuleInfo;
import agent.dbgeng.dbgeng.DebugProcessId;
import agent.dbgeng.dbgeng.DebugProcessInfo;
import agent.dbgeng.dbgeng.DebugProcessRecord;
import agent.dbgeng.dbgeng.DebugRegisters;
import agent.dbgeng.dbgeng.DebugSessionId;
import agent.dbgeng.dbgeng.DebugSymbols;
import agent.dbgeng.dbgeng.DebugSystemObjects;
import agent.dbgeng.dbgeng.DebugSystemProcessRecord;
import agent.dbgeng.dbgeng.DebugSystemThreadRecord;
import agent.dbgeng.dbgeng.DebugThreadId;
import agent.dbgeng.dbgeng.DebugThreadInfo;
import agent.dbgeng.dbgeng.DebugThreadRecord;
import agent.dbgeng.gadp.impl.AbstractClientThreadExecutor;
import agent.dbgeng.gadp.impl.DbgEngClientThreadExecutor;
import agent.dbgeng.impl.dbgeng.DbgEngUtil;
@ -96,6 +100,9 @@ import agent.dbgeng.manager.cmd.DbgInsertBreakpointCommand;
import agent.dbgeng.manager.cmd.DbgLaunchProcessCommand;
import agent.dbgeng.manager.cmd.DbgListAvailableProcessesCommand;
import agent.dbgeng.manager.cmd.DbgListBreakpointsCommand;
import agent.dbgeng.manager.cmd.DbgListOSMemoryRegionsCommand;
import agent.dbgeng.manager.cmd.DbgListOSProcessesCommand;
import agent.dbgeng.manager.cmd.DbgListOSThreadsCommand;
import agent.dbgeng.manager.cmd.DbgListProcessesCommand;
import agent.dbgeng.manager.cmd.DbgOpenDumpCommand;
import agent.dbgeng.manager.cmd.DbgPendingCommand;
@ -145,7 +152,6 @@ import ghidra.dbg.target.TargetLauncher.CmdLineParser;
import ghidra.dbg.target.TargetLauncher.TargetCmdLineLauncher;
import ghidra.dbg.target.TargetObject;
import ghidra.dbg.util.HandlerMap;
import ghidra.dbg.util.PathUtils;
import ghidra.lifecycle.Internal;
import ghidra.util.Msg;
import ghidra.util.datastruct.ListenerSet;
@ -236,17 +242,6 @@ public class DbgManagerImpl implements DbgManager {
}
}
public DbgThreadImpl getThreadComputeIfAbsent(String key, DbgProcessImpl proc, boolean fire) {
String index = PathUtils.parseIndex(key);
Integer tid = Integer.decode(index);
DebugThreadId id = getSystemObjects().getThreadIdBySystemId(tid);
if (id == null) {
id = new DebugThreadId(tid);
return getThreadComputeIfAbsent(id, proc, tid, fire);
}
return getThreadComputeIfAbsent(id, proc, tid, fire);
}
public DbgThreadImpl getThreadComputeIfAbsent(DebugThreadId id, DbgProcessImpl process,
long tid, boolean fire) {
synchronized (threads) {
@ -368,7 +363,7 @@ public class DbgManagerImpl implements DbgManager {
public DbgSessionImpl getSessionComputeIfAbsent(DebugSessionId id, boolean fire) {
synchronized (sessions) {
if (!sessions.containsKey(id) && id.id >= 0) {
if (!sessions.containsKey(id) && id.value() >= 0) {
DbgSessionImpl session = new DbgSessionImpl(this, id);
session.add();
if (fire) {
@ -727,7 +722,7 @@ public class DbgManagerImpl implements DbgManager {
if (eventThread != null) {
((DbgThreadImpl) eventThread).setInfo(lastEventInformation);
}
return currentThread == null ? new DebugThreadId(-1) : currentThread.getId();
return currentThread == null ? new DebugThreadRecord(-1) : currentThread.getId();
}
/**
@ -799,7 +794,7 @@ public class DbgManagerImpl implements DbgManager {
getEventListeners().fire.threadCreated(thread, DbgCause.Causes.UNCLAIMED);
getEventListeners().fire.threadSelected(thread, null, evt.getCause());
String key = Long.toHexString(eventId.id);
String key = eventId.id();
if (statusByNameMap.containsKey(key)) {
return statusByNameMap.get(key);
}
@ -824,7 +819,7 @@ public class DbgManagerImpl implements DbgManager {
getEventListeners().fire.eventSelected(evt, evt.getCause());
getEventListeners().fire.threadExited(eventId, process, evt.getCause());
String key = Long.toHexString(eventId.id);
String key = eventId.id();
if (statusByNameMap.containsKey(key)) {
return statusByNameMap.get(key);
}
@ -846,11 +841,11 @@ public class DbgManagerImpl implements DbgManager {
}
DebugThreadId eventId = updateState();
currentThread = evt.getThread();
//currentThread = evt.getThread();
currentThread.setState(evt.getState(), evt.getCause(), evt.getReason());
getEventListeners().fire.threadSelected(currentThread, evt.getFrame(), evt.getCause());
String key = Long.toHexString(eventId.id);
String key = eventId.id();
if (statusByNameMap.containsKey(key)) {
return statusByNameMap.get(key);
}
@ -878,7 +873,7 @@ public class DbgManagerImpl implements DbgManager {
//proc.moduleLoaded(info.moduleInfo);
//getEventListeners().fire.moduleLoaded(proc, info.moduleInfo, evt.getCause());
String key = Long.toHexString(proc.getId().id);
String key = proc.getId().id();
if (statusByNameMap.containsKey(key)) {
return statusByNameMap.get(key);
}
@ -911,7 +906,7 @@ public class DbgManagerImpl implements DbgManager {
process.remove(evt.getCause());
getEventListeners().fire.processRemoved(process.getId(), evt.getCause());
String key = Long.toHexString(process.getId().id);
String key = process.getId().id();
if (statusByNameMap.containsKey(key)) {
return statusByNameMap.get(key);
}
@ -931,7 +926,7 @@ public class DbgManagerImpl implements DbgManager {
currentProcess = evt.getProcess();
getEventListeners().fire.processSelected(currentProcess, evt.getCause());
String key = Long.toHexString(eventId.id);
String key = eventId.id();
if (statusByNameMap.containsKey(key)) {
return statusByNameMap.get(key);
}
@ -1059,7 +1054,7 @@ public class DbgManagerImpl implements DbgManager {
if (flags.contains(ChangeEngineState.CURRENT_THREAD)) {
long id = evt.getArgument();
for (DebugThreadId key : getThreads()) {
if (key.id == id) {
if (key.value() == id) {
DbgThread thread = getThread(key);
if (thread != null) {
getEventListeners().fire.threadSelected(thread, null, evt.getCause());
@ -1088,7 +1083,7 @@ public class DbgManagerImpl implements DbgManager {
currentSession = evt.getSession();
getEventListeners().fire.sessionSelected(currentSession, evt.getCause());
String key = Long.toHexString(eventId.id);
String key = eventId.id();
if (statusByNameMap.containsKey(key)) {
return statusByNameMap.get(key);
}
@ -1113,9 +1108,9 @@ public class DbgManagerImpl implements DbgManager {
else {
processCount--;
}
DebugProcessId id = new DebugProcessId(info.intValue());
DebugProcessId id = new DebugProcessRecord(info.intValue());
String key = Long.toHexString(id.id);
String key = id.id();
if (statusByNameMap.containsKey(key)) {
return statusByNameMap.get(key);
}
@ -1316,32 +1311,13 @@ public class DbgManagerImpl implements DbgManager {
if (tag == null) {
for (DebugThreadId tid : tids) {
Msg.debug(this, "TRAP Added: " + id + " on " + tid);
if (!claimsBreakpointAdded.satisfy(tid)) {
/*
AbstractSctlTrapSpec spec =
server.getDialect().create(AbstractSctlTrapSpec.class);
spec.setActionStop();
spec.setAddress(newOffset);
synth.synthSetTrap(null, tid.id, spec, id);
*/
}
else {
if (claimsBreakpointAdded.satisfy(tid)) {
Msg.debug(this, " claimed");
}
breaksById.put(id, new BreakpointTag(newOffset));
}
}
else if (tag.offset != newOffset) {
/*
for (DebugThreadId tid : tids) {
synth.synthClearTrap(null, tid.id, id);
AbstractSctlTrapSpec spec =
server.getDialect().create(AbstractSctlTrapSpec.class);
spec.setActionStop();
spec.setAddress(newOffset);
synth.synthSetTrap(null, tid.id, spec, id);
}
*/
tag.offset = newOffset;
} // else the breakpoint is unchanged
}
@ -1353,12 +1329,7 @@ public class DbgManagerImpl implements DbgManager {
}
for (DebugThreadId tid : tids) {
Msg.debug(this, "TRAP Removed: " + id + " on " + tid);
if (!claimsBreakpointRemoved.satisfy(new BreakId(tid, id))) {
/*
synth.synthClearTrap(null, tid.id, id);
*/
}
else {
if (claimsBreakpointRemoved.satisfy(new BreakId(tid, id))) {
Msg.debug(this, " claimed");
}
}
@ -1376,6 +1347,21 @@ public class DbgManagerImpl implements DbgManager {
return execute(new DbgListProcessesCommand(this));
}
@Override
public CompletableFuture<Map<DebugProcessId, DbgProcess>> listOSProcesses() {
return execute(new DbgListOSProcessesCommand(this));
}
@Override
public CompletableFuture<List<DbgModuleMemory>> listOSMemory() {
return execute(new DbgListOSMemoryRegionsCommand(this));
}
@Override
public CompletableFuture<Map<DebugThreadId, DbgThread>> listOSThreads(DbgProcessImpl proc) {
return execute(new DbgListOSThreadsCommand(this, proc));
}
@Override
public CompletableFuture<List<Pair<Integer, String>>> listAvailableProcesses() {
return execute(new DbgListAvailableProcessesCommand(this));
@ -1682,7 +1668,6 @@ public class DbgManagerImpl implements DbgManager {
//System.err.println("EXIT");
waiting = false;
updateState();
getEventListeners().fire.threadSelected(eventThread, null, Causes.UNCLAIMED);
return CompletableFuture.completedFuture(null);
}
@ -1782,28 +1767,32 @@ public class DbgManagerImpl implements DbgManager {
DebugSystemObjects so = getSystemObjects();
currentSession = eventSession = getSessionComputeIfAbsent(esid, true);
if (kernelMode) {
long poffset = so.getCurrentProcessDataOffset();
currentProcess = eventProcess = getProcessComputeIfAbsent(new DebugProcessId(poffset), -1, true);
if (currentProcess.getPid() < 0) {
DbgProcessImpl cp = getProcessComputeIfAbsent(new DebugSystemProcessRecord(epid.value()), -1, true);
cp.setOffset(so.getCurrentProcessDataOffset());
currentProcess = eventProcess = cp;
if (currentProcess.getId().isSystem()) {
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);
DbgProcessImpl mirror = getProcessComputeIfAbsent(new DebugProcessRecord(proc.getPid()), proc.getPid(), true);
if (mirror != null) {
mirror.setOffset(currentProcess.getOffset());
currentProcess = eventProcess = mirror;
getEventListeners().fire.processSelected(eventProcess, Causes.UNCLAIMED);
}
});
}
long toffset = so.getCurrentThreadDataOffset();
currentThread = eventThread = getThreadComputeIfAbsent(new DebugThreadId(toffset), (DbgProcessImpl) eventProcess, -1, false);
if (currentThread.getTid() < 0) {
DbgThreadImpl ct = getThreadComputeIfAbsent(new DebugSystemThreadRecord(etid.value()), cp, -1, false);
ct.setOffset(so.getCurrentThreadDataOffset());
currentThread = eventThread = ct;
if (currentThread.getId().isSystem()) {
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);
DbgThreadImpl mirror = getThreadComputeIfAbsent(new DebugThreadRecord(thread.getTid()), (DbgProcessImpl) eventProcess, thread.getTid(), true);
if (mirror != null) {
mirror.setOffset(currentThread.getOffset());
currentThread = eventThread = mirror;
getEventListeners().fire.threadSelected(eventThread, null, Causes.UNCLAIMED);
}
});
@ -1813,6 +1802,7 @@ public class DbgManagerImpl implements DbgManager {
eventProcess = getProcessComputeIfAbsent(epid, so.getCurrentProcessSystemId(), true);
currentThread = eventThread = getThreadComputeIfAbsent(etid, (DbgProcessImpl) eventProcess,
so.getCurrentThreadSystemId(), false);
getEventListeners().fire.threadSelected(eventThread, null, Causes.UNCLAIMED);
}
}

View File

@ -133,6 +133,7 @@ public class DbgProcessImpl implements DbgProcess {
* @param thread the thread to add
*/
public void addThread(DbgThreadImpl thread) {
assert(thread.getProcess().equals(this));
DbgThreadImpl exists = threads.get(thread.getId());
if (exists != null) {
Msg.warn(this, "Adding pre-existing thread " + exists);
@ -207,6 +208,9 @@ public class DbgProcessImpl implements DbgProcess {
@Override
public CompletableFuture<Map<DebugThreadId, DbgThread>> listThreads() {
if (manager.isKernelMode() && !id.isSystem()) {
return CompletableFuture.completedFuture(getKnownThreads());
}
return manager.execute(new DbgListThreadsCommand(manager, this));
}

View File

@ -18,6 +18,7 @@ package agent.dbgeng.model.iface2;
import java.util.concurrent.CompletableFuture;
import agent.dbgeng.dbgeng.DebugProcessId;
import agent.dbgeng.dbgeng.DebugProcessRecord;
import agent.dbgeng.manager.DbgEventsListenerAdapter;
import agent.dbgeng.manager.DbgProcess;
import agent.dbgeng.manager.DbgState;
@ -73,7 +74,7 @@ public interface DbgModelTargetProcess extends //
try {
String index = PathUtils.parseIndex(getName());
Long pid = Long.decode(index);
DebugProcessId id = new DebugProcessId(pid);
DebugProcessId id = new DebugProcessRecord(pid);
return manager.getProcessComputeIfAbsent(id, pid, fire);
}
catch (IllegalArgumentException e) {

View File

@ -82,11 +82,12 @@ public interface DbgModelTargetRegisterBank extends DbgModelTargetObject, Target
VALUE_ATTRIBUTE_NAME, value.toString(16) //
), "Refreshed");
if (value.longValue() != 0) {
String newval = reg.getName() + " : " + value.toString(16);
String valstr = Long.toUnsignedString(value.longValue(), 16); //value.toString(16);
String newval = reg.getName() + " : " + valstr;
reg.changeAttributes(List.of(), Map.of( //
DISPLAY_ATTRIBUTE_NAME, newval //
), "Refreshed");
reg.setModified(value.toString(16).equals(oldval));
reg.setModified(valstr.equals(oldval));
}
}

View File

@ -21,10 +21,16 @@ import java.util.concurrent.CompletableFuture;
import agent.dbgeng.dbgeng.DebugClient.DebugOutputFlags;
import agent.dbgeng.dbgeng.DebugSessionId;
import agent.dbgeng.dbgeng.DebugSessionRecord;
import agent.dbgeng.manager.DbgEventsListenerAdapter;
import agent.dbgeng.manager.DbgSession;
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.DbgModelTargetExecutionStateful;
import agent.dbgeng.model.iface1.DbgModelTargetInterpreter;
import agent.dbgeng.model.iface1.DbgModelTargetInterruptible;
import agent.dbgeng.model.iface1.DbgModelTargetResumable;
import ghidra.dbg.target.TargetAggregate;
import ghidra.dbg.target.TargetConsole;
import ghidra.dbg.target.TargetConsole.Channel;
@ -52,7 +58,7 @@ public interface DbgModelTargetSession extends //
try {
String index = PathUtils.parseIndex(getName());
Integer sid = Integer.decode(index);
DebugSessionId id = new DebugSessionId(sid);
DebugSessionId id = new DebugSessionRecord(sid);
return manager.getSessionComputeIfAbsent(id, fire);
}
catch (IllegalArgumentException e) {

View File

@ -18,6 +18,7 @@ package agent.dbgeng.model.iface2;
import java.util.concurrent.CompletableFuture;
import agent.dbgeng.dbgeng.DebugThreadId;
import agent.dbgeng.dbgeng.DebugThreadRecord;
import agent.dbgeng.manager.DbgEventsListenerAdapter;
import agent.dbgeng.manager.DbgReason;
import agent.dbgeng.manager.DbgState;
@ -30,7 +31,9 @@ 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 ghidra.dbg.target.*;
import ghidra.dbg.target.TargetAggregate;
import ghidra.dbg.target.TargetMethod;
import ghidra.dbg.target.TargetThread;
import ghidra.dbg.util.PathUtils;
import ghidra.program.model.address.Address;
@ -54,7 +57,7 @@ public interface DbgModelTargetThread extends //
DbgProcessImpl process = parentProcess == null ? null : (DbgProcessImpl) parentProcess.getProcess();
String index = PathUtils.parseIndex(getName());
Long tid = Long.decode(index);
DebugThreadId id = new DebugThreadId(tid);
DebugThreadId id = new DebugThreadRecord(tid);
DbgThreadImpl thread = manager.getThreadComputeIfAbsent(id, process, tid, fire);
return thread;
}

View File

@ -23,11 +23,13 @@ import java.util.concurrent.RejectedExecutionException;
import org.apache.commons.lang3.exception.ExceptionUtils;
import agent.dbgeng.dbgeng.DebugSessionId;
import agent.dbgeng.dbgeng.DebugSessionRecord;
import agent.dbgeng.manager.DbgManager;
import agent.dbgeng.manager.DbgSession;
import agent.dbgeng.model.AbstractDbgModel;
import agent.dbgeng.model.iface2.*;
import agent.dbgeng.model.iface2.DbgModelTargetProcess;
import agent.dbgeng.model.iface2.DbgModelTargetSession;
import agent.dbgeng.model.iface2.DbgModelTargetSessionContainer;
import ghidra.async.AsyncUtils;
import ghidra.dbg.DebuggerModelClosedReason;
import ghidra.dbg.DebuggerObjectModelWithMemory;
@ -36,7 +38,11 @@ import ghidra.dbg.target.TargetMemory;
import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.AnnotatedSchemaContext;
import ghidra.dbg.target.schema.TargetObjectSchema;
import ghidra.program.model.address.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.address.DefaultAddressFactory;
import ghidra.program.model.address.GenericAddressSpace;
public class DbgModelImpl extends AbstractDbgModel implements DebuggerObjectModelWithMemory {
// TODO: Need some minimal memory modeling per architecture on the model/agent side.
@ -67,7 +73,7 @@ public class DbgModelImpl extends AbstractDbgModel implements DebuggerObjectMode
//System.out.println(XmlSchemaContext.serialize(SCHEMA_CTX));
this.root = new DbgModelTargetRootImpl(this, ROOT_SCHEMA);
this.completedRoot = CompletableFuture.completedFuture(root);
DbgSession s = dbg.getSessionComputeIfAbsent(new DebugSessionId(0), true);
DbgSession s = dbg.getSessionComputeIfAbsent(new DebugSessionRecord(0), true);
DbgModelTargetSessionContainer sessions = root.sessions;
this.session = (DbgModelTargetSessionImpl) sessions.getTargetSession(s);
addModelRoot(root);

View File

@ -15,24 +15,46 @@
*/
package agent.dbgeng.model.impl;
import java.lang.invoke.MethodHandles;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import agent.dbgeng.manager.DbgModuleMemory;
import agent.dbgeng.manager.cmd.*;
import agent.dbgeng.manager.cmd.DbgListKernelMemoryRegionsCommand;
import agent.dbgeng.manager.cmd.DbgListMemoryRegionsCommand;
import agent.dbgeng.manager.cmd.DbgListOSMemoryRegionsCommand;
import agent.dbgeng.manager.cmd.DbgReadBusDataCommand;
import agent.dbgeng.manager.cmd.DbgReadControlCommand;
import agent.dbgeng.manager.cmd.DbgReadDebuggerDataCommand;
import agent.dbgeng.manager.cmd.DbgReadIoCommand;
import agent.dbgeng.manager.cmd.DbgReadMemoryCommand;
import agent.dbgeng.manager.cmd.DbgReadPhysicalMemoryCommand;
import agent.dbgeng.manager.cmd.DbgWriteBusDataCommand;
import agent.dbgeng.manager.cmd.DbgWriteControlCommand;
import agent.dbgeng.manager.cmd.DbgWriteIoCommand;
import agent.dbgeng.manager.cmd.DbgWriteMemoryCommand;
import agent.dbgeng.manager.cmd.DbgWritePhysicalMemoryCommand;
import agent.dbgeng.manager.impl.DbgManagerImpl;
import agent.dbgeng.manager.impl.DbgProcessImpl;
import agent.dbgeng.model.iface2.*;
import agent.dbgeng.model.iface2.DbgModelTargetMemoryContainer;
import agent.dbgeng.model.iface2.DbgModelTargetMemoryRegion;
import agent.dbgeng.model.iface2.DbgModelTargetProcess;
import generic.ULongSpan;
import generic.ULongSpan.ULongSpanSet;
import ghidra.async.AsyncUtils;
import ghidra.dbg.DebuggerObjectModel.RefreshBehavior;
import ghidra.dbg.error.DebuggerMemoryAccessException;
import ghidra.dbg.error.DebuggerModelAccessException;
import ghidra.dbg.target.TargetMethod;
import ghidra.dbg.target.TargetMethod.AnnotatedTargetMethod;
import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*;
import ghidra.dbg.target.schema.TargetAttributeType;
import ghidra.dbg.target.schema.TargetElementType;
import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
import ghidra.program.model.address.Address;
import ghidra.util.datastruct.WeakValueHashMap;
@ -41,6 +63,7 @@ import ghidra.util.datastruct.WeakValueHashMap;
elements = {
@TargetElementType(type = DbgModelTargetMemoryRegionImpl.class) },
attributes = {
@TargetAttributeType(name = "Populate", type = TargetMethod.class),
@TargetAttributeType(type = Void.class) },
canonicalContainer = true)
public class DbgModelTargetMemoryContainerImpl extends DbgModelTargetObjectImpl
@ -57,6 +80,12 @@ public class DbgModelTargetMemoryContainerImpl extends DbgModelTargetObjectImpl
if (!getModel().isSuppressDescent()) {
requestElements(RefreshBehavior.REFRESH_ALWAYS);
}
DbgManagerImpl manager = getManager();
if (manager.isKernelMode()) {
changeAttributes(List.of(), List.of(),
AnnotatedTargetMethod.collectExports(MethodHandles.lookup(), getModel(), this),
"Methods");
}
}
@Override
@ -96,7 +125,7 @@ public class DbgModelTargetMemoryContainerImpl extends DbgModelTargetObjectImpl
return manager.execute(new DbgListKernelMemoryRegionsCommand(manager));
}
if (manager.useAltMemoryQuery()) {
return manager.execute(new DbgListMemoryRegionsCommandAlt(manager));
return manager.execute(new DbgListOSMemoryRegionsCommand(manager));
}
return manager.execute(new DbgListMemoryRegionsCommand(manager));
}
@ -271,4 +300,13 @@ public class DbgModelTargetMemoryContainerImpl extends DbgModelTargetObjectImpl
return CompletableFuture.completedFuture(null);
}
}
@TargetMethod.Export("Populate")
public CompletableFuture<Void> populate() {
return getManager().listOSMemory().thenAccept(byName -> {
List<TargetObject> sections;
synchronized (this) {
sections = byName.stream().map(this::getTargetMemory).collect(Collectors.toList());
}
setElements(sections, Map.of(), "Refreshed");
});
}}

View File

@ -20,6 +20,7 @@ import java.util.concurrent.CompletableFuture;
import agent.dbgeng.manager.DbgModule;
import agent.dbgeng.manager.DbgProcess;
import agent.dbgeng.manager.impl.DbgManagerImpl;
import agent.dbgeng.model.iface2.DbgModelTargetModule;
import agent.dbgeng.model.iface2.DbgModelTargetModuleContainer;
import ghidra.dbg.DebuggerObjectModel.RefreshBehavior;
@ -49,9 +50,16 @@ public class DbgModelTargetModuleContainerImpl extends DbgModelTargetObjectImpl
super(process.getModel(), process, "Modules", "ModuleContainer");
this.targetProcess = process;
this.process = process.process;
if (!getModel().isSuppressDescent()) {
requestElements(RefreshBehavior.REFRESH_NEVER);
DbgManagerImpl manager = getManager();
if (manager.isKernelMode()) {
if (!this.process.getId().isSystem()) {
return;
}
}
if (getModel().isSuppressDescent()) {
return;
}
requestElements(RefreshBehavior.REFRESH_NEVER);
}
@Override

View File

@ -125,9 +125,18 @@ public class DbgModelTargetObjectImpl extends DefaultTargetObject<TargetObject,
return;
}
}
if (this instanceof DbgModelTargetExecutionStateful) {
DbgModelTargetExecutionStateful stateful = (DbgModelTargetExecutionStateful) this;
stateful.setExecutionState(exec, "Refreshed");
if (proxy instanceof DbgModelTargetExecutionStateful stateful) {
if (proxy instanceof DbgModelTargetSession) {
if (state != DbgState.EXIT) {
stateful.setExecutionState(exec, "Refreshed");
}
}
else {
TargetExecutionState previous = stateful.getExecutionState();
if (!previous.equals(TargetExecutionState.INACTIVE)) {
stateful.setExecutionState(exec, "Refreshed");
}
}
}
}

View File

@ -15,22 +15,38 @@
*/
package agent.dbgeng.model.impl;
import java.lang.invoke.MethodHandles;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import agent.dbgeng.dbgeng.*;
import agent.dbgeng.manager.*;
import agent.dbgeng.dbgeng.DebugModuleInfo;
import agent.dbgeng.dbgeng.DebugProcessId;
import agent.dbgeng.dbgeng.DebugThreadId;
import agent.dbgeng.manager.DbgCause;
import agent.dbgeng.manager.DbgProcess;
import agent.dbgeng.manager.DbgReason;
import agent.dbgeng.manager.DbgState;
import agent.dbgeng.manager.DbgThread;
import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo;
import agent.dbgeng.manager.impl.DbgManagerImpl;
import agent.dbgeng.model.iface1.DbgModelTargetConfigurable;
import agent.dbgeng.model.iface2.*;
import agent.dbgeng.model.iface2.DbgModelTargetMemoryContainer;
import agent.dbgeng.model.iface2.DbgModelTargetModuleContainer;
import agent.dbgeng.model.iface2.DbgModelTargetProcess;
import agent.dbgeng.model.iface2.DbgModelTargetProcessContainer;
import agent.dbgeng.model.iface2.DbgModelTargetSession;
import ghidra.async.AsyncUtils;
import ghidra.dbg.DebuggerObjectModel.RefreshBehavior;
import ghidra.dbg.error.DebuggerIllegalArgumentException;
import ghidra.dbg.target.TargetConfigurable;
import ghidra.dbg.target.TargetMethod;
import ghidra.dbg.target.TargetMethod.AnnotatedTargetMethod;
import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*;
import ghidra.dbg.target.schema.TargetAttributeType;
import ghidra.dbg.target.schema.TargetElementType;
import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
@TargetObjectSchemaInfo(
name = "ProcessContainer",
@ -39,6 +55,7 @@ import ghidra.dbg.target.schema.*;
},
attributes = {
@TargetAttributeType(name = TargetConfigurable.BASE_ATTRIBUTE_NAME, type = Integer.class),
@TargetAttributeType(name = "Populate", type = TargetMethod.class),
@TargetAttributeType(type = Void.class)
},
canonicalContainer = true)
@ -49,7 +66,8 @@ public class DbgModelTargetProcessContainerImpl extends DbgModelTargetObjectImpl
super(session.getModel(), session, "Processes", "ProcessContainer");
this.changeAttributes(List.of(), Map.of(BASE_ATTRIBUTE_NAME, 16), "Initialized");
getManager().addEventsListener(this);
DbgManagerImpl manager = getManager();
manager.addEventsListener(this);
}
@Override
@ -62,7 +80,14 @@ public class DbgModelTargetProcessContainerImpl extends DbgModelTargetObjectImpl
broadcast().event(getProxy(), null, TargetEventType.PROCESS_CREATED,
"Process " + proc.getId() + " started " + process.getName() + "pid=" + proc.getPid(),
List.of(process));
}
DbgManagerImpl manager = getManager();
if (manager.isKernelMode()) {
changeAttributes(List.of(), List.of(),
AnnotatedTargetMethod.collectExports(MethodHandles.lookup(), getModel(), this),
"Methods");
}
}
@Override
public void processStarted(DbgProcess proc, DbgCause cause) {
@ -133,7 +158,8 @@ public class DbgModelTargetProcessContainerImpl extends DbgModelTargetObjectImpl
@Override
public CompletableFuture<Void> requestElements(RefreshBehavior refresh) {
return getManager().listProcesses().thenAccept(byIID -> {
DbgManagerImpl manager = getManager();
return manager.listProcesses().thenAccept(byIID -> {
List<TargetObject> processes;
synchronized (this) {
processes = byIID.values()
@ -188,4 +214,15 @@ public class DbgModelTargetProcessContainerImpl extends DbgModelTargetObjectImpl
return AsyncUtils.NIL;
}
@TargetMethod.Export("Populate")
public CompletableFuture<Void> populate() {
return getManager().listOSProcesses().thenAccept(byPID -> {
List<TargetObject> processes;
synchronized (this) {
processes =
byPID.values().stream().map(this::getTargetProcess).collect(Collectors.toList());
}
setElements(processes, Map.of(), "Refreshed");
});
}
}

View File

@ -20,14 +20,24 @@ import java.util.Map;
import java.util.concurrent.CompletableFuture;
import agent.dbgeng.dbgeng.DebugProcessId;
import agent.dbgeng.manager.*;
import agent.dbgeng.manager.DbgCause;
import agent.dbgeng.manager.DbgProcess;
import agent.dbgeng.manager.DbgState;
import agent.dbgeng.manager.DbgThread;
import agent.dbgeng.manager.impl.DbgManagerImpl;
import agent.dbgeng.model.iface1.DbgModelTargetFocusScope;
import agent.dbgeng.model.iface2.*;
import agent.dbgeng.model.iface2.DbgModelTargetDebugContainer;
import agent.dbgeng.model.iface2.DbgModelTargetMemoryContainer;
import agent.dbgeng.model.iface2.DbgModelTargetModuleContainer;
import agent.dbgeng.model.iface2.DbgModelTargetProcess;
import agent.dbgeng.model.iface2.DbgModelTargetProcessContainer;
import agent.dbgeng.model.iface2.DbgModelTargetThreadContainer;
import ghidra.dbg.DebuggerObjectModel.RefreshBehavior;
import ghidra.dbg.target.*;
import ghidra.dbg.target.TargetAttachable;
import ghidra.dbg.target.TargetEventScope.TargetEventType;
import ghidra.dbg.target.schema.*;
import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.TargetAttributeType;
import ghidra.dbg.target.schema.TargetElementType;
import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
import ghidra.dbg.util.PathUtils;
@TargetObjectSchemaInfo(
@ -69,7 +79,7 @@ public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
TargetAttachKind.BY_OBJECT_REF, TargetAttachKind.BY_ID);
protected static String indexProcess(DebugProcessId debugProcessId) {
return PathUtils.makeIndex(debugProcessId.id);
return debugProcessId.id();
}
protected static String indexProcess(DbgProcess process) {
@ -111,32 +121,42 @@ public class DbgModelTargetProcessImpl extends DbgModelTargetObjectImpl
SUPPORTED_ATTACH_KINDS_ATTRIBUTE_NAME, SUPPORTED_KINDS, //
SUPPORTED_STEP_KINDS_ATTRIBUTE_NAME, DbgModelTargetThreadImpl.SUPPORTED_KINDS //
), "Initialized");
setExecutionState(TargetExecutionState.ALIVE, "Initialized");
if (getManager().isKernelMode()) {
TargetExecutionState state = process.getPid() > 0 ?
TargetExecutionState.INACTIVE : TargetExecutionState.ALIVE;
setExecutionState(state, "Initialized");
}
else {
setExecutionState(TargetExecutionState.ALIVE, "Initialized");
}
getManager().addEventsListener(this);
}
@Override
public String getDisplay() {
if (getManager().isKernelMode()) {
return "[kernel]";
}
DebugProcessId id = process.getId();
Long pid = process.getPid();
if (pid < 0) {
return "[" + process.getId().id + "]";
if (getManager().isKernelMode()) {
if (id.isSystem()) {
return "["+id.id()+"]";
}
String pidstr = Long.toString(pid, base);
if (base == 16) {
pidstr = "0x" + pidstr;
}
Long offset = process.getOffset();
return offset == null ? "[" + pidstr + "]" : "[" + pidstr + " : " + Long.toHexString(offset) + "]";
}
String pidstr = Long.toString(pid, base);
if (base == 16) {
pidstr = "0x" + pidstr;
}
return "[" + process.getId().id + ":" + pidstr + "]";
}
@Override
public void processSelected(DbgProcess eventProcess, DbgCause cause) {
if (eventProcess.equals(process)) {
((DbgModelTargetFocusScope) searchForSuitable(TargetFocusScope.class)).setFocus(this);
else {
if (pid < 0) {
return "[" + id.id() + "]";
}
String pidstr = Long.toString(pid, base);
if (base == 16) {
pidstr = "0x" + pidstr;
}
return "[" + id.id() + ":" + pidstr + "]";
}
}

View File

@ -170,13 +170,14 @@ public class DbgModelTargetRegisterContainerImpl extends DbgModelTargetObjectImp
private void changeAttrs(DbgModelTargetRegister reg, BigInteger value) {
String oldval = (String) reg.getCachedAttributes().get(VALUE_ATTRIBUTE_NAME);
String valstr = Long.toUnsignedString(value.longValue(), 16); //value.toString(16);
String newval = (value.longValue() == 0) ? reg.getName()
: reg.getName() + " : " + value.toString(16);
: reg.getName() + " : " + valstr;
reg.changeAttributes(List.of(), Map.of( //
VALUE_ATTRIBUTE_NAME, value.toString(16), //
VALUE_ATTRIBUTE_NAME, valstr, //
DISPLAY_ATTRIBUTE_NAME, newval //
), "Refreshed");
reg.setModified(!value.toString(16).equals(oldval));
reg.setModified(!valstr.equals(oldval));
}
@Override

View File

@ -15,16 +15,41 @@
*/
package agent.dbgeng.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 agent.dbgeng.manager.*;
import agent.dbgeng.dbgeng.DebugProcessId;
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.impl.DbgManagerImpl;
import agent.dbgeng.manager.impl.DbgProcessImpl;
import agent.dbgeng.model.AbstractDbgModel;
import agent.dbgeng.model.iface1.DbgModelSelectableObject;
import agent.dbgeng.model.iface2.*;
import agent.dbgeng.model.iface1.DbgModelTargetExecutionStateful;
import agent.dbgeng.model.iface2.DbgModelTargetConnector;
import agent.dbgeng.model.iface2.DbgModelTargetRoot;
import agent.dbgeng.model.iface2.DbgModelTargetThread;
import ghidra.dbg.DebuggerObjectModel.RefreshBehavior;
import ghidra.dbg.error.DebuggerUserException;
import ghidra.dbg.target.*;
import ghidra.dbg.target.schema.*;
import ghidra.dbg.target.TargetEventScope;
import ghidra.dbg.target.TargetExecutionStateful;
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.schema.TargetAttributeType;
import ghidra.dbg.target.schema.TargetElementType;
import ghidra.dbg.target.schema.TargetObjectSchema;
import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
import ghidra.dbg.util.PathUtils;
@TargetObjectSchemaInfo(
@ -142,6 +167,117 @@ public class DbgModelTargetRootImpl extends DbgModelDefaultTargetModelRoot
}
}
@Override
public void processSelected(DbgProcess process, DbgCause cause) {
if (process != null) {
objectSelected(process);
}
}
@Override
public void threadSelected(DbgThread thread, DbgStackFrame frame, DbgCause cause) {
if (thread != null) {
objectSelected(thread);
if (frame != null) {
objectSelected(frame);
}
}
}
public void objectSelected(Object object) {
AbstractDbgModel model = getModel();
List<String> objPath = findObject(object);
model.fetchModelObject(objPath, RefreshBehavior.REFRESH_WHEN_ABSENT).thenAccept(obj ->
update(obj)
);
}
private List<String> findObject(Object obj) {
DbgManagerImpl manager = getManager();
List<String> objpath = new ArrayList<>();
if (obj == null) {
return objpath;
}
DbgSession session = manager.getCurrentSession();
if (obj instanceof DbgSession) {
session = (DbgSession) obj;
}
if (session == null) {
return objpath;
}
String skey = DbgModelTargetSessionImpl.keySession(session);
if (obj instanceof DbgSession || obj instanceof String) {
objpath = List.of("Sessions", skey);
return objpath;
}
DbgProcess process = manager.getCurrentProcess();
if (obj instanceof DbgProcess) {
process = (DbgProcess) obj;
}
if (process == null) {
return objpath;
}
String pkey = DbgModelTargetProcessImpl.keyProcess(process);
if (obj instanceof DbgProcess || obj instanceof DebugProcessId) {
objpath = List.of("Sessions", skey, "Processes", pkey);
return objpath;
}
DbgThread thread = manager.getCurrentThread();
if (obj instanceof DbgThread) {
thread = (DbgThread) obj;
process = thread.getProcess();
pkey = DbgModelTargetProcessImpl.keyProcess(process);
}
if (thread == null) {
return objpath;
}
String tkey = DbgModelTargetThreadImpl.keyThread(thread);
if (getManager().isKernelMode()) {
if (tkey.equals("[0x0]")) {
// Weird, but necessary...
pkey = "[0x0]";
}
}
if (obj instanceof DbgThread || obj instanceof DebugThreadId) {
objpath = List.of("Sessions", skey, "Processes", pkey, "Threads", tkey);
return objpath;
}
if (obj instanceof DbgStackFrame) {
DbgStackFrame frame = (DbgStackFrame) obj;
thread = frame.getThread();
process = thread.getProcess();
String fkey = DbgModelTargetStackFrameImpl.keyFrame(frame);
tkey = DbgModelTargetThreadImpl.keyThread(thread);
pkey = DbgModelTargetProcessImpl.keyProcess(process);
objpath = List.of("Sessions", skey, "Processes", pkey, "Threads", tkey, "Stack",
"Frames", fkey);
return objpath;
}
return objpath;
}
private void update(TargetObject obj) {
if (obj instanceof DbgModelSelectableObject) {
setFocus((DbgModelSelectableObject) obj);
}
if (obj instanceof DbgModelTargetExecutionStateful) {
activate((DbgModelTargetExecutionStateful) obj);
}
}
private void activate(DbgModelTargetExecutionStateful stateful) {
TargetExecutionState state = stateful.getExecutionState();
if (state.equals(TargetExecutionState.INACTIVE)) {
stateful.changeAttributes(List.of(), Map.of( //
TargetExecutionStateful.STATE_ATTRIBUTE_NAME, TargetExecutionState.ALIVE //
), "Selected");
stateful.fetchAttributes(RefreshBehavior.REFRESH_ALWAYS);
}
}
@Override
public boolean isAccessible() {
return accessible;

View File

@ -52,7 +52,7 @@ public class DbgModelTargetSessionImpl extends DbgModelTargetObjectImpl
// NB: This should almost certainly always be implemented by the root of the object tree
protected static String indexSession(DebugSessionId debugSystemId) {
return PathUtils.makeIndex(debugSystemId.id);
return debugSystemId.id();
}
protected static String indexSession(DbgSession session) {

View File

@ -109,7 +109,7 @@ public class DbgModelTargetStackFrameImpl extends DbgModelTargetObjectImpl
if (frame.getFunction() == null) {
return String.format("#%d 0x%s", frame.getLevel(), frame.getAddress().toString(16));
}
return String.format("#%d 0x%s in %s ()", frame.getLevel(), frame.getAddress().toString(16),
return String.format("#%d 0x%s in %s", frame.getLevel(), frame.getAddress().toString(16),
frame.getFunction());
}

View File

@ -15,30 +15,47 @@
*/
package agent.dbgeng.model.impl;
import java.lang.invoke.MethodHandles;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import agent.dbgeng.dbgeng.DebugThreadId;
import agent.dbgeng.manager.*;
import agent.dbgeng.manager.reason.*;
import agent.dbgeng.manager.DbgCause;
import agent.dbgeng.manager.DbgProcess;
import agent.dbgeng.manager.DbgReason;
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.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.DbgModelTargetConfigurable;
import agent.dbgeng.model.iface2.*;
import agent.dbgeng.model.iface2.DbgModelTargetProcess;
import agent.dbgeng.model.iface2.DbgModelTargetThread;
import agent.dbgeng.model.iface2.DbgModelTargetThreadContainer;
import ghidra.async.AsyncUtils;
import ghidra.dbg.DebuggerObjectModel.RefreshBehavior;
import ghidra.dbg.error.DebuggerIllegalArgumentException;
import ghidra.dbg.target.TargetConfigurable;
import ghidra.dbg.target.TargetMethod;
import ghidra.dbg.target.TargetMethod.AnnotatedTargetMethod;
import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.*;
import ghidra.dbg.target.schema.TargetAttributeType;
import ghidra.dbg.target.schema.TargetElementType;
import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
@TargetObjectSchemaInfo(
name = "ThreadContainer",
elements = {
@TargetElementType(type = DbgModelTargetThreadImpl.class)
},
},
attributes = {
@TargetAttributeType(name = TargetConfigurable.BASE_ATTRIBUTE_NAME, type = Integer.class),
@TargetAttributeType(name = "Populate", type = TargetMethod.class),
@TargetAttributeType(type = Void.class)
},
canonicalContainer = true)
@ -50,11 +67,16 @@ public class DbgModelTargetThreadContainerImpl extends DbgModelTargetObjectImpl
public DbgModelTargetThreadContainerImpl(DbgModelTargetProcessImpl process) {
super(process.getModel(), process, "Threads", "ThreadContainer");
this.process = process.process;
this.changeAttributes(List.of(), Map.of(BASE_ATTRIBUTE_NAME, 16), "Initialized");
this.changeAttributes(List.of(), Map.of(
BASE_ATTRIBUTE_NAME, 16 //
), "Initialized");
getManager().addEventsListener(this);
if (!getModel().isSuppressDescent()) {
requestElements(RefreshBehavior.REFRESH_NEVER);
DbgManagerImpl manager = getManager();
manager.addEventsListener(this);
if (manager.isKernelMode() && !process.getProcess().getId().isSystem()) {
changeAttributes(List.of(), List.of(),
AnnotatedTargetMethod.collectExports(MethodHandles.lookup(), getModel(), this),
"Methods");
}
}
@ -71,6 +93,9 @@ public class DbgModelTargetThreadContainerImpl extends DbgModelTargetObjectImpl
@Override
public void threadStateChanged(DbgThread thread, DbgState state, DbgCause cause,
DbgReason reason) {
if (!thread.getProcess().equals(process)) {
return;
}
DbgModelTargetThread targetThread = getTargetThread(thread);
TargetEventType eventType = getEventType(state, cause, reason);
broadcast().event(getProxy(), targetThread, eventType,
@ -163,4 +188,17 @@ public class DbgModelTargetThreadContainerImpl extends DbgModelTargetObjectImpl
}
return AsyncUtils.NIL;
}
@TargetMethod.Export("Populate")
public CompletableFuture<Void> populate() {
return getManager().listOSThreads((DbgProcessImpl) process).thenAccept(byTID -> {
List<TargetObject> threads;
synchronized (this) {
threads =
byTID.values().stream().map(this::getTargetThread).collect(Collectors.toList());
}
setElements(threads, Map.of(), "Refreshed");
});
}
}

View File

@ -21,14 +21,19 @@ import java.util.Map;
import java.util.concurrent.CompletableFuture;
import agent.dbgeng.dbgeng.DebugThreadId;
import agent.dbgeng.manager.*;
import agent.dbgeng.manager.DbgReason;
import agent.dbgeng.manager.DbgState;
import agent.dbgeng.manager.DbgThread;
import agent.dbgeng.manager.impl.DbgManagerImpl;
import agent.dbgeng.model.iface1.DbgModelTargetFocusScope;
import agent.dbgeng.model.iface2.*;
import agent.dbgeng.model.iface2.DbgModelTargetProcess;
import agent.dbgeng.model.iface2.DbgModelTargetRegisterContainerAndBank;
import agent.dbgeng.model.iface2.DbgModelTargetThread;
import agent.dbgeng.model.iface2.DbgModelTargetThreadContainer;
import ghidra.dbg.target.TargetEnvironment;
import ghidra.dbg.target.TargetFocusScope;
import ghidra.dbg.target.TargetMethod.AnnotatedTargetMethod;
import ghidra.dbg.target.schema.*;
import ghidra.dbg.target.schema.TargetAttributeType;
import ghidra.dbg.target.schema.TargetElementType;
import ghidra.dbg.target.schema.TargetObjectSchemaInfo;
import ghidra.dbg.util.PathUtils;
@TargetObjectSchemaInfo(
@ -61,7 +66,7 @@ public class DbgModelTargetThreadImpl extends DbgModelTargetObjectImpl
TargetStepKind.EXTENDED);
protected static String indexThread(DebugThreadId debugThreadId) {
return PathUtils.makeIndex(debugThreadId.id);
return debugThreadId.id();
}
protected static String indexThread(DbgThread thread) {
@ -110,24 +115,31 @@ public class DbgModelTargetThreadImpl extends DbgModelTargetObjectImpl
@Override
public String getDisplay() {
if (getManager().isKernelMode()) {
return "[PR" + thread.getId().id + "]";
if (thread == null) {
return "[unknown]";
}
DebugThreadId id = thread.getId();
Long tid = thread.getTid();
if (tid < 0) {
return "[" + thread.getId().id + "]";
if (getManager().isKernelMode()) {
if (id.isSystem()) {
return "[" + id.id() + "]";
}
String tidstr = Long.toString(tid, base);
if (base == 16) {
tidstr = "0x" + tidstr;
}
Long offset = thread.getOffset();
return offset == null ? "[" + tidstr + "]" : "[" + tidstr + " : " + Long.toHexString(offset) + "]";
}
String tidstr = Long.toString(tid, base);
if (base == 16) {
tidstr = "0x" + tidstr;
}
return "[" + thread.getId().id + ":" + tidstr + "]";
}
@Override
public void threadSelected(DbgThread eventThread, DbgStackFrame frame, DbgCause cause) {
if (eventThread.equals(thread)) {
((DbgModelTargetFocusScope) searchForSuitable(TargetFocusScope.class)).setFocus(this);
else {
if (tid < 0) {
return "[" + id.id() + "]";
}
String tidstr = Long.toString(tid, base);
if (base == 16) {
tidstr = "0x" + tidstr;
}
return "[" + id.id() + ":" + tidstr + "]";
}
}

View File

@ -16,17 +16,52 @@
package agent.dbgmodel.gadp.impl;
import java.nio.ByteBuffer;
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.Set;
import com.sun.jna.platform.win32.WinDef.ULONGLONG;
import com.sun.jna.platform.win32.COM.COMException;
import agent.dbgeng.dbgeng.*;
import agent.dbgeng.dbgeng.DebugAdvanced;
import agent.dbgeng.dbgeng.DebugClient;
import agent.dbgeng.dbgeng.DebugControl;
import agent.dbgeng.dbgeng.DebugDataSpaces;
import agent.dbgeng.dbgeng.DebugEventCallbacks;
import agent.dbgeng.dbgeng.DebugInputCallbacks;
import agent.dbgeng.dbgeng.DebugModule;
import agent.dbgeng.dbgeng.DebugModuleInfo;
import agent.dbgeng.dbgeng.DebugOutputCallbacks;
import agent.dbgeng.dbgeng.DebugProcessId;
import agent.dbgeng.dbgeng.DebugProcessRecord;
import agent.dbgeng.dbgeng.DebugRegisters;
import agent.dbgeng.dbgeng.DebugRunningProcess;
import agent.dbgeng.dbgeng.DebugRunningProcess.Description;
import agent.dbgeng.dbgeng.DebugRunningProcess.Description.ProcessDescriptionFlags;
import agent.dbgeng.dbgeng.DebugValue.*;
import agent.dbgeng.dbgeng.DebugServerId;
import agent.dbgeng.dbgeng.DebugSessionId;
import agent.dbgeng.dbgeng.DebugSymbolEntry;
import agent.dbgeng.dbgeng.DebugSymbolId;
import agent.dbgeng.dbgeng.DebugSymbolName;
import agent.dbgeng.dbgeng.DebugSymbols;
import agent.dbgeng.dbgeng.DebugSystemObjects;
import agent.dbgeng.dbgeng.DebugThreadId;
import agent.dbgeng.dbgeng.DebugValue;
import agent.dbgeng.dbgeng.DebugValue.DebugInt16Value;
import agent.dbgeng.dbgeng.DebugValue.DebugInt32Value;
import agent.dbgeng.dbgeng.DebugValue.DebugInt64Value;
import agent.dbgeng.dbgeng.DebugValue.DebugValueType;
import agent.dbgmodel.dbgmodel.bridge.HostDataModelAccess;
import agent.dbgmodel.dbgmodel.debughost.*;
import agent.dbgmodel.dbgmodel.debughost.DebugHost;
import agent.dbgmodel.dbgmodel.debughost.DebugHostContext;
import agent.dbgmodel.dbgmodel.debughost.DebugHostMemory1;
import agent.dbgmodel.dbgmodel.debughost.DebugHostModule1;
import agent.dbgmodel.dbgmodel.debughost.DebugHostSymbol1;
import agent.dbgmodel.dbgmodel.debughost.DebugHostSymbolEnumerator;
import agent.dbgmodel.dbgmodel.debughost.DebugHostSymbols;
import agent.dbgmodel.dbgmodel.main.ModelObject;
import agent.dbgmodel.impl.dbgmodel.DebugRunningProcessImpl;
import agent.dbgmodel.impl.dbgmodel.bridge.HDMAUtil;
@ -592,7 +627,7 @@ public class WrappedDbgModel
public void setCurrentThreadId(DebugThreadId dti) {
DebugSystemObjects so = client.getSystemObjects();
DebugThreadId currentThreadId = so.getCurrentThreadId();
if (dti.id != currentThreadId.id) {
if (!dti.id().equals(currentThreadId.id())) {
so.setCurrentThreadId(dti);
}
/*
@ -919,7 +954,7 @@ public class WrappedDbgModel
}
int pid = Integer.decode(id);
if (pid == 0) {
return new DebugProcessId(-1);
return new DebugProcessRecord(-1);
}
DebugProcessId dpi = client.getSystemObjects().getProcessIdBySystemId(pid);
addObj(dpi, id);

View File

@ -164,30 +164,26 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
@Override
public void processSelected(DbgProcess process, DbgCause cause) {
objectSelected(process);
if (getManager().isKernelMode()) {
processActivated(process);
if (process != null) {
objectSelected(process);
}
}
@Override
public void threadSelected(DbgThread thread, DbgStackFrame frame, DbgCause cause) {
objectSelected(thread);
if (getManager().isKernelMode() && thread != null) {
processActivated(thread.getProcess());
threadActivated(thread);
}
if (frame != null) {
objectSelected(frame);
if (thread != null) {
objectSelected(thread);
if (frame != null) {
objectSelected(frame);
}
}
}
public void objectSelected(Object object) {
List<String> objPath = findObject(object);
TargetObject obj = getModel().getModelObject(objPath);
if (obj instanceof DbgModelSelectableObject) {
setFocus((DbgModelSelectableObject) obj);
}
model.fetchModelObject(objPath, RefreshBehavior.REFRESH_WHEN_ABSENT).thenAccept(obj ->
update(obj)
);
}
@Override
@ -217,21 +213,6 @@ 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(RefreshBehavior.REFRESH_ALWAYS);
}
}
@Override
public void threadCreated(DbgThread thread, DbgCause cause) {
getObject(thread).thenAccept(obj -> {
@ -253,21 +234,6 @@ 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(RefreshBehavior.REFRESH_ALWAYS);
}
}
@Override
public void moduleLoaded(DbgProcess proc, DebugModuleInfo info, DbgCause cause) {
getObjectRevisited(proc, List.of("Modules"), info).thenAccept(obj -> {
@ -340,7 +306,7 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
xpath.addAll(ext);
// NB: fetchModelObject may have to be called with false
return AsyncUtils.sequence(TypeSpec.cls(DbgModelTargetObject.class)).then(seq -> {
getModel().fetchModelObject(xpath, false).handle(seq::next);
getModel().fetchModelObject(xpath, RefreshBehavior.REFRESH_NEVER).handle(seq::next);
}, TypeSpec.cls(TargetObject.class)).then((pobj, seq) -> {
if (pobj == null) {
seq.exit();
@ -564,11 +530,11 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
DebugSystemObjects so = getManager().getSystemObjects();
List<String> objpath = new ArrayList<>();
DebugSessionId sid = so.getCurrentSystemId();
String skey = sid.id < 0 ? PathUtils.makeKey("0x0")
: PathUtils.makeKey("0x" + Integer.toHexString(sid.id));
String skey = sid.value() < 0 ? PathUtils.makeKey("0x0")
: PathUtils.makeKey("0x" + sid.id());
if (obj instanceof DbgSession) {
DbgSession session = (DbgSession) obj;
skey = PathUtils.makeKey("0x" + Long.toHexString(session.getId().id));
skey = PathUtils.makeKey("0x" + session.getId().id());
}
if (obj instanceof DbgSession || obj instanceof String) {
objpath = List.of("Sessions", skey);
@ -615,6 +581,30 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot
return objpath;
}
private void update(TargetObject obj) {
if (obj instanceof DbgModelSelectableObject) {
setFocus((DbgModelSelectableObject) obj);
}
if (obj instanceof DbgModelTargetExecutionStateful) {
activate((DbgModelTargetExecutionStateful) obj);
// OK, this sucks, but not all threads are parented to activated objects
DbgModelTargetProcess parentProcess = ((DbgModelTargetObject) obj).getParentProcess();
if (obj instanceof DbgModelTargetExecutionStateful) {
activate(parentProcess);
}
}
}
private void activate(DbgModelTargetExecutionStateful stateful) {
TargetExecutionState state = stateful.getExecutionState();
if (state.equals(TargetExecutionState.INACTIVE)) {
stateful.changeAttributes(List.of(), Map.of( //
TargetExecutionStateful.STATE_ATTRIBUTE_NAME, TargetExecutionState.ALIVE //
), "Selected");
stateful.fetchAttributes(RefreshBehavior.REFRESH_ALWAYS);
}
}
private TargetEventType getEventType(DbgState state, DbgCause cause, DbgReason reason) {
switch (state) {
case RUNNING:

View File

@ -83,7 +83,7 @@ public class DbgModelSetContextMWETest extends AbstractGhidraHeadlessIntegration
private void dumpRegsViaDX() {
DebugThreadId id = so.getCurrentThreadId();
if (id.id == -1) {
if (id.value() == -1) {
return;
}
@ -102,7 +102,7 @@ public class DbgModelSetContextMWETest extends AbstractGhidraHeadlessIntegration
private void dumpFrame0ViaDX() {
DebugThreadId id = so.getCurrentThreadId();
if (id.id == -1) {
if (id.value() == -1) {
return;
}
@ -135,44 +135,44 @@ public class DbgModelSetContextMWETest extends AbstractGhidraHeadlessIntegration
private void dumpFrame0ViaK() {
DebugThreadId id = so.getCurrentThreadId();
if (id.id == -1) {
if (id.value() == -1) {
return;
}
try {
DebugStackInformation stackInfo = control.getStackTrace(0, 0, 0);
if (stackInfo.getNumberOfFrames() == 0) {
Msg.info(this, "t" + id.id + ".Stack is empty?");
Msg.info(this, "t" + id.id() + ".Stack is empty?");
}
else {
DEBUG_STACK_FRAME frame = stackInfo.getFrame(0);
Msg.info(this,
String.format("t%d.Frame[0].io=%08x", id.id,
String.format("t%d.Frame[0].io=%08x", id.id(),
frame.InstructionOffset.longValue()));
}
}
catch (Exception e) {
Msg.info(this, "Could not read t" + id.id + ".Frame[0].io: " + e);
Msg.info(this, "Could not read t" + id.id() + ".Frame[0].io: " + e);
}
}
private void dumpPCViaRegsAPI() {
DebugThreadId id = so.getCurrentThreadId();
if (id.id == -1) {
if (id.value() == -1) {
return;
}
try {
Msg.info(this, String.format("t%d.rip=%s", id.id,
Msg.info(this, String.format("t%d.rip=%s", id.id(),
registers.getValueByName("rip")));
}
catch (Exception e) {
Msg.info(this, "Could not read t" + id.id + ".RIP: " + e);
Msg.info(this, "Could not read t" + id.id() + ".RIP: " + e);
}
try {
Msg.info(this, String.format("t%d.eip=%s", id.id,
Msg.info(this, String.format("t%d.eip=%s", id.id(),
registers.getValueByName("eip")));
}
catch (Exception e) {
Msg.info(this, "Could not read t" + id.id + ".EIP: " + e);
Msg.info(this, "Could not read t" + id.id() + ".EIP: " + e);
}
}

View File

@ -31,6 +31,7 @@ import java.util.concurrent.TimeoutException;
import org.junit.Test;
import ghidra.async.*;
import ghidra.dbg.DebuggerObjectModel.RefreshBehavior;
import ghidra.dbg.gadp.GadpVersion;
import ghidra.dbg.gadp.protocol.Gadp;
import ghidra.dbg.gadp.util.AsyncProtobufMessageChannel;
@ -400,7 +401,7 @@ public class GadpClientTest implements AsyncTestUtils {
assertEquals(HELLO_WORLD, waitOn(fetchVal1));
assertEquals(HELLO_WORLD, waitOn(fetchVal2));
CompletableFuture<?> fetchVal3 = client.fetchModelValue(PathUtils.parse("value"), true);
CompletableFuture<?> fetchVal3 = client.fetchModelValue(PathUtils.parse("value"), RefreshBehavior.REFRESH_ALWAYS);
srv.handleResyncAttributes(List.of(), true, null, Map.of("value", "Hi"));
assertEquals("Hi", waitOn(fetchVal3));
}

View File

@ -20,8 +20,14 @@ import java.awt.Color;
import java.awt.event.MouseEvent;
import java.io.PrintWriter;
import java.lang.invoke.MethodHandles;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@ -36,7 +42,10 @@ import org.apache.commons.lang3.StringUtils;
import docking.ActionContext;
import docking.WindowPosition;
import docking.action.*;
import docking.action.DockingAction;
import docking.action.DockingActionIf;
import docking.action.MenuData;
import docking.action.ToggleDockingAction;
import docking.action.builder.ActionBuilder;
import docking.action.builder.ToggleActionBuilder;
import docking.widgets.OptionDialog;
@ -47,29 +56,107 @@ import generic.theme.GColor;
import ghidra.app.plugin.core.debug.DebuggerCoordinates;
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.*;
import ghidra.app.plugin.core.debug.gui.objects.actions.*;
import ghidra.app.plugin.core.debug.gui.objects.components.*;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractAttachAction;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractConsoleAction;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractDetachAction;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractInterruptAction;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractKillAction;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractLaunchAction;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractQuickLaunchAction;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractRecordAction;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractRefreshAction;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractResumeAction;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractSetBreakpointAction;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractStepFinishAction;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractStepIntoAction;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractStepLastAction;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractStepOverAction;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractToggleAction;
import ghidra.app.plugin.core.debug.gui.objects.actions.DisplayAsGraphAction;
import ghidra.app.plugin.core.debug.gui.objects.actions.DisplayAsTableAction;
import ghidra.app.plugin.core.debug.gui.objects.actions.DisplayAsTreeAction;
import ghidra.app.plugin.core.debug.gui.objects.actions.DisplayAsXMLAction;
import ghidra.app.plugin.core.debug.gui.objects.actions.DisplayFilteredGraphAction;
import ghidra.app.plugin.core.debug.gui.objects.actions.DisplayFilteredTableAction;
import ghidra.app.plugin.core.debug.gui.objects.actions.DisplayFilteredTreeAction;
import ghidra.app.plugin.core.debug.gui.objects.actions.DisplayFilteredXMLAction;
import ghidra.app.plugin.core.debug.gui.objects.actions.DisplayMethodsAction;
import ghidra.app.plugin.core.debug.gui.objects.actions.ExportAsFactsAction;
import ghidra.app.plugin.core.debug.gui.objects.actions.ExportAsXMLAction;
import ghidra.app.plugin.core.debug.gui.objects.actions.ImportFromFactsAction;
import ghidra.app.plugin.core.debug.gui.objects.actions.ImportFromXMLAction;
import ghidra.app.plugin.core.debug.gui.objects.actions.OpenWinDbgTraceAction;
import ghidra.app.plugin.core.debug.gui.objects.actions.SetTimeoutAction;
import ghidra.app.plugin.core.debug.gui.objects.components.DebuggerAttachDialog;
import ghidra.app.plugin.core.debug.gui.objects.components.DebuggerBreakpointDialog;
import ghidra.app.plugin.core.debug.gui.objects.components.DebuggerMethodInvocationDialog;
import ghidra.app.plugin.core.debug.gui.objects.components.DummyTargetObject;
import ghidra.app.plugin.core.debug.gui.objects.components.GenericDebuggerProgramLaunchOffer;
import ghidra.app.plugin.core.debug.gui.objects.components.ObjectAttributeColumn;
import ghidra.app.plugin.core.debug.gui.objects.components.ObjectAttributeRow;
import ghidra.app.plugin.core.debug.gui.objects.components.ObjectElementColumn;
import ghidra.app.plugin.core.debug.gui.objects.components.ObjectElementRow;
import ghidra.app.plugin.core.debug.gui.objects.components.ObjectEnumeratedColumnTableModel;
import ghidra.app.plugin.core.debug.gui.objects.components.ObjectNode;
import ghidra.app.plugin.core.debug.gui.objects.components.ObjectPane;
import ghidra.app.plugin.core.debug.gui.objects.components.ObjectTable;
import ghidra.app.plugin.core.debug.gui.objects.components.ObjectTree;
import ghidra.app.plugin.core.debug.mapping.DebuggerMemoryMapper;
import ghidra.app.script.*;
import ghidra.app.services.*;
import ghidra.app.script.GhidraScript;
import ghidra.app.script.GhidraScriptLoadException;
import ghidra.app.script.GhidraScriptProvider;
import ghidra.app.script.GhidraScriptUtil;
import ghidra.app.script.GhidraState;
import ghidra.app.services.ConsoleService;
import ghidra.app.services.DebuggerListingService;
import ghidra.app.services.DebuggerModelService;
import ghidra.app.services.DebuggerStaticMappingService;
import ghidra.app.services.DebuggerTraceManagerService;
import ghidra.app.services.DebuggerTraceManagerService.ActivationCause;
import ghidra.async.*;
import ghidra.dbg.*;
import ghidra.app.services.GraphDisplayBroker;
import ghidra.app.services.TraceRecorder;
import ghidra.async.AsyncFence;
import ghidra.async.AsyncUtils;
import ghidra.async.TypeSpec;
import ghidra.dbg.AnnotatedDebuggerAttributeListener;
import ghidra.dbg.DebugModelConventions;
import ghidra.dbg.DebuggerModelListener;
import ghidra.dbg.DebuggerObjectModel;
import ghidra.dbg.DebuggerObjectModel.RefreshBehavior;
import ghidra.dbg.error.DebuggerMemoryAccessException;
import ghidra.dbg.target.*;
import ghidra.dbg.target.TargetAccessConditioned;
import ghidra.dbg.target.TargetAttachable;
import ghidra.dbg.target.TargetAttacher;
import ghidra.dbg.target.TargetBreakpointSpec;
import ghidra.dbg.target.TargetBreakpointSpecContainer;
import ghidra.dbg.target.TargetConfigurable;
import ghidra.dbg.target.TargetConsole.Channel;
import ghidra.dbg.target.TargetDetachable;
import ghidra.dbg.target.TargetExecutionStateful;
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
import ghidra.dbg.target.TargetFocusScope;
import ghidra.dbg.target.TargetInterpreter;
import ghidra.dbg.target.TargetInterruptible;
import ghidra.dbg.target.TargetKillable;
import ghidra.dbg.target.TargetLauncher;
import ghidra.dbg.target.TargetMethod;
import ghidra.dbg.target.TargetMethod.ParameterDescription;
import ghidra.dbg.target.TargetMethod.TargetParameterMap;
import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.TargetProcess;
import ghidra.dbg.target.TargetResumable;
import ghidra.dbg.target.TargetSteppable;
import ghidra.dbg.target.TargetSteppable.TargetStepKind;
import ghidra.dbg.target.TargetTogglable;
import ghidra.dbg.util.DebuggerCallbackReorderer;
import ghidra.dbg.util.PathUtils;
import ghidra.framework.model.Project;
import ghidra.framework.options.AutoOptions;
import ghidra.framework.options.SaveState;
import ghidra.framework.options.annotation.AutoOptionDefined;
import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.AutoConfigState;
import ghidra.framework.plugintool.AutoService;
import ghidra.framework.plugintool.ComponentProviderAdapter;
import ghidra.framework.plugintool.annotation.AutoConfigStateField;
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
import ghidra.program.model.address.Address;
@ -79,7 +166,9 @@ import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection;
import ghidra.trace.model.Trace;
import ghidra.trace.model.thread.TraceThread;
import ghidra.util.*;
import ghidra.util.HelpLocation;
import ghidra.util.Msg;
import ghidra.util.Swing;
import ghidra.util.datastruct.PrivatelyQueuedListener;
import ghidra.util.table.GhidraTable;
import ghidra.util.task.TaskMonitor;
@ -1412,7 +1501,15 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter
list.toArray(new String[] {}), lastMethod, OptionDialog.QUESTION_MESSAGE);
if (choice != null) {
TargetMethod method = (TargetMethod) attributes.get(choice);
Map<String, ?> args = methodDialog.promptArguments(method.getParameters());
TargetParameterMap parameters = method.getParameters();
if (parameters.isEmpty()) {
method.invoke(new HashMap<String, Object>());
if (!choice.equals("unload")) {
lastMethod = choice;
}
return;
}
Map<String, ?> args = methodDialog.promptArguments(parameters);
if (args != null) {
String script = (String) args.get("Script");
if (script != null && !script.isEmpty()) {

View File

@ -27,6 +27,7 @@ import ghidra.app.plugin.core.debug.gui.objects.DebuggerObjectsProvider;
import ghidra.app.plugin.core.debug.gui.objects.ObjectContainer;
import ghidra.app.script.AskDialog;
import ghidra.dbg.DebuggerObjectModel;
import ghidra.dbg.DebuggerObjectModel.RefreshBehavior;
import ghidra.dbg.target.TargetObject;
import ghidra.framework.plugintool.PluginTool;
@ -77,7 +78,7 @@ public abstract class DisplayFilteredAction extends DockingAction {
final List<String> path) {
TargetObject to = container.getTargetObject();
DebuggerObjectModel model = to.getModel();
model.fetchModelObject(path, true).thenAccept(obj -> {
model.fetchModelObject(path, RefreshBehavior.REFRESH_ALWAYS).thenAccept(obj -> {
container.setTargetObject(obj);
finishGetOffspring(container, path);
});

View File

@ -353,7 +353,7 @@ public interface DebuggerObjectModel {
* @param refresh true to refresh caches
* @return the found value, or {@code null} if it does not exist
*/
public CompletableFuture<?> fetchModelValue(List<String> path, boolean refresh);
public CompletableFuture<?> fetchModelValue(List<String> path, RefreshBehavior refresh);
/**
* @see #fetchModelValue(List)
@ -406,7 +406,7 @@ public interface DebuggerObjectModel {
* @throws DebuggerModelTypeException if the value at the path is not a {@link TargetObject}
*/
public default CompletableFuture<? extends TargetObject> fetchModelObject(List<String> path,
boolean refresh) {
RefreshBehavior refresh) {
return fetchModelValue(path, refresh).thenApply(v -> {
if (v == null) {
return null;
@ -431,7 +431,7 @@ public interface DebuggerObjectModel {
*/
@Deprecated
public default CompletableFuture<? extends TargetObject> fetchModelObject(List<String> path) {
return fetchModelObject(path, false);
return fetchModelObject(path, RefreshBehavior.REFRESH_NEVER);
}
/**

View File

@ -21,7 +21,6 @@ import java.util.concurrent.CompletableFuture;
import ghidra.async.AsyncUtils;
import ghidra.dbg.DebuggerObjectModel;
import ghidra.dbg.DebuggerObjectModel.RefreshBehavior;
import ghidra.dbg.error.DebuggerModelTypeException;
import ghidra.dbg.target.TargetObject;
import ghidra.dbg.util.PathUtils;
@ -50,17 +49,26 @@ public interface SpiDebuggerObjectModel extends DebuggerObjectModel {
}
public static CompletableFuture<Object> fetchSuccessorValue(TargetObject obj,
List<String> path, boolean refresh, boolean followLinks) {
List<String> path, RefreshBehavior refresh, boolean followLinks) {
if (path.isEmpty()) {
return CompletableFuture.completedFuture(obj);
}
String key = path.get(0);
CompletableFuture<?> futureChild;
if (refresh) {
futureChild = fetchFreshChild(obj, key);
}
else {
futureChild = obj.fetchChild(key);
switch (refresh) {
case REFRESH_ALWAYS:
futureChild = fetchFreshChild(obj, key);
break;
case REFRESH_NEVER:
futureChild = obj.fetchChild(key);
break;
case REFRESH_WHEN_ABSENT:
default:
CompletableFuture<?> futureChild0 = obj.fetchChild(key);
futureChild = futureChild0.thenCompose(c -> {
return c == null ? fetchFreshChild(obj, key) : CompletableFuture.completedFuture(c);
});
break;
}
return futureChild.thenCompose(c -> {
if (c == null) {
@ -91,7 +99,7 @@ public interface SpiDebuggerObjectModel extends DebuggerObjectModel {
}
@Override
public default CompletableFuture<?> fetchModelValue(List<String> path, boolean refresh) {
public default CompletableFuture<?> fetchModelValue(List<String> path, RefreshBehavior refresh) {
return fetchModelRoot().thenCompose(root -> {
return fetchSuccessorValue(root, path, refresh, true);
});
@ -99,7 +107,45 @@ public interface SpiDebuggerObjectModel extends DebuggerObjectModel {
@Override
public default CompletableFuture<?> fetchModelValue(List<String> path) {
return fetchModelValue(path, false);
return fetchModelValue(path, RefreshBehavior.REFRESH_NEVER);
}
public static CompletableFuture<Object> fetchSuccessorValueUsingAvailableCache(TargetObject obj,
List<String> path, boolean followLinks) {
if (path.isEmpty()) {
return CompletableFuture.completedFuture(obj);
}
String key = path.get(0);
CompletableFuture<?> futureChild = obj.fetchChild(key);
CompletableFuture<?> ffutureChild = futureChild.thenCompose(c -> {
return c == null ? fetchFreshChild(obj, key) : CompletableFuture.completedFuture(c);
});
return ffutureChild.thenCompose(c -> {
if (c == null) {
return AsyncUtils.nil();
}
if (!(c instanceof TargetObject)) {
if (path.size() == 1) {
return CompletableFuture.completedFuture(c);
}
else {
List<String> p = PathUtils.extend(obj.getPath(), key);
throw DebuggerModelTypeException.typeRequired(c, p, TargetObject.class);
}
}
TargetObject child = (TargetObject) c;
if (PathUtils.isLink(obj.getPath(), key, child.getPath()) && !followLinks) {
if (path.size() == 1) {
return CompletableFuture.completedFuture(c);
}
else {
List<String> p = PathUtils.extend(obj.getPath(), key);
throw DebuggerModelTypeException.linkForbidden(child, p);
}
}
List<String> remains = path.subList(1, path.size());
return fetchSuccessorValueUsingAvailableCache(child, remains, followLinks);
});
}
@Override