diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugProcessId.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugProcessId.java index 53dd553282..705edbe095 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugProcessId.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugProcessId.java @@ -26,15 +26,15 @@ package agent.dbgeng.dbgeng; * PIDs. */ public class DebugProcessId implements Comparable { - public final int id; + public final long id; - public DebugProcessId(int id) { + public DebugProcessId(long id) { this.id = id; } @Override public int hashCode() { - return Integer.hashCode(id); + return Long.hashCode(id); } @Override @@ -51,7 +51,7 @@ public class DebugProcessId implements Comparable { @Override public int compareTo(DebugProcessId that) { - return Integer.compare(this.id, that.id); + return Long.compare(this.id, that.id); } @Override diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugSystemObjects.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugSystemObjects.java index 9accb9cbc3..dd5b5232bd 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugSystemObjects.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugSystemObjects.java @@ -99,4 +99,16 @@ public interface DebugSystemObjects { DebugProcessId getProcessIdBySystemId(int systemId); + long getCurrentThreadDataOffset(); + + long getCurrentProcessDataOffset(); + + long getImplicitThreadDataOffset(); + + long getImplicitProcessDataOffset(); + + void setImplicitThreadDataOffset(long systemOffset); + + void setImplicitProcessDataOffset(long systemOffset); + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugThreadId.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugThreadId.java index f9799bcc14..d1b9e2b943 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugThreadId.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugThreadId.java @@ -26,15 +26,15 @@ package agent.dbgeng.dbgeng; * TIDs. */ public class DebugThreadId implements Comparable { - public final int id; + public final long id; - public DebugThreadId(int id) { + public DebugThreadId(long id) { this.id = id; } @Override public int hashCode() { - return Integer.hashCode(id); + return Long.hashCode(id); } @Override @@ -51,7 +51,7 @@ public class DebugThreadId implements Comparable { @Override public int compareTo(DebugThreadId that) { - return Integer.compare(this.id, that.id); + return Long.compare(this.id, that.id); } @Override diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/sysobj/DebugSystemObjectsImpl1.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/sysobj/DebugSystemObjectsImpl1.java index 88b98a2b35..b27094d5b9 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/sysobj/DebugSystemObjectsImpl1.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/sysobj/DebugSystemObjectsImpl1.java @@ -228,6 +228,28 @@ public class DebugSystemObjectsImpl1 implements DebugSystemObjectsInternal { return pulSysId.getValue().intValue(); } + @Override + public long getCurrentThreadDataOffset() { + ULONGLONGByReference pulSysOffset = new ULONGLONGByReference(); + HRESULT hr = jnaSysobj.GetCurrentThreadDataOffset(pulSysOffset); + if (hr.equals(COMUtilsExtra.E_UNEXPECTED) || hr.equals(COMUtilsExtra.E_NOTIMPLEMENTED)) { + return -1; + } + COMUtils.checkRC(hr); + return pulSysOffset.getValue().longValue(); + } + + @Override + public long getCurrentProcessDataOffset() { + ULONGLONGByReference pulSysOffset = new ULONGLONGByReference(); + HRESULT hr = jnaSysobj.GetCurrentProcessDataOffset(pulSysOffset); + if (hr.equals(COMUtilsExtra.E_UNEXPECTED) || hr.equals(COMUtilsExtra.E_NOTIMPLEMENTED)) { + return -1; + } + COMUtils.checkRC(hr); + return pulSysOffset.getValue().longValue(); + } + @Override public DebugSessionId getEventSystem() { throw new UnsupportedOperationException("Not supported by this interface"); @@ -252,4 +274,26 @@ public class DebugSystemObjectsImpl1 implements DebugSystemObjectsInternal { public List getSystems(int start, int count) { throw new UnsupportedOperationException("Not supported by this interface"); } + + @Override + public long getImplicitThreadDataOffset() { + throw new UnsupportedOperationException("Not supported by this interface"); + } + + @Override + public long getImplicitProcessDataOffset() { + throw new UnsupportedOperationException("Not supported by this interface"); + } + + @Override + public void setImplicitThreadDataOffset(long offset) { + throw new UnsupportedOperationException("Not supported by this interface"); + } + + @Override + public void setImplicitProcessDataOffset(long offset) { + throw new UnsupportedOperationException("Not supported by this interface"); + } + + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/sysobj/DebugSystemObjectsImpl2.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/sysobj/DebugSystemObjectsImpl2.java index f4bf16593d..251f47eafd 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/sysobj/DebugSystemObjectsImpl2.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/sysobj/DebugSystemObjectsImpl2.java @@ -15,6 +15,12 @@ */ package agent.dbgeng.impl.dbgeng.sysobj; +import com.sun.jna.platform.win32.COM.COMUtils; +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 agent.dbgeng.dbgeng.COMUtilsExtra; import agent.dbgeng.jna.dbgeng.sysobj.IDebugSystemObjects2; public class DebugSystemObjectsImpl2 extends DebugSystemObjectsImpl1 { @@ -25,4 +31,45 @@ public class DebugSystemObjectsImpl2 extends DebugSystemObjectsImpl1 { super(jnaSysobj); this.jnaSysobj = jnaSysobj; } + + public long getImplicitThreadDataOffset() { + ULONGLONGByReference pulSysOffset = new ULONGLONGByReference(); + HRESULT hr = jnaSysobj.GetImplicitThreadDataOffset(pulSysOffset); + if (hr.equals(COMUtilsExtra.E_UNEXPECTED) || hr.equals(COMUtilsExtra.E_NOTIMPLEMENTED)) { + return -1; + } + COMUtils.checkRC(hr); + return pulSysOffset.getValue().longValue(); + } + + @Override + public long getImplicitProcessDataOffset() { + ULONGLONGByReference pulSysOffset = new ULONGLONGByReference(); + HRESULT hr = jnaSysobj.GetImplicitProcessDataOffset(pulSysOffset); + if (hr.equals(COMUtilsExtra.E_UNEXPECTED) || hr.equals(COMUtilsExtra.E_NOTIMPLEMENTED)) { + return -1; + } + COMUtils.checkRC(hr); + return pulSysOffset.getValue().longValue(); + } + + public void setImplicitThreadDataOffset(long offset) { + ULONGLONG ulSysOffset = new ULONGLONG(offset); + HRESULT hr = jnaSysobj.SetImplicitThreadDataOffset(ulSysOffset); + if (hr.equals(COMUtilsExtra.E_UNEXPECTED) || hr.equals(COMUtilsExtra.E_NOTIMPLEMENTED)) { + return; + } + COMUtils.checkRC(hr); + } + + @Override + public void setImplicitProcessDataOffset(long offset) { + ULONGLONG ulSysOffset = new ULONGLONG(offset); + HRESULT hr = jnaSysobj.SetImplicitProcessDataOffset(ulSysOffset); + if (hr.equals(COMUtilsExtra.E_UNEXPECTED) || hr.equals(COMUtilsExtra.E_NOTIMPLEMENTED)) { + return; + } + COMUtils.checkRC(hr); + } + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/sysobj/IDebugSystemObjects.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/sysobj/IDebugSystemObjects.java index 9cb2940f16..bcd5bfd64b 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/sysobj/IDebugSystemObjects.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/sysobj/IDebugSystemObjects.java @@ -98,4 +98,9 @@ public interface IDebugSystemObjects extends IUnknown { HRESULT GetThreadIdBySystemId(ULONG SystemId, ULONGByReference Id); HRESULT GetProcessIdBySystemId(ULONG SystemId, ULONGByReference Id); + + HRESULT GetCurrentThreadDataOffset(ULONGLONGByReference SysOffset); + + HRESULT GetCurrentProcessDataOffset(ULONGLONGByReference SysOffset); + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/sysobj/IDebugSystemObjects2.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/sysobj/IDebugSystemObjects2.java index 2a1fdfe3c8..8866b85115 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/sysobj/IDebugSystemObjects2.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/sysobj/IDebugSystemObjects2.java @@ -16,6 +16,9 @@ package agent.dbgeng.jna.dbgeng.sysobj; import com.sun.jna.platform.win32.Guid.IID; +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 agent.dbgeng.jna.dbgeng.UnknownWithUtils.VTableIndex; @@ -37,4 +40,13 @@ public interface IDebugSystemObjects2 extends IDebugSystemObjects { return this.ordinal() + start; } } + + HRESULT GetImplicitThreadDataOffset(ULONGLONGByReference SysOffset); + + HRESULT GetImplicitProcessDataOffset(ULONGLONGByReference SysOffset); + + HRESULT SetImplicitThreadDataOffset(ULONGLONG SysOffset); + + HRESULT SetImplicitProcessDataOffset(ULONGLONG SysOffset); + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/sysobj/WrapIDebugSystemObjects.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/sysobj/WrapIDebugSystemObjects.java index a550266dac..7784216623 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/sysobj/WrapIDebugSystemObjects.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/sysobj/WrapIDebugSystemObjects.java @@ -21,6 +21,7 @@ import com.sun.jna.platform.win32.WinDef.*; import com.sun.jna.platform.win32.WinNT.HRESULT; import agent.dbgeng.jna.dbgeng.UnknownWithUtils; +import agent.dbgeng.jna.dbgeng.sysobj.IDebugSystemObjects2.VTIndices2; public class WrapIDebugSystemObjects extends UnknownWithUtils implements IDebugSystemObjects { public static class ByReference extends WrapIDebugSystemObjects @@ -120,4 +121,15 @@ public class WrapIDebugSystemObjects extends UnknownWithUtils implements IDebugS public HRESULT GetCurrentProcessSystemId(ULONGByReference SysId) { return _invokeHR(VTIndices.GET_CURRENT_PROCESS_SYSTEM_ID, getPointer(), SysId); } + + @Override + public HRESULT GetCurrentThreadDataOffset(ULONGLONGByReference SysOffset) { + return _invokeHR(VTIndices.GET_CURRENT_THREAD_DATA_OFFSET, getPointer(), SysOffset); + } + + @Override + public HRESULT GetCurrentProcessDataOffset(ULONGLONGByReference SysOffset) { + return _invokeHR(VTIndices.GET_CURRENT_PROCESS_DATA_OFFSET, getPointer(), SysOffset); + } + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/sysobj/WrapIDebugSystemObjects2.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/sysobj/WrapIDebugSystemObjects2.java index 163bfaeadb..d8d1d7097c 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/sysobj/WrapIDebugSystemObjects2.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/sysobj/WrapIDebugSystemObjects2.java @@ -17,6 +17,11 @@ package agent.dbgeng.jna.dbgeng.sysobj; import com.sun.jna.Pointer; import com.sun.jna.Structure; +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 agent.dbgeng.jna.dbgeng.sysobj.IDebugSystemObjects2.VTIndices2; public class WrapIDebugSystemObjects2 extends WrapIDebugSystemObjects implements IDebugSystemObjects2 { @@ -30,4 +35,25 @@ public class WrapIDebugSystemObjects2 extends WrapIDebugSystemObjects public WrapIDebugSystemObjects2(Pointer pvInstance) { super(pvInstance); } + + @Override + public HRESULT GetImplicitThreadDataOffset(ULONGLONGByReference SysOffset) { + return _invokeHR(VTIndices2.GET_IMPLICIT_THREAD_DATA_OFFSET, getPointer(), SysOffset); + } + + @Override + public HRESULT GetImplicitProcessDataOffset(ULONGLONGByReference SysOffset) { + return _invokeHR(VTIndices2.GET_IMPLICIT_PROCESS_DATA_OFFSET, getPointer(), SysOffset); + } + + @Override + public HRESULT SetImplicitThreadDataOffset(ULONGLONG SysOffset) { + return _invokeHR(VTIndices2.SET_IMPLICIT_THREAD_DATA_OFFSET, getPointer(), SysOffset); + } + + @Override + public HRESULT SetImplicitProcessDataOffset(ULONGLONG SysOffset) { + return _invokeHR(VTIndices2.SET_IMPLICIT_PROCESS_DATA_OFFSET, getPointer(), SysOffset); + } + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgThread.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgThread.java index 9981b436d9..ae20f29ee9 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgThread.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgThread.java @@ -163,4 +163,4 @@ public interface DbgThread */ Machine getExecutingProcessorType(); -} +} \ No newline at end of file diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgAttachKernelCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgAttachKernelCommand.java index e0a5fabd08..b83912d0f4 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgAttachKernelCommand.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgAttachKernelCommand.java @@ -22,6 +22,7 @@ import agent.dbgeng.manager.*; import agent.dbgeng.manager.evt.AbstractDbgCompletedCommandEvent; import agent.dbgeng.manager.evt.DbgProcessCreatedEvent; import agent.dbgeng.manager.impl.DbgManagerImpl; +import ghidra.util.Msg; /** * Implementation of {@link DbgProcess#fileExecAndSymbols(String)} @@ -59,6 +60,9 @@ public class DbgAttachKernelCommand extends AbstractDbgCommand { @Override public void invoke() { + if (!System.getenv().containsKey("_NT_SYMBOL_PATH")) { + Msg.warn(this, "_NT_SYMBOL_PATH is undefined - you may need to define it or run .sympath"); + } DebugClient dbgeng = manager.getClient(); long flags = (Long) args.get("Flags"); String options = (String) args.get("Options"); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetActiveProcessCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetActiveProcessCommand.java index 62d3f0cc36..e8162e18b8 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetActiveProcessCommand.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetActiveProcessCommand.java @@ -15,14 +15,22 @@ */ package agent.dbgeng.manager.cmd; +import java.math.BigInteger; + +import agent.dbgeng.dbgeng.DebugControl; import agent.dbgeng.dbgeng.DebugProcessId; import agent.dbgeng.dbgeng.DebugSystemObjects; +import agent.dbgeng.manager.DbgEvent; import agent.dbgeng.manager.DbgProcess; +import agent.dbgeng.manager.evt.AbstractDbgCompletedCommandEvent; +import agent.dbgeng.manager.evt.DbgConsoleOutputEvent; import agent.dbgeng.manager.impl.DbgManagerImpl; +import agent.dbgeng.manager.impl.DbgProcessImpl; public class DbgSetActiveProcessCommand extends AbstractDbgCommand { - private DbgProcess process; + private DbgProcessImpl process; + private Long offset; /** * Set the active process @@ -32,7 +40,47 @@ public class DbgSetActiveProcessCommand extends AbstractDbgCommand { */ public DbgSetActiveProcessCommand(DbgManagerImpl manager, DbgProcess process) { super(manager); - this.process = process; + this.process = (DbgProcessImpl) process; + } + + @Override + public boolean handle(DbgEvent evt, DbgPendingCommand pending) { + if (evt instanceof AbstractDbgCompletedCommandEvent && pending.getCommand().equals(this)) { + return true; + } + else if (evt instanceof DbgConsoleOutputEvent) { + pending.steal(evt); + } + return false; + } + + @Override + public Void complete(DbgPendingCommand pending) { + StringBuilder builder = new StringBuilder(); + for (DbgConsoleOutputEvent out : pending.findAllOf(DbgConsoleOutputEvent.class)) { + builder.append(out.getOutput()); + } + parse(builder.toString()); + if (offset != null) { + manager.getSystemObjects().setImplicitThreadDataOffset(offset); + } + return null; + } + + private void parse(String result) { + String[] lines = result.split("\n"); + for (int i = 0; i < lines.length; i++) { + String line = lines[i]; + if (line.contains("PROCESS")) { + String[] fields = line.trim().split("\\s+"); + if (fields.length > 1 && fields[0].equals("PROCESS")) { + BigInteger val = new BigInteger(fields[1], 16); + offset = val.longValue(); + process.setOffset(offset); + } + break; + } + } } @Override @@ -41,9 +89,19 @@ public class DbgSetActiveProcessCommand extends AbstractDbgCommand { DebugProcessId id = process.getId(); if (id != null) { DebugSystemObjects so = manager.getSystemObjects(); - DebugProcessId currentProcessId = so.getCurrentProcessId(); - if (id.id != currentProcessId.id) { + if (manager.isKernelMode()) { + offset = process.getOffset(); + if (offset == null || offset == 0L) { + DebugControl control = manager.getControl(); + control.execute("!process "+Long.toHexString(process.getPid())); + } + } + else { so.setCurrentProcessId(id); + DebugProcessId currentProcessId = so.getCurrentProcessId(); + if (id.id != currentProcessId.id) { + so.setCurrentProcessId(id); + } } } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetActiveThreadCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetActiveThreadCommand.java index e9455a1148..2ce79ca96c 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetActiveThreadCommand.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetActiveThreadCommand.java @@ -15,14 +15,22 @@ */ package agent.dbgeng.manager.cmd; +import java.math.BigInteger; + +import agent.dbgeng.dbgeng.DebugControl; import agent.dbgeng.dbgeng.DebugThreadId; +import agent.dbgeng.manager.DbgEvent; import agent.dbgeng.manager.DbgThread; +import agent.dbgeng.manager.evt.AbstractDbgCompletedCommandEvent; +import agent.dbgeng.manager.evt.DbgConsoleOutputEvent; import agent.dbgeng.manager.impl.DbgManagerImpl; +import agent.dbgeng.manager.impl.DbgThreadImpl; public class DbgSetActiveThreadCommand extends AbstractDbgCommand { - private DbgThread thread; + private DbgThreadImpl thread; private Integer frameId; + private Long offset; /** * Set the active thread @@ -33,15 +41,64 @@ public class DbgSetActiveThreadCommand extends AbstractDbgCommand { */ public DbgSetActiveThreadCommand(DbgManagerImpl manager, DbgThread thread, Integer frameId) { super(manager); - this.thread = thread; + this.thread = (DbgThreadImpl) thread; this.frameId = frameId; } + @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 Void complete(DbgPendingCommand pending) { + StringBuilder builder = new StringBuilder(); + for (DbgConsoleOutputEvent out : pending.findAllOf(DbgConsoleOutputEvent.class)) { + builder.append(out.getOutput()); + } + parse(builder.toString()); + if (offset != null) { + manager.getSystemObjects().setImplicitThreadDataOffset(offset); + } + return null; + } + + private void parse(String result) { + String[] lines = result.split("\n"); + for (int i = 0; i < lines.length; i++) { + String line = lines[i]; + if (line.contains("THREAD")) { + String[] fields = line.trim().split("\\s+"); + if (fields.length > 1 && fields[0].equals("THREAD")) { + BigInteger val = new BigInteger(fields[1], 16); + offset = val.longValue(); + thread.setOffset(offset); + } + break; + } + } + } + @Override public void invoke() { DebugThreadId id = thread.getId(); if (id != null) { - manager.getSystemObjects().setCurrentThreadId(id); + if (!manager.isKernelMode()) { + manager.getSystemObjects().setCurrentThreadId(id); + } + else { + offset = thread.getOffset(); + if (offset == null || offset == 0L) { + DebugControl control = manager.getControl(); + control.execute("!thread -t "+Long.toHexString(thread.getTid())); + } + } if (frameId != null) { manager.getSymbols().setCurrentScopeFrameIndex(frameId); } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetCurrentState.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetCurrentState.java new file mode 100644 index 0000000000..7ce45f5d66 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetCurrentState.java @@ -0,0 +1,102 @@ +/* ### + * IP: GHIDRA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package agent.dbgeng.manager.cmd; + +import agent.dbgeng.dbgeng.DebugControl; +import agent.dbgeng.dbgeng.DebugProcessId; +import agent.dbgeng.dbgeng.DebugSystemObjects; +import agent.dbgeng.dbgeng.DebugThreadId; +import agent.dbgeng.manager.DbgEvent; +import agent.dbgeng.manager.DbgThread; +import agent.dbgeng.manager.evt.AbstractDbgCompletedCommandEvent; +import agent.dbgeng.manager.evt.DbgConsoleOutputEvent; +import agent.dbgeng.manager.impl.DbgManagerImpl; +import agent.dbgeng.manager.impl.DbgProcessImpl; +import agent.dbgeng.manager.impl.DbgThreadImpl; +import ghidra.util.Msg; + +public class DbgSetCurrentState extends AbstractDbgCommand { + + private long pid; + private long tid; + private DebugProcessId pID; + private DebugThreadId tID; + + public DbgSetCurrentState(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 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; + } + + private void parse(String result) { + String[] lines = result.split("\n"); + for (int i = 0; i < lines.length; i++) { + String line = lines[i]; + if (line.contains("THREAD")) { + String[] fields = line.trim().split("\\s+"); + if (fields.length > 3 && fields[2].equals("Cid")) { + 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); + } + } + break; + } + } + } + + @Override + public void invoke() { + DebugControl control = manager.getControl(); + control.execute("!thread"); + } + +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgManagerImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgManagerImpl.java index ffbce86d07..3e5f31a431 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgManagerImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgManagerImpl.java @@ -15,9 +15,20 @@ */ package agent.dbgeng.manager.impl; -import static ghidra.async.AsyncUtils.*; +import static ghidra.async.AsyncUtils.sequence; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.NavigableMap; +import java.util.Objects; +import java.util.Set; +import java.util.TreeMap; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; @@ -26,31 +37,114 @@ import org.apache.commons.lang3.tuple.Pair; import com.sun.jna.platform.win32.COM.COMException; -import agent.dbgeng.dbgeng.*; +import agent.dbgeng.dbgeng.DbgEng; +import agent.dbgeng.dbgeng.DebugAdvanced; +import agent.dbgeng.dbgeng.DebugBreakpoint; import agent.dbgeng.dbgeng.DebugBreakpoint.BreakFlags; import agent.dbgeng.dbgeng.DebugBreakpoint.BreakType; -import agent.dbgeng.dbgeng.DebugClient.*; +import agent.dbgeng.dbgeng.DebugClient; +import agent.dbgeng.dbgeng.DebugClient.ChangeDebuggeeState; +import agent.dbgeng.dbgeng.DebugClient.ChangeEngineState; +import agent.dbgeng.dbgeng.DebugClient.DebugCreateFlags; +import agent.dbgeng.dbgeng.DebugClient.DebugEndSessionFlags; +import agent.dbgeng.dbgeng.DebugClient.DebugEngCreateFlags; +import agent.dbgeng.dbgeng.DebugClient.DebugStatus; +import agent.dbgeng.dbgeng.DebugClient.DebugVerifierFlags; +import agent.dbgeng.dbgeng.DebugClient.ExecutionState; +import agent.dbgeng.dbgeng.DebugClientReentrant; +import agent.dbgeng.dbgeng.DebugControl; import agent.dbgeng.dbgeng.DebugControl.DebugInterrupt; +import agent.dbgeng.dbgeng.DebugDataSpaces; +import agent.dbgeng.dbgeng.DebugEventInformation; +import agent.dbgeng.dbgeng.DebugExceptionRecord64; +import agent.dbgeng.dbgeng.DebugModuleInfo; +import agent.dbgeng.dbgeng.DebugProcessId; +import agent.dbgeng.dbgeng.DebugProcessInfo; +import agent.dbgeng.dbgeng.DebugRegisters; +import agent.dbgeng.dbgeng.DebugSessionId; +import agent.dbgeng.dbgeng.DebugSymbols; +import agent.dbgeng.dbgeng.DebugSystemObjects; +import agent.dbgeng.dbgeng.DebugThreadId; +import agent.dbgeng.dbgeng.DebugThreadInfo; import agent.dbgeng.gadp.impl.AbstractClientThreadExecutor; import agent.dbgeng.gadp.impl.DbgEngClientThreadExecutor; import agent.dbgeng.impl.dbgeng.DbgEngUtil; import agent.dbgeng.jna.dbgeng.WinNTExtra; -import agent.dbgeng.manager.*; +import agent.dbgeng.manager.DbgCause; import agent.dbgeng.manager.DbgCause.Causes; +import agent.dbgeng.manager.DbgCommand; +import agent.dbgeng.manager.DbgEvent; +import agent.dbgeng.manager.DbgEventsListener; +import agent.dbgeng.manager.DbgManager; +import agent.dbgeng.manager.DbgModuleMemory; +import agent.dbgeng.manager.DbgProcess; +import agent.dbgeng.manager.DbgSession; +import agent.dbgeng.manager.DbgState; +import agent.dbgeng.manager.DbgStateListener; +import agent.dbgeng.manager.DbgThread; import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo; import agent.dbgeng.manager.breakpoint.DbgBreakpointType; -import agent.dbgeng.manager.cmd.*; -import agent.dbgeng.manager.evt.*; +import agent.dbgeng.manager.cmd.DbgAddProcessCommand; +import agent.dbgeng.manager.cmd.DbgAddSessionCommand; +import agent.dbgeng.manager.cmd.DbgAttachKernelCommand; +import agent.dbgeng.manager.cmd.DbgCommandError; +import agent.dbgeng.manager.cmd.DbgConsoleExecCommand; +import agent.dbgeng.manager.cmd.DbgDeleteBreakpointsCommand; +import agent.dbgeng.manager.cmd.DbgDisableBreakpointsCommand; +import agent.dbgeng.manager.cmd.DbgEnableBreakpointsCommand; +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.DbgListProcessesCommand; +import agent.dbgeng.manager.cmd.DbgOpenDumpCommand; +import agent.dbgeng.manager.cmd.DbgPendingCommand; +import agent.dbgeng.manager.cmd.DbgRemoveProcessCommand; +import agent.dbgeng.manager.cmd.DbgRemoveSessionCommand; +import agent.dbgeng.manager.cmd.DbgRequestActivationCommand; +import agent.dbgeng.manager.cmd.DbgRequestFocusCommand; +import agent.dbgeng.manager.cmd.DbgSetActiveProcessCommand; +import agent.dbgeng.manager.cmd.DbgSetActiveSessionCommand; +import agent.dbgeng.manager.cmd.DbgSetActiveThreadCommand; +import agent.dbgeng.manager.cmd.DbgSetCurrentState; +import agent.dbgeng.manager.evt.AbstractDbgEvent; +import agent.dbgeng.manager.evt.DbgBreakpointCreatedEvent; +import agent.dbgeng.manager.evt.DbgBreakpointDeletedEvent; +import agent.dbgeng.manager.evt.DbgBreakpointEvent; +import agent.dbgeng.manager.evt.DbgBreakpointModifiedEvent; +import agent.dbgeng.manager.evt.DbgCommandDoneEvent; +import agent.dbgeng.manager.evt.DbgConsoleOutputEvent; +import agent.dbgeng.manager.evt.DbgDebuggeeStateChangeEvent; +import agent.dbgeng.manager.evt.DbgExceptionEvent; +import agent.dbgeng.manager.evt.DbgModuleLoadedEvent; +import agent.dbgeng.manager.evt.DbgModuleUnloadedEvent; +import agent.dbgeng.manager.evt.DbgProcessCreatedEvent; +import agent.dbgeng.manager.evt.DbgProcessExitedEvent; +import agent.dbgeng.manager.evt.DbgProcessSelectedEvent; +import agent.dbgeng.manager.evt.DbgPromptChangedEvent; +import agent.dbgeng.manager.evt.DbgRunningEvent; +import agent.dbgeng.manager.evt.DbgSessionSelectedEvent; +import agent.dbgeng.manager.evt.DbgStateChangedEvent; +import agent.dbgeng.manager.evt.DbgStoppedEvent; +import agent.dbgeng.manager.evt.DbgSystemErrorEvent; +import agent.dbgeng.manager.evt.DbgSystemsEvent; +import agent.dbgeng.manager.evt.DbgThreadCreatedEvent; +import agent.dbgeng.manager.evt.DbgThreadExitedEvent; +import agent.dbgeng.manager.evt.DbgThreadSelectedEvent; import agent.dbgeng.model.iface1.DbgModelTargetActiveScope; import agent.dbgeng.model.iface1.DbgModelTargetFocusScope; import agent.dbgeng.model.iface2.DbgModelTargetObject; import agent.dbgeng.model.iface2.DbgModelTargetThread; -import ghidra.async.*; +import ghidra.async.AsyncClaimQueue; +import ghidra.async.AsyncReference; +import ghidra.async.AsyncUtils; +import ghidra.async.TypeSpec; import ghidra.comm.util.BitmaskSet; 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; @@ -141,8 +235,19 @@ 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, - int tid, boolean fire) { + long tid, boolean fire) { synchronized (threads) { if (threads.containsKey(id)) { DbgThreadImpl existingThread = threads.get(id); @@ -220,7 +325,18 @@ public class DbgManagerImpl implements DbgManager { } } - public DbgProcessImpl getProcessComputeIfAbsent(DebugProcessId id, int pid, boolean fire) { + public DbgProcessImpl getProcessComputeIfAbsent(String key, boolean fire) { + String index = PathUtils.parseIndex(key); + Integer pid = Integer.decode(index); + DebugProcessId id = getSystemObjects().getProcessIdBySystemId(pid); + if (id == null) { + id = new DebugProcessId(pid); + return getProcessComputeIfAbsent(id, pid, fire); + } + return getProcessComputeIfAbsent(id, pid, fire); + } + + public DbgProcessImpl getProcessComputeIfAbsent(DebugProcessId id, long pid, boolean fire) { synchronized (processes) { if (processes.containsKey(id)) { DbgProcessImpl existingProc = processes.get(id); @@ -642,7 +758,7 @@ public class DbgManagerImpl implements DbgManager { DebugThreadId etid = so.getEventThread(); DebugProcessId epid = so.getEventProcess(); DebugSessionId esid = so.getCurrentSystemId(); - + DebugControl control = dbgeng.getControl(); int execType = WinNTExtra.Machine.IMAGE_FILE_MACHINE_AMD64.val; try { @@ -657,15 +773,11 @@ public class DbgManagerImpl implements DbgManager { lastEventInformation = control.getLastEventInformation(); lastEventInformation.setSession(esid); lastEventInformation.setExecutingProcessorType(execType); - currentSession = eventSession = getSessionComputeIfAbsent(esid, true); - currentProcess = - eventProcess = getProcessComputeIfAbsent(epid, so.getCurrentProcessSystemId(), true); - currentThread = eventThread = getThreadComputeIfAbsent(etid, (DbgProcessImpl) eventProcess, - so.getCurrentThreadSystemId(), false); + updateStateFromSystemObject(etid, epid, esid); if (eventThread != null) { ((DbgThreadImpl) eventThread).setInfo(lastEventInformation); } - return etid; + return currentThread.getId(); } /** @@ -710,7 +822,6 @@ public class DbgManagerImpl implements DbgManager { * @return retval handling/break status */ protected DebugStatus processException(DbgExceptionEvent evt, Void v) { - DebugThreadId eventId = updateState(); getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.threadSelected(eventThread, null, evt.getCause()); @@ -730,18 +841,15 @@ public class DbgManagerImpl implements DbgManager { * @return retval handling/break status */ protected DebugStatus processThreadCreated(DbgThreadCreatedEvent evt, Void v) { - DebugClient dbgeng = engThread.getClient(); - DebugSystemObjects so = dbgeng.getSystemObjects(); - DebugThreadId eventId = updateState(); DbgProcessImpl process = getCurrentProcess(); - int tid = so.getCurrentThreadSystemId(); - DbgThreadImpl thread = getThreadComputeIfAbsent(eventId, process, tid, true); + DbgThreadImpl thread = getThreadFromDebugProcessInfo(process, evt.getInfo()); + getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.threadCreated(thread, DbgCause.Causes.UNCLAIMED); getEventListeners().fire.threadSelected(thread, null, evt.getCause()); - String key = Integer.toHexString(eventId.id); + String key = Long.toHexString(eventId.id); if (statusByNameMap.containsKey(key)) { return statusByNameMap.get(key); } @@ -766,7 +874,7 @@ public class DbgManagerImpl implements DbgManager { getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.threadExited(eventId, process, evt.getCause()); - String key = Integer.toHexString(eventId.id); + String key = Long.toHexString(eventId.id); if (statusByNameMap.containsKey(key)) { return statusByNameMap.get(key); } @@ -787,7 +895,7 @@ public class DbgManagerImpl implements DbgManager { currentThread.setState(evt.getState(), evt.getCause(), evt.getReason()); getEventListeners().fire.threadSelected(currentThread, evt.getFrame(), evt.getCause()); - String key = Integer.toHexString(eventId.id); + String key = Long.toHexString(eventId.id); if (statusByNameMap.containsKey(key)) { return statusByNameMap.get(key); } @@ -802,31 +910,20 @@ public class DbgManagerImpl implements DbgManager { * @return retval handling/break status */ protected DebugStatus processProcessCreated(DbgProcessCreatedEvent evt, Void v) { - DebugThreadId eventId = updateState(); - DebugClient dbgeng = engThread.getClient(); - DebugSystemObjects so = dbgeng.getSystemObjects(); - DebugProcessInfo info = evt.getInfo(); - long handle = info.handle; - DebugProcessId id = so.getProcessIdByHandle(handle); - //so.setCurrentProcessId(id); - int pid = so.getCurrentProcessSystemId(); - DbgProcessImpl proc = getProcessComputeIfAbsent(id, pid, true); + DbgProcessImpl proc = getProcessFromDebugProcessInfo(info); getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.processAdded(proc, evt.getCause()); getEventListeners().fire.processSelected(proc, evt.getCause()); - handle = info.initialThreadInfo.handle; - DebugThreadId idt = so.getThreadIdByHandle(handle); - int tid = so.getCurrentThreadSystemId(); - getThreadComputeIfAbsent(idt, proc, tid, true); + getThreadFromDebugProcessInfo(proc, info.initialThreadInfo); //getEventListeners().fire.threadCreated(thread, evt.getCause()); //getEventListeners().fire.threadSelected(thread, null, evt.getCause()); //proc.moduleLoaded(info.moduleInfo); //getEventListeners().fire.moduleLoaded(proc, info.moduleInfo, evt.getCause()); - String key = Integer.toHexString(id.id); + String key = Long.toHexString(proc.getId().id); if (statusByNameMap.containsKey(key)) { return statusByNameMap.get(key); } @@ -859,7 +956,7 @@ public class DbgManagerImpl implements DbgManager { process.remove(evt.getCause()); getEventListeners().fire.processRemoved(process.getId(), evt.getCause()); - String key = Integer.toHexString(process.getId().id); + String key = Long.toHexString(process.getId().id); if (statusByNameMap.containsKey(key)) { return statusByNameMap.get(key); } @@ -879,7 +976,7 @@ public class DbgManagerImpl implements DbgManager { currentProcess = evt.getProcess(); getEventListeners().fire.processSelected(currentProcess, evt.getCause()); - String key = Integer.toHexString(eventId.id); + String key = Long.toHexString(eventId.id); if (statusByNameMap.containsKey(key)) { return statusByNameMap.get(key); } @@ -1036,7 +1133,7 @@ public class DbgManagerImpl implements DbgManager { currentSession = evt.getSession(); getEventListeners().fire.sessionSelected(currentSession, evt.getCause()); - String key = Integer.toHexString(eventId.id); + String key = Long.toHexString(eventId.id); if (statusByNameMap.containsKey(key)) { return statusByNameMap.get(key); } @@ -1063,7 +1160,7 @@ public class DbgManagerImpl implements DbgManager { } DebugProcessId id = new DebugProcessId(info.intValue()); - String key = Integer.toHexString(id.id); + String key = Long.toHexString(id.id); if (statusByNameMap.containsKey(key)) { return statusByNameMap.get(key); } @@ -1553,12 +1650,18 @@ public class DbgManagerImpl implements DbgManager { } public CompletableFuture setActiveThread(DbgThread thread) { + if (thread == null) { + return CompletableFuture.completedFuture(null); + } currentThread = thread; currentProcess = thread.getProcess(); return execute(new DbgSetActiveThreadCommand(this, thread, null)); } public CompletableFuture setActiveProcess(DbgProcess process) { + if (process == null) { + return CompletableFuture.completedFuture(null); + } currentProcess = process; return execute(new DbgSetActiveProcessCommand(this, process)); } @@ -1683,4 +1786,63 @@ public class DbgManagerImpl implements DbgManager { public long getProcessCount() { return processCount; } + + public DebugThreadId getThreadIdBySystemId(Integer tid) { + return getSystemObjects().getThreadIdBySystemId(tid); + } + + public DebugProcessId getProcessIdBySystemId(Integer pid) { + return getSystemObjects().getProcessIdBySystemId(pid); + } + + private DbgProcessImpl getProcessFromDebugProcessInfo(DebugProcessInfo info) { + DebugSystemObjects so = getSystemObjects(); + DebugProcessId id = so.getProcessIdByHandle(info.handle); + if (kernelMode) { +// try { +// return (DbgProcessImpl) execute(new DbgSetCurrentState(this)).get().getProcess(); +// } catch (Exception e) { +// e.printStackTrace(); +// return null; +// } + return null; + } else { + int pid = so.getCurrentProcessSystemId(); + return getProcessComputeIfAbsent(id, pid, true); + } + } + + private DbgThreadImpl getThreadFromDebugProcessInfo(DbgProcessImpl proc, DebugThreadInfo info) { + DebugSystemObjects so = getSystemObjects(); + DebugThreadId id = so.getThreadIdByHandle(info.handle); + if (kernelMode) { +// try { +// return (DbgThreadImpl) execute(new DbgSetCurrentState(this)).get(); +// } catch (Exception e) { +// e.printStackTrace(); +// return null; +// } + return null; + } else { + int pid = so.getCurrentThreadSystemId(); + return getThreadComputeIfAbsent(id, proc, pid, true); + } + } + + private void updateStateFromSystemObject(DebugThreadId etid, DebugProcessId epid, DebugSessionId esid) { + DebugSystemObjects so = getSystemObjects(); + currentSession = eventSession = getSessionComputeIfAbsent(esid, true); + if (kernelMode) { + execute(new DbgSetCurrentState(this)).thenAccept(thread -> { + currentThread = eventThread = thread; + currentProcess = eventProcess = thread.getProcess(); + }); + } else { + currentProcess = + eventProcess = getProcessComputeIfAbsent(epid, so.getCurrentProcessSystemId(), true); + currentThread = eventThread = getThreadComputeIfAbsent(etid, (DbgProcessImpl) eventProcess, + so.getCurrentThreadSystemId(), false); + } + } + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgProcessImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgProcessImpl.java index 78b44f0964..83de1257a0 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgProcessImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgProcessImpl.java @@ -51,6 +51,7 @@ public class DbgProcessImpl implements DbgProcess { private DebugProcessId id; private Long pid; private Long exitCode; + private Long offset; /** * Construct a new inferior @@ -373,4 +374,13 @@ public class DbgProcessImpl implements DbgProcess { public CompletableFuture evaluate(String expression) { return manager.execute(new DbgEvaluateCommand(manager, expression)); } + + public Long getOffset() { + return offset; + } + + public void setOffset(long offset) { + this.offset = offset; + } + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgThreadImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgThreadImpl.java index abd96b2bfe..1635f38cdd 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgThreadImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgThreadImpl.java @@ -40,8 +40,9 @@ public class DbgThreadImpl implements DbgThread { DbgManagerImpl manager; private DbgProcessImpl process; private DebugThreadId id; - private long tid; + private Long tid; private DebugEventInformation info; + private Long offset; private final AsyncReference state = new AsyncReference<>(DbgState.STOPPED); @@ -284,4 +285,13 @@ public class DbgThreadImpl implements DbgThread { int executingProcessorType = info.getExecutingProcessorType(); return WinNTExtra.Machine.getByNumber(executingProcessorType); } + + public Long getOffset() { + return offset; + } + + public void setOffset(long offset) { + this.offset = offset; + } + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface1/DbgModelTargetSteppable.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface1/DbgModelTargetSteppable.java index dfa70993f9..2a60ac97ea 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface1/DbgModelTargetSteppable.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface1/DbgModelTargetSteppable.java @@ -19,6 +19,7 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; import agent.dbgeng.manager.DbgManager.ExecSuffix; +import agent.dbgeng.manager.DbgProcess; import agent.dbgeng.manager.DbgThread; import agent.dbgeng.model.iface2.*; import ghidra.dbg.target.TargetSteppable; @@ -68,8 +69,12 @@ public interface DbgModelTargetSteppable extends DbgModelTargetObject, TargetSte } if (this instanceof DbgModelTargetProcess) { DbgModelTargetProcess targetProcess = (DbgModelTargetProcess) this; + DbgProcess process = targetProcess.getProcess(); + if (process == null) { + process = getManager().getCurrentProcess(); + } return getModel() - .gateFuture(targetProcess.getProcess().step(convertToDbg(kind))); + .gateFuture(process.step(convertToDbg(kind))); } return getModel().gateFuture(thread.step(convertToDbg(kind))); } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetProcess.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetProcess.java index b500a8686f..203ef0b661 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetProcess.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetProcess.java @@ -58,15 +58,8 @@ public interface DbgModelTargetProcess extends // public default DbgProcess getProcess(boolean fire) { DbgManagerImpl manager = getManager(); - DebugSystemObjects so = manager.getSystemObjects(); try { - String index = PathUtils.parseIndex(getName()); - Integer pid = Integer.decode(index); - DebugProcessId id = so.getProcessIdBySystemId(pid); - if (id == null) { - id = so.getCurrentProcessId(); - } - return manager.getProcessComputeIfAbsent(id, pid, fire); + return manager.getProcessComputeIfAbsent(getName(), fire); } catch (IllegalArgumentException e) { return manager.getCurrentProcess(); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetThread.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetThread.java index 8663a6f270..4331e899ce 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetThread.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetThread.java @@ -42,17 +42,10 @@ public interface DbgModelTargetThread extends // public default DbgThread getThread(boolean fire) { DbgManagerImpl manager = getManager(); - DebugSystemObjects so = manager.getSystemObjects(); try { - String index = PathUtils.parseIndex(getName()); - int tid = Integer.decode(index); - DebugThreadId id = so.getThreadIdBySystemId(tid); - if (id == null) { - id = so.getCurrentThreadId(); - } DbgModelTargetProcess parentProcess = getParentProcess(); - DbgProcessImpl process = (DbgProcessImpl) parentProcess.getProcess(); - DbgThreadImpl thread = manager.getThreadComputeIfAbsent(id, process, tid, fire); + DbgProcessImpl process = parentProcess == null ? null : (DbgProcessImpl) parentProcess.getProcess(); + DbgThreadImpl thread = manager.getThreadComputeIfAbsent(getName(), process, fire); return thread; } catch (IllegalArgumentException e) { diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetProcessContainerImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetProcessContainerImpl.java index bc581e0507..775ae6f641 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetProcessContainerImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetProcessContainerImpl.java @@ -57,7 +57,7 @@ public class DbgModelTargetProcessContainerImpl extends DbgModelTargetObjectImpl session.setAccessible(true); DbgModelTargetProcess process = getTargetProcess(proc); changeElements(List.of(), List.of(process), Map.of(), "Added"); - process.processStarted(proc.getPid()); + process.processStarted(Long.valueOf(proc.getPid())); broadcast().event(getProxy(), null, TargetEventType.PROCESS_CREATED, "Process " + proc.getId() + " started " + process.getName() + "pid=" + proc.getPid(), List.of(process)); @@ -66,7 +66,7 @@ public class DbgModelTargetProcessContainerImpl extends DbgModelTargetObjectImpl @Override public void processStarted(DbgProcess proc, DbgCause cause) { DbgModelTargetProcess process = getTargetProcess(proc); - process.processStarted(proc.getPid()); + process.processStarted(Long.valueOf(proc.getPid())); } @Override diff --git a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/gadp/impl/WrappedDbgModel.java b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/gadp/impl/WrappedDbgModel.java index 25dfce013e..8429c315a6 100644 --- a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/gadp/impl/WrappedDbgModel.java +++ b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/gadp/impl/WrappedDbgModel.java @@ -721,13 +721,41 @@ public class WrappedDbgModel @Override public int getCurrentThreadSystemId() { // used by impl return client.getSystemObjects().getCurrentThreadSystemId(); - //return getCurrentThreadId().id; } @Override public int getCurrentProcessSystemId() { // used by impl return client.getSystemObjects().getCurrentProcessSystemId(); - //return getCurrentProcessId().id; + } + + @Override + public long getCurrentThreadDataOffset() { // used by impl + return client.getSystemObjects().getCurrentThreadDataOffset(); + } + + @Override + public long getCurrentProcessDataOffset() { // used by impl + return client.getSystemObjects().getCurrentProcessDataOffset(); + } + + @Override + public long getImplicitThreadDataOffset() { // used by impl + return client.getSystemObjects().getImplicitThreadDataOffset(); + } + + @Override + public long getImplicitProcessDataOffset() { // used by impl + return client.getSystemObjects().getImplicitProcessDataOffset(); + } + + @Override + public void setImplicitThreadDataOffset(long offset) { // used by impl + client.getSystemObjects().setImplicitThreadDataOffset(offset); + } + + @Override + public void setImplicitProcessDataOffset(long offset) { // used by impl + client.getSystemObjects().setImplicitProcessDataOffset(offset); } @Override diff --git a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/impl/dbgmodel/concept/IterableConceptImpl.java b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/impl/dbgmodel/concept/IterableConceptImpl.java index 25f84a6854..f80e80dfaf 100644 --- a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/impl/dbgmodel/concept/IterableConceptImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/impl/dbgmodel/concept/IterableConceptImpl.java @@ -28,6 +28,7 @@ import agent.dbgmodel.dbgmodel.main.*; import agent.dbgmodel.impl.dbgmodel.main.ModelIteratorInternal; import agent.dbgmodel.jna.dbgmodel.concept.IIterableConcept; import agent.dbgmodel.jna.dbgmodel.main.WrapIModelIterator; +import ghidra.util.Msg; public class IterableConceptImpl implements IterableConceptInternal { @SuppressWarnings("unused") @@ -63,6 +64,10 @@ public class IterableConceptImpl implements IterableConceptInternal { if (hr.equals(COMUtilsExtra.E_FAIL)) { return null; } + if (hr.equals(COMUtilsExtra.E_BOUNDS)) { + Msg.error(this, "iterator out of bounds - check symbol path"); + return null; + } if (hr.equals(COMUtilsExtra.E_COM_EXC)) { return null; } diff --git a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/impl/dbgmodel/main/RawEnumeratorImpl.java b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/impl/dbgmodel/main/RawEnumeratorImpl.java index 1f3fc1366f..7bbffa9ee4 100644 --- a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/impl/dbgmodel/main/RawEnumeratorImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/impl/dbgmodel/main/RawEnumeratorImpl.java @@ -64,7 +64,7 @@ public class RawEnumeratorImpl extends UnknownExImpl implements RawEnumeratorInt ULONGByReference ulKind = new ULONGByReference(); PointerByReference ppValue = new PointerByReference(); HRESULT hr = jnaData.GetNext(bref, ulKind, ppValue); - if (hr.equals(COMUtilsExtra.E_BOUNDS)) { + if (hr.equals(COMUtilsExtra.E_BOUNDS) || hr.equals(COMUtilsExtra.E_CANNOT_READ)) { return null; } COMUtils.checkRC(hr); diff --git a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DbgModel2TargetObjectImpl.java b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DbgModel2TargetObjectImpl.java index 6aa72afdd4..5c7a329935 100644 --- a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DbgModel2TargetObjectImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DbgModel2TargetObjectImpl.java @@ -15,14 +15,12 @@ */ package agent.dbgmodel.model.impl; -import java.lang.invoke.MethodHandles; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; -import agent.dbgeng.manager.DbgEventsListener; -import agent.dbgeng.manager.DbgStateListener; +import agent.dbgeng.manager.*; import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo; import agent.dbgeng.model.AbstractDbgModel; import agent.dbgeng.model.iface1.DbgModelSelectableObject; @@ -38,7 +36,6 @@ import ghidra.dbg.target.*; import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointKind; import ghidra.dbg.target.TargetBreakpointSpecContainer.TargetBreakpointKindSet; import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState; -import ghidra.dbg.target.TargetMethod.AnnotatedTargetMethod; import ghidra.dbg.target.schema.TargetObjectSchema; import ghidra.dbg.util.PathUtils; import ghidra.dbg.util.PathUtils.TargetObjectKeyComparator; @@ -253,6 +250,11 @@ public class DbgModel2TargetObjectImpl extends DefaultTargetObject { DbgModelTargetProcess targetProcess = (DbgModelTargetProcess) obj; if (targetProcess == null) { - System.err.println("processAdded - null"); return; } DbgModelTargetProcessContainer container = @@ -196,7 +195,6 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot getObject(thread).thenAccept(obj -> { DbgModelTargetThread targetThread = (DbgModelTargetThread) obj; if (targetThread == null) { - System.err.println("threadCreated - null"); return; } DbgModelTargetThreadContainer container = @@ -270,12 +268,10 @@ public class DbgModel2TargetRootImpl extends DbgModel2DefaultTargetModelRoot getModel().fetchModelObject(objPath).handle(seq::next); }, TypeSpec.cls(TargetObject.class)).then((pobj, seq) -> { DbgModelTargetObject pimpl = (DbgModelTargetObject) pobj; - getModel().addModelObject(object, pimpl); seq.exit(pimpl); }).finish(); } - //TODO: fix this private CompletableFuture getObjectRevisited(Object object, List ext, Object info) { List objPath = findObject(object); diff --git a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DelegateDbgModel2TargetObject.java b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DelegateDbgModel2TargetObject.java index 417563afc4..77f2fef03d 100644 --- a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DelegateDbgModel2TargetObject.java +++ b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DelegateDbgModel2TargetObject.java @@ -18,16 +18,55 @@ package agent.dbgmodel.model.impl; import java.lang.invoke.MethodHandles; import java.lang.ref.Cleaner; import java.lang.ref.Cleaner.Cleanable; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; -import agent.dbgeng.manager.*; +import agent.dbgeng.manager.DbgCause; +import agent.dbgeng.manager.DbgEventsListener; +import agent.dbgeng.manager.DbgReason; +import agent.dbgeng.manager.DbgState; +import agent.dbgeng.manager.DbgStateListener; import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo; -import agent.dbgeng.model.iface1.*; -import agent.dbgeng.model.iface2.*; +import agent.dbgeng.model.iface1.DbgModelTargetAccessConditioned; +import agent.dbgeng.model.iface1.DbgModelTargetBptHelper; +import agent.dbgeng.model.iface1.DbgModelTargetExecutionStateful; +import agent.dbgeng.model.iface1.DbgModelTargetMethod; +import agent.dbgeng.model.iface2.DbgModelTargetAvailable; +import agent.dbgeng.model.iface2.DbgModelTargetAvailableContainer; +import agent.dbgeng.model.iface2.DbgModelTargetBreakpointContainer; +import agent.dbgeng.model.iface2.DbgModelTargetBreakpointSpec; +import agent.dbgeng.model.iface2.DbgModelTargetDebugContainer; +import agent.dbgeng.model.iface2.DbgModelTargetMemoryContainer; +import agent.dbgeng.model.iface2.DbgModelTargetModule; +import agent.dbgeng.model.iface2.DbgModelTargetModuleContainer; +import agent.dbgeng.model.iface2.DbgModelTargetObject; +import agent.dbgeng.model.iface2.DbgModelTargetProcess; +import agent.dbgeng.model.iface2.DbgModelTargetProcessContainer; +import agent.dbgeng.model.iface2.DbgModelTargetRegister; +import agent.dbgeng.model.iface2.DbgModelTargetRegisterBank; +import agent.dbgeng.model.iface2.DbgModelTargetRegisterContainer; +import agent.dbgeng.model.iface2.DbgModelTargetSession; +import agent.dbgeng.model.iface2.DbgModelTargetSessionAttributes; +import agent.dbgeng.model.iface2.DbgModelTargetSessionContainer; +import agent.dbgeng.model.iface2.DbgModelTargetStack; +import agent.dbgeng.model.iface2.DbgModelTargetStackFrame; +import agent.dbgeng.model.iface2.DbgModelTargetTTD; +import agent.dbgeng.model.iface2.DbgModelTargetThread; +import agent.dbgeng.model.iface2.DbgModelTargetThreadContainer; import agent.dbgmodel.dbgmodel.main.ModelObject; import agent.dbgmodel.jna.dbgmodel.DbgModelNative.ModelObjectKind; -import ghidra.dbg.target.*; +import ghidra.dbg.target.TargetAccessConditioned; import ghidra.dbg.target.TargetBreakpointSpec.TargetBreakpointAction; +import ghidra.dbg.target.TargetExecutionStateful; +import ghidra.dbg.target.TargetObject; +import ghidra.dbg.target.TargetRegisterBank; +import ghidra.dbg.target.TargetRegisterContainer; +import ghidra.dbg.target.TargetStack; +import ghidra.dbg.target.TargetStackFrame; +import ghidra.dbg.target.TargetThread; import ghidra.dbg.util.PathUtils; import ghidra.util.datastruct.ListenerSet; @@ -303,9 +342,18 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp DbgModelTargetThread targetThread = (DbgModelTargetThread) proxy; targetThread.getThread(false); } + + boolean kernelMode = getModel().getManager().isKernelMode(); + if (kernelMode) { + if (proxy instanceof DbgModelTargetProcess || // + proxy instanceof DbgModelTargetThread) { + return; + } + } if (getModel().isSuppressDescent()) { return; } + if (proxy instanceof DbgModelTargetSession || // proxy instanceof DbgModelTargetProcess || // proxy instanceof DbgModelTargetThread) { @@ -416,9 +464,15 @@ public class DelegateDbgModel2TargetObject extends DbgModel2TargetObjectImpl imp } DbgModelTargetRegisterContainer container = (DbgModelTargetRegisterContainer) getCachedAttribute("Registers"); + if (container == null) { + return; + } delegates.add((DelegateDbgModel2TargetObject) container.getDelegate()); DbgModelTargetRegisterBank bank = (DbgModelTargetRegisterBank) container.getCachedAttribute("User"); + if (bank == null) { + return; + } delegates.add((DelegateDbgModel2TargetObject) bank.getDelegate()); for (DelegateDbgModel2TargetObject delegate : delegates) { delegate.threadStateChangedSpecific(state, reason); diff --git a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/resources/agent/dbgmodel/model/impl/dbgmodel_schema.xml b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/resources/agent/dbgmodel/model/impl/dbgmodel_schema.xml index cc010c0613..407efc794a 100644 --- a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/resources/agent/dbgmodel/model/impl/dbgmodel_schema.xml +++ b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/resources/agent/dbgmodel/model/impl/dbgmodel_schema.xml @@ -144,7 +144,7 @@