From 1862e439a185cd4a5d441309ba0df37d7f59605e Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Tue, 21 Sep 2021 10:44:52 -0400 Subject: [PATCH 01/17] GP-1288: IDebugControl additions --- .../agent/dbgeng/jna/dbgeng/DbgEngNative.java | 44 +++++++++++ .../jna/dbgeng/control/IDebugControl.java | 37 ++++++++- .../jna/dbgeng/control/WrapIDebugControl.java | 78 ++++++++++++++++++- 3 files changed, 155 insertions(+), 4 deletions(-) diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/DbgEngNative.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/DbgEngNative.java index f92849965f..2fd40d0a4a 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/DbgEngNative.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/DbgEngNative.java @@ -459,4 +459,48 @@ public interface DbgEngNative extends StdCallLibrary { return FIELDS; } } + + public class DEBUG_SPECIFIC_FILTER_PARAMETERS extends Structure { + public static class ByReference extends DEBUG_SPECIFIC_FILTER_PARAMETERS + implements Structure.ByReference { + } + + public static final List FIELDS = + createFieldsOrder("ExecutionOption", "ContinueOption", "TextSize", "CommandSize", + "ArgumentSize"); + + public ULONG ExecutionOption; + public ULONG ContinueOption; + public ULONG TextSize; + public ULONG CommandSize; + public ULONG ArgumentSize; + + @Override + protected List getFieldOrder() { + return FIELDS; + } + } + + public class DEBUG_EXCEPTION_FILTER_PARAMETERS extends Structure { + public static class ByReference extends DEBUG_EXCEPTION_FILTER_PARAMETERS + implements Structure.ByReference { + } + + public static final List FIELDS = + createFieldsOrder("ExecutionOption", "ContinueOption", "TextSize", "CommandSize", + "SecondCommandSize", "ExceptionCode"); + + public ULONG ExecutionOption; + public ULONG ContinueOption; + public ULONG TextSize; + public ULONG CommandSize; + public ULONG SecondCommandSize; + public ULONG ExceptionCode; + + @Override + protected List getFieldOrder() { + return FIELDS; + } + } + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/IDebugControl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/IDebugControl.java index 665e2493b1..5490ad044b 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/IDebugControl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/IDebugControl.java @@ -21,8 +21,7 @@ import com.sun.jna.platform.win32.WinNT.HRESULT; import com.sun.jna.platform.win32.COM.IUnknown; import com.sun.jna.ptr.PointerByReference; -import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_STACK_FRAME; -import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_VALUE; +import agent.dbgeng.jna.dbgeng.DbgEngNative.*; import agent.dbgeng.jna.dbgeng.UnknownWithUtils.VTableIndex; import agent.dbgeng.jna.dbgeng.breakpoint.IDebugBreakpoint; @@ -184,4 +183,38 @@ public interface IDebugControl extends IUnknown { HRESULT GetExecutingProcessorType(ULONGByReference Type); HRESULT GetDebuggeeType(ULONGByReference Class, ULONGByReference Qualifier); + + HRESULT GetNumberEventFilters(ULONGByReference SpecificEvents, + ULONGByReference SpecificExceptions, ULONGByReference ArbitraryExceptions); + + HRESULT GetEventFilterText(ULONG Index, byte[] Buffer, ULONG BufferSize, + ULONGByReference TextSize); + + HRESULT GetEventFilterCommand(ULONG Index, byte[] Buffer, ULONG BufferSize, + ULONGByReference CommandSize); + + HRESULT SetEventFilterCommand(ULONG Index, String Command); + + HRESULT GetSpecificFilterParameters(ULONG Start, ULONG Count, + DEBUG_SPECIFIC_FILTER_PARAMETERS[] Params); + + HRESULT SetSpecificFilterParameters(ULONG Start, ULONG Count, + DEBUG_SPECIFIC_FILTER_PARAMETERS[] Params); + + HRESULT GetSpecificFilterArgument(ULONG Index, byte[] Buffer, ULONG BufferSize, + ULONGByReference ArgumentSize); + + HRESULT SetSpecificFilterArgument(ULONG Index, String Argument); + + HRESULT GetExceptionFilterParameters(ULONG Count, ULONGByReference Codes, ULONG Start, + DEBUG_EXCEPTION_FILTER_PARAMETERS[] Params); + + HRESULT SetExceptionFilterParameters(ULONG Count, + DEBUG_EXCEPTION_FILTER_PARAMETERS[] Params); + + HRESULT GetExceptionFilterSecondCommand(ULONG Index, byte[] Buffer, ULONG BufferSize, + ULONGByReference CommandSize); + + HRESULT SetExceptionFilterSecondCommand(ULONG Index, String Command); + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/WrapIDebugControl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/WrapIDebugControl.java index 6409d93929..b7268c227f 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/WrapIDebugControl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/WrapIDebugControl.java @@ -23,8 +23,7 @@ import com.sun.jna.platform.win32.WinDef.*; import com.sun.jna.platform.win32.WinNT.HRESULT; import com.sun.jna.ptr.PointerByReference; -import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_STACK_FRAME; -import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_VALUE; +import agent.dbgeng.jna.dbgeng.DbgEngNative.*; import agent.dbgeng.jna.dbgeng.UnknownWithUtils; import agent.dbgeng.jna.dbgeng.breakpoint.IDebugBreakpoint; @@ -178,4 +177,79 @@ public class WrapIDebugControl extends UnknownWithUtils implements IDebugControl return _invokeHR(VTIndices.GET_DEBUGGEE_TYPE, getPointer(), Class, Qualifier); } + @Override + public HRESULT GetNumberEventFilters(ULONGByReference SpecificEvents, + ULONGByReference SpecificExceptions, ULONGByReference ArbitraryExceptions) { + return _invokeHR(VTIndices.GET_NUMBER_EVENT_FILTERS, getPointer(), SpecificEvents, + SpecificExceptions, ArbitraryExceptions); + } + + @Override + public HRESULT GetEventFilterText(ULONG Index, byte[] Buffer, ULONG BufferSize, + ULONGByReference TextSize) { + return _invokeHR(VTIndices.GET_EVENT_FILTER_TEXT, getPointer(), Index, Buffer, + BufferSize, TextSize); + } + + @Override + public HRESULT GetEventFilterCommand(ULONG Index, byte[] Buffer, ULONG BufferSize, + ULONGByReference CommandSize) { + return _invokeHR(VTIndices.GET_EVENT_FILTER_COMMAND, getPointer(), Index, Buffer, + BufferSize, CommandSize); + } + + @Override + public HRESULT SetEventFilterCommand(ULONG Index, String Command) { + return _invokeHR(VTIndices.SET_EVENT_FILTER_COMMAND, getPointer(), Index, Command); + } + + @Override + public HRESULT GetSpecificFilterParameters(ULONG Start, ULONG Count, + DEBUG_SPECIFIC_FILTER_PARAMETERS[] Params) { + return _invokeHR(VTIndices.SET_EVENT_FILTER_COMMAND, getPointer(), Start, Count, Params); + } + + @Override + public HRESULT SetSpecificFilterParameters(ULONG Start, ULONG Count, + DEBUG_SPECIFIC_FILTER_PARAMETERS[] Params) { + return _invokeHR(VTIndices.SET_EVENT_FILTER_COMMAND, getPointer(), Start, Count, Params); + } + + @Override + public HRESULT GetSpecificFilterArgument(ULONG Index, byte[] Buffer, ULONG BufferSize, + ULONGByReference ArgumentSize) { + return _invokeHR(VTIndices.SET_EVENT_FILTER_COMMAND, getPointer(), Index, Buffer, + BufferSize, ArgumentSize); + } + + @Override + public HRESULT SetSpecificFilterArgument(ULONG Index, String Argument) { + return _invokeHR(VTIndices.SET_EVENT_FILTER_COMMAND, getPointer(), Index, Argument); + } + + @Override + public HRESULT GetExceptionFilterParameters(ULONG Count, ULONGByReference Codes, ULONG Start, + DEBUG_EXCEPTION_FILTER_PARAMETERS[] Params) { + return _invokeHR(VTIndices.SET_EVENT_FILTER_COMMAND, getPointer(), Count, Codes, Start, + Params); + } + + @Override + public HRESULT SetExceptionFilterParameters(ULONG Count, + DEBUG_EXCEPTION_FILTER_PARAMETERS[] Params) { + return _invokeHR(VTIndices.SET_EVENT_FILTER_COMMAND, getPointer(), Count, Params); + } + + @Override + public HRESULT GetExceptionFilterSecondCommand(ULONG Index, byte[] Buffer, ULONG BufferSize, + ULONGByReference CommandSize) { + return _invokeHR(VTIndices.GET_EXCEPTION_FILTER_SECOND_COMMAND, getPointer(), Index, Buffer, + BufferSize, CommandSize); + } + + @Override + public HRESULT SetExceptionFilterSecondCommand(ULONG Index, String Command) { + return _invokeHR(VTIndices.SET_EXCEPTION_FILTER_SECOND_COMMAND, getPointer(), Index, + Command); + } } From b54012395ce8f6d4630368f4e5bcfa828315700e Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Tue, 21 Sep 2021 12:16:13 -0400 Subject: [PATCH 02/17] GP-1288: DebugControl filter additions --- .../agent/dbgeng/dbgeng/DebugControl.java | 25 ++++ .../DebugExceptionFilterInformation.java | 42 ++++++ .../dbgeng/dbgeng/DebugFilterInformation.java | 42 ++++++ .../DebugSpecificFilterInformation.java | 42 ++++++ .../dbgeng/control/DebugControlImpl1.java | 125 +++++++++++++++++- .../jna/dbgeng/control/IDebugControl.java | 2 +- .../jna/dbgeng/control/WrapIDebugControl.java | 2 +- 7 files changed, 276 insertions(+), 4 deletions(-) create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugExceptionFilterInformation.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugFilterInformation.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugSpecificFilterInformation.java diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java index 125dee70f6..c7ac845713 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java @@ -356,4 +356,29 @@ public interface DebugControl extends DebugControlReentrant { int getExecutingProcessorType(); int getDebuggeeType(); + + DebugFilterInformation getNumberEventFilters(); + + String getEventFilterText(int index); + + String getEventFilterCommand(int index); + + void setEventFilterCommand(int index, String text); + + DebugSpecificFilterInformation getSpecificFilterParameters(int start, int count); + + void setSpecificFilterParameters(int start, int count, DebugSpecificFilterInformation info); + + String getSpecificFilterArgument(int index); + + void setSpecificFilterArgument(int index, String arg); + + DebugExceptionFilterInformation getExceptionFilterParameters(int start, int[] codes, int count); + + void setExceptionFilterParameters(int count, DebugExceptionFilterInformation info); + + String getExceptionFilterSecondCommand(int index); + + void setExceptionFilterSecondCommand(int index, String cmd); + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugExceptionFilterInformation.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugExceptionFilterInformation.java new file mode 100644 index 0000000000..252afcdc85 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugExceptionFilterInformation.java @@ -0,0 +1,42 @@ +/* ### + * 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; + +import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_EXCEPTION_FILTER_PARAMETERS; + +public class DebugExceptionFilterInformation { + + private int nParams; + private DEBUG_EXCEPTION_FILTER_PARAMETERS[] parameters; + + public DebugExceptionFilterInformation(int nParams, + DEBUG_EXCEPTION_FILTER_PARAMETERS[] parameters) { + this.nParams = nParams; + this.parameters = parameters; + } + + public int getNumberOfParameters() { + return nParams; + } + + public DEBUG_EXCEPTION_FILTER_PARAMETERS getParameter(int paramNumber) { + return parameters[paramNumber]; + } + + public DEBUG_EXCEPTION_FILTER_PARAMETERS[] getParameters() { + return parameters; + } +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugFilterInformation.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugFilterInformation.java new file mode 100644 index 0000000000..5b22b62212 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugFilterInformation.java @@ -0,0 +1,42 @@ +/* ### + * 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 class DebugFilterInformation { + + private int nEvents; + private int nSpecificExceptions; + private int nArbitraryExceptions; + + public DebugFilterInformation(int nEvents, int nSpecificExceptions, int nArbitraryExceptions) { + this.nEvents = nEvents; + this.nSpecificExceptions = nSpecificExceptions; + this.nArbitraryExceptions = nArbitraryExceptions; + } + + public int getNumberEvents() { + return nEvents; + } + + public int getNumberSpecificExceptions() { + return nSpecificExceptions; + } + + public int getNumberArbitraryExceptions() { + return nArbitraryExceptions; + } + +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugSpecificFilterInformation.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugSpecificFilterInformation.java new file mode 100644 index 0000000000..b1cd3e8808 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugSpecificFilterInformation.java @@ -0,0 +1,42 @@ +/* ### + * 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; + +import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_SPECIFIC_FILTER_PARAMETERS; + +public class DebugSpecificFilterInformation { + + private int nParams; + private DEBUG_SPECIFIC_FILTER_PARAMETERS[] parameters; + + public DebugSpecificFilterInformation(int nParams, + DEBUG_SPECIFIC_FILTER_PARAMETERS[] parameters) { + this.nParams = nParams; + this.parameters = parameters; + } + + public int getNumberOfParameters() { + return nParams; + } + + public DEBUG_SPECIFIC_FILTER_PARAMETERS getParameter(int paramNumber) { + return parameters[paramNumber]; + } + + public DEBUG_SPECIFIC_FILTER_PARAMETERS[] getParameters() { + return parameters; + } +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/control/DebugControlImpl1.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/control/DebugControlImpl1.java index 8f5974245a..056ea0a3f6 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/control/DebugControlImpl1.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/control/DebugControlImpl1.java @@ -31,8 +31,7 @@ import agent.dbgeng.dbgeng.DebugClient.DebugStatus; import agent.dbgeng.dbgeng.DebugValue.DebugValueType; import agent.dbgeng.impl.dbgeng.DbgEngUtil; import agent.dbgeng.impl.dbgeng.breakpoint.DebugBreakpointInternal; -import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_STACK_FRAME; -import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_VALUE; +import agent.dbgeng.jna.dbgeng.DbgEngNative.*; import agent.dbgeng.jna.dbgeng.breakpoint.IDebugBreakpoint; import agent.dbgeng.jna.dbgeng.breakpoint.WrapIDebugBreakpoint; import agent.dbgeng.jna.dbgeng.control.IDebugControl; @@ -301,4 +300,126 @@ public class DebugControlImpl1 implements DebugControlInternal { COMUtils.checkRC(jnaControl.GetDebuggeeType(ulClass, ulQualifier)); return ulClass.getValue().intValue(); } + + @Override + public DebugFilterInformation getNumberEventFilters() { + ULONGByReference ulSpecificEvents = new ULONGByReference(); + ULONGByReference ulSpecificExceptions = new ULONGByReference(); + ULONGByReference ulArbitraryExceptions = new ULONGByReference(); + COMUtils.checkRC(jnaControl.GetNumberEventFilters(ulSpecificEvents, ulSpecificExceptions, + ulArbitraryExceptions)); + return new DebugFilterInformation( + ulSpecificEvents.getValue().intValue(), + ulSpecificExceptions.getValue().intValue(), + ulArbitraryExceptions.getValue().intValue()); + } + + @Override + public String getEventFilterText(int index) { + ULONG ulIndex = new ULONG(index); + ULONGByReference ulTextSize = new ULONGByReference(); + COMUtils.checkRC(jnaControl.GetEventFilterText(ulIndex, null, new ULONG(0), ulTextSize)); + byte[] buffer = new byte[ulTextSize.getValue().intValue()]; + ULONG ulBufferSize = ulTextSize.getValue(); + COMUtils.checkRC(jnaControl.GetEventFilterText(ulIndex, buffer, ulBufferSize, null)); + return Native.toString(buffer); + } + + @Override + public String getEventFilterCommand(int index) { + ULONG ulIndex = new ULONG(index); + ULONGByReference ulCommandSize = new ULONGByReference(); + COMUtils.checkRC( + jnaControl.GetEventFilterCommand(ulIndex, null, new ULONG(0), ulCommandSize)); + byte[] buffer = new byte[ulCommandSize.getValue().intValue()]; + ULONG ulBufferSize = ulCommandSize.getValue(); + COMUtils.checkRC(jnaControl.GetEventFilterCommand(ulIndex, buffer, ulBufferSize, null)); + return Native.toString(buffer); + } + + @Override + public void setEventFilterCommand(int index, String text) { + ULONG ulIndex = new ULONG(index); + COMUtils.checkRC(jnaControl.SetEventFilterCommand(ulIndex, text)); + } + + @Override + public DebugSpecificFilterInformation getSpecificFilterParameters(int start, int count) { + ULONG ulStart = new ULONG(start); + ULONG ulCount = new ULONG(count); + DEBUG_SPECIFIC_FILTER_PARAMETERS[] pParams = new DEBUG_SPECIFIC_FILTER_PARAMETERS[count]; + COMUtils.checkRC(jnaControl.GetSpecificFilterParameters(ulStart, ulCount, pParams)); + return new DebugSpecificFilterInformation(count, pParams); + } + + @Override + public void setSpecificFilterParameters(int start, int count, + DebugSpecificFilterInformation info) { + ULONG ulStart = new ULONG(start); + ULONG ulCount = new ULONG(count); + COMUtils.checkRC( + jnaControl.SetSpecificFilterParameters(ulStart, ulCount, info.getParameters())); + } + + @Override + public String getSpecificFilterArgument(int index) { + ULONG ulIndex = new ULONG(index); + ULONGByReference ulArgumentSize = new ULONGByReference(); + COMUtils.checkRC( + jnaControl.GetSpecificFilterArgument(ulIndex, null, new ULONG(0), ulArgumentSize)); + byte[] buffer = new byte[ulArgumentSize.getValue().intValue()]; + ULONG ulBufferSize = ulArgumentSize.getValue(); + COMUtils.checkRC( + jnaControl.GetSpecificFilterArgument(ulIndex, buffer, ulBufferSize, null)); + return Native.toString(buffer); + } + + @Override + public void setSpecificFilterArgument(int index, String arg) { + ULONG ulIndex = new ULONG(index); + COMUtils.checkRC(jnaControl.SetSpecificFilterArgument(ulIndex, arg)); + } + + @Override + public DebugExceptionFilterInformation getExceptionFilterParameters(int start, int[] codes, + int count) { + ULONG ulStart = new ULONG(start); + ULONG[] ulCodes = new ULONG[codes.length]; + for (int i = 0; i < codes.length; i++) { + ulCodes[i] = new ULONG(codes[i]); + } + ULONG ulCount = new ULONG(count); + DEBUG_EXCEPTION_FILTER_PARAMETERS[] pParams = new DEBUG_EXCEPTION_FILTER_PARAMETERS[count]; + COMUtils.checkRC( + jnaControl.GetExceptionFilterParameters(ulCount, ulCodes, ulStart, pParams)); + return new DebugExceptionFilterInformation(count, pParams); + } + + @Override + public void setExceptionFilterParameters(int count, + DebugExceptionFilterInformation info) { + ULONG ulCount = new ULONG(count); + COMUtils.checkRC( + jnaControl.SetExceptionFilterParameters(ulCount, info.getParameters())); + } + + @Override + public String getExceptionFilterSecondCommand(int index) { + ULONG ulIndex = new ULONG(index); + ULONGByReference ulCommandSize = new ULONGByReference(); + COMUtils.checkRC( + jnaControl.GetExceptionFilterSecondCommand(ulIndex, null, new ULONG(0), ulCommandSize)); + byte[] buffer = new byte[ulCommandSize.getValue().intValue()]; + ULONG ulBufferSize = ulCommandSize.getValue(); + COMUtils.checkRC( + jnaControl.GetExceptionFilterSecondCommand(ulIndex, buffer, ulBufferSize, null)); + return Native.toString(buffer); + } + + @Override + public void setExceptionFilterSecondCommand(int index, String cmd) { + ULONG ulIndex = new ULONG(index); + COMUtils.checkRC(jnaControl.SetExceptionFilterSecondCommand(ulIndex, cmd)); + } + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/IDebugControl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/IDebugControl.java index 5490ad044b..8f3a095a6f 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/IDebugControl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/IDebugControl.java @@ -206,7 +206,7 @@ public interface IDebugControl extends IUnknown { HRESULT SetSpecificFilterArgument(ULONG Index, String Argument); - HRESULT GetExceptionFilterParameters(ULONG Count, ULONGByReference Codes, ULONG Start, + HRESULT GetExceptionFilterParameters(ULONG Count, ULONG[] Codes, ULONG Start, DEBUG_EXCEPTION_FILTER_PARAMETERS[] Params); HRESULT SetExceptionFilterParameters(ULONG Count, diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/WrapIDebugControl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/WrapIDebugControl.java index b7268c227f..be19407fb9 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/WrapIDebugControl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/WrapIDebugControl.java @@ -228,7 +228,7 @@ public class WrapIDebugControl extends UnknownWithUtils implements IDebugControl } @Override - public HRESULT GetExceptionFilterParameters(ULONG Count, ULONGByReference Codes, ULONG Start, + public HRESULT GetExceptionFilterParameters(ULONG Count, ULONG[] Codes, ULONG Start, DEBUG_EXCEPTION_FILTER_PARAMETERS[] Params) { return _invokeHR(VTIndices.SET_EVENT_FILTER_COMMAND, getPointer(), Count, Codes, Start, Params); From 7105c13681ac0509e84bfb3c8f2ef146f62eea23 Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Tue, 21 Sep 2021 12:17:37 -0400 Subject: [PATCH 03/17] GP-1288: start on filter commands --- .../cmd/DbgListExceptionFiltersCommand.java | 50 +++++++++++++++++++ .../cmd/DbgListSpecificFiltersCommand.java | 49 ++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListSpecificFiltersCommand.java diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java new file mode 100644 index 0000000000..950b06f7af --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java @@ -0,0 +1,50 @@ +/* ### + * 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.util.ArrayList; +import java.util.List; + +import agent.dbgeng.dbgeng.DebugExceptionFilterInformation; +import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_EXCEPTION_FILTER_PARAMETERS; +import agent.dbgeng.manager.impl.DbgManagerImpl; + +public class DbgListExceptionFiltersCommand + extends AbstractDbgCommand> { + private List result; + + public DbgListExceptionFiltersCommand(DbgManagerImpl manager) { + super(manager); + } + + @Override + public List complete(DbgPendingCommand pending) { + return result; + } + + @Override + public void invoke() { + result = new ArrayList<>(); + // TODO set up codes + int[] codes = new int[0]; + DebugExceptionFilterInformation filterInfo = + manager.getControl().getExceptionFilterParameters(0, codes, 0); + for (int i = 0; i < filterInfo.getNumberOfParameters(); i++) { + DEBUG_EXCEPTION_FILTER_PARAMETERS fi = filterInfo.getParameter(i); + result.add(fi); + } + } +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListSpecificFiltersCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListSpecificFiltersCommand.java new file mode 100644 index 0000000000..17e1c23749 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListSpecificFiltersCommand.java @@ -0,0 +1,49 @@ +/* ### + * 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.util.ArrayList; +import java.util.List; + +import agent.dbgeng.dbgeng.DebugSpecificFilterInformation; +import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_SPECIFIC_FILTER_PARAMETERS; +import agent.dbgeng.manager.impl.DbgManagerImpl; + +public class DbgListSpecificFiltersCommand + extends AbstractDbgCommand> { + private List result; + + public DbgListSpecificFiltersCommand(DbgManagerImpl manager) { + super(manager); + } + + @Override + public List complete(DbgPendingCommand pending) { + return result; + } + + @Override + public void invoke() { + result = new ArrayList<>(); + // TODO set parameters + DebugSpecificFilterInformation filterInfo = + manager.getControl().getSpecificFilterParameters(0, 0); + for (int i = 0; i < filterInfo.getNumberOfParameters(); i++) { + DEBUG_SPECIFIC_FILTER_PARAMETERS fi = filterInfo.getParameter(i); + result.add(fi); + } + } +} From 2f1f78dc97eb75a94355ac4becc89f99d1ddb7eb Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Tue, 21 Sep 2021 17:40:34 +0000 Subject: [PATCH 04/17] GP-1288: basic event/exc objects --- .../agent/dbgeng/manager/DbgEventFilter.java | 22 ++++++ .../dbgeng/manager/DbgExceptionFilter.java | 22 ++++++ .../dbgeng/manager/impl/DbgManagerImpl.java | 8 ++ .../model/iface2/DbgModelTargetEvent.java | 29 +++++++ .../iface2/DbgModelTargetEventContainer.java | 30 +++++++ .../model/iface2/DbgModelTargetException.java | 29 +++++++ .../DbgModelTargetExceptionContainer.java | 30 +++++++ .../DbgModelTargetDebugContainerImpl.java | 19 ++++- .../DbgModelTargetEventContainerImpl.java | 68 ++++++++++++++++ .../model/impl/DbgModelTargetEventImpl.java | 78 ++++++++++++++++++ .../DbgModelTargetExceptionContainerImpl.java | 68 ++++++++++++++++ .../impl/DbgModelTargetExceptionImpl.java | 79 +++++++++++++++++++ 12 files changed, 481 insertions(+), 1 deletion(-) create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgExceptionFilter.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEvent.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventContainer.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetException.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetExceptionContainer.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventContainerImpl.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionContainerImpl.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java new file mode 100644 index 0000000000..007ef68206 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java @@ -0,0 +1,22 @@ +/* ### + * 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; + +public interface DbgEventFilter { + + String getName(); + +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgExceptionFilter.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgExceptionFilter.java new file mode 100644 index 0000000000..a1fa35c9e9 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgExceptionFilter.java @@ -0,0 +1,22 @@ +/* ### + * 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; + +public interface DbgExceptionFilter { + + String getName(); + +} 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 3d13198ac9..ef34b36f06 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 @@ -1585,4 +1585,12 @@ public class DbgManagerImpl implements DbgManager { return processCount; } + public CompletableFuture> listEventFilters() { + return CompletableFuture.completedFuture(new HashMap()); + } + + public CompletableFuture> listExceptionFilters() { + return CompletableFuture.completedFuture(new HashMap()); + } + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEvent.java new file mode 100644 index 0000000000..dfbcc6eb35 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEvent.java @@ -0,0 +1,29 @@ +/* ### + * 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.model.iface2; + +import agent.dbgeng.manager.DbgEventFilter; + +public interface DbgModelTargetEvent extends DbgModelTargetObject { + + @Override + public default String getDisplay() { + return getName(); + } + + public DbgEventFilter getFilter(); + +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventContainer.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventContainer.java new file mode 100644 index 0000000000..4085880f94 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventContainer.java @@ -0,0 +1,30 @@ +/* ### + * 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.model.iface2; + +import ghidra.dbg.target.TargetAggregate; +import ghidra.dbg.target.schema.*; + +@TargetObjectSchemaInfo( + name = "EventContainer", + elements = { + @TargetElementType(type = DbgModelTargetEvent.class) }, + attributes = { + @TargetAttributeType(type = Void.class) }, + canonicalContainer = true) +public interface DbgModelTargetEventContainer extends DbgModelTargetObject, TargetAggregate { + +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetException.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetException.java new file mode 100644 index 0000000000..34c48922f4 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetException.java @@ -0,0 +1,29 @@ +/* ### + * 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.model.iface2; + +import agent.dbgeng.manager.DbgExceptionFilter; + +public interface DbgModelTargetException extends DbgModelTargetObject { + + @Override + public default String getDisplay() { + return getName(); + } + + public DbgExceptionFilter getFilter(); + +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetExceptionContainer.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetExceptionContainer.java new file mode 100644 index 0000000000..6f0e06b6d6 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetExceptionContainer.java @@ -0,0 +1,30 @@ +/* ### + * 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.model.iface2; + +import ghidra.dbg.target.TargetAggregate; +import ghidra.dbg.target.schema.*; + +@TargetObjectSchemaInfo( + name = "EventContainer", + elements = { + @TargetElementType(type = DbgModelTargetException.class) }, + attributes = { + @TargetAttributeType(type = Void.class) }, + canonicalContainer = true) +public interface DbgModelTargetExceptionContainer extends DbgModelTargetObject, TargetAggregate { + +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetDebugContainerImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetDebugContainerImpl.java index ed0c590045..be53560a77 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetDebugContainerImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetDebugContainerImpl.java @@ -31,6 +31,16 @@ import ghidra.dbg.target.schema.TargetObjectSchemaInfo; type = DbgModelTargetBreakpointContainerImpl.class, required = true, fixed = true), + @TargetAttributeType( + name = "Events", + type = DbgModelTargetEventContainerImpl.class, + required = true, + fixed = true), + @TargetAttributeType( + name = "Exceptions", + type = DbgModelTargetEventContainerImpl.class, + required = true, + fixed = true), @TargetAttributeType(type = Void.class) }, canonicalContainer = true) @@ -38,6 +48,9 @@ public class DbgModelTargetDebugContainerImpl extends DbgModelTargetObjectImpl implements DbgModelTargetDebugContainer { protected final DbgModelTargetBreakpointContainerImpl breakpoints; + protected final DbgModelTargetEventContainerImpl events; + protected final DbgModelTargetExceptionContainerImpl exceptions; + private DbgModelTargetProcess process; public DbgModelTargetDebugContainerImpl(DbgModelTargetProcess process) { @@ -45,9 +58,13 @@ public class DbgModelTargetDebugContainerImpl extends DbgModelTargetObjectImpl this.process = process; this.breakpoints = new DbgModelTargetBreakpointContainerImpl(this); + this.events = new DbgModelTargetEventContainerImpl(this); + this.exceptions = new DbgModelTargetExceptionContainerImpl(this); changeAttributes(List.of(), List.of( // - breakpoints // + breakpoints, // + events, // + exceptions // ), Map.of(), "Initialized"); } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventContainerImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventContainerImpl.java new file mode 100644 index 0000000000..f42a1bdbdd --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventContainerImpl.java @@ -0,0 +1,68 @@ +/* ### + * 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.model.impl; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +import agent.dbgeng.manager.DbgEventFilter; +import agent.dbgeng.manager.impl.DbgManagerImpl; +import agent.dbgeng.model.iface2.*; +import ghidra.dbg.target.TargetObject; +import ghidra.dbg.target.schema.*; + +@TargetObjectSchemaInfo( + name = "EventContainer", + elements = { // + @TargetElementType(type = DbgModelTargetEvent.class) // + }, + attributes = { // + @TargetAttributeType(type = Void.class) // + }, + canonicalContainer = true) +public class DbgModelTargetEventContainerImpl extends DbgModelTargetObjectImpl + implements DbgModelTargetEventContainer { + + public DbgModelTargetEventContainerImpl(DbgModelTargetDebugContainer debug) { + super(debug.getModel(), debug, "Events", "EventContainer"); + } + + public DbgModelTargetEvent getTargetEvent(DbgEventFilter info) { + DbgModelImpl impl = (DbgModelImpl) model; + TargetObject modelObject = impl.getModelObject(info); + if (modelObject != null) { + return (DbgModelTargetEvent) modelObject; + } + return new DbgModelTargetEventImpl(this, info); + } + + @Override + public CompletableFuture requestElements(boolean refresh) { + DbgManagerImpl manager = getManager(); + return manager.listEventFilters().thenAccept(byName -> { + List filters; + synchronized (this) { + filters = byName.values() + .stream() + .map(this::getTargetEvent) + .collect(Collectors.toList()); + } + setElements(filters, Map.of(), "Refreshed"); + }); + } +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java new file mode 100644 index 0000000000..394c9d8f3d --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java @@ -0,0 +1,78 @@ +/* ### + * 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.model.impl; + +import agent.dbgeng.manager.DbgEventFilter; +import agent.dbgeng.model.iface2.DbgModelTargetEvent; +import agent.dbgeng.model.iface2.DbgModelTargetEventContainer; +import ghidra.dbg.target.schema.*; +import ghidra.dbg.util.PathUtils; +import ghidra.program.model.address.Address; + +@TargetObjectSchemaInfo( + name = "Module", + elements = { + @TargetElementType(type = Void.class) }, + attributes = { + @TargetAttributeType( + name = "Symbols", + type = DbgModelTargetSymbolContainerImpl.class, + required = true, + fixed = true), + @TargetAttributeType(name = "BaseAddress", type = Address.class), + @TargetAttributeType(name = "ImageName", type = String.class), + @TargetAttributeType(name = "TimeStamp", type = Integer.class), + @TargetAttributeType(name = "Len", type = String.class), + @TargetAttributeType(type = Void.class) }) +public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl + implements DbgModelTargetEvent { + protected static String indexFilter(DbgEventFilter filter) { + return filter.getName(); + } + + protected static String keyFilter(DbgEventFilter filter) { + return PathUtils.makeKey(indexFilter(filter)); + } + + private DbgEventFilter filter; + + public DbgModelTargetEventImpl(DbgModelTargetEventContainer events, DbgEventFilter filter) { + super(events.getModel(), events, keyFilter(filter), "EventFilter"); + this.getModel().addModelObject(filter, this); + this.filter = filter; + + /* + changeAttributes(List.of(), List.of( // + symbols // + // sections.getName(), sections, // + ), Map.of( // + DISPLAY_ATTRIBUTE_NAME, getIndex(), // + SHORT_DISPLAY_ATTRIBUTE_NAME, module.getName(), // + MODULE_NAME_ATTRIBUTE_NAME, module.getImageName(), // + "BaseAddress", space.getAddress(module.getKnownBase()), // + "ImageName", module.getImageName(), // + "TimeStamp", module.getTimeStamp(), // + "Len", Integer.toHexString(module.getSize()) // + ), "Initialized"); + */ + } + + @Override + public DbgEventFilter getFilter() { + return filter; + } + +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionContainerImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionContainerImpl.java new file mode 100644 index 0000000000..c68955b824 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionContainerImpl.java @@ -0,0 +1,68 @@ +/* ### + * 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.model.impl; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +import agent.dbgeng.manager.DbgExceptionFilter; +import agent.dbgeng.manager.impl.DbgManagerImpl; +import agent.dbgeng.model.iface2.*; +import ghidra.dbg.target.TargetObject; +import ghidra.dbg.target.schema.*; + +@TargetObjectSchemaInfo( + name = "ExceptionContainer", + elements = { // + @TargetElementType(type = DbgModelTargetEvent.class) // + }, + attributes = { // + @TargetAttributeType(type = Void.class) // + }, + canonicalContainer = true) +public class DbgModelTargetExceptionContainerImpl extends DbgModelTargetObjectImpl + implements DbgModelTargetEventContainer { + + public DbgModelTargetExceptionContainerImpl(DbgModelTargetDebugContainer debug) { + super(debug.getModel(), debug, "Exceptions", "ExceptionContainer"); + } + + public DbgModelTargetException getTargetException(DbgExceptionFilter info) { + DbgModelImpl impl = (DbgModelImpl) model; + TargetObject modelObject = impl.getModelObject(info); + if (modelObject != null) { + return (DbgModelTargetException) modelObject; + } + return new DbgModelTargetExceptionImpl(this, info); + } + + @Override + public CompletableFuture requestElements(boolean refresh) { + DbgManagerImpl manager = getManager(); + return manager.listExceptionFilters().thenAccept(byName -> { + List filters; + synchronized (this) { + filters = byName.values() + .stream() + .map(this::getTargetException) + .collect(Collectors.toList()); + } + setElements(filters, Map.of(), "Refreshed"); + }); + } +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java new file mode 100644 index 0000000000..c93f807123 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java @@ -0,0 +1,79 @@ +/* ### + * 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.model.impl; + +import agent.dbgeng.manager.DbgExceptionFilter; +import agent.dbgeng.model.iface2.DbgModelTargetEventContainer; +import agent.dbgeng.model.iface2.DbgModelTargetException; +import ghidra.dbg.target.schema.*; +import ghidra.dbg.util.PathUtils; +import ghidra.program.model.address.Address; + +@TargetObjectSchemaInfo( + name = "Module", + elements = { + @TargetElementType(type = Void.class) }, + attributes = { + @TargetAttributeType( + name = "Symbols", + type = DbgModelTargetSymbolContainerImpl.class, + required = true, + fixed = true), + @TargetAttributeType(name = "BaseAddress", type = Address.class), + @TargetAttributeType(name = "ImageName", type = String.class), + @TargetAttributeType(name = "TimeStamp", type = Integer.class), + @TargetAttributeType(name = "Len", type = String.class), + @TargetAttributeType(type = Void.class) }) +public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl + implements DbgModelTargetException { + protected static String indexFilter(DbgExceptionFilter filter) { + return filter.getName(); + } + + protected static String keyFilter(DbgExceptionFilter filter) { + return PathUtils.makeKey(indexFilter(filter)); + } + + private DbgExceptionFilter filter; + + public DbgModelTargetExceptionImpl(DbgModelTargetEventContainer events, + DbgExceptionFilter filter) { + super(events.getModel(), events, keyFilter(filter), "ExceptionFilter"); + this.getModel().addModelObject(filter, this); + this.filter = filter; + + /* + changeAttributes(List.of(), List.of( // + symbols // + // sections.getName(), sections, // + ), Map.of( // + DISPLAY_ATTRIBUTE_NAME, getIndex(), // + SHORT_DISPLAY_ATTRIBUTE_NAME, module.getName(), // + MODULE_NAME_ATTRIBUTE_NAME, module.getImageName(), // + "BaseAddress", space.getAddress(module.getKnownBase()), // + "ImageName", module.getImageName(), // + "TimeStamp", module.getTimeStamp(), // + "Len", Integer.toHexString(module.getSize()) // + ), "Initialized"); + */ + } + + @Override + public DbgExceptionFilter getFilter() { + return filter; + } + +} From 4b98c30ff14468d24c96297e41de5ed80bfec34a Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Tue, 21 Sep 2021 21:25:56 +0000 Subject: [PATCH 05/17] GP-1288: more exception work --- .../dbgeng/control/DebugControlImpl1.java | 10 +-- .../agent/dbgeng/manager/DbgEventFilter.java | 2 + .../dbgeng/manager/DbgExceptionFilter.java | 2 + ...d.java => DbgListEventFiltersCommand.java} | 29 +++++---- .../cmd/DbgListExceptionFiltersCommand.java | 26 ++++---- .../manager/impl/DbgEventFilterImpl.java | 39 +++++++++++ .../manager/impl/DbgExceptionFilterImpl.java | 39 +++++++++++ .../dbgeng/manager/impl/DbgManagerImpl.java | 9 --- .../DbgModelTargetDebugContainerImpl.java | 2 +- .../DbgModelTargetEventContainerImpl.java | 61 +++++++++++------- .../model/impl/DbgModelTargetEventImpl.java | 12 +--- .../DbgModelTargetExceptionContainerImpl.java | 64 ++++++++++++------- .../impl/DbgModelTargetExceptionImpl.java | 18 ++---- 13 files changed, 200 insertions(+), 113 deletions(-) rename Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/{DbgListSpecificFiltersCommand.java => DbgListEventFiltersCommand.java} (51%) create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/control/DebugControlImpl1.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/control/DebugControlImpl1.java index 056ea0a3f6..72295fe833 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/control/DebugControlImpl1.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/control/DebugControlImpl1.java @@ -384,14 +384,14 @@ public class DebugControlImpl1 implements DebugControlInternal { public DebugExceptionFilterInformation getExceptionFilterParameters(int start, int[] codes, int count) { ULONG ulStart = new ULONG(start); - ULONG[] ulCodes = new ULONG[codes.length]; - for (int i = 0; i < codes.length; i++) { - ulCodes[i] = new ULONG(codes[i]); - } + //ULONG[] ulCodes = new ULONG[codes.length]; + //for (int i = 0; i < codes.length; i++) { + // ulCodes[i] = new ULONG(codes[i]); + //} ULONG ulCount = new ULONG(count); DEBUG_EXCEPTION_FILTER_PARAMETERS[] pParams = new DEBUG_EXCEPTION_FILTER_PARAMETERS[count]; COMUtils.checkRC( - jnaControl.GetExceptionFilterParameters(ulCount, ulCodes, ulStart, pParams)); + jnaControl.GetExceptionFilterParameters(ulCount, null, ulStart, pParams)); return new DebugExceptionFilterInformation(count, pParams); } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java index 007ef68206..af13e3d5ab 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java @@ -19,4 +19,6 @@ public interface DbgEventFilter { String getName(); + String getCmd(); + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgExceptionFilter.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgExceptionFilter.java index a1fa35c9e9..dfe9387b82 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgExceptionFilter.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgExceptionFilter.java @@ -19,4 +19,6 @@ public interface DbgExceptionFilter { String getName(); + String getArg(); + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListSpecificFiltersCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java similarity index 51% rename from Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListSpecificFiltersCommand.java rename to Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java index 17e1c23749..d3559707c0 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListSpecificFiltersCommand.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java @@ -18,32 +18,35 @@ package agent.dbgeng.manager.cmd; import java.util.ArrayList; import java.util.List; -import agent.dbgeng.dbgeng.DebugSpecificFilterInformation; -import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_SPECIFIC_FILTER_PARAMETERS; +import agent.dbgeng.dbgeng.DebugControl; +import agent.dbgeng.dbgeng.DebugFilterInformation; +import agent.dbgeng.manager.DbgEventFilter; +import agent.dbgeng.manager.impl.DbgEventFilterImpl; import agent.dbgeng.manager.impl.DbgManagerImpl; -public class DbgListSpecificFiltersCommand - extends AbstractDbgCommand> { - private List result; +public class DbgListEventFiltersCommand + extends AbstractDbgCommand> { + private List result; - public DbgListSpecificFiltersCommand(DbgManagerImpl manager) { + public DbgListEventFiltersCommand(DbgManagerImpl manager) { super(manager); } @Override - public List complete(DbgPendingCommand pending) { + public List complete(DbgPendingCommand pending) { return result; } @Override public void invoke() { result = new ArrayList<>(); - // TODO set parameters - DebugSpecificFilterInformation filterInfo = - manager.getControl().getSpecificFilterParameters(0, 0); - for (int i = 0; i < filterInfo.getNumberOfParameters(); i++) { - DEBUG_SPECIFIC_FILTER_PARAMETERS fi = filterInfo.getParameter(i); - result.add(fi); + DebugControl control = manager.getControl(); + DebugFilterInformation info = control.getNumberEventFilters(); + for (int i = 0; i < info.getNumberEvents(); i++) { + String text = control.getEventFilterText(i); + String cmd = control.getEventFilterCommand(i); + DbgEventFilterImpl f = new DbgEventFilterImpl(text, cmd); + result.add(f); } } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java index 950b06f7af..b88ccadb3f 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java @@ -18,33 +18,33 @@ package agent.dbgeng.manager.cmd; import java.util.ArrayList; import java.util.List; -import agent.dbgeng.dbgeng.DebugExceptionFilterInformation; -import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_EXCEPTION_FILTER_PARAMETERS; +import agent.dbgeng.dbgeng.*; +import agent.dbgeng.manager.DbgExceptionFilter; import agent.dbgeng.manager.impl.DbgManagerImpl; public class DbgListExceptionFiltersCommand - extends AbstractDbgCommand> { - private List result; + extends AbstractDbgCommand> { + private List result; public DbgListExceptionFiltersCommand(DbgManagerImpl manager) { super(manager); } @Override - public List complete(DbgPendingCommand pending) { + public List complete(DbgPendingCommand pending) { return result; } @Override public void invoke() { result = new ArrayList<>(); - // TODO set up codes - int[] codes = new int[0]; - DebugExceptionFilterInformation filterInfo = - manager.getControl().getExceptionFilterParameters(0, codes, 0); - for (int i = 0; i < filterInfo.getNumberOfParameters(); i++) { - DEBUG_EXCEPTION_FILTER_PARAMETERS fi = filterInfo.getParameter(i); - result.add(fi); - } + DebugControl control = manager.getControl(); + DebugFilterInformation info = control.getNumberEventFilters(); + int nEvents = info.getNumberEvents(); + int nExcs = info.getNumberSpecificExceptions(); + DebugSpecificFilterInformation spec = control.getSpecificFilterParameters(0, nEvents); + DebugExceptionFilterInformation exc = + control.getExceptionFilterParameters(nEvents, null, nExcs); + result = new ArrayList<>(); } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java new file mode 100644 index 0000000000..09f9d46e5b --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java @@ -0,0 +1,39 @@ +/* ### + * 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.impl; + +import agent.dbgeng.manager.DbgEventFilter; + +public class DbgEventFilterImpl implements DbgEventFilter { + private final String text; + private final String cmd; + + public DbgEventFilterImpl(String text, String cmd) { + this.text = text; + this.cmd = cmd; + } + + @Override + public String getName() { + return text; + } + + @Override + public String getCmd() { + return cmd; + } + +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java new file mode 100644 index 0000000000..4461c636bc --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java @@ -0,0 +1,39 @@ +/* ### + * 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.impl; + +import agent.dbgeng.manager.DbgExceptionFilter; + +public class DbgExceptionFilterImpl implements DbgExceptionFilter { + private final String text; + private final String cmd; + + public DbgExceptionFilterImpl(String text, String cmd) { + this.text = text; + this.cmd = cmd; + } + + @Override + public String getName() { + return text; + } + + @Override + public String getArg() { + return cmd; + } + +} 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 ef34b36f06..7cc617693d 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 @@ -1584,13 +1584,4 @@ public class DbgManagerImpl implements DbgManager { public long getProcessCount() { return processCount; } - - public CompletableFuture> listEventFilters() { - return CompletableFuture.completedFuture(new HashMap()); - } - - public CompletableFuture> listExceptionFilters() { - return CompletableFuture.completedFuture(new HashMap()); - } - } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetDebugContainerImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetDebugContainerImpl.java index be53560a77..e61f5ad972 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetDebugContainerImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetDebugContainerImpl.java @@ -38,7 +38,7 @@ import ghidra.dbg.target.schema.TargetObjectSchemaInfo; fixed = true), @TargetAttributeType( name = "Exceptions", - type = DbgModelTargetEventContainerImpl.class, + type = DbgModelTargetExceptionContainerImpl.class, required = true, fixed = true), @TargetAttributeType(type = Void.class) diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventContainerImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventContainerImpl.java index f42a1bdbdd..893b2b6c8e 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventContainerImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventContainerImpl.java @@ -21,48 +21,63 @@ import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import agent.dbgeng.manager.DbgEventFilter; +import agent.dbgeng.manager.cmd.DbgListEventFiltersCommand; import agent.dbgeng.manager.impl.DbgManagerImpl; import agent.dbgeng.model.iface2.*; +import ghidra.async.AsyncUtils; import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.schema.*; +import ghidra.util.datastruct.WeakValueHashMap; @TargetObjectSchemaInfo( name = "EventContainer", - elements = { // - @TargetElementType(type = DbgModelTargetEvent.class) // - }, - attributes = { // - @TargetAttributeType(type = Void.class) // - }, + elements = { + @TargetElementType(type = DbgModelTargetEventImpl.class) }, + attributes = { + @TargetAttributeType(type = Void.class) }, canonicalContainer = true) public class DbgModelTargetEventContainerImpl extends DbgModelTargetObjectImpl implements DbgModelTargetEventContainer { + protected final DbgModelTargetDebugContainer debug; + + protected final Map events = + new WeakValueHashMap<>(); + public DbgModelTargetEventContainerImpl(DbgModelTargetDebugContainer debug) { super(debug.getModel(), debug, "Events", "EventContainer"); - } - - public DbgModelTargetEvent getTargetEvent(DbgEventFilter info) { - DbgModelImpl impl = (DbgModelImpl) model; - TargetObject modelObject = impl.getModelObject(info); - if (modelObject != null) { - return (DbgModelTargetEvent) modelObject; - } - return new DbgModelTargetEventImpl(this, info); + this.debug = debug; + requestElements(true); } @Override public CompletableFuture requestElements(boolean refresh) { - DbgManagerImpl manager = getManager(); - return manager.listEventFilters().thenAccept(byName -> { - List filters; + DbgModelTargetProcess targetProcess = getParentProcess(); + if (!refresh || !targetProcess.getProcess().equals(getManager().getCurrentProcess())) { + return AsyncUtils.NIL; + } + return listEventFilters().thenAccept(byName -> { + List eventObjs; synchronized (this) { - filters = byName.values() - .stream() - .map(this::getTargetEvent) - .collect(Collectors.toList()); + eventObjs = byName.stream().map(this::getTargetEvent).collect(Collectors.toList()); } - setElements(filters, Map.of(), "Refreshed"); + setElements(eventObjs, Map.of(), "Refreshed"); }); } + + public synchronized DbgModelTargetEvent getTargetEvent(DbgEventFilter filter) { + String id = filter.getName(); + DbgModelTargetEventImpl event = events.get(id); + if (event != null && event.getFilter().getName().equals(id)) { + return event; + } + event = new DbgModelTargetEventImpl(this, filter); + events.put(filter.getName(), event); + return event; + } + + public CompletableFuture> listEventFilters() { + DbgManagerImpl manager = getManager(); + return manager.execute(new DbgListEventFiltersCommand(manager)); + } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java index 394c9d8f3d..314a4166c2 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java @@ -20,22 +20,12 @@ import agent.dbgeng.model.iface2.DbgModelTargetEvent; import agent.dbgeng.model.iface2.DbgModelTargetEventContainer; import ghidra.dbg.target.schema.*; import ghidra.dbg.util.PathUtils; -import ghidra.program.model.address.Address; @TargetObjectSchemaInfo( - name = "Module", + name = "Event", elements = { @TargetElementType(type = Void.class) }, attributes = { - @TargetAttributeType( - name = "Symbols", - type = DbgModelTargetSymbolContainerImpl.class, - required = true, - fixed = true), - @TargetAttributeType(name = "BaseAddress", type = Address.class), - @TargetAttributeType(name = "ImageName", type = String.class), - @TargetAttributeType(name = "TimeStamp", type = Integer.class), - @TargetAttributeType(name = "Len", type = String.class), @TargetAttributeType(type = Void.class) }) public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl implements DbgModelTargetEvent { diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionContainerImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionContainerImpl.java index c68955b824..4a85bd3f5e 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionContainerImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionContainerImpl.java @@ -21,48 +21,64 @@ import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import agent.dbgeng.manager.DbgExceptionFilter; +import agent.dbgeng.manager.cmd.DbgListExceptionFiltersCommand; import agent.dbgeng.manager.impl.DbgManagerImpl; import agent.dbgeng.model.iface2.*; +import ghidra.async.AsyncUtils; import ghidra.dbg.target.TargetObject; import ghidra.dbg.target.schema.*; +import ghidra.util.datastruct.WeakValueHashMap; @TargetObjectSchemaInfo( name = "ExceptionContainer", - elements = { // - @TargetElementType(type = DbgModelTargetEvent.class) // - }, - attributes = { // - @TargetAttributeType(type = Void.class) // - }, + elements = { + @TargetElementType(type = DbgModelTargetExceptionImpl.class) }, + attributes = { + @TargetAttributeType(type = Void.class) }, canonicalContainer = true) public class DbgModelTargetExceptionContainerImpl extends DbgModelTargetObjectImpl - implements DbgModelTargetEventContainer { + implements DbgModelTargetExceptionContainer { + + protected final DbgModelTargetDebugContainer debug; + + protected final Map exceptions = + new WeakValueHashMap<>(); public DbgModelTargetExceptionContainerImpl(DbgModelTargetDebugContainer debug) { super(debug.getModel(), debug, "Exceptions", "ExceptionContainer"); - } - - public DbgModelTargetException getTargetException(DbgExceptionFilter info) { - DbgModelImpl impl = (DbgModelImpl) model; - TargetObject modelObject = impl.getModelObject(info); - if (modelObject != null) { - return (DbgModelTargetException) modelObject; - } - return new DbgModelTargetExceptionImpl(this, info); + this.debug = debug; + requestElements(true); } @Override public CompletableFuture requestElements(boolean refresh) { - DbgManagerImpl manager = getManager(); - return manager.listExceptionFilters().thenAccept(byName -> { - List filters; + DbgModelTargetProcess targetProcess = getParentProcess(); + if (!refresh || !targetProcess.getProcess().equals(getManager().getCurrentProcess())) { + return AsyncUtils.NIL; + } + return listExceptionFilters().thenAccept(byName -> { + List excObjs; synchronized (this) { - filters = byName.values() - .stream() - .map(this::getTargetException) - .collect(Collectors.toList()); + excObjs = + byName.stream().map(this::getTargetException).collect(Collectors.toList()); } - setElements(filters, Map.of(), "Refreshed"); + setElements(excObjs, Map.of(), "Refreshed"); }); } + + public synchronized DbgModelTargetException getTargetException(DbgExceptionFilter filter) { + String id = filter.getName(); + DbgModelTargetExceptionImpl exc = exceptions.get(id); + if (exc != null && exc.getFilter().getName().equals(id)) { + return exc; + } + exc = new DbgModelTargetExceptionImpl(this, filter); + exceptions.put(filter.getName(), exc); + return exc; + } + + public CompletableFuture> listExceptionFilters() { + DbgManagerImpl manager = getManager(); + return manager.execute(new DbgListExceptionFiltersCommand(manager)); + } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java index c93f807123..78da2d163e 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java @@ -16,26 +16,16 @@ package agent.dbgeng.model.impl; import agent.dbgeng.manager.DbgExceptionFilter; -import agent.dbgeng.model.iface2.DbgModelTargetEventContainer; import agent.dbgeng.model.iface2.DbgModelTargetException; +import agent.dbgeng.model.iface2.DbgModelTargetExceptionContainer; import ghidra.dbg.target.schema.*; import ghidra.dbg.util.PathUtils; -import ghidra.program.model.address.Address; @TargetObjectSchemaInfo( - name = "Module", + name = "Exception", elements = { @TargetElementType(type = Void.class) }, attributes = { - @TargetAttributeType( - name = "Symbols", - type = DbgModelTargetSymbolContainerImpl.class, - required = true, - fixed = true), - @TargetAttributeType(name = "BaseAddress", type = Address.class), - @TargetAttributeType(name = "ImageName", type = String.class), - @TargetAttributeType(name = "TimeStamp", type = Integer.class), - @TargetAttributeType(name = "Len", type = String.class), @TargetAttributeType(type = Void.class) }) public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl implements DbgModelTargetException { @@ -49,9 +39,9 @@ public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl private DbgExceptionFilter filter; - public DbgModelTargetExceptionImpl(DbgModelTargetEventContainer events, + public DbgModelTargetExceptionImpl(DbgModelTargetExceptionContainer exceptions, DbgExceptionFilter filter) { - super(events.getModel(), events, keyFilter(filter), "ExceptionFilter"); + super(exceptions.getModel(), exceptions, keyFilter(filter), "ExceptionFilter"); this.getModel().addModelObject(filter, this); this.filter = filter; From 2c5b8d58638d1314cd21a35355eee5900822b19e Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Tue, 21 Sep 2021 22:58:08 +0000 Subject: [PATCH 06/17] GP-1288: Objects view for events/exceptions working --- .../jna/dbgeng/control/WrapIDebugControl.java | 15 +++++--- .../agent/dbgeng/manager/DbgEventFilter.java | 8 ++++ .../dbgeng/manager/DbgExceptionFilter.java | 13 ++++++- .../cmd/DbgListEventFiltersCommand.java | 10 +++-- .../cmd/DbgListExceptionFiltersCommand.java | 15 +++++++- .../manager/impl/DbgEventFilterImpl.java | 26 ++++++++++++- .../manager/impl/DbgExceptionFilterImpl.java | 37 ++++++++++++++++++- .../model/impl/DbgModelTargetEventImpl.java | 21 ++++------- .../impl/DbgModelTargetExceptionImpl.java | 23 +++++------- 9 files changed, 127 insertions(+), 41 deletions(-) diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/WrapIDebugControl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/WrapIDebugControl.java index be19407fb9..ef2f0b6ef9 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/WrapIDebugControl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/jna/dbgeng/control/WrapIDebugControl.java @@ -206,38 +206,41 @@ public class WrapIDebugControl extends UnknownWithUtils implements IDebugControl @Override public HRESULT GetSpecificFilterParameters(ULONG Start, ULONG Count, DEBUG_SPECIFIC_FILTER_PARAMETERS[] Params) { - return _invokeHR(VTIndices.SET_EVENT_FILTER_COMMAND, getPointer(), Start, Count, Params); + return _invokeHR(VTIndices.GET_SPECIFIC_FILTER_PARAMETERS, getPointer(), Start, Count, + Params); } @Override public HRESULT SetSpecificFilterParameters(ULONG Start, ULONG Count, DEBUG_SPECIFIC_FILTER_PARAMETERS[] Params) { - return _invokeHR(VTIndices.SET_EVENT_FILTER_COMMAND, getPointer(), Start, Count, Params); + return _invokeHR(VTIndices.SET_SPECIFIC_FILTER_PARAMETERS, getPointer(), Start, Count, + Params); } @Override public HRESULT GetSpecificFilterArgument(ULONG Index, byte[] Buffer, ULONG BufferSize, ULONGByReference ArgumentSize) { - return _invokeHR(VTIndices.SET_EVENT_FILTER_COMMAND, getPointer(), Index, Buffer, + return _invokeHR(VTIndices.GET_SPECIFIC_FILTER_ARGUMENT, getPointer(), Index, Buffer, BufferSize, ArgumentSize); } @Override public HRESULT SetSpecificFilterArgument(ULONG Index, String Argument) { - return _invokeHR(VTIndices.SET_EVENT_FILTER_COMMAND, getPointer(), Index, Argument); + return _invokeHR(VTIndices.SET_SPECIFIC_FILTER_ARGUMENT, getPointer(), Index, Argument); } @Override public HRESULT GetExceptionFilterParameters(ULONG Count, ULONG[] Codes, ULONG Start, DEBUG_EXCEPTION_FILTER_PARAMETERS[] Params) { - return _invokeHR(VTIndices.SET_EVENT_FILTER_COMMAND, getPointer(), Count, Codes, Start, + return _invokeHR(VTIndices.GET_EXCEPTION_FILTER_PARAMETERS, getPointer(), Count, Codes, + Start, Params); } @Override public HRESULT SetExceptionFilterParameters(ULONG Count, DEBUG_EXCEPTION_FILTER_PARAMETERS[] Params) { - return _invokeHR(VTIndices.SET_EVENT_FILTER_COMMAND, getPointer(), Count, Params); + return _invokeHR(VTIndices.SET_EXCEPTION_FILTER_PARAMETERS, getPointer(), Count, Params); } @Override diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java index af13e3d5ab..cf7946a74b 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java @@ -21,4 +21,12 @@ public interface DbgEventFilter { String getCmd(); + int getExecutionOption(); + + void setExecutionOption(int executionOption); + + int getContinueOption(); + + void setContinueOption(int continueOption); + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgExceptionFilter.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgExceptionFilter.java index dfe9387b82..e62b3fad41 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgExceptionFilter.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgExceptionFilter.java @@ -19,6 +19,17 @@ public interface DbgExceptionFilter { String getName(); - String getArg(); + String getCmd(); + String getSecondCmd(); + + int getExecutionOption(); + + void setExecutionOption(int executionOption); + + int getContinueOption(); + + void setContinueOption(int continueOption); + + long getExceptionCode(); } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java index d3559707c0..8c2bf4cea3 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java @@ -18,8 +18,8 @@ package agent.dbgeng.manager.cmd; import java.util.ArrayList; import java.util.List; -import agent.dbgeng.dbgeng.DebugControl; -import agent.dbgeng.dbgeng.DebugFilterInformation; +import agent.dbgeng.dbgeng.*; +import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_SPECIFIC_FILTER_PARAMETERS; import agent.dbgeng.manager.DbgEventFilter; import agent.dbgeng.manager.impl.DbgEventFilterImpl; import agent.dbgeng.manager.impl.DbgManagerImpl; @@ -42,10 +42,14 @@ public class DbgListEventFiltersCommand result = new ArrayList<>(); DebugControl control = manager.getControl(); DebugFilterInformation info = control.getNumberEventFilters(); + DebugSpecificFilterInformation exc = + control.getSpecificFilterParameters(0, info.getNumberEvents()); for (int i = 0; i < info.getNumberEvents(); i++) { String text = control.getEventFilterText(i); String cmd = control.getEventFilterCommand(i); - DbgEventFilterImpl f = new DbgEventFilterImpl(text, cmd); + DEBUG_SPECIFIC_FILTER_PARAMETERS p = exc.getParameter(i); + DbgEventFilterImpl f = new DbgEventFilterImpl(text, cmd, p.ExecutionOption.intValue(), + p.ContinueOption.intValue()); result.add(f); } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java index b88ccadb3f..8006d2ecd1 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java @@ -19,7 +19,9 @@ import java.util.ArrayList; import java.util.List; import agent.dbgeng.dbgeng.*; +import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_EXCEPTION_FILTER_PARAMETERS; import agent.dbgeng.manager.DbgExceptionFilter; +import agent.dbgeng.manager.impl.DbgExceptionFilterImpl; import agent.dbgeng.manager.impl.DbgManagerImpl; public class DbgListExceptionFiltersCommand @@ -42,9 +44,18 @@ public class DbgListExceptionFiltersCommand DebugFilterInformation info = control.getNumberEventFilters(); int nEvents = info.getNumberEvents(); int nExcs = info.getNumberSpecificExceptions(); - DebugSpecificFilterInformation spec = control.getSpecificFilterParameters(0, nEvents); + //DebugSpecificFilterInformation spec = control.getSpecificFilterParameters(0, nEvents); DebugExceptionFilterInformation exc = control.getExceptionFilterParameters(nEvents, null, nExcs); - result = new ArrayList<>(); + for (int i = 0; i < exc.getParameters().length; i++) { + DEBUG_EXCEPTION_FILTER_PARAMETERS p = exc.getParameter(i); + String text = control.getEventFilterText(nEvents + i); + String cmd = control.getEventFilterCommand(nEvents + i); + String cmd2 = control.getExceptionFilterSecondCommand(nEvents + i); + DbgExceptionFilterImpl filter = new DbgExceptionFilterImpl(text, cmd, cmd2, + p.ExecutionOption.intValue(), p.ContinueOption.intValue(), + p.ExceptionCode.longValue()); + result.add(filter); + } } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java index 09f9d46e5b..a360f22a36 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java @@ -20,10 +20,14 @@ import agent.dbgeng.manager.DbgEventFilter; public class DbgEventFilterImpl implements DbgEventFilter { private final String text; private final String cmd; + private int executionOption; + private int continueOption; - public DbgEventFilterImpl(String text, String cmd) { + public DbgEventFilterImpl(String text, String cmd, int executionOption, int continueOption) { this.text = text; this.cmd = cmd; + this.setExecutionOption(executionOption); + this.setContinueOption(continueOption); } @Override @@ -36,4 +40,24 @@ public class DbgEventFilterImpl implements DbgEventFilter { return cmd; } + @Override + public int getExecutionOption() { + return executionOption; + } + + @Override + public void setExecutionOption(int executionOption) { + this.executionOption = executionOption; + } + + @Override + public int getContinueOption() { + return continueOption; + } + + @Override + public void setContinueOption(int continueOption) { + this.continueOption = continueOption; + } + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java index 4461c636bc..8db4a75d75 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java @@ -20,10 +20,19 @@ import agent.dbgeng.manager.DbgExceptionFilter; public class DbgExceptionFilterImpl implements DbgExceptionFilter { private final String text; private final String cmd; + private final String cmd2; + private int executionOption; + private int continueOption; + private long exceptionCode; - public DbgExceptionFilterImpl(String text, String cmd) { + public DbgExceptionFilterImpl(String text, String cmd, String cmd2, int executionOption, + int continueOption, long exceptionCode) { this.text = text; this.cmd = cmd; + this.cmd2 = cmd2; + this.setExecutionOption(executionOption); + this.setContinueOption(continueOption); + this.exceptionCode = exceptionCode; } @Override @@ -32,8 +41,32 @@ public class DbgExceptionFilterImpl implements DbgExceptionFilter { } @Override - public String getArg() { + public String getCmd() { return cmd; } + public String getSecondCmd() { + return cmd2; + } + + public int getExecutionOption() { + return executionOption; + } + + public void setExecutionOption(int executionOption) { + this.executionOption = executionOption; + } + + public int getContinueOption() { + return continueOption; + } + + public void setContinueOption(int continueOption) { + this.continueOption = continueOption; + } + + public long getExceptionCode() { + return exceptionCode; + } + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java index 314a4166c2..4577b5ff1d 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java @@ -15,6 +15,9 @@ */ package agent.dbgeng.model.impl; +import java.util.List; +import java.util.Map; + import agent.dbgeng.manager.DbgEventFilter; import agent.dbgeng.model.iface2.DbgModelTargetEvent; import agent.dbgeng.model.iface2.DbgModelTargetEventContainer; @@ -26,7 +29,7 @@ import ghidra.dbg.util.PathUtils; elements = { @TargetElementType(type = Void.class) }, attributes = { - @TargetAttributeType(type = Void.class) }) + @TargetAttributeType(type = Object.class) }) public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl implements DbgModelTargetEvent { protected static String indexFilter(DbgEventFilter filter) { @@ -44,20 +47,12 @@ public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl this.getModel().addModelObject(filter, this); this.filter = filter; - /* - changeAttributes(List.of(), List.of( // - symbols // - // sections.getName(), sections, // - ), Map.of( // + changeAttributes(List.of(), List.of(), Map.of( // DISPLAY_ATTRIBUTE_NAME, getIndex(), // - SHORT_DISPLAY_ATTRIBUTE_NAME, module.getName(), // - MODULE_NAME_ATTRIBUTE_NAME, module.getImageName(), // - "BaseAddress", space.getAddress(module.getKnownBase()), // - "ImageName", module.getImageName(), // - "TimeStamp", module.getTimeStamp(), // - "Len", Integer.toHexString(module.getSize()) // + "Command", filter.getCmd(), // + "Execute", filter.getExecutionOption(), // + "Continue", filter.getContinueOption() // ), "Initialized"); - */ } @Override diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java index 78da2d163e..fea9fd4162 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java @@ -15,6 +15,9 @@ */ package agent.dbgeng.model.impl; +import java.util.List; +import java.util.Map; + import agent.dbgeng.manager.DbgExceptionFilter; import agent.dbgeng.model.iface2.DbgModelTargetException; import agent.dbgeng.model.iface2.DbgModelTargetExceptionContainer; @@ -26,7 +29,7 @@ import ghidra.dbg.util.PathUtils; elements = { @TargetElementType(type = Void.class) }, attributes = { - @TargetAttributeType(type = Void.class) }) + @TargetAttributeType(type = Object.class) }) public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl implements DbgModelTargetException { protected static String indexFilter(DbgExceptionFilter filter) { @@ -45,20 +48,14 @@ public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl this.getModel().addModelObject(filter, this); this.filter = filter; - /* - changeAttributes(List.of(), List.of( // - symbols // - // sections.getName(), sections, // - ), Map.of( // + changeAttributes(List.of(), List.of(), Map.of( // DISPLAY_ATTRIBUTE_NAME, getIndex(), // - SHORT_DISPLAY_ATTRIBUTE_NAME, module.getName(), // - MODULE_NAME_ATTRIBUTE_NAME, module.getImageName(), // - "BaseAddress", space.getAddress(module.getKnownBase()), // - "ImageName", module.getImageName(), // - "TimeStamp", module.getTimeStamp(), // - "Len", Integer.toHexString(module.getSize()) // + "Command", filter.getCmd(), // + "SecondCmd", filter.getCmd(), // + "Execute", filter.getExecutionOption(), // + "Continue", filter.getContinueOption(), // + "Exception", Long.toHexString(filter.getExceptionCode()) // ), "Initialized"); - */ } @Override From cd1b5f6592db1a04e9564966a0893bea5d19ac56 Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Wed, 22 Sep 2021 15:54:14 +0000 Subject: [PATCH 07/17] GP-1288: convert options to objects --- .../agent/dbgeng/dbgeng/DebugControl.java | 49 ++++++++++ .../dbgeng/manager/DbgExceptionFilter.java | 16 +--- .../manager/impl/DbgEventFilterImpl.java | 8 +- .../manager/impl/DbgExceptionFilterImpl.java | 42 +-------- .../iface2/DbgModelTargetEventOption.java | 27 ++++++ .../model/impl/DbgModelTargetEventImpl.java | 19 +++- .../impl/DbgModelTargetEventOptionImpl.java | 94 +++++++++++++++++++ .../impl/DbgModelTargetExceptionImpl.java | 21 ++++- 8 files changed, 212 insertions(+), 64 deletions(-) create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventOptionImpl.java diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java index c7ac845713..bcf66bdfa9 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java @@ -114,6 +114,55 @@ public interface DebugControl extends DebugControlReentrant { ; } + public static enum DebugFilterExecutionOption { + DEBUG_FILTER_BREAK(0, "Break"), // + DEBUG_FILTER_SECOND_CHANCE_BREAK(1, "Second-chance Break"), // + DEBUG_FILTER_OUTPUT(2, "Output-only"), // + DEBUG_FILTER_IGNORE(3, "Ignore"), // + DEBUG_FILTER_REMOVE(4, "Remove"), // + ; + + public static DebugFilterExecutionOption getByNumber(int val) { + for (DebugFilterExecutionOption m : DebugFilterExecutionOption.values()) { + if (m.val == val) { + return m; + } + } + return null; + } + + DebugFilterExecutionOption(int val, String description) { + this.val = val; + this.description = description; + } + + public final int val; + public final String description; + } + + public static enum DebugFilterContinuationOption { + DEBUG_FILTER_GO_HANDLED(0, "Handled"), // + DEBUG_FILTER_GO_NOT_HANDLED(1, "Not Handled"), // + ; + + public static DebugFilterContinuationOption getByNumber(int val) { + for (DebugFilterContinuationOption m : DebugFilterContinuationOption.values()) { + if (m.val == val) { + return m; + } + } + return null; + } + + DebugFilterContinuationOption(int val, String description) { + this.val = val; + this.description = description; + } + + public final int val; + public final String description; + } + boolean getInterrupt(); int getInterruptTimeout(); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgExceptionFilter.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgExceptionFilter.java index e62b3fad41..c053f4c6fe 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgExceptionFilter.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgExceptionFilter.java @@ -15,21 +15,9 @@ */ package agent.dbgeng.manager; -public interface DbgExceptionFilter { - - String getName(); - - String getCmd(); +public interface DbgExceptionFilter extends DbgEventFilter { String getSecondCmd(); - int getExecutionOption(); - - void setExecutionOption(int executionOption); - - int getContinueOption(); - - void setContinueOption(int continueOption); - - long getExceptionCode(); + String getExceptionCode(); } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java index a360f22a36..9fbff3fda0 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java @@ -18,10 +18,10 @@ package agent.dbgeng.manager.impl; import agent.dbgeng.manager.DbgEventFilter; public class DbgEventFilterImpl implements DbgEventFilter { - private final String text; - private final String cmd; - private int executionOption; - private int continueOption; + protected final String text; + protected final String cmd; + protected int executionOption; + protected int continueOption; public DbgEventFilterImpl(String text, String cmd, int executionOption, int continueOption) { this.text = text; diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java index 8db4a75d75..4e32f78cca 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java @@ -17,56 +17,24 @@ package agent.dbgeng.manager.impl; import agent.dbgeng.manager.DbgExceptionFilter; -public class DbgExceptionFilterImpl implements DbgExceptionFilter { - private final String text; - private final String cmd; +public class DbgExceptionFilterImpl extends DbgEventFilterImpl implements DbgExceptionFilter { + private final String cmd2; - private int executionOption; - private int continueOption; private long exceptionCode; public DbgExceptionFilterImpl(String text, String cmd, String cmd2, int executionOption, int continueOption, long exceptionCode) { - this.text = text; - this.cmd = cmd; + super(text, cmd, executionOption, continueOption); this.cmd2 = cmd2; - this.setExecutionOption(executionOption); - this.setContinueOption(continueOption); this.exceptionCode = exceptionCode; } - @Override - public String getName() { - return text; - } - - @Override - public String getCmd() { - return cmd; - } - public String getSecondCmd() { return cmd2; } - public int getExecutionOption() { - return executionOption; - } - - public void setExecutionOption(int executionOption) { - this.executionOption = executionOption; - } - - public int getContinueOption() { - return continueOption; - } - - public void setContinueOption(int continueOption) { - this.continueOption = continueOption; - } - - public long getExceptionCode() { - return exceptionCode; + public String getExceptionCode() { + return Long.toHexString(exceptionCode); } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java new file mode 100644 index 0000000000..3300d54e76 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java @@ -0,0 +1,27 @@ +/* ### + * 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.model.iface2; + +import ghidra.dbg.target.TargetTogglable; + +public interface DbgModelTargetEventOption extends DbgModelTargetObject, TargetTogglable { + + @Override + public default String getDisplay() { + return getName(); + } + +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java index 4577b5ff1d..3b5e644c8b 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java @@ -18,9 +18,10 @@ package agent.dbgeng.model.impl; import java.util.List; import java.util.Map; +import agent.dbgeng.dbgeng.DebugControl.DebugFilterContinuationOption; +import agent.dbgeng.dbgeng.DebugControl.DebugFilterExecutionOption; import agent.dbgeng.manager.DbgEventFilter; -import agent.dbgeng.model.iface2.DbgModelTargetEvent; -import agent.dbgeng.model.iface2.DbgModelTargetEventContainer; +import agent.dbgeng.model.iface2.*; import ghidra.dbg.target.schema.*; import ghidra.dbg.util.PathUtils; @@ -40,6 +41,9 @@ public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl return PathUtils.makeKey(indexFilter(filter)); } + protected DbgModelTargetEventOption execOption; + protected DbgModelTargetEventOption contOption; + private DbgEventFilter filter; public DbgModelTargetEventImpl(DbgModelTargetEventContainer events, DbgEventFilter filter) { @@ -47,11 +51,18 @@ public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl this.getModel().addModelObject(filter, this); this.filter = filter; + DebugFilterExecutionOption exec = + DebugFilterExecutionOption.getByNumber(filter.getExecutionOption()); + DebugFilterContinuationOption cont = + DebugFilterContinuationOption.getByNumber(filter.getContinueOption()); + execOption = new DbgModelTargetEventOptionImpl(this, exec); + contOption = new DbgModelTargetEventOptionImpl(this, cont); + changeAttributes(List.of(), List.of(), Map.of( // DISPLAY_ATTRIBUTE_NAME, getIndex(), // "Command", filter.getCmd(), // - "Execute", filter.getExecutionOption(), // - "Continue", filter.getContinueOption() // + "Execute", execOption, // + "Continue", contOption // ), "Initialized"); } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventOptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventOptionImpl.java new file mode 100644 index 0000000000..15a3d13011 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventOptionImpl.java @@ -0,0 +1,94 @@ +/* ### + * 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.model.impl; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +import agent.dbgeng.dbgeng.DebugControl.DebugFilterContinuationOption; +import agent.dbgeng.dbgeng.DebugControl.DebugFilterExecutionOption; +import agent.dbgeng.model.iface2.*; +import ghidra.dbg.target.schema.*; +import ghidra.dbg.util.PathUtils; + +@TargetObjectSchemaInfo( + name = "Event", + elements = { + @TargetElementType(type = Void.class) }, + attributes = { + @TargetAttributeType(type = Object.class) }) +public class DbgModelTargetEventOptionImpl extends DbgModelTargetObjectImpl + implements DbgModelTargetEventOption { + + protected static String keyFilter(DebugFilterExecutionOption option) { + return PathUtils.makeKey(option.description); + } + + protected static String keyFilter(DebugFilterContinuationOption option) { + return PathUtils.makeKey(option.description); + } + + private DebugFilterExecutionOption optionEx; + private DebugFilterContinuationOption optionCont; + + public DbgModelTargetEventOptionImpl(DbgModelTargetEvent event, + DebugFilterExecutionOption option) { + super(event.getModel(), event, keyFilter(option), "EventFilter"); + this.getModel().addModelObject(option, this); + this.optionEx = option; + } + + public DbgModelTargetEventOptionImpl(DbgModelTargetEvent event, + DebugFilterContinuationOption option) { + super(event.getModel(), event, keyFilter(option), "EventFilter"); + this.getModel().addModelObject(option, this); + this.optionCont = option; + } + + public DbgModelTargetEventOptionImpl(DbgModelTargetException exc, + DebugFilterExecutionOption option) { + super(exc.getModel(), exc, keyFilter(option), "EventFilter"); + this.getModel().addModelObject(option, this); + this.optionEx = option; + } + + public DbgModelTargetEventOptionImpl(DbgModelTargetException exc, + DebugFilterContinuationOption option) { + super(exc.getModel(), exc, keyFilter(option), "EventFilter"); + this.getModel().addModelObject(option, this); + this.optionCont = option; + } + + @Override + public CompletableFuture disable() { + // TODO Auto-generated method stub + return null; + } + + @Override + public CompletableFuture enable() { + // TODO Auto-generated method stub + return null; + } + + public void setAttributes() { + changeAttributes(List.of(), List.of(), Map.of( // + DISPLAY_ATTRIBUTE_NAME, getName() // + ), "Initialized"); + } + +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java index fea9fd4162..2f58e36bac 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java @@ -18,9 +18,10 @@ package agent.dbgeng.model.impl; import java.util.List; import java.util.Map; +import agent.dbgeng.dbgeng.DebugControl.DebugFilterContinuationOption; +import agent.dbgeng.dbgeng.DebugControl.DebugFilterExecutionOption; import agent.dbgeng.manager.DbgExceptionFilter; -import agent.dbgeng.model.iface2.DbgModelTargetException; -import agent.dbgeng.model.iface2.DbgModelTargetExceptionContainer; +import agent.dbgeng.model.iface2.*; import ghidra.dbg.target.schema.*; import ghidra.dbg.util.PathUtils; @@ -40,6 +41,9 @@ public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl return PathUtils.makeKey(indexFilter(filter)); } + protected DbgModelTargetEventOption execOption; + protected DbgModelTargetEventOption contOption; + private DbgExceptionFilter filter; public DbgModelTargetExceptionImpl(DbgModelTargetExceptionContainer exceptions, @@ -48,13 +52,20 @@ public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl this.getModel().addModelObject(filter, this); this.filter = filter; + DebugFilterExecutionOption exec = + DebugFilterExecutionOption.getByNumber(filter.getExecutionOption()); + DebugFilterContinuationOption cont = + DebugFilterContinuationOption.getByNumber(filter.getContinueOption()); + execOption = new DbgModelTargetEventOptionImpl(this, exec); + contOption = new DbgModelTargetEventOptionImpl(this, cont); + changeAttributes(List.of(), List.of(), Map.of( // DISPLAY_ATTRIBUTE_NAME, getIndex(), // "Command", filter.getCmd(), // "SecondCmd", filter.getCmd(), // - "Execute", filter.getExecutionOption(), // - "Continue", filter.getContinueOption(), // - "Exception", Long.toHexString(filter.getExceptionCode()) // + "Execute", execOption, // + "Continue", contOption, // + "Exception", filter.getExceptionCode() // ), "Initialized"); } From 9c3084ccee6af48629bf238b9ec919cb47c69296 Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Wed, 22 Sep 2021 22:05:28 +0000 Subject: [PATCH 08/17] GP-1288: more visible clues --- .../agent/dbgeng/dbgeng/DebugControl.java | 14 +++ .../agent/dbgeng/manager/DbgEventFilter.java | 2 + .../dbgeng/manager/DbgEventsListener.java | 9 ++ .../manager/DbgEventsListenerAdapter.java | 6 ++ .../cmd/DbgListEventFiltersCommand.java | 5 +- .../cmd/DbgListExceptionFiltersCommand.java | 2 +- .../cmd/DbgToggleContinuationCommand.java | 60 ++++++++++++ .../cmd/DbgToggleExecutionCommand.java | 60 ++++++++++++ .../manager/impl/DbgEventFilterImpl.java | 11 ++- .../manager/impl/DbgExceptionFilterImpl.java | 5 +- .../dbgeng/manager/impl/DbgManagerImpl.java | 9 +- .../agent/dbgeng/model/AbstractDbgModel.java | 2 + .../model/iface2/DbgModelTargetEvent.java | 17 ++-- .../iface2/DbgModelTargetEventOption.java | 5 - .../model/iface2/DbgModelTargetException.java | 7 +- .../agent/dbgeng/model/impl/DbgModelImpl.java | 1 + ...DbgModelTargetContinuationOptionImpl.java} | 69 ++++++-------- .../model/impl/DbgModelTargetEventImpl.java | 51 +++++++++- .../impl/DbgModelTargetExceptionImpl.java | 31 ++++++- .../DbgModelTargetExecutionOptionImpl.java | 81 ++++++++++++++++ .../dbgmodel/model/impl/DbgModel2Impl.java | 5 + .../core/debug/gui/DebuggerResources.java | 16 ++++ .../gui/objects/DebuggerObjectsProvider.java | 92 +++++++++++-------- 23 files changed, 454 insertions(+), 106 deletions(-) create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgToggleContinuationCommand.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgToggleExecutionCommand.java rename Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/{DbgModelTargetEventOptionImpl.java => DbgModelTargetContinuationOptionImpl.java} (52%) create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java index bcf66bdfa9..46dfa561f1 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java @@ -114,6 +114,20 @@ public interface DebugControl extends DebugControlReentrant { ; } + public static enum DebugFilterOrdinals { + DEBUG_FILTER_CREATE_THREAD, // + DEBUG_FILTER_EXIT_THREAD, // + DEBUG_FILTER_CREATE_PROCESS, // + DEBUG_FILTER_EXIT_PROCESS, // + DEBUG_FILTER_LOAD_MODULE, // + DEBUG_FILTER_UNLOAD_MODULE, // + DEBUG_FILTER_SYSTEM_ERROR, // + DEBUG_FILTER_INITIAL_BREAKPOINT, // + DEBUG_FILTER_INITIAL_MODULE_LOAD, // + DEBUG_FILTER_DEBUGGEE_OUTPUT, // + ; + } + public static enum DebugFilterExecutionOption { DEBUG_FILTER_BREAK(0, "Break"), // DEBUG_FILTER_SECOND_CHANCE_BREAK(1, "Second-chance Break"), // diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java index cf7946a74b..e5052cc383 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java @@ -17,6 +17,8 @@ package agent.dbgeng.manager; public interface DbgEventFilter { + int getIndex(); + String getName(); String getCmd(); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventsListener.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventsListener.java index de3d2595c5..768fa6361b 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventsListener.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventsListener.java @@ -17,6 +17,7 @@ package agent.dbgeng.manager; import agent.dbgeng.dbgeng.*; import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo; +import agent.dbgeng.manager.evt.AbstractDbgEvent; public interface DbgEventsListener { @@ -123,6 +124,14 @@ public interface DbgEventsListener { */ void threadSelected(DbgThread thread, DbgStackFrame frame, DbgCause cause); + /** + * A system event has occurred (gained focus) + * + * @param event a handle to the current event + * @param cause the cause of this event + */ + void eventSelected(AbstractDbgEvent event, DbgCause cause); + /** * A module has been loaded by an process * diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventsListenerAdapter.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventsListenerAdapter.java index 80781c35db..794e667600 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventsListenerAdapter.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventsListenerAdapter.java @@ -17,6 +17,7 @@ package agent.dbgeng.manager; import agent.dbgeng.dbgeng.*; import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo; +import agent.dbgeng.manager.evt.AbstractDbgEvent; public interface DbgEventsListenerAdapter extends DbgEventsListener { @@ -82,6 +83,11 @@ public interface DbgEventsListenerAdapter extends DbgEventsListener { // Extension point } + @Override + public default void eventSelected(AbstractDbgEvent event, DbgCause cause) { + // Extension point + } + @Override public default void moduleLoaded(DbgProcess process, DebugModuleInfo info, DbgCause cause) { // Extension point diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java index 8c2bf4cea3..c63254af28 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java @@ -48,8 +48,9 @@ public class DbgListEventFiltersCommand String text = control.getEventFilterText(i); String cmd = control.getEventFilterCommand(i); DEBUG_SPECIFIC_FILTER_PARAMETERS p = exc.getParameter(i); - DbgEventFilterImpl f = new DbgEventFilterImpl(text, cmd, p.ExecutionOption.intValue(), - p.ContinueOption.intValue()); + DbgEventFilterImpl f = + new DbgEventFilterImpl(i, text, cmd, p.ExecutionOption.intValue(), + p.ContinueOption.intValue()); result.add(f); } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java index 8006d2ecd1..27a19a04c6 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java @@ -52,7 +52,7 @@ public class DbgListExceptionFiltersCommand String text = control.getEventFilterText(nEvents + i); String cmd = control.getEventFilterCommand(nEvents + i); String cmd2 = control.getExceptionFilterSecondCommand(nEvents + i); - DbgExceptionFilterImpl filter = new DbgExceptionFilterImpl(text, cmd, cmd2, + DbgExceptionFilterImpl filter = new DbgExceptionFilterImpl(i, text, cmd, cmd2, p.ExecutionOption.intValue(), p.ContinueOption.intValue(), p.ExceptionCode.longValue()); result.add(filter); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgToggleContinuationCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgToggleContinuationCommand.java new file mode 100644 index 0000000000..743996685f --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgToggleContinuationCommand.java @@ -0,0 +1,60 @@ +/* ### + * 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 com.sun.jna.platform.win32.WinDef.ULONG; + +import agent.dbgeng.dbgeng.*; +import agent.dbgeng.dbgeng.DebugControl.DebugFilterContinuationOption; +import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_EXCEPTION_FILTER_PARAMETERS; +import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_SPECIFIC_FILTER_PARAMETERS; +import agent.dbgeng.manager.impl.DbgManagerImpl; + +public class DbgToggleContinuationCommand + extends AbstractDbgCommand { + + private int index; + private DebugFilterContinuationOption optionCont; + + public DbgToggleContinuationCommand(DbgManagerImpl manager, int index, + DebugFilterContinuationOption optionCont) { + super(manager); + this.index = index; + this.optionCont = optionCont; + } + + @Override + public void invoke() { + DebugControl control = manager.getControl(); + DebugFilterInformation info = control.getNumberEventFilters(); + int nEvents = info.getNumberEvents(); + int nExcs = info.getNumberSpecificExceptions(); + if (index < nEvents) { + DebugSpecificFilterInformation exc = + control.getSpecificFilterParameters(0, nEvents); + DEBUG_SPECIFIC_FILTER_PARAMETERS p = exc.getParameter(index); + p.ContinueOption = new ULONG(optionCont.ordinal()); + control.setSpecificFilterParameters(0, nEvents, exc); + } + else { + DebugExceptionFilterInformation exc = + control.getExceptionFilterParameters(nEvents, null, nExcs); + DEBUG_EXCEPTION_FILTER_PARAMETERS p = exc.getParameter(index); + p.ContinueOption = new ULONG(optionCont.ordinal()); + control.setExceptionFilterParameters(nExcs, exc); + } + } +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgToggleExecutionCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgToggleExecutionCommand.java new file mode 100644 index 0000000000..e612f1e1e8 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgToggleExecutionCommand.java @@ -0,0 +1,60 @@ +/* ### + * 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 com.sun.jna.platform.win32.WinDef.ULONG; + +import agent.dbgeng.dbgeng.*; +import agent.dbgeng.dbgeng.DebugControl.DebugFilterExecutionOption; +import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_EXCEPTION_FILTER_PARAMETERS; +import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_SPECIFIC_FILTER_PARAMETERS; +import agent.dbgeng.manager.impl.DbgManagerImpl; + +public class DbgToggleExecutionCommand + extends AbstractDbgCommand { + + private int index; + private DebugFilterExecutionOption optionCont; + + public DbgToggleExecutionCommand(DbgManagerImpl manager, int index, + DebugFilterExecutionOption optionCont) { + super(manager); + this.index = index; + this.optionCont = optionCont; + } + + @Override + public void invoke() { + DebugControl control = manager.getControl(); + DebugFilterInformation info = control.getNumberEventFilters(); + int nEvents = info.getNumberEvents(); + int nExcs = info.getNumberSpecificExceptions(); + if (index < nEvents) { + DebugSpecificFilterInformation exc = + control.getSpecificFilterParameters(0, nEvents); + DEBUG_SPECIFIC_FILTER_PARAMETERS p = exc.getParameter(index); + p.ExecutionOption = new ULONG(optionCont.ordinal()); + control.setSpecificFilterParameters(0, nEvents, exc); + } + else { + DebugExceptionFilterInformation exc = + control.getExceptionFilterParameters(nEvents, null, nExcs); + DEBUG_EXCEPTION_FILTER_PARAMETERS p = exc.getParameter(index); + p.ExecutionOption = new ULONG(optionCont.ordinal()); + control.setExceptionFilterParameters(nExcs, exc); + } + } +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java index 9fbff3fda0..9e277d0210 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java @@ -18,18 +18,27 @@ package agent.dbgeng.manager.impl; import agent.dbgeng.manager.DbgEventFilter; public class DbgEventFilterImpl implements DbgEventFilter { + + protected int index; protected final String text; protected final String cmd; protected int executionOption; protected int continueOption; - public DbgEventFilterImpl(String text, String cmd, int executionOption, int continueOption) { + public DbgEventFilterImpl(int index, String text, String cmd, int executionOption, + int continueOption) { + this.index = index; this.text = text; this.cmd = cmd; this.setExecutionOption(executionOption); this.setContinueOption(continueOption); } + @Override + public int getIndex() { + return index; + } + @Override public String getName() { return text; diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java index 4e32f78cca..7f57150f91 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java @@ -22,9 +22,10 @@ public class DbgExceptionFilterImpl extends DbgEventFilterImpl implements DbgExc private final String cmd2; private long exceptionCode; - public DbgExceptionFilterImpl(String text, String cmd, String cmd2, int executionOption, + public DbgExceptionFilterImpl(int index, String text, String cmd, String cmd2, + int executionOption, int continueOption, long exceptionCode) { - super(text, cmd, executionOption, continueOption); + super(index, text, cmd, executionOption, continueOption); this.cmd2 = cmd2; this.exceptionCode = exceptionCode; } 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 7cc617693d..e969b3b5a9 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 @@ -685,6 +685,7 @@ public class DbgManagerImpl implements DbgManager { */ protected DebugStatus processException(DbgExceptionEvent evt, Void v) { DebugThreadId eventId = updateState(); + getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.threadSelected(eventThread, null, evt.getCause()); DebugExceptionRecord64 info = evt.getInfo(); @@ -710,6 +711,7 @@ public class DbgManagerImpl implements DbgManager { DbgProcessImpl process = getCurrentProcess(); int tid = so.getCurrentThreadSystemId(); DbgThreadImpl thread = getThreadComputeIfAbsent(eventId, process, tid); + getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.threadCreated(thread, DbgCause.Causes.UNCLAIMED); getEventListeners().fire.threadSelected(thread, null, evt.getCause()); @@ -735,6 +737,7 @@ public class DbgManagerImpl implements DbgManager { thread.remove(); } process.threadExited(eventId); + getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.threadExited(eventId, process, evt.getCause()); String key = Integer.toHexString(eventId.id); @@ -783,6 +786,7 @@ public class DbgManagerImpl implements DbgManager { //so.setCurrentProcessId(id); int pid = so.getCurrentProcessSystemId(); DbgProcessImpl proc = getProcessComputeIfAbsent(id, pid); + getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.processAdded(proc, evt.getCause()); getEventListeners().fire.processSelected(proc, evt.getCause()); @@ -815,8 +819,9 @@ public class DbgManagerImpl implements DbgManager { DbgThreadImpl thread = getCurrentThread(); DbgProcessImpl process = getCurrentProcess(); process.setExitCode(Long.valueOf(evt.getInfo())); - getEventListeners().fire.threadExited(eventId, process, evt.getCause()); + getEventListeners().fire.eventSelected(evt, evt.getCause()); + getEventListeners().fire.threadExited(eventId, process, evt.getCause()); getEventListeners().fire.processExited(process, evt.getCause()); for (DebugBreakpoint bpt : getBreakpoints()) { @@ -867,6 +872,7 @@ public class DbgManagerImpl implements DbgManager { DbgProcessImpl process = getCurrentProcess(); DebugModuleInfo info = evt.getInfo(); process.moduleLoaded(info); + getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.moduleLoaded(process, info, evt.getCause()); String key = info.getModuleName(); @@ -888,6 +894,7 @@ public class DbgManagerImpl implements DbgManager { DbgProcessImpl process = getCurrentProcess(); DebugModuleInfo info = evt.getInfo(); process.moduleUnloaded(info); + getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.moduleUnloaded(process, info, evt.getCause()); String key = info.getModuleName(); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/AbstractDbgModel.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/AbstractDbgModel.java index de1a51b3a3..a93feae241 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/AbstractDbgModel.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/AbstractDbgModel.java @@ -42,4 +42,6 @@ public abstract class AbstractDbgModel extends AbstractDebuggerObjectModel { public abstract TargetObject getModelObject(Object object); + public abstract void deleteModelObject(Object object); + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEvent.java index dfbcc6eb35..c03e282925 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEvent.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEvent.java @@ -15,15 +15,18 @@ */ package agent.dbgeng.model.iface2; -import agent.dbgeng.manager.DbgEventFilter; +import agent.dbgeng.manager.*; +import agent.dbgeng.manager.evt.AbstractDbgEvent; +import agent.dbgeng.model.iface1.DbgModelSelectableObject; -public interface DbgModelTargetEvent extends DbgModelTargetObject { - - @Override - public default String getDisplay() { - return getName(); - } +public interface DbgModelTargetEvent extends DbgModelSelectableObject, DbgEventsListenerAdapter // +{ public DbgEventFilter getFilter(); + public int getEventIndex(); + + @Override + void eventSelected(AbstractDbgEvent event, DbgCause cause); + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java index 3300d54e76..2d2df7d5e0 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java @@ -19,9 +19,4 @@ import ghidra.dbg.target.TargetTogglable; public interface DbgModelTargetEventOption extends DbgModelTargetObject, TargetTogglable { - @Override - public default String getDisplay() { - return getName(); - } - } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetException.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetException.java index 34c48922f4..a28c5731d0 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetException.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetException.java @@ -17,12 +17,7 @@ package agent.dbgeng.model.iface2; import agent.dbgeng.manager.DbgExceptionFilter; -public interface DbgModelTargetException extends DbgModelTargetObject { - - @Override - public default String getDisplay() { - return getName(); - } +public interface DbgModelTargetException extends DbgModelTargetEvent { public DbgExceptionFilter getFilter(); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelImpl.java index b05703ca08..b030ff7c7e 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelImpl.java @@ -164,6 +164,7 @@ public class DbgModelImpl extends AbstractDbgModel implements DebuggerObjectMode return objectMap.get(object); } + @Override public void deleteModelObject(Object object) { objectMap.remove(object); } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventOptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetContinuationOptionImpl.java similarity index 52% rename from Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventOptionImpl.java rename to Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetContinuationOptionImpl.java index 15a3d13011..4633bf7b39 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventOptionImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetContinuationOptionImpl.java @@ -20,75 +20,66 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; import agent.dbgeng.dbgeng.DebugControl.DebugFilterContinuationOption; -import agent.dbgeng.dbgeng.DebugControl.DebugFilterExecutionOption; +import agent.dbgeng.manager.cmd.DbgToggleContinuationCommand; +import agent.dbgeng.manager.impl.DbgManagerImpl; import agent.dbgeng.model.iface2.*; import ghidra.dbg.target.schema.*; -import ghidra.dbg.util.PathUtils; @TargetObjectSchemaInfo( - name = "Event", + name = "ContinuationFilter", elements = { @TargetElementType(type = Void.class) }, attributes = { @TargetAttributeType(type = Object.class) }) -public class DbgModelTargetEventOptionImpl extends DbgModelTargetObjectImpl +public class DbgModelTargetContinuationOptionImpl extends DbgModelTargetObjectImpl implements DbgModelTargetEventOption { - protected static String keyFilter(DebugFilterExecutionOption option) { - return PathUtils.makeKey(option.description); - } - - protected static String keyFilter(DebugFilterContinuationOption option) { - return PathUtils.makeKey(option.description); - } - - private DebugFilterExecutionOption optionEx; + private DbgModelTargetEvent event; private DebugFilterContinuationOption optionCont; - public DbgModelTargetEventOptionImpl(DbgModelTargetEvent event, - DebugFilterExecutionOption option) { - super(event.getModel(), event, keyFilter(option), "EventFilter"); + public DbgModelTargetContinuationOptionImpl(DbgModelTargetEvent event, + DebugFilterContinuationOption option) { + super(event.getModel(), event, "Continue", "ContinuationFilter"); this.getModel().addModelObject(option, this); - this.optionEx = option; + this.event = event; + this.optionCont = option; + setAttributes(); } - public DbgModelTargetEventOptionImpl(DbgModelTargetEvent event, + public DbgModelTargetContinuationOptionImpl(DbgModelTargetException exc, DebugFilterContinuationOption option) { - super(event.getModel(), event, keyFilter(option), "EventFilter"); - this.getModel().addModelObject(option, this); - this.optionCont = option; - } - - public DbgModelTargetEventOptionImpl(DbgModelTargetException exc, - DebugFilterExecutionOption option) { - super(exc.getModel(), exc, keyFilter(option), "EventFilter"); - this.getModel().addModelObject(option, this); - this.optionEx = option; - } - - public DbgModelTargetEventOptionImpl(DbgModelTargetException exc, - DebugFilterContinuationOption option) { - super(exc.getModel(), exc, keyFilter(option), "EventFilter"); + super(exc.getModel(), exc, "Continue", "ContinuationFilter"); + this.event = exc; this.getModel().addModelObject(option, this); this.optionCont = option; + setAttributes(); } @Override public CompletableFuture disable() { - // TODO Auto-generated method stub - return null; + DbgManagerImpl manager = getManager(); + optionCont = DebugFilterContinuationOption.DEBUG_FILTER_GO_NOT_HANDLED; + setAttributes(); + return manager.execute( + new DbgToggleContinuationCommand(manager, event.getEventIndex(), optionCont)); } @Override public CompletableFuture enable() { - // TODO Auto-generated method stub - return null; + DbgManagerImpl manager = getManager(); + optionCont = DebugFilterContinuationOption.DEBUG_FILTER_GO_HANDLED; + setAttributes(); + return manager.execute( + new DbgToggleContinuationCommand(manager, event.getEventIndex(), optionCont)); } public void setAttributes() { changeAttributes(List.of(), List.of(), Map.of( // - DISPLAY_ATTRIBUTE_NAME, getName() // - ), "Initialized"); + DISPLAY_ATTRIBUTE_NAME, getName() + " : " + optionCont.description, // + VALUE_ATTRIBUTE_NAME, optionCont, // + ENABLED_ATTRIBUTE_NAME, + optionCont.equals(DebugFilterContinuationOption.DEBUG_FILTER_GO_HANDLED)), + "Refreshed"); } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java index 3b5e644c8b..62b9aa7fde 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java @@ -18,9 +18,10 @@ package agent.dbgeng.model.impl; import java.util.List; import java.util.Map; -import agent.dbgeng.dbgeng.DebugControl.DebugFilterContinuationOption; -import agent.dbgeng.dbgeng.DebugControl.DebugFilterExecutionOption; +import agent.dbgeng.dbgeng.DebugControl.*; +import agent.dbgeng.manager.DbgCause; import agent.dbgeng.manager.DbgEventFilter; +import agent.dbgeng.manager.evt.*; import agent.dbgeng.model.iface2.*; import ghidra.dbg.target.schema.*; import ghidra.dbg.util.PathUtils; @@ -55,8 +56,8 @@ public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl DebugFilterExecutionOption.getByNumber(filter.getExecutionOption()); DebugFilterContinuationOption cont = DebugFilterContinuationOption.getByNumber(filter.getContinueOption()); - execOption = new DbgModelTargetEventOptionImpl(this, exec); - contOption = new DbgModelTargetEventOptionImpl(this, cont); + execOption = new DbgModelTargetExecutionOptionImpl(this, exec); + contOption = new DbgModelTargetContinuationOptionImpl(this, cont); changeAttributes(List.of(), List.of(), Map.of( // DISPLAY_ATTRIBUTE_NAME, getIndex(), // @@ -64,6 +65,8 @@ public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl "Execute", execOption, // "Continue", contOption // ), "Initialized"); + + getManager().addEventsListener(this); } @Override @@ -71,4 +74,44 @@ public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl return filter; } + @Override + public int getEventIndex() { + return filter.getIndex(); + } + + @Override + public void eventSelected(AbstractDbgEvent event, DbgCause cause) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, false), "Refreshed"); + if (event instanceof DbgThreadCreatedEvent && + getEventIndex() == DebugFilterOrdinals.DEBUG_FILTER_CREATE_THREAD.ordinal()) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } + if (event instanceof DbgThreadExitedEvent && + getEventIndex() == DebugFilterOrdinals.DEBUG_FILTER_EXIT_THREAD.ordinal()) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } + if (event instanceof DbgProcessCreatedEvent && + getEventIndex() == DebugFilterOrdinals.DEBUG_FILTER_CREATE_PROCESS.ordinal()) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } + if (event instanceof DbgProcessExitedEvent && + getEventIndex() == DebugFilterOrdinals.DEBUG_FILTER_EXIT_PROCESS.ordinal()) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } + if (event instanceof DbgModuleLoadedEvent && + getEventIndex() == DebugFilterOrdinals.DEBUG_FILTER_LOAD_MODULE.ordinal()) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } + if (event instanceof DbgModuleUnloadedEvent && + getEventIndex() == DebugFilterOrdinals.DEBUG_FILTER_UNLOAD_MODULE.ordinal()) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } + } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java index 2f58e36bac..3976a1809b 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java @@ -20,8 +20,14 @@ import java.util.Map; import agent.dbgeng.dbgeng.DebugControl.DebugFilterContinuationOption; import agent.dbgeng.dbgeng.DebugControl.DebugFilterExecutionOption; +import agent.dbgeng.dbgeng.DebugExceptionRecord64; +import agent.dbgeng.manager.DbgCause; import agent.dbgeng.manager.DbgExceptionFilter; +import agent.dbgeng.manager.evt.AbstractDbgEvent; +import agent.dbgeng.manager.evt.DbgExceptionEvent; +import agent.dbgeng.model.iface1.DbgModelTargetFocusScope; import agent.dbgeng.model.iface2.*; +import ghidra.dbg.target.TargetFocusScope; import ghidra.dbg.target.schema.*; import ghidra.dbg.util.PathUtils; @@ -56,8 +62,8 @@ public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl DebugFilterExecutionOption.getByNumber(filter.getExecutionOption()); DebugFilterContinuationOption cont = DebugFilterContinuationOption.getByNumber(filter.getContinueOption()); - execOption = new DbgModelTargetEventOptionImpl(this, exec); - contOption = new DbgModelTargetEventOptionImpl(this, cont); + execOption = new DbgModelTargetExecutionOptionImpl(this, exec); + contOption = new DbgModelTargetContinuationOptionImpl(this, cont); changeAttributes(List.of(), List.of(), Map.of( // DISPLAY_ATTRIBUTE_NAME, getIndex(), // @@ -67,6 +73,8 @@ public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl "Continue", contOption, // "Exception", filter.getExceptionCode() // ), "Initialized"); + + getManager().addEventsListener(this); } @Override @@ -74,4 +82,23 @@ public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl return filter; } + @Override + public int getEventIndex() { + return filter.getIndex(); + } + + @Override + public void eventSelected(AbstractDbgEvent event, DbgCause cause) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, false), "Refreshed"); + if (event instanceof DbgExceptionEvent) { + DebugExceptionRecord64 info = (DebugExceptionRecord64) event.getInfo(); + if (info.code == Long.parseLong(filter.getExceptionCode(), 16)) { + ((DbgModelTargetFocusScope) searchForSuitable(TargetFocusScope.class)) + .setFocus(this); + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } + } + } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java new file mode 100644 index 0000000000..ffc81fa1d7 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java @@ -0,0 +1,81 @@ +/* ### + * 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.model.impl; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +import agent.dbgeng.dbgeng.DebugControl.DebugFilterExecutionOption; +import agent.dbgeng.manager.cmd.DbgToggleExecutionCommand; +import agent.dbgeng.manager.impl.DbgManagerImpl; +import agent.dbgeng.model.iface2.*; +import ghidra.dbg.target.schema.*; + +@TargetObjectSchemaInfo( + name = "ExecutionFilter", + elements = { + @TargetElementType(type = Void.class) }, + attributes = { + @TargetAttributeType(type = Object.class) }) +public class DbgModelTargetExecutionOptionImpl extends DbgModelTargetObjectImpl + implements DbgModelTargetEventOption { + + private DbgModelTargetEvent event; + private DebugFilterExecutionOption optionExc; + + public DbgModelTargetExecutionOptionImpl(DbgModelTargetEvent event, + DebugFilterExecutionOption option) { + super(event.getModel(), event, "Execute", "ExecutionFilter"); + this.event = event; + this.getModel().addModelObject(option, this); + this.optionExc = option; + setAttributes(); + } + + public DbgModelTargetExecutionOptionImpl(DbgModelTargetException exc, + DebugFilterExecutionOption option) { + super(exc.getModel(), exc, "Execute", "ExecutionFilter"); + this.event = exc; + this.getModel().addModelObject(option, this); + this.optionExc = option; + setAttributes(); + } + + @Override + public CompletableFuture disable() { + return enable(); + } + + @Override + public CompletableFuture enable() { + DbgManagerImpl manager = getManager(); + int ordinal = (optionExc.ordinal() + 1) % (DebugFilterExecutionOption.values().length - 1); + optionExc = DebugFilterExecutionOption.getByNumber(ordinal); + setAttributes(); + return manager.execute( + new DbgToggleExecutionCommand(manager, event.getEventIndex(), optionExc)); + } + + public void setAttributes() { + changeAttributes(List.of(), List.of(), Map.of( // + DISPLAY_ATTRIBUTE_NAME, getName() + " : " + optionExc.description, // + VALUE_ATTRIBUTE_NAME, optionExc, // + ENABLED_ATTRIBUTE_NAME, + optionExc.equals(DebugFilterExecutionOption.DEBUG_FILTER_BREAK)), "Refreshed"); + } + +} diff --git a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DbgModel2Impl.java b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DbgModel2Impl.java index 9b708f990b..48b4900954 100644 --- a/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DbgModel2Impl.java +++ b/Ghidra/Debug/Debugger-agent-dbgmodel/src/main/java/agent/dbgmodel/model/impl/DbgModel2Impl.java @@ -182,6 +182,11 @@ public class DbgModel2Impl extends AbstractDbgModel return objectMap.get(object); } + @Override + public void deleteModelObject(Object object) { + objectMap.remove(object); + } + @Override public CompletableFuture gateFuture(CompletableFuture future) { return super.gateFuture(future).exceptionally(ex -> { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java index 67047d5f53..e54e947418 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java @@ -1210,6 +1210,22 @@ public interface DebuggerResources { } } + abstract class AbstractToggleAction extends DockingAction { + public static final String NAME = "Toggle"; + public static final Icon ICON = ICON_BREAKPOINT_MIXED_ED_MARKER; + public static final String HELP_ANCHOR = "toggle_option"; + + public static HelpLocation help(Plugin owner) { + return new HelpLocation(owner.getName(), HELP_ANCHOR); + } + + public AbstractToggleAction(Plugin owner) { + super(NAME, owner.getName()); + setDescription("Enable or disable an option"); + setHelpLocation(new HelpLocation(owner.getName(), HELP_ANCHOR)); + } + } + interface MapIdenticallyAction { String NAME = "Map Identically"; String DESCRIPTION = diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java index d0fc11fc8d..fd413e7f3a 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java @@ -1148,43 +1148,43 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter groupTargetIndex++; new ActionBuilder("Finish", plugin.getName()) - .keyBinding("F12") - .toolBarGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) - .toolBarIcon(AbstractStepFinishAction.ICON) - .popupMenuPath("&Finish") - .popupMenuGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) - .popupMenuIcon(AbstractStepFinishAction.ICON) - .helpLocation(AbstractStepFinishAction.help(plugin)) - //.withContext(ObjectActionContext.class) - .enabledWhen(ctx -> - isInstance(ctx, TargetSteppable.class) && isStopped(ctx)) - .popupWhen(ctx -> - isInstance(ctx, TargetSteppable.class) && isStopped(ctx)) - .onAction(ctx -> performStepFinish(ctx)) - .enabled(false) - .buildAndInstallLocal(this); + .keyBinding("F12") + .toolBarGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) + .toolBarIcon(AbstractStepFinishAction.ICON) + .popupMenuPath("&Finish") + .popupMenuGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) + .popupMenuIcon(AbstractStepFinishAction.ICON) + .helpLocation(AbstractStepFinishAction.help(plugin)) + //.withContext(ObjectActionContext.class) + .enabledWhen(ctx -> + isInstance(ctx, TargetSteppable.class) && isStopped(ctx)) + .popupWhen(ctx -> + isInstance(ctx, TargetSteppable.class) && isStopped(ctx)) + .onAction(ctx -> performStepFinish(ctx)) + .enabled(false) + .buildAndInstallLocal(this); + + groupTargetIndex++; + + new ActionBuilder("Step Last", plugin.getName()) + .keyBinding("ALT F8") + .toolBarGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) + .toolBarIcon(AbstractStepLastAction.ICON) + .popupMenuPath("&Step Last") + .popupMenuGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) + .popupMenuIcon(AbstractStepLastAction.ICON) + .helpLocation(AbstractStepLastAction.help(plugin)) + //.withContext(ObjectActionContext.class) + .enabledWhen(ctx -> + isInstance(ctx, TargetSteppable.class) && isStopped(ctx)) + .popupWhen(ctx -> + isInstance(ctx, TargetSteppable.class) && isStopped(ctx)) + .onAction(ctx -> performStepLast(ctx)) + .enabled(false) + .buildAndInstallLocal(this); + + groupTargetIndex++; - groupTargetIndex++; - - new ActionBuilder("Step Last", plugin.getName()) - .keyBinding("ALT F8") - .toolBarGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) - .toolBarIcon(AbstractStepLastAction.ICON) - .popupMenuPath("&Step Last") - .popupMenuGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) - .popupMenuIcon(AbstractStepLastAction.ICON) - .helpLocation(AbstractStepLastAction.help(plugin)) - //.withContext(ObjectActionContext.class) - .enabledWhen(ctx -> - isInstance(ctx, TargetSteppable.class) && isStopped(ctx)) - .popupWhen(ctx -> - isInstance(ctx, TargetSteppable.class) && isStopped(ctx)) - .onAction(ctx -> performStepLast(ctx)) - .enabled(false) - .buildAndInstallLocal(this); - - groupTargetIndex++; - actionAddBreakpoint = new ActionBuilder("Add Breakpoint", plugin.getName()) .keyBinding("F3") .toolBarGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) @@ -1221,6 +1221,20 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter groupTargetIndex++; + new ActionBuilder("Toggle", plugin.getName()) + .keyBinding("T") + .toolBarGroup(DebuggerResources.GROUP_CONTROL, "X" + groupTargetIndex) + .popupMenuPath("&Toggle") + .popupMenuGroup(DebuggerResources.GROUP_CONTROL, "X" + groupTargetIndex) + .helpLocation(AbstractToggleAction.help(plugin)) + .enabledWhen(ctx -> isInstance(ctx, TargetTogglable.class)) + .popupWhen(ctx -> isInstance(ctx, TargetResumable.class)) + .onAction(ctx -> performToggle(ctx)) + .enabled(false) + .buildAndInstallLocal(this); + + groupTargetIndex++; + displayAsTreeAction = new DisplayAsTreeAction(tool, plugin.getName(), this); displayAsTableAction = new DisplayAsTableAction(tool, plugin.getName(), this); displayAsGraphAction = new DisplayAsGraphAction(tool, plugin.getName(), this); @@ -1486,6 +1500,12 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter }, "Couldn't set breakpoint"); } + public void performToggle(ActionContext context) { + performAction(context, false, TargetTogglable.class, t -> { + return t.toggle(!t.isEnabled()); + }, "Couldn't toggle"); + } + public void initiateConsole(ActionContext context) { performAction(context, false, TargetInterpreter.class, interpreter -> { getPlugin().showConsole(interpreter); From 885bdd36b35c21d389eb41c033d9ef5a29156c57 Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Thu, 23 Sep 2021 15:34:23 +0000 Subject: [PATCH 09/17] GP-1288: more work on config options --- .../dbgeng/control/DebugControlImpl1.java | 14 +++- .../agent/dbgeng/manager/DbgEventFilter.java | 2 + .../cmd/DbgListEventFiltersCommand.java | 3 +- .../cmd/DbgSetFilterArgumentCommand.java | 39 ++++++++++ .../cmd/DbgSetFilterCommandCommand.java | 39 ++++++++++ .../DbgSetFilterSecondChanceCmdCommand.java | 39 ++++++++++ .../manager/impl/DbgEventFilterImpl.java | 9 ++- .../manager/impl/DbgExceptionFilterImpl.java | 2 +- .../model/iface2/DbgModelTargetEvent.java | 6 +- .../iface2/DbgModelTargetEventOption.java | 6 ++ .../DbgModelTargetContinuationOptionImpl.java | 18 +++-- .../model/impl/DbgModelTargetEventImpl.java | 73 ++++++++++++++++-- .../impl/DbgModelTargetExceptionImpl.java | 77 +++++++++++++++++-- .../DbgModelTargetExecutionOptionImpl.java | 12 ++- .../gui/objects/DebuggerObjectsProvider.java | 32 +++++++- .../ghidra/dbg/target/TargetConfigurable.java | 7 ++ 16 files changed, 349 insertions(+), 29 deletions(-) create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetFilterArgumentCommand.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetFilterCommandCommand.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetFilterSecondChanceCmdCommand.java diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/control/DebugControlImpl1.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/control/DebugControlImpl1.java index 72295fe833..495f5bfcf8 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/control/DebugControlImpl1.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/control/DebugControlImpl1.java @@ -365,8 +365,12 @@ public class DebugControlImpl1 implements DebugControlInternal { public String getSpecificFilterArgument(int index) { ULONG ulIndex = new ULONG(index); ULONGByReference ulArgumentSize = new ULONGByReference(); - COMUtils.checkRC( - jnaControl.GetSpecificFilterArgument(ulIndex, null, new ULONG(0), ulArgumentSize)); + HRESULT hr = + jnaControl.GetSpecificFilterArgument(ulIndex, null, new ULONG(0), ulArgumentSize); + if (hr.equals(COMUtilsExtra.E_INVALID_PARAM)) { + return null; + } + COMUtils.checkRC(hr); byte[] buffer = new byte[ulArgumentSize.getValue().intValue()]; ULONG ulBufferSize = ulArgumentSize.getValue(); COMUtils.checkRC( @@ -376,8 +380,10 @@ public class DebugControlImpl1 implements DebugControlInternal { @Override public void setSpecificFilterArgument(int index, String arg) { - ULONG ulIndex = new ULONG(index); - COMUtils.checkRC(jnaControl.SetSpecificFilterArgument(ulIndex, arg)); + if (arg != null) { + ULONG ulIndex = new ULONG(index); + COMUtils.checkRC(jnaControl.SetSpecificFilterArgument(ulIndex, arg)); + } } @Override diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java index e5052cc383..26af765ed8 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/DbgEventFilter.java @@ -21,6 +21,8 @@ public interface DbgEventFilter { String getName(); + String getArg(); + String getCmd(); int getExecutionOption(); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java index c63254af28..d985ba429a 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java @@ -47,9 +47,10 @@ public class DbgListEventFiltersCommand for (int i = 0; i < info.getNumberEvents(); i++) { String text = control.getEventFilterText(i); String cmd = control.getEventFilterCommand(i); + String arg = control.getSpecificFilterArgument(i); DEBUG_SPECIFIC_FILTER_PARAMETERS p = exc.getParameter(i); DbgEventFilterImpl f = - new DbgEventFilterImpl(i, text, cmd, p.ExecutionOption.intValue(), + new DbgEventFilterImpl(i, text, cmd, arg, p.ExecutionOption.intValue(), p.ContinueOption.intValue()); result.add(f); } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetFilterArgumentCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetFilterArgumentCommand.java new file mode 100644 index 0000000000..6b3ffc0c8a --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetFilterArgumentCommand.java @@ -0,0 +1,39 @@ +/* ### + * 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.manager.impl.DbgManagerImpl; + +public class DbgSetFilterArgumentCommand + extends AbstractDbgCommand { + + private int index; + private String cmd; + + public DbgSetFilterArgumentCommand(DbgManagerImpl manager, int index, + String cmd) { + super(manager); + this.index = index; + this.cmd = cmd; + } + + @Override + public void invoke() { + DebugControl control = manager.getControl(); + control.setEventFilterCommand(index, cmd); + } +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetFilterCommandCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetFilterCommandCommand.java new file mode 100644 index 0000000000..0030ec7068 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetFilterCommandCommand.java @@ -0,0 +1,39 @@ +/* ### + * 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.manager.impl.DbgManagerImpl; + +public class DbgSetFilterCommandCommand + extends AbstractDbgCommand { + + private int index; + private String cmd; + + public DbgSetFilterCommandCommand(DbgManagerImpl manager, int index, + String cmd) { + super(manager); + this.index = index; + this.cmd = cmd; + } + + @Override + public void invoke() { + DebugControl control = manager.getControl(); + control.setEventFilterCommand(index, cmd); + } +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetFilterSecondChanceCmdCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetFilterSecondChanceCmdCommand.java new file mode 100644 index 0000000000..47e0d5ffd3 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgSetFilterSecondChanceCmdCommand.java @@ -0,0 +1,39 @@ +/* ### + * 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.manager.impl.DbgManagerImpl; + +public class DbgSetFilterSecondChanceCmdCommand + extends AbstractDbgCommand { + + private int index; + private String cmd; + + public DbgSetFilterSecondChanceCmdCommand(DbgManagerImpl manager, int index, + String cmd) { + super(manager); + this.index = index; + this.cmd = cmd; + } + + @Override + public void invoke() { + DebugControl control = manager.getControl(); + control.setExceptionFilterSecondCommand(index, cmd); + } +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java index 9e277d0210..8f03909f36 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgEventFilterImpl.java @@ -21,15 +21,17 @@ public class DbgEventFilterImpl implements DbgEventFilter { protected int index; protected final String text; + protected final String arg; protected final String cmd; protected int executionOption; protected int continueOption; - public DbgEventFilterImpl(int index, String text, String cmd, int executionOption, + public DbgEventFilterImpl(int index, String text, String cmd, String arg, int executionOption, int continueOption) { this.index = index; this.text = text; this.cmd = cmd; + this.arg = arg; this.setExecutionOption(executionOption); this.setContinueOption(continueOption); } @@ -44,6 +46,11 @@ public class DbgEventFilterImpl implements DbgEventFilter { return text; } + @Override + public String getArg() { + return arg == null ? "N/A" : arg; + } + @Override public String getCmd() { return cmd; diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java index 7f57150f91..a20f277ee4 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgExceptionFilterImpl.java @@ -25,7 +25,7 @@ public class DbgExceptionFilterImpl extends DbgEventFilterImpl implements DbgExc public DbgExceptionFilterImpl(int index, String text, String cmd, String cmd2, int executionOption, int continueOption, long exceptionCode) { - super(index, text, cmd, executionOption, continueOption); + super(index, text, cmd, null, executionOption, continueOption); this.cmd2 = cmd2; this.exceptionCode = exceptionCode; } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEvent.java index c03e282925..8b5de3f811 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEvent.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEvent.java @@ -18,8 +18,12 @@ package agent.dbgeng.model.iface2; import agent.dbgeng.manager.*; import agent.dbgeng.manager.evt.AbstractDbgEvent; import agent.dbgeng.model.iface1.DbgModelSelectableObject; +import agent.dbgeng.model.iface1.DbgModelTargetConfigurable; -public interface DbgModelTargetEvent extends DbgModelSelectableObject, DbgEventsListenerAdapter // +public interface DbgModelTargetEvent extends + DbgModelSelectableObject, // + DbgModelTargetConfigurable, // + DbgEventsListenerAdapter // { public DbgEventFilter getFilter(); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java index 2d2df7d5e0..4a552b363c 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java @@ -15,8 +15,14 @@ */ package agent.dbgeng.model.iface2; +import java.util.concurrent.CompletableFuture; + import ghidra.dbg.target.TargetTogglable; public interface DbgModelTargetEventOption extends DbgModelTargetObject, TargetTogglable { + int getOption(); + + CompletableFuture setOption(int ordinal); + } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetContinuationOptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetContinuationOptionImpl.java index 4633bf7b39..15d87c027e 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetContinuationOptionImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetContinuationOptionImpl.java @@ -57,17 +57,23 @@ public class DbgModelTargetContinuationOptionImpl extends DbgModelTargetObjectIm @Override public CompletableFuture disable() { - DbgManagerImpl manager = getManager(); - optionCont = DebugFilterContinuationOption.DEBUG_FILTER_GO_NOT_HANDLED; - setAttributes(); - return manager.execute( - new DbgToggleContinuationCommand(manager, event.getEventIndex(), optionCont)); + return setOption(DebugFilterContinuationOption.DEBUG_FILTER_GO_NOT_HANDLED.ordinal()); } @Override public CompletableFuture enable() { + return setOption(DebugFilterContinuationOption.DEBUG_FILTER_GO_HANDLED.ordinal()); + } + + @Override + public int getOption() { + return optionCont.ordinal(); + } + + @Override + public CompletableFuture setOption(int ordinal) { DbgManagerImpl manager = getManager(); - optionCont = DebugFilterContinuationOption.DEBUG_FILTER_GO_HANDLED; + optionCont = DebugFilterContinuationOption.getByNumber(ordinal); setAttributes(); return manager.execute( new DbgToggleContinuationCommand(manager, event.getEventIndex(), optionCont)); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java index 62b9aa7fde..a691b05c61 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java @@ -15,14 +15,20 @@ */ package agent.dbgeng.model.impl; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.concurrent.CompletableFuture; import agent.dbgeng.dbgeng.DebugControl.*; import agent.dbgeng.manager.DbgCause; import agent.dbgeng.manager.DbgEventFilter; +import agent.dbgeng.manager.cmd.DbgSetFilterArgumentCommand; +import agent.dbgeng.manager.cmd.DbgSetFilterCommandCommand; import agent.dbgeng.manager.evt.*; +import agent.dbgeng.manager.impl.DbgManagerImpl; import agent.dbgeng.model.iface2.*; +import ghidra.async.AsyncUtils; +import ghidra.dbg.error.DebuggerIllegalArgumentException; +import ghidra.dbg.target.TargetMethod.ParameterDescription; import ghidra.dbg.target.schema.*; import ghidra.dbg.util.PathUtils; @@ -34,6 +40,12 @@ import ghidra.dbg.util.PathUtils; @TargetAttributeType(type = Object.class) }) public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl implements DbgModelTargetEvent { + + final String COMMAND_ATTRIBUTE_NAME = "Command"; + final String ARGUMENT_ATTRIBUTE_NAME = "Argument"; + final String CONTINUE_OPTION_ATTRIBUTE_NAME = "Continue"; + final String EXECUTE_OPTION_ATTRIBUTE_NAME = "Execute"; + protected static String indexFilter(DbgEventFilter filter) { return filter.getName(); } @@ -61,9 +73,10 @@ public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl changeAttributes(List.of(), List.of(), Map.of( // DISPLAY_ATTRIBUTE_NAME, getIndex(), // - "Command", filter.getCmd(), // - "Execute", execOption, // - "Continue", contOption // + COMMAND_ATTRIBUTE_NAME, filter.getCmd(), // + ARGUMENT_ATTRIBUTE_NAME, filter.getArg(), // + EXECUTE_OPTION_ATTRIBUTE_NAME, execOption, // + CONTINUE_OPTION_ATTRIBUTE_NAME, contOption // ), "Initialized"); getManager().addEventsListener(this); @@ -114,4 +127,54 @@ public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); } } + + @Override + public Map> getConfigParameters() { + Map> map = new HashMap<>(); + ParameterDescription cmdDesc = ParameterDescription.create(String.class, + COMMAND_ATTRIBUTE_NAME, false, "", COMMAND_ATTRIBUTE_NAME, "filter command"); + map.put(COMMAND_ATTRIBUTE_NAME, cmdDesc); + ParameterDescription argDesc = + ParameterDescription.create(String.class, ARGUMENT_ATTRIBUTE_NAME, false, "", + ARGUMENT_ATTRIBUTE_NAME, "filter argument"); + map.put(ARGUMENT_ATTRIBUTE_NAME, argDesc); + return map; + } + + @Override + public CompletableFuture writeConfigurationOption(String key, Object value) { + DbgManagerImpl manager = getManager(); + switch (key) { + case COMMAND_ATTRIBUTE_NAME: + if (value instanceof String) { + this.changeAttributes(List.of(), Map.of(COMMAND_ATTRIBUTE_NAME, value), + "Modified"); + String cmd = (String) getCachedAttribute(COMMAND_ATTRIBUTE_NAME); + return manager.execute( + new DbgSetFilterCommandCommand(manager, getEventIndex(), cmd)); + } + throw new DebuggerIllegalArgumentException("Command should be a string"); + case ARGUMENT_ATTRIBUTE_NAME: + if (value instanceof String) { + this.changeAttributes(List.of(), Map.of(ARGUMENT_ATTRIBUTE_NAME, value), + "Modified"); + String cmd = (String) getCachedAttribute(ARGUMENT_ATTRIBUTE_NAME); + return manager.execute( + new DbgSetFilterArgumentCommand(manager, getEventIndex(), cmd)); + } + throw new DebuggerIllegalArgumentException("Argument should be a string"); + case EXECUTE_OPTION_ATTRIBUTE_NAME: + if (value instanceof Integer) { + execOption.setOption((Integer) value); + } + throw new DebuggerIllegalArgumentException("Option should be numeric"); + case CONTINUE_OPTION_ATTRIBUTE_NAME: + if (value instanceof Integer) { + contOption.setOption((Integer) value); + } + throw new DebuggerIllegalArgumentException("Option should be numeric"); + default: + } + return AsyncUtils.NIL; + } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java index 3976a1809b..c7faedd862 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java @@ -15,19 +15,25 @@ */ package agent.dbgeng.model.impl; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.concurrent.CompletableFuture; import agent.dbgeng.dbgeng.DebugControl.DebugFilterContinuationOption; import agent.dbgeng.dbgeng.DebugControl.DebugFilterExecutionOption; import agent.dbgeng.dbgeng.DebugExceptionRecord64; import agent.dbgeng.manager.DbgCause; import agent.dbgeng.manager.DbgExceptionFilter; +import agent.dbgeng.manager.cmd.DbgSetFilterCommandCommand; +import agent.dbgeng.manager.cmd.DbgSetFilterSecondChanceCmdCommand; import agent.dbgeng.manager.evt.AbstractDbgEvent; import agent.dbgeng.manager.evt.DbgExceptionEvent; +import agent.dbgeng.manager.impl.DbgManagerImpl; import agent.dbgeng.model.iface1.DbgModelTargetFocusScope; import agent.dbgeng.model.iface2.*; +import ghidra.async.AsyncUtils; +import ghidra.dbg.error.DebuggerIllegalArgumentException; import ghidra.dbg.target.TargetFocusScope; +import ghidra.dbg.target.TargetMethod.ParameterDescription; import ghidra.dbg.target.schema.*; import ghidra.dbg.util.PathUtils; @@ -39,6 +45,13 @@ import ghidra.dbg.util.PathUtils; @TargetAttributeType(type = Object.class) }) public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl implements DbgModelTargetException { + + final String COMMAND_ATTRIBUTE_NAME = "Command"; + final String COMMAND2_ATTRIBUTE_NAME = "SecondCmd"; + final String CONTINUE_OPTION_ATTRIBUTE_NAME = "Continue"; + final String EXECUTE_OPTION_ATTRIBUTE_NAME = "Execute"; + final String EXCEPTION_CODE_ATTRIBUTE_NAME = "Exception"; + protected static String indexFilter(DbgExceptionFilter filter) { return filter.getName(); } @@ -67,11 +80,11 @@ public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl changeAttributes(List.of(), List.of(), Map.of( // DISPLAY_ATTRIBUTE_NAME, getIndex(), // - "Command", filter.getCmd(), // - "SecondCmd", filter.getCmd(), // - "Execute", execOption, // - "Continue", contOption, // - "Exception", filter.getExceptionCode() // + COMMAND_ATTRIBUTE_NAME, filter.getCmd(), // + COMMAND2_ATTRIBUTE_NAME, filter.getCmd(), // + EXECUTE_OPTION_ATTRIBUTE_NAME, execOption, // + CONTINUE_OPTION_ATTRIBUTE_NAME, contOption, // + EXCEPTION_CODE_ATTRIBUTE_NAME, filter.getExceptionCode() // ), "Initialized"); getManager().addEventsListener(this); @@ -101,4 +114,54 @@ public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl } } } + + @Override + public Map> getConfigParameters() { + Map> map = new HashMap<>(); + ParameterDescription cmdDesc = ParameterDescription.create(String.class, + COMMAND_ATTRIBUTE_NAME, false, "", COMMAND_ATTRIBUTE_NAME, "filter command"); + map.put(COMMAND_ATTRIBUTE_NAME, cmdDesc); + ParameterDescription cmdDesc2 = + ParameterDescription.create(String.class, COMMAND2_ATTRIBUTE_NAME, false, "", + COMMAND2_ATTRIBUTE_NAME, "filter 2nd-chance command"); + map.put(COMMAND2_ATTRIBUTE_NAME, cmdDesc2); + return map; + } + + @Override + public CompletableFuture writeConfigurationOption(String key, Object value) { + DbgManagerImpl manager = getManager(); + switch (key) { + case COMMAND_ATTRIBUTE_NAME: + if (value instanceof String) { + this.changeAttributes(List.of(), Map.of(COMMAND_ATTRIBUTE_NAME, value), + "Modified"); + String cmd = (String) getCachedAttribute(COMMAND_ATTRIBUTE_NAME); + return manager.execute( + new DbgSetFilterCommandCommand(manager, getEventIndex(), cmd)); + } + throw new DebuggerIllegalArgumentException("Command should be a string"); + case COMMAND2_ATTRIBUTE_NAME: + if (value instanceof String) { + this.changeAttributes(List.of(), Map.of(COMMAND2_ATTRIBUTE_NAME, value), + "Modified"); + String cmd = (String) getCachedAttribute(COMMAND2_ATTRIBUTE_NAME); + return manager.execute( + new DbgSetFilterSecondChanceCmdCommand(manager, getEventIndex(), cmd)); + } + throw new DebuggerIllegalArgumentException("Command should be a string"); + case EXECUTE_OPTION_ATTRIBUTE_NAME: + if (value instanceof Integer) { + execOption.setOption((Integer) value); + } + throw new DebuggerIllegalArgumentException("Option should be numeric"); + case CONTINUE_OPTION_ATTRIBUTE_NAME: + if (value instanceof Integer) { + contOption.setOption((Integer) value); + } + throw new DebuggerIllegalArgumentException("Option should be numeric"); + default: + } + return AsyncUtils.NIL; + } } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java index ffc81fa1d7..15c95c9838 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java @@ -62,8 +62,18 @@ public class DbgModelTargetExecutionOptionImpl extends DbgModelTargetObjectImpl @Override public CompletableFuture enable() { - DbgManagerImpl manager = getManager(); int ordinal = (optionExc.ordinal() + 1) % (DebugFilterExecutionOption.values().length - 1); + return setOption(ordinal); + } + + @Override + public int getOption() { + return optionExc.ordinal(); + } + + @Override + public CompletableFuture setOption(int ordinal) { + DbgManagerImpl manager = getManager(); optionExc = DebugFilterExecutionOption.getByNumber(ordinal); setAttributes(); return manager.execute( diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java index fd413e7f3a..10004344d1 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java @@ -20,6 +20,7 @@ import java.awt.Color; import java.awt.event.MouseEvent; import java.lang.invoke.MethodHandles; import java.util.*; +import java.util.Map.Entry; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; @@ -212,6 +213,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter private boolean asTree = true; private MyObjectListener listener = new MyObjectListener(); + public DebuggerMethodInvocationDialog configDialog; public DebuggerMethodInvocationDialog launchDialog; public DebuggerAttachDialog attachDialog; public DebuggerBreakpointDialog breakpointDialog; @@ -336,6 +338,8 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter //attachDialogOld = new DebuggerAttachDialog(this); attachDialog = new DebuggerAttachDialog(this); breakpointDialog = new DebuggerBreakpointDialog(this); + configDialog = new DebuggerMethodInvocationDialog(tool, "Config", "Config", + DebuggerResources.ICON_LAUNCH); } private void addToPanel(ObjectPane p) throws Exception { @@ -1228,13 +1232,27 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter .popupMenuGroup(DebuggerResources.GROUP_CONTROL, "X" + groupTargetIndex) .helpLocation(AbstractToggleAction.help(plugin)) .enabledWhen(ctx -> isInstance(ctx, TargetTogglable.class)) - .popupWhen(ctx -> isInstance(ctx, TargetResumable.class)) + .popupWhen(ctx -> isInstance(ctx, TargetTogglable.class)) .onAction(ctx -> performToggle(ctx)) .enabled(false) .buildAndInstallLocal(this); groupTargetIndex++; - + + new ActionBuilder("Configure", plugin.getName()) + .keyBinding("C") + .toolBarGroup(DebuggerResources.GROUP_CONTROL, "X" + groupTargetIndex) + .popupMenuPath("&Configure") + .popupMenuGroup(DebuggerResources.GROUP_CONTROL, "X" + groupTargetIndex) + .helpLocation(AbstractToggleAction.help(plugin)) + .enabledWhen(ctx -> isInstance(ctx, TargetConfigurable.class)) + .popupWhen(ctx -> isInstance(ctx, TargetConfigurable.class)) + .onAction(ctx -> performConfigure(ctx)) + .enabled(false) + .buildAndInstallLocal(this); + + groupTargetIndex++; + displayAsTreeAction = new DisplayAsTreeAction(tool, plugin.getName(), this); displayAsTableAction = new DisplayAsTableAction(tool, plugin.getName(), this); displayAsGraphAction = new DisplayAsGraphAction(tool, plugin.getName(), this); @@ -1506,6 +1524,16 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter }, "Couldn't toggle"); } + public void performConfigure(ActionContext context) { + performAction(context, false, TargetConfigurable.class, configurable -> { + Map args = configDialog.promptArguments(configurable.getConfigParameters()); + for (Entry entry : args.entrySet()) { + configurable.writeConfigurationOption(entry.getKey(), entry.getValue()); + } + return AsyncUtils.NIL; + }, "Couldn't configure"); + } + public void initiateConsole(ActionContext context) { performAction(context, false, TargetInterpreter.class, interpreter -> { getPlugin().showConsole(interpreter); diff --git a/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetConfigurable.java b/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetConfigurable.java index 33df530d99..44965552c0 100644 --- a/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetConfigurable.java +++ b/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetConfigurable.java @@ -15,9 +15,12 @@ */ package ghidra.dbg.target; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.CompletableFuture; import ghidra.dbg.DebuggerTargetObjectIface; +import ghidra.dbg.target.TargetMethod.ParameterDescription; /** * A target with writable configuration options @@ -55,4 +58,8 @@ public interface TargetConfigurable extends TargetObject { * is not valid. */ public CompletableFuture writeConfigurationOption(String key, Object value); + + public default Map> getConfigParameters() { + return new HashMap<>(); + } } From 23f50fdf109ac941ff6fc4fa80c3d1fd2434c3cd Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Thu, 23 Sep 2021 15:56:24 +0000 Subject: [PATCH 10/17] GP-1288: config options done --- .../model/iface2/DbgModelTargetEventOption.java | 2 +- .../impl/DbgModelTargetContinuationOptionImpl.java | 2 +- .../dbgeng/model/impl/DbgModelTargetEventImpl.java | 13 +++++++++++-- .../model/impl/DbgModelTargetExceptionImpl.java | 13 +++++++++++-- .../impl/DbgModelTargetExecutionOptionImpl.java | 2 +- .../debug/gui/objects/DebuggerObjectsProvider.java | 8 +++++--- 6 files changed, 30 insertions(+), 10 deletions(-) diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java index 4a552b363c..d601205443 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetEventOption.java @@ -21,7 +21,7 @@ import ghidra.dbg.target.TargetTogglable; public interface DbgModelTargetEventOption extends DbgModelTargetObject, TargetTogglable { - int getOption(); + Integer getOption(); CompletableFuture setOption(int ordinal); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetContinuationOptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetContinuationOptionImpl.java index 15d87c027e..80b8c49e37 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetContinuationOptionImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetContinuationOptionImpl.java @@ -66,7 +66,7 @@ public class DbgModelTargetContinuationOptionImpl extends DbgModelTargetObjectIm } @Override - public int getOption() { + public Integer getOption() { return optionCont.ordinal(); } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java index a691b05c61..65eaad2ff8 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java @@ -138,6 +138,15 @@ public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl ParameterDescription.create(String.class, ARGUMENT_ATTRIBUTE_NAME, false, "", ARGUMENT_ATTRIBUTE_NAME, "filter argument"); map.put(ARGUMENT_ATTRIBUTE_NAME, argDesc); + ParameterDescription execDesc = + ParameterDescription.create(Integer.class, EXECUTE_OPTION_ATTRIBUTE_NAME, false, + execOption.getOption(), EXECUTE_OPTION_ATTRIBUTE_NAME, "filter execution option"); + map.put(EXECUTE_OPTION_ATTRIBUTE_NAME, execDesc); + ParameterDescription contDesc = + ParameterDescription.create(Integer.class, CONTINUE_OPTION_ATTRIBUTE_NAME, false, + contOption.getOption(), CONTINUE_OPTION_ATTRIBUTE_NAME, + "filter continuation option"); + map.put(CONTINUE_OPTION_ATTRIBUTE_NAME, contDesc); return map; } @@ -165,12 +174,12 @@ public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl throw new DebuggerIllegalArgumentException("Argument should be a string"); case EXECUTE_OPTION_ATTRIBUTE_NAME: if (value instanceof Integer) { - execOption.setOption((Integer) value); + return execOption.setOption((Integer) value); } throw new DebuggerIllegalArgumentException("Option should be numeric"); case CONTINUE_OPTION_ATTRIBUTE_NAME: if (value instanceof Integer) { - contOption.setOption((Integer) value); + return contOption.setOption((Integer) value); } throw new DebuggerIllegalArgumentException("Option should be numeric"); default: diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java index c7faedd862..1c1b7dbe27 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java @@ -125,6 +125,15 @@ public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl ParameterDescription.create(String.class, COMMAND2_ATTRIBUTE_NAME, false, "", COMMAND2_ATTRIBUTE_NAME, "filter 2nd-chance command"); map.put(COMMAND2_ATTRIBUTE_NAME, cmdDesc2); + ParameterDescription execDesc = + ParameterDescription.create(Integer.class, EXECUTE_OPTION_ATTRIBUTE_NAME, false, + execOption.getOption(), EXECUTE_OPTION_ATTRIBUTE_NAME, "filter execution option"); + map.put(EXECUTE_OPTION_ATTRIBUTE_NAME, execDesc); + ParameterDescription contDesc = + ParameterDescription.create(Integer.class, CONTINUE_OPTION_ATTRIBUTE_NAME, false, + contOption.getOption(), CONTINUE_OPTION_ATTRIBUTE_NAME, + "filter continuation option"); + map.put(CONTINUE_OPTION_ATTRIBUTE_NAME, contDesc); return map; } @@ -152,12 +161,12 @@ public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl throw new DebuggerIllegalArgumentException("Command should be a string"); case EXECUTE_OPTION_ATTRIBUTE_NAME: if (value instanceof Integer) { - execOption.setOption((Integer) value); + return execOption.setOption((Integer) value); } throw new DebuggerIllegalArgumentException("Option should be numeric"); case CONTINUE_OPTION_ATTRIBUTE_NAME: if (value instanceof Integer) { - contOption.setOption((Integer) value); + return contOption.setOption((Integer) value); } throw new DebuggerIllegalArgumentException("Option should be numeric"); default: diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java index 15c95c9838..2ba750752b 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java @@ -67,7 +67,7 @@ public class DbgModelTargetExecutionOptionImpl extends DbgModelTargetObjectImpl } @Override - public int getOption() { + public Integer getOption() { return optionExc.ordinal(); } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java index 10004344d1..b111e37163 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java @@ -338,7 +338,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter //attachDialogOld = new DebuggerAttachDialog(this); attachDialog = new DebuggerAttachDialog(this); breakpointDialog = new DebuggerBreakpointDialog(this); - configDialog = new DebuggerMethodInvocationDialog(tool, "Config", "Config", + configDialog = new DebuggerMethodInvocationDialog(tool, "Configuration", "Configure", DebuggerResources.ICON_LAUNCH); } @@ -1527,8 +1527,10 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter public void performConfigure(ActionContext context) { performAction(context, false, TargetConfigurable.class, configurable -> { Map args = configDialog.promptArguments(configurable.getConfigParameters()); - for (Entry entry : args.entrySet()) { - configurable.writeConfigurationOption(entry.getKey(), entry.getValue()); + if (args != null) { + for (Entry entry : args.entrySet()) { + configurable.writeConfigurationOption(entry.getKey(), entry.getValue()); + } } return AsyncUtils.NIL; }, "Couldn't configure"); From 932813cd879930b24acb090353e79a2381d815e0 Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Thu, 23 Sep 2021 17:02:29 +0000 Subject: [PATCH 11/17] GP-1288: per request, removed duplicate DummyProc's --- .../java/agent/dbgeng/dbgeng/DebugClient.java | 2 +- .../impl/dbgeng/client/DebugClientImpl1.java | 2 +- .../src/test/java/agent/dbgeng/DummyProc.java | 51 -- .../java/agent/dbgeng/dbgeng/DbgEngTest.java | 9 +- .../agent/dbgeng/dbgeng/DbgEngTestOld.java | 675 ------------------ .../manager/impl/AbstractDbgManagerTest.java | 7 +- .../java/agent/dbgeng/testutil/DummyProc.java | 80 --- .../dbgmodel/gadp/impl/WrappedDbgModel.java | 2 +- .../test/java/agent/dbgmodel/DummyProc.java | 51 -- 9 files changed, 11 insertions(+), 868 deletions(-) delete mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/DummyProc.java delete mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/dbgeng/DbgEngTestOld.java delete mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/testutil/DummyProc.java delete mode 100644 Ghidra/Debug/Debugger-agent-dbgmodel/src/test/java/agent/dbgmodel/DummyProc.java diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugClient.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugClient.java index b4cac3b939..155b14417a 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugClient.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugClient.java @@ -362,7 +362,7 @@ public interface DebugClient extends DebugClientReentrant { Description getProcessDescription(DebugServerId si, int systemId, BitmaskSet flags); - void attachProcess(DebugServerId si, int processId, BitmaskSet attachFlags); + void attachProcess(DebugServerId si, long processId, BitmaskSet attachFlags); void createProcess(DebugServerId si, String commandLine, BitmaskSet createFlags); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/client/DebugClientImpl1.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/client/DebugClientImpl1.java index 3eb055bd30..9016849487 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/client/DebugClientImpl1.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/client/DebugClientImpl1.java @@ -183,7 +183,7 @@ public class DebugClientImpl1 implements DebugClientInternal { } @Override - public void attachProcess(DebugServerId si, int processId, + public void attachProcess(DebugServerId si, long processId, BitmaskSet attachFlags) { ULONGLONG ullServer = new ULONGLONG(si.id); ULONG ulPid = new ULONG(processId); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/DummyProc.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/DummyProc.java deleted file mode 100644 index 749015715c..0000000000 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/DummyProc.java +++ /dev/null @@ -1,51 +0,0 @@ -/* ### - * 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; - -import static org.junit.Assume.assumeTrue; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import com.sun.jna.Pointer; -import com.sun.jna.platform.win32.Kernel32; -import com.sun.jna.platform.win32.WinNT.HANDLE; - -public class DummyProc implements AutoCloseable { - final Process process; - public final int pid; - - public DummyProc(String... args) throws IOException, NoSuchFieldException, SecurityException, - IllegalArgumentException, IllegalAccessException { - process = new ProcessBuilder(args).start(); - - Class cls = process.getClass(); - assumeTrue(cls.getName().equals("java.lang.ProcessImpl")); - Field handleFld = cls.getDeclaredField("handle"); - handleFld.setAccessible(true); - long handle = handleFld.getLong(process); - pid = Kernel32.INSTANCE.GetProcessId(new HANDLE(new Pointer(handle))); - } - - @Override - public void close() throws Exception { - if (!process.destroyForcibly().waitFor(1000, TimeUnit.MILLISECONDS)) { - throw new TimeoutException("Could not terminate process " + pid); - } - } -} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/dbgeng/DbgEngTest.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/dbgeng/DbgEngTest.java index 547401bbdf..a52ca42f55 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/dbgeng/DbgEngTest.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/dbgeng/DbgEngTest.java @@ -16,7 +16,7 @@ package agent.dbgeng.dbgeng; import static org.junit.Assert.*; -import static org.junit.Assume.assumeTrue; +import static org.junit.Assume.*; import java.io.*; import java.nio.ByteBuffer; @@ -29,7 +29,7 @@ import com.sun.jna.Native; import com.sun.jna.platform.win32.COM.COMException; import com.sun.jna.win32.StdCallLibrary; -import agent.dbgeng.DummyProc; +//import agent.dbgeng.DummyProc; import agent.dbgeng.dbgeng.DebugBreakpoint.BreakType; import agent.dbgeng.dbgeng.DebugClient.*; import agent.dbgeng.dbgeng.DebugDataSpaces.*; @@ -40,6 +40,7 @@ import agent.dbgeng.dbgeng.DebugValue.DebugInt64Value; import agent.dbgeng.dbgeng.DebugValue.DebugValueType; import agent.dbgeng.dbgeng.util.DebugEventCallbacksAdapter; import ghidra.comm.util.BitmaskSet; +import ghidra.dbg.testutil.DummyProc; import ghidra.framework.Application; import ghidra.test.AbstractGhidraHeadlessIntegrationTest; import ghidra.util.Msg; @@ -697,7 +698,7 @@ public class DbgEngTest extends AbstractGhidraHeadlessIntegrationTest { return DebugStatus.NO_CHANGE; } }); - try (DummyProc proc = new DummyProc(specimen)) { + try (DummyProc proc = DummyProc.run(specimen)) { System.out.println("Started " + specimen + " with PID=" + proc.pid); Thread.sleep(1000); System.out.println("Attaching..."); @@ -839,7 +840,7 @@ public class DbgEngTest extends AbstractGhidraHeadlessIntegrationTest { final String specimenA = "C:\\windows\\notepad.exe"; final String specimenC = "C:\\windows\\system32\\win32calc.exe"; - try (DummyProc proc = new DummyProc(specimenX)) { + try (DummyProc proc = DummyProc.run(specimenX)) { client.setOutputCallbacks(new ConsoleOutputCallbacks()); BreakAllCallbacks cb = new BreakAllCallbacks(client); client.setEventCallbacks(cb); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/dbgeng/DbgEngTestOld.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/dbgeng/DbgEngTestOld.java deleted file mode 100644 index 2085936a69..0000000000 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/dbgeng/DbgEngTestOld.java +++ /dev/null @@ -1,675 +0,0 @@ -/* ### - * 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; - -import static org.junit.Assert.*; - -import java.io.*; -import java.nio.ByteBuffer; -import java.util.*; -import java.util.concurrent.CompletableFuture; - -import org.junit.*; - -import com.sun.jna.platform.win32.COM.COMException; - -import agent.dbgeng.DummyProc; -import agent.dbgeng.dbgeng.DebugBreakpoint.BreakType; -import agent.dbgeng.dbgeng.DebugClient.*; -import agent.dbgeng.dbgeng.DebugDataSpaces.*; -import agent.dbgeng.dbgeng.DebugModule.DebugModuleName; -import agent.dbgeng.dbgeng.DebugRegisters.DebugRegisterSource; -import agent.dbgeng.dbgeng.DebugValue.DebugInt64Value; -import agent.dbgeng.dbgeng.util.DebugEventCallbacksAdapter; -import ghidra.comm.util.BitmaskSet; -import ghidra.framework.Application; -import ghidra.test.AbstractGhidraHeadlessIntegrationTest; -import ghidra.util.Msg; -import ghidra.util.NumericUtilities; - -public class DbgEngTestOld extends AbstractGhidraHeadlessIntegrationTest { - protected static DebugClient cachedClient = null; - - protected DebugClient doDebugCreate() { - System.out.println("Creating a client"); - return DbgEng.debugCreate().createClient(); - } - - protected DebugClient debugCreate() { - //if (cachedClient == null) { - cachedClient = doDebugCreate(); - //} - return cachedClient; - } - - protected DebugClient client; - protected DebugControl control; - - @Before - public void setUp() { - DbgEngTest.assumeDbgengDLLLoadable(); - client = debugCreate(); - control = client.getControl(); - } - - @Test - public void testPrintln() { - CompletableFuture cb = new CompletableFuture<>(); - client.setOutputCallbacks(new DebugOutputCallbacks() { - @Override - public void output(int mask, String text) { - System.out.print(text); - cb.complete(text); - } - }); - control.outln("Hello, World!"); - String back = cb.getNow(null); - // NOTE: I'd like to be precise wrt/ new lines, but it seems to vary with version. - assertEquals("Hello, World!", back.trim()); - } - - @Test - public void testGetProcessSystemIds() { - List procs = client.getRunningProcesses(client.getLocalServer()); - System.out.println("Total: " + procs.size()); - procs.sort(null); - for (DebugRunningProcess p : procs) { - System.out.println("ID: " + p.getSystemId()); - } - } - - @Test - public void testGetProcessDescriptions() { - List procs = client.getRunningProcesses(client.getLocalServer()); - System.out.println("Total: " + procs.size()); - procs.sort(null); - for (DebugRunningProcess p : procs) { - try { - System.out.println(p.getFullDescription()); - } - catch (COMException e) { - System.out.println("Error with PID " + p.getSystemId() + ": " + e.getMessage()); - } - } - } - - public static abstract class NoisyDebugEventCallbacksAdapter - extends DebugEventCallbacksAdapter { - final DebugStatus defaultStatus; - - public NoisyDebugEventCallbacksAdapter(DebugStatus defaultStatus) { - this.defaultStatus = defaultStatus; - } - - @Override - public DebugStatus createProcess(DebugProcessInfo debugProcessInfo) { - Msg.info(this, "createProcess: " + debugProcessInfo); - return defaultStatus; - } - - @Override - public DebugStatus createThread(DebugThreadInfo debugThreadInfo) { - Msg.info(this, "createThread: " + debugThreadInfo); - return defaultStatus; - } - - @Override - public DebugStatus exitProcess(int exitCode) { - Msg.info(this, "exitProcess: " + Integer.toHexString(exitCode)); - return defaultStatus; - } - - @Override - public DebugStatus breakpoint(DebugBreakpoint bp) { - Msg.info(this, "breakpoint: " + bp); - return defaultStatus; - } - - @Override - public DebugStatus changeDebuggeeState(BitmaskSet flags, - long argument) { - Msg.info(this, "changeDebuggeeState: " + flags + ", " + argument); - return defaultStatus; - } - - @Override - public DebugStatus changeEngineState(BitmaskSet flags, long argument) { - Msg.info(this, "changeEngineState: " + flags + ", " + argument); - return defaultStatus; - } - - @Override - public DebugStatus changeSymbolState(BitmaskSet flags, long argument) { - Msg.info(this, "changeSymbolState: " + flags + ", " + argument); - return defaultStatus; - } - - @Override - public DebugStatus exception(DebugExceptionRecord64 exception, boolean firstChance) { - Msg.info(this, "exception: " + exception + ", " + firstChance); - return defaultStatus; - } - - @Override - public DebugStatus exitThread(int exitCode) { - Msg.info(this, "exitThread: " + Integer.toHexString(exitCode)); - return defaultStatus; - } - - @Override - public DebugStatus loadModule(DebugModuleInfo debugModuleInfo) { - Msg.info(this, "loadModule: " + debugModuleInfo); - return defaultStatus; - } - - @Override - public DebugStatus sessionStatus(SessionStatus status) { - Msg.info(this, "sessionStatus: " + status); - return defaultStatus; - } - - @Override - public DebugStatus systemError(int error, int level) { - Msg.info(this, "systemError: " + error + ", " + level); - return defaultStatus; - } - - @Override - public DebugStatus unloadModule(String imageBaseName, long baseOffset) { - Msg.info(this, "unloadModule: " + imageBaseName + ", " + baseOffset); - return defaultStatus; - } - } - - protected class ProcMaker implements AutoCloseable { - public ProcMaker(String cmdLine) { - this.cmdLine = cmdLine; - } - - final String cmdLine; - - final CompletableFuture procInfo = new CompletableFuture<>(); - final CompletableFuture threadInfo = new CompletableFuture<>(); - final CompletableFuture procExit = new CompletableFuture<>(); - - StringBuilder outputCapture = null; - - public void start() { - client.setEventCallbacks(new NoisyDebugEventCallbacksAdapter(DebugStatus.NO_CHANGE) { - @Override - public DebugStatus createProcess(DebugProcessInfo debugProcessInfo) { - super.createProcess(debugProcessInfo); - procInfo.complete(debugProcessInfo); - return DebugStatus.BREAK; - } - - @Override - public DebugStatus createThread(DebugThreadInfo debugThreadInfo) { - super.createThread(debugThreadInfo); - threadInfo.complete(debugThreadInfo); - return DebugStatus.BREAK; - } - - @Override - public DebugStatus exitProcess(int exitCode) { - super.exitProcess(exitCode); - procExit.complete(exitCode); - return DebugStatus.BREAK; - } - }); - client.setOutputCallbacks(new DebugOutputCallbacks() { - @Override - public void output(int mask, String text) { - System.out.print(text); - if (outputCapture != null) { - outputCapture.append(text); - } - } - }); - - Msg.debug(this, "Starting " + cmdLine + " with client " + client); - control.execute(".create " + cmdLine); - control.waitForEvent(); - DebugProcessInfo pi = procInfo.getNow(null); - assertNotNull(pi); - control.execute("g"); - control.waitForEvent(); - DebugThreadInfo ti = threadInfo.getNow(null); - assertNotNull(ti); - } - - public void kill() { - Msg.debug(this, "Killing " + cmdLine); - control.execute(".kill"); - control.waitForEvent(); - Integer exitCode = procExit.getNow(null); - client.setOutputCallbacks(null); - assertNotNull(exitCode); - } - - public List execCapture(String command) { - try { - outputCapture = new StringBuilder(); - control.execute(command); - return Arrays.asList(outputCapture.toString().split("\n")); - } - finally { - outputCapture = null; - } - } - - @Override - public void close() { - if (procInfo.isDone() && !procExit.isDone()) { - kill(); - } - } - } - - @Test - public void testGetSingleRegister() { - try (ProcMaker maker = new ProcMaker("notepad")) { - maker.start(); - - List out = maker.execCapture("r"); - String expected = - out.stream().filter(s -> s.startsWith("rax")).findAny().get().split("\\s+")[0]; - - DebugRegisters regs = client.getRegisters(); - DebugInt64Value raxVal = (DebugInt64Value) regs.getValueByName("rax"); - - String actual = String.format("rax=%016x", raxVal.longValue()); - assertEquals(expected, actual); - } - } - - @Test - public void testGetRegisters() { - try (ProcMaker maker = new ProcMaker("notepad")) { - maker.start(); - - List out = maker.execCapture("r"); - String expected = out.stream().filter(s -> s.startsWith("rax")).findAny().get(); - - DebugRegisters regs = client.getRegisters(); - List indices = new ArrayList<>(); - int raxIdx = regs.getIndexByName("rax"); - int rbxIdx = regs.getIndexByName("rbx"); - int rcxIdx = regs.getIndexByName("rcx"); - indices.add(raxIdx); - indices.add(rbxIdx); - indices.add(rcxIdx); - Map values = - regs.getValues(DebugRegisterSource.DEBUG_REGSRC_DEBUGGEE, indices); - - String actual = String.format("rax=%016x rbx=%016x rcx=%016x", - ((DebugInt64Value) values.get(raxIdx)).longValue(), - ((DebugInt64Value) values.get(rbxIdx)).longValue(), - ((DebugInt64Value) values.get(rcxIdx)).longValue()); - assertEquals(expected, actual); - } - } - - @Test - public void testSetSingleRegister() { - try (ProcMaker maker = new ProcMaker("notepad")) { - maker.start(); - - DebugRegisters regs = client.getRegisters(); - regs.setValueByName("rax", new DebugInt64Value(0x0102030405060708L)); - - List out = maker.execCapture("r"); - String actual = - out.stream().filter(s -> s.startsWith("rax")).findAny().get().split("\\s+")[0]; - assertEquals("rax=0102030405060708", actual); - } - } - - @Test - public void testSetRegisters() { - try (ProcMaker maker = new ProcMaker("notepad")) { - maker.start(); - - DebugRegisters regs = client.getRegisters(); - // Purposefully choosing non-linked variant. - // Want to know that order does not make a difference. - Map values = new HashMap<>(); - values.put(regs.getIndexByName("rax"), new DebugInt64Value(0x0102030405060708L)); - values.put(regs.getIndexByName("rbx"), new DebugInt64Value(0x1122334455667788L)); - values.put(regs.getIndexByName("rcx"), new DebugInt64Value(0x8877665544332211L)); - regs.setValues(DebugRegisterSource.DEBUG_REGSRC_DEBUGGEE, values); - - List out = maker.execCapture("r"); - String actual = out.stream().filter(s -> s.startsWith("rax")).findAny().get(); - assertEquals("rax=0102030405060708 rbx=1122334455667788 rcx=8877665544332211", actual); - } - } - - @Test - public void testQueryVirtual() { - // Also, an experiment to figure out how it works - try (ProcMaker maker = new ProcMaker("notepad")) { - maker.start(); - - List collected1 = new ArrayList<>(); - try { - long last = 0; - long offset = 0; - do { - System.out.print(Long.toHexString(offset) + ": "); - DebugMemoryBasicInformation info = client.getDataSpaces().queryVirtual(offset); - System.out.println(info); - collected1.add(info); - last = offset; - offset += info.regionSize; - } - while (Long.compareUnsigned(last, offset) < 0); - } - catch (COMException e) { - if (!e.getMessage().contains("HRESULT: 80004002")) { - throw e; - } - } - - List collected2 = new ArrayList<>(); - for (DebugMemoryBasicInformation info : client.getDataSpaces().iterateVirtual(0)) { - collected2.add(info); - } - - assertTrue(collected1.size() > 0); - assertEquals(collected1, collected2); - } - } - - @Test - public void testModules() { - try (ProcMaker maker = new ProcMaker("notepad")) { - maker.start(); - - for (DebugModule mod : client.getSymbols().iterateModules(0)) { - System.out.println(mod.getIndex() + ": " + Long.toHexString(mod.getBase()) + ": " + - mod.getName(DebugModuleName.MODULE)); - System.out.println(" Img: " + mod.getName(DebugModuleName.IMAGE)); - System.out.println(" Load: " + mod.getName(DebugModuleName.LOADED_IMAGE)); - } - } - } - - @Test(expected = COMException.class) - public void testModuleOutOfBounds() { - try (ProcMaker maker = new ProcMaker("notepad")) { - maker.start(); - - DebugModule umod = client.getSymbols() - .getModuleByIndex( - client.getSymbols().getNumberLoadedModules() + 1); - System.out.println(umod.getBase()); - } - } - - @Test - public void testQueryVirtualWithModule() { - try (ProcMaker maker = new ProcMaker("notepad")) { - maker.start(); - - for (DebugMemoryBasicInformation info : client.getDataSpaces().iterateVirtual(0)) { - if (info.state != PageState.FREE) { - DebugModule mod = null; - String name = "[NONE]"; - try { - mod = client.getSymbols().getModuleByOffset(info.baseAddress, 0); - name = mod.getName(DebugModuleName.IMAGE); - } - catch (COMException e) { - name = "[ERR:" + e + "]"; - } - System.out.println(String.format("%016x", info.baseAddress) + ":" + - Long.toHexString(info.regionSize) + ":" + info.state + " from " + name + - " " + info.type + info.protect); - } - } - } - } - - @Test - public void testSymbols() { - try (ProcMaker maker = new ProcMaker("notepad")) { - maker.start(); - - Set symbols = new LinkedHashSet<>(); - Set modules = new LinkedHashSet<>(); - for (DebugSymbolName sym : client.getSymbols().iterateSymbolMatches("*")) { - String[] parts = sym.name.split("!"); - symbols.add(sym); - modules.add(parts[0]); - } - System.out.println("Total Symbols: " + symbols.size()); - System.out.println("Total Modules (by symbol name): " + modules.size()); - - // These make assumptions that could be broken later. - // It used to expect at least 10 modules (devised when testing on Win7). Now it's 5! - assertTrue("Fewer than 1000 symbols: " + symbols.size(), symbols.size() > 1000); - assertTrue("Fewer than 3 modules: " + modules.size(), modules.size() > 3); - } - } - - @Test - public void testSymbolInfo() { - try (ProcMaker maker = new ProcMaker("notepad")) { - maker.start(); - - int count = 0; - for (DebugSymbolId symid : client.getSymbols().getSymbolIdsByName("ntdll!*")) { - //System.out.println(symid); - DebugSymbolEntry syment = client.getSymbols().getSymbolEntry(symid); - if (syment.typeId != 0) { - System.out.println(" " + syment); - } - count++; - } - - assertTrue(count > 10); - } - } - - @Test - public void testReadMemory() throws FileNotFoundException, IOException { - try (ProcMaker maker = new ProcMaker("notepad")) { - maker.start(); - - control.execute(".server tcp:port=54321"); - int len = 256; - - DebugModule notepadModule = client.getSymbols().getModuleByModuleName("notepad", 0); - System.out.println("Base: " + Long.toHexString(notepadModule.getBase())); - ByteBuffer data = ByteBuffer.allocate(len); - client.getDataSpaces().readVirtual(notepadModule.getBase(), data, data.remaining()); - System.out.println(NumericUtilities.convertBytesToString(data.array())); - - // TODO: Avoid hardcoding path to notepad - try (FileInputStream fis = new FileInputStream("C:\\Windows\\notepad.exe")) { - byte[] fromFile = new byte[len]; - fis.read(fromFile); - // TODO: Note sure why, but this seems to be the case after it's loaded - //ByteBuffer toWriteBase = ByteBuffer.wrap(fromFile).order(ByteOrder.LITTLE_ENDIAN); - //toWriteBase.putLong(280, notepadModule.getBase()); - System.out.println(NumericUtilities.convertBytesToString(fromFile)); - assertArrayEquals(fromFile, data.array()); - } - - data.clear(); - data.putInt(0x12345678); - client.getDataSpaces().readVirtual(notepadModule.getBase(), data, data.remaining()); - data.flip(); - - assertEquals(0x12345678, data.getInt()); - } - } - - @Test - public void testWriteMemory() { - try (ProcMaker maker = new ProcMaker("notepad")) { - maker.start(); - - // TODO: How to write to protected memory? - // Debugger should be able to modify program code. - DebugMemoryBasicInformation writable = null; - space: for (DebugMemoryBasicInformation info : client.getDataSpaces() - .iterateVirtual( - 0)) { - for (PageProtection prot : info.protect) { - if (prot.isWrite()) { - writable = info; - break space; - } - } - } - if (writable == null) { - throw new AssertionError("No writable pages?"); - } - System.out.println("writable: " + writable); - ByteBuffer toWrite = ByteBuffer.allocate(10); - toWrite.putInt(0x12345678); - toWrite.putInt(0x89abcdef); - toWrite.putShort((short) 0x5555); - toWrite.flip(); - client.getDataSpaces().writeVirtual(writable.baseAddress, toWrite, toWrite.remaining()); - - ByteBuffer toRead = ByteBuffer.allocate(10); - client.getDataSpaces().readVirtual(writable.baseAddress, toRead, toRead.remaining()); - - assertArrayEquals(toWrite.array(), toRead.array()); - } - } - - @Test - public void testBreakpoints() { - try (ProcMaker maker = new ProcMaker("notepad")) { - maker.start(); - - DebugBreakpoint bpt = control.addBreakpoint(BreakType.CODE); - System.out.println("Breakpoint id: " + bpt.getId()); - System.out.println("Flags: " + bpt.getFlags()); - DebugBreakpoint bpt2 = control.getBreakpointById(bpt.getId()); - assertEquals(bpt, bpt2); - } - } - - @Test - public void testFreezeUnfreeze() { - try (ProcMaker maker = new ProcMaker("notepad")) { - maker.start(); - - // Trying to see if any events will help me track frozen threads - System.out.println("****Freezing"); - control.execute("~0 f"); - System.out.println("****Unfreezing"); - control.execute("~0 u"); - System.out.println("****Done"); - // Well, that result stinks. - // There is no event to tell me about frozenness - } - } - - @Test - @Ignore("I can't find a reliable means to detect the last thread. " + - "There's supposed to be an initial break, but it is rarely reported. " + - "I thought about toolhelp, but that presumes local live debugging.") - public void testMultiThreadAttach() throws Exception { - // I need to see how to attach to multi-threaded processes. There must be some event - // or condition to indicate when all threads have been discovered. - String specimen = - Application.getOSFile("sctldbgeng", "expCreateThreadSpin.exe").getCanonicalPath(); - client.setOutputCallbacks(new DebugOutputCallbacks() { - @Override - public void output(int mask, String text) { - System.out.print(text); - System.out.flush(); - } - }); - client.setEventCallbacks(new DebugEventCallbacksAdapter() { - @Override - public DebugStatus breakpoint(DebugBreakpoint bp) { - control.outln("*** Breakpoint: " + bp); - return DebugStatus.BREAK; - } - - @Override - public DebugStatus exception(DebugExceptionRecord64 exception, boolean firstChance) { - control.outln("*** Exception: " + exception + "," + firstChance); - return DebugStatus.BREAK; - } - - @Override - public DebugStatus createThread(DebugThreadInfo debugThreadInfo) { - control.outln("*** CreateThread: " + debugThreadInfo); - System.out.println("Threads: " + client.getSystemObjects().getThreads()); - return DebugStatus.BREAK; - } - - @Override - public DebugStatus createProcess(DebugProcessInfo debugProcessInfo) { - control.outln("*** CreateProcess: " + debugProcessInfo); - System.out.println("Threads: " + client.getSystemObjects().getThreads()); - return DebugStatus.BREAK; - } - - @Override - public DebugStatus exitThread(int exitCode) { - control.outln("*** ExitThread: code=" + exitCode + ", " + - client.getSystemObjects().getEventThread()); - System.out.println("Threads: " + client.getSystemObjects().getThreads()); - return DebugStatus.BREAK; - } - - @Override - public DebugStatus exitProcess(int exitCode) { - control.outln("*** ExitProcess: code=" + exitCode + ", " + - client.getSystemObjects().getEventProcess()); - System.out.println("Threads: " + client.getSystemObjects().getThreads()); - return DebugStatus.BREAK; - } - - @Override - public DebugStatus changeEngineState(BitmaskSet flags, - long argument) { - if (flags.contains(ChangeEngineState.EXECUTION_STATUS)) { - control.outln( - "*** ExecutionStatus: " + control.getExecutionStatus()); - } - return DebugStatus.NO_CHANGE; - } - }); - try (DummyProc proc = new DummyProc(specimen)) { - System.out.println("Started " + specimen + " with PID=" + proc.pid); - Thread.sleep(1000); - System.out.println("Attaching..."); - client.attachProcess(client.getLocalServer(), proc.pid, BitmaskSet.of()); - if (true) { - for (int i = 0; i < 10; i++) { - System.out.println("WAIT " + i + "..."); - control.waitForEvent(100); - System.out.println("STATUS: " + control.getExecutionStatus()); - System.out.println("DONE " + i); - // control.execute("~*"); - } - } - } - finally { - client.setEventCallbacks(null); - } - } -} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/manager/impl/AbstractDbgManagerTest.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/manager/impl/AbstractDbgManagerTest.java index 2e3d11b3b8..5b1d00f163 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/manager/impl/AbstractDbgManagerTest.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/manager/impl/AbstractDbgManagerTest.java @@ -15,8 +15,7 @@ */ package agent.dbgeng.manager.impl; -import static agent.dbgeng.testutil.DummyProc.runProc; -import static ghidra.async.AsyncUtils.sequence; +import static ghidra.async.AsyncUtils.*; import static org.junit.Assert.*; import java.io.IOException; @@ -38,9 +37,9 @@ import agent.dbgeng.dbgeng.DebugProcessId; import agent.dbgeng.manager.*; import agent.dbgeng.manager.DbgManager.ExecSuffix; import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo; -import agent.dbgeng.testutil.DummyProc; import ghidra.async.AsyncFence; import ghidra.async.TypeSpec; +import ghidra.dbg.testutil.DummyProc; import ghidra.test.AbstractGhidraHeadlessIntegrationTest; import ghidra.util.Msg; @@ -188,7 +187,7 @@ public abstract class AbstractDbgManagerTest extends AbstractGhidraHeadlessInteg @Test public void testAttachDetach() throws Throwable { - try (DummyProc echo = runProc("dd"); DbgManager mgr = DbgManager.newInstance()) { + try (DummyProc echo = DummyProc.run("dd"); DbgManager mgr = DbgManager.newInstance()) { AtomicReference> threads = new AtomicReference<>(); waitOn(sequence(TypeSpec.VOID).then(seq -> { startManager(mgr).handle(seq::next); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/testutil/DummyProc.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/testutil/DummyProc.java deleted file mode 100644 index 1adb15354c..0000000000 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/testutil/DummyProc.java +++ /dev/null @@ -1,80 +0,0 @@ -/* ### - * 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.testutil; - -import static org.junit.Assume.assumeNoException; -import static org.junit.Assume.assumeTrue; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import com.sun.jna.Pointer; -import com.sun.jna.platform.win32.Kernel32; -import com.sun.jna.platform.win32.WinNT.HANDLE; - -// TODO: Factor this with ghidra.dbg.util.DummyProc (Framework-Debugging) -// Need to work out OS-specific nuances. -public class DummyProc implements AutoCloseable { - final Process process; - public final long pid; - - static ProcessBuilder addWindows64Path(ProcessBuilder builder) { - builder.environment() - .put("PATH", - System.getenv("PATH") + ":" + System.getProperty("user.dir") + - "/build/os/linux64"); - return builder; - } - - public static DummyProc runProc(String... args) throws NoSuchFieldException, SecurityException, - IllegalArgumentException, IllegalAccessException, IOException { - DummyProc proc = new DummyProc(args); - return proc; - } - - DummyProc(String... args) throws IOException, NoSuchFieldException, SecurityException, - IllegalArgumentException, IllegalAccessException { - //args[0] = which(args[0]); - process = new ProcessBuilder(args).start(); - - @SuppressWarnings("hiding") - long pid = -1; - try { - //Field pidFld = process.getClass().getDeclaredField("pid"); - //pidFld.setAccessible(true); - //pid = pidFld.getLong(process); - Class cls = process.getClass(); - assumeTrue(cls.getName().equals("java.lang.ProcessImpl")); - Field handleFld = cls.getDeclaredField("handle"); - handleFld.setAccessible(true); - long handle = handleFld.getLong(process); - pid = Kernel32.INSTANCE.GetProcessId(new HANDLE(new Pointer(handle))); - } - catch (NoSuchFieldException | SecurityException e) { - assumeNoException(e); - } - this.pid = pid; - } - - @Override - public void close() throws Exception { - if (!process.destroyForcibly().waitFor(1000, TimeUnit.MILLISECONDS)) { - throw new TimeoutException("Could not terminate process " + pid); - } - } -} 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 cfe2e965f1..5913f3768a 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 @@ -102,7 +102,7 @@ public class WrappedDbgModel } @Override - public void attachProcess(DebugServerId si, int processId, + public void attachProcess(DebugServerId si, long processId, BitmaskSet attachFlags) { client.attachProcess(si, processId, attachFlags); } diff --git a/Ghidra/Debug/Debugger-agent-dbgmodel/src/test/java/agent/dbgmodel/DummyProc.java b/Ghidra/Debug/Debugger-agent-dbgmodel/src/test/java/agent/dbgmodel/DummyProc.java deleted file mode 100644 index a7f411b83d..0000000000 --- a/Ghidra/Debug/Debugger-agent-dbgmodel/src/test/java/agent/dbgmodel/DummyProc.java +++ /dev/null @@ -1,51 +0,0 @@ -/* ### - * 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.dbgmodel; - -import static org.junit.Assume.assumeTrue; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import com.sun.jna.Pointer; -import com.sun.jna.platform.win32.Kernel32; -import com.sun.jna.platform.win32.WinNT.HANDLE; - -public class DummyProc implements AutoCloseable { - final Process process; - public final int pid; - - public DummyProc(String... args) throws IOException, NoSuchFieldException, SecurityException, - IllegalArgumentException, IllegalAccessException { - process = new ProcessBuilder(args).start(); - - Class cls = process.getClass(); - assumeTrue(cls.getName().equals("java.lang.ProcessImpl")); - Field handleFld = cls.getDeclaredField("handle"); - handleFld.setAccessible(true); - long handle = handleFld.getLong(process); - pid = Kernel32.INSTANCE.GetProcessId(new HANDLE(new Pointer(handle))); - } - - @Override - public void close() throws Exception { - if (!process.destroyForcibly().waitFor(1000, TimeUnit.MILLISECONDS)) { - throw new TimeoutException("Could not terminate process " + pid); - } - } -} From 5453aabfaf51153bc5088869b6c0586e12e98cb1 Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Thu, 23 Sep 2021 17:49:41 +0000 Subject: [PATCH 12/17] GP-1288: support for dbgmodel --- .../DbgModelTargetDebugContainerImpl.java | 4 ++-- .../model/impl/DbgModel2TargetObjectImpl.java | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetDebugContainerImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetDebugContainerImpl.java index e61f5ad972..b09f64641c 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetDebugContainerImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetDebugContainerImpl.java @@ -48,8 +48,8 @@ public class DbgModelTargetDebugContainerImpl extends DbgModelTargetObjectImpl implements DbgModelTargetDebugContainer { protected final DbgModelTargetBreakpointContainerImpl breakpoints; - protected final DbgModelTargetEventContainerImpl events; - protected final DbgModelTargetExceptionContainerImpl exceptions; + protected DbgModelTargetEventContainerImpl events; + protected DbgModelTargetExceptionContainerImpl exceptions; private DbgModelTargetProcess process; 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 74b43594a5..67cfa33ca0 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 @@ -319,6 +319,27 @@ public class DbgModel2TargetObjectImpl extends DefaultTargetObject Date: Thu, 23 Sep 2021 18:10:41 +0000 Subject: [PATCH 13/17] GP-1288: optimization for known sizes --- .../agent/dbgeng/dbgeng/DebugControl.java | 8 +-- .../dbgeng/control/DebugControlImpl1.java | 58 ++++++++++++------- .../cmd/DbgListEventFiltersCommand.java | 6 +- .../cmd/DbgListExceptionFiltersCommand.java | 8 +-- 4 files changed, 47 insertions(+), 33 deletions(-) diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java index 46dfa561f1..de7aedd7e5 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/dbgeng/DebugControl.java @@ -422,9 +422,9 @@ public interface DebugControl extends DebugControlReentrant { DebugFilterInformation getNumberEventFilters(); - String getEventFilterText(int index); + String getEventFilterText(int index, int size); - String getEventFilterCommand(int index); + String getEventFilterCommand(int index, int size); void setEventFilterCommand(int index, String text); @@ -432,7 +432,7 @@ public interface DebugControl extends DebugControlReentrant { void setSpecificFilterParameters(int start, int count, DebugSpecificFilterInformation info); - String getSpecificFilterArgument(int index); + String getSpecificFilterArgument(int index, int size); void setSpecificFilterArgument(int index, String arg); @@ -440,7 +440,7 @@ public interface DebugControl extends DebugControlReentrant { void setExceptionFilterParameters(int count, DebugExceptionFilterInformation info); - String getExceptionFilterSecondCommand(int index); + String getExceptionFilterSecondCommand(int index, int size); void setExceptionFilterSecondCommand(int index, String cmd); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/control/DebugControlImpl1.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/control/DebugControlImpl1.java index 495f5bfcf8..63ca444e04 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/control/DebugControlImpl1.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/impl/dbgeng/control/DebugControlImpl1.java @@ -315,24 +315,31 @@ public class DebugControlImpl1 implements DebugControlInternal { } @Override - public String getEventFilterText(int index) { + public String getEventFilterText(int index, int size) { ULONG ulIndex = new ULONG(index); + ULONG ulBufferSize = new ULONG(size); ULONGByReference ulTextSize = new ULONGByReference(); - COMUtils.checkRC(jnaControl.GetEventFilterText(ulIndex, null, new ULONG(0), ulTextSize)); - byte[] buffer = new byte[ulTextSize.getValue().intValue()]; - ULONG ulBufferSize = ulTextSize.getValue(); + if (size == 0) { + COMUtils.checkRC( + jnaControl.GetEventFilterText(ulIndex, null, new ULONG(0), ulTextSize)); + ulBufferSize = ulTextSize.getValue(); + } + byte[] buffer = new byte[ulBufferSize.intValue()]; COMUtils.checkRC(jnaControl.GetEventFilterText(ulIndex, buffer, ulBufferSize, null)); return Native.toString(buffer); } @Override - public String getEventFilterCommand(int index) { + public String getEventFilterCommand(int index, int size) { ULONG ulIndex = new ULONG(index); + ULONG ulBufferSize = new ULONG(size); ULONGByReference ulCommandSize = new ULONGByReference(); - COMUtils.checkRC( - jnaControl.GetEventFilterCommand(ulIndex, null, new ULONG(0), ulCommandSize)); - byte[] buffer = new byte[ulCommandSize.getValue().intValue()]; - ULONG ulBufferSize = ulCommandSize.getValue(); + if (size == 0) { + COMUtils.checkRC( + jnaControl.GetEventFilterCommand(ulIndex, null, new ULONG(0), ulCommandSize)); + ulBufferSize = ulCommandSize.getValue(); + } + byte[] buffer = new byte[ulBufferSize.intValue()]; COMUtils.checkRC(jnaControl.GetEventFilterCommand(ulIndex, buffer, ulBufferSize, null)); return Native.toString(buffer); } @@ -362,17 +369,20 @@ public class DebugControlImpl1 implements DebugControlInternal { } @Override - public String getSpecificFilterArgument(int index) { + public String getSpecificFilterArgument(int index, int size) { ULONG ulIndex = new ULONG(index); + ULONG ulBufferSize = new ULONG(size); ULONGByReference ulArgumentSize = new ULONGByReference(); - HRESULT hr = - jnaControl.GetSpecificFilterArgument(ulIndex, null, new ULONG(0), ulArgumentSize); - if (hr.equals(COMUtilsExtra.E_INVALID_PARAM)) { - return null; + if (size == 0) { + HRESULT hr = + jnaControl.GetSpecificFilterArgument(ulIndex, null, ulBufferSize, ulArgumentSize); + if (hr.equals(COMUtilsExtra.E_INVALID_PARAM)) { + return null; + } + COMUtils.checkRC(hr); + ulBufferSize = ulArgumentSize.getValue(); } - COMUtils.checkRC(hr); - byte[] buffer = new byte[ulArgumentSize.getValue().intValue()]; - ULONG ulBufferSize = ulArgumentSize.getValue(); + byte[] buffer = new byte[ulBufferSize.intValue()]; COMUtils.checkRC( jnaControl.GetSpecificFilterArgument(ulIndex, buffer, ulBufferSize, null)); return Native.toString(buffer); @@ -410,13 +420,17 @@ public class DebugControlImpl1 implements DebugControlInternal { } @Override - public String getExceptionFilterSecondCommand(int index) { + public String getExceptionFilterSecondCommand(int index, int size) { ULONG ulIndex = new ULONG(index); + ULONG ulBufferSize = new ULONG(size); ULONGByReference ulCommandSize = new ULONGByReference(); - COMUtils.checkRC( - jnaControl.GetExceptionFilterSecondCommand(ulIndex, null, new ULONG(0), ulCommandSize)); - byte[] buffer = new byte[ulCommandSize.getValue().intValue()]; - ULONG ulBufferSize = ulCommandSize.getValue(); + if (size == 0) { + COMUtils.checkRC( + jnaControl.GetExceptionFilterSecondCommand(ulIndex, null, ulBufferSize, + ulCommandSize)); + ulBufferSize = ulCommandSize.getValue(); + } + byte[] buffer = new byte[ulBufferSize.intValue()]; COMUtils.checkRC( jnaControl.GetExceptionFilterSecondCommand(ulIndex, buffer, ulBufferSize, null)); return Native.toString(buffer); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java index d985ba429a..8fff92de76 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListEventFiltersCommand.java @@ -45,10 +45,10 @@ public class DbgListEventFiltersCommand DebugSpecificFilterInformation exc = control.getSpecificFilterParameters(0, info.getNumberEvents()); for (int i = 0; i < info.getNumberEvents(); i++) { - String text = control.getEventFilterText(i); - String cmd = control.getEventFilterCommand(i); - String arg = control.getSpecificFilterArgument(i); DEBUG_SPECIFIC_FILTER_PARAMETERS p = exc.getParameter(i); + String text = control.getEventFilterText(i, p.TextSize.intValue()); + String cmd = control.getEventFilterCommand(i, p.CommandSize.intValue()); + String arg = control.getSpecificFilterArgument(i, p.ArgumentSize.intValue()); DbgEventFilterImpl f = new DbgEventFilterImpl(i, text, cmd, arg, p.ExecutionOption.intValue(), p.ContinueOption.intValue()); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java index 27a19a04c6..0fe8c61f0b 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java @@ -44,14 +44,14 @@ public class DbgListExceptionFiltersCommand DebugFilterInformation info = control.getNumberEventFilters(); int nEvents = info.getNumberEvents(); int nExcs = info.getNumberSpecificExceptions(); - //DebugSpecificFilterInformation spec = control.getSpecificFilterParameters(0, nEvents); DebugExceptionFilterInformation exc = control.getExceptionFilterParameters(nEvents, null, nExcs); for (int i = 0; i < exc.getParameters().length; i++) { DEBUG_EXCEPTION_FILTER_PARAMETERS p = exc.getParameter(i); - String text = control.getEventFilterText(nEvents + i); - String cmd = control.getEventFilterCommand(nEvents + i); - String cmd2 = control.getExceptionFilterSecondCommand(nEvents + i); + String text = control.getEventFilterText(nEvents + i, p.TextSize.intValue()); + String cmd = control.getEventFilterCommand(nEvents + i, p.CommandSize.intValue()); + String cmd2 = control.getExceptionFilterSecondCommand(nEvents + i, + p.SecondCommandSize.intValue()); DbgExceptionFilterImpl filter = new DbgExceptionFilterImpl(i, text, cmd, cmd2, p.ExecutionOption.intValue(), p.ContinueOption.intValue(), p.ExceptionCode.longValue()); From fc115e715ea77735693947da35d04e6c2ed93235 Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Thu, 23 Sep 2021 19:20:46 +0000 Subject: [PATCH 14/17] GP-1288: added arbitrary excs --- .../cmd/DbgListExceptionFiltersCommand.java | 18 ++++++++++++++++++ .../gui/objects/DebuggerObjectsProvider.java | 15 ++++++++++----- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java index 0fe8c61f0b..047943fb4b 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/cmd/DbgListExceptionFiltersCommand.java @@ -44,6 +44,7 @@ public class DbgListExceptionFiltersCommand DebugFilterInformation info = control.getNumberEventFilters(); int nEvents = info.getNumberEvents(); int nExcs = info.getNumberSpecificExceptions(); + int nExcsA = info.getNumberArbitraryExceptions(); DebugExceptionFilterInformation exc = control.getExceptionFilterParameters(nEvents, null, nExcs); for (int i = 0; i < exc.getParameters().length; i++) { @@ -57,5 +58,22 @@ public class DbgListExceptionFiltersCommand p.ExceptionCode.longValue()); result.add(filter); } + if (nExcsA > 0) { + DebugExceptionFilterInformation excA = + control.getExceptionFilterParameters(nEvents + nExcs, null, nExcsA); + for (int i = 0; i < excA.getParameters().length; i++) { + DEBUG_EXCEPTION_FILTER_PARAMETERS p = excA.getParameter(i); + String text = Long.toHexString(p.ExceptionCode.longValue()); + // control.getEventFilterText(nEvents + nExcs + i, p.TextSize.intValue()); + String cmd = + control.getEventFilterCommand(nEvents + nExcs + i, p.CommandSize.intValue()); + String cmd2 = control.getExceptionFilterSecondCommand(nEvents + nExcs + i, + p.SecondCommandSize.intValue()); + DbgExceptionFilterImpl filter = new DbgExceptionFilterImpl(i, text, cmd, cmd2, + p.ExecutionOption.intValue(), p.ContinueOption.intValue(), + p.ExceptionCode.longValue()); + result.add(filter); + } + } } } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java index b111e37163..5d4dd9612e 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java @@ -54,6 +54,7 @@ import ghidra.dbg.target.*; import ghidra.dbg.target.TargetConsole.Channel; import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState; import ghidra.dbg.target.TargetLauncher.TargetCmdLineLauncher; +import ghidra.dbg.target.TargetMethod.ParameterDescription; import ghidra.dbg.target.TargetSteppable.TargetStepKind; import ghidra.dbg.util.DebuggerCallbackReorderer; import ghidra.dbg.util.PathUtils; @@ -1193,7 +1194,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter .keyBinding("F3") .toolBarGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) .toolBarIcon(AbstractSetBreakpointAction.ICON) - .popupMenuPath("&AddBreakpoint") + .popupMenuPath("&Add Breakpoint") .popupMenuGroup(DebuggerResources.GROUP_CONTROL, "C" + groupTargetIndex) .popupMenuIcon(AbstractSetBreakpointAction.ICON) .helpLocation(AbstractSetBreakpointAction.help(plugin)) @@ -1526,10 +1527,14 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter public void performConfigure(ActionContext context) { performAction(context, false, TargetConfigurable.class, configurable -> { - Map args = configDialog.promptArguments(configurable.getConfigParameters()); - if (args != null) { - for (Entry entry : args.entrySet()) { - configurable.writeConfigurationOption(entry.getKey(), entry.getValue()); + Map> configParameters = + configurable.getConfigParameters(); + if (configParameters.size() > 0) { + Map args = configDialog.promptArguments(configParameters); + if (args != null) { + for (Entry entry : args.entrySet()) { + configurable.writeConfigurationOption(entry.getKey(), entry.getValue()); + } } } return AsyncUtils.NIL; From f242f3fc559d65571e63df077db90da81b58bbdb Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Thu, 23 Sep 2021 21:04:40 +0000 Subject: [PATCH 15/17] GP-1288: added system error event logic --- .../evt/DbgInitialBreakpointEvent.java | 25 +++++++++++ .../evt/DbgInitialModuleLoadEvent.java | 25 +++++++++++ .../manager/evt/DbgSystemErrorEvent.java | 44 +++++++++++++++++++ .../impl/DbgDebugEventCallbacksAdapter.java | 5 +++ .../dbgeng/manager/impl/DbgManagerImpl.java | 8 ++++ .../model/impl/DbgModelTargetEventImpl.java | 20 +++++++++ 6 files changed, 127 insertions(+) create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgInitialBreakpointEvent.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgInitialModuleLoadEvent.java create mode 100644 Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgSystemErrorEvent.java diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgInitialBreakpointEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgInitialBreakpointEvent.java new file mode 100644 index 0000000000..9b428d0c60 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgInitialBreakpointEvent.java @@ -0,0 +1,25 @@ +/* ### + * 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.evt; + +import agent.dbgeng.dbgeng.DebugBreakpoint; + +public class DbgInitialBreakpointEvent extends AbstractDbgEvent { + + public DbgInitialBreakpointEvent(DebugBreakpoint info) { + super(info); + } +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgInitialModuleLoadEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgInitialModuleLoadEvent.java new file mode 100644 index 0000000000..b1aaca8d20 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgInitialModuleLoadEvent.java @@ -0,0 +1,25 @@ +/* ### + * 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.evt; + +import agent.dbgeng.dbgeng.DebugModuleInfo; + +public class DbgInitialModuleLoadEvent extends AbstractDbgEvent { + + public DbgInitialModuleLoadEvent(DebugModuleInfo info) { + super(info); + } +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgSystemErrorEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgSystemErrorEvent.java new file mode 100644 index 0000000000..8c79fef490 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgSystemErrorEvent.java @@ -0,0 +1,44 @@ +/* ### + * 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.evt; + +/** + * The event corresponding with "{@code =thread-selected}" + */ +public class DbgSystemErrorEvent extends AbstractDbgEvent { + private final int error; + private final int level; + + /** + * The selected error ID must be specified by dbgeng. + * + * @param error dbgeng-provided id + */ + public DbgSystemErrorEvent(int error, int level) { + super(error); + this.error = error; + this.level = level; + } + + public int getError() { + return error; + } + + public int getLevel() { + return level; + } + +} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgDebugEventCallbacksAdapter.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgDebugEventCallbacksAdapter.java index d836efd2d4..034f5ab19a 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgDebugEventCallbacksAdapter.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/impl/DbgDebugEventCallbacksAdapter.java @@ -132,6 +132,11 @@ public class DbgDebugEventCallbacksAdapter extends DebugEventCallbacksAdapter { return checkInterrupt(DebugStatus.NO_CHANGE); } + @Override + public DebugStatus systemError(int error, int level) { + return checkInterrupt(manager.processEvent(new DbgSystemErrorEvent(error, level))); + } + /* @Override public DebugStatus changeDebuggeeState(BitmaskSet flags, long argument) { 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 e969b3b5a9..8d142cf56c 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 @@ -594,6 +594,7 @@ public class DbgManagerImpl implements DbgManager { handlerMap.put(DbgStateChangedEvent.class, this::processStateChanged); handlerMap.put(DbgSessionSelectedEvent.class, this::processSessionSelected); handlerMap.put(DbgSystemsEvent.class, this::processSystemsEvent); + handlerMap.putVoid(DbgSystemErrorEvent.class, this::processSystemErrorEvent); handlerMap.putVoid(DbgCommandDoneEvent.class, this::processDefault); handlerMap.putVoid(DbgStoppedEvent.class, this::processDefault); handlerMap.putVoid(DbgRunningEvent.class, this::processDefault); @@ -1041,7 +1042,14 @@ public class DbgManagerImpl implements DbgManager { return statusMap.get(evt.getClass()); } + protected void processSystemErrorEvent(DbgSystemErrorEvent evt, Void v) { + getEventListeners().fire.eventSelected(evt, evt.getCause()); + String error = "SystemError " + evt.getError() + ":" + evt.getLevel(); + getEventListeners().fire.consoleOutput(error, 0); + } + protected void processConsoleOutput(DbgConsoleOutputEvent evt, Void v) { + getEventListeners().fire.eventSelected(evt, evt.getCause()); getEventListeners().fire.consoleOutput(evt.getInfo(), evt.getMask()); } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java index 65eaad2ff8..0559b2cafb 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java @@ -126,6 +126,26 @@ public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl changeAttributes(List.of(), List.of(), Map.of( // MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); } + if (event instanceof DbgInitialBreakpointEvent && + getEventIndex() == DebugFilterOrdinals.DEBUG_FILTER_INITIAL_BREAKPOINT.ordinal()) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } + if (event instanceof DbgInitialModuleLoadEvent && + getEventIndex() == DebugFilterOrdinals.DEBUG_FILTER_INITIAL_MODULE_LOAD.ordinal()) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } + if (event instanceof DbgSystemErrorEvent && + getEventIndex() == DebugFilterOrdinals.DEBUG_FILTER_SYSTEM_ERROR.ordinal()) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } + if (event instanceof DbgConsoleOutputEvent && + getEventIndex() == DebugFilterOrdinals.DEBUG_FILTER_DEBUGGEE_OUTPUT.ordinal()) { + changeAttributes(List.of(), List.of(), Map.of( // + MODIFIED_ATTRIBUTE_NAME, true), "Refreshed"); + } } @Override From 2c3d6704af433749aca490cab65f1b7a2297e571 Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Thu, 30 Sep 2021 19:54:41 +0000 Subject: [PATCH 16/17] GP-1288: Addressing some of my own review comments --- .../evt/DbgBreakpointCreatedEvent.java | 9 ++---- .../evt/DbgBreakpointDeletedEvent.java | 7 +---- .../evt/DbgBreakpointModifiedEvent.java | 9 ++---- .../manager/evt/DbgCommandDoneEvent.java | 6 ---- .../manager/evt/DbgCommandErrorEvent.java | 3 -- .../manager/evt/DbgCommandRunningEvent.java | 6 ---- .../manager/evt/DbgConsoleOutputEvent.java | 3 -- .../manager/evt/DbgProcessSelectedEvent.java | 3 -- .../dbgeng/manager/evt/DbgRunningEvent.java | 7 +---- .../manager/evt/DbgSessionSelectedEvent.java | 3 -- .../dbgeng/manager/evt/DbgStoppedEvent.java | 9 ++---- .../manager/evt/DbgSystemErrorEvent.java | 3 -- .../dbgeng/manager/evt/DbgSystemsEvent.java | 3 -- .../manager/evt/DbgThreadSelectedEvent.java | 3 -- .../model/impl/DbgModelTargetEventImpl.java | 2 +- .../impl/DbgModelTargetExceptionImpl.java | 2 +- .../java/agent/dbgeng/dbgeng/DbgEngTest.java | 3 +- .../gui/objects/DebuggerObjectsProvider.java | 28 +++++++++++-------- .../ghidra/dbg/target/TargetConfigurable.java | 23 +++++++++++---- 19 files changed, 45 insertions(+), 87 deletions(-) diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgBreakpointCreatedEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgBreakpointCreatedEvent.java index 973b38a1fe..99b03440d2 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgBreakpointCreatedEvent.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgBreakpointCreatedEvent.java @@ -17,16 +17,11 @@ package agent.dbgeng.manager.evt; import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo; -/** - * The event corresponding with "{@code =breakpoint-created}" - */ public class DbgBreakpointCreatedEvent extends AbstractDbgEvent { private final DbgBreakpointInfo bkptInfo; /** - * Construct a new event by parsing the tail for information - * - * The breakpoint information must be specified by GDB. + * Construct a new event from the given info * * @param info breakpoint info * @@ -39,7 +34,7 @@ public class DbgBreakpointCreatedEvent extends AbstractDbgEvent { private final long number; /** - * Construct a new event by parsing the tail for information - * - * The breakpoint number must be specified by GDB. + * Construct a new event from the given info * * @param info breakpoint info */ diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgBreakpointModifiedEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgBreakpointModifiedEvent.java index 02c3e75fa5..718e95a3d7 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgBreakpointModifiedEvent.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgBreakpointModifiedEvent.java @@ -17,17 +17,12 @@ package agent.dbgeng.manager.evt; import agent.dbgeng.manager.breakpoint.DbgBreakpointInfo; -/** - * The event corresponding with "{@code =breakpoint-modified}" - */ public class DbgBreakpointModifiedEvent extends AbstractDbgEvent { private long bptId; /** - * Construct a new event by parsing the tail for information - * - * The breakpoint information must be specified by GDB. + * Construct a new event from the given info * * @param info breakpoint info */ @@ -44,7 +39,7 @@ public class DbgBreakpointModifiedEvent extends AbstractDbgEvent cmd; - /** - * Construct a new event, parsing the tail for information - */ public DbgCommandDoneEvent() { super(); } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgCommandErrorEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgCommandErrorEvent.java index 7f2549b0cd..a065869226 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgCommandErrorEvent.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgCommandErrorEvent.java @@ -18,9 +18,6 @@ package agent.dbgeng.manager.evt; import agent.dbgeng.manager.DbgEvent; import agent.dbgeng.manager.DbgState; -/** - * The event corresponding with "{@code ^error}" - */ public class DbgCommandErrorEvent extends AbstractDbgCompletedCommandEvent { /** diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgCommandRunningEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgCommandRunningEvent.java index f33c06f079..f812681354 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgCommandRunningEvent.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgCommandRunningEvent.java @@ -17,14 +17,8 @@ package agent.dbgeng.manager.evt; import agent.dbgeng.manager.DbgState; -/** - * The event corresponding with "{@code ^running}" - */ public class DbgCommandRunningEvent extends AbstractDbgCompletedCommandEvent { - /** - * Construct a new event, parsing the tail for information - */ public DbgCommandRunningEvent() { super(); } diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgConsoleOutputEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgConsoleOutputEvent.java index 2a751813e9..7004ee9328 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgConsoleOutputEvent.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgConsoleOutputEvent.java @@ -15,9 +15,6 @@ */ package agent.dbgeng.manager.evt; -/** - * The event corresponding with "{@code ~""}" output records - */ public class DbgConsoleOutputEvent extends AbstractDbgEvent { private int mask; diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgProcessSelectedEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgProcessSelectedEvent.java index 12326e064d..cce6c76dfe 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgProcessSelectedEvent.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgProcessSelectedEvent.java @@ -18,9 +18,6 @@ package agent.dbgeng.manager.evt; import agent.dbgeng.dbgeng.DebugProcessId; import agent.dbgeng.manager.impl.DbgProcessImpl; -/** - * The event corresponding with "{@code =thread-selected}" - */ public class DbgProcessSelectedEvent extends AbstractDbgEvent { private final DebugProcessId id; private DbgProcessImpl process; diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgRunningEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgRunningEvent.java index 78c1c528dd..84b50954a2 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgRunningEvent.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgRunningEvent.java @@ -18,16 +18,11 @@ package agent.dbgeng.manager.evt; import agent.dbgeng.dbgeng.DebugThreadId; import agent.dbgeng.manager.DbgState; -/** - * The event corresponding with "{@code *running}" - */ public class DbgRunningEvent extends AbstractDbgEvent { private final DebugThreadId id; /** - * Construct a new event, parsing the tail for information - * - * A thread ID must be specified by dbgeng. + * Construct a new event with the given thread ID * * @param id the event info */ diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgSessionSelectedEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgSessionSelectedEvent.java index 350714e86e..e5297d2c44 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgSessionSelectedEvent.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgSessionSelectedEvent.java @@ -18,9 +18,6 @@ package agent.dbgeng.manager.evt; import agent.dbgeng.dbgeng.DebugSessionId; import agent.dbgeng.manager.impl.DbgSessionImpl; -/** - * The event corresponding with "{@code =thread-selected}" - */ public class DbgSessionSelectedEvent extends AbstractDbgEvent { private final DebugSessionId id; private DbgSessionImpl session; diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgStoppedEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgStoppedEvent.java index 3df476fc79..209d34fb88 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgStoppedEvent.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgStoppedEvent.java @@ -20,18 +20,13 @@ import agent.dbgeng.manager.DbgState; import agent.dbgeng.manager.impl.DbgStackFrameImpl; import agent.dbgeng.manager.impl.DbgThreadImpl; -/** - * The event corresponding with "{@code *stopped}" - */ public class DbgStoppedEvent extends AbstractDbgEvent { private final DebugThreadId id; /** - * Construct a new event, parsing the tail for information + * Construct a new event with the given thread ID * - * A thread ID must be specified by dbgeng. - * - * @param id the event info + * @param id the thread ID */ public DbgStoppedEvent(DebugThreadId id) { super(id); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgSystemErrorEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgSystemErrorEvent.java index 8c79fef490..f2e8885625 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgSystemErrorEvent.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgSystemErrorEvent.java @@ -15,9 +15,6 @@ */ package agent.dbgeng.manager.evt; -/** - * The event corresponding with "{@code =thread-selected}" - */ public class DbgSystemErrorEvent extends AbstractDbgEvent { private final int error; private final int level; diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgSystemsEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgSystemsEvent.java index 788851d79f..f82b5e55de 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgSystemsEvent.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgSystemsEvent.java @@ -15,9 +15,6 @@ */ package agent.dbgeng.manager.evt; -/** - * The event corresponding with "{@code =thread-selected}" - */ public class DbgSystemsEvent extends AbstractDbgEvent { private final long id; diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgThreadSelectedEvent.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgThreadSelectedEvent.java index cd86b59804..7e3bfe54f5 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgThreadSelectedEvent.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/manager/evt/DbgThreadSelectedEvent.java @@ -21,9 +21,6 @@ import agent.dbgeng.manager.DbgThread; import agent.dbgeng.manager.impl.DbgStackFrameImpl; import agent.dbgeng.manager.impl.DbgThreadImpl; -/** - * The event corresponding with "{@code =thread-selected}" - */ public class DbgThreadSelectedEvent extends AbstractDbgEvent { private final DebugThreadId id; private DbgState state; diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java index 0559b2cafb..b1054b8628 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetEventImpl.java @@ -149,7 +149,7 @@ public class DbgModelTargetEventImpl extends DbgModelTargetObjectImpl } @Override - public Map> getConfigParameters() { + public Map> getConfigurableOptions() { Map> map = new HashMap<>(); ParameterDescription cmdDesc = ParameterDescription.create(String.class, COMMAND_ATTRIBUTE_NAME, false, "", COMMAND_ATTRIBUTE_NAME, "filter command"); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java index 1c1b7dbe27..967a743a1f 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExceptionImpl.java @@ -116,7 +116,7 @@ public class DbgModelTargetExceptionImpl extends DbgModelTargetObjectImpl } @Override - public Map> getConfigParameters() { + public Map> getConfigurableOptions() { Map> map = new HashMap<>(); ParameterDescription cmdDesc = ParameterDescription.create(String.class, COMMAND_ATTRIBUTE_NAME, false, "", COMMAND_ATTRIBUTE_NAME, "filter command"); diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/dbgeng/DbgEngTest.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/dbgeng/DbgEngTest.java index a52ca42f55..51be388ae5 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/dbgeng/DbgEngTest.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/test/java/agent/dbgeng/dbgeng/DbgEngTest.java @@ -16,7 +16,7 @@ package agent.dbgeng.dbgeng; import static org.junit.Assert.*; -import static org.junit.Assume.*; +import static org.junit.Assume.assumeTrue; import java.io.*; import java.nio.ByteBuffer; @@ -29,7 +29,6 @@ import com.sun.jna.Native; import com.sun.jna.platform.win32.COM.COMException; import com.sun.jna.win32.StdCallLibrary; -//import agent.dbgeng.DummyProc; import agent.dbgeng.dbgeng.DebugBreakpoint.BreakType; import agent.dbgeng.dbgeng.DebugClient.*; import agent.dbgeng.dbgeng.DebugDataSpaces.*; diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java index 5d4dd9612e..740f4926a4 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java @@ -46,8 +46,7 @@ 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.services.*; -import ghidra.async.AsyncUtils; -import ghidra.async.TypeSpec; +import ghidra.async.*; import ghidra.dbg.*; import ghidra.dbg.error.DebuggerMemoryAccessException; import ghidra.dbg.target.*; @@ -1528,17 +1527,22 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter public void performConfigure(ActionContext context) { performAction(context, false, TargetConfigurable.class, configurable -> { Map> configParameters = - configurable.getConfigParameters(); - if (configParameters.size() > 0) { - Map args = configDialog.promptArguments(configParameters); - if (args != null) { - for (Entry entry : args.entrySet()) { - configurable.writeConfigurationOption(entry.getKey(), entry.getValue()); - } - } + configurable.getConfigurableOptions(); + if (configParameters.isEmpty()) { + return AsyncUtils.NIL; } - return AsyncUtils.NIL; - }, "Couldn't configure"); + Map args = configDialog.promptArguments(configParameters); + if (args == null) { + // User cancelled + return AsyncUtils.NIL; + } + AsyncFence fence = new AsyncFence(); + for (Entry entry : args.entrySet()) { + fence.include( + configurable.writeConfigurationOption(entry.getKey(), entry.getValue())); + } + return fence.ready(); + }, "Couldn't configure one or more options"); } public void initiateConsole(ActionContext context) { diff --git a/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetConfigurable.java b/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetConfigurable.java index 44965552c0..975635dcb7 100644 --- a/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetConfigurable.java +++ b/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetConfigurable.java @@ -26,10 +26,9 @@ import ghidra.dbg.target.TargetMethod.ParameterDescription; * A target with writable configuration options * *

- * In general, the options are stored as attributes, so that the current values are retrievable by - * the client, and so that the names and types of options are known. Note that not every attribute - * denotes a writable option. Enumeration of available options is not yet specified, but for the - * moment, we assume a subset of the attributes. + * In general, the options are also stored as attributes, so that the current values are retrievable + * by the client. Note that not every attribute denotes a writable option. The list of configurable + * options, along with a description of each, is retrieved using {@link #getConfigurableOptions()}. * *

* Options should be close to their scope of applicability. For example, if an object affects the @@ -51,6 +50,11 @@ public interface TargetConfigurable extends TargetObject { /** * Write a single option to this object * + *

+ * TODO: This should probably be replaced with a {@code configure(Map options)} + * method. That should also make it easy to validate the arguments using the same mechanisms as + * for {@link TargetMethod#invoke(Map)}. + * * @param key the name of the option, typically corresponding to the same-named attribute * @param value the value to assign the option, typically conforming to the attribute schema * @return a future which completes when the change is processed. @@ -59,7 +63,16 @@ public interface TargetConfigurable extends TargetObject { */ public CompletableFuture writeConfigurationOption(String key, Object value); - public default Map> getConfigParameters() { + /** + * Get the map of writable configuration options + * + *

+ * TODO: Implement this properly in all subclasses to advertise their parameters. Then remove + * this default implementation. + * + * @return a map of names to option descriptions + */ + public default Map> getConfigurableOptions() { return new HashMap<>(); } } From 09f00348fc93230b22fe5b59b551632781382686 Mon Sep 17 00:00:00 2001 From: d-millar <33498836+d-millar@users.noreply.github.com> Date: Thu, 30 Sep 2021 17:25:25 -0400 Subject: [PATCH 17/17] GP-1288: post-review fixes --- .../iface2/DbgModelTargetExceptionContainer.java | 2 +- .../impl/DbgModelTargetExecutionOptionImpl.java | 6 +++--- Ghidra/Debug/Debugger/certification.manifest | 2 ++ .../plugin/core/debug/gui/DebuggerResources.java | 5 ++++- .../gui/objects/DebuggerObjectsProvider.java | 2 +- .../Debugger/src/main/resources/images/conf.png | Bin 0 -> 787 bytes .../main/resources/images/system-switch-user.png | Bin 0 -> 761 bytes 7 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 Ghidra/Debug/Debugger/src/main/resources/images/conf.png create mode 100644 Ghidra/Debug/Debugger/src/main/resources/images/system-switch-user.png diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetExceptionContainer.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetExceptionContainer.java index 6f0e06b6d6..7b66363730 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetExceptionContainer.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/iface2/DbgModelTargetExceptionContainer.java @@ -19,7 +19,7 @@ import ghidra.dbg.target.TargetAggregate; import ghidra.dbg.target.schema.*; @TargetObjectSchemaInfo( - name = "EventContainer", + name = "ExceptionContainer", elements = { @TargetElementType(type = DbgModelTargetException.class) }, attributes = { diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java index 2ba750752b..014962d10c 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/java/agent/dbgeng/model/impl/DbgModelTargetExecutionOptionImpl.java @@ -26,7 +26,7 @@ import agent.dbgeng.model.iface2.*; import ghidra.dbg.target.schema.*; @TargetObjectSchemaInfo( - name = "ExecutionFilter", + name = "ExecutionOption", elements = { @TargetElementType(type = Void.class) }, attributes = { @@ -39,7 +39,7 @@ public class DbgModelTargetExecutionOptionImpl extends DbgModelTargetObjectImpl public DbgModelTargetExecutionOptionImpl(DbgModelTargetEvent event, DebugFilterExecutionOption option) { - super(event.getModel(), event, "Execute", "ExecutionFilter"); + super(event.getModel(), event, "Execute", "ExecutionOption"); this.event = event; this.getModel().addModelObject(option, this); this.optionExc = option; @@ -48,7 +48,7 @@ public class DbgModelTargetExecutionOptionImpl extends DbgModelTargetObjectImpl public DbgModelTargetExecutionOptionImpl(DbgModelTargetException exc, DebugFilterExecutionOption option) { - super(exc.getModel(), exc, "Execute", "ExecutionFilter"); + super(exc.getModel(), exc, "Execute", "ExecutionOption"); this.event = exc; this.getModel().addModelObject(option, this); this.optionExc = option; diff --git a/Ghidra/Debug/Debugger/certification.manifest b/Ghidra/Debug/Debugger/certification.manifest index e0ef58ee77..e67929747c 100644 --- a/Ghidra/Debug/Debugger/certification.manifest +++ b/Ghidra/Debug/Debugger/certification.manifest @@ -148,6 +148,7 @@ src/main/resources/images/breakpoints-enable-all.png||GHIDRA||||END| src/main/resources/images/breakpoints-make-effective.png||GHIDRA||||END| src/main/resources/images/breakpoints.png||GHIDRA||||END| src/main/resources/images/closedFolder.png||Modified Nuvola Icons - LGPL 2.1||||END| +src/main/resources/images/conf.png||GHIDRA||||END| src/main/resources/images/connect.png||GHIDRA||||END| src/main/resources/images/console.png||GHIDRA||||END| src/main/resources/images/continue.png||GHIDRA||||END| @@ -176,6 +177,7 @@ src/main/resources/images/stepout.png||GHIDRA||||END| src/main/resources/images/stepover.png||GHIDRA||||END| src/main/resources/images/stop.png||GHIDRA||||END| src/main/resources/images/sync_enabled.png||GHIDRA||||END| +src/main/resources/images/system-switch-user.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/resources/images/table.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END| src/main/resources/images/text-xml.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END| src/main/resources/images/thread.png||GHIDRA||||END| diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java index e54e947418..c47eb3f3d7 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/DebuggerResources.java @@ -170,6 +170,9 @@ public interface DebuggerResources { ImageIcon ICON_BLANK = ResourceManager.loadImage("images/blank.png"); ImageIcon ICON_PACKAGE = ResourceManager.loadImage("images/debugger32.png"); + ImageIcon ICON_CONFIG = ResourceManager.loadImage("images/conf.png"); + ImageIcon ICON_TOGGLE = ResourceManager.loadImage("images/system-switch-user.png"); + HelpLocation HELP_PACKAGE = new HelpLocation("Debugger", "package"); String HELP_ANCHOR_PLUGIN = "plugin"; @@ -1212,7 +1215,7 @@ public interface DebuggerResources { abstract class AbstractToggleAction extends DockingAction { public static final String NAME = "Toggle"; - public static final Icon ICON = ICON_BREAKPOINT_MIXED_ED_MARKER; + public static final Icon ICON = ICON_TOGGLE; public static final String HELP_ANCHOR = "toggle_option"; public static HelpLocation help(Plugin owner) { diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java index 740f4926a4..9cb56ca38d 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/objects/DebuggerObjectsProvider.java @@ -339,7 +339,7 @@ public class DebuggerObjectsProvider extends ComponentProviderAdapter attachDialog = new DebuggerAttachDialog(this); breakpointDialog = new DebuggerBreakpointDialog(this); configDialog = new DebuggerMethodInvocationDialog(tool, "Configuration", "Configure", - DebuggerResources.ICON_LAUNCH); + DebuggerResources.ICON_CONFIG); } private void addToPanel(ObjectPane p) throws Exception { diff --git a/Ghidra/Debug/Debugger/src/main/resources/images/conf.png b/Ghidra/Debug/Debugger/src/main/resources/images/conf.png new file mode 100644 index 0000000000000000000000000000000000000000..4c659e70a27e3c85faf242eff2a315eb20bc9656 GIT binary patch literal 787 zcmV+u1MK{XP)LD8S#1jlC*b6RVh8#}({_0Q+Exkga z&-DJ{<>7sw$1=w7f6(<-V_{*zNGVZDA*G~LDp_BfvtNV7#l^(N#zyir*IKi_zRud( z8h>XwGc%LS=ktkwG3e>(*?f9>`mnULw5gP88e`B}Bc()Z&Ghv2w?c@NlyWzfO8o+S z1h9-TtgNiOw{1I|n3!WgBD6{{DWk)oSIBj*fI3 z#~dCWBBkWv;lT>S&d<+axI_xIzvZl~_LE}rKh zguoa>yWQ^eEWlb`Uf!`R>xV+2&^`HjW7(ky}cFf zcKhe6tE(;B7-O{7?}mqmyK}i5T5HnjG~?sr6pKZ+x3`Jon0mdA5Q4tGKGNxQH}K9F zW4ZvOlv~wm^}AFmQ4IrPQyNmzN*^p+wuZKM5gzDwRrY zfT^h|gb*Dio}8R~1{fS1{4JSGcC>B1<;Ka$N%LwXr4+}<$6qzmn+yIc{sa?dOq_EFs)h8y$IRyYF)#w)_z=>OLJP+tC7D8G zW>}kROsGf2X7bx4ExTJ7I6c7O;$hx?ev3&G(pCW|DM7*X+B9dM zoTX`N6RT>Kj-Z3hVlx;R85^OkyNxSnu3%%!ozg8*@&P9wK*Q|M+3eoFy`7n^8MM}< z_`Z+ld4yreaPKg4-`+9t^>IF+r348G^3#C@v%t{Y5Jg?Y)-9%LxLCYMduuzTku}g{sY_r<{F%SVE-~&H_3Q*1O zNA@1!_1bItANEtP*C{9sV3oC0cQv(6C>fneYyv;>0lN-XkYNqnn7afq?2a2yZZjfO r6KN{|TF#*bYykxShqX{$e@^rZO#Lf0n5^ literal 0 HcmV?d00001