mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-01-09 22:17:55 -05:00
GP-1978: Delete Framework-Debugging. Merge needed parts into
TraceModeling.
This commit is contained in:
@@ -32,7 +32,8 @@ from pybag.dbgeng.win32.kernel32 import STILL_ACTIVE
|
|||||||
|
|
||||||
from . import util, arch, methods, hooks
|
from . import util, arch, methods, hooks
|
||||||
from .dbgmodel.imodelobject import ModelObjectKind
|
from .dbgmodel.imodelobject import ModelObjectKind
|
||||||
from .exdi import exdi_commands, exdi_methods
|
if util.is_exdi():
|
||||||
|
from .exdi import exdi_commands, exdi_methods
|
||||||
|
|
||||||
PAGE_SIZE = 4096
|
PAGE_SIZE = 4096
|
||||||
|
|
||||||
|
|||||||
@@ -243,18 +243,6 @@ def refresh_processes(node: sch.Schema('ProcessContainer')):
|
|||||||
commands.ghidra_trace_put_processes()
|
commands.ghidra_trace_put_processes()
|
||||||
|
|
||||||
|
|
||||||
@REGISTRY.method(action='refresh', display='Refresh Breakpoint Locations')
|
|
||||||
def refresh_proc_breakpoints(node: sch.Schema('BreakpointLocationContainer')):
|
|
||||||
"""
|
|
||||||
Refresh the breakpoint locations for the process.
|
|
||||||
|
|
||||||
In the course of refreshing the locations, the breakpoint list will also be
|
|
||||||
refreshed.
|
|
||||||
"""
|
|
||||||
with commands.open_tracked_tx('Refresh Breakpoint Locations'):
|
|
||||||
commands.ghidra_trace_put_breakpoints()
|
|
||||||
|
|
||||||
|
|
||||||
@REGISTRY.method(action='refresh', display='Refresh Environment')
|
@REGISTRY.method(action='refresh', display='Refresh Environment')
|
||||||
def refresh_environment(node: sch.Schema('Environment')):
|
def refresh_environment(node: sch.Schema('Environment')):
|
||||||
"""Refresh the environment descriptors (arch, os, endian)."""
|
"""Refresh the environment descriptors (arch, os, endian)."""
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<context>
|
<context>
|
||||||
<schema name="DbgRoot" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="DbgRoot" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<attribute name="Sessions" schema="SessionContainer" required="yes" fixed="yes" />
|
<attribute name="Sessions" schema="SessionContainer" required="yes" fixed="yes" />
|
||||||
<attribute name="Settings" schema="ANY" />
|
<attribute name="Settings" schema="ANY" />
|
||||||
<attribute name="State" schema="ANY" />
|
<attribute name="State" schema="ANY" />
|
||||||
@@ -11,19 +10,12 @@
|
|||||||
<attribute schema="ANY"/>
|
<attribute schema="ANY"/>
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="SessionContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="SessionContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<element schema="Session" />
|
<element schema="Session" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="ANY"/>
|
<attribute schema="ANY"/>
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Session" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Session" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Activatable" />
|
<interface name="Activatable" />
|
||||||
<interface name="Access" />
|
|
||||||
<interface name="Attacher" />
|
|
||||||
<interface name="Interpreter" />
|
|
||||||
<interface name="Interruptible" />
|
|
||||||
<interface name="Launcher" />
|
|
||||||
<interface name="ActiveScope" />
|
|
||||||
<interface name="EventScope" />
|
<interface name="EventScope" />
|
||||||
<interface name="FocusScope" />
|
<interface name="FocusScope" />
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
@@ -49,20 +41,16 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="BreakpointContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="BreakpointContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="BreakpointLocationContainer" />
|
|
||||||
<interface name="BreakpointSpecContainer" />
|
|
||||||
<element schema="BreakpointSpec" />
|
<element schema="BreakpointSpec" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="AvailableContainer" canonical="yes" elementResync="ALWAYS" attributeResync="NEVER">
|
<schema name="AvailableContainer" canonical="yes" elementResync="ALWAYS" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<element schema="Attachable" />
|
<element schema="Attachable" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="ProcessContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="ProcessContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<element schema="Process" />
|
<element schema="Process" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
@@ -70,12 +58,11 @@
|
|||||||
<schema name="BreakpointSpec" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="BreakpointSpec" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="BreakpointSpec" />
|
<interface name="BreakpointSpec" />
|
||||||
<interface name="BreakpointLocation" />
|
<interface name="BreakpointLocation" />
|
||||||
<interface name="Deletable" />
|
|
||||||
<interface name="Togglable" />
|
<interface name="Togglable" />
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="Expression" schema="STRING" required="yes" hidden="yes" />
|
<attribute name="Expression" schema="STRING" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_expression" to="Expression" />
|
<attribute-alias from="_expression" to="Expression" />
|
||||||
<attribute name="Kinds" schema="SET_BREAKPOINT_KIND" required="yes" hidden="yes" />
|
<attribute name="Kinds" schema="STRING" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_kinds" to="Kinds" />
|
<attribute-alias from="_kinds" to="Kinds" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute name="Range" schema="RANGE" />
|
<attribute name="Range" schema="RANGE" />
|
||||||
@@ -92,7 +79,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Attachable" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Attachable" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Attachable" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="PID" schema="LONG" />
|
<attribute name="PID" schema="LONG" />
|
||||||
<attribute-alias from="_pid" to="PID" />
|
<attribute-alias from="_pid" to="PID" />
|
||||||
@@ -105,18 +91,9 @@
|
|||||||
<interface name="Process" />
|
<interface name="Process" />
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
<interface name="ExecutionStateful" />
|
<interface name="ExecutionStateful" />
|
||||||
<interface name="Attacher" />
|
|
||||||
<interface name="Deletable" />
|
|
||||||
<interface name="Detachable" />
|
|
||||||
<interface name="Killable" />
|
|
||||||
<interface name="Launcher" />
|
|
||||||
<interface name="Resumable" />
|
|
||||||
<interface name="Steppable" />
|
|
||||||
<interface name="Interruptible" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="Threads" schema="ThreadContainer" required="yes" fixed="yes" />
|
<attribute name="Threads" schema="ThreadContainer" required="yes" fixed="yes" />
|
||||||
<attribute name="Debug" schema="DebugBreakpointContainer" required="yes" fixed="yes" />
|
<attribute name="Debug" schema="DebugBreakpointContainer" required="yes" fixed="yes" />
|
||||||
<!-- attribute name="Breakpoints" schema="BreakpointLocationContainer" required="yes" fixed="yes" /-->
|
|
||||||
<attribute name="Exit Code" schema="LONG" />
|
<attribute name="Exit Code" schema="LONG" />
|
||||||
<attribute-alias from="_exit_code" to="Exit Code" />
|
<attribute-alias from="_exit_code" to="Exit Code" />
|
||||||
<attribute name="Environment" schema="Environment" required="yes" fixed="yes" />
|
<attribute name="Environment" schema="Environment" required="yes" fixed="yes" />
|
||||||
@@ -128,7 +105,6 @@
|
|||||||
<attribute-alias from="_pid" to="PID" />
|
<attribute-alias from="_pid" to="PID" />
|
||||||
<attribute name="State" schema="EXECUTION_STATE" required="yes" hidden="yes" />
|
<attribute name="State" schema="EXECUTION_STATE" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_state" to="State" />
|
<attribute-alias from="_state" to="State" />
|
||||||
<attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" hidden="yes" />
|
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
@@ -149,7 +125,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="ModuleContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
<schema name="ModuleContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||||
<interface name="ModuleContainer" />
|
|
||||||
<element schema="Module" />
|
<element schema="Module" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
@@ -160,22 +135,7 @@
|
|||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="BreakpointLocation" elementResync="NEVER" attributeResync="NEVER">
|
|
||||||
<interface name="BreakpointLocation" />
|
|
||||||
<element schema="VOID" />
|
|
||||||
<attribute name="Range" schema="RANGE" />
|
|
||||||
<attribute-alias from="_range" to="Range" />
|
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
|
||||||
<attribute schema="VOID" />
|
|
||||||
</schema>
|
|
||||||
<schema name="BreakpointLocationContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
|
||||||
<interface name="BreakpointLocationContainer" />
|
|
||||||
<element schema="BreakpointLocation" />
|
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
|
||||||
<attribute schema="VOID" />
|
|
||||||
</schema>
|
|
||||||
<schema name="ThreadContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="ThreadContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<element schema="Thread" />
|
<element schema="Thread" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
@@ -192,7 +152,6 @@
|
|||||||
<interface name="Activatable" />
|
<interface name="Activatable" />
|
||||||
<interface name="Thread" />
|
<interface name="Thread" />
|
||||||
<interface name="ExecutionStateful" />
|
<interface name="ExecutionStateful" />
|
||||||
<interface name="Steppable" />
|
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="Stack" schema="StackFramesContainer" required="yes" fixed="yes" />
|
<attribute name="Stack" schema="StackFramesContainer" required="yes" fixed="yes" />
|
||||||
@@ -238,7 +197,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="SectionContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="SectionContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="SectionContainer" />
|
|
||||||
<element schema="Section" />
|
<element schema="Section" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
@@ -258,13 +216,11 @@
|
|||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="SymbolContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
<schema name="SymbolContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||||
<interface name="SymbolNamespace" />
|
|
||||||
<element schema="Symbol" />
|
<element schema="Symbol" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Symbol" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Symbol" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Symbol" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
@@ -298,7 +254,6 @@
|
|||||||
</schema>
|
</schema>
|
||||||
<schema name="RegisterValueContainer" attributeResync="ONCE">
|
<schema name="RegisterValueContainer" attributeResync="ONCE">
|
||||||
<interface name="RegisterContainer" />
|
<interface name="RegisterContainer" />
|
||||||
<interface name="RegisterBank" />
|
|
||||||
<attribute name="General Purpose Registers" schema="RegisterBank" />
|
<attribute name="General Purpose Registers" schema="RegisterBank" />
|
||||||
<attribute name="Floating Point Registers" schema="RegisterBank" />
|
<attribute name="Floating Point Registers" schema="RegisterBank" />
|
||||||
<attribute name="Advanced Vector Extensions" schema="RegisterBank" />
|
<attribute name="Advanced Vector Extensions" schema="RegisterBank" />
|
||||||
@@ -310,7 +265,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="RegisterBank" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
<schema name="RegisterBank" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||||
<interface name="RegisterBank" />
|
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<context>
|
<context>
|
||||||
<schema name="DbgRoot" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="DbgRoot" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<attribute name="Sessions" schema="SessionContainer" required="yes" fixed="yes" />
|
<attribute name="Sessions" schema="SessionContainer" required="yes" fixed="yes" />
|
||||||
<attribute name="Settings" schema="ANY" />
|
<attribute name="Settings" schema="ANY" />
|
||||||
<attribute name="State" schema="ANY" />
|
<attribute name="State" schema="ANY" />
|
||||||
@@ -11,19 +10,12 @@
|
|||||||
<attribute schema="ANY"/>
|
<attribute schema="ANY"/>
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="SessionContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="SessionContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<element schema="Session" />
|
<element schema="Session" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="ANY"/>
|
<attribute schema="ANY"/>
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Session" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Session" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Activatable" />
|
<interface name="Activatable" />
|
||||||
<interface name="Access" />
|
|
||||||
<interface name="Attacher" />
|
|
||||||
<interface name="Interpreter" />
|
|
||||||
<interface name="Interruptible" />
|
|
||||||
<interface name="Launcher" />
|
|
||||||
<interface name="ActiveScope" />
|
|
||||||
<interface name="EventScope" />
|
<interface name="EventScope" />
|
||||||
<interface name="FocusScope" />
|
<interface name="FocusScope" />
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
@@ -52,20 +44,16 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="BreakpointContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="BreakpointContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="BreakpointLocationContainer" />
|
|
||||||
<interface name="BreakpointSpecContainer" />
|
|
||||||
<element schema="BreakpointSpec" />
|
<element schema="BreakpointSpec" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="AvailableContainer" canonical="yes" elementResync="ALWAYS" attributeResync="NEVER">
|
<schema name="AvailableContainer" canonical="yes" elementResync="ALWAYS" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<element schema="Attachable" />
|
<element schema="Attachable" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="ProcessContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="ProcessContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<element schema="Process" />
|
<element schema="Process" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
@@ -73,12 +61,11 @@
|
|||||||
<schema name="BreakpointSpec" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="BreakpointSpec" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="BreakpointSpec" />
|
<interface name="BreakpointSpec" />
|
||||||
<interface name="BreakpointLocation" />
|
<interface name="BreakpointLocation" />
|
||||||
<interface name="Deletable" />
|
|
||||||
<interface name="Togglable" />
|
<interface name="Togglable" />
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="Expression" schema="STRING" required="yes" hidden="yes" />
|
<attribute name="Expression" schema="STRING" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_expression" to="Expression" />
|
<attribute-alias from="_expression" to="Expression" />
|
||||||
<attribute name="Kinds" schema="SET_BREAKPOINT_KIND" required="yes" hidden="yes" />
|
<attribute name="Kinds" schema="STRING" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_kinds" to="Kinds" />
|
<attribute-alias from="_kinds" to="Kinds" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute name="Range" schema="RANGE" />
|
<attribute name="Range" schema="RANGE" />
|
||||||
@@ -95,7 +82,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Attachable" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Attachable" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Attachable" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="PID" schema="LONG" />
|
<attribute name="PID" schema="LONG" />
|
||||||
<attribute-alias from="_pid" to="PID" />
|
<attribute-alias from="_pid" to="PID" />
|
||||||
@@ -108,18 +94,9 @@
|
|||||||
<interface name="Process" />
|
<interface name="Process" />
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
<interface name="ExecutionStateful" />
|
<interface name="ExecutionStateful" />
|
||||||
<interface name="Attacher" />
|
|
||||||
<interface name="Deletable" />
|
|
||||||
<interface name="Detachable" />
|
|
||||||
<interface name="Killable" />
|
|
||||||
<interface name="Launcher" />
|
|
||||||
<interface name="Resumable" />
|
|
||||||
<interface name="Steppable" />
|
|
||||||
<interface name="Interruptible" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="Threads" schema="ThreadContainer" required="yes" fixed="yes" />
|
<attribute name="Threads" schema="ThreadContainer" required="yes" fixed="yes" />
|
||||||
<attribute name="Debug" schema="DebugBreakpointContainer" required="yes" fixed="yes" />
|
<attribute name="Debug" schema="DebugBreakpointContainer" required="yes" fixed="yes" />
|
||||||
<!-- attribute name="Breakpoints" schema="BreakpointLocationContainer" required="yes" fixed="yes" /-->
|
|
||||||
<attribute name="Exit Code" schema="LONG" />
|
<attribute name="Exit Code" schema="LONG" />
|
||||||
<attribute-alias from="_exit_code" to="Exit Code" />
|
<attribute-alias from="_exit_code" to="Exit Code" />
|
||||||
<attribute name="Environment" schema="Environment" required="yes" fixed="yes" />
|
<attribute name="Environment" schema="Environment" required="yes" fixed="yes" />
|
||||||
@@ -131,7 +108,6 @@
|
|||||||
<attribute-alias from="_pid" to="PID" />
|
<attribute-alias from="_pid" to="PID" />
|
||||||
<attribute name="State" schema="EXECUTION_STATE" required="yes" hidden="yes" />
|
<attribute name="State" schema="EXECUTION_STATE" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_state" to="State" />
|
<attribute-alias from="_state" to="State" />
|
||||||
<attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" hidden="yes" />
|
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
@@ -163,22 +139,7 @@
|
|||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="BreakpointLocation" elementResync="NEVER" attributeResync="NEVER">
|
|
||||||
<interface name="BreakpointLocation" />
|
|
||||||
<element schema="VOID" />
|
|
||||||
<attribute name="Range" schema="RANGE" />
|
|
||||||
<attribute-alias from="_range" to="Range" />
|
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
|
||||||
<attribute schema="VOID" />
|
|
||||||
</schema>
|
|
||||||
<schema name="BreakpointLocationContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
|
||||||
<interface name="BreakpointLocationContainer" />
|
|
||||||
<element schema="BreakpointLocation" />
|
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
|
||||||
<attribute schema="VOID" />
|
|
||||||
</schema>
|
|
||||||
<schema name="ThreadContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="ThreadContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<element schema="Thread" />
|
<element schema="Thread" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
@@ -195,7 +156,6 @@
|
|||||||
<interface name="Activatable" />
|
<interface name="Activatable" />
|
||||||
<interface name="Thread" />
|
<interface name="Thread" />
|
||||||
<interface name="ExecutionStateful" />
|
<interface name="ExecutionStateful" />
|
||||||
<interface name="Steppable" />
|
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="Stack" schema="StackFramesContainer" required="yes" fixed="yes" />
|
<attribute name="Stack" schema="StackFramesContainer" required="yes" fixed="yes" />
|
||||||
@@ -241,7 +201,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="SectionContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="SectionContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="SectionContainer" />
|
|
||||||
<element schema="Section" />
|
<element schema="Section" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
@@ -261,13 +220,11 @@
|
|||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="SymbolContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
<schema name="SymbolContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||||
<interface name="SymbolNamespace" />
|
|
||||||
<element schema="Symbol" />
|
<element schema="Symbol" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Symbol" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Symbol" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Symbol" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
@@ -301,7 +258,6 @@
|
|||||||
</schema>
|
</schema>
|
||||||
<schema name="RegisterValueContainer" attributeResync="ONCE">
|
<schema name="RegisterValueContainer" attributeResync="ONCE">
|
||||||
<interface name="RegisterContainer" />
|
<interface name="RegisterContainer" />
|
||||||
<interface name="RegisterBank" />
|
|
||||||
<attribute name="General Purpose Registers" schema="RegisterBank" />
|
<attribute name="General Purpose Registers" schema="RegisterBank" />
|
||||||
<attribute name="Floating Point Registers" schema="RegisterBank" />
|
<attribute name="Floating Point Registers" schema="RegisterBank" />
|
||||||
<attribute name="Advanced Vector Extensions" schema="RegisterBank" />
|
<attribute name="Advanced Vector Extensions" schema="RegisterBank" />
|
||||||
@@ -313,7 +269,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="RegisterBank" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
<schema name="RegisterBank" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||||
<interface name="RegisterBank" />
|
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
@@ -328,14 +283,6 @@
|
|||||||
<interface name="Process" />
|
<interface name="Process" />
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
<interface name="ExecutionStateful" />
|
<interface name="ExecutionStateful" />
|
||||||
<interface name="Attacher" />
|
|
||||||
<interface name="Deletable" />
|
|
||||||
<interface name="Detachable" />
|
|
||||||
<interface name="Killable" />
|
|
||||||
<interface name="Launcher" />
|
|
||||||
<interface name="Resumable" />
|
|
||||||
<interface name="Steppable" />
|
|
||||||
<interface name="Interruptible" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="Threads" schema="ExdiThreadContainer" required="yes" fixed="yes" />
|
<attribute name="Threads" schema="ExdiThreadContainer" required="yes" fixed="yes" />
|
||||||
<!-- attribute name="Modules" schema="ModuleContainer" required="yes" fixed="yes" /-->
|
<!-- attribute name="Modules" schema="ModuleContainer" required="yes" fixed="yes" /-->
|
||||||
@@ -343,7 +290,6 @@
|
|||||||
<attribute-alias from="_pid" to="PID" />
|
<attribute-alias from="_pid" to="PID" />
|
||||||
<attribute name="State" schema="EXECUTION_STATE" required="yes" hidden="yes" />
|
<attribute name="State" schema="EXECUTION_STATE" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_state" to="State" />
|
<attribute-alias from="_state" to="State" />
|
||||||
<attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" hidden="yes" />
|
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
@@ -375,7 +321,6 @@
|
|||||||
<schema name="ExdiThread" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="ExdiThread" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Thread" />
|
<interface name="Thread" />
|
||||||
<interface name="ExecutionStateful" />
|
<interface name="ExecutionStateful" />
|
||||||
<interface name="Steppable" />
|
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="TID" schema="LONG" />
|
<attribute name="TID" schema="LONG" />
|
||||||
|
|||||||
@@ -228,19 +228,6 @@ def refresh_processes(node: sch.Schema('ProcessContainer')):
|
|||||||
commands.ghidra_trace_put_threads()
|
commands.ghidra_trace_put_threads()
|
||||||
|
|
||||||
|
|
||||||
@REGISTRY.method(action='refresh')
|
|
||||||
def refresh_proc_breakpoints(node: sch.Schema('BreakpointLocationContainer')):
|
|
||||||
"""
|
|
||||||
Refresh the breakpoint locations for the process.
|
|
||||||
|
|
||||||
In the course of refreshing the locations, the breakpoint list will also be
|
|
||||||
refreshed.
|
|
||||||
"""
|
|
||||||
with commands.open_tracked_tx('Refresh Breakpoint Locations'):
|
|
||||||
commands.ghidra_trace_put_breakpoints()
|
|
||||||
|
|
||||||
|
|
||||||
@REGISTRY.method(action='refresh')
|
|
||||||
def refresh_environment(node: sch.Schema('Environment')):
|
def refresh_environment(node: sch.Schema('Environment')):
|
||||||
"""Refresh the environment descriptors (arch, os, endian)."""
|
"""Refresh the environment descriptors (arch, os, endian)."""
|
||||||
with commands.open_tracked_tx('Refresh Environment'):
|
with commands.open_tracked_tx('Refresh Environment'):
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
<context>
|
<context>
|
||||||
<schema name="TTDSession" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="TTDSession" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Access" />
|
|
||||||
<interface name="Attacher" />
|
|
||||||
<interface name="Interpreter" />
|
|
||||||
<interface name="Interruptible" />
|
|
||||||
<interface name="Launcher" />
|
|
||||||
<interface name="ActiveScope" />
|
|
||||||
<interface name="EventScope" />
|
<interface name="EventScope" />
|
||||||
<interface name="FocusScope" />
|
<interface name="FocusScope" />
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
@@ -24,20 +18,16 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="BreakpointContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="BreakpointContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="BreakpointLocationContainer" />
|
|
||||||
<interface name="BreakpointSpecContainer" />
|
|
||||||
<element schema="BreakpointSpec" />
|
<element schema="BreakpointSpec" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="AvailableContainer" canonical="yes" elementResync="ALWAYS" attributeResync="NEVER">
|
<schema name="AvailableContainer" canonical="yes" elementResync="ALWAYS" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<element schema="Attachable" />
|
<element schema="Attachable" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="ProcessContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="ProcessContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<element schema="Process" />
|
<element schema="Process" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
@@ -45,12 +35,11 @@
|
|||||||
<schema name="BreakpointSpec" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="BreakpointSpec" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="BreakpointSpec" />
|
<interface name="BreakpointSpec" />
|
||||||
<interface name="BreakpointLocation" />
|
<interface name="BreakpointLocation" />
|
||||||
<interface name="Deletable" />
|
|
||||||
<interface name="Togglable" />
|
<interface name="Togglable" />
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="Expression" schema="STRING" required="yes" hidden="yes" />
|
<attribute name="Expression" schema="STRING" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_expression" to="Expression" />
|
<attribute-alias from="_expression" to="Expression" />
|
||||||
<attribute name="Kinds" schema="SET_BREAKPOINT_KIND" required="yes" hidden="yes" />
|
<attribute name="Kinds" schema="STRING" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_kinds" to="Kinds" />
|
<attribute-alias from="_kinds" to="Kinds" />
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
@@ -67,7 +56,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Attachable" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Attachable" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Attachable" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="PID" schema="LONG" />
|
<attribute name="PID" schema="LONG" />
|
||||||
<attribute-alias from="_pid" to="PID" />
|
<attribute-alias from="_pid" to="PID" />
|
||||||
@@ -80,18 +68,9 @@
|
|||||||
<interface name="Process" />
|
<interface name="Process" />
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
<interface name="ExecutionStateful" />
|
<interface name="ExecutionStateful" />
|
||||||
<interface name="Attacher" />
|
|
||||||
<interface name="Deletable" />
|
|
||||||
<interface name="Detachable" />
|
|
||||||
<interface name="Killable" />
|
|
||||||
<interface name="Launcher" />
|
|
||||||
<interface name="Resumable" />
|
|
||||||
<interface name="Steppable" />
|
|
||||||
<interface name="Interruptible" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="Threads" schema="ThreadContainer" required="yes" fixed="yes" />
|
<attribute name="Threads" schema="ThreadContainer" required="yes" fixed="yes" />
|
||||||
<attribute name="Breakpoints" schema="BreakpointContainer" required="yes" fixed="yes" />
|
<attribute name="Breakpoints" schema="BreakpointContainer" required="yes" fixed="yes" />
|
||||||
<!-- attribute name="Breakpoints" schema="BreakpointLocationContainer" required="yes" fixed="yes" /-->
|
|
||||||
<attribute name="Exit Code" schema="LONG" />
|
<attribute name="Exit Code" schema="LONG" />
|
||||||
<attribute-alias from="_exit_code" to="Exit Code" />
|
<attribute-alias from="_exit_code" to="Exit Code" />
|
||||||
<attribute name="Environment" schema="Environment" required="yes" fixed="yes" />
|
<attribute name="Environment" schema="Environment" required="yes" fixed="yes" />
|
||||||
@@ -101,7 +80,6 @@
|
|||||||
<attribute-alias from="_pid" to="PID" />
|
<attribute-alias from="_pid" to="PID" />
|
||||||
<attribute name="State" schema="EXECUTION_STATE" required="yes" hidden="yes" />
|
<attribute name="State" schema="EXECUTION_STATE" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_state" to="State" />
|
<attribute-alias from="_state" to="State" />
|
||||||
<attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" hidden="yes" />
|
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
@@ -122,7 +100,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="ModuleContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
<schema name="ModuleContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||||
<interface name="ModuleContainer" />
|
|
||||||
<element schema="Module" />
|
<element schema="Module" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
@@ -133,23 +110,7 @@
|
|||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="BreakpointLocation" elementResync="NEVER" attributeResync="NEVER">
|
|
||||||
<interface name="BreakpointLocation" />
|
|
||||||
<element schema="VOID" />
|
|
||||||
<attribute name="Range" schema="RANGE" />
|
|
||||||
<attribute-alias from="_range" to="Range" />
|
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
|
||||||
<attribute schema="VOID" />
|
|
||||||
</schema>
|
|
||||||
<schema name="BreakpointLocationContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
|
||||||
<interface name="BreakpointLocationContainer" />
|
|
||||||
<element schema="BreakpointLocation" />
|
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
|
||||||
<attribute schema="VOID" />
|
|
||||||
</schema>
|
|
||||||
<schema name="ThreadContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="ThreadContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<element schema="Thread" />
|
<element schema="Thread" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
@@ -166,7 +127,6 @@
|
|||||||
<interface name="Activatable" />
|
<interface name="Activatable" />
|
||||||
<interface name="Thread" />
|
<interface name="Thread" />
|
||||||
<interface name="ExecutionStateful" />
|
<interface name="ExecutionStateful" />
|
||||||
<interface name="Steppable" />
|
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="Stack" schema="Stack" required="yes" fixed="yes" />
|
<attribute name="Stack" schema="Stack" required="yes" fixed="yes" />
|
||||||
@@ -209,7 +169,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="SectionContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="SectionContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="SectionContainer" />
|
|
||||||
<element schema="Section" />
|
<element schema="Section" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
@@ -221,13 +180,11 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="SymbolContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
<schema name="SymbolContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||||
<interface name="SymbolNamespace" />
|
|
||||||
<element schema="Symbol" />
|
<element schema="Symbol" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Symbol" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Symbol" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Symbol" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
@@ -262,7 +219,6 @@
|
|||||||
</schema>
|
</schema>
|
||||||
<schema name="RegisterValueContainer" attributeResync="ONCE">
|
<schema name="RegisterValueContainer" attributeResync="ONCE">
|
||||||
<interface name="RegisterContainer" />
|
<interface name="RegisterContainer" />
|
||||||
<interface name="RegisterBank" />
|
|
||||||
<attribute name="General Purpose Registers" schema="RegisterBank" />
|
<attribute name="General Purpose Registers" schema="RegisterBank" />
|
||||||
<attribute name="Floating Point Registers" schema="RegisterBank" />
|
<attribute name="Floating Point Registers" schema="RegisterBank" />
|
||||||
<attribute name="Advanced Vector Extensions" schema="RegisterBank" />
|
<attribute name="Advanced Vector Extensions" schema="RegisterBank" />
|
||||||
@@ -271,7 +227,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="RegisterBank" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
<schema name="RegisterBank" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||||
<interface name="RegisterBank" />
|
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
<context>
|
<context>
|
||||||
<schema name="GdbSession" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="GdbSession" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Access" />
|
|
||||||
<interface name="Attacher" />
|
|
||||||
<interface name="Interpreter" />
|
|
||||||
<interface name="Interruptible" />
|
|
||||||
<interface name="Launcher" />
|
|
||||||
<interface name="ActiveScope" />
|
|
||||||
<interface name="EventScope" />
|
<interface name="EventScope" />
|
||||||
<interface name="FocusScope" />
|
<interface name="FocusScope" />
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
@@ -25,31 +19,27 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="BreakpointContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="BreakpointContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="BreakpointSpecContainer" />
|
|
||||||
<element schema="BreakpointSpec" />
|
<element schema="BreakpointSpec" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="AvailableContainer" canonical="yes" elementResync="ALWAYS" attributeResync="NEVER">
|
<schema name="AvailableContainer" canonical="yes" elementResync="ALWAYS" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<element schema="Attachable" />
|
<element schema="Attachable" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="InferiorContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="InferiorContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<element schema="Inferior" />
|
<element schema="Inferior" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="BreakpointSpec" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="BreakpointSpec" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="BreakpointSpec" />
|
<interface name="BreakpointSpec" />
|
||||||
<interface name="Deletable" />
|
|
||||||
<interface name="Togglable" />
|
<interface name="Togglable" />
|
||||||
<element schema="BreakpointLocation" />
|
<element schema="BreakpointLocation" />
|
||||||
<attribute name="Expression" schema="STRING" required="yes" hidden="yes" />
|
<attribute name="Expression" schema="STRING" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_expression" to="Expression" />
|
<attribute-alias from="_expression" to="Expression" />
|
||||||
<attribute name="Kinds" schema="SET_BREAKPOINT_KIND" required="yes" hidden="yes" />
|
<attribute name="Kinds" schema="STRING" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_kinds" to="Kinds" />
|
<attribute-alias from="_kinds" to="Kinds" />
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
@@ -65,7 +55,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Attachable" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Attachable" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Attachable" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="PID" schema="LONG" />
|
<attribute name="PID" schema="LONG" />
|
||||||
<attribute-alias from="_pid" to="PID" />
|
<attribute-alias from="_pid" to="PID" />
|
||||||
@@ -78,14 +67,6 @@
|
|||||||
<interface name="Process" />
|
<interface name="Process" />
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
<interface name="ExecutionStateful" />
|
<interface name="ExecutionStateful" />
|
||||||
<interface name="Attacher" />
|
|
||||||
<interface name="Deletable" />
|
|
||||||
<interface name="Detachable" />
|
|
||||||
<interface name="Killable" />
|
|
||||||
<interface name="Launcher" />
|
|
||||||
<interface name="Resumable" />
|
|
||||||
<interface name="Steppable" />
|
|
||||||
<interface name="Interruptible" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="Threads" schema="ThreadContainer" required="yes" fixed="yes" />
|
<attribute name="Threads" schema="ThreadContainer" required="yes" fixed="yes" />
|
||||||
<attribute name="Breakpoints" schema="BreakpointLocationContainer" required="yes" fixed="yes" />
|
<attribute name="Breakpoints" schema="BreakpointLocationContainer" required="yes" fixed="yes" />
|
||||||
@@ -98,7 +79,6 @@
|
|||||||
<attribute-alias from="_pid" to="PID" />
|
<attribute-alias from="_pid" to="PID" />
|
||||||
<attribute name="State" schema="EXECUTION_STATE" required="yes" hidden="yes" />
|
<attribute name="State" schema="EXECUTION_STATE" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_state" to="State" />
|
<attribute-alias from="_state" to="State" />
|
||||||
<attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" hidden="yes" />
|
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
@@ -119,7 +99,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="ModuleContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
<schema name="ModuleContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||||
<interface name="ModuleContainer" />
|
|
||||||
<element schema="Module" />
|
<element schema="Module" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
@@ -142,30 +121,19 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="BreakpointLocationContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="BreakpointLocationContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="BreakpointLocationContainer" />
|
|
||||||
<element schema="BreakpointLocation" />
|
<element schema="BreakpointLocation" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="ThreadContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="ThreadContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<element schema="Thread" />
|
<element schema="Thread" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Method" elementResync="NEVER" attributeResync="NEVER">
|
|
||||||
<interface name="Method" />
|
|
||||||
<element schema="VOID" />
|
|
||||||
<attribute name="_display" schema="STRING" required="yes" fixed="yes" hidden="yes" />
|
|
||||||
<attribute name="_return_type" schema="TYPE" required="yes" fixed="yes" hidden="yes" />
|
|
||||||
<attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" fixed="yes" hidden="yes" />
|
|
||||||
<attribute schema="VOID" fixed="yes" hidden="yes" />
|
|
||||||
</schema>
|
|
||||||
<schema name="Thread" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Thread" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Activatable" />
|
<interface name="Activatable" />
|
||||||
<interface name="Thread" />
|
<interface name="Thread" />
|
||||||
<interface name="ExecutionStateful" />
|
<interface name="ExecutionStateful" />
|
||||||
<interface name="Steppable" />
|
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="Stack" schema="Stack" required="yes" fixed="yes" />
|
<attribute name="Stack" schema="Stack" required="yes" fixed="yes" />
|
||||||
@@ -208,7 +176,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="SectionContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="SectionContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="SectionContainer" />
|
|
||||||
<element schema="Section" />
|
<element schema="Section" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
@@ -220,13 +187,11 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="SymbolContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
<schema name="SymbolContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||||
<interface name="SymbolNamespace" />
|
|
||||||
<element schema="Symbol" />
|
<element schema="Symbol" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Symbol" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Symbol" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Symbol" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
@@ -259,7 +224,6 @@
|
|||||||
</schema>
|
</schema>
|
||||||
<schema name="RegisterValueContainer" attributeResync="NEVER">
|
<schema name="RegisterValueContainer" attributeResync="NEVER">
|
||||||
<interface name="RegisterContainer" />
|
<interface name="RegisterContainer" />
|
||||||
<interface name="RegisterBank" />
|
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ Module.manifest||GHIDRA||||END|
|
|||||||
README.md||GHIDRA||||END|
|
README.md||GHIDRA||||END|
|
||||||
build.gradle||GHIDRA||||END|
|
build.gradle||GHIDRA||||END|
|
||||||
data/debugger-launchers/local-lldb.bat||GHIDRA||||END|
|
data/debugger-launchers/local-lldb.bat||GHIDRA||||END|
|
||||||
src/llvm-project/lldb/bindings/java/java-typemaps.swig||Apache License 2.0 with LLVM Exceptions||||END|
|
|
||||||
src/llvm-project/lldb/bindings/java/java.swig||Apache License 2.0 with LLVM Exceptions||||END|
|
|
||||||
src/main/py/LICENSE||GHIDRA||||END|
|
src/main/py/LICENSE||GHIDRA||||END|
|
||||||
src/main/py/MANIFEST.in||GHIDRA||||END|
|
src/main/py/MANIFEST.in||GHIDRA||||END|
|
||||||
src/main/py/README.md||GHIDRA||||END|
|
src/main/py/README.md||GHIDRA||||END|
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
<context>
|
<context>
|
||||||
<schema name="LldbSession" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="LldbSession" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Access" />
|
|
||||||
<interface name="Attacher" />
|
|
||||||
<interface name="Interpreter" />
|
|
||||||
<interface name="Interruptible" />
|
|
||||||
<interface name="Launcher" />
|
|
||||||
<interface name="ActiveScope" />
|
|
||||||
<interface name="EventScope" />
|
<interface name="EventScope" />
|
||||||
<interface name="FocusScope" />
|
<interface name="FocusScope" />
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
@@ -26,7 +20,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="BreakpointContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="BreakpointContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="BreakpointSpecContainer" />
|
|
||||||
<element schema="BreakpointSpec" />
|
<element schema="BreakpointSpec" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
@@ -37,25 +30,22 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="AvailableContainer" canonical="yes" elementResync="ALWAYS" attributeResync="NEVER">
|
<schema name="AvailableContainer" canonical="yes" elementResync="ALWAYS" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<element schema="Attachable" />
|
<element schema="Attachable" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="ProcessContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="ProcessContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<element schema="Process" />
|
<element schema="Process" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="BreakpointSpec" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="BreakpointSpec" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="BreakpointSpec" />
|
<interface name="BreakpointSpec" />
|
||||||
<interface name="Deletable" />
|
|
||||||
<interface name="Togglable" />
|
<interface name="Togglable" />
|
||||||
<element schema="BreakpointLocation" />
|
<element schema="BreakpointLocation" />
|
||||||
<attribute name="Expression" schema="STRING" required="yes" hidden="yes" />
|
<attribute name="Expression" schema="STRING" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_expression" to="Expression" />
|
<attribute-alias from="_expression" to="Expression" />
|
||||||
<attribute name="Kinds" schema="SET_BREAKPOINT_KIND" required="yes" hidden="yes" />
|
<attribute name="Kinds" schema="STRING" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_kinds" to="Kinds" />
|
<attribute-alias from="_kinds" to="Kinds" />
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
@@ -72,11 +62,10 @@
|
|||||||
</schema>
|
</schema>
|
||||||
<schema name="WatchpointSpec" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="WatchpointSpec" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="BreakpointSpec" />
|
<interface name="BreakpointSpec" />
|
||||||
<interface name="Deletable" />
|
|
||||||
<interface name="Togglable" />
|
<interface name="Togglable" />
|
||||||
<attribute name="Expression" schema="STRING" required="yes" hidden="yes" />
|
<attribute name="Expression" schema="STRING" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_expression" to="Expression" />
|
<attribute-alias from="_expression" to="Expression" />
|
||||||
<attribute name="Kinds" schema="SET_BREAKPOINT_KIND" required="yes" hidden="yes" />
|
<attribute name="Kinds" schema="STRING" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_kinds" to="Kinds" />
|
<attribute-alias from="_kinds" to="Kinds" />
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
@@ -90,7 +79,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Attachable" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Attachable" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Attachable" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="PID" schema="LONG" />
|
<attribute name="PID" schema="LONG" />
|
||||||
<attribute-alias from="_pid" to="PID" />
|
<attribute-alias from="_pid" to="PID" />
|
||||||
@@ -103,14 +91,6 @@
|
|||||||
<interface name="Process" />
|
<interface name="Process" />
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
<interface name="ExecutionStateful" />
|
<interface name="ExecutionStateful" />
|
||||||
<interface name="Attacher" />
|
|
||||||
<interface name="Deletable" />
|
|
||||||
<interface name="Detachable" />
|
|
||||||
<interface name="Killable" />
|
|
||||||
<interface name="Launcher" />
|
|
||||||
<interface name="Resumable" />
|
|
||||||
<interface name="Steppable" />
|
|
||||||
<interface name="Interruptible" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="Threads" schema="ThreadContainer" required="yes" fixed="yes" />
|
<attribute name="Threads" schema="ThreadContainer" required="yes" fixed="yes" />
|
||||||
<attribute name="Breakpoints" schema="BreakpointLocationContainer" required="yes" fixed="yes" />
|
<attribute name="Breakpoints" schema="BreakpointLocationContainer" required="yes" fixed="yes" />
|
||||||
@@ -124,7 +104,6 @@
|
|||||||
<attribute-alias from="_pid" to="PID" />
|
<attribute-alias from="_pid" to="PID" />
|
||||||
<attribute name="State" schema="EXECUTION_STATE" required="yes" hidden="yes" />
|
<attribute name="State" schema="EXECUTION_STATE" required="yes" hidden="yes" />
|
||||||
<attribute-alias from="_state" to="State" />
|
<attribute-alias from="_state" to="State" />
|
||||||
<attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" hidden="yes" />
|
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
@@ -146,7 +125,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="ModuleContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
<schema name="ModuleContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||||
<interface name="ModuleContainer" />
|
|
||||||
<element schema="Module" />
|
<element schema="Module" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
@@ -168,30 +146,19 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="BreakpointLocationContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="BreakpointLocationContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="BreakpointLocationContainer" />
|
|
||||||
<element schema="BreakpointLocation" />
|
<element schema="BreakpointLocation" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="ThreadContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="ThreadContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Configurable" />
|
|
||||||
<element schema="Thread" />
|
<element schema="Thread" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Method" elementResync="NEVER" attributeResync="NEVER">
|
|
||||||
<interface name="Method" />
|
|
||||||
<element schema="VOID" />
|
|
||||||
<attribute name="_display" schema="STRING" required="yes" fixed="yes" hidden="yes" />
|
|
||||||
<attribute name="_return_type" schema="TYPE" required="yes" fixed="yes" hidden="yes" />
|
|
||||||
<attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" fixed="yes" hidden="yes" />
|
|
||||||
<attribute schema="VOID" fixed="yes" hidden="yes" />
|
|
||||||
</schema>
|
|
||||||
<schema name="Thread" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Thread" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Activatable" />
|
<interface name="Activatable" />
|
||||||
<interface name="Thread" />
|
<interface name="Thread" />
|
||||||
<interface name="ExecutionStateful" />
|
<interface name="ExecutionStateful" />
|
||||||
<interface name="Steppable" />
|
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="Stack" schema="Stack" required="yes" fixed="yes" />
|
<attribute name="Stack" schema="Stack" required="yes" fixed="yes" />
|
||||||
@@ -203,7 +170,6 @@
|
|||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute name="Advance" schema="Method" required="yes" fixed="yes" hidden="yes" />
|
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Module" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Module" elementResync="NEVER" attributeResync="NEVER">
|
||||||
@@ -234,7 +200,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="SectionContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="SectionContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="SectionContainer" />
|
|
||||||
<element schema="Section" />
|
<element schema="Section" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
@@ -246,13 +211,11 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="SymbolContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
<schema name="SymbolContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||||
<interface name="SymbolNamespace" />
|
|
||||||
<element schema="Symbol" />
|
<element schema="Symbol" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Symbol" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Symbol" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Symbol" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
@@ -286,7 +249,6 @@
|
|||||||
</schema>
|
</schema>
|
||||||
<schema name="RegisterValueContainer" attributeResync="ONCE">
|
<schema name="RegisterValueContainer" attributeResync="ONCE">
|
||||||
<interface name="RegisterContainer" />
|
<interface name="RegisterContainer" />
|
||||||
<interface name="RegisterBank" />
|
|
||||||
<attribute name="General Purpose Registers" schema="RegisterBank" />
|
<attribute name="General Purpose Registers" schema="RegisterBank" />
|
||||||
<attribute name="Floating Point Registers" schema="RegisterBank" />
|
<attribute name="Floating Point Registers" schema="RegisterBank" />
|
||||||
<attribute name="Advanced Vector Extensions" schema="RegisterBank" />
|
<attribute name="Advanced Vector Extensions" schema="RegisterBank" />
|
||||||
@@ -298,7 +260,6 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="RegisterBank" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
<schema name="RegisterBank" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||||
<interface name="RegisterBank" />
|
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import ghidra.trace.model.Trace;
|
|||||||
import ghidra.trace.model.guest.TracePlatform;
|
import ghidra.trace.model.guest.TracePlatform;
|
||||||
import ghidra.trace.model.program.TraceProgramView;
|
import ghidra.trace.model.program.TraceProgramView;
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
import ghidra.trace.model.target.TraceObjectKeyPath;
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.trace.model.time.schedule.TraceSchedule;
|
import ghidra.trace.model.time.schedule.TraceSchedule;
|
||||||
import ghidra.util.TriConsumer;
|
import ghidra.util.TriConsumer;
|
||||||
@@ -467,14 +467,14 @@ public interface DebuggerTraceManagerService {
|
|||||||
* @param path the path
|
* @param path the path
|
||||||
* @return the best coordinates
|
* @return the best coordinates
|
||||||
*/
|
*/
|
||||||
DebuggerCoordinates resolvePath(TraceObjectKeyPath path);
|
DebuggerCoordinates resolvePath(KeyPath path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activate the given canonical object path
|
* Activate the given canonical object path
|
||||||
*
|
*
|
||||||
* @param path the desired path
|
* @param path the desired path
|
||||||
*/
|
*/
|
||||||
default void activatePath(TraceObjectKeyPath path) {
|
default void activatePath(KeyPath path) {
|
||||||
activate(resolvePath(path));
|
activate(resolvePath(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import generic.theme.GIcon;
|
|||||||
import ghidra.app.services.DebuggerEmulationService;
|
import ghidra.app.services.DebuggerEmulationService;
|
||||||
import ghidra.app.services.DebuggerTraceManagerService;
|
import ghidra.app.services.DebuggerTraceManagerService;
|
||||||
import ghidra.app.services.DebuggerTraceManagerService.ActivationCause;
|
import ghidra.app.services.DebuggerTraceManagerService.ActivationCause;
|
||||||
import ghidra.async.AsyncUtils;
|
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
@@ -258,7 +257,7 @@ public enum ControlMode {
|
|||||||
return CompletableFuture.failedFuture(new MemoryAccessException());
|
return CompletableFuture.failedFuture(new MemoryAccessException());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return AsyncUtils.nil();
|
return CompletableFuture.completedFuture(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -16,19 +16,19 @@
|
|||||||
package ghidra.debug.api.model;
|
package ghidra.debug.api.model;
|
||||||
|
|
||||||
import docking.DefaultActionContext;
|
import docking.DefaultActionContext;
|
||||||
import ghidra.trace.model.target.TraceObjectKeyPath;
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Really just used by scripts to get a path into an action context
|
* Really just used by scripts to get a path into an action context
|
||||||
*/
|
*/
|
||||||
public class DebuggerSingleObjectPathActionContext extends DefaultActionContext {
|
public class DebuggerSingleObjectPathActionContext extends DefaultActionContext {
|
||||||
private final TraceObjectKeyPath path;
|
private final KeyPath path;
|
||||||
|
|
||||||
public DebuggerSingleObjectPathActionContext(TraceObjectKeyPath path) {
|
public DebuggerSingleObjectPathActionContext(KeyPath path) {
|
||||||
this.path = path;
|
this.path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TraceObjectKeyPath getPath() {
|
public KeyPath getPath() {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -22,18 +22,18 @@ import java.util.function.BooleanSupplier;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
import ghidra.program.model.lang.RegisterValue;
|
import ghidra.program.model.lang.RegisterValue;
|
||||||
|
import ghidra.trace.model.TraceExecutionState;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||||
import ghidra.trace.model.guest.TracePlatform;
|
import ghidra.trace.model.guest.TracePlatform;
|
||||||
import ghidra.trace.model.memory.TraceMemoryState;
|
import ghidra.trace.model.memory.TraceMemoryState;
|
||||||
import ghidra.trace.model.stack.TraceStackFrame;
|
import ghidra.trace.model.stack.TraceStackFrame;
|
||||||
import ghidra.trace.model.target.TraceObjectKeyPath;
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.util.Swing;
|
import ghidra.util.Swing;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
@@ -196,7 +196,7 @@ public interface Target {
|
|||||||
* @param path the path of the object
|
* @param path the path of the object
|
||||||
* @return the thread, or null
|
* @return the thread, or null
|
||||||
*/
|
*/
|
||||||
TraceThread getThreadForSuccessor(TraceObjectKeyPath path);
|
TraceThread getThreadForSuccessor(KeyPath path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the execution state of the given thread
|
* Get the execution state of the given thread
|
||||||
@@ -204,7 +204,7 @@ public interface Target {
|
|||||||
* @param thread the thread
|
* @param thread the thread
|
||||||
* @return the state
|
* @return the state
|
||||||
*/
|
*/
|
||||||
TargetExecutionState getThreadExecutionState(TraceThread thread);
|
TraceExecutionState getThreadExecutionState(TraceThread thread);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the trace stack frame that contains the given object
|
* Get the trace stack frame that contains the given object
|
||||||
@@ -212,7 +212,7 @@ public interface Target {
|
|||||||
* @param path the path of the object
|
* @param path the path of the object
|
||||||
* @return the stack frame, or null
|
* @return the stack frame, or null
|
||||||
*/
|
*/
|
||||||
TraceStackFrame getStackFrameForSuccessor(TraceObjectKeyPath path);
|
TraceStackFrame getStackFrameForSuccessor(KeyPath path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the target supports synchronizing focus
|
* Check if the target supports synchronizing focus
|
||||||
@@ -226,7 +226,7 @@ public interface Target {
|
|||||||
*
|
*
|
||||||
* @return the focused object's path, or null
|
* @return the focused object's path, or null
|
||||||
*/
|
*/
|
||||||
TraceObjectKeyPath getFocus();
|
KeyPath getFocus();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #activate(DebuggerCoordinates, DebuggerCoordinates)
|
* @see #activate(DebuggerCoordinates, DebuggerCoordinates)
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import java.util.*;
|
|||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
import ghidra.app.services.DebuggerTraceManagerService;
|
import ghidra.app.services.DebuggerTraceManagerService;
|
||||||
import ghidra.dbg.target.TargetObject;
|
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
import ghidra.framework.data.DefaultProjectData;
|
import ghidra.framework.data.DefaultProjectData;
|
||||||
import ghidra.framework.model.*;
|
import ghidra.framework.model.*;
|
||||||
@@ -35,7 +34,7 @@ import ghidra.trace.model.guest.TracePlatform;
|
|||||||
import ghidra.trace.model.program.TraceProgramView;
|
import ghidra.trace.model.program.TraceProgramView;
|
||||||
import ghidra.trace.model.stack.*;
|
import ghidra.trace.model.stack.*;
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
import ghidra.trace.model.target.TraceObjectKeyPath;
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
import ghidra.trace.model.thread.TraceObjectThread;
|
import ghidra.trace.model.thread.TraceObjectThread;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.trace.model.time.TraceSnapshot;
|
import ghidra.trace.model.time.TraceSnapshot;
|
||||||
@@ -98,7 +97,7 @@ public class DebuggerCoordinates {
|
|||||||
private final TraceProgramView view;
|
private final TraceProgramView view;
|
||||||
private final TraceSchedule time;
|
private final TraceSchedule time;
|
||||||
private final Integer frame;
|
private final Integer frame;
|
||||||
private final TraceObjectKeyPath path;
|
private final KeyPath path;
|
||||||
|
|
||||||
private final int hash;
|
private final int hash;
|
||||||
|
|
||||||
@@ -107,7 +106,7 @@ public class DebuggerCoordinates {
|
|||||||
private TraceObject registerContainer;
|
private TraceObject registerContainer;
|
||||||
|
|
||||||
DebuggerCoordinates(Trace trace, TracePlatform platform, Target target, TraceThread thread,
|
DebuggerCoordinates(Trace trace, TracePlatform platform, Target target, TraceThread thread,
|
||||||
TraceProgramView view, TraceSchedule time, Integer frame, TraceObjectKeyPath path) {
|
TraceProgramView view, TraceSchedule time, Integer frame, KeyPath path) {
|
||||||
this.trace = trace;
|
this.trace = trace;
|
||||||
this.platform = platform;
|
this.platform = platform;
|
||||||
this.target = target;
|
this.target = target;
|
||||||
@@ -182,13 +181,13 @@ public class DebuggerCoordinates {
|
|||||||
return resolveThread(trace, TraceSchedule.ZERO);
|
return resolveThread(trace, TraceSchedule.ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TraceObjectKeyPath resolvePath(Trace trace, TraceThread thread, Integer frame,
|
private static KeyPath resolvePath(Trace trace, TraceThread thread, Integer frame,
|
||||||
TraceSchedule time) {
|
TraceSchedule time) {
|
||||||
TraceObjectKeyPath path = resolvePath(thread, frame, time);
|
KeyPath path = resolvePath(thread, frame, time);
|
||||||
if (path != null) {
|
if (path != null) {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
return TraceObjectKeyPath.of();
|
return KeyPath.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TraceProgramView resolveView(Trace trace, TraceSchedule time) {
|
private static TraceProgramView resolveView(Trace trace, TraceSchedule time) {
|
||||||
@@ -214,7 +213,7 @@ public class DebuggerCoordinates {
|
|||||||
TraceProgramView newView = resolveView(newTrace);
|
TraceProgramView newView = resolveView(newTrace);
|
||||||
TraceSchedule newTime = null; // Allow later resolution
|
TraceSchedule newTime = null; // Allow later resolution
|
||||||
Integer newFrame = resolveFrame(newThread, newTime);
|
Integer newFrame = resolveFrame(newThread, newTime);
|
||||||
TraceObjectKeyPath newPath = resolvePath(newTrace, newThread, newFrame, newTime);
|
KeyPath newPath = resolvePath(newTrace, newThread, newFrame, newTime);
|
||||||
return new DebuggerCoordinates(newTrace, newPlatform, null, newThread, newView, newTime,
|
return new DebuggerCoordinates(newTrace, newPlatform, null, newThread, newView, newTime,
|
||||||
newFrame, newPath);
|
newFrame, newPath);
|
||||||
}
|
}
|
||||||
@@ -248,7 +247,7 @@ public class DebuggerCoordinates {
|
|||||||
return resolveFrame(target, target.getFocus());
|
return resolveFrame(target, target.getFocus());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TraceObjectKeyPath resolvePath(Target target, TraceThread thread,
|
private static KeyPath resolvePath(Target target, TraceThread thread,
|
||||||
Integer frame, TraceSchedule time) {
|
Integer frame, TraceSchedule time) {
|
||||||
if (target.getSnap() != time.getSnap() || !target.isSupportsFocus()) {
|
if (target.getSnap() != time.getSnap() || !target.isSupportsFocus()) {
|
||||||
return resolvePath(target.getTrace(), thread, frame, time);
|
return resolvePath(target.getTrace(), thread, frame, time);
|
||||||
@@ -273,7 +272,7 @@ public class DebuggerCoordinates {
|
|||||||
TraceProgramView newView = resolveView(newTrace);
|
TraceProgramView newView = resolveView(newTrace);
|
||||||
TraceSchedule newTime = null; // Allow later resolution
|
TraceSchedule newTime = null; // Allow later resolution
|
||||||
Integer newFrame = resolveFrame(newThread, newTime);
|
Integer newFrame = resolveFrame(newThread, newTime);
|
||||||
TraceObjectKeyPath newPath = resolvePath(newTrace, newThread, newFrame, newTime);
|
KeyPath newPath = resolvePath(newTrace, newThread, newFrame, newTime);
|
||||||
return new DebuggerCoordinates(newTrace, newPlatform, null, newThread, newView, newTime,
|
return new DebuggerCoordinates(newTrace, newPlatform, null, newThread, newView, newTime,
|
||||||
newFrame, newPath);
|
newFrame, newPath);
|
||||||
}
|
}
|
||||||
@@ -300,8 +299,8 @@ public class DebuggerCoordinates {
|
|||||||
TraceThread newThread = thread != null ? thread : resolveThread(newTarget, newTime);
|
TraceThread newThread = thread != null ? thread : resolveThread(newTarget, newTime);
|
||||||
TraceProgramView newView = view != null ? view : resolveView(newTrace, newTime);
|
TraceProgramView newView = view != null ? view : resolveView(newTrace, newTime);
|
||||||
Integer newFrame = frame != null ? frame : resolveFrame(newTarget, newThread, newTime);
|
Integer newFrame = frame != null ? frame : resolveFrame(newTarget, newThread, newTime);
|
||||||
TraceObjectKeyPath threadOrFramePath = resolvePath(newTarget, newThread, newFrame, newTime);
|
KeyPath threadOrFramePath = resolvePath(newTarget, newThread, newFrame, newTime);
|
||||||
TraceObjectKeyPath newPath = choose(path, threadOrFramePath);
|
KeyPath newPath = choose(path, threadOrFramePath);
|
||||||
return new DebuggerCoordinates(newTrace, newPlatform, newTarget, newThread, newView,
|
return new DebuggerCoordinates(newTrace, newPlatform, newTarget, newThread, newView,
|
||||||
newTime, newFrame, newPath);
|
newTime, newFrame, newPath);
|
||||||
}
|
}
|
||||||
@@ -313,7 +312,7 @@ public class DebuggerCoordinates {
|
|||||||
return thread(trace.getThreadManager().getThread(thread.getKey()));
|
return thread(trace.getThreadManager().getThread(thread.getKey()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TraceObjectKeyPath resolvePath(TraceThread thread, Integer frameLevel,
|
private static KeyPath resolvePath(TraceThread thread, Integer frameLevel,
|
||||||
TraceSchedule time) {
|
TraceSchedule time) {
|
||||||
if (thread instanceof TraceObjectThread tot) {
|
if (thread instanceof TraceObjectThread tot) {
|
||||||
TraceObject objThread = tot.getObject();
|
TraceObject objThread = tot.getObject();
|
||||||
@@ -340,8 +339,8 @@ public class DebuggerCoordinates {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TraceObjectKeyPath choose(TraceObjectKeyPath curPath,
|
private static KeyPath choose(KeyPath curPath,
|
||||||
TraceObjectKeyPath newPath) {
|
KeyPath newPath) {
|
||||||
if (curPath == null) {
|
if (curPath == null) {
|
||||||
return newPath;
|
return newPath;
|
||||||
}
|
}
|
||||||
@@ -371,8 +370,8 @@ public class DebuggerCoordinates {
|
|||||||
// Yes, override frame with 0 on thread changes, unless target says otherwise
|
// Yes, override frame with 0 on thread changes, unless target says otherwise
|
||||||
Integer newFrame = resolveFrame(target, newThread, newTime);
|
Integer newFrame = resolveFrame(target, newThread, newTime);
|
||||||
// Yes, forced frame change may also force object change
|
// Yes, forced frame change may also force object change
|
||||||
TraceObjectKeyPath threadOrFramePath = resolvePath(newThread, newFrame, newTime);
|
KeyPath threadOrFramePath = resolvePath(newThread, newFrame, newTime);
|
||||||
TraceObjectKeyPath newPath = choose(path, threadOrFramePath);
|
KeyPath newPath = choose(path, threadOrFramePath);
|
||||||
return new DebuggerCoordinates(newTrace, newPlatform, target, newThread, newView, newTime,
|
return new DebuggerCoordinates(newTrace, newPlatform, target, newThread, newView, newTime,
|
||||||
newFrame, newPath);
|
newFrame, newPath);
|
||||||
}
|
}
|
||||||
@@ -412,8 +411,8 @@ public class DebuggerCoordinates {
|
|||||||
: resolveThread(trace, target, newTime);
|
: resolveThread(trace, target, newTime);
|
||||||
// This will cause the frame to reset to 0 on every snap change. That's fair....
|
// This will cause the frame to reset to 0 on every snap change. That's fair....
|
||||||
Integer newFrame = resolveFrame(newThread, newTime);
|
Integer newFrame = resolveFrame(newThread, newTime);
|
||||||
TraceObjectKeyPath threadOrFramePath = resolvePath(newThread, newFrame, newTime);
|
KeyPath threadOrFramePath = resolvePath(newThread, newFrame, newTime);
|
||||||
TraceObjectKeyPath newPath = choose(path, threadOrFramePath);
|
KeyPath newPath = choose(path, threadOrFramePath);
|
||||||
return new DebuggerCoordinates(trace, platform, target, newThread, view, newTime,
|
return new DebuggerCoordinates(trace, platform, target, newThread, view, newTime,
|
||||||
newFrame, newPath);
|
newFrame, newPath);
|
||||||
}
|
}
|
||||||
@@ -425,8 +424,8 @@ public class DebuggerCoordinates {
|
|||||||
if (Objects.equals(frame, newFrame)) {
|
if (Objects.equals(frame, newFrame)) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
TraceObjectKeyPath threadOrFramePath = resolvePath(thread, newFrame, getTime());
|
KeyPath threadOrFramePath = resolvePath(thread, newFrame, getTime());
|
||||||
TraceObjectKeyPath newPath = choose(path, threadOrFramePath);
|
KeyPath newPath = choose(path, threadOrFramePath);
|
||||||
return new DebuggerCoordinates(trace, platform, target, thread, view, time, newFrame,
|
return new DebuggerCoordinates(trace, platform, target, thread, view, time, newFrame,
|
||||||
newPath);
|
newPath);
|
||||||
}
|
}
|
||||||
@@ -480,7 +479,7 @@ public class DebuggerCoordinates {
|
|||||||
return time(resolveTime(newView)).replaceView(newView);
|
return time(resolveTime(newView)).replaceView(newView);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TraceThread resolveThread(Trace trace, TraceObjectKeyPath path) {
|
private static TraceThread resolveThread(Trace trace, KeyPath path) {
|
||||||
TraceObject object = trace.getObjectManager().getObjectByCanonicalPath(path);
|
TraceObject object = trace.getObjectManager().getObjectByCanonicalPath(path);
|
||||||
if (object == null) {
|
if (object == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -490,7 +489,7 @@ public class DebuggerCoordinates {
|
|||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Integer resolveFrame(Trace trace, TraceObjectKeyPath path) {
|
private static Integer resolveFrame(Trace trace, KeyPath path) {
|
||||||
TraceObject object = trace.getObjectManager().getObjectByCanonicalPath(path);
|
TraceObject object = trace.getObjectManager().getObjectByCanonicalPath(path);
|
||||||
if (object == null) {
|
if (object == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -502,7 +501,7 @@ public class DebuggerCoordinates {
|
|||||||
return frame == null ? null : frame.getLevel();
|
return frame == null ? null : frame.getLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public DebuggerCoordinates path(TraceObjectKeyPath newPath) {
|
public DebuggerCoordinates path(KeyPath newPath) {
|
||||||
if (trace == null && newPath == null) {
|
if (trace == null && newPath == null) {
|
||||||
return NOWHERE;
|
return NOWHERE;
|
||||||
}
|
}
|
||||||
@@ -524,7 +523,7 @@ public class DebuggerCoordinates {
|
|||||||
newFrame, newPath);
|
newFrame, newPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DebuggerCoordinates pathNonCanonical(TraceObjectKeyPath newPath) {
|
public DebuggerCoordinates pathNonCanonical(KeyPath newPath) {
|
||||||
if (trace == null && newPath == null) {
|
if (trace == null && newPath == null) {
|
||||||
return NOWHERE;
|
return NOWHERE;
|
||||||
}
|
}
|
||||||
@@ -549,19 +548,15 @@ public class DebuggerCoordinates {
|
|||||||
throw new IllegalArgumentException("No such object at path " + newPath);
|
throw new IllegalArgumentException("No such object at path " + newPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static TraceThread resolveThread(Target target, TraceObjectKeyPath objectPath) {
|
protected static TraceThread resolveThread(Target target, KeyPath objectPath) {
|
||||||
return target.getThreadForSuccessor(objectPath);
|
return target.getThreadForSuccessor(objectPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static Integer resolveFrame(Target target, TraceObjectKeyPath objectPath) {
|
protected static Integer resolveFrame(Target target, KeyPath objectPath) {
|
||||||
TraceStackFrame frame = target.getStackFrameForSuccessor(objectPath);
|
TraceStackFrame frame = target.getStackFrameForSuccessor(objectPath);
|
||||||
return frame == null ? null : frame.getLevel();
|
return frame == null ? null : frame.getLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public DebuggerCoordinates object(TargetObject targetObject) {
|
|
||||||
return path(TraceObjectKeyPath.of(targetObject.getPath()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public DebuggerCoordinates object(TraceObject newObject) {
|
public DebuggerCoordinates object(TraceObject newObject) {
|
||||||
if (newObject == null) {
|
if (newObject == null) {
|
||||||
return path(null);
|
return path(null);
|
||||||
@@ -604,7 +599,7 @@ public class DebuggerCoordinates {
|
|||||||
return frame == null ? 0 : frame;
|
return frame == null ? 0 : frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TraceObjectKeyPath getPath() {
|
public KeyPath getPath() {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,7 +621,7 @@ public class DebuggerCoordinates {
|
|||||||
if (registerContainer != null) {
|
if (registerContainer != null) {
|
||||||
return registerContainer;
|
return registerContainer;
|
||||||
}
|
}
|
||||||
return registerContainer = getObject().queryRegisterContainer(getFrame());
|
return registerContainer = getObject().findRegisterContainer(getFrame());
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized long getViewSnap() {
|
public synchronized long getViewSnap() {
|
||||||
@@ -761,7 +756,7 @@ public class DebuggerCoordinates {
|
|||||||
if (trace != null && coordState.hasValue(KEY_OBJ_PATH)) {
|
if (trace != null && coordState.hasValue(KEY_OBJ_PATH)) {
|
||||||
String pathString = coordState.getString(KEY_OBJ_PATH, "");
|
String pathString = coordState.getString(KEY_OBJ_PATH, "");
|
||||||
try {
|
try {
|
||||||
TraceObjectKeyPath path = TraceObjectKeyPath.parse(pathString);
|
KeyPath path = KeyPath.parse(pathString);
|
||||||
object = trace.getObjectManager().getObjectByCanonicalPath(path);
|
object = trace.getObjectManager().getObjectByCanonicalPath(path);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -21,12 +21,11 @@ import java.util.concurrent.ExecutionException;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import ghidra.async.AsyncUtils;
|
import ghidra.async.AsyncUtils;
|
||||||
import ghidra.dbg.target.TargetObject;
|
|
||||||
import ghidra.dbg.target.schema.*;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.debug.api.target.ActionName;
|
import ghidra.debug.api.target.ActionName;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
|
import ghidra.trace.model.target.schema.*;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A remote method registered by the back-end debugger.
|
* A remote method registered by the back-end debugger.
|
||||||
@@ -102,7 +101,7 @@ public interface RemoteMethod {
|
|||||||
* Check the type of an argument.
|
* Check the type of an argument.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* This is a hack, because {@link TargetObjectSchema} expects {@link TargetObject}, or a
|
* This is a hack, because {@link TraceObjectSchema} expects {@link TargetObject}, or a
|
||||||
* primitive. We instead need {@link TraceObject}. I'd add the method to the schema, except that
|
* primitive. We instead need {@link TraceObject}. I'd add the method to the schema, except that
|
||||||
* trace stuff is not in its dependencies.
|
* trace stuff is not in its dependencies.
|
||||||
*
|
*
|
||||||
@@ -111,17 +110,17 @@ public interface RemoteMethod {
|
|||||||
* @param sch the type of the parameter
|
* @param sch the type of the parameter
|
||||||
* @param arg the argument
|
* @param arg the argument
|
||||||
*/
|
*/
|
||||||
static void checkType(String paramName, SchemaName schName, TargetObjectSchema sch,
|
static void checkType(String paramName, SchemaName schName, TraceObjectSchema sch,
|
||||||
Object arg) {
|
Object arg) {
|
||||||
// if sch is null, it was definitely an object-type schema without context
|
// if sch is null, it was definitely an object-type schema without context
|
||||||
if (sch != null) {
|
if (sch != null) {
|
||||||
if (sch.getType() != TargetObject.class) {
|
if (sch.getType() != TraceObject.class) {
|
||||||
if (sch.getType().isInstance(arg)) {
|
if (sch.getType().isInstance(arg)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (arg instanceof TraceObject obj) {
|
else if (arg instanceof TraceObject obj) {
|
||||||
if (sch.isAssignableFrom(obj.getTargetSchema())) {
|
if (sch.isAssignableFrom(obj.getSchema())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,7 +143,7 @@ public interface RemoteMethod {
|
|||||||
*/
|
*/
|
||||||
default Trace validate(Map<String, Object> arguments) {
|
default Trace validate(Map<String, Object> arguments) {
|
||||||
Trace trace = null;
|
Trace trace = null;
|
||||||
SchemaContext ctx = EnumerableTargetObjectSchema.MinimalSchemaContext.INSTANCE;
|
SchemaContext ctx = PrimitiveTraceObjectSchema.MinimalSchemaContext.INSTANCE;
|
||||||
for (Map.Entry<String, RemoteParameter> ent : parameters().entrySet()) {
|
for (Map.Entry<String, RemoteParameter> ent : parameters().entrySet()) {
|
||||||
if (!arguments.containsKey(ent.getKey())) {
|
if (!arguments.containsKey(ent.getKey())) {
|
||||||
if (ent.getValue().required()) {
|
if (ent.getValue().required()) {
|
||||||
@@ -165,7 +164,7 @@ public interface RemoteMethod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
SchemaName schName = ent.getValue().type();
|
SchemaName schName = ent.getValue().type();
|
||||||
TargetObjectSchema sch = ctx.getSchemaOrNull(schName);
|
TraceObjectSchema sch = ctx.getSchemaOrNull(schName);
|
||||||
checkType(ent.getKey(), schName, sch, arg);
|
checkType(ent.getKey(), schName, sch, arg);
|
||||||
}
|
}
|
||||||
for (Map.Entry<String, Object> ent : arguments.entrySet()) {
|
for (Map.Entry<String, Object> ent : arguments.entrySet()) {
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.debug.api.tracermi;
|
package ghidra.debug.api.tracermi;
|
||||||
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
|
|
||||||
public interface RemoteParameter {
|
public interface RemoteParameter {
|
||||||
String name();
|
String name();
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import ghidra.app.script.GhidraScript;
|
|||||||
import ghidra.app.script.GhidraState;
|
import ghidra.app.script.GhidraState;
|
||||||
import ghidra.app.services.*;
|
import ghidra.app.services.*;
|
||||||
import ghidra.app.services.DebuggerControlService.StateEditor;
|
import ghidra.app.services.DebuggerControlService.StateEditor;
|
||||||
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
|
||||||
import ghidra.debug.api.breakpoint.LogicalBreakpoint;
|
import ghidra.debug.api.breakpoint.LogicalBreakpoint;
|
||||||
import ghidra.debug.api.control.ControlMode;
|
import ghidra.debug.api.control.ControlMode;
|
||||||
import ghidra.debug.api.model.DebuggerObjectActionContext;
|
import ghidra.debug.api.model.DebuggerObjectActionContext;
|
||||||
@@ -51,6 +50,7 @@ import ghidra.trace.model.memory.TraceMemoryOperations;
|
|||||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||||
import ghidra.trace.model.program.TraceProgramView;
|
import ghidra.trace.model.program.TraceProgramView;
|
||||||
import ghidra.trace.model.target.*;
|
import ghidra.trace.model.target.*;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
import ghidra.trace.model.thread.TraceObjectThread;
|
import ghidra.trace.model.thread.TraceObjectThread;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.trace.model.time.schedule.TraceSchedule;
|
import ghidra.trace.model.time.schedule.TraceSchedule;
|
||||||
@@ -1452,13 +1452,13 @@ public interface FlatDebuggerAPI {
|
|||||||
return createContext(objThread.getObject());
|
return createContext(objThread.getObject());
|
||||||
}
|
}
|
||||||
return new DebuggerSingleObjectPathActionContext(
|
return new DebuggerSingleObjectPathActionContext(
|
||||||
TraceObjectKeyPath.parse(thread.getPath()));
|
KeyPath.parse(thread.getPath()));
|
||||||
}
|
}
|
||||||
|
|
||||||
default ActionContext createContext(Trace trace) {
|
default ActionContext createContext(Trace trace) {
|
||||||
DebuggerCoordinates coords = getTraceManager().getCurrentFor(trace);
|
DebuggerCoordinates coords = getTraceManager().getCurrentFor(trace);
|
||||||
if (coords == null) {
|
if (coords == null) {
|
||||||
return new DebuggerSingleObjectPathActionContext(TraceObjectKeyPath.of());
|
return new DebuggerSingleObjectPathActionContext(KeyPath.of());
|
||||||
}
|
}
|
||||||
if (coords.getObject() != null) {
|
if (coords.getObject() != null) {
|
||||||
return createContext(coords.getObject());
|
return createContext(coords.getObject());
|
||||||
@@ -1466,7 +1466,7 @@ public interface FlatDebuggerAPI {
|
|||||||
if (coords.getPath() != null) {
|
if (coords.getPath() != null) {
|
||||||
return new DebuggerSingleObjectPathActionContext(coords.getPath());
|
return new DebuggerSingleObjectPathActionContext(coords.getPath());
|
||||||
}
|
}
|
||||||
return new DebuggerSingleObjectPathActionContext(TraceObjectKeyPath.of());
|
return new DebuggerSingleObjectPathActionContext(KeyPath.of());
|
||||||
}
|
}
|
||||||
|
|
||||||
default ActionEntry findAction(Target target, ActionName action, ActionContext context) {
|
default ActionEntry findAction(Target target, ActionName action, ActionContext context) {
|
||||||
@@ -1688,25 +1688,25 @@ public interface FlatDebuggerAPI {
|
|||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* If the trace does not have a live target, it is considered
|
* If the trace does not have a live target, it is considered
|
||||||
* {@link TargetExecutionState#TERMINATED} (even if the trace <em>never</em> technically had a
|
* {@link TraceExecutionState#TERMINATED} (even if the trace <em>never</em> technically had a
|
||||||
* live target.) Otherwise, this gets the state of that live target. <b>NOTE:</b> This does not
|
* live target.) Otherwise, this gets the state of that live target. <b>NOTE:</b> This does not
|
||||||
* consider the current snap. It only considers a live target in the present.
|
* consider the current snap. It only considers a live target in the present.
|
||||||
*
|
*
|
||||||
* @param trace the trace
|
* @param trace the trace
|
||||||
* @return the trace's execution state
|
* @return the trace's execution state
|
||||||
*/
|
*/
|
||||||
default TargetExecutionState getExecutionState(Trace trace) {
|
default TraceExecutionState getExecutionState(Trace trace) {
|
||||||
Target target = getTargetService().getTarget(trace);
|
Target target = getTargetService().getTarget(trace);
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
return TargetExecutionState.TERMINATED;
|
return TraceExecutionState.TERMINATED;
|
||||||
}
|
}
|
||||||
// Use resume action's enablement as a proxy for state
|
// Use resume action's enablement as a proxy for state
|
||||||
// This should work for recorder or rmi targets
|
// This should work for recorder or rmi targets
|
||||||
ActionEntry action = findAction(target, ActionName.RESUME, createContext(trace));
|
ActionEntry action = findAction(target, ActionName.RESUME, createContext(trace));
|
||||||
if (action == null) {
|
if (action == null) {
|
||||||
return TargetExecutionState.ALIVE;
|
return TraceExecutionState.ALIVE;
|
||||||
}
|
}
|
||||||
return action.isEnabled() ? TargetExecutionState.STOPPED : TargetExecutionState.RUNNING;
|
return action.isEnabled() ? TraceExecutionState.STOPPED : TraceExecutionState.RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1714,7 +1714,7 @@ public interface FlatDebuggerAPI {
|
|||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* If the thread does not have a corresponding live target thread, it is considered
|
* If the thread does not have a corresponding live target thread, it is considered
|
||||||
* {@link TargetExecutionState#TERMINATED} (even if the thread <em>never</em> technically had a
|
* {@link TraceExecutionState#TERMINATED} (even if the thread <em>never</em> technically had a
|
||||||
* live target thread.) Otherwise, this gets the state of that live target thread. <b>NOTE:</b>
|
* live target thread.) Otherwise, this gets the state of that live target thread. <b>NOTE:</b>
|
||||||
* This does not consider the current snap. It only considers a live target thread in the
|
* This does not consider the current snap. It only considers a live target thread in the
|
||||||
* present. In other words, if the user rewinds trace history to a point where the thread was
|
* present. In other words, if the user rewinds trace history to a point where the thread was
|
||||||
@@ -1725,10 +1725,10 @@ public interface FlatDebuggerAPI {
|
|||||||
* @param thread
|
* @param thread
|
||||||
* @return the thread's execution state
|
* @return the thread's execution state
|
||||||
*/
|
*/
|
||||||
default TargetExecutionState getExecutionState(TraceThread thread) {
|
default TraceExecutionState getExecutionState(TraceThread thread) {
|
||||||
DebuggerCoordinates coords = getTraceManager().getCurrentFor(thread.getTrace());
|
DebuggerCoordinates coords = getTraceManager().getCurrentFor(thread.getTrace());
|
||||||
if (!coords.isAlive()) {
|
if (!coords.isAlive()) {
|
||||||
return TargetExecutionState.TERMINATED;
|
return TraceExecutionState.TERMINATED;
|
||||||
}
|
}
|
||||||
return coords.getTarget().getThreadExecutionState(thread);
|
return coords.getTarget().getThreadExecutionState(thread);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,7 @@ eclipse.project.name = 'Debug Debugger-isf'
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api project(':Framework-AsyncComm')
|
api project(':Framework-AsyncComm')
|
||||||
api project(':Framework-Debugging')
|
|
||||||
api project(':ProposedUtils')
|
api project(':ProposedUtils')
|
||||||
|
|
||||||
testImplementation project(path: ':Framework-AsyncComm', configuration: 'testArtifacts')
|
testImplementation project(path: ':Framework-AsyncComm', configuration: 'testArtifacts')
|
||||||
testImplementation project(path: ':Framework-Debugging', configuration: 'testArtifacts')
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -15,9 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.dbg.jdi.manager;
|
package ghidra.dbg.jdi.manager;
|
||||||
|
|
||||||
import ghidra.dbg.target.TargetConsole.Channel;
|
|
||||||
|
|
||||||
public interface JdiConsoleOutputListener {
|
public interface JdiConsoleOutputListener {
|
||||||
|
/**
|
||||||
|
* For console output notifications, indicates whether it is normal or error output
|
||||||
|
*/
|
||||||
|
public static enum Channel {
|
||||||
|
STDOUT, STDERR;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JDI outputted some text
|
* JDI outputted some text
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import com.sun.jdi.connect.AttachingConnector;
|
|||||||
import com.sun.jdi.connect.Connector;
|
import com.sun.jdi.connect.Connector;
|
||||||
import com.sun.jdi.connect.Connector.Argument;
|
import com.sun.jdi.connect.Connector.Argument;
|
||||||
|
|
||||||
import ghidra.dbg.util.ShellUtils;
|
import ghidra.pty.ShellUtils;
|
||||||
|
|
||||||
public class JdiArguments {
|
public class JdiArguments {
|
||||||
enum Mode {
|
enum Mode {
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ import ghidra.app.plugin.core.debug.client.tracermi.*;
|
|||||||
import ghidra.app.plugin.core.debug.client.tracermi.RmiMethodRegistry.TraceMethod;
|
import ghidra.app.plugin.core.debug.client.tracermi.RmiMethodRegistry.TraceMethod;
|
||||||
import ghidra.dbg.jdi.manager.impl.DebugStatus;
|
import ghidra.dbg.jdi.manager.impl.DebugStatus;
|
||||||
import ghidra.dbg.jdi.manager.impl.JdiManagerImpl;
|
import ghidra.dbg.jdi.manager.impl.JdiManagerImpl;
|
||||||
import ghidra.dbg.target.schema.EnumerableTargetObjectSchema;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
|
import ghidra.trace.model.target.schema.PrimitiveTraceObjectSchema;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
public class JdiConnector {
|
public class JdiConnector {
|
||||||
@@ -92,7 +92,7 @@ public class JdiConnector {
|
|||||||
private final Map<ReferenceType, AddressRange> cpAddressRangeByClass = new HashMap<>();
|
private final Map<ReferenceType, AddressRange> cpAddressRangeByClass = new HashMap<>();
|
||||||
|
|
||||||
private final Map<String, DebugStatus> returnStatusMap = new HashMap<>();
|
private final Map<String, DebugStatus> returnStatusMap = new HashMap<>();
|
||||||
final TargetObjectSchema rootSchema;
|
final TraceObjectSchema rootSchema;
|
||||||
private Map<String, String> env;
|
private Map<String, String> env;
|
||||||
|
|
||||||
public JdiConnector(JdiManagerImpl manager, Map<String, String> env) {
|
public JdiConnector(JdiManagerImpl manager, Map<String, String> env) {
|
||||||
@@ -166,7 +166,7 @@ public class JdiConnector {
|
|||||||
* TODO: The return type should be reflected from the method; however, none of the parameter
|
* TODO: The return type should be reflected from the method; however, none of the parameter
|
||||||
* collection routines currently use the return type, so just use ANY for now.
|
* collection routines currently use the return type, so just use ANY for now.
|
||||||
*/
|
*/
|
||||||
TargetObjectSchema schema = EnumerableTargetObjectSchema.ANY;
|
TraceObjectSchema schema = PrimitiveTraceObjectSchema.ANY;
|
||||||
RmiRemoteMethod method = new RmiRemoteMethod(rootSchema.getContext(), name, action, display,
|
RmiRemoteMethod method = new RmiRemoteMethod(rootSchema.getContext(), name, action, display,
|
||||||
description, schema, methods, m);
|
description, schema, methods, m);
|
||||||
remoteMethodRegistry.putMethod(name, method);
|
remoteMethodRegistry.putMethod(name, method);
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ import com.sun.jdi.request.*;
|
|||||||
|
|
||||||
import ghidra.app.plugin.core.debug.client.tracermi.*;
|
import ghidra.app.plugin.core.debug.client.tracermi.*;
|
||||||
import ghidra.app.plugin.core.debug.client.tracermi.RmiMethodRegistry.TraceMethod;
|
import ghidra.app.plugin.core.debug.client.tracermi.RmiMethodRegistry.TraceMethod;
|
||||||
import ghidra.dbg.target.TargetMethod.Param;
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressRange;
|
import ghidra.program.model.address.AddressRange;
|
||||||
import ghidra.rmi.trace.TraceRmi.MemoryState;
|
import ghidra.rmi.trace.TraceRmi.MemoryState;
|
||||||
|
import ghidra.trace.model.target.iface.TraceObjectMethod.Param;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
public class JdiMethods implements RmiMethods {
|
public class JdiMethods implements RmiMethods {
|
||||||
@@ -343,7 +343,7 @@ public class JdiMethods implements RmiMethods {
|
|||||||
name = "find") String targetClass) {
|
name = "find") String targetClass) {
|
||||||
return find_class(obj, targetClass);
|
return find_class(obj, targetClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TraceMethod(display = "Load class")
|
@TraceMethod(display = "Load class")
|
||||||
public boolean find_class(
|
public boolean find_class(
|
||||||
@Param(
|
@Param(
|
||||||
@@ -377,10 +377,12 @@ public class JdiMethods implements RmiMethods {
|
|||||||
|
|
||||||
@TraceMethod(display = "Refresh reference types")
|
@TraceMethod(display = "Refresh reference types")
|
||||||
public void refresh_canonical_reference_types(
|
public void refresh_canonical_reference_types(
|
||||||
@Param(schema = "CanonicalReferenceTypeContainer", name = "container") RmiTraceObject obj) {
|
@Param(
|
||||||
|
schema = "CanonicalReferenceTypeContainer",
|
||||||
|
name = "container") RmiTraceObject obj) {
|
||||||
refresh_reference_types(obj);
|
refresh_reference_types(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NB. Did not assign action="refresh" because this method is expensive. Assigning that action
|
* NB. Did not assign action="refresh" because this method is expensive. Assigning that action
|
||||||
* name will cause the UI to do it upon expanding the node, which we <em>do not</em> want.
|
* name will cause the UI to do it upon expanding the node, which we <em>do not</em> want.
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<context>
|
<context>
|
||||||
<schema name="Debugger" elementResync="NEVER" attributeResync="ALWAYS">
|
<schema name="Debugger" elementResync="NEVER" attributeResync="ALWAYS">
|
||||||
<interface name="Access" />
|
|
||||||
<interface name="Attacher" />
|
|
||||||
<interface name="EventScope" />
|
<interface name="EventScope" />
|
||||||
<interface name="Launcher" />
|
|
||||||
<interface name="ActiveScope" />
|
|
||||||
<interface name="FocusScope" />
|
<interface name="FocusScope" />
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
@@ -20,7 +16,6 @@
|
|||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute name="_event_process" schema="OBJECT" hidden="yes" />
|
<attribute name="_event_process" schema="OBJECT" hidden="yes" />
|
||||||
<attribute name="_event_thread" schema="OBJECT" hidden="yes" />
|
<attribute name="_event_thread" schema="OBJECT" hidden="yes" />
|
||||||
<attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" hidden="yes" />
|
|
||||||
<attribute name="_focus" schema="OBJECT" required="no" hidden="yes" />
|
<attribute name="_focus" schema="OBJECT" required="no" hidden="yes" />
|
||||||
<attribute name="_system" schema="OBJECT" hidden="no" />
|
<attribute name="_system" schema="OBJECT" hidden="no" />
|
||||||
<attribute name="Available" schema="AvailableContainer" fixed="yes" />
|
<attribute name="Available" schema="AvailableContainer" fixed="yes" />
|
||||||
@@ -73,9 +68,7 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="KernelConnector" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="KernelConnector" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Launcher" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" fixed="yes" hidden="yes" />
|
|
||||||
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
@@ -87,9 +80,7 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="ProcessAttachConnector" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="ProcessAttachConnector" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Launcher" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" fixed="yes" hidden="yes" />
|
|
||||||
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
@@ -101,9 +92,7 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="ProcessLaunchConnector" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="ProcessLaunchConnector" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Launcher" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" fixed="yes" hidden="yes" />
|
|
||||||
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
@@ -115,9 +104,7 @@
|
|||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="TraceOrDumpConnector" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="TraceOrDumpConnector" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Launcher" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" fixed="yes" hidden="yes" />
|
|
||||||
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
@@ -131,17 +118,8 @@
|
|||||||
<schema name="VirtualMachine" elementResync="NEVER" attributeResync="ONCE">
|
<schema name="VirtualMachine" elementResync="NEVER" attributeResync="ONCE">
|
||||||
<interface name="Process" />
|
<interface name="Process" />
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
<interface name="Access" />
|
|
||||||
<interface name="Activatable" />
|
<interface name="Activatable" />
|
||||||
<interface name="ExecutionStateful" />
|
<interface name="ExecutionStateful" />
|
||||||
<interface name="Interpreter" />
|
|
||||||
<interface name="Interruptible" />
|
|
||||||
<interface name="Deletable" />
|
|
||||||
<interface name="Detachable" />
|
|
||||||
<interface name="Killable" />
|
|
||||||
<interface name="Resumable" />
|
|
||||||
<interface name="Steppable" />
|
|
||||||
<interface name="Interruptible" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="_accessible" schema="BOOL" hidden="yes" />
|
<attribute name="_accessible" schema="BOOL" hidden="yes" />
|
||||||
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
@@ -168,7 +146,6 @@
|
|||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Available" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Available" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Attachable" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="_pid" schema="LONG" hidden="yes" required="yes" />
|
<attribute name="_pid" schema="LONG" hidden="yes" required="yes" />
|
||||||
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
@@ -236,16 +213,6 @@
|
|||||||
<interface name="Activatable" />
|
<interface name="Activatable" />
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
<interface name="ExecutionStateful" />
|
<interface name="ExecutionStateful" />
|
||||||
<interface name="Access" />
|
|
||||||
<interface name="Attacher" />
|
|
||||||
<interface name="Attachable" />
|
|
||||||
<!-- interface name="Launcher" / -->
|
|
||||||
<interface name="Deletable" />
|
|
||||||
<interface name="Detachable" />
|
|
||||||
<interface name="Killable" />
|
|
||||||
<interface name="Resumable" />
|
|
||||||
<interface name="Steppable" />
|
|
||||||
<interface name="Interruptible" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="_pid" schema="LONG" hidden="yes" />
|
<attribute name="_pid" schema="LONG" hidden="yes" />
|
||||||
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
@@ -258,8 +225,6 @@
|
|||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute name="_state" schema="EXECUTION_STATE" required="no" hidden="yes" />
|
<attribute name="_state" schema="EXECUTION_STATE" required="no" hidden="yes" />
|
||||||
<attribute name="_accessible" schema="BOOL" required="yes" hidden="yes" />
|
<attribute name="_accessible" schema="BOOL" required="yes" hidden="yes" />
|
||||||
<attribute name="_supported_attach_kinds" schema="SET_ATTACH_KIND" required="yes" hidden="yes" />
|
|
||||||
<attribute name="_supported_step_kinds" schema="SET_STEP_KIND" required="yes" fixed="yes" hidden="yes" />
|
|
||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Memory" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Memory" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
@@ -296,25 +261,8 @@
|
|||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="VOID" />
|
<attribute schema="VOID" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="DebugContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
|
||||||
<interface name="Aggregate" />
|
|
||||||
<element schema="OBJECT" />
|
|
||||||
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
|
||||||
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
|
||||||
<attribute name="_update_mode" schema="UPDATE_MODE" hidden="yes" />
|
|
||||||
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
|
||||||
<attribute name="_value" schema="ANY" hidden="yes" />
|
|
||||||
<attribute name="_type" schema="STRING" hidden="yes" />
|
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
|
||||||
<attribute name="Breakpoints" schema="BreakpointContainer" required="yes" fixed="no" />
|
|
||||||
<attribute schema="ANY" />
|
|
||||||
</schema>
|
|
||||||
<schema name="BreakpointContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="BreakpointContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="BreakpointLocationContainer" />
|
|
||||||
<interface name="BreakpointSpecContainer" />
|
|
||||||
<element schema="BreakpointSpec" />
|
<element schema="BreakpointSpec" />
|
||||||
<attribute name="_supported_breakpoint_kinds" schema="SET_BREAKPOINT_KIND" required="yes" hidden="yes" />
|
|
||||||
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
@@ -328,12 +276,9 @@
|
|||||||
<schema name="BreakpointSpec" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="BreakpointSpec" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="BreakpointSpec" />
|
<interface name="BreakpointSpec" />
|
||||||
<interface name="BreakpointLocation" />
|
<interface name="BreakpointLocation" />
|
||||||
<interface name="Deletable" />
|
|
||||||
<element schema="OBJECT" />
|
<element schema="OBJECT" />
|
||||||
<attribute name="_expression" schema="STRING" required="yes" hidden="yes" />
|
<attribute name="_expression" schema="STRING" required="yes" hidden="yes" />
|
||||||
<attribute name="_kinds" schema="SET_BREAKPOINT_KIND" required="yes" hidden="yes" />
|
<attribute name="_kinds" schema="STRING" required="yes" hidden="yes" />
|
||||||
<attribute name="_container" schema="BreakpointContainer" />
|
|
||||||
<attribute name="_affects" schema="LIST_OBJECT" hidden="yes" />
|
|
||||||
<attribute name="_spec" schema="BreakpointSpec" />
|
<attribute name="_spec" schema="BreakpointSpec" />
|
||||||
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
@@ -362,7 +307,6 @@
|
|||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Event" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Event" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Deletable" />
|
|
||||||
<element schema="OBJECT" />
|
<element schema="OBJECT" />
|
||||||
<attribute name="_enabled" schema="BOOL" required="yes" hidden="yes" />
|
<attribute name="_enabled" schema="BOOL" required="yes" hidden="yes" />
|
||||||
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
@@ -375,57 +319,12 @@
|
|||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="SymbolContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
|
||||||
<interface name="SymbolNamespace" />
|
|
||||||
<element schema="Symbol" />
|
|
||||||
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
|
||||||
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
|
||||||
<attribute name="_update_mode" schema="UPDATE_MODE" hidden="yes" />
|
|
||||||
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
|
||||||
<attribute name="_value" schema="ANY" hidden="yes" />
|
|
||||||
<attribute name="_type" schema="STRING" hidden="yes" />
|
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
|
||||||
<attribute schema="ANY" />
|
|
||||||
</schema>
|
|
||||||
<schema name="Symbol" elementResync="NEVER" attributeResync="NEVER">
|
|
||||||
<interface name="Symbol" />
|
|
||||||
<element schema="VOID" />
|
|
||||||
<attribute name="_namespace" schema="SymbolContainer" />
|
|
||||||
<attribute name="_data_type" schema="DATA_TYPE" fixed="yes" hidden="yes" />
|
|
||||||
<attribute name="_size" schema="LONG" fixed="yes" hidden="yes" />
|
|
||||||
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
|
||||||
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
|
||||||
<attribute name="_update_mode" schema="UPDATE_MODE" hidden="yes" />
|
|
||||||
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
|
||||||
<attribute name="_value" schema="ADDRESS" hidden="yes" />
|
|
||||||
<attribute name="_type" schema="STRING" hidden="yes" />
|
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
|
||||||
<attribute schema="VOID" />
|
|
||||||
</schema>
|
|
||||||
<schema name="RegisterContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="RegisterContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="RegisterContainer" />
|
<interface name="RegisterContainer" />
|
||||||
<interface name="RegisterBank" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="RegisterDescriptor" elementResync="NEVER" attributeResync="NEVER">
|
|
||||||
<interface name="Register" />
|
|
||||||
<element schema="VOID" />
|
|
||||||
<attribute name="_length" schema="INT" fixed="yes" hidden="yes" />
|
|
||||||
<attribute name="_container" schema="RegisterContainer" />
|
|
||||||
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
|
||||||
<attribute name="_display" schema="STRING" hidden="yes" />
|
|
||||||
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
|
||||||
<attribute name="_update_mode" schema="UPDATE_MODE" hidden="yes" />
|
|
||||||
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
|
||||||
<attribute name="_value" schema="ANY" required="yes" hidden="yes" />
|
|
||||||
<attribute name="_type" schema="STRING" hidden="yes" />
|
|
||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
|
||||||
<attribute schema="VOID" />
|
|
||||||
</schema>
|
|
||||||
<schema name="Stack" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Stack" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Stack" />
|
<interface name="Stack" />
|
||||||
<element schema="StackFrame" />
|
<element schema="StackFrame" />
|
||||||
@@ -553,17 +452,14 @@
|
|||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="CanonicalMethodContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="CanonicalMethodContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="SectionContainer" />
|
|
||||||
<element schema="Method" />
|
<element schema="Method" />
|
||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="MethodContainer" canonical="no" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="MethodContainer" canonical="no" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="SectionContainer" />
|
|
||||||
<element schema="Method" />
|
<element schema="Method" />
|
||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="MethodProxy" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="MethodProxy" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="SectionContainer" />
|
|
||||||
<element schema="Method" />
|
<element schema="Method" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Method" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Method" elementResync="NEVER" attributeResync="NEVER">
|
||||||
@@ -701,13 +597,13 @@
|
|||||||
<attribute name="Type" schema="Type" />
|
<attribute name="Type" schema="Type" />
|
||||||
<attribute schema="ANY" />
|
<attribute schema="ANY" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="ClassObjecReferenceContainer" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="ClassObjectReferenceContainer" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<element schema="ClassObjecReference" />
|
<element schema="ClassObjectReference" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="ClassObjecReferenceProxy" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="ClassObjectReferenceProxy" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<element schema="ClassObjecReference" />
|
<element schema="ClassObjectReference" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="ClassObjecReference" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="ClassObjectReference" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<element schema="ANY" />
|
<element schema="ANY" />
|
||||||
<attribute name="ReflectedType" schema="ReferenceTypeProxy" />
|
<attribute name="ReflectedType" schema="ReferenceTypeProxy" />
|
||||||
<attribute name="Relations" schema="ObjectRelations" required="no" fixed="yes" />
|
<attribute name="Relations" schema="ObjectRelations" required="no" fixed="yes" />
|
||||||
@@ -750,7 +646,6 @@
|
|||||||
<schema name="ThreadGroupReference" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="ThreadGroupReference" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
<interface name="ExecutionStateful" />
|
<interface name="ExecutionStateful" />
|
||||||
<interface name="Steppable" />
|
|
||||||
<element schema="ANY" />
|
<element schema="ANY" />
|
||||||
<attribute name="Parent" schema="ThreadGroupReferenceProxy" />
|
<attribute name="Parent" schema="ThreadGroupReferenceProxy" />
|
||||||
<attribute name="Relations" schema="ObjectRelations" required="no" fixed="yes" />
|
<attribute name="Relations" schema="ObjectRelations" required="no" fixed="yes" />
|
||||||
@@ -775,12 +670,8 @@
|
|||||||
<schema name="Thread" elementResync="NEVER" attributeResync="NEVER">
|
<schema name="Thread" elementResync="NEVER" attributeResync="NEVER">
|
||||||
<interface name="Thread" />
|
<interface name="Thread" />
|
||||||
<interface name="Aggregate" />
|
<interface name="Aggregate" />
|
||||||
<interface name="Access" />
|
|
||||||
<interface name="Activatable" />
|
<interface name="Activatable" />
|
||||||
<interface name="ExecutionStateful" />
|
<interface name="ExecutionStateful" />
|
||||||
<interface name="Resumable" />
|
|
||||||
<interface name="Steppable" />
|
|
||||||
<interface name="Interruptible" />
|
|
||||||
<element schema="VOID" />
|
<element schema="VOID" />
|
||||||
<attribute name="_tid" schema="INT" hidden="yes" />
|
<attribute name="_tid" schema="INT" hidden="yes" />
|
||||||
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
@@ -793,7 +684,6 @@
|
|||||||
<attribute name="_order" schema="INT" hidden="yes" />
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
<attribute name="_accessible" schema="BOOL" required="yes" hidden="yes" />
|
<attribute name="_accessible" schema="BOOL" required="yes" hidden="yes" />
|
||||||
<attribute name="_state" schema="EXECUTION_STATE" required="no" hidden="yes" />
|
<attribute name="_state" schema="EXECUTION_STATE" required="no" hidden="yes" />
|
||||||
<attribute name="_supported_step_kinds" schema="SET_STEP_KIND" required="yes" fixed="yes" hidden="yes" />
|
|
||||||
<attribute name="Stack" schema="Stack" required="yes" fixed="yes" />
|
<attribute name="Stack" schema="Stack" required="yes" fixed="yes" />
|
||||||
<attribute name="Id" schema="OBJECT" />
|
<attribute name="Id" schema="OBJECT" />
|
||||||
<attribute name="Name" schema="OBJECT" />
|
<attribute name="Name" schema="OBJECT" />
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -33,7 +33,6 @@ dependencies {
|
|||||||
testImplementation project(path: ':Generic', configuration: 'testArtifacts')
|
testImplementation project(path: ':Generic', configuration: 'testArtifacts')
|
||||||
testImplementation project(path: ':Debugger', configuration: 'testArtifacts')
|
testImplementation project(path: ':Debugger', configuration: 'testArtifacts')
|
||||||
testImplementation project(path: ':Framework-AsyncComm', configuration: 'testArtifacts')
|
testImplementation project(path: ':Framework-AsyncComm', configuration: 'testArtifacts')
|
||||||
testImplementation project(path: ':Framework-Debugging', configuration: 'testArtifacts')
|
|
||||||
testImplementation project(path: ':Framework-TraceModeling', configuration: 'testArtifacts')
|
testImplementation project(path: ':Framework-TraceModeling', configuration: 'testArtifacts')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ import org.jdom.JDOMException;
|
|||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
|
|
||||||
import ghidra.app.plugin.core.debug.service.tracermi.TraceRmiHandler;
|
import ghidra.app.plugin.core.debug.service.tracermi.TraceRmiHandler;
|
||||||
import ghidra.dbg.target.schema.*;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
import ghidra.rmi.trace.TraceRmi;
|
import ghidra.rmi.trace.TraceRmi;
|
||||||
@@ -36,6 +34,8 @@ import ghidra.rmi.trace.TraceRmi.*;
|
|||||||
import ghidra.rmi.trace.TraceRmi.Language;
|
import ghidra.rmi.trace.TraceRmi.Language;
|
||||||
import ghidra.rmi.trace.TraceRmi.Value.Builder;
|
import ghidra.rmi.trace.TraceRmi.Value.Builder;
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
|
import ghidra.trace.model.target.schema.*;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.Swing;
|
import ghidra.util.Swing;
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ public class RmiClient {
|
|||||||
private static RmiMethodRegistry methodRegistry;
|
private static RmiMethodRegistry methodRegistry;
|
||||||
private Deque<RequestResult> requests = new LinkedList<>();
|
private Deque<RequestResult> requests = new LinkedList<>();
|
||||||
|
|
||||||
public static TargetObjectSchema loadSchema(String resourceName, String rootName) {
|
public static TraceObjectSchema loadSchema(String resourceName, String rootName) {
|
||||||
XmlSchemaContext schemaContext;
|
XmlSchemaContext schemaContext;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -820,7 +820,7 @@ public class RmiClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TargetObjectSchema getSchema(String schema) {
|
public TraceObjectSchema getSchema(String schema) {
|
||||||
return schemaContext.getSchema(new SchemaName(schema));
|
return schemaContext.getSchema(new SchemaName(schema));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,10 +18,9 @@ package ghidra.app.plugin.core.debug.client.tracermi;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Parameter;
|
import java.lang.reflect.Parameter;
|
||||||
|
|
||||||
import ghidra.dbg.target.TargetMethod;
|
import ghidra.trace.model.target.iface.TraceObjectMethod.ParameterDescription;
|
||||||
import ghidra.dbg.target.TargetMethod.ParameterDescription;
|
import ghidra.trace.model.target.schema.*;
|
||||||
import ghidra.dbg.target.schema.*;
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
|
|
||||||
public class RmiRemoteMethod {
|
public class RmiRemoteMethod {
|
||||||
|
|
||||||
@@ -31,12 +30,12 @@ public class RmiRemoteMethod {
|
|||||||
private String display;
|
private String display;
|
||||||
private String description;
|
private String description;
|
||||||
private RmiRemoteMethodParameter[] params;
|
private RmiRemoteMethodParameter[] params;
|
||||||
private TargetObjectSchema schema;
|
private TraceObjectSchema schema;
|
||||||
private RmiMethods instance;
|
private RmiMethods instance;
|
||||||
private Method m;
|
private Method m;
|
||||||
|
|
||||||
public RmiRemoteMethod(SchemaContext schemaContext, String name, String action, String display,
|
public RmiRemoteMethod(SchemaContext schemaContext, String name, String action, String display,
|
||||||
String description, TargetObjectSchema schema, RmiMethods instance, Method m) {
|
String description, TraceObjectSchema schema, RmiMethods instance, Method m) {
|
||||||
this.schemaContext = schemaContext;
|
this.schemaContext = schemaContext;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.action = action;
|
this.action = action;
|
||||||
@@ -49,10 +48,10 @@ public class RmiRemoteMethod {
|
|||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (Parameter p : m.getParameters()) {
|
for (Parameter p : m.getParameters()) {
|
||||||
ParameterDescription<?> desc = TargetMethod.ParameterDescription.annotated(p);
|
ParameterDescription<?> desc = ParameterDescription.annotated(p);
|
||||||
TargetObjectSchema pschema;
|
TraceObjectSchema pschema;
|
||||||
if (desc.type != RmiTraceObject.class) {
|
if (desc.type != RmiTraceObject.class) {
|
||||||
pschema = EnumerableTargetObjectSchema.schemaForPrimitive(desc.type);
|
pschema = PrimitiveTraceObjectSchema.schemaForPrimitive(desc.type);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pschema = schemaContext.getSchema(new SchemaName(desc.schema));
|
pschema = schemaContext.getSchema(new SchemaName(desc.schema));
|
||||||
@@ -86,7 +85,7 @@ public class RmiRemoteMethod {
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TargetObjectSchema getSchema() {
|
public TraceObjectSchema getSchema() {
|
||||||
return schema;
|
return schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,19 +15,19 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.client.tracermi;
|
package ghidra.app.plugin.core.debug.client.tracermi;
|
||||||
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.rmi.trace.TraceRmi.*;
|
import ghidra.rmi.trace.TraceRmi.*;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||||
|
|
||||||
public class RmiRemoteMethodParameter {
|
public class RmiRemoteMethodParameter {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final TargetObjectSchema schema;
|
private final TraceObjectSchema schema;
|
||||||
private final boolean required;
|
private final boolean required;
|
||||||
private final Object defaultValue;
|
private final Object defaultValue;
|
||||||
private final String display;
|
private final String display;
|
||||||
private final String description;
|
private final String description;
|
||||||
|
|
||||||
public RmiRemoteMethodParameter(String name, TargetObjectSchema schema, boolean required,
|
public RmiRemoteMethodParameter(String name, TraceObjectSchema schema, boolean required,
|
||||||
Object defaultValue, String display, String description) {
|
Object defaultValue, String display, String description) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.schema = schema;
|
this.schema = schema;
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ import java.util.concurrent.locks.ReadWriteLock;
|
|||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
import ghidra.app.plugin.core.debug.client.tracermi.RmiClient.RequestResult;
|
import ghidra.app.plugin.core.debug.client.tracermi.RmiClient.RequestResult;
|
||||||
import ghidra.dbg.target.schema.SchemaContext;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.RegisterValue;
|
import ghidra.program.model.lang.RegisterValue;
|
||||||
import ghidra.rmi.trace.TraceRmi.*;
|
import ghidra.rmi.trace.TraceRmi.*;
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
|
import ghidra.trace.model.target.schema.SchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||||
import ghidra.util.LockHold;
|
import ghidra.util.LockHold;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
@@ -181,7 +181,7 @@ public class RmiTrace {
|
|||||||
RmiTraceObject parent = proxyObject(d.getParent());
|
RmiTraceObject parent = proxyObject(d.getParent());
|
||||||
Lifespan span = Lifespan.span(d.getSpan().getMin(), d.getSpan().getMax());
|
Lifespan span = Lifespan.span(d.getSpan().getMin(), d.getSpan().getMax());
|
||||||
Object value = client.argToObject(id, d.getValue());
|
Object value = client.argToObject(id, d.getValue());
|
||||||
TargetObjectSchema schema = client.getSchema(client.argToType(d.getValue()));
|
TraceObjectSchema schema = client.getSchema(client.argToType(d.getValue()));
|
||||||
result.add(new RmiTraceObjectValue(parent, span, d.getKey(), value, schema));
|
result.add(new RmiTraceObjectValue(parent, span, d.getKey(), value, schema));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.client.tracermi;
|
package ghidra.app.plugin.core.debug.client.tracermi;
|
||||||
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||||
|
|
||||||
public record RmiTraceObjectValue(RmiTraceObject parent, Lifespan span, String key, Object value,
|
public record RmiTraceObjectValue(RmiTraceObject parent, Lifespan span, String key, Object value,
|
||||||
TargetObjectSchema schema) {}
|
TraceObjectSchema schema) {}
|
||||||
|
|||||||
@@ -24,14 +24,13 @@ import javax.swing.JLabel;
|
|||||||
|
|
||||||
import ghidra.app.plugin.core.debug.gui.AbstractDebuggerParameterDialog;
|
import ghidra.app.plugin.core.debug.gui.AbstractDebuggerParameterDialog;
|
||||||
import ghidra.app.plugin.core.debug.service.tracermi.TraceRmiTarget.Missing;
|
import ghidra.app.plugin.core.debug.service.tracermi.TraceRmiTarget.Missing;
|
||||||
import ghidra.dbg.target.TargetObject;
|
|
||||||
import ghidra.dbg.target.schema.SchemaContext;
|
|
||||||
import ghidra.debug.api.ValStr;
|
import ghidra.debug.api.ValStr;
|
||||||
import ghidra.debug.api.tracermi.RemoteParameter;
|
import ghidra.debug.api.tracermi.RemoteParameter;
|
||||||
import ghidra.framework.options.SaveState;
|
import ghidra.framework.options.SaveState;
|
||||||
import ghidra.framework.plugintool.AutoConfigState.ConfigStateField;
|
import ghidra.framework.plugintool.AutoConfigState.ConfigStateField;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
|
import ghidra.trace.model.target.schema.SchemaContext;
|
||||||
|
|
||||||
public class RemoteMethodInvocationDialog extends AbstractDebuggerParameterDialog<RemoteParameter> {
|
public class RemoteMethodInvocationDialog extends AbstractDebuggerParameterDialog<RemoteParameter> {
|
||||||
|
|
||||||
@@ -84,11 +83,7 @@ public class RemoteMethodInvocationDialog extends AbstractDebuggerParameterDialo
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Class<?> parameterType(RemoteParameter parameter) {
|
protected Class<?> parameterType(RemoteParameter parameter) {
|
||||||
Class<?> type = ctx.getSchema(parameter.type()).getType();
|
return ctx.getSchema(parameter.type()).getType();
|
||||||
if (TargetObject.class.isAssignableFrom(type)) {
|
|
||||||
return TraceObject.class;
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import ghidra.app.plugin.core.terminal.TerminalListener;
|
|||||||
import ghidra.app.services.*;
|
import ghidra.app.services.*;
|
||||||
import ghidra.app.services.DebuggerTraceManagerService.ActivationCause;
|
import ghidra.app.services.DebuggerTraceManagerService.ActivationCause;
|
||||||
import ghidra.async.AsyncUtils;
|
import ghidra.async.AsyncUtils;
|
||||||
import ghidra.dbg.util.ShellUtils;
|
|
||||||
import ghidra.debug.api.ValStr;
|
import ghidra.debug.api.ValStr;
|
||||||
import ghidra.debug.api.action.AutoMapSpec;
|
import ghidra.debug.api.action.AutoMapSpec;
|
||||||
import ghidra.debug.api.modules.DebuggerMissingProgramActionContext;
|
import ghidra.debug.api.modules.DebuggerMissingProgramActionContext;
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ import javax.swing.Icon;
|
|||||||
|
|
||||||
import generic.theme.GIcon;
|
import generic.theme.GIcon;
|
||||||
import generic.theme.Gui;
|
import generic.theme.Gui;
|
||||||
import ghidra.dbg.util.ShellUtils;
|
|
||||||
import ghidra.debug.api.ValStr;
|
import ghidra.debug.api.ValStr;
|
||||||
import ghidra.debug.api.tracermi.LaunchParameter;
|
import ghidra.debug.api.tracermi.LaunchParameter;
|
||||||
import ghidra.framework.Application;
|
import ghidra.framework.Application;
|
||||||
import ghidra.framework.plugintool.AutoConfigState.PathIsDir;
|
import ghidra.framework.plugintool.AutoConfigState.PathIsDir;
|
||||||
import ghidra.framework.plugintool.AutoConfigState.PathIsFile;
|
import ghidra.framework.plugintool.AutoConfigState.PathIsFile;
|
||||||
|
import ghidra.pty.ShellUtils;
|
||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -17,10 +17,10 @@ package ghidra.app.plugin.core.debug.service.tracermi;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.debug.api.target.ActionName;
|
import ghidra.debug.api.target.ActionName;
|
||||||
import ghidra.debug.api.tracermi.*;
|
import ghidra.debug.api.tracermi.*;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
|
|
||||||
public record RecordRemoteMethod(TraceRmiHandler handler, String name, ActionName action,
|
public record RecordRemoteMethod(TraceRmiHandler handler, String name, ActionName action,
|
||||||
String display, String description, Map<String, RemoteParameter> parameters,
|
String display, String description, Map<String, RemoteParameter> parameters,
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -15,10 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.service.tracermi;
|
package ghidra.app.plugin.core.debug.service.tracermi;
|
||||||
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.debug.api.tracermi.RemoteParameter;
|
import ghidra.debug.api.tracermi.RemoteParameter;
|
||||||
import ghidra.program.model.address.AddressOverflowException;
|
import ghidra.program.model.address.AddressOverflowException;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
|
|
||||||
public record RecordRemoteParameter(TraceRmiHandler handler, String name, SchemaName type,
|
public record RecordRemoteParameter(TraceRmiHandler handler, String name, SchemaName type,
|
||||||
boolean required, ValueSupplier defaultValue, String display, String description)
|
boolean required, ValueSupplier defaultValue, String display, String description)
|
||||||
|
|||||||
@@ -35,10 +35,6 @@ import ghidra.app.plugin.core.debug.disassemble.DebuggerDisassemblerPlugin;
|
|||||||
import ghidra.app.plugin.core.debug.disassemble.TraceDisassembleCommand;
|
import ghidra.app.plugin.core.debug.disassemble.TraceDisassembleCommand;
|
||||||
import ghidra.app.services.DebuggerControlService;
|
import ghidra.app.services.DebuggerControlService;
|
||||||
import ghidra.app.services.DebuggerTraceManagerService;
|
import ghidra.app.services.DebuggerTraceManagerService;
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
|
||||||
import ghidra.dbg.util.PathPattern;
|
|
||||||
import ghidra.dbg.util.PathUtils;
|
|
||||||
import ghidra.debug.api.progress.CloseableTaskMonitor;
|
import ghidra.debug.api.progress.CloseableTaskMonitor;
|
||||||
import ghidra.debug.api.target.ActionName;
|
import ghidra.debug.api.target.ActionName;
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
@@ -60,6 +56,9 @@ import ghidra.trace.model.guest.TracePlatform;
|
|||||||
import ghidra.trace.model.memory.*;
|
import ghidra.trace.model.memory.*;
|
||||||
import ghidra.trace.model.target.*;
|
import ghidra.trace.model.target.*;
|
||||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||||
|
import ghidra.trace.model.target.path.*;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
|
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||||
import ghidra.trace.model.time.TraceSnapshot;
|
import ghidra.trace.model.time.TraceSnapshot;
|
||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
@@ -652,12 +651,12 @@ public class TraceRmiHandler extends AbstractTraceRmiConnection {
|
|||||||
.getCompilerSpecByID(new CompilerSpecID(compiler.getId()));
|
.getCompilerSpecByID(new CompilerSpecID(compiler.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static TraceObjectKeyPath toKeyPath(ObjPath path) {
|
protected static KeyPath toKeyPath(ObjPath path) {
|
||||||
return TraceObjectKeyPath.parse(path.getPath());
|
return KeyPath.parse(path.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static PathPattern toPathPattern(ObjPath path) {
|
protected static PathPattern toPathPattern(ObjPath path) {
|
||||||
return new PathPattern(PathUtils.parse(path.getPath()));
|
return PathFilter.parse(path.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static Lifespan toLifespan(Span span) {
|
protected static Lifespan toLifespan(Span span) {
|
||||||
@@ -686,7 +685,7 @@ public class TraceRmiHandler extends AbstractTraceRmiConnection {
|
|||||||
return ObjSpec.newBuilder().setId(object.getKey()).build();
|
return ObjSpec.newBuilder().setId(object.getKey()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static ObjPath makeObjPath(TraceObjectKeyPath path) {
|
protected static ObjPath makeObjPath(KeyPath path) {
|
||||||
return ObjPath.newBuilder().setPath(path.toString()).build();
|
return ObjPath.newBuilder().setPath(path.toString()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,13 +30,6 @@ import ghidra.app.plugin.core.debug.service.target.AbstractTarget;
|
|||||||
import ghidra.app.services.DebuggerConsoleService;
|
import ghidra.app.services.DebuggerConsoleService;
|
||||||
import ghidra.app.services.DebuggerTraceManagerService;
|
import ghidra.app.services.DebuggerTraceManagerService;
|
||||||
import ghidra.async.*;
|
import ghidra.async.*;
|
||||||
import ghidra.dbg.target.*;
|
|
||||||
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
|
||||||
import ghidra.dbg.target.schema.*;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.dbg.util.PathMatcher;
|
|
||||||
import ghidra.dbg.util.PathPredicates;
|
|
||||||
import ghidra.dbg.util.PathPredicates.Align;
|
|
||||||
import ghidra.debug.api.ValStr;
|
import ghidra.debug.api.ValStr;
|
||||||
import ghidra.debug.api.model.DebuggerObjectActionContext;
|
import ghidra.debug.api.model.DebuggerObjectActionContext;
|
||||||
import ghidra.debug.api.model.DebuggerSingleObjectPathActionContext;
|
import ghidra.debug.api.model.DebuggerSingleObjectPathActionContext;
|
||||||
@@ -48,17 +41,20 @@ import ghidra.pcode.utils.Utils;
|
|||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
import ghidra.program.model.lang.RegisterValue;
|
import ghidra.program.model.lang.RegisterValue;
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.*;
|
||||||
import ghidra.trace.model.Trace;
|
|
||||||
import ghidra.trace.model.breakpoint.*;
|
import ghidra.trace.model.breakpoint.*;
|
||||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet;
|
import ghidra.trace.model.breakpoint.TraceBreakpointKind.TraceBreakpointKindSet;
|
||||||
import ghidra.trace.model.guest.TracePlatform;
|
import ghidra.trace.model.guest.TracePlatform;
|
||||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
import ghidra.trace.model.memory.*;
|
||||||
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
|
||||||
import ghidra.trace.model.stack.*;
|
import ghidra.trace.model.stack.*;
|
||||||
import ghidra.trace.model.target.*;
|
import ghidra.trace.model.target.*;
|
||||||
import ghidra.trace.model.thread.TraceObjectThread;
|
import ghidra.trace.model.target.iface.*;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.target.info.TraceObjectInterfaceUtils;
|
||||||
|
import ghidra.trace.model.target.path.*;
|
||||||
|
import ghidra.trace.model.target.path.PathFilter.Align;
|
||||||
|
import ghidra.trace.model.target.schema.*;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
|
import ghidra.trace.model.thread.*;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
@@ -110,16 +106,16 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TargetExecutionState getThreadExecutionState(TraceThread thread) {
|
public TraceExecutionState getThreadExecutionState(TraceThread thread) {
|
||||||
if (!(thread instanceof TraceObjectThread tot)) {
|
if (!(thread instanceof TraceObjectThread tot)) {
|
||||||
Msg.error(this, "Non-object thread with Trace RMI!");
|
Msg.error(this, "Non-object thread with Trace RMI!");
|
||||||
return TargetExecutionState.ALIVE;
|
return TraceExecutionState.ALIVE;
|
||||||
}
|
}
|
||||||
return tot.getObject().getExecutionState(getSnap());
|
return tot.getObject().getExecutionState(getSnap());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TraceThread getThreadForSuccessor(TraceObjectKeyPath path) {
|
public TraceThread getThreadForSuccessor(KeyPath path) {
|
||||||
TraceObject object = trace.getObjectManager().getObjectByCanonicalPath(path);
|
TraceObject object = trace.getObjectManager().getObjectByCanonicalPath(path);
|
||||||
if (object == null) {
|
if (object == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -130,7 +126,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TraceStackFrame getStackFrameForSuccessor(TraceObjectKeyPath path) {
|
public TraceStackFrame getStackFrameForSuccessor(KeyPath path) {
|
||||||
TraceObject object = trace.getObjectManager().getObjectByCanonicalPath(path);
|
TraceObject object = trace.getObjectManager().getObjectByCanonicalPath(path);
|
||||||
if (object == null) {
|
if (object == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -203,15 +199,15 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
TraceObjectValue attrEnabled =
|
TraceObjectValue attrEnabled =
|
||||||
object.getAttribute(getSnap(), TargetTogglable.ENABLED_ATTRIBUTE_NAME);
|
object.getAttribute(getSnap(), TraceObjectTogglable.KEY_ENABLED);
|
||||||
boolean enabled = attrEnabled != null && attrEnabled.getValue() instanceof Boolean b && b;
|
boolean enabled = attrEnabled != null && attrEnabled.getValue() instanceof Boolean b && b;
|
||||||
return !enabled;
|
return !enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object findArgumentForSchema(ActionName action, ActionContext context,
|
protected Object findArgumentForSchema(ActionName action, ActionContext context,
|
||||||
TargetObjectSchema schema, boolean allowContextObject, boolean allowCoordsObject,
|
TraceObjectSchema schema, boolean allowContextObject, boolean allowCoordsObject,
|
||||||
boolean allowSuitableObject) {
|
boolean allowSuitableObject) {
|
||||||
if (schema instanceof EnumerableTargetObjectSchema prim) {
|
if (schema instanceof PrimitiveTraceObjectSchema prim) {
|
||||||
return switch (prim) {
|
return switch (prim) {
|
||||||
case OBJECT -> findObject(context, allowContextObject, allowCoordsObject);
|
case OBJECT -> findObject(context, allowContextObject, allowCoordsObject);
|
||||||
case ADDRESS -> findAddress(context);
|
case ADDRESS -> findAddress(context);
|
||||||
@@ -225,9 +221,9 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (allowSuitableObject) {
|
if (allowSuitableObject) {
|
||||||
return object.querySuitableSchema(schema);
|
return object.findSuitableSchema(schema);
|
||||||
}
|
}
|
||||||
if (object.getTargetSchema() == schema) {
|
if (object.getSchema() == schema) {
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -246,7 +242,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
Msg.trace(this, "No root schema, yet: " + trace);
|
Msg.trace(this, "No root schema, yet: " + trace);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
TargetObjectSchema schema = ctx.getSchemaOrNull(type);
|
TraceObjectSchema schema = ctx.getSchemaOrNull(type);
|
||||||
if (schema == null) {
|
if (schema == null) {
|
||||||
Msg.error(this, "Schema " + type + " not in trace! " + trace);
|
Msg.error(this, "Schema " + type + " not in trace! " + trace);
|
||||||
return null;
|
return null;
|
||||||
@@ -275,19 +271,19 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TargetExecutionState getStateOf(TraceObject object) {
|
private TraceExecutionState getStateOf(TraceObject object) {
|
||||||
try {
|
try {
|
||||||
return object.getExecutionState(getSnap());
|
return object.getExecutionState(getSnap());
|
||||||
}
|
}
|
||||||
catch (NoSuchElementException e) {
|
catch (NoSuchElementException e) {
|
||||||
return TargetExecutionState.TERMINATED;
|
return TraceExecutionState.TERMINATED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean whenState(TraceObject object,
|
private boolean whenState(TraceObject object,
|
||||||
Predicate<TargetExecutionState> predicate) {
|
Predicate<TraceExecutionState> predicate) {
|
||||||
try {
|
try {
|
||||||
TargetExecutionState state = getStateOf(object);
|
TraceExecutionState state = getStateOf(object);
|
||||||
return state == null || predicate.test(state);
|
return state == null || predicate.test(state);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
@@ -300,7 +296,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
long score = 0;
|
long score = 0;
|
||||||
for (Object o : args.values()) {
|
for (Object o : args.values()) {
|
||||||
if (o instanceof TraceObject obj) {
|
if (o instanceof TraceObject obj) {
|
||||||
score += obj.getCanonicalPath().getKeyList().size();
|
score += obj.getCanonicalPath().size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return score;
|
return score;
|
||||||
@@ -315,7 +311,8 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
RemoteParameter firstParam = method.parameters()
|
RemoteParameter firstParam = method.parameters()
|
||||||
.values()
|
.values()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(p -> TargetObject.class.isAssignableFrom(ctx.getSchema(p.type()).getType()))
|
.filter(
|
||||||
|
p -> TraceObjectInterfaceUtils.isTraceObject(ctx.getSchema(p.type()).getType()))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
if (firstParam == null) {
|
if (firstParam == null) {
|
||||||
@@ -405,7 +402,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
.values()
|
.values()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(p -> {
|
.filter(p -> {
|
||||||
TargetObjectSchema schema = ctx.getSchemaOrNull(p.type());
|
TraceObjectSchema schema = ctx.getSchemaOrNull(p.type());
|
||||||
if (schema == null) {
|
if (schema == null) {
|
||||||
Msg.error(this,
|
Msg.error(this,
|
||||||
"Method " + method + " refers to invalid schema name: " + p.type());
|
"Method " + method + " refers to invalid schema name: " + p.type());
|
||||||
@@ -489,22 +486,22 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSupportsFocus() {
|
public boolean isSupportsFocus() {
|
||||||
TargetObjectSchema schema = trace.getObjectManager().getRootSchema();
|
TraceObjectSchema schema = trace.getObjectManager().getRootSchema();
|
||||||
if (schema == null) {
|
if (schema == null) {
|
||||||
Msg.trace(this, "Checked for focus support before root schema is available");
|
Msg.trace(this, "Checked for focus support before root schema is available");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return schema
|
return schema
|
||||||
.getInterfaces()
|
.getInterfaces()
|
||||||
.contains(TargetFocusScope.class) &&
|
.contains(TraceObjectFocusScope.class) &&
|
||||||
!connection.getMethods().getByAction(ActionName.ACTIVATE).isEmpty();
|
!connection.getMethods().getByAction(ActionName.ACTIVATE).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TraceObjectKeyPath getFocus() {
|
public KeyPath getFocus() {
|
||||||
TraceObjectValue focusVal = trace.getObjectManager()
|
TraceObjectValue focusVal = trace.getObjectManager()
|
||||||
.getRootObject()
|
.getRootObject()
|
||||||
.getAttribute(getSnap(), TargetFocusScope.FOCUS_ATTRIBUTE_NAME);
|
.getAttribute(getSnap(), TraceObjectFocusScope.KEY_FOCUS);
|
||||||
if (focusVal == null || !focusVal.isObject()) {
|
if (focusVal == null || !focusVal.isObject()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -552,17 +549,17 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
|
|
||||||
protected static boolean typeMatches(RemoteMethod method, RemoteParameter param,
|
protected static boolean typeMatches(RemoteMethod method, RemoteParameter param,
|
||||||
SchemaContext ctx, Class<?> type) {
|
SchemaContext ctx, Class<?> type) {
|
||||||
TargetObjectSchema sch = ctx.getSchemaOrNull(param.type());
|
TraceObjectSchema sch = ctx.getSchemaOrNull(param.type());
|
||||||
if (sch == null) {
|
if (sch == null) {
|
||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
"The parameter '%s' of method '%s' refers to a non-existent schema '%s'"
|
"The parameter '%s' of method '%s' refers to a non-existent schema '%s'"
|
||||||
.formatted(param.name(), method.name(), param.type()));
|
.formatted(param.name(), method.name(), param.type()));
|
||||||
}
|
}
|
||||||
if (type == TargetObject.class) {
|
if (type == TraceObject.class) {
|
||||||
// The method cannot impose any further restriction. It must accept any object.
|
// The method cannot impose any further restriction. It must accept any object.
|
||||||
return sch == EnumerableTargetObjectSchema.OBJECT;
|
return sch == PrimitiveTraceObjectSchema.OBJECT;
|
||||||
}
|
}
|
||||||
else if (TargetObject.class.isAssignableFrom(type)) {
|
else if (TraceObjectInterface.class.isAssignableFrom(type)) {
|
||||||
return sch.getInterfaces().contains(type);
|
return sch.getInterfaces().contains(type);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -651,14 +648,13 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
return matchers(hasFocusTime, hasFocusSnap, hasFocus);
|
return matchers(hasFocusTime, hasFocusSnap, hasFocus);
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<ActivateMatcher> makeBySpecificity(TargetObjectSchema rootSchema,
|
static List<ActivateMatcher> makeBySpecificity(TraceObjectSchema rootSchema,
|
||||||
TraceObjectKeyPath path) {
|
KeyPath path) {
|
||||||
List<ActivateMatcher> result = new ArrayList<>();
|
List<ActivateMatcher> result = new ArrayList<>();
|
||||||
List<String> keyList = path.getKeyList();
|
result.addAll(makeAllFor((path.size() + 1) * 3,
|
||||||
result.addAll(makeAllFor((keyList.size() + 1) * 3,
|
new TypeParamSpec("focus", TraceObject.class)));
|
||||||
new TypeParamSpec("focus", TargetObject.class)));
|
List<TraceObjectSchema> schemas = rootSchema.getSuccessorSchemas(path);
|
||||||
List<TargetObjectSchema> schemas = rootSchema.getSuccessorSchemas(keyList);
|
for (int i = path.size(); i > 0; i--) { // Inclusive on both ends
|
||||||
for (int i = keyList.size(); i > 0; i--) { // Inclusive on both ends
|
|
||||||
result.addAll(
|
result.addAll(
|
||||||
makeAllFor(i * 3, new SchemaParamSpec("focus", schemas.get(i).getName())));
|
makeAllFor(i * 3, new SchemaParamSpec("focus", schemas.get(i).getName())));
|
||||||
}
|
}
|
||||||
@@ -675,7 +671,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
|
|
||||||
record ReadMemMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
record ReadMemMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||||
static final ReadMemMatcher HAS_PROC_RANGE = new ReadMemMatcher(2, List.of(
|
static final ReadMemMatcher HAS_PROC_RANGE = new ReadMemMatcher(2, List.of(
|
||||||
new TypeParamSpec("process", TargetProcess.class),
|
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||||
new TypeParamSpec("range", AddressRange.class)));
|
new TypeParamSpec("range", AddressRange.class)));
|
||||||
static final ReadMemMatcher HAS_RANGE = new ReadMemMatcher(1, List.of(
|
static final ReadMemMatcher HAS_RANGE = new ReadMemMatcher(1, List.of(
|
||||||
new TypeParamSpec("range", AddressRange.class)));
|
new TypeParamSpec("range", AddressRange.class)));
|
||||||
@@ -684,7 +680,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
|
|
||||||
record WriteMemMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
record WriteMemMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||||
static final WriteMemMatcher HAS_PROC_START_DATA = new WriteMemMatcher(2, List.of(
|
static final WriteMemMatcher HAS_PROC_START_DATA = new WriteMemMatcher(2, List.of(
|
||||||
new TypeParamSpec("process", TargetProcess.class),
|
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||||
new TypeParamSpec("start", Address.class),
|
new TypeParamSpec("start", Address.class),
|
||||||
new TypeParamSpec("data", byte[].class)));
|
new TypeParamSpec("data", byte[].class)));
|
||||||
static final WriteMemMatcher HAS_START_DATA = new WriteMemMatcher(1, List.of(
|
static final WriteMemMatcher HAS_START_DATA = new WriteMemMatcher(1, List.of(
|
||||||
@@ -695,45 +691,43 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
|
|
||||||
record ReadRegsMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
record ReadRegsMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||||
static final ReadRegsMatcher HAS_CONTAINER = new ReadRegsMatcher(3, List.of(
|
static final ReadRegsMatcher HAS_CONTAINER = new ReadRegsMatcher(3, List.of(
|
||||||
new TypeParamSpec("container", TargetRegisterContainer.class)));
|
new TypeParamSpec("container", TraceObjectRegisterContainer.class)));
|
||||||
static final ReadRegsMatcher HAS_BANK = new ReadRegsMatcher(2, List.of(
|
|
||||||
new TypeParamSpec("bank", TargetRegisterBank.class)));
|
|
||||||
static final ReadRegsMatcher HAS_REGISTER = new ReadRegsMatcher(1, List.of(
|
static final ReadRegsMatcher HAS_REGISTER = new ReadRegsMatcher(1, List.of(
|
||||||
new TypeParamSpec("register", TargetRegister.class)));
|
new TypeParamSpec("register", TraceObjectRegister.class)));
|
||||||
static final List<ReadRegsMatcher> ALL = matchers(HAS_CONTAINER, HAS_BANK, HAS_REGISTER);
|
static final List<ReadRegsMatcher> ALL = matchers(HAS_CONTAINER, HAS_REGISTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
record WriteRegMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
record WriteRegMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||||
static final WriteRegMatcher HAS_FRAME_NAME_VALUE = new WriteRegMatcher(3, List.of(
|
static final WriteRegMatcher HAS_FRAME_NAME_VALUE = new WriteRegMatcher(3, List.of(
|
||||||
new TypeParamSpec("frame", TargetStackFrame.class),
|
new TypeParamSpec("frame", TraceObjectStackFrame.class),
|
||||||
new TypeParamSpec("name", String.class),
|
new TypeParamSpec("name", String.class),
|
||||||
new TypeParamSpec("value", byte[].class)));
|
new TypeParamSpec("value", byte[].class)));
|
||||||
static final WriteRegMatcher HAS_THREAD_NAME_VALUE = new WriteRegMatcher(2, List.of(
|
static final WriteRegMatcher HAS_THREAD_NAME_VALUE = new WriteRegMatcher(2, List.of(
|
||||||
new TypeParamSpec("thread", TargetThread.class),
|
new TypeParamSpec("thread", TraceObjectThread.class),
|
||||||
new TypeParamSpec("name", String.class),
|
new TypeParamSpec("name", String.class),
|
||||||
new TypeParamSpec("value", byte[].class)));
|
new TypeParamSpec("value", byte[].class)));
|
||||||
static final WriteRegMatcher HAS_REG_VALUE = new WriteRegMatcher(1, List.of(
|
static final WriteRegMatcher HAS_REG_VALUE = new WriteRegMatcher(1, List.of(
|
||||||
new TypeParamSpec("register", TargetRegister.class),
|
new TypeParamSpec("register", TraceObjectRegister.class),
|
||||||
new TypeParamSpec("value", byte[].class)));
|
new TypeParamSpec("value", byte[].class)));
|
||||||
static final List<WriteRegMatcher> ALL = matchers(HAS_FRAME_NAME_VALUE, HAS_REG_VALUE);
|
static final List<WriteRegMatcher> ALL = matchers(HAS_FRAME_NAME_VALUE, HAS_REG_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
record BreakExecMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
record BreakExecMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||||
static final BreakExecMatcher HAS_PROC_ADDR_COND_CMDS = new BreakExecMatcher(8, List.of(
|
static final BreakExecMatcher HAS_PROC_ADDR_COND_CMDS = new BreakExecMatcher(8, List.of(
|
||||||
new TypeParamSpec("process", TargetProcess.class),
|
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||||
new TypeParamSpec("address", Address.class),
|
new TypeParamSpec("address", Address.class),
|
||||||
new NameParamSpec("condition", String.class),
|
new NameParamSpec("condition", String.class),
|
||||||
new NameParamSpec("commands", String.class)));
|
new NameParamSpec("commands", String.class)));
|
||||||
static final BreakExecMatcher HAS_PROC_ADDR_COND = new BreakExecMatcher(7, List.of(
|
static final BreakExecMatcher HAS_PROC_ADDR_COND = new BreakExecMatcher(7, List.of(
|
||||||
new TypeParamSpec("process", TargetProcess.class),
|
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||||
new TypeParamSpec("address", Address.class),
|
new TypeParamSpec("address", Address.class),
|
||||||
new NameParamSpec("condition", String.class)));
|
new NameParamSpec("condition", String.class)));
|
||||||
static final BreakExecMatcher HAS_PROC_ADDR_CMDS = new BreakExecMatcher(6, List.of(
|
static final BreakExecMatcher HAS_PROC_ADDR_CMDS = new BreakExecMatcher(6, List.of(
|
||||||
new TypeParamSpec("process", TargetProcess.class),
|
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||||
new TypeParamSpec("address", Address.class),
|
new TypeParamSpec("address", Address.class),
|
||||||
new NameParamSpec("commands", String.class)));
|
new NameParamSpec("commands", String.class)));
|
||||||
static final BreakExecMatcher HAS_PROC_ADDR = new BreakExecMatcher(5, List.of(
|
static final BreakExecMatcher HAS_PROC_ADDR = new BreakExecMatcher(5, List.of(
|
||||||
new TypeParamSpec("process", TargetProcess.class),
|
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||||
new TypeParamSpec("address", Address.class)));
|
new TypeParamSpec("address", Address.class)));
|
||||||
static final BreakExecMatcher HAS_ADDR_COND_CMDS = new BreakExecMatcher(4, List.of(
|
static final BreakExecMatcher HAS_ADDR_COND_CMDS = new BreakExecMatcher(4, List.of(
|
||||||
new TypeParamSpec("address", Address.class),
|
new TypeParamSpec("address", Address.class),
|
||||||
@@ -755,20 +749,20 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
// TODO: Probably need a better way to deal with optional requirements
|
// TODO: Probably need a better way to deal with optional requirements
|
||||||
record BreakAccMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
record BreakAccMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||||
static final BreakAccMatcher HAS_PROC_RNG_COND_CMDS = new BreakAccMatcher(8, List.of(
|
static final BreakAccMatcher HAS_PROC_RNG_COND_CMDS = new BreakAccMatcher(8, List.of(
|
||||||
new TypeParamSpec("process", TargetProcess.class),
|
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||||
new TypeParamSpec("range", AddressRange.class),
|
new TypeParamSpec("range", AddressRange.class),
|
||||||
new NameParamSpec("condition", String.class),
|
new NameParamSpec("condition", String.class),
|
||||||
new NameParamSpec("commands", String.class)));
|
new NameParamSpec("commands", String.class)));
|
||||||
static final BreakAccMatcher HAS_PROC_RNG_COND = new BreakAccMatcher(7, List.of(
|
static final BreakAccMatcher HAS_PROC_RNG_COND = new BreakAccMatcher(7, List.of(
|
||||||
new TypeParamSpec("process", TargetProcess.class),
|
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||||
new TypeParamSpec("range", AddressRange.class),
|
new TypeParamSpec("range", AddressRange.class),
|
||||||
new NameParamSpec("condition", String.class)));
|
new NameParamSpec("condition", String.class)));
|
||||||
static final BreakAccMatcher HAS_PROC_RNG_CMDS = new BreakAccMatcher(6, List.of(
|
static final BreakAccMatcher HAS_PROC_RNG_CMDS = new BreakAccMatcher(6, List.of(
|
||||||
new TypeParamSpec("process", TargetProcess.class),
|
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||||
new TypeParamSpec("range", AddressRange.class),
|
new TypeParamSpec("range", AddressRange.class),
|
||||||
new NameParamSpec("commands", String.class)));
|
new NameParamSpec("commands", String.class)));
|
||||||
static final BreakAccMatcher HAS_PROC_RNG = new BreakAccMatcher(5, List.of(
|
static final BreakAccMatcher HAS_PROC_RNG = new BreakAccMatcher(5, List.of(
|
||||||
new TypeParamSpec("process", TargetProcess.class),
|
new TypeParamSpec("process", TraceObjectProcess.class),
|
||||||
new TypeParamSpec("range", AddressRange.class)));
|
new TypeParamSpec("range", AddressRange.class)));
|
||||||
static final BreakAccMatcher HAS_RNG_COND_CMDS = new BreakAccMatcher(4, List.of(
|
static final BreakAccMatcher HAS_RNG_COND_CMDS = new BreakAccMatcher(4, List.of(
|
||||||
new TypeParamSpec("range", AddressRange.class),
|
new TypeParamSpec("range", AddressRange.class),
|
||||||
@@ -789,19 +783,19 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
|
|
||||||
record DelBreakMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
record DelBreakMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||||
static final DelBreakMatcher HAS_LOC = new DelBreakMatcher(2, List.of(
|
static final DelBreakMatcher HAS_LOC = new DelBreakMatcher(2, List.of(
|
||||||
new TypeParamSpec("location", TargetBreakpointLocation.class)));
|
new TypeParamSpec("location", TraceObjectBreakpointLocation.class)));
|
||||||
static final DelBreakMatcher HAS_SPEC = new DelBreakMatcher(1, List.of(
|
static final DelBreakMatcher HAS_SPEC = new DelBreakMatcher(1, List.of(
|
||||||
new TypeParamSpec("specification", TargetBreakpointSpec.class)));
|
new TypeParamSpec("specification", TraceObjectBreakpointSpec.class)));
|
||||||
static final List<DelBreakMatcher> ALL = matchers(HAS_LOC, HAS_SPEC);
|
static final List<DelBreakMatcher> ALL = matchers(HAS_LOC, HAS_SPEC);
|
||||||
static final List<DelBreakMatcher> SPEC = matchers(HAS_SPEC);
|
static final List<DelBreakMatcher> SPEC = matchers(HAS_SPEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
record ToggleBreakMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
record ToggleBreakMatcher(int score, List<ParamSpec> spec) implements MethodMatcher {
|
||||||
static final ToggleBreakMatcher HAS_LOC = new ToggleBreakMatcher(2, List.of(
|
static final ToggleBreakMatcher HAS_LOC = new ToggleBreakMatcher(2, List.of(
|
||||||
new TypeParamSpec("location", TargetBreakpointLocation.class),
|
new TypeParamSpec("location", TraceObjectBreakpointLocation.class),
|
||||||
new TypeParamSpec("enabled", Boolean.class)));
|
new TypeParamSpec("enabled", Boolean.class)));
|
||||||
static final ToggleBreakMatcher HAS_SPEC = new ToggleBreakMatcher(1, List.of(
|
static final ToggleBreakMatcher HAS_SPEC = new ToggleBreakMatcher(1, List.of(
|
||||||
new TypeParamSpec("specification", TargetBreakpointSpec.class),
|
new TypeParamSpec("specification", TraceObjectBreakpointSpec.class),
|
||||||
new TypeParamSpec("enabled", Boolean.class)));
|
new TypeParamSpec("enabled", Boolean.class)));
|
||||||
static final List<ToggleBreakMatcher> ALL = matchers(HAS_LOC, HAS_SPEC);
|
static final List<ToggleBreakMatcher> ALL = matchers(HAS_LOC, HAS_SPEC);
|
||||||
static final List<ToggleBreakMatcher> SPEC = matchers(HAS_SPEC);
|
static final List<ToggleBreakMatcher> SPEC = matchers(HAS_SPEC);
|
||||||
@@ -928,7 +922,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
return AsyncUtils.nil();
|
return AsyncUtils.nil();
|
||||||
}
|
}
|
||||||
|
|
||||||
SchemaName name = object.getTargetSchema().getName();
|
SchemaName name = object.getSchema().getName();
|
||||||
MatchedMethod activate = matches.getBest("activate_" + name, ActionName.ACTIVATE,
|
MatchedMethod activate = matches.getBest("activate_" + name, ActionName.ACTIVATE,
|
||||||
() -> ActivateMatcher.makeBySpecificity(trace.getObjectManager().getRootSchema(),
|
() -> ActivateMatcher.makeBySpecificity(trace.getObjectManager().getRootSchema(),
|
||||||
object.getCanonicalPath()));
|
object.getCanonicalPath()));
|
||||||
@@ -939,7 +933,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
Map<String, Object> args = new HashMap<>();
|
Map<String, Object> args = new HashMap<>();
|
||||||
RemoteParameter paramFocus = activate.params.get("focus");
|
RemoteParameter paramFocus = activate.params.get("focus");
|
||||||
args.put(paramFocus.name(),
|
args.put(paramFocus.name(),
|
||||||
object.querySuitableSchema(getSchemaContext().getSchema(paramFocus.type())));
|
object.findSuitableSchema(getSchemaContext().getSchema(paramFocus.type())));
|
||||||
RemoteParameter paramTime = activate.params.get("time");
|
RemoteParameter paramTime = activate.params.get("time");
|
||||||
if (paramTime != null) {
|
if (paramTime != null) {
|
||||||
args.put(paramTime.name(), coords.getTime().toString());
|
args.put(paramTime.name(), coords.getTime().toString());
|
||||||
@@ -974,7 +968,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected SchemaContext getSchemaContext() {
|
protected SchemaContext getSchemaContext() {
|
||||||
TargetObjectSchema rootSchema = trace.getObjectManager().getRootSchema();
|
TraceObjectSchema rootSchema = trace.getObjectManager().getRootSchema();
|
||||||
if (rootSchema == null) {
|
if (rootSchema == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -987,7 +981,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
Lifespan.at(getSnap()),
|
Lifespan.at(getSnap()),
|
||||||
new AddressRangeImpl(space.getMinAddress(), space.getMaxAddress()))) {
|
new AddressRangeImpl(space.getMinAddress(), space.getMaxAddress()))) {
|
||||||
TraceObject obj = ((TraceObjectMemoryRegion) region).getObject();
|
TraceObject obj = ((TraceObjectMemoryRegion) region).getObject();
|
||||||
return obj.queryCanonicalAncestorsTargetInterface(TargetProcess.class)
|
return obj.findCanonicalAncestorsInterface(TraceObjectProcess.class)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
@@ -1092,7 +1086,7 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
Msg.error(this, "Non-object trace with TraceRmi!");
|
Msg.error(this, "Non-object trace with TraceRmi!");
|
||||||
return AsyncUtils.nil();
|
return AsyncUtils.nil();
|
||||||
}
|
}
|
||||||
TraceObject container = tot.getObject().queryRegisterContainer(frame);
|
TraceObject container = tot.getObject().findRegisterContainer(frame);
|
||||||
if (container == null) {
|
if (container == null) {
|
||||||
Msg.error(this,
|
Msg.error(this,
|
||||||
"Cannot find register container for thread,frame: " + thread + "," + frame);
|
"Cannot find register container for thread,frame: " + thread + "," + frame);
|
||||||
@@ -1110,25 +1104,11 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
keys.add("[" + lower + "]");
|
keys.add("[" + lower + "]");
|
||||||
}
|
}
|
||||||
Set<TraceObject> regs = container
|
Set<TraceObject> regs = container
|
||||||
.querySuccessorsTargetInterface(Lifespan.at(getSnap()), TargetRegister.class,
|
.findSuccessorsInterface(Lifespan.at(getSnap()), TraceObjectRegister.class,
|
||||||
true)
|
true)
|
||||||
.filter(p -> keys.contains(p.getLastEntry().getEntryKey().toLowerCase()))
|
.filter(p -> keys.contains(p.getLastEntry().getEntryKey().toLowerCase()))
|
||||||
.map(r -> r.getDestination(null))
|
.map(r -> r.getDestination(null))
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
RemoteParameter paramBank = readRegs.params.get("bank");
|
|
||||||
if (paramBank != null) {
|
|
||||||
Set<TraceObject> banks = regs.stream()
|
|
||||||
.flatMap(r -> r.queryCanonicalAncestorsTargetInterface(TargetRegisterBank.class)
|
|
||||||
.findFirst()
|
|
||||||
.stream())
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
AsyncFence fence = new AsyncFence();
|
|
||||||
banks.stream().forEach(b -> {
|
|
||||||
fence.include(requestCaches.readRegs(b, readRegs.method, Map.of(
|
|
||||||
paramBank.name(), b)));
|
|
||||||
});
|
|
||||||
return fence.ready();
|
|
||||||
}
|
|
||||||
RemoteParameter paramRegister = readRegs.params.get("register");
|
RemoteParameter paramRegister = readRegs.params.get("register");
|
||||||
if (paramRegister != null) {
|
if (paramRegister != null) {
|
||||||
AsyncFence fence = new AsyncFence();
|
AsyncFence fence = new AsyncFence();
|
||||||
@@ -1142,17 +1122,18 @@ public class TraceRmiTarget extends AbstractTarget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected TraceObject findRegisterObject(TraceObjectThread thread, int frame, String name) {
|
protected TraceObject findRegisterObject(TraceObjectThread thread, int frame, String name) {
|
||||||
TraceObject container = thread.getObject().queryRegisterContainer(frame);
|
TraceObject container = thread.getObject().findRegisterContainer(frame);
|
||||||
if (container == null) {
|
if (container == null) {
|
||||||
Msg.error(this, "No register container for thread=" + thread + ",frame=" + frame);
|
Msg.error(this, "No register container for thread=" + thread + ",frame=" + frame);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
PathMatcher matcher = container.getTargetSchema().searchFor(TargetRegister.class, true);
|
PathMatcher matcher =
|
||||||
PathPredicates pred = matcher.applyKeys(Align.RIGHT, name)
|
container.getSchema().searchFor(TraceObjectRegister.class, true);
|
||||||
|
PathFilter filter = matcher.applyKeys(Align.RIGHT, name)
|
||||||
.or(matcher.applyKeys(Align.RIGHT, name.toLowerCase()))
|
.or(matcher.applyKeys(Align.RIGHT, name.toLowerCase()))
|
||||||
.or(matcher.applyKeys(Align.RIGHT, name.toUpperCase()));
|
.or(matcher.applyKeys(Align.RIGHT, name.toUpperCase()));
|
||||||
TraceObjectValPath regValPath =
|
TraceObjectValPath regValPath =
|
||||||
container.getCanonicalSuccessors(pred).findFirst().orElse(null);
|
container.getCanonicalSuccessors(filter).findFirst().orElse(null);
|
||||||
if (regValPath == null) {
|
if (regValPath == null) {
|
||||||
Msg.error(this, "Cannot find register object for " + name + " in " + container);
|
Msg.error(this, "Cannot find register object for " + name + " in " + container);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -32,15 +32,15 @@ import ghidra.app.plugin.core.debug.gui.InvocationDialogHelper;
|
|||||||
import ghidra.app.plugin.core.debug.service.tracermi.TestTraceRmiConnection.TestRemoteMethod;
|
import ghidra.app.plugin.core.debug.service.tracermi.TestTraceRmiConnection.TestRemoteMethod;
|
||||||
import ghidra.app.plugin.core.debug.service.tracermi.TestTraceRmiConnection.TestRemoteParameter;
|
import ghidra.app.plugin.core.debug.service.tracermi.TestTraceRmiConnection.TestRemoteParameter;
|
||||||
import ghidra.async.SwingExecutorService;
|
import ghidra.async.SwingExecutorService;
|
||||||
import ghidra.dbg.target.TargetMethod.Param;
|
|
||||||
import ghidra.dbg.target.TargetMethod.ParameterDescription;
|
|
||||||
import ghidra.dbg.target.schema.*;
|
|
||||||
import ghidra.dbg.target.schema.EnumerableTargetObjectSchema.MinimalSchemaContext;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.debug.api.ValStr;
|
import ghidra.debug.api.ValStr;
|
||||||
import ghidra.debug.api.tracermi.RemoteMethod;
|
import ghidra.debug.api.tracermi.RemoteMethod;
|
||||||
import ghidra.debug.api.tracermi.RemoteParameter;
|
import ghidra.debug.api.tracermi.RemoteParameter;
|
||||||
import ghidra.framework.options.PropertyBoolean;
|
import ghidra.framework.options.PropertyBoolean;
|
||||||
|
import ghidra.trace.model.target.iface.TraceObjectMethod.Param;
|
||||||
|
import ghidra.trace.model.target.iface.TraceObjectMethod.ParameterDescription;
|
||||||
|
import ghidra.trace.model.target.schema.*;
|
||||||
|
import ghidra.trace.model.target.schema.PrimitiveTraceObjectSchema.MinimalSchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
|
|
||||||
public class RemoteMethodInvocationDialogTest extends AbstractGhidraHeadedDebuggerTest {
|
public class RemoteMethodInvocationDialogTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
|
|
||||||
@@ -53,14 +53,14 @@ public class RemoteMethodInvocationDialogTest extends AbstractGhidraHeadedDebugg
|
|||||||
params.put(parameter.name(), parameter);
|
params.put(parameter.name(), parameter);
|
||||||
}
|
}
|
||||||
return new TestRemoteMethod(m.getName(), null, "Test", "A test method", params,
|
return new TestRemoteMethod(m.getName(), null, "Test", "A test method", params,
|
||||||
EnumerableTargetObjectSchema.schemaForPrimitive(m.getReturnType()));
|
PrimitiveTraceObjectSchema.schemaForPrimitive(m.getReturnType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TestRemoteParameter createParameter(Parameter p) {
|
public static TestRemoteParameter createParameter(Parameter p) {
|
||||||
ParameterDescription<?> desc = ParameterDescription.annotated(p);
|
ParameterDescription<?> desc = ParameterDescription.annotated(p);
|
||||||
TargetObjectSchema schema = EnumerableTargetObjectSchema.schemaForPrimitive(desc.type);
|
TraceObjectSchema schema = PrimitiveTraceObjectSchema.schemaForPrimitive(desc.type);
|
||||||
if (schema == EnumerableTargetObjectSchema.OBJECT ||
|
if (schema == PrimitiveTraceObjectSchema.OBJECT ||
|
||||||
schema == EnumerableTargetObjectSchema.ANY) {
|
schema == PrimitiveTraceObjectSchema.ANY) {
|
||||||
schema = CTX.getSchema(new SchemaName(desc.schema));
|
schema = CTX.getSchema(new SchemaName(desc.schema));
|
||||||
}
|
}
|
||||||
return new TestRemoteParameter(desc.name, schema, desc.required, desc.defaultValue,
|
return new TestRemoteParameter(desc.name, schema, desc.required, desc.defaultValue,
|
||||||
|
|||||||
@@ -38,13 +38,13 @@ import ghidra.app.plugin.core.debug.service.tracermi.TestTraceRmiClient.Tx;
|
|||||||
import ghidra.app.plugin.core.debug.service.tracermi.TraceRmiPlugin;
|
import ghidra.app.plugin.core.debug.service.tracermi.TraceRmiPlugin;
|
||||||
import ghidra.app.services.DebuggerControlService;
|
import ghidra.app.services.DebuggerControlService;
|
||||||
import ghidra.app.services.TraceRmiService;
|
import ghidra.app.services.TraceRmiService;
|
||||||
import ghidra.dbg.target.schema.SchemaContext;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
|
||||||
import ghidra.debug.api.control.ControlMode;
|
import ghidra.debug.api.control.ControlMode;
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
import ghidra.debug.api.tracermi.TraceRmiAcceptor;
|
import ghidra.debug.api.tracermi.TraceRmiAcceptor;
|
||||||
import ghidra.debug.api.tracermi.TraceRmiConnection;
|
import ghidra.debug.api.tracermi.TraceRmiConnection;
|
||||||
|
import ghidra.trace.model.target.schema.SchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
public class TraceRmiConnectionManagerProviderTest extends AbstractGhidraHeadedDebuggerTest {
|
public class TraceRmiConnectionManagerProviderTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -25,20 +25,21 @@ import db.Transaction;
|
|||||||
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest;
|
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest;
|
||||||
import ghidra.app.plugin.core.debug.service.tracermi.TestTraceRmiConnection.TestRemoteMethod;
|
import ghidra.app.plugin.core.debug.service.tracermi.TestTraceRmiConnection.TestRemoteMethod;
|
||||||
import ghidra.app.plugin.core.debug.service.tracermi.TestTraceRmiConnection.TestRemoteParameter;
|
import ghidra.app.plugin.core.debug.service.tracermi.TestTraceRmiConnection.TestRemoteParameter;
|
||||||
import ghidra.dbg.target.schema.EnumerableTargetObjectSchema;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.debug.api.target.ActionName;
|
import ghidra.debug.api.target.ActionName;
|
||||||
import ghidra.debug.api.tracermi.RemoteMethod;
|
import ghidra.debug.api.tracermi.RemoteMethod;
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.target.*;
|
import ghidra.trace.model.target.*;
|
||||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
import ghidra.trace.model.target.schema.PrimitiveTraceObjectSchema;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
|
|
||||||
public class RemoteMethodTest extends AbstractGhidraHeadedDebuggerTest {
|
public class RemoteMethodTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
@Test
|
@Test
|
||||||
public void testRemoteMethodValidateObjectGivenObject() throws Throwable {
|
public void testRemoteMethodValidateObjectGivenObject() throws Throwable {
|
||||||
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
||||||
"A test method", EnumerableTargetObjectSchema.VOID.getName(),
|
"A test method", PrimitiveTraceObjectSchema.VOID.getName(),
|
||||||
new TestRemoteParameter("obj", EnumerableTargetObjectSchema.OBJECT.getName(), true,
|
new TestRemoteParameter("obj", PrimitiveTraceObjectSchema.OBJECT.getName(), true,
|
||||||
null, "Arg1", "An argument"));
|
null, "Arg1", "An argument"));
|
||||||
|
|
||||||
createTrace();
|
createTrace();
|
||||||
@@ -56,8 +57,8 @@ public class RemoteMethodTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testRemoteMethodValidateObjectGivenProcess() throws Throwable {
|
public void testRemoteMethodValidateObjectGivenProcess() throws Throwable {
|
||||||
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
||||||
"A test method", EnumerableTargetObjectSchema.VOID.getName(),
|
"A test method", PrimitiveTraceObjectSchema.VOID.getName(),
|
||||||
new TestRemoteParameter("obj", EnumerableTargetObjectSchema.OBJECT.getName(), true,
|
new TestRemoteParameter("obj", PrimitiveTraceObjectSchema.OBJECT.getName(), true,
|
||||||
null, "Arg1", "An argument"));
|
null, "Arg1", "An argument"));
|
||||||
|
|
||||||
createTrace();
|
createTrace();
|
||||||
@@ -66,7 +67,7 @@ public class RemoteMethodTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
tb.trace.getObjectManager().createRootObject(CTX.getSchema(new SchemaName("Session")));
|
tb.trace.getObjectManager().createRootObject(CTX.getSchema(new SchemaName("Session")));
|
||||||
process =
|
process =
|
||||||
tb.trace.getObjectManager().createObject(TraceObjectKeyPath.parse("Processes[0]"));
|
tb.trace.getObjectManager().createObject(KeyPath.parse("Processes[0]"));
|
||||||
process.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
process.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,8 +77,8 @@ public class RemoteMethodTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testRemoteMethodValidateObjectGivenInt() throws Throwable {
|
public void testRemoteMethodValidateObjectGivenInt() throws Throwable {
|
||||||
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
||||||
"A test method", EnumerableTargetObjectSchema.VOID.getName(),
|
"A test method", PrimitiveTraceObjectSchema.VOID.getName(),
|
||||||
new TestRemoteParameter("obj", EnumerableTargetObjectSchema.OBJECT.getName(), true,
|
new TestRemoteParameter("obj", PrimitiveTraceObjectSchema.OBJECT.getName(), true,
|
||||||
null, "Arg1", "An argument"));
|
null, "Arg1", "An argument"));
|
||||||
|
|
||||||
method.validate(Map.of("obj", 1));
|
method.validate(Map.of("obj", 1));
|
||||||
@@ -86,7 +87,7 @@ public class RemoteMethodTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testRemoteMethodValidateProcessGivenProcess() throws Throwable {
|
public void testRemoteMethodValidateProcessGivenProcess() throws Throwable {
|
||||||
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
||||||
"A test method", EnumerableTargetObjectSchema.VOID.getName(),
|
"A test method", PrimitiveTraceObjectSchema.VOID.getName(),
|
||||||
new TestRemoteParameter("proc", new SchemaName("Process"), true,
|
new TestRemoteParameter("proc", new SchemaName("Process"), true,
|
||||||
null, "Proc1", "A Process argument"));
|
null, "Proc1", "A Process argument"));
|
||||||
|
|
||||||
@@ -96,7 +97,7 @@ public class RemoteMethodTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
tb.trace.getObjectManager().createRootObject(CTX.getSchema(new SchemaName("Session")));
|
tb.trace.getObjectManager().createRootObject(CTX.getSchema(new SchemaName("Session")));
|
||||||
process =
|
process =
|
||||||
tb.trace.getObjectManager().createObject(TraceObjectKeyPath.parse("Processes[0]"));
|
tb.trace.getObjectManager().createObject(KeyPath.parse("Processes[0]"));
|
||||||
process.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
process.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +107,7 @@ public class RemoteMethodTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testRemoteMethodValidateProcessGivenInt() throws Throwable {
|
public void testRemoteMethodValidateProcessGivenInt() throws Throwable {
|
||||||
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
||||||
"A test method", EnumerableTargetObjectSchema.VOID.getName(),
|
"A test method", PrimitiveTraceObjectSchema.VOID.getName(),
|
||||||
new TestRemoteParameter("proc", new SchemaName("Process"), true,
|
new TestRemoteParameter("proc", new SchemaName("Process"), true,
|
||||||
null, "Proc1", "A Process argument"));
|
null, "Proc1", "A Process argument"));
|
||||||
|
|
||||||
@@ -122,8 +123,8 @@ public class RemoteMethodTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testRemoteMethodValidateAnyGivenInteger() throws Throwable {
|
public void testRemoteMethodValidateAnyGivenInteger() throws Throwable {
|
||||||
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
||||||
"A test method", EnumerableTargetObjectSchema.VOID.getName(),
|
"A test method", PrimitiveTraceObjectSchema.VOID.getName(),
|
||||||
new TestRemoteParameter("arg", EnumerableTargetObjectSchema.ANY.getName(), true,
|
new TestRemoteParameter("arg", PrimitiveTraceObjectSchema.ANY.getName(), true,
|
||||||
null, "Arg1", "An argument"));
|
null, "Arg1", "An argument"));
|
||||||
|
|
||||||
method.validate(Map.of("arg", 1));
|
method.validate(Map.of("arg", 1));
|
||||||
@@ -132,8 +133,8 @@ public class RemoteMethodTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testRemoteMethodValidateAnyGivenObject() throws Throwable {
|
public void testRemoteMethodValidateAnyGivenObject() throws Throwable {
|
||||||
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
||||||
"A test method", EnumerableTargetObjectSchema.VOID.getName(),
|
"A test method", PrimitiveTraceObjectSchema.VOID.getName(),
|
||||||
new TestRemoteParameter("arg", EnumerableTargetObjectSchema.ANY.getName(), true,
|
new TestRemoteParameter("arg", PrimitiveTraceObjectSchema.ANY.getName(), true,
|
||||||
null, "Arg1", "An argument"));
|
null, "Arg1", "An argument"));
|
||||||
|
|
||||||
createTrace();
|
createTrace();
|
||||||
@@ -151,8 +152,8 @@ public class RemoteMethodTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testRemoteMethodValidateAnyGivenProcess() throws Throwable {
|
public void testRemoteMethodValidateAnyGivenProcess() throws Throwable {
|
||||||
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
||||||
"A test method", EnumerableTargetObjectSchema.VOID.getName(),
|
"A test method", PrimitiveTraceObjectSchema.VOID.getName(),
|
||||||
new TestRemoteParameter("arg", EnumerableTargetObjectSchema.ANY.getName(), true,
|
new TestRemoteParameter("arg", PrimitiveTraceObjectSchema.ANY.getName(), true,
|
||||||
null, "Arg1", "An argument"));
|
null, "Arg1", "An argument"));
|
||||||
|
|
||||||
createTrace();
|
createTrace();
|
||||||
@@ -161,7 +162,7 @@ public class RemoteMethodTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
tb.trace.getObjectManager().createRootObject(CTX.getSchema(new SchemaName("Session")));
|
tb.trace.getObjectManager().createRootObject(CTX.getSchema(new SchemaName("Session")));
|
||||||
process =
|
process =
|
||||||
tb.trace.getObjectManager().createObject(TraceObjectKeyPath.parse("Processes[0]"));
|
tb.trace.getObjectManager().createObject(KeyPath.parse("Processes[0]"));
|
||||||
process.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
process.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,8 +172,8 @@ public class RemoteMethodTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testRemoteMethodValidateIntegerGivenInteger() throws Throwable {
|
public void testRemoteMethodValidateIntegerGivenInteger() throws Throwable {
|
||||||
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
||||||
"A test method", EnumerableTargetObjectSchema.VOID.getName(),
|
"A test method", PrimitiveTraceObjectSchema.VOID.getName(),
|
||||||
new TestRemoteParameter("arg", EnumerableTargetObjectSchema.INT.getName(), true,
|
new TestRemoteParameter("arg", PrimitiveTraceObjectSchema.INT.getName(), true,
|
||||||
null, "Arg1", "An argument"));
|
null, "Arg1", "An argument"));
|
||||||
|
|
||||||
method.validate(Map.of("arg", 1));
|
method.validate(Map.of("arg", 1));
|
||||||
@@ -181,8 +182,8 @@ public class RemoteMethodTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void testRemoteMethodValidateIntegerGivenLong() throws Throwable {
|
public void testRemoteMethodValidateIntegerGivenLong() throws Throwable {
|
||||||
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
RemoteMethod method = new TestRemoteMethod("test", ActionName.name("test"), "Test",
|
||||||
"A test method", EnumerableTargetObjectSchema.VOID.getName(),
|
"A test method", PrimitiveTraceObjectSchema.VOID.getName(),
|
||||||
new TestRemoteParameter("arg", EnumerableTargetObjectSchema.INT.getName(), true,
|
new TestRemoteParameter("arg", PrimitiveTraceObjectSchema.INT.getName(), true,
|
||||||
null, "Arg1", "An argument"));
|
null, "Arg1", "An argument"));
|
||||||
|
|
||||||
method.validate(Map.of("arg", 1L));
|
method.validate(Map.of("arg", 1L));
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -20,11 +20,11 @@ import static org.junit.Assert.assertEquals;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.channels.SocketChannel;
|
import java.nio.channels.SocketChannel;
|
||||||
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
|
||||||
import ghidra.framework.Application;
|
import ghidra.framework.Application;
|
||||||
import ghidra.rmi.trace.TraceRmi.*;
|
import ghidra.rmi.trace.TraceRmi.*;
|
||||||
import ghidra.rmi.trace.TraceRmi.Compiler;
|
import ghidra.rmi.trace.TraceRmi.Compiler;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||||
|
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||||
|
|
||||||
public class TestTraceRmiClient {
|
public class TestTraceRmiClient {
|
||||||
final ProtobufSocket<RootMessage> socket;
|
final ProtobufSocket<RootMessage> socket;
|
||||||
@@ -128,7 +128,7 @@ public class TestTraceRmiClient {
|
|||||||
socket.recv());
|
socket.recv());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createRootObject(int traceId, TargetObjectSchema schema) throws IOException {
|
public void createRootObject(int traceId, TraceObjectSchema schema) throws IOException {
|
||||||
String xmlCtx = XmlSchemaContext.serialize(schema.getContext());
|
String xmlCtx = XmlSchemaContext.serialize(schema.getContext());
|
||||||
socket.send(RootMessage.newBuilder()
|
socket.send(RootMessage.newBuilder()
|
||||||
.setRequestCreateRootObject(RequestCreateRootObject.newBuilder()
|
.setRequestCreateRootObject(RequestCreateRootObject.newBuilder()
|
||||||
|
|||||||
@@ -27,14 +27,14 @@ import java.util.stream.Stream;
|
|||||||
import db.Transaction;
|
import db.Transaction;
|
||||||
import ghidra.app.services.DebuggerTargetService;
|
import ghidra.app.services.DebuggerTargetService;
|
||||||
import ghidra.async.*;
|
import ghidra.async.*;
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.debug.api.target.ActionName;
|
import ghidra.debug.api.target.ActionName;
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
import ghidra.debug.api.tracermi.*;
|
import ghidra.debug.api.tracermi.*;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
import ghidra.trace.model.time.TraceSnapshot;
|
import ghidra.trace.model.time.TraceSnapshot;
|
||||||
|
|
||||||
public abstract class TestTraceRmiConnection extends AbstractTraceRmiConnection {
|
public abstract class TestTraceRmiConnection extends AbstractTraceRmiConnection {
|
||||||
@@ -70,13 +70,13 @@ public abstract class TestTraceRmiConnection extends AbstractTraceRmiConnection
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TestRemoteMethod(String name, ActionName action, String display, String description,
|
public TestRemoteMethod(String name, ActionName action, String display, String description,
|
||||||
Map<String, RemoteParameter> parameters, TargetObjectSchema retType) {
|
Map<String, RemoteParameter> parameters, TraceObjectSchema retType) {
|
||||||
this(name, action, display, description, parameters, retType.getName(),
|
this(name, action, display, description, parameters, retType.getName(),
|
||||||
new AsyncPairingQueue<>(), new AsyncPairingQueue<>());
|
new AsyncPairingQueue<>(), new AsyncPairingQueue<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public TestRemoteMethod(String name, ActionName action, String display, String description,
|
public TestRemoteMethod(String name, ActionName action, String display, String description,
|
||||||
TargetObjectSchema retType, RemoteParameter... parameters) {
|
TraceObjectSchema retType, RemoteParameter... parameters) {
|
||||||
this(name, action, display, description, Stream.of(parameters)
|
this(name, action, display, description, Stream.of(parameters)
|
||||||
.collect(Collectors.toMap(RemoteParameter::name, p -> p)),
|
.collect(Collectors.toMap(RemoteParameter::name, p -> p)),
|
||||||
retType);
|
retType);
|
||||||
@@ -110,7 +110,7 @@ public abstract class TestTraceRmiConnection extends AbstractTraceRmiConnection
|
|||||||
|
|
||||||
public record TestRemoteParameter(String name, SchemaName type, boolean required,
|
public record TestRemoteParameter(String name, SchemaName type, boolean required,
|
||||||
Object defaultValue, String display, String description) implements RemoteParameter {
|
Object defaultValue, String display, String description) implements RemoteParameter {
|
||||||
public TestRemoteParameter(String name, TargetObjectSchema type, boolean required,
|
public TestRemoteParameter(String name, TraceObjectSchema type, boolean required,
|
||||||
Object defaultValue, String display, String description) {
|
Object defaultValue, String display, String description) {
|
||||||
this(name, type.getName(), required, defaultValue, display, description);
|
this(name, type.getName(), required, defaultValue, display, description);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -25,7 +25,6 @@ eclipse.project.name = 'Debug Debugger'
|
|||||||
dependencies {
|
dependencies {
|
||||||
api project(':Debugger-api')
|
api project(':Debugger-api')
|
||||||
api project(':Framework-AsyncComm')
|
api project(':Framework-AsyncComm')
|
||||||
api project(':Framework-Debugging')
|
|
||||||
api project(':Framework-TraceModeling')
|
api project(':Framework-TraceModeling')
|
||||||
api project(':Base')
|
api project(':Base')
|
||||||
api project(':ByteViewer')
|
api project(':ByteViewer')
|
||||||
@@ -36,7 +35,6 @@ dependencies {
|
|||||||
testImplementation project(path: ':Generic', configuration: 'testArtifacts')
|
testImplementation project(path: ':Generic', configuration: 'testArtifacts')
|
||||||
testImplementation project(path: ':Base', configuration: 'testArtifacts')
|
testImplementation project(path: ':Base', configuration: 'testArtifacts')
|
||||||
testImplementation project(path: ':Framework-AsyncComm', configuration: 'testArtifacts')
|
testImplementation project(path: ':Framework-AsyncComm', configuration: 'testArtifacts')
|
||||||
testImplementation project(path: ':Framework-Debugging', configuration: 'testArtifacts')
|
|
||||||
testImplementation project(path: ':Framework-TraceModeling', configuration: 'testArtifacts')
|
testImplementation project(path: ':Framework-TraceModeling', configuration: 'testArtifacts')
|
||||||
testImplementation project(path: ':Project', configuration: 'testArtifacts')
|
testImplementation project(path: ':Project', configuration: 'testArtifacts')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +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 ghidra.app.plugin.core.debug.event;
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
|
|
||||||
import ghidra.dbg.DebuggerObjectModel;
|
|
||||||
import ghidra.framework.plugintool.PluginEvent;
|
|
||||||
|
|
||||||
public class ModelActivatedPluginEvent extends PluginEvent {
|
|
||||||
static final String NAME = "Model Focus";
|
|
||||||
|
|
||||||
private final WeakReference<DebuggerObjectModel> newModelRef;
|
|
||||||
|
|
||||||
public ModelActivatedPluginEvent(String source, DebuggerObjectModel model) {
|
|
||||||
super(source, NAME);
|
|
||||||
this.newModelRef = new WeakReference<>(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DebuggerObjectModel getActiveModel() {
|
|
||||||
return newModelRef.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -16,7 +16,6 @@
|
|||||||
package ghidra.app.plugin.core.debug.gui.memory;
|
package ghidra.app.plugin.core.debug.gui.memory;
|
||||||
|
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
@@ -27,15 +26,15 @@ import docking.ReusableDialogComponentProvider;
|
|||||||
import docking.widgets.model.GAddressRangeField;
|
import docking.widgets.model.GAddressRangeField;
|
||||||
import docking.widgets.model.GSpanField;
|
import docking.widgets.model.GSpanField;
|
||||||
import ghidra.app.plugin.core.debug.utils.MiscellaneousUtils;
|
import ghidra.app.plugin.core.debug.utils.MiscellaneousUtils;
|
||||||
import ghidra.dbg.target.TargetMemoryRegion;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||||
import ghidra.trace.model.target.TraceObjectKeyPath;
|
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||||
import ghidra.util.layout.PairLayout;
|
import ghidra.util.layout.PairLayout;
|
||||||
|
|
||||||
public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider {
|
public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider {
|
||||||
@@ -155,17 +154,17 @@ public class DebuggerAddRegionDialog extends ReusableDialogComponentProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected String computeDefaultPath(DebuggerCoordinates current) {
|
protected String computeDefaultPath(DebuggerCoordinates current) {
|
||||||
TargetObjectSchema rootSchema = trace.getObjectManager().getRootSchema();
|
TraceObjectSchema rootSchema = trace.getObjectManager().getRootSchema();
|
||||||
if (rootSchema == null) {
|
if (rootSchema == null) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
List<String> suitable = rootSchema.searchForSuitableContainer(TargetMemoryRegion.class,
|
KeyPath suitable = rootSchema.searchForSuitableContainer(TraceObjectMemoryRegion.class,
|
||||||
current.getPath().getKeyList());
|
current.getPath());
|
||||||
if (suitable == null) {
|
if (suitable == null) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return TraceObjectKeyPath.of(suitable).index("New").toString();
|
return suitable.index("New").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setValues(DebuggerCoordinates current) {
|
protected void setValues(DebuggerCoordinates current) {
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.gui.memory;
|
package ghidra.app.plugin.core.debug.gui.memory;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -23,8 +22,6 @@ import docking.widgets.table.TableColumnDescriptor;
|
|||||||
import ghidra.app.plugin.core.debug.gui.model.*;
|
import ghidra.app.plugin.core.debug.gui.model.*;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.columns.*;
|
import ghidra.app.plugin.core.debug.gui.model.columns.*;
|
||||||
import ghidra.dbg.target.*;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.debug.api.model.DebuggerObjectActionContext;
|
import ghidra.debug.api.model.DebuggerObjectActionContext;
|
||||||
import ghidra.docking.settings.Settings;
|
import ghidra.docking.settings.Settings;
|
||||||
import ghidra.framework.plugintool.Plugin;
|
import ghidra.framework.plugintool.Plugin;
|
||||||
@@ -32,9 +29,11 @@ import ghidra.framework.plugintool.ServiceProvider;
|
|||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressRange;
|
import ghidra.program.model.address.AddressRange;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
import ghidra.trace.model.memory.*;
|
||||||
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||||
|
import ghidra.trace.model.thread.TraceObjectProcess;
|
||||||
|
|
||||||
public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceObjectMemoryRegion> {
|
public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceObjectMemoryRegion> {
|
||||||
|
|
||||||
@@ -67,7 +66,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||||||
|
|
||||||
private static class RegionStartColumn extends AbstractTraceValueObjectAddressColumn {
|
private static class RegionStartColumn extends AbstractTraceValueObjectAddressColumn {
|
||||||
public RegionStartColumn() {
|
public RegionStartColumn() {
|
||||||
super(TargetMemoryRegion.RANGE_ATTRIBUTE_NAME);
|
super(TraceObjectMemoryRegion.KEY_RANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -83,7 +82,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||||||
|
|
||||||
private static class RegionEndColumn extends AbstractTraceValueObjectAddressColumn {
|
private static class RegionEndColumn extends AbstractTraceValueObjectAddressColumn {
|
||||||
public RegionEndColumn() {
|
public RegionEndColumn() {
|
||||||
super(TargetMemoryRegion.RANGE_ATTRIBUTE_NAME);
|
super(TraceObjectMemoryRegion.KEY_RANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -99,7 +98,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||||||
|
|
||||||
private static class RegionLengthColumn extends AbstractTraceValueObjectLengthColumn {
|
private static class RegionLengthColumn extends AbstractTraceValueObjectLengthColumn {
|
||||||
public RegionLengthColumn() {
|
public RegionLengthColumn() {
|
||||||
super(TargetMemoryRegion.RANGE_ATTRIBUTE_NAME);
|
super(TraceObjectMemoryRegion.KEY_RANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -121,7 +120,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||||||
|
|
||||||
public static class RegionReadColumn extends RegionFlagColumn {
|
public static class RegionReadColumn extends RegionFlagColumn {
|
||||||
public RegionReadColumn() {
|
public RegionReadColumn() {
|
||||||
super(TargetMemoryRegion.READABLE_ATTRIBUTE_NAME);
|
super(TraceObjectMemoryRegion.KEY_READABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -132,7 +131,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||||||
|
|
||||||
public static class RegionWriteColumn extends RegionFlagColumn {
|
public static class RegionWriteColumn extends RegionFlagColumn {
|
||||||
public RegionWriteColumn() {
|
public RegionWriteColumn() {
|
||||||
super(TargetMemoryRegion.WRITABLE_ATTRIBUTE_NAME);
|
super(TraceObjectMemoryRegion.KEY_WRITABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -143,7 +142,7 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||||||
|
|
||||||
public static class RegionExecuteColumn extends RegionFlagColumn {
|
public static class RegionExecuteColumn extends RegionFlagColumn {
|
||||||
public RegionExecuteColumn() {
|
public RegionExecuteColumn() {
|
||||||
super(TargetMemoryRegion.EXECUTABLE_ATTRIBUTE_NAME);
|
super(TraceObjectMemoryRegion.KEY_EXECUTABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -173,9 +172,9 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static ModelQuery successorRegions(TargetObjectSchema rootSchema, List<String> path) {
|
protected static ModelQuery successorRegions(TraceObjectSchema rootSchema, KeyPath path) {
|
||||||
TargetObjectSchema schema = rootSchema.getSuccessorSchema(path);
|
TraceObjectSchema schema = rootSchema.getSuccessorSchema(path);
|
||||||
return new ModelQuery(schema.searchFor(TargetMemoryRegion.class, path, true));
|
return new ModelQuery(schema.searchFor(TraceObjectMemoryRegion.class, path, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Set<TraceMemoryRegion> getSelectedRegions(DebuggerObjectActionContext ctx) {
|
protected Set<TraceMemoryRegion> getSelectedRegions(DebuggerObjectActionContext ctx) {
|
||||||
@@ -193,23 +192,23 @@ public class DebuggerRegionsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ModelQuery computeQuery(TraceObject object) {
|
protected ModelQuery computeQuery(TraceObject object) {
|
||||||
TargetObjectSchema rootSchema = object.getRoot().getTargetSchema();
|
TraceObjectSchema rootSchema = object.getRoot().getSchema();
|
||||||
List<String> seedPath = object.getCanonicalPath().getKeyList();
|
KeyPath seedPath = object.getCanonicalPath();
|
||||||
List<String> processPath = rootSchema.searchForAncestor(TargetProcess.class, seedPath);
|
KeyPath processPath = rootSchema.searchForAncestor(TraceObjectProcess.class, seedPath);
|
||||||
if (processPath != null) {
|
if (processPath != null) {
|
||||||
ModelQuery result = successorRegions(rootSchema, processPath);
|
ModelQuery result = successorRegions(rootSchema, processPath);
|
||||||
if (!result.isEmpty()) {
|
if (!result.isEmpty()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<String> memoryPath = rootSchema.searchForSuitable(TargetMemory.class, seedPath);
|
KeyPath memoryPath = rootSchema.searchForSuitable(TraceObjectMemory.class, seedPath);
|
||||||
if (memoryPath != null) {
|
if (memoryPath != null) {
|
||||||
ModelQuery result = successorRegions(rootSchema, memoryPath);
|
ModelQuery result = successorRegions(rootSchema, memoryPath);
|
||||||
if (!result.isEmpty()) {
|
if (!result.isEmpty()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return successorRegions(rootSchema, List.of());
|
return successorRegions(rootSchema, KeyPath.ROOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectedRegions(Set<TraceMemoryRegion> sel) {
|
public void setSelectedRegions(Set<TraceMemoryRegion> sel) {
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -35,6 +35,8 @@ import ghidra.framework.plugintool.*;
|
|||||||
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.target.*;
|
import ghidra.trace.model.target.*;
|
||||||
|
import ghidra.trace.model.target.iface.TraceObjectInterface;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
|
||||||
public abstract class AbstractObjectsTableBasedPanel<U extends TraceObjectInterface>
|
public abstract class AbstractObjectsTableBasedPanel<U extends TraceObjectInterface>
|
||||||
extends ObjectsTablePanel
|
extends ObjectsTablePanel
|
||||||
@@ -136,7 +138,7 @@ public abstract class AbstractObjectsTableBasedPanel<U extends TraceObjectInterf
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void activatePath(TraceObjectKeyPath path) {
|
public void activatePath(KeyPath path) {
|
||||||
if (current.getTrace() == null) {
|
if (current.getTrace() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -63,6 +63,7 @@ import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
|||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.target.*;
|
import ghidra.trace.model.target.*;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
@@ -229,7 +230,7 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||||||
protected PathsTablePanel attributesTablePanel;
|
protected PathsTablePanel attributesTablePanel;
|
||||||
|
|
||||||
/*testing*/ DebuggerCoordinates current = DebuggerCoordinates.NOWHERE;
|
/*testing*/ DebuggerCoordinates current = DebuggerCoordinates.NOWHERE;
|
||||||
/*testing*/ TraceObjectKeyPath path = TraceObjectKeyPath.of();
|
/*testing*/ KeyPath path = KeyPath.of();
|
||||||
|
|
||||||
@AutoServiceConsumed
|
@AutoServiceConsumed
|
||||||
protected DebuggerTraceManagerService traceManager;
|
protected DebuggerTraceManagerService traceManager;
|
||||||
@@ -433,7 +434,7 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||||||
mainPanel.revalidate();
|
mainPanel.revalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void activatePath(TraceObjectKeyPath path) {
|
protected void activatePath(KeyPath path) {
|
||||||
if (current.getTrace() == null) {
|
if (current.getTrace() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -457,7 +458,7 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void activatePath(TraceObjectKeyPath path) {
|
public void activatePath(KeyPath path) {
|
||||||
DebuggerModelProvider.this.activatePath(path);
|
DebuggerModelProvider.this.activatePath(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -510,7 +511,7 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||||||
List<AbstractNode> sel = objectsTreePanel.getSelectedItems();
|
List<AbstractNode> sel = objectsTreePanel.getSelectedItems();
|
||||||
if (sel.size() == 1) {
|
if (sel.size() == 1) {
|
||||||
TraceObjectValue value = sel.get(0).getValue();
|
TraceObjectValue value = sel.get(0).getValue();
|
||||||
setPath(value == null ? TraceObjectKeyPath.of() : value.getCanonicalPath(),
|
setPath(value == null ? KeyPath.of() : value.getCanonicalPath(),
|
||||||
objectsTreePanel, EventOrigin.INTERNAL_GENERATED);
|
objectsTreePanel, EventOrigin.INTERNAL_GENERATED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -674,7 +675,7 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||||||
@Override
|
@Override
|
||||||
public boolean verify(JComponent input) {
|
public boolean verify(JComponent input) {
|
||||||
try {
|
try {
|
||||||
TraceObjectKeyPath path = TraceObjectKeyPath.parse(pathField.getText());
|
KeyPath path = KeyPath.parse(pathField.getText());
|
||||||
setPath(path, null, EventOrigin.USER_GENERATED);
|
setPath(path, null, EventOrigin.USER_GENERATED);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -687,7 +688,7 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||||||
goButton = new JButton("Go");
|
goButton = new JButton("Go");
|
||||||
ActionListener gotoPath = evt -> {
|
ActionListener gotoPath = evt -> {
|
||||||
try {
|
try {
|
||||||
TraceObjectKeyPath path = TraceObjectKeyPath.parse(pathField.getText());
|
KeyPath path = KeyPath.parse(pathField.getText());
|
||||||
activatePath(path);
|
activatePath(path);
|
||||||
KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
|
KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
|
||||||
}
|
}
|
||||||
@@ -854,7 +855,7 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||||||
SaveState dataState = new SaveState();
|
SaveState dataState = new SaveState();
|
||||||
this.writeDataState(dataState);
|
this.writeDataState(dataState);
|
||||||
// Selection is not saved to the tool state
|
// Selection is not saved to the tool state
|
||||||
Set<TraceObjectKeyPath> selection = this.objectsTreePanel.getSelectedKeyPaths();
|
Set<KeyPath> selection = this.objectsTreePanel.getSelectedKeyPaths();
|
||||||
// coords are omitted by main window
|
// coords are omitted by main window
|
||||||
// also, cannot save unless trace is in a project
|
// also, cannot save unless trace is in a project
|
||||||
clone.coordinatesActivated(current);
|
clone.coordinatesActivated(current);
|
||||||
@@ -908,7 +909,7 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||||||
if (values.size() != 1) {
|
if (values.size() != 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TraceObjectKeyPath canonicalPath = values.get(0).getChild().getCanonicalPath();
|
KeyPath canonicalPath = values.get(0).getChild().getCanonicalPath();
|
||||||
setPath(canonicalPath);
|
setPath(canonicalPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -917,12 +918,12 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||||||
return mainPanel;
|
return mainPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TraceObjectKeyPath findAsSibling(TraceObject object) {
|
protected KeyPath findAsSibling(TraceObject object) {
|
||||||
Trace trace = current.getTrace();
|
Trace trace = current.getTrace();
|
||||||
if (trace == null) {
|
if (trace == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
TraceObjectKeyPath parentPath = path.parent();
|
KeyPath parentPath = path.parent();
|
||||||
if (parentPath == null) {
|
if (parentPath == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -940,7 +941,7 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TraceObjectKeyPath findAsParent(TraceObject object) {
|
protected KeyPath findAsParent(TraceObject object) {
|
||||||
Trace trace = current.getTrace();
|
Trace trace = current.getTrace();
|
||||||
if (trace == null) {
|
if (trace == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -953,7 +954,7 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||||||
if (sel == null) {
|
if (sel == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
for (TraceObjectKeyPath p = sel.getCanonicalPath(); p != null; p = p.parent()) {
|
for (KeyPath p = sel.getCanonicalPath(); p != null; p = p.parent()) {
|
||||||
if (objectManager.getObjectByCanonicalPath(p) == object) {
|
if (objectManager.getObjectByCanonicalPath(p) == object) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -985,7 +986,7 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||||||
if (findAsParent(object) != null) {
|
if (findAsParent(object) != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TraceObjectKeyPath sibling = findAsSibling(object);
|
KeyPath sibling = findAsSibling(object);
|
||||||
if (sibling != null) {
|
if (sibling != null) {
|
||||||
objectsTreePanel.setSelectedKeyPaths(List.of(sibling));
|
objectsTreePanel.setSelectedKeyPaths(List.of(sibling));
|
||||||
setPath(sibling);
|
setPath(sibling);
|
||||||
@@ -1002,7 +1003,7 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setPath(TraceObjectKeyPath path, JComponent source, EventOrigin origin) {
|
protected void setPath(KeyPath path, JComponent source, EventOrigin origin) {
|
||||||
if (Objects.equals(this.path, path) && getTreeSelection() != null) {
|
if (Objects.equals(this.path, path) && getTreeSelection() != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1018,11 +1019,11 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||||||
attributesTablePanel.setQuery(ModelQuery.attributesOf(path));
|
attributesTablePanel.setQuery(ModelQuery.attributesOf(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPath(TraceObjectKeyPath path) {
|
public void setPath(KeyPath path) {
|
||||||
setPath(path, null, EventOrigin.API_GENERATED);
|
setPath(path, null, EventOrigin.API_GENERATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TraceObjectKeyPath getPath() {
|
public KeyPath getPath() {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1137,11 +1138,11 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||||||
return showMethodsInTree;
|
return showMethodsInTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setTreeSelection(TraceObjectKeyPath path, EventOrigin origin) {
|
protected void setTreeSelection(KeyPath path, EventOrigin origin) {
|
||||||
objectsTreePanel.setSelectedKeyPaths(List.of(path), origin);
|
objectsTreePanel.setSelectedKeyPaths(List.of(path), origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setTreeSelection(TraceObjectKeyPath path) {
|
protected void setTreeSelection(KeyPath path) {
|
||||||
setTreeSelection(path, EventOrigin.API_GENERATED);
|
setTreeSelection(path, EventOrigin.API_GENERATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1189,6 +1190,6 @@ public class DebuggerModelProvider extends ComponentProvider implements Saveable
|
|||||||
coordinatesActivated(coords);
|
coordinatesActivated(coords);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setPath(TraceObjectKeyPath.parse(saveState.getString(KEY_PATH, "")));
|
setPath(KeyPath.parse(saveState.getString(KEY_PATH, "")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -17,11 +17,11 @@ package ghidra.app.plugin.core.debug.gui.model;
|
|||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import ghidra.dbg.util.PathPredicates;
|
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
import ghidra.trace.model.target.TraceObjectValue;
|
import ghidra.trace.model.target.TraceObjectValue;
|
||||||
|
import ghidra.trace.model.target.path.PathFilter;
|
||||||
|
|
||||||
public interface DisplaysModified {
|
public interface DisplaysModified {
|
||||||
/**
|
/**
|
||||||
@@ -140,8 +140,7 @@ public interface DisplaysModified {
|
|||||||
return isEdgesDiffer(newContains ? value : null, diffEdge);
|
return isEdgesDiffer(newContains ? value : null, diffEdge);
|
||||||
}
|
}
|
||||||
TraceObjectValue diffEdge = diffTrace.getObjectManager()
|
TraceObjectValue diffEdge = diffTrace.getObjectManager()
|
||||||
.getValuePaths(Lifespan.at(diffSnap),
|
.getValuePaths(Lifespan.at(diffSnap), PathFilter.pattern(value.getCanonicalPath()))
|
||||||
PathPredicates.pattern(value.getCanonicalPath().getKeyList()))
|
|
||||||
.findAny()
|
.findAny()
|
||||||
.map(p -> p.getLastEntry())
|
.map(p -> p.getLastEntry())
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -19,9 +19,9 @@ import java.util.stream.*;
|
|||||||
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
|
||||||
import ghidra.dbg.target.TargetObject;
|
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
import ghidra.trace.model.target.TraceObjectValue;
|
import ghidra.trace.model.target.TraceObjectValue;
|
||||||
|
import ghidra.trace.model.target.iface.TraceObjectInterface;
|
||||||
import ghidra.util.HTMLUtilities;
|
import ghidra.util.HTMLUtilities;
|
||||||
import ghidra.util.NumericUtilities;
|
import ghidra.util.NumericUtilities;
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ public interface DisplaysObjectValues {
|
|||||||
|
|
||||||
default String getObjectType(TraceObjectValue edge) {
|
default String getObjectType(TraceObjectValue edge) {
|
||||||
TraceObject object = edge.getChild();
|
TraceObject object = edge.getChild();
|
||||||
return object.getTargetSchema().getName().toString();
|
return object.getSchema().getName().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
default String getObjectLinkToolTip(TraceObjectValue edge) {
|
default String getObjectLinkToolTip(TraceObjectValue edge) {
|
||||||
@@ -132,7 +132,7 @@ public interface DisplaysObjectValues {
|
|||||||
default String getObjectDisplay(TraceObjectValue edge) {
|
default String getObjectDisplay(TraceObjectValue edge) {
|
||||||
TraceObject object = edge.getChild();
|
TraceObject object = edge.getChild();
|
||||||
TraceObjectValue displayAttr =
|
TraceObjectValue displayAttr =
|
||||||
object.getAttribute(getSnap(), TargetObject.DISPLAY_ATTRIBUTE_NAME);
|
object.getAttribute(getSnap(), TraceObjectInterface.KEY_DISPLAY);
|
||||||
if (displayAttr != null) {
|
if (displayAttr != null) {
|
||||||
return displayAttr.getValue().toString();
|
return displayAttr.getValue().toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,50 +15,51 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.gui.model;
|
package ghidra.app.plugin.core.debug.gui.model;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import ghidra.dbg.target.schema.EnumerableTargetObjectSchema;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.AttributeSchema;
|
|
||||||
import ghidra.dbg.util.*;
|
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.target.*;
|
import ghidra.trace.model.target.*;
|
||||||
|
import ghidra.trace.model.target.path.*;
|
||||||
|
import ghidra.trace.model.target.schema.PrimitiveTraceObjectSchema;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.AttributeSchema;
|
||||||
|
|
||||||
public class ModelQuery {
|
public class ModelQuery {
|
||||||
public static final ModelQuery EMPTY = new ModelQuery(PathPredicates.EMPTY);
|
public static final ModelQuery EMPTY = new ModelQuery(PathFilter.NONE);
|
||||||
// TODO: A more capable query language, e.g., with WHERE clauses.
|
// TODO: A more capable query language, e.g., with WHERE clauses.
|
||||||
// Could also want math expressions for the conditionals... Hmm.
|
// Could also want math expressions for the conditionals... Hmm.
|
||||||
// They need to be user enterable, so just a Java API won't suffice.
|
// They need to be user enterable, so just a Java API won't suffice.
|
||||||
|
|
||||||
public static ModelQuery parse(String queryString) {
|
public static ModelQuery parse(String queryString) {
|
||||||
return new ModelQuery(PathPredicates.parse(queryString));
|
return new ModelQuery(PathFilter.parse(queryString));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ModelQuery elementsOf(TraceObjectKeyPath path) {
|
public static ModelQuery elementsOf(KeyPath path) {
|
||||||
return new ModelQuery(new PathPattern(PathUtils.extend(path.getKeyList(), "[]")));
|
return new ModelQuery(new PathPattern(path.index("")));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ModelQuery attributesOf(TraceObjectKeyPath path) {
|
public static ModelQuery attributesOf(KeyPath path) {
|
||||||
return new ModelQuery(new PathPattern(PathUtils.extend(path.getKeyList(), "")));
|
return new ModelQuery(new PathPattern(path.key("")));
|
||||||
}
|
}
|
||||||
|
|
||||||
private final PathPredicates predicates;
|
private final PathFilter filter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: This should probably be more capable, but for now, just support simple path patterns
|
* TODO: This should probably be more capable, but for now, just support simple path patterns
|
||||||
*
|
*
|
||||||
* @param predicates the patterns
|
* @param filter the filter
|
||||||
*/
|
*/
|
||||||
public ModelQuery(PathPredicates predicates) {
|
public ModelQuery(PathFilter filter) {
|
||||||
this.predicates = predicates;
|
this.filter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "<ModelQuery: " + predicates.toString() + ">";
|
return "<ModelQuery: " + filter.toString() + ">";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -70,7 +71,7 @@ public class ModelQuery {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ModelQuery that = (ModelQuery) obj;
|
ModelQuery that = (ModelQuery) obj;
|
||||||
if (!Objects.equals(this.predicates, that.predicates)) {
|
if (!Objects.equals(this.filter, that.filter)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -82,7 +83,7 @@ public class ModelQuery {
|
|||||||
* @return the string
|
* @return the string
|
||||||
*/
|
*/
|
||||||
public String toQueryString() {
|
public String toQueryString() {
|
||||||
return predicates.getSingletonPattern().toPatternString();
|
return filter.getSingletonPattern().toPatternString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -95,7 +96,7 @@ public class ModelQuery {
|
|||||||
public Stream<TraceObject> streamObjects(Trace trace, Lifespan span) {
|
public Stream<TraceObject> streamObjects(Trace trace, Lifespan span) {
|
||||||
TraceObjectManager objects = trace.getObjectManager();
|
TraceObjectManager objects = trace.getObjectManager();
|
||||||
TraceObject root = objects.getRootObject();
|
TraceObject root = objects.getRootObject();
|
||||||
return objects.getValuePaths(span, predicates)
|
return objects.getValuePaths(span, filter)
|
||||||
.map(p -> p.getDestinationValue(root))
|
.map(p -> p.getDestinationValue(root))
|
||||||
.filter(v -> v instanceof TraceObject)
|
.filter(v -> v instanceof TraceObject)
|
||||||
.map(v -> (TraceObject) v);
|
.map(v -> (TraceObject) v);
|
||||||
@@ -103,32 +104,32 @@ public class ModelQuery {
|
|||||||
|
|
||||||
public Stream<TraceObjectValue> streamValues(Trace trace, Lifespan span) {
|
public Stream<TraceObjectValue> streamValues(Trace trace, Lifespan span) {
|
||||||
TraceObjectManager objects = trace.getObjectManager();
|
TraceObjectManager objects = trace.getObjectManager();
|
||||||
return objects.getValuePaths(span, predicates).map(p -> {
|
return objects.getValuePaths(span, filter).map(p -> {
|
||||||
TraceObjectValue last = p.getLastEntry();
|
TraceObjectValue last = p.getLastEntry();
|
||||||
return last == null ? objects.getRootObject().getCanonicalParent(0) : last;
|
return last == null ? objects.getRootObject().getCanonicalParent(0) : last;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream<TraceObjectValPath> streamPaths(Trace trace, Lifespan span) {
|
public Stream<TraceObjectValPath> streamPaths(Trace trace, Lifespan span) {
|
||||||
return trace.getObjectManager().getValuePaths(span, predicates).map(p -> p);
|
return trace.getObjectManager().getValuePaths(span, filter).map(p -> p);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TargetObjectSchema> computeSchemas(Trace trace) {
|
public List<TraceObjectSchema> computeSchemas(Trace trace) {
|
||||||
TargetObjectSchema rootSchema = trace.getObjectManager().getRootSchema();
|
TraceObjectSchema rootSchema = trace.getObjectManager().getRootSchema();
|
||||||
if (rootSchema == null) {
|
if (rootSchema == null) {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
return predicates.getPatterns()
|
return filter.getPatterns()
|
||||||
.stream()
|
.stream()
|
||||||
.map(p -> rootSchema.getSuccessorSchema(p.asPath()))
|
.map(p -> rootSchema.getSuccessorSchema(p.asPath()))
|
||||||
.distinct()
|
.distinct()
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public TargetObjectSchema computeSingleSchema(Trace trace) {
|
public TraceObjectSchema computeSingleSchema(Trace trace) {
|
||||||
List<TargetObjectSchema> schemas = computeSchemas(trace);
|
List<TraceObjectSchema> schemas = computeSchemas(trace);
|
||||||
if (schemas.size() != 1) {
|
if (schemas.size() != 1) {
|
||||||
return EnumerableTargetObjectSchema.OBJECT;
|
return PrimitiveTraceObjectSchema.OBJECT;
|
||||||
}
|
}
|
||||||
return schemas.get(0);
|
return schemas.get(0);
|
||||||
}
|
}
|
||||||
@@ -143,7 +144,7 @@ public class ModelQuery {
|
|||||||
* @return the list of attributes
|
* @return the list of attributes
|
||||||
*/
|
*/
|
||||||
public Stream<AttributeSchema> computeAttributes(Trace trace) {
|
public Stream<AttributeSchema> computeAttributes(Trace trace) {
|
||||||
TargetObjectSchema schema = computeSingleSchema(trace);
|
TraceObjectSchema schema = computeSingleSchema(trace);
|
||||||
return schema.getAttributeSchemas()
|
return schema.getAttributeSchemas()
|
||||||
.entrySet()
|
.entrySet()
|
||||||
.stream()
|
.stream()
|
||||||
@@ -155,12 +156,12 @@ public class ModelQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected static boolean includes(Lifespan span, PathPattern pattern, TraceObjectValue value) {
|
protected static boolean includes(Lifespan span, PathPattern pattern, TraceObjectValue value) {
|
||||||
List<String> asPath = pattern.asPath();
|
KeyPath asPath = pattern.asPath();
|
||||||
if (asPath.isEmpty()) {
|
if (asPath.isRoot()) {
|
||||||
// If the pattern is the root, then only match the "root value"
|
// If the pattern is the root, then only match the "root value"
|
||||||
return value.getParent() == null;
|
return value.getParent() == null;
|
||||||
}
|
}
|
||||||
if (!PathPredicates.keyMatches(PathUtils.getKey(asPath), value.getEntryKey())) {
|
if (!PathFilter.keyMatches(asPath.key(), value.getEntryKey())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
TraceObject parent = value.getParent();
|
TraceObject parent = value.getParent();
|
||||||
@@ -188,7 +189,7 @@ public class ModelQuery {
|
|||||||
if (!span.intersects(value.getLifespan())) {
|
if (!span.intersects(value.getLifespan())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (PathPattern pattern : predicates.getPatterns()) {
|
for (PathPattern pattern : filter.getPatterns()) {
|
||||||
if (includes(span, pattern, value)) {
|
if (includes(span, pattern, value)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -204,16 +205,16 @@ public class ModelQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if any of the value's paths could be an ancestor of a result
|
// Check if any of the value's paths could be an ancestor of a result
|
||||||
List<String> asPath = new ArrayList<>(pattern.asPath());
|
KeyPath asPath = pattern.asPath();
|
||||||
// Destroy the pattern from the right, thus iterating each ancestor
|
// Destroy the pattern from the right, thus iterating each ancestor
|
||||||
while (!asPath.isEmpty()) {
|
while (!asPath.isRoot()) {
|
||||||
// The value's key much match somewhere in the pattern to be involved
|
// The value's key much match somewhere in the pattern to be involved
|
||||||
if (!PathPredicates.keyMatches(PathUtils.getKey(asPath), value.getEntryKey())) {
|
if (!PathFilter.keyMatches(asPath.key(), value.getEntryKey())) {
|
||||||
asPath.remove(asPath.size() - 1);
|
asPath = asPath.parent();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// If it does, then check if any path to the value's parent matches the rest
|
// If it does, then check if any path to the value's parent matches the rest
|
||||||
asPath.remove(asPath.size() - 1);
|
asPath = asPath.parent();
|
||||||
if (parent.getAncestors(span, new PathPattern(asPath))
|
if (parent.getAncestors(span, new PathPattern(asPath))
|
||||||
.anyMatch(v -> v.getSource(parent).isRoot())) {
|
.anyMatch(v -> v.getSource(parent).isRoot())) {
|
||||||
return true;
|
return true;
|
||||||
@@ -233,15 +234,15 @@ public class ModelQuery {
|
|||||||
if (!span.intersects(value.getLifespan())) {
|
if (!span.intersects(value.getLifespan())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (PathPattern pattern : predicates.getPatterns()) {
|
for (PathPattern pattern : filter.getPatterns()) {
|
||||||
if (involves(span, pattern, value)) {
|
if (involves(span, pattern, value)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return predicates.isEmpty();
|
return filter.isNone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -24,7 +24,6 @@ import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueProperty;
|
|||||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.PathTableModel.PathRow;
|
import ghidra.app.plugin.core.debug.gui.model.PathTableModel.PathRow;
|
||||||
import ghidra.app.services.DebuggerListingService;
|
import ghidra.app.services.DebuggerListingService;
|
||||||
import ghidra.dbg.target.*;
|
|
||||||
import ghidra.debug.api.model.DebuggerSingleObjectPathActionContext;
|
import ghidra.debug.api.model.DebuggerSingleObjectPathActionContext;
|
||||||
import ghidra.debug.api.target.ActionName;
|
import ghidra.debug.api.target.ActionName;
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
@@ -36,6 +35,8 @@ import ghidra.program.model.address.AddressRange;
|
|||||||
import ghidra.program.util.ProgramLocation;
|
import ghidra.program.util.ProgramLocation;
|
||||||
import ghidra.program.util.ProgramSelection;
|
import ghidra.program.util.ProgramSelection;
|
||||||
import ghidra.trace.model.target.*;
|
import ghidra.trace.model.target.*;
|
||||||
|
import ghidra.trace.model.target.iface.*;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
public interface ObjectDefaultActionsMixin {
|
public interface ObjectDefaultActionsMixin {
|
||||||
@@ -44,7 +45,7 @@ public interface ObjectDefaultActionsMixin {
|
|||||||
|
|
||||||
DebuggerCoordinates getCurrent();
|
DebuggerCoordinates getCurrent();
|
||||||
|
|
||||||
void activatePath(TraceObjectKeyPath path);
|
void activatePath(KeyPath path);
|
||||||
|
|
||||||
default void toggleObject(TraceObject object) {
|
default void toggleObject(TraceObject object) {
|
||||||
if (!getCurrent().isAliveAndPresent()) {
|
if (!getCurrent().isAliveAndPresent()) {
|
||||||
@@ -124,8 +125,9 @@ public interface ObjectDefaultActionsMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default boolean performDefaultAction(TraceObject object) {
|
default boolean performDefaultAction(TraceObject object) {
|
||||||
Set<Class<? extends TargetObject>> interfaces = object.getTargetSchema().getInterfaces();
|
Set<Class<? extends TraceObjectInterface>> interfaces =
|
||||||
if (interfaces.contains(TargetActivatable.class)) {
|
object.getSchema().getInterfaces();
|
||||||
|
if (interfaces.contains(TraceObjectActivatable.class)) {
|
||||||
activatePath(object.getCanonicalPath());
|
activatePath(object.getCanonicalPath());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -133,7 +135,7 @@ public interface ObjectDefaultActionsMixin {
|
|||||||
* Should I check aliveAndPresent() here? If I do, behavior changes when target is dead,
|
* Should I check aliveAndPresent() here? If I do, behavior changes when target is dead,
|
||||||
* which might be unexpected.
|
* which might be unexpected.
|
||||||
*/
|
*/
|
||||||
if (interfaces.contains(TargetTogglable.class)) {
|
if (interfaces.contains(TraceObjectTogglable.class)) {
|
||||||
toggleObject(object);
|
toggleObject(object);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -26,9 +26,6 @@ import docking.widgets.table.RangeCursorTableHeaderRenderer.SeekListener;
|
|||||||
import docking.widgets.table.TableColumnDescriptor;
|
import docking.widgets.table.TableColumnDescriptor;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.columns.*;
|
import ghidra.app.plugin.core.debug.gui.model.columns.*;
|
||||||
import ghidra.dbg.target.schema.SchemaContext;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.AttributeSchema;
|
|
||||||
import ghidra.docking.settings.Settings;
|
import ghidra.docking.settings.Settings;
|
||||||
import ghidra.framework.plugintool.Plugin;
|
import ghidra.framework.plugintool.Plugin;
|
||||||
import ghidra.framework.plugintool.ServiceProvider;
|
import ghidra.framework.plugintool.ServiceProvider;
|
||||||
@@ -38,6 +35,9 @@ import ghidra.trace.model.Lifespan.*;
|
|||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
import ghidra.trace.model.target.TraceObjectValue;
|
import ghidra.trace.model.target.TraceObjectValue;
|
||||||
|
import ghidra.trace.model.target.schema.SchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.AttributeSchema;
|
||||||
import ghidra.util.HTMLUtilities;
|
import ghidra.util.HTMLUtilities;
|
||||||
import ghidra.util.NumericUtilities;
|
import ghidra.util.NumericUtilities;
|
||||||
import ghidra.util.datastruct.ListenerSet;
|
import ghidra.util.datastruct.ListenerSet;
|
||||||
@@ -444,7 +444,7 @@ public class ObjectTableModel extends AbstractQueryTableModel<ValueRow> {
|
|||||||
AttributeSchema attributeSchema) {
|
AttributeSchema attributeSchema) {
|
||||||
String name = attributeSchema.getName();
|
String name = attributeSchema.getName();
|
||||||
Class<?> type = computeAttributeType(ctx, attributeSchema);
|
Class<?> type = computeAttributeType(ctx, attributeSchema);
|
||||||
return new AutoAttributeColumn<>(name, type, attributeSchema.isHidden());
|
return new AutoAttributeColumn<>(name, type, attributeSchema.isHidden(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean hidden;
|
final boolean hidden;
|
||||||
@@ -528,7 +528,7 @@ public class ObjectTableModel extends AbstractQueryTableModel<ValueRow> {
|
|||||||
if (trace == null || query == null) {
|
if (trace == null || query == null) {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
TargetObjectSchema rootSchema = trace.getObjectManager().getRootSchema();
|
TraceObjectSchema rootSchema = trace.getObjectManager().getRootSchema();
|
||||||
if (rootSchema == null) {
|
if (rootSchema == null) {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
@@ -563,7 +563,7 @@ public class ObjectTableModel extends AbstractQueryTableModel<ValueRow> {
|
|||||||
if (trace == null) {
|
if (trace == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
TargetObjectSchema rootSchema = trace.getObjectManager().getRootSchema();
|
TraceObjectSchema rootSchema = trace.getObjectManager().getRootSchema();
|
||||||
if (rootSchema == null) {
|
if (rootSchema == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -573,7 +573,7 @@ public class ObjectTableModel extends AbstractQueryTableModel<ValueRow> {
|
|||||||
TraceValueObjectAttributeColumn<?> column =
|
TraceValueObjectAttributeColumn<?> column =
|
||||||
columnCache.computeIfAbsent(ColKey.fromSchema(ctx, as),
|
columnCache.computeIfAbsent(ColKey.fromSchema(ctx, as),
|
||||||
ck -> AutoAttributeColumn.fromSchema(ctx, as));
|
ck -> AutoAttributeColumn.fromSchema(ctx, as));
|
||||||
if (as.isHidden()) {
|
if (as.isHidden(as.getName())) {
|
||||||
descriptor.addHiddenColumn(column);
|
descriptor.addHiddenColumn(column);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -24,11 +24,15 @@ import docking.widgets.tree.GTreeLazyNode;
|
|||||||
import docking.widgets.tree.GTreeNode;
|
import docking.widgets.tree.GTreeNode;
|
||||||
import generic.theme.GIcon;
|
import generic.theme.GIcon;
|
||||||
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
|
||||||
import ghidra.dbg.target.*;
|
|
||||||
import ghidra.dbg.util.PathUtils.TargetObjectKeyComparator;
|
|
||||||
import ghidra.framework.model.*;
|
import ghidra.framework.model.*;
|
||||||
import ghidra.trace.model.*;
|
import ghidra.trace.model.*;
|
||||||
import ghidra.trace.model.target.*;
|
import ghidra.trace.model.breakpoint.TraceObjectBreakpointLocation;
|
||||||
|
import ghidra.trace.model.breakpoint.TraceObjectBreakpointSpec;
|
||||||
|
import ghidra.trace.model.target.TraceObject;
|
||||||
|
import ghidra.trace.model.target.TraceObjectValue;
|
||||||
|
import ghidra.trace.model.target.iface.*;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath.KeyComparator;
|
||||||
import ghidra.trace.util.TraceEvents;
|
import ghidra.trace.util.TraceEvents;
|
||||||
import ghidra.util.HTMLUtilities;
|
import ghidra.util.HTMLUtilities;
|
||||||
import ghidra.util.LockHold;
|
import ghidra.util.LockHold;
|
||||||
@@ -59,25 +63,26 @@ public class ObjectTreeModel implements DisplaysModified {
|
|||||||
|
|
||||||
protected boolean isEventValue(TraceObjectValue value) {
|
protected boolean isEventValue(TraceObjectValue value) {
|
||||||
if (!value.getParent()
|
if (!value.getParent()
|
||||||
.getTargetSchema()
|
.getSchema()
|
||||||
.getInterfaces()
|
.getInterfaces()
|
||||||
.contains(TargetEventScope.class)) {
|
.contains(TraceObjectEventScope.class)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!TargetEventScope.EVENT_OBJECT_ATTRIBUTE_NAME.equals(value.getEntryKey())) {
|
if (!TraceObjectEventScope.KEY_EVENT_THREAD.equals(value.getEntryKey())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isEnabledValue(TraceObjectValue value) {
|
protected boolean isEnabledValue(TraceObjectValue value) {
|
||||||
Set<Class<? extends TargetObject>> interfaces =
|
Set<Class<? extends TraceObjectInterface>> interfaces =
|
||||||
value.getParent().getTargetSchema().getInterfaces();
|
value.getParent().getSchema().getInterfaces();
|
||||||
if (!interfaces.contains(TargetBreakpointSpec.class) &&
|
if (!interfaces.contains(TraceObjectBreakpointSpec.class) &&
|
||||||
!interfaces.contains(TargetBreakpointLocation.class)) {
|
!interfaces.contains(TraceObjectBreakpointLocation.class) &&
|
||||||
|
!interfaces.contains(TraceObjectTogglable.class)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!TargetBreakpointSpec.ENABLED_ATTRIBUTE_NAME.equals(value.getEntryKey())) {
|
if (!TraceObjectTogglable.KEY_ENABLED.equals(value.getEntryKey())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -257,7 +262,7 @@ public class ObjectTreeModel implements DisplaysModified {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int c;
|
int c;
|
||||||
c = TargetObjectKeyComparator.CHILD.compare(this.getValue().getEntryKey(),
|
c = KeyComparator.CHILD.compare(this.getValue().getEntryKey(),
|
||||||
that.getValue().getEntryKey());
|
that.getValue().getEntryKey());
|
||||||
if (c != 0) {
|
if (c != 0) {
|
||||||
return c;
|
return c;
|
||||||
@@ -297,11 +302,11 @@ public class ObjectTreeModel implements DisplaysModified {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbstractNode getNode(TraceObjectKeyPath p, int pos) {
|
protected AbstractNode getNode(KeyPath p, int pos) {
|
||||||
if (pos >= p.getKeyList().size()) {
|
if (pos >= p.size()) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
String key = p.getKeyList().get(pos);
|
String key = p.key(pos);
|
||||||
AbstractNode matched = children().stream()
|
AbstractNode matched = children().stream()
|
||||||
.map(c -> (AbstractNode) c)
|
.map(c -> (AbstractNode) c)
|
||||||
.filter(c -> key.equals(c.getValue().getEntryKey()))
|
.filter(c -> key.equals(c.getValue().getEntryKey()))
|
||||||
@@ -313,7 +318,7 @@ public class ObjectTreeModel implements DisplaysModified {
|
|||||||
return matched.getNode(p, pos + 1);
|
return matched.getNode(p, pos + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractNode getNode(TraceObjectKeyPath p) {
|
public AbstractNode getNode(KeyPath p) {
|
||||||
return getNode(p, 0);
|
return getNode(p, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -575,7 +580,7 @@ public class ObjectTreeModel implements DisplaysModified {
|
|||||||
if (parentValue == null) {
|
if (parentValue == null) {
|
||||||
return super.getIcon(expanded);
|
return super.getIcon(expanded);
|
||||||
}
|
}
|
||||||
if (!parentValue.getParent().getTargetSchema().isCanonicalContainer()) {
|
if (!parentValue.getParent().getSchema().isCanonicalContainer()) {
|
||||||
return super.getIcon(expanded);
|
return super.getIcon(expanded);
|
||||||
}
|
}
|
||||||
if (!isOnEventPath(object)) {
|
if (!isOnEventPath(object)) {
|
||||||
@@ -661,7 +666,8 @@ public class ObjectTreeModel implements DisplaysModified {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected TraceObject getEventObject(TraceObject object) {
|
protected TraceObject getEventObject(TraceObject object) {
|
||||||
TraceObject scope = object.queryCanonicalAncestorsTargetInterface(TargetEventScope.class)
|
TraceObject scope = object
|
||||||
|
.findCanonicalAncestorsInterface(TraceObjectEventScope.class)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
if (scope == null) {
|
if (scope == null) {
|
||||||
@@ -671,7 +677,7 @@ public class ObjectTreeModel implements DisplaysModified {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
TraceObjectValue eventValue =
|
TraceObjectValue eventValue =
|
||||||
scope.getAttribute(snap, TargetEventScope.EVENT_OBJECT_ATTRIBUTE_NAME);
|
scope.getAttribute(snap, TraceObjectEventScope.KEY_EVENT_THREAD);
|
||||||
if (eventValue == null || !eventValue.isObject()) {
|
if (eventValue == null || !eventValue.isObject()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -698,7 +704,7 @@ public class ObjectTreeModel implements DisplaysModified {
|
|||||||
if (type.contains("Breakpoint")) {
|
if (type.contains("Breakpoint")) {
|
||||||
TraceObject object = edge.getChild();
|
TraceObject object = edge.getChild();
|
||||||
TraceObjectValue en =
|
TraceObjectValue en =
|
||||||
object.getAttribute(snap, TargetBreakpointSpec.ENABLED_ATTRIBUTE_NAME);
|
object.getAttribute(snap, TraceObjectTogglable.KEY_ENABLED);
|
||||||
// includes true or non-boolean values
|
// includes true or non-boolean values
|
||||||
if (en == null || !Objects.equals(false, en.getValue())) {
|
if (en == null || !Objects.equals(false, en.getValue())) {
|
||||||
return DebuggerResources.ICON_SET_BREAKPOINT;
|
return DebuggerResources.ICON_SET_BREAKPOINT;
|
||||||
@@ -941,7 +947,7 @@ public class ObjectTreeModel implements DisplaysModified {
|
|||||||
return showMethods;
|
return showMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractNode getNode(TraceObjectKeyPath p) {
|
public AbstractNode getNode(KeyPath p) {
|
||||||
return root.getNode(p);
|
return root.getNode(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -26,10 +26,10 @@ import javax.swing.table.TableColumn;
|
|||||||
import docking.widgets.table.GTableColumnModel;
|
import docking.widgets.table.GTableColumnModel;
|
||||||
import docking.widgets.table.GTableTextCellEditor;
|
import docking.widgets.table.GTableTextCellEditor;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.*;
|
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.*;
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.framework.plugintool.Plugin;
|
import ghidra.framework.plugintool.Plugin;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||||
|
|
||||||
public class ObjectsTablePanel extends AbstractQueryTablePanel<ValueRow, ObjectTableModel> {
|
public class ObjectsTablePanel extends AbstractQueryTablePanel<ValueRow, ObjectTableModel> {
|
||||||
|
|
||||||
@@ -91,11 +91,11 @@ public class ObjectsTablePanel extends AbstractQueryTablePanel<ValueRow, ObjectT
|
|||||||
if (query == null) {
|
if (query == null) {
|
||||||
return DEFAULT_PREF_KEY;
|
return DEFAULT_PREF_KEY;
|
||||||
}
|
}
|
||||||
List<TargetObjectSchema> schemas = query.computeSchemas(trace);
|
List<TraceObjectSchema> schemas = query.computeSchemas(trace);
|
||||||
if (schemas.isEmpty()) {
|
if (schemas.isEmpty()) {
|
||||||
return DEFAULT_PREF_KEY;
|
return DEFAULT_PREF_KEY;
|
||||||
}
|
}
|
||||||
TargetObjectSchema rootSchema = trace.getObjectManager().getRootSchema();
|
TraceObjectSchema rootSchema = trace.getObjectManager().getRootSchema();
|
||||||
if (rootSchema == null) {
|
if (rootSchema == null) {
|
||||||
return DEFAULT_PREF_KEY;
|
return DEFAULT_PREF_KEY;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -37,6 +37,7 @@ import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
|||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.target.*;
|
import ghidra.trace.model.target.*;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
import ghidra.util.Swing;
|
import ghidra.util.Swing;
|
||||||
|
|
||||||
public class ObjectsTreePanel extends JPanel {
|
public class ObjectsTreePanel extends JPanel {
|
||||||
@@ -173,7 +174,7 @@ public class ObjectsTreePanel extends JPanel {
|
|||||||
protected final ObjectGTree tree;
|
protected final ObjectGTree tree;
|
||||||
|
|
||||||
protected boolean showing = false;
|
protected boolean showing = false;
|
||||||
protected Set<TraceObjectKeyPath> savedSelection = null;
|
protected Set<KeyPath> savedSelection = null;
|
||||||
protected DebuggerCoordinates current = DebuggerCoordinates.NOWHERE;
|
protected DebuggerCoordinates current = DebuggerCoordinates.NOWHERE;
|
||||||
protected DebuggerCoordinates previous = DebuggerCoordinates.NOWHERE;
|
protected DebuggerCoordinates previous = DebuggerCoordinates.NOWHERE;
|
||||||
protected boolean limitToSnap = true;
|
protected boolean limitToSnap = true;
|
||||||
@@ -264,13 +265,13 @@ public class ObjectsTreePanel extends JPanel {
|
|||||||
// Repaint for bold current path is already going to happen
|
// Repaint for bold current path is already going to happen
|
||||||
|
|
||||||
// Repaint is not enough, as node sizes may change
|
// Repaint is not enough, as node sizes may change
|
||||||
for (TraceObjectKeyPath path = current.getPath(); path != null; path = path.parent()) {
|
for (KeyPath path = current.getPath(); path != null; path = path.parent()) {
|
||||||
AbstractNode node = treeModel.getNode(path);
|
AbstractNode node = treeModel.getNode(path);
|
||||||
if (node != null) {
|
if (node != null) {
|
||||||
node.fireNodeChanged();
|
node.fireNodeChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (TraceObjectKeyPath path = previous.getPath(); path != null; path = path.parent()) {
|
for (KeyPath path = previous.getPath(); path != null; path = path.parent()) {
|
||||||
AbstractNode node = treeModel.getNode(path);
|
AbstractNode node = treeModel.getNode(path);
|
||||||
if (node != null) {
|
if (node != null) {
|
||||||
node.fireNodeChanged();
|
node.fireNodeChanged();
|
||||||
@@ -421,14 +422,14 @@ public class ObjectsTreePanel extends JPanel {
|
|||||||
return getItemFromPath(tree.getSelectionPath());
|
return getItemFromPath(tree.getSelectionPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractNode getNode(TraceObjectKeyPath path) {
|
public AbstractNode getNode(KeyPath path) {
|
||||||
return treeModel.getNode(path);
|
return treeModel.getNode(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectedKeyPaths(Collection<TraceObjectKeyPath> keyPaths, EventOrigin origin) {
|
public void setSelectedKeyPaths(Collection<KeyPath> keyPaths, EventOrigin origin) {
|
||||||
savedSelection = keyPaths instanceof Set<TraceObjectKeyPath> s ? s : Set.copyOf(keyPaths);
|
savedSelection = keyPaths instanceof Set<KeyPath> s ? s : Set.copyOf(keyPaths);
|
||||||
List<TreePath> treePaths = new ArrayList<>();
|
List<TreePath> treePaths = new ArrayList<>();
|
||||||
for (TraceObjectKeyPath path : keyPaths) {
|
for (KeyPath path : keyPaths) {
|
||||||
AbstractNode node = getNode(path);
|
AbstractNode node = getNode(path);
|
||||||
if (node != null) {
|
if (node != null) {
|
||||||
treePaths.add(node.getTreePath());
|
treePaths.add(node.getTreePath());
|
||||||
@@ -437,12 +438,12 @@ public class ObjectsTreePanel extends JPanel {
|
|||||||
tree.setSelectionPaths(treePaths.toArray(TreePath[]::new), origin);
|
tree.setSelectionPaths(treePaths.toArray(TreePath[]::new), origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<TraceObjectKeyPath> getSelectedKeyPaths() {
|
public Set<KeyPath> getSelectedKeyPaths() {
|
||||||
Set<TraceObjectKeyPath> result = new HashSet<>();
|
Set<KeyPath> result = new HashSet<>();
|
||||||
for (AbstractNode node : getSelectedItems()) {
|
for (AbstractNode node : getSelectedItems()) {
|
||||||
TraceObjectValue value = node.getValue();
|
TraceObjectValue value = node.getValue();
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
result.add(TraceObjectKeyPath.of());
|
result.add(KeyPath.of());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result.add(value.getCanonicalPath());
|
result.add(value.getCanonicalPath());
|
||||||
@@ -451,7 +452,7 @@ public class ObjectsTreePanel extends JPanel {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectedKeyPaths(Collection<TraceObjectKeyPath> keyPaths) {
|
public void setSelectedKeyPaths(Collection<KeyPath> keyPaths) {
|
||||||
setSelectedKeyPaths(keyPaths, EventOrigin.API_GENERATED);
|
setSelectedKeyPaths(keyPaths, EventOrigin.API_GENERATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -16,7 +16,8 @@
|
|||||||
package ghidra.app.plugin.core.debug.gui.model;
|
package ghidra.app.plugin.core.debug.gui.model;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.util.*;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import docking.widgets.table.RangeCursorTableHeaderRenderer.SeekListener;
|
import docking.widgets.table.RangeCursorTableHeaderRenderer.SeekListener;
|
||||||
@@ -27,12 +28,13 @@ import ghidra.framework.plugintool.Plugin;
|
|||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.target.*;
|
import ghidra.trace.model.target.*;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
|
||||||
public class PathTableModel extends AbstractQueryTableModel<PathRow> {
|
public class PathTableModel extends AbstractQueryTableModel<PathRow> {
|
||||||
record Seen(List<String> path, long minSnap) {
|
record Seen(KeyPath path, long minSnap) {
|
||||||
static Seen forPath(TraceObjectValPath path) {
|
static Seen forPath(TraceObjectValPath valPath) {
|
||||||
TraceObjectValue last = path.getLastEntry();
|
TraceObjectValue last = valPath.getLastEntry();
|
||||||
return new Seen(path.getKeyList(), last == null ? 0 : last.getMinSnap());
|
return new Seen(valPath.getPath(), last == null ? 0 : last.getMinSnap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -17,7 +17,6 @@ package ghidra.app.plugin.core.debug.gui.model.columns;
|
|||||||
|
|
||||||
import docking.widgets.table.AbstractDynamicTableColumn;
|
import docking.widgets.table.AbstractDynamicTableColumn;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.PathTableModel.PathRow;
|
import ghidra.app.plugin.core.debug.gui.model.PathTableModel.PathRow;
|
||||||
import ghidra.dbg.util.PathUtils;
|
|
||||||
import ghidra.docking.settings.Settings;
|
import ghidra.docking.settings.Settings;
|
||||||
import ghidra.framework.plugintool.ServiceProvider;
|
import ghidra.framework.plugintool.ServiceProvider;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
@@ -39,6 +38,6 @@ public class TracePathStringColumn extends AbstractDynamicTableColumn<PathRow, S
|
|||||||
@Override
|
@Override
|
||||||
public String getValue(PathRow rowObject, Settings settings, Trace data,
|
public String getValue(PathRow rowObject, Settings settings, Trace data,
|
||||||
ServiceProvider serviceProvider) throws IllegalArgumentException {
|
ServiceProvider serviceProvider) throws IllegalArgumentException {
|
||||||
return PathUtils.toString(rowObject.getPath().getKeyList());
|
return rowObject.getPath().getPath().toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -19,10 +19,10 @@ import java.util.Comparator;
|
|||||||
|
|
||||||
import docking.widgets.table.AbstractDynamicTableColumn;
|
import docking.widgets.table.AbstractDynamicTableColumn;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
||||||
import ghidra.dbg.util.PathUtils.TargetObjectKeyComparator;
|
|
||||||
import ghidra.docking.settings.Settings;
|
import ghidra.docking.settings.Settings;
|
||||||
import ghidra.framework.plugintool.ServiceProvider;
|
import ghidra.framework.plugintool.ServiceProvider;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath.KeyComparator;
|
||||||
import ghidra.util.table.column.GColumnRenderer;
|
import ghidra.util.table.column.GColumnRenderer;
|
||||||
|
|
||||||
public class TraceValueKeyColumn extends AbstractDynamicTableColumn<ValueRow, String, Trace> {
|
public class TraceValueKeyColumn extends AbstractDynamicTableColumn<ValueRow, String, Trace> {
|
||||||
@@ -46,6 +46,6 @@ public class TraceValueKeyColumn extends AbstractDynamicTableColumn<ValueRow, St
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Comparator<String> getComparator() {
|
public Comparator<String> getComparator() {
|
||||||
return TargetObjectKeyComparator.CHILD;
|
return KeyComparator.CHILD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -17,16 +17,10 @@ package ghidra.app.plugin.core.debug.gui.model.columns;
|
|||||||
|
|
||||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueProperty;
|
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueProperty;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
||||||
import ghidra.dbg.target.TargetAttacher.TargetAttachKindSet;
|
import ghidra.trace.model.TraceExecutionState;
|
||||||
import ghidra.dbg.target.TargetBreakpointSpecContainer.TargetBreakpointKindSet;
|
import ghidra.trace.model.target.schema.SchemaContext;
|
||||||
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||||
import ghidra.dbg.target.TargetMethod.TargetParameterMap;
|
import ghidra.trace.model.target.schema.TraceObjectSchema.AttributeSchema;
|
||||||
import ghidra.dbg.target.TargetObject;
|
|
||||||
import ghidra.dbg.target.TargetSteppable.TargetStepKindSet;
|
|
||||||
import ghidra.dbg.target.schema.SchemaContext;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.AttributeSchema;
|
|
||||||
import ghidra.trace.model.target.TraceObject;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A column which displays the object's value for a given attribute
|
* A column which displays the object's value for a given attribute
|
||||||
@@ -44,24 +38,9 @@ public class TraceValueObjectAttributeColumn<T> extends TraceValueObjectProperty
|
|||||||
*/
|
*/
|
||||||
public static Class<?> computeAttributeType(SchemaContext ctx,
|
public static Class<?> computeAttributeType(SchemaContext ctx,
|
||||||
AttributeSchema attributeSchema) {
|
AttributeSchema attributeSchema) {
|
||||||
TargetObjectSchema schema = ctx.getSchema(attributeSchema.getSchema());
|
TraceObjectSchema schema = ctx.getSchema(attributeSchema.getSchema());
|
||||||
Class<?> type = schema.getType();
|
Class<?> type = schema.getType();
|
||||||
if (type == TargetObject.class) {
|
if (type == TraceExecutionState.class) {
|
||||||
return TraceObject.class;
|
|
||||||
}
|
|
||||||
if (type == TargetExecutionState.class) {
|
|
||||||
return String.class;
|
|
||||||
}
|
|
||||||
if (type == TargetParameterMap.class) {
|
|
||||||
return String.class;
|
|
||||||
}
|
|
||||||
if (type == TargetAttachKindSet.class) {
|
|
||||||
return String.class;
|
|
||||||
}
|
|
||||||
if (type == TargetBreakpointKindSet.class) {
|
|
||||||
return String.class;
|
|
||||||
}
|
|
||||||
if (type == TargetStepKindSet.class) {
|
|
||||||
return String.class;
|
return String.class;
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
|
|||||||
@@ -15,7 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.gui.modules;
|
package ghidra.app.plugin.core.debug.gui.modules;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.swing.event.ListSelectionEvent;
|
import javax.swing.event.ListSelectionEvent;
|
||||||
|
|
||||||
@@ -25,9 +26,6 @@ import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueAttribute;
|
|||||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.columns.*;
|
import ghidra.app.plugin.core.debug.gui.model.columns.*;
|
||||||
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
||||||
import ghidra.dbg.target.TargetModule;
|
|
||||||
import ghidra.dbg.target.TargetProcess;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.debug.api.model.DebuggerObjectActionContext;
|
import ghidra.debug.api.model.DebuggerObjectActionContext;
|
||||||
import ghidra.docking.settings.Settings;
|
import ghidra.docking.settings.Settings;
|
||||||
import ghidra.framework.plugintool.Plugin;
|
import ghidra.framework.plugintool.Plugin;
|
||||||
@@ -38,12 +36,15 @@ import ghidra.trace.model.Trace;
|
|||||||
import ghidra.trace.model.modules.*;
|
import ghidra.trace.model.modules.*;
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
import ghidra.trace.model.target.TraceObjectValue;
|
import ghidra.trace.model.target.TraceObjectValue;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||||
|
import ghidra.trace.model.thread.TraceObjectProcess;
|
||||||
|
|
||||||
public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceObjectModule> {
|
public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceObjectModule> {
|
||||||
|
|
||||||
private static class ModuleBaseColumn extends AbstractTraceValueObjectAddressColumn {
|
private static class ModuleBaseColumn extends AbstractTraceValueObjectAddressColumn {
|
||||||
public ModuleBaseColumn() {
|
public ModuleBaseColumn() {
|
||||||
super(TargetModule.RANGE_ATTRIBUTE_NAME);
|
super(TraceObjectModule.KEY_RANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -59,7 +60,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||||||
|
|
||||||
private static class ModuleMaxColumn extends AbstractTraceValueObjectAddressColumn {
|
private static class ModuleMaxColumn extends AbstractTraceValueObjectAddressColumn {
|
||||||
public ModuleMaxColumn() {
|
public ModuleMaxColumn() {
|
||||||
super(TargetModule.RANGE_ATTRIBUTE_NAME);
|
super(TraceObjectModule.KEY_RANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -75,7 +76,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||||||
|
|
||||||
private static class ModuleNameColumn extends TraceValueObjectAttributeColumn<String> {
|
private static class ModuleNameColumn extends TraceValueObjectAttributeColumn<String> {
|
||||||
public ModuleNameColumn() {
|
public ModuleNameColumn() {
|
||||||
super(TargetModule.MODULE_NAME_ATTRIBUTE_NAME, String.class);
|
super(TraceObjectModule.KEY_MODULE_NAME, String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -97,7 +98,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
ValueAttribute<AddressRange> attr =
|
ValueAttribute<AddressRange> attr =
|
||||||
rowObject.getAttribute(TargetModule.RANGE_ATTRIBUTE_NAME, AddressRange.class);
|
rowObject.getAttribute(TraceObjectModule.KEY_RANGE, AddressRange.class);
|
||||||
if (attr == null) {
|
if (attr == null) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -130,7 +131,7 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||||||
|
|
||||||
private static class ModuleLengthColumn extends AbstractTraceValueObjectLengthColumn {
|
private static class ModuleLengthColumn extends AbstractTraceValueObjectLengthColumn {
|
||||||
public ModuleLengthColumn() {
|
public ModuleLengthColumn() {
|
||||||
super(TargetModule.RANGE_ATTRIBUTE_NAME);
|
super(TraceObjectModule.KEY_RANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -219,9 +220,9 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static ModelQuery successorModules(TargetObjectSchema rootSchema, List<String> path) {
|
protected static ModelQuery successorModules(TraceObjectSchema rootSchema, KeyPath path) {
|
||||||
TargetObjectSchema schema = rootSchema.getSuccessorSchema(path);
|
TraceObjectSchema schema = rootSchema.getSuccessorSchema(path);
|
||||||
return new ModelQuery(schema.searchFor(TargetModule.class, path, true));
|
return new ModelQuery(schema.searchFor(TraceObjectModule.class, path, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private final DebuggerModulesProvider provider;
|
private final DebuggerModulesProvider provider;
|
||||||
@@ -238,25 +239,24 @@ public class DebuggerModulesPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ModelQuery computeQuery(TraceObject object) {
|
protected ModelQuery computeQuery(TraceObject object) {
|
||||||
TargetObjectSchema rootSchema = object.getRoot().getTargetSchema();
|
TraceObjectSchema rootSchema = object.getRoot().getSchema();
|
||||||
List<String> seedPath = object.getCanonicalPath().getKeyList();
|
KeyPath seedPath = object.getCanonicalPath();
|
||||||
List<String> processPath = rootSchema.searchForAncestor(TargetProcess.class, seedPath);
|
KeyPath processPath = rootSchema.searchForAncestor(TraceObjectProcess.class, seedPath);
|
||||||
if (processPath != null) {
|
if (processPath != null) {
|
||||||
ModelQuery result = successorModules(rootSchema, processPath);
|
ModelQuery result = successorModules(rootSchema, processPath);
|
||||||
if (!result.isEmpty()) {
|
if (!result.isEmpty()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<String> containerPath =
|
KeyPath containerPath =
|
||||||
rootSchema.searchForSuitableContainer(TargetModule.class, seedPath);
|
rootSchema.searchForSuitableContainer(TraceObjectModule.class, seedPath);
|
||||||
|
|
||||||
if (containerPath != null) {
|
if (containerPath != null) {
|
||||||
ModelQuery result = successorModules(rootSchema, containerPath);
|
ModelQuery result = successorModules(rootSchema, containerPath);
|
||||||
if (!result.isEmpty()) {
|
if (!result.isEmpty()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return successorModules(rootSchema, List.of());
|
return successorModules(rootSchema, KeyPath.ROOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectedModules(Set<TraceModule> sel) {
|
public void setSelectedModules(Set<TraceModule> sel) {
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.gui.modules;
|
package ghidra.app.plugin.core.debug.gui.modules;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -26,9 +25,6 @@ import docking.widgets.table.TableFilter;
|
|||||||
import ghidra.app.plugin.core.debug.gui.model.*;
|
import ghidra.app.plugin.core.debug.gui.model.*;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.*;
|
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.*;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.columns.*;
|
import ghidra.app.plugin.core.debug.gui.model.columns.*;
|
||||||
import ghidra.dbg.target.*;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.dbg.util.PathUtils;
|
|
||||||
import ghidra.docking.settings.Settings;
|
import ghidra.docking.settings.Settings;
|
||||||
import ghidra.framework.plugintool.Plugin;
|
import ghidra.framework.plugintool.Plugin;
|
||||||
import ghidra.framework.plugintool.ServiceProvider;
|
import ghidra.framework.plugintool.ServiceProvider;
|
||||||
@@ -36,16 +32,20 @@ import ghidra.program.model.address.Address;
|
|||||||
import ghidra.program.model.address.AddressRange;
|
import ghidra.program.model.address.AddressRange;
|
||||||
import ghidra.trace.database.module.TraceObjectSection;
|
import ghidra.trace.database.module.TraceObjectSection;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.modules.TraceObjectModule;
|
||||||
import ghidra.trace.model.modules.TraceSection;
|
import ghidra.trace.model.modules.TraceSection;
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
import ghidra.trace.model.target.TraceObjectValue;
|
import ghidra.trace.model.target.TraceObjectValue;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||||
|
import ghidra.trace.model.thread.TraceObjectProcess;
|
||||||
|
|
||||||
public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceObjectSection> {
|
public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceObjectSection> {
|
||||||
|
|
||||||
private static class SectionStartColumn extends AbstractTraceValueObjectAddressColumn {
|
private static class SectionStartColumn extends AbstractTraceValueObjectAddressColumn {
|
||||||
|
|
||||||
public SectionStartColumn() {
|
public SectionStartColumn() {
|
||||||
super(TargetSection.RANGE_ATTRIBUTE_NAME);
|
super(TraceObjectSection.KEY_RANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -61,7 +61,7 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
|
|||||||
|
|
||||||
private static class SectionEndColumn extends AbstractTraceValueObjectAddressColumn {
|
private static class SectionEndColumn extends AbstractTraceValueObjectAddressColumn {
|
||||||
public SectionEndColumn() {
|
public SectionEndColumn() {
|
||||||
super(TargetSection.RANGE_ATTRIBUTE_NAME);
|
super(TraceObjectSection.KEY_RANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -84,11 +84,7 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
|
|||||||
@Override
|
@Override
|
||||||
public String getValue(ValueRow rowObject, Settings settings, Trace data,
|
public String getValue(ValueRow rowObject, Settings settings, Trace data,
|
||||||
ServiceProvider serviceProvider) throws IllegalArgumentException {
|
ServiceProvider serviceProvider) throws IllegalArgumentException {
|
||||||
String key = rowObject.getValue().getEntryKey();
|
return KeyPath.parseIfIndex(rowObject.getValue().getEntryKey());
|
||||||
if (PathUtils.isIndex(key)) {
|
|
||||||
return PathUtils.parseIndex(key);
|
|
||||||
}
|
|
||||||
return key;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +121,7 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
TraceObjectValue nameEntry = module.getAttribute(row.currentSnap(),
|
TraceObjectValue nameEntry = module.getAttribute(row.currentSnap(),
|
||||||
TargetModule.MODULE_NAME_ATTRIBUTE_NAME);
|
TraceObjectModule.KEY_MODULE_NAME);
|
||||||
if (nameEntry == null) {
|
if (nameEntry == null) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -137,7 +133,7 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
|
|||||||
|
|
||||||
private static class SectionLengthColumn extends AbstractTraceValueObjectLengthColumn {
|
private static class SectionLengthColumn extends AbstractTraceValueObjectLengthColumn {
|
||||||
public SectionLengthColumn() {
|
public SectionLengthColumn() {
|
||||||
super(TargetSection.RANGE_ATTRIBUTE_NAME);
|
super(TraceObjectSection.KEY_RANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -166,21 +162,20 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
|
|||||||
|
|
||||||
private static TraceObject getModule(ValueRow row) {
|
private static TraceObject getModule(ValueRow row) {
|
||||||
TraceObjectValue moduleEntry =
|
TraceObjectValue moduleEntry =
|
||||||
row.getAttributeEntry(TargetSection.MODULE_ATTRIBUTE_NAME);
|
row.getAttributeEntry(TraceObjectSection.KEY_MODULE);
|
||||||
if (moduleEntry != null && moduleEntry.isObject()) {
|
if (moduleEntry != null && moduleEntry.isObject()) {
|
||||||
return moduleEntry.getChild();
|
return moduleEntry.getChild();
|
||||||
}
|
}
|
||||||
return row.getValue()
|
return row.getValue()
|
||||||
.getChild()
|
.getChild()
|
||||||
.queryCanonicalAncestorsTargetInterface(TargetModule.class)
|
.findCanonicalAncestorsInterface(TraceObjectModule.class)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static ModelQuery successorSections(TargetObjectSchema rootSchema,
|
protected static ModelQuery successorSections(TraceObjectSchema rootSchema, KeyPath path) {
|
||||||
List<String> path) {
|
TraceObjectSchema schema = rootSchema.getSuccessorSchema(path);
|
||||||
TargetObjectSchema schema = rootSchema.getSuccessorSchema(path);
|
return new ModelQuery(schema.searchFor(TraceObjectSection.class, path, true));
|
||||||
return new ModelQuery(schema.searchFor(TargetSection.class, path, true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SectionsBySelectedModulesTableFilter implements TableFilter<ValueRow> {
|
private class SectionsBySelectedModulesTableFilter implements TableFilter<ValueRow> {
|
||||||
@@ -217,9 +212,9 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ModelQuery computeQuery(TraceObject object) {
|
protected ModelQuery computeQuery(TraceObject object) {
|
||||||
TargetObjectSchema rootSchema = object.getRoot().getTargetSchema();
|
TraceObjectSchema rootSchema = object.getRoot().getSchema();
|
||||||
List<String> seedPath = object.getCanonicalPath().getKeyList();
|
KeyPath seedPath = object.getCanonicalPath();
|
||||||
List<String> processPath = rootSchema.searchForAncestor(TargetProcess.class, seedPath);
|
KeyPath processPath = rootSchema.searchForAncestor(TraceObjectProcess.class, seedPath);
|
||||||
if (processPath != null) {
|
if (processPath != null) {
|
||||||
ModelQuery result = successorSections(rootSchema, processPath);
|
ModelQuery result = successorSections(rootSchema, processPath);
|
||||||
if (!result.isEmpty()) {
|
if (!result.isEmpty()) {
|
||||||
@@ -227,8 +222,8 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Yes, anchor on the *module* container when searching for sections
|
// Yes, anchor on the *module* container when searching for sections
|
||||||
List<String> containerPath =
|
KeyPath containerPath =
|
||||||
rootSchema.searchForSuitableContainer(TargetModule.class, seedPath);
|
rootSchema.searchForSuitableContainer(TraceObjectModule.class, seedPath);
|
||||||
|
|
||||||
if (containerPath != null) {
|
if (containerPath != null) {
|
||||||
ModelQuery result = successorSections(rootSchema, containerPath);
|
ModelQuery result = successorSections(rootSchema, containerPath);
|
||||||
@@ -236,7 +231,7 @@ public class DebuggerSectionsPanel extends AbstractObjectsTableBasedPanel<TraceO
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return successorSections(rootSchema, List.of());
|
return successorSections(rootSchema, KeyPath.ROOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFilteredBySelectedModules(boolean filtered) {
|
public void setFilteredBySelectedModules(boolean filtered) {
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ import java.util.Set;
|
|||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
|
|
||||||
import ghidra.app.plugin.core.debug.gui.AbstractDebuggerParameterDialog;
|
import ghidra.app.plugin.core.debug.gui.AbstractDebuggerParameterDialog;
|
||||||
import ghidra.dbg.target.TargetMethod;
|
|
||||||
import ghidra.dbg.target.TargetMethod.ParameterDescription;
|
|
||||||
import ghidra.debug.api.ValStr;
|
import ghidra.debug.api.ValStr;
|
||||||
import ghidra.framework.options.SaveState;
|
import ghidra.framework.options.SaveState;
|
||||||
import ghidra.framework.plugintool.AutoConfigState.ConfigStateField;
|
import ghidra.framework.plugintool.AutoConfigState.ConfigStateField;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
|
import ghidra.trace.model.target.iface.TraceObjectMethod;
|
||||||
|
import ghidra.trace.model.target.iface.TraceObjectMethod.ParameterDescription;
|
||||||
|
|
||||||
@Deprecated(forRemoval = true, since = "11.3")
|
@Deprecated(forRemoval = true, since = "11.3")
|
||||||
public class DebuggerMethodInvocationDialog
|
public class DebuggerMethodInvocationDialog
|
||||||
@@ -71,7 +71,7 @@ public class DebuggerMethodInvocationDialog
|
|||||||
protected Map<String, ValStr<?>> validateArguments(
|
protected Map<String, ValStr<?>> validateArguments(
|
||||||
Map<String, ParameterDescription<?>> parameters, Map<String, ValStr<?>> arguments) {
|
Map<String, ParameterDescription<?>> parameters, Map<String, ValStr<?>> arguments) {
|
||||||
Map<String, ?> args = ValStr.toPlainMap(arguments);
|
Map<String, ?> args = ValStr.toPlainMap(arguments);
|
||||||
return ValStr.fromPlainMap(TargetMethod.validateArguments(parameters, args, false));
|
return ValStr.fromPlainMap(TraceObjectMethod.validateArguments(parameters, args, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ import ghidra.app.services.DebuggerControlService.StateEditor;
|
|||||||
import ghidra.async.AsyncLazyValue;
|
import ghidra.async.AsyncLazyValue;
|
||||||
import ghidra.async.AsyncUtils;
|
import ghidra.async.AsyncUtils;
|
||||||
import ghidra.base.widgets.table.DataTypeTableCellEditor;
|
import ghidra.base.widgets.table.DataTypeTableCellEditor;
|
||||||
import ghidra.dbg.error.DebuggerModelAccessException;
|
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.docking.settings.*;
|
import ghidra.docking.settings.*;
|
||||||
@@ -1318,7 +1317,7 @@ public class DebuggerRegistersProvider extends ComponentProviderAdapter
|
|||||||
|
|
||||||
private void reportError(String title, String message, Throwable ex) {
|
private void reportError(String title, String message, Throwable ex) {
|
||||||
plugin.getTool().setStatusInfo(message + ": " + ex.getMessage());
|
plugin.getTool().setStatusInfo(message + ": " + ex.getMessage());
|
||||||
if (title != null && !(ex instanceof DebuggerModelAccessException)) {
|
if (title != null) {
|
||||||
Msg.showError(this, getComponent(), title, message, ex);
|
Msg.showError(this, getComponent(), title, message, ex);
|
||||||
}
|
}
|
||||||
else if (consoleService != null) {
|
else if (consoleService != null) {
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.gui.stack;
|
package ghidra.app.plugin.core.debug.gui.stack;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
@@ -27,10 +26,6 @@ import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.*;
|
|||||||
import ghidra.app.plugin.core.debug.gui.model.columns.*;
|
import ghidra.app.plugin.core.debug.gui.model.columns.*;
|
||||||
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
||||||
import ghidra.app.services.DebuggerTraceManagerService;
|
import ghidra.app.services.DebuggerTraceManagerService;
|
||||||
import ghidra.dbg.target.TargetStack;
|
|
||||||
import ghidra.dbg.target.TargetStackFrame;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.dbg.util.PathMatcher;
|
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.docking.settings.Settings;
|
import ghidra.docking.settings.Settings;
|
||||||
import ghidra.framework.plugintool.Plugin;
|
import ghidra.framework.plugintool.Plugin;
|
||||||
@@ -39,9 +34,13 @@ import ghidra.framework.plugintool.annotation.AutoServiceConsumed;
|
|||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.stack.TraceObjectStack;
|
||||||
import ghidra.trace.model.stack.TraceObjectStackFrame;
|
import ghidra.trace.model.stack.TraceObjectStackFrame;
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
import ghidra.trace.model.target.TraceObjectValue;
|
import ghidra.trace.model.target.TraceObjectValue;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
import ghidra.trace.model.target.path.PathMatcher;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||||
|
|
||||||
public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObjectStackFrame>
|
public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObjectStackFrame>
|
||||||
implements ListSelectionListener {
|
implements ListSelectionListener {
|
||||||
@@ -60,7 +59,7 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObje
|
|||||||
|
|
||||||
private static class FramePcColumn extends TraceValueObjectAttributeColumn<Address> {
|
private static class FramePcColumn extends TraceValueObjectAttributeColumn<Address> {
|
||||||
public FramePcColumn() {
|
public FramePcColumn() {
|
||||||
super(TargetStackFrame.PC_ATTRIBUTE_NAME, Address.class);
|
super(TraceObjectStackFrame.KEY_PC, Address.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -73,7 +72,7 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObje
|
|||||||
if (!(row.getValue().getValue() instanceof TraceObject object)) {
|
if (!(row.getValue().getValue() instanceof TraceObject object)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
TraceObjectValue attrPc = object.getAttribute(snap, TargetStackFrame.PC_ATTRIBUTE_NAME);
|
TraceObjectValue attrPc = object.getAttribute(snap, TraceObjectStackFrame.KEY_PC);
|
||||||
if (attrPc == null || !(attrPc.getValue() instanceof Address pc)) {
|
if (attrPc == null || !(attrPc.getValue() instanceof Address pc)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -189,14 +188,14 @@ public class DebuggerStackPanel extends AbstractObjectsTableBasedPanel<TraceObje
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ModelQuery computeQuery(TraceObject object) {
|
protected ModelQuery computeQuery(TraceObject object) {
|
||||||
TargetObjectSchema rootSchema = object.getRoot().getTargetSchema();
|
TraceObjectSchema rootSchema = object.getRoot().getSchema();
|
||||||
List<String> stackPath = rootSchema
|
KeyPath stackPath =
|
||||||
.searchForSuitable(TargetStack.class, object.getCanonicalPath().getKeyList());
|
rootSchema.searchForSuitable(TraceObjectStack.class, object.getCanonicalPath());
|
||||||
if (stackPath == null) {
|
if (stackPath == null) {
|
||||||
return ModelQuery.EMPTY;
|
return ModelQuery.EMPTY;
|
||||||
}
|
}
|
||||||
TargetObjectSchema stackSchema = rootSchema.getSuccessorSchema(stackPath);
|
TraceObjectSchema stackSchema = rootSchema.getSuccessorSchema(stackPath);
|
||||||
PathMatcher matcher = stackSchema.searchFor(TargetStackFrame.class, stackPath, true);
|
PathMatcher matcher = stackSchema.searchFor(TraceObjectStackFrame.class, stackPath, true);
|
||||||
return new ModelQuery(matcher);
|
return new ModelQuery(matcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.gui.thread;
|
package ghidra.app.plugin.core.debug.gui.thread;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import javax.swing.event.ListSelectionEvent;
|
import javax.swing.event.ListSelectionEvent;
|
||||||
@@ -30,8 +29,6 @@ import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.*;
|
|||||||
import ghidra.app.plugin.core.debug.gui.model.columns.*;
|
import ghidra.app.plugin.core.debug.gui.model.columns.*;
|
||||||
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
||||||
import ghidra.app.services.DebuggerTraceManagerService;
|
import ghidra.app.services.DebuggerTraceManagerService;
|
||||||
import ghidra.dbg.target.*;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.docking.settings.Settings;
|
import ghidra.docking.settings.Settings;
|
||||||
import ghidra.framework.plugintool.Plugin;
|
import ghidra.framework.plugintool.Plugin;
|
||||||
@@ -41,13 +38,17 @@ import ghidra.program.model.address.Address;
|
|||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
|
import ghidra.trace.model.target.iface.TraceObjectExecutionStateful;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema;
|
||||||
|
import ghidra.trace.model.thread.TraceObjectProcess;
|
||||||
import ghidra.trace.model.thread.TraceObjectThread;
|
import ghidra.trace.model.thread.TraceObjectThread;
|
||||||
|
|
||||||
public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceObjectThread> {
|
public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceObjectThread> {
|
||||||
|
|
||||||
protected static ModelQuery successorThreads(TargetObjectSchema rootSchema, List<String> path) {
|
protected static ModelQuery successorThreads(TraceObjectSchema rootSchema, KeyPath path) {
|
||||||
TargetObjectSchema schema = rootSchema.getSuccessorSchema(path);
|
TraceObjectSchema schema = rootSchema.getSuccessorSchema(path);
|
||||||
return new ModelQuery(schema.searchFor(TargetThread.class, path, true));
|
return new ModelQuery(schema.searchFor(TraceObjectThread.class, path, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ThreadPathColumn extends TraceValueKeyColumn {
|
private static class ThreadPathColumn extends TraceValueKeyColumn {
|
||||||
@@ -245,7 +246,7 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||||||
private static class ThreadStateColumn extends TraceValueObjectAttributeColumn<String> {
|
private static class ThreadStateColumn extends TraceValueObjectAttributeColumn<String> {
|
||||||
public ThreadStateColumn() {
|
public ThreadStateColumn() {
|
||||||
// NB. The recorder converts enums to strings
|
// NB. The recorder converts enums to strings
|
||||||
super(TargetExecutionStateful.STATE_ATTRIBUTE_NAME, String.class);
|
super(TraceObjectExecutionStateful.KEY_STATE, String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -343,17 +344,17 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ModelQuery computeQuery(TraceObject object) {
|
protected ModelQuery computeQuery(TraceObject object) {
|
||||||
TargetObjectSchema rootSchema = object.getRoot().getTargetSchema();
|
TraceObjectSchema rootSchema = object.getRoot().getSchema();
|
||||||
List<String> seedPath = object.getCanonicalPath().getKeyList();
|
KeyPath seedPath = object.getCanonicalPath();
|
||||||
List<String> processPath = rootSchema.searchForAncestor(TargetProcess.class, seedPath);
|
KeyPath processPath = rootSchema.searchForAncestor(TraceObjectProcess.class, seedPath);
|
||||||
if (processPath != null) {
|
if (processPath != null) {
|
||||||
ModelQuery result = successorThreads(rootSchema, processPath);
|
ModelQuery result = successorThreads(rootSchema, processPath);
|
||||||
if (!result.isEmpty()) {
|
if (!result.isEmpty()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<String> containerPath =
|
KeyPath containerPath =
|
||||||
rootSchema.searchForSuitableContainer(TargetThread.class, seedPath);
|
rootSchema.searchForSuitableContainer(TraceObjectThread.class, seedPath);
|
||||||
|
|
||||||
if (containerPath != null) {
|
if (containerPath != null) {
|
||||||
ModelQuery result = successorThreads(rootSchema, containerPath);
|
ModelQuery result = successorThreads(rootSchema, containerPath);
|
||||||
@@ -361,7 +362,7 @@ public class DebuggerThreadsPanel extends AbstractObjectsTableBasedPanel<TraceOb
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return successorThreads(rootSchema, List.of());
|
return successorThreads(rootSchema, KeyPath.ROOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void trySelectCurrentThread() {
|
private void trySelectCurrentThread() {
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -19,13 +19,11 @@ import db.Transaction;
|
|||||||
import ghidra.app.plugin.core.debug.gui.action.PCLocationTrackingSpec;
|
import ghidra.app.plugin.core.debug.gui.action.PCLocationTrackingSpec;
|
||||||
import ghidra.app.plugin.core.debug.gui.action.SPLocationTrackingSpec;
|
import ghidra.app.plugin.core.debug.gui.action.SPLocationTrackingSpec;
|
||||||
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
||||||
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.*;
|
||||||
import ghidra.trace.model.Trace;
|
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
@@ -120,7 +118,7 @@ public class ThreadRow {
|
|||||||
if (target == null) {
|
if (target == null) {
|
||||||
return ThreadState.ALIVE;
|
return ThreadState.ALIVE;
|
||||||
}
|
}
|
||||||
TargetExecutionState state = target.getThreadExecutionState(thread);
|
TraceExecutionState state = target.getThreadExecutionState(thread);
|
||||||
if (state == null) {
|
if (state == null) {
|
||||||
return ThreadState.UNKNOWN;
|
return ThreadState.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -17,13 +17,14 @@ package ghidra.app.plugin.core.debug.mapping;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import ghidra.dbg.target.TargetEnvironment;
|
|
||||||
import ghidra.dbg.util.PathPredicates;
|
|
||||||
import ghidra.program.model.lang.Endian;
|
import ghidra.program.model.lang.Endian;
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
import ghidra.trace.model.target.TraceObjectValue;
|
import ghidra.trace.model.target.TraceObjectValue;
|
||||||
|
import ghidra.trace.model.target.iface.TraceObjectEnvironment;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
import ghidra.trace.model.target.path.PathFilter;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.classfinder.ClassSearcher;
|
import ghidra.util.classfinder.ClassSearcher;
|
||||||
import ghidra.util.classfinder.ExtensionPoint;
|
import ghidra.util.classfinder.ExtensionPoint;
|
||||||
@@ -65,12 +66,12 @@ public interface DebuggerPlatformOpinion extends ExtensionPoint {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
TraceObject root = object.getRoot();
|
TraceObject root = object.getRoot();
|
||||||
List<String> pathToEnv = root.getTargetSchema()
|
KeyPath pathToEnv = root.getSchema()
|
||||||
.searchForSuitable(TargetEnvironment.class, object.getCanonicalPath().getKeyList());
|
.searchForSuitable(TraceObjectEnvironment.class, object.getCanonicalPath());
|
||||||
if (pathToEnv == null) {
|
if (pathToEnv == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return root.getSuccessors(Lifespan.at(snap), PathPredicates.pattern(pathToEnv))
|
return root.getSuccessors(Lifespan.at(snap), PathFilter.pattern(pathToEnv))
|
||||||
.findAny()
|
.findAny()
|
||||||
.map(p -> p.getDestination(root))
|
.map(p -> p.getDestination(root))
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
@@ -85,15 +86,15 @@ public interface DebuggerPlatformOpinion extends ExtensionPoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static String getDebugggerFromEnv(TraceObject env, long snap) {
|
static String getDebugggerFromEnv(TraceObject env, long snap) {
|
||||||
return getStringAttribute(env, snap, TargetEnvironment.DEBUGGER_ATTRIBUTE_NAME);
|
return getStringAttribute(env, snap, TraceObjectEnvironment.KEY_DEBUGGER);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getArchitectureFromEnv(TraceObject env, long snap) {
|
static String getArchitectureFromEnv(TraceObject env, long snap) {
|
||||||
return getStringAttribute(env, snap, TargetEnvironment.ARCH_ATTRIBUTE_NAME);
|
return getStringAttribute(env, snap, TraceObjectEnvironment.KEY_ARCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getOperatingSystemFromEnv(TraceObject env, long snap) {
|
static String getOperatingSystemFromEnv(TraceObject env, long snap) {
|
||||||
return getStringAttribute(env, snap, TargetEnvironment.OS_ATTRIBUTE_NAME);
|
return getStringAttribute(env, snap, TraceObjectEnvironment.KEY_OS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,7 +105,7 @@ public interface DebuggerPlatformOpinion extends ExtensionPoint {
|
|||||||
* @return the endianness, or null
|
* @return the endianness, or null
|
||||||
*/
|
*/
|
||||||
static Endian getEndianFromEnv(TraceObject env, long snap) {
|
static Endian getEndianFromEnv(TraceObject env, long snap) {
|
||||||
String strEndian = getStringAttribute(env, snap, TargetEnvironment.ENDIAN_ATTRIBUTE_NAME);
|
String strEndian = getStringAttribute(env, snap, TraceObjectEnvironment.KEY_ENDIAN);
|
||||||
if (strEndian == null) {
|
if (strEndian == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -15,21 +15,21 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.debug.service.breakpoint;
|
package ghidra.app.plugin.core.debug.service.breakpoint;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Collection;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import db.Transaction;
|
import db.Transaction;
|
||||||
import ghidra.async.AsyncUtils;
|
import ghidra.async.AsyncUtils;
|
||||||
import ghidra.dbg.target.*;
|
|
||||||
import ghidra.dbg.util.PathMatcher;
|
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
import ghidra.trace.model.breakpoint.*;
|
||||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
|
||||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||||
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
import ghidra.trace.model.target.path.PathMatcher;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
|
||||||
public record PlaceEmuBreakpointActionItem(Trace trace, long snap, Address address, long length,
|
public record PlaceEmuBreakpointActionItem(Trace trace, long snap, Address address, long length,
|
||||||
@@ -69,7 +69,8 @@ public record PlaceEmuBreakpointActionItem(Trace trace, long snap, Address addre
|
|||||||
if (region == null) {
|
if (region == null) {
|
||||||
throw new IllegalArgumentException("Address does not belong to a memory in the trace");
|
throw new IllegalArgumentException("Address does not belong to a memory in the trace");
|
||||||
}
|
}
|
||||||
return region.getObject().querySuitableTargetInterface(TargetBreakpointSpecContainer.class);
|
return region.getObject()
|
||||||
|
.findSuitableContainerInterface(TraceObjectBreakpointSpec.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String computePath() {
|
private String computePath() {
|
||||||
@@ -83,21 +84,21 @@ public record PlaceEmuBreakpointActionItem(Trace trace, long snap, Address addre
|
|||||||
"Address is not associated with a breakpoint container");
|
"Address is not associated with a breakpoint container");
|
||||||
}
|
}
|
||||||
PathMatcher specMatcher =
|
PathMatcher specMatcher =
|
||||||
container.getTargetSchema().searchFor(TargetBreakpointSpec.class, true);
|
container.getSchema().searchFor(TraceObjectBreakpointSpec.class, true);
|
||||||
if (specMatcher == null) {
|
if (specMatcher == null) {
|
||||||
throw new IllegalArgumentException("Cannot find path to breakpoint specifications");
|
throw new IllegalArgumentException("Cannot find path to breakpoint specifications");
|
||||||
}
|
}
|
||||||
List<String> specRelPath = specMatcher.applyKeys(name).getSingletonPath();
|
KeyPath specRelPath = specMatcher.applyKeys(name).getSingletonPath();
|
||||||
if (specRelPath == null) {
|
if (specRelPath == null) {
|
||||||
throw new IllegalArgumentException("Too many wildcards to breakpoint specification");
|
throw new IllegalArgumentException("Too many wildcards to breakpoint specification");
|
||||||
}
|
}
|
||||||
PathMatcher locMatcher = container.getTargetSchema()
|
PathMatcher locMatcher = container.getSchema()
|
||||||
.getSuccessorSchema(specRelPath)
|
.getSuccessorSchema(specRelPath)
|
||||||
.searchFor(TargetBreakpointLocation.class, true);
|
.searchFor(TraceObjectBreakpointLocation.class, true);
|
||||||
if (locMatcher == null) {
|
if (locMatcher == null) {
|
||||||
throw new IllegalArgumentException("Cannot find path to breakpoint locations");
|
throw new IllegalArgumentException("Cannot find path to breakpoint locations");
|
||||||
}
|
}
|
||||||
List<String> locRelPath = locMatcher.applyIntKeys(0).getSingletonPath();
|
KeyPath locRelPath = locMatcher.applyIntKeys(0).getSingletonPath();
|
||||||
if (locRelPath == null) {
|
if (locRelPath == null) {
|
||||||
throw new IllegalArgumentException("Too many wildcards to breakpoint location");
|
throw new IllegalArgumentException("Too many wildcards to breakpoint location");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,10 +27,6 @@ import db.Transaction;
|
|||||||
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
||||||
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils.Extrema;
|
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils.Extrema;
|
||||||
import ghidra.app.services.DebuggerEmulationService;
|
import ghidra.app.services.DebuggerEmulationService;
|
||||||
import ghidra.dbg.target.*;
|
|
||||||
import ghidra.dbg.target.schema.*;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.dbg.util.*;
|
|
||||||
import ghidra.framework.model.DomainFile;
|
import ghidra.framework.model.DomainFile;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.*;
|
import ghidra.program.model.lang.*;
|
||||||
@@ -42,8 +38,13 @@ import ghidra.trace.database.DBTrace;
|
|||||||
import ghidra.trace.model.*;
|
import ghidra.trace.model.*;
|
||||||
import ghidra.trace.model.memory.*;
|
import ghidra.trace.model.memory.*;
|
||||||
import ghidra.trace.model.modules.TraceConflictedMappingException;
|
import ghidra.trace.model.modules.TraceConflictedMappingException;
|
||||||
import ghidra.trace.model.target.*;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||||
|
import ghidra.trace.model.target.TraceObjectManager;
|
||||||
|
import ghidra.trace.model.target.iface.TraceObjectInterface;
|
||||||
|
import ghidra.trace.model.target.path.*;
|
||||||
|
import ghidra.trace.model.target.schema.*;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
import ghidra.trace.model.thread.*;
|
import ghidra.trace.model.thread.*;
|
||||||
import ghidra.trace.model.time.TraceSnapshot;
|
import ghidra.trace.model.time.TraceSnapshot;
|
||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
@@ -72,8 +73,6 @@ public class ProgramEmulationUtils {
|
|||||||
</schema>
|
</schema>
|
||||||
<schema name='BreakpointContainer' canonical='yes' elementResync='NEVER'
|
<schema name='BreakpointContainer' canonical='yes' elementResync='NEVER'
|
||||||
attributeResync='NEVER'>
|
attributeResync='NEVER'>
|
||||||
<interface name='BreakpointSpecContainer' />
|
|
||||||
<interface name='BreakpointLocationContainer' />
|
|
||||||
<element schema='Breakpoint' />
|
<element schema='Breakpoint' />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name='Breakpoint' elementResync='NEVER' attributeResync='NEVER'>
|
<schema name='Breakpoint' elementResync='NEVER' attributeResync='NEVER'>
|
||||||
@@ -123,7 +122,7 @@ public class ProgramEmulationUtils {
|
|||||||
</context>
|
</context>
|
||||||
""";
|
""";
|
||||||
public static final SchemaContext EMU_CTX;
|
public static final SchemaContext EMU_CTX;
|
||||||
public static final TargetObjectSchema EMU_SESSION_SCHEMA;
|
public static final TraceObjectSchema EMU_SESSION_SCHEMA;
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
EMU_CTX = XmlSchemaContext.deserialize(EMU_CTX_XML);
|
EMU_CTX = XmlSchemaContext.deserialize(EMU_CTX_XML);
|
||||||
@@ -234,9 +233,10 @@ public class ProgramEmulationUtils {
|
|||||||
|
|
||||||
// NB. No need to populate as module.
|
// NB. No need to populate as module.
|
||||||
// UI will sync from mapping, so it's obvious where the cursor is.
|
// UI will sync from mapping, so it's obvious where the cursor is.
|
||||||
String path = PathUtils.toString(patRegion
|
String path = patRegion
|
||||||
.applyKeys(block.getStart() + "-" + modName + ":" + block.getName())
|
.applyKeys(block.getStart() + "-" + modName + ":" + block.getName())
|
||||||
.getSingletonPath());
|
.getSingletonPath()
|
||||||
|
.toString();
|
||||||
trace.getMemoryManager()
|
trace.getMemoryManager()
|
||||||
.createRegion(path, snapshot.getKey(), range, getRegionFlags(block));
|
.createRegion(path, snapshot.getKey(), range, getRegionFlags(block));
|
||||||
}
|
}
|
||||||
@@ -270,8 +270,8 @@ public class ProgramEmulationUtils {
|
|||||||
// N.B. Bytes will be loaded lazily
|
// N.B. Bytes will be loaded lazily
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PathPattern computePattern(TargetObjectSchema root, Trace trace,
|
public static PathPattern computePattern(TraceObjectSchema root, Trace trace,
|
||||||
Class<? extends TargetObject> iface) {
|
Class<? extends TraceObjectInterface> iface) {
|
||||||
PathMatcher matcher = root.searchFor(iface, true);
|
PathMatcher matcher = root.searchFor(iface, true);
|
||||||
PathPattern pattern = matcher.getSingletonPattern();
|
PathPattern pattern = matcher.getSingletonPattern();
|
||||||
if (pattern == null || pattern.countWildcards() != 1) {
|
if (pattern == null || pattern.countWildcards() != 1) {
|
||||||
@@ -282,19 +282,19 @@ public class ProgramEmulationUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static PathPattern computePatternRegion(Trace trace) {
|
public static PathPattern computePatternRegion(Trace trace) {
|
||||||
TargetObjectSchema root = trace.getObjectManager().getRootSchema();
|
TraceObjectSchema root = trace.getObjectManager().getRootSchema();
|
||||||
if (root == null) {
|
if (root == null) {
|
||||||
return new PathPattern(PathUtils.parse("Memory[]"));
|
return PathFilter.parse("Memory[]");
|
||||||
}
|
}
|
||||||
return computePattern(root, trace, TargetMemoryRegion.class);
|
return computePattern(root, trace, TraceObjectMemoryRegion.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PathPattern computePatternThread(Trace trace) {
|
public static PathPattern computePatternThread(Trace trace) {
|
||||||
TargetObjectSchema root = trace.getObjectManager().getRootSchema();
|
TraceObjectSchema root = trace.getObjectManager().getRootSchema();
|
||||||
if (root == null) {
|
if (root == null) {
|
||||||
return new PathPattern(PathUtils.parse("Threads[]"));
|
return PathFilter.parse("Threads[]");
|
||||||
}
|
}
|
||||||
return computePattern(root, trace, TargetThread.class);
|
return computePattern(root, trace, TraceObjectThread.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -312,13 +312,13 @@ public class ProgramEmulationUtils {
|
|||||||
PathPattern patThread = computePatternThread(trace);
|
PathPattern patThread = computePatternThread(trace);
|
||||||
long next = tm.getAllThreads().size();
|
long next = tm.getAllThreads().size();
|
||||||
String path;
|
String path;
|
||||||
while (!tm.getThreadsByPath(path =
|
while (!tm.getThreadsByPath(
|
||||||
PathUtils.toString(patThread.applyKeys(Long.toString(next)).getSingletonPath()))
|
path = patThread.applyKeys(Long.toString(next)).getSingletonPath().toString())
|
||||||
.isEmpty()) {
|
.isEmpty()) {
|
||||||
next++;
|
next++;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return tm.createThread(path, "[" + next + "]", snap);
|
return tm.createThread(path, KeyPath.makeIndex(next), snap);
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
@@ -341,15 +341,14 @@ public class ProgramEmulationUtils {
|
|||||||
TraceMemoryManager memory = trace.getMemoryManager();
|
TraceMemoryManager memory = trace.getMemoryManager();
|
||||||
if (thread instanceof TraceObjectThread ot) {
|
if (thread instanceof TraceObjectThread ot) {
|
||||||
TraceObject object = ot.getObject();
|
TraceObject object = ot.getObject();
|
||||||
PathPredicates regsMatcher = object.getRoot()
|
PathFilter regsFilter = object.getRoot()
|
||||||
.getTargetSchema()
|
.getSchema()
|
||||||
.searchForRegisterContainer(0, object.getCanonicalPath().getKeyList());
|
.searchForRegisterContainer(0, object.getCanonicalPath());
|
||||||
if (regsMatcher.isEmpty()) {
|
if (regsFilter.isNone()) {
|
||||||
throw new IllegalArgumentException("Cannot create register container");
|
throw new IllegalArgumentException("Cannot create register container");
|
||||||
}
|
}
|
||||||
for (PathPattern regsPattern : regsMatcher.getPatterns()) {
|
for (PathPattern regsPattern : regsFilter.getPatterns()) {
|
||||||
trace.getObjectManager()
|
trace.getObjectManager().createObject(regsPattern.getSingletonPath());
|
||||||
.createObject(TraceObjectKeyPath.of(regsPattern.getSingletonPath()));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -448,12 +447,10 @@ public class ProgramEmulationUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PathPattern patRegion = computePatternRegion(trace);
|
PathPattern patRegion = computePatternRegion(trace);
|
||||||
String threadName = PathUtils.isIndex(thread.getName())
|
String threadName = KeyPath.parseIfIndex(thread.getName());
|
||||||
? PathUtils.parseIndex(thread.getName())
|
String path = patRegion.applyKeys(alloc.getMinAddress() + "-stack " + threadName)
|
||||||
: thread.getName();
|
.getSingletonPath()
|
||||||
String path = PathUtils.toString(
|
.toString();
|
||||||
patRegion.applyKeys(alloc.getMinAddress() + "-stack " + threadName)
|
|
||||||
.getSingletonPath());
|
|
||||||
TraceMemoryManager mm = trace.getMemoryManager();
|
TraceMemoryManager mm = trace.getMemoryManager();
|
||||||
try {
|
try {
|
||||||
return mm.createRegion(path, snap, alloc,
|
return mm.createRegion(path, snap, alloc,
|
||||||
@@ -512,9 +509,9 @@ public class ProgramEmulationUtils {
|
|||||||
return alloc;
|
return alloc;
|
||||||
}
|
}
|
||||||
PathPattern patRegion = computePatternRegion(trace);
|
PathPattern patRegion = computePatternRegion(trace);
|
||||||
String path = PathUtils.toString(
|
String path = patRegion.applyKeys(stackBlock.getStart() + "-STACK")
|
||||||
patRegion.applyKeys(stackBlock.getStart() + "-STACK")
|
.getSingletonPath()
|
||||||
.getSingletonPath());
|
.toString();
|
||||||
TraceMemoryManager mm = trace.getMemoryManager();
|
TraceMemoryManager mm = trace.getMemoryManager();
|
||||||
try {
|
try {
|
||||||
return mm.createRegion(path, snap, alloc,
|
return mm.createRegion(path, snap, alloc,
|
||||||
@@ -584,12 +581,11 @@ public class ProgramEmulationUtils {
|
|||||||
for (AddressRange candidate : left) {
|
for (AddressRange candidate : left) {
|
||||||
if (Long.compareUnsigned(candidate.getLength(), size) >= 0) {
|
if (Long.compareUnsigned(candidate.getLength(), size) >= 0) {
|
||||||
AddressRange alloc = new AddressRangeImpl(candidate.getMinAddress(), size);
|
AddressRange alloc = new AddressRangeImpl(candidate.getMinAddress(), size);
|
||||||
String threadName = PathUtils.isIndex(thread.getName())
|
String threadName = KeyPath.parseIfIndex(thread.getName());
|
||||||
? PathUtils.parseIndex(thread.getName())
|
String path = patRegion
|
||||||
: thread.getName();
|
.applyKeys(alloc.getMinAddress() + "-stack " + threadName)
|
||||||
String path = PathUtils.toString(
|
.getSingletonPath()
|
||||||
patRegion.applyKeys(alloc.getMinAddress() + "-stack " + threadName)
|
.toString();
|
||||||
.getSingletonPath());
|
|
||||||
return mm.createRegion(path, snap, alloc,
|
return mm.createRegion(path, snap, alloc,
|
||||||
TraceMemoryFlag.READ, TraceMemoryFlag.WRITE).getRange();
|
TraceMemoryFlag.READ, TraceMemoryFlag.WRITE).getRange();
|
||||||
}
|
}
|
||||||
@@ -606,13 +602,13 @@ public class ProgramEmulationUtils {
|
|||||||
TraceObjectManager om = trace.getObjectManager();
|
TraceObjectManager om = trace.getObjectManager();
|
||||||
om.createRootObject(EMU_SESSION_SCHEMA);
|
om.createRootObject(EMU_SESSION_SCHEMA);
|
||||||
|
|
||||||
om.createObject(TraceObjectKeyPath.parse("Breakpoints"))
|
om.createObject(KeyPath.parse("Breakpoints"))
|
||||||
.insert(Lifespan.ALL, ConflictResolution.DENY);
|
.insert(Lifespan.ALL, ConflictResolution.DENY);
|
||||||
om.createObject(TraceObjectKeyPath.parse("Memory"))
|
om.createObject(KeyPath.parse("Memory"))
|
||||||
.insert(Lifespan.ALL, ConflictResolution.DENY);
|
.insert(Lifespan.ALL, ConflictResolution.DENY);
|
||||||
om.createObject(TraceObjectKeyPath.parse("Modules"))
|
om.createObject(KeyPath.parse("Modules"))
|
||||||
.insert(Lifespan.ALL, ConflictResolution.DENY);
|
.insert(Lifespan.ALL, ConflictResolution.DENY);
|
||||||
om.createObject(TraceObjectKeyPath.parse("Threads"))
|
om.createObject(KeyPath.parse("Threads"))
|
||||||
.insert(Lifespan.ALL, ConflictResolution.DENY);
|
.insert(Lifespan.ALL, ConflictResolution.DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -23,7 +23,6 @@ import java.util.stream.Collectors;
|
|||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import ghidra.app.plugin.core.debug.service.modules.ProgramModuleIndexer.IndexEntry;
|
import ghidra.app.plugin.core.debug.service.modules.ProgramModuleIndexer.IndexEntry;
|
||||||
import ghidra.dbg.util.PathUtils;
|
|
||||||
import ghidra.debug.api.modules.*;
|
import ghidra.debug.api.modules.*;
|
||||||
import ghidra.framework.model.DomainFile;
|
import ghidra.framework.model.DomainFile;
|
||||||
import ghidra.graph.*;
|
import ghidra.graph.*;
|
||||||
@@ -31,6 +30,7 @@ import ghidra.graph.jung.JungDirectedGraph;
|
|||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||||
import ghidra.trace.model.modules.TraceModule;
|
import ghidra.trace.model.modules.TraceModule;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
public enum DebuggerStaticMappingProposals {
|
public enum DebuggerStaticMappingProposals {
|
||||||
@@ -243,11 +243,8 @@ public enum DebuggerStaticMappingProposals {
|
|||||||
protected static Set<String> getLikelyModulesFromName(TraceMemoryRegion region) {
|
protected static Set<String> getLikelyModulesFromName(TraceMemoryRegion region) {
|
||||||
String key;
|
String key;
|
||||||
try {
|
try {
|
||||||
List<String> path = PathUtils.parse(region.getPath());
|
KeyPath path = KeyPath.parse(region.getPath());
|
||||||
key = PathUtils.getKey(path);
|
key = KeyPath.parseIfIndex(path.key());
|
||||||
if (PathUtils.isIndex(key)) {
|
|
||||||
key = PathUtils.parseIndex(key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException e) { // Parse error
|
catch (IllegalArgumentException e) { // Parse error
|
||||||
Msg.error(DebuggerStaticMappingProposals.class,
|
Msg.error(DebuggerStaticMappingProposals.class,
|
||||||
|
|||||||
@@ -496,7 +496,7 @@ public class DebuggerStaticMappingServicePlugin extends Plugin
|
|||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
InfoPerTrace info = requireTrackedInfo(trace);
|
InfoPerTrace info = requireTrackedInfo(trace);
|
||||||
if (info == null) {
|
if (info == null) {
|
||||||
return null;
|
return Map.of();
|
||||||
}
|
}
|
||||||
return info.getOpenMappedViews(set, Lifespan.at(snap));
|
return info.getOpenMappedViews(set, Lifespan.at(snap));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import ghidra.app.services.*;
|
|||||||
import ghidra.app.services.DebuggerControlService.ControlModeChangeListener;
|
import ghidra.app.services.DebuggerControlService.ControlModeChangeListener;
|
||||||
import ghidra.async.*;
|
import ghidra.async.*;
|
||||||
import ghidra.async.AsyncConfigFieldCodec.BooleanAsyncConfigFieldCodec;
|
import ghidra.async.AsyncConfigFieldCodec.BooleanAsyncConfigFieldCodec;
|
||||||
import ghidra.dbg.target.TargetObject;
|
|
||||||
import ghidra.debug.api.control.ControlMode;
|
import ghidra.debug.api.control.ControlMode;
|
||||||
import ghidra.debug.api.platform.DebuggerPlatformMapper;
|
import ghidra.debug.api.platform.DebuggerPlatformMapper;
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
@@ -61,7 +60,7 @@ import ghidra.trace.model.guest.TracePlatform;
|
|||||||
import ghidra.trace.model.program.TraceProgramView;
|
import ghidra.trace.model.program.TraceProgramView;
|
||||||
import ghidra.trace.model.program.TraceVariableSnapProgramView;
|
import ghidra.trace.model.program.TraceVariableSnapProgramView;
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
import ghidra.trace.model.target.TraceObjectKeyPath;
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.trace.model.time.TraceSnapshot;
|
import ghidra.trace.model.time.TraceSnapshot;
|
||||||
import ghidra.trace.model.time.schedule.TraceSchedule;
|
import ghidra.trace.model.time.schedule.TraceSchedule;
|
||||||
@@ -120,7 +119,7 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
|
|||||||
Target target = current.getTarget();
|
Target target = current.getTarget();
|
||||||
if (supportsFocus(target)) {
|
if (supportsFocus(target)) {
|
||||||
// TODO: Same for stack frame? I can't imagine it's as common as this....
|
// TODO: Same for stack frame? I can't imagine it's as common as this....
|
||||||
TraceObjectKeyPath focus = target.getFocus();
|
KeyPath focus = target.getFocus();
|
||||||
if (focus == null) {
|
if (focus == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -257,7 +256,7 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DebuggerCoordinates coords = current;
|
DebuggerCoordinates coords = current;
|
||||||
TraceObjectKeyPath focus = curTarget.getFocus();
|
KeyPath focus = curTarget.getFocus();
|
||||||
if (focus != null) {
|
if (focus != null) {
|
||||||
coords = coords.path(focus);
|
coords = coords.path(focus);
|
||||||
}
|
}
|
||||||
@@ -288,7 +287,6 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
|
|||||||
new ForFollowPresentListener();
|
new ForFollowPresentListener();
|
||||||
|
|
||||||
protected DebuggerCoordinates current = DebuggerCoordinates.NOWHERE;
|
protected DebuggerCoordinates current = DebuggerCoordinates.NOWHERE;
|
||||||
protected TargetObject curObj;
|
|
||||||
@AutoConfigStateField(codec = BooleanAsyncConfigFieldCodec.class)
|
@AutoConfigStateField(codec = BooleanAsyncConfigFieldCodec.class)
|
||||||
protected final AsyncReference<Boolean, Void> saveTracesByDefault = new AsyncReference<>(true);
|
protected final AsyncReference<Boolean, Void> saveTracesByDefault = new AsyncReference<>(true);
|
||||||
@AutoConfigStateField(codec = BooleanAsyncConfigFieldCodec.class)
|
@AutoConfigStateField(codec = BooleanAsyncConfigFieldCodec.class)
|
||||||
@@ -1216,7 +1214,7 @@ public class DebuggerTraceManagerServicePlugin extends Plugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DebuggerCoordinates resolvePath(TraceObjectKeyPath path) {
|
public DebuggerCoordinates resolvePath(KeyPath path) {
|
||||||
return current.path(path);
|
return current.path(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -24,9 +24,6 @@ import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerService
|
|||||||
import ghidra.app.plugin.core.progmgr.ProgramManagerPlugin;
|
import ghidra.app.plugin.core.progmgr.ProgramManagerPlugin;
|
||||||
import ghidra.app.services.DebuggerTraceManagerService;
|
import ghidra.app.services.DebuggerTraceManagerService;
|
||||||
import ghidra.app.services.ProgramManager;
|
import ghidra.app.services.ProgramManager;
|
||||||
import ghidra.dbg.target.schema.SchemaContext;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
|
||||||
import ghidra.framework.model.DomainFolder;
|
import ghidra.framework.model.DomainFolder;
|
||||||
import ghidra.program.database.ProgramBuilder;
|
import ghidra.program.database.ProgramBuilder;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
@@ -36,6 +33,9 @@ import ghidra.trace.database.ToyDBTraceBuilder;
|
|||||||
import ghidra.trace.database.memory.DBTraceMemoryManager;
|
import ghidra.trace.database.memory.DBTraceMemoryManager;
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.memory.TraceMemoryFlag;
|
import ghidra.trace.model.memory.TraceMemoryFlag;
|
||||||
|
import ghidra.trace.model.target.schema.SchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import help.screenshot.GhidraScreenShotGenerator;
|
import help.screenshot.GhidraScreenShotGenerator;
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -26,10 +26,6 @@ import db.Transaction;
|
|||||||
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest;
|
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
||||||
import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServicePlugin;
|
import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServicePlugin;
|
||||||
import ghidra.dbg.target.TargetEventScope;
|
|
||||||
import ghidra.dbg.target.schema.SchemaContext;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
|
||||||
import ghidra.program.database.ProgramBuilder;
|
import ghidra.program.database.ProgramBuilder;
|
||||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||||
import ghidra.trace.database.target.DBTraceObjectManager;
|
import ghidra.trace.database.target.DBTraceObjectManager;
|
||||||
@@ -37,6 +33,10 @@ import ghidra.trace.database.target.DBTraceObjectValue;
|
|||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.target.TraceObject;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||||
|
import ghidra.trace.model.target.iface.TraceObjectEventScope;
|
||||||
|
import ghidra.trace.model.target.schema.SchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
import help.screenshot.GhidraScreenShotGenerator;
|
import help.screenshot.GhidraScreenShotGenerator;
|
||||||
|
|
||||||
public class DebuggerModelPluginScreenShots extends GhidraScreenShotGenerator {
|
public class DebuggerModelPluginScreenShots extends GhidraScreenShotGenerator {
|
||||||
@@ -61,8 +61,6 @@ public class DebuggerModelPluginScreenShots extends GhidraScreenShotGenerator {
|
|||||||
<attribute name="Modules" schema="ModuleContainer" />
|
<attribute name="Modules" schema="ModuleContainer" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="BreakpointContainer" canonical="yes">
|
<schema name="BreakpointContainer" canonical="yes">
|
||||||
<interface name="BreakpointSpecContainer" />
|
|
||||||
<interface name="BreakpointLocationContainer" />
|
|
||||||
<element schema="Breakpoint" />
|
<element schema="Breakpoint" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="Breakpoint">
|
<schema name="Breakpoint">
|
||||||
@@ -98,7 +96,10 @@ public class DebuggerModelPluginScreenShots extends GhidraScreenShotGenerator {
|
|||||||
<attribute-alias from="_pc" to="PC" />
|
<attribute-alias from="_pc" to="PC" />
|
||||||
</schema>
|
</schema>
|
||||||
<schema name="ModuleContainer" canonical="yes">
|
<schema name="ModuleContainer" canonical="yes">
|
||||||
<interface name="ModuleContainer" />
|
<element schema="Module" />
|
||||||
|
</schema>
|
||||||
|
<schema name="Module">
|
||||||
|
<interface name="Module" />
|
||||||
</schema>
|
</schema>
|
||||||
</context>""";
|
</context>""";
|
||||||
public static final SchemaContext CTX;
|
public static final SchemaContext CTX;
|
||||||
@@ -179,7 +180,7 @@ public class DebuggerModelPluginScreenShots extends GhidraScreenShotGenerator {
|
|||||||
proc.child("Modules");
|
proc.child("Modules");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
root.value(TargetEventScope.EVENT_OBJECT_ATTRIBUTE_NAME, l.thread);
|
root.value(TraceObjectEventScope.KEY_EVENT_THREAD, l.thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
traceManager.openTrace(tb.trace);
|
traceManager.openTrace(tb.trace);
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -21,11 +21,11 @@ import org.junit.Test;
|
|||||||
import db.Transaction;
|
import db.Transaction;
|
||||||
import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServicePlugin;
|
import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServicePlugin;
|
||||||
import ghidra.app.services.DebuggerTraceManagerService;
|
import ghidra.app.services.DebuggerTraceManagerService;
|
||||||
import ghidra.dbg.target.schema.SchemaContext;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
|
||||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||||
import ghidra.trace.database.target.DBTraceObjectManagerTest;
|
import ghidra.trace.database.target.DBTraceObjectManagerTest;
|
||||||
|
import ghidra.trace.model.target.schema.SchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
import help.screenshot.GhidraScreenShotGenerator;
|
import help.screenshot.GhidraScreenShotGenerator;
|
||||||
|
|
||||||
public class DebuggerPlatformPluginScreenShots extends GhidraScreenShotGenerator {
|
public class DebuggerPlatformPluginScreenShots extends GhidraScreenShotGenerator {
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -40,9 +40,6 @@ import ghidra.app.services.*;
|
|||||||
import ghidra.app.services.DebuggerControlService.StateEditor;
|
import ghidra.app.services.DebuggerControlService.StateEditor;
|
||||||
import ghidra.app.services.DebuggerEmulationService.EmulationResult;
|
import ghidra.app.services.DebuggerEmulationService.EmulationResult;
|
||||||
import ghidra.async.AsyncTestUtils;
|
import ghidra.async.AsyncTestUtils;
|
||||||
import ghidra.dbg.target.schema.SchemaContext;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
|
||||||
import ghidra.debug.api.control.ControlMode;
|
import ghidra.debug.api.control.ControlMode;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.framework.model.DomainFolder;
|
import ghidra.framework.model.DomainFolder;
|
||||||
@@ -66,6 +63,9 @@ import ghidra.trace.model.Lifespan;
|
|||||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||||
import ghidra.trace.model.stack.TraceStack;
|
import ghidra.trace.model.stack.TraceStack;
|
||||||
import ghidra.trace.model.stack.TraceStackFrame;
|
import ghidra.trace.model.stack.TraceStackFrame;
|
||||||
|
import ghidra.trace.model.target.schema.SchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.trace.model.time.schedule.Scheduler;
|
import ghidra.trace.model.time.schedule.Scheduler;
|
||||||
import ghidra.util.InvalidNameException;
|
import ghidra.util.InvalidNameException;
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -44,7 +44,7 @@ import ghidra.trace.database.time.DBTraceTimeManager;
|
|||||||
import ghidra.trace.model.DefaultTraceLocation;
|
import ghidra.trace.model.DefaultTraceLocation;
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||||
import ghidra.trace.model.target.TraceObjectKeyPath;
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
import ghidra.trace.model.thread.TraceObjectThread;
|
import ghidra.trace.model.thread.TraceObjectThread;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
@@ -122,13 +122,13 @@ public class DebuggerThreadsPluginScreenShots extends GhidraScreenShotGenerator
|
|||||||
t3.getObject().setValue(Lifespan.nowOn(0), "_state", "TERMINATED");
|
t3.getObject().setValue(Lifespan.nowOn(0), "_state", "TERMINATED");
|
||||||
t4.getObject().setValue(Lifespan.nowOn(0), "_state", "TERMINATED");
|
t4.getObject().setValue(Lifespan.nowOn(0), "_state", "TERMINATED");
|
||||||
|
|
||||||
om.createObject(TraceObjectKeyPath.parse("Threads[1].Registers"))
|
om.createObject(KeyPath.parse("Threads[1].Registers"))
|
||||||
.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
||||||
om.createObject(TraceObjectKeyPath.parse("Threads[2].Registers"))
|
om.createObject(KeyPath.parse("Threads[2].Registers"))
|
||||||
.insert(Lifespan.nowOn(2), ConflictResolution.DENY);
|
.insert(Lifespan.nowOn(2), ConflictResolution.DENY);
|
||||||
om.createObject(TraceObjectKeyPath.parse("Threads[3].Registers"))
|
om.createObject(KeyPath.parse("Threads[3].Registers"))
|
||||||
.insert(Lifespan.nowOn(5), ConflictResolution.DENY);
|
.insert(Lifespan.nowOn(5), ConflictResolution.DENY);
|
||||||
om.createObject(TraceObjectKeyPath.parse("Threads[4].Registers"))
|
om.createObject(KeyPath.parse("Threads[4].Registers"))
|
||||||
.insert(Lifespan.nowOn(10), ConflictResolution.DENY);
|
.insert(Lifespan.nowOn(10), ConflictResolution.DENY);
|
||||||
// insert calls will extend thread life :/
|
// insert calls will extend thread life :/
|
||||||
t3.getObject().getCanonicalParent(13).setMaxSnap(10);
|
t3.getObject().getCanonicalParent(13).setMaxSnap(10);
|
||||||
|
|||||||
@@ -40,10 +40,6 @@ import ghidra.app.plugin.core.debug.service.emulation.DebuggerEmulationServicePl
|
|||||||
import ghidra.app.plugin.core.debug.service.emulation.ProgramEmulationUtils;
|
import ghidra.app.plugin.core.debug.service.emulation.ProgramEmulationUtils;
|
||||||
import ghidra.app.plugin.core.debug.service.platform.DebuggerPlatformServicePlugin;
|
import ghidra.app.plugin.core.debug.service.platform.DebuggerPlatformServicePlugin;
|
||||||
import ghidra.app.services.*;
|
import ghidra.app.services.*;
|
||||||
import ghidra.dbg.target.TargetEnvironment;
|
|
||||||
import ghidra.dbg.target.schema.SchemaContext;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
|
||||||
import ghidra.debug.api.control.ControlMode;
|
import ghidra.debug.api.control.ControlMode;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSet;
|
import ghidra.program.model.address.AddressSet;
|
||||||
@@ -66,7 +62,11 @@ import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
|||||||
import ghidra.trace.model.program.TraceProgramView;
|
import ghidra.trace.model.program.TraceProgramView;
|
||||||
import ghidra.trace.model.stack.*;
|
import ghidra.trace.model.stack.*;
|
||||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||||
import ghidra.trace.model.target.TraceObjectKeyPath;
|
import ghidra.trace.model.target.iface.TraceObjectEnvironment;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
import ghidra.trace.model.target.schema.SchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
import ghidra.trace.model.thread.TraceObjectThread;
|
import ghidra.trace.model.thread.TraceObjectThread;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.trace.model.time.schedule.TraceSchedule;
|
import ghidra.trace.model.time.schedule.TraceSchedule;
|
||||||
@@ -174,15 +174,15 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
objects.createRootObject(ctx.getSchema(new SchemaName("Session")));
|
objects.createRootObject(ctx.getSchema(new SchemaName("Session")));
|
||||||
DBTraceObject env =
|
DBTraceObject env =
|
||||||
objects.createObject(TraceObjectKeyPath.parse("Targets[0].Environment"));
|
objects.createObject(KeyPath.parse("Targets[0].Environment"));
|
||||||
assertEquals(ctx.getSchema(new SchemaName("Environment")), env.getTargetSchema());
|
assertEquals(ctx.getSchema(new SchemaName("Environment")), env.getSchema());
|
||||||
Lifespan zeroOn = Lifespan.nowOn(0);
|
Lifespan zeroOn = Lifespan.nowOn(0);
|
||||||
env.insert(zeroOn, ConflictResolution.DENY);
|
env.insert(zeroOn, ConflictResolution.DENY);
|
||||||
env.setAttribute(zeroOn, TargetEnvironment.DEBUGGER_ATTRIBUTE_NAME, "test");
|
env.setAttribute(zeroOn, TraceObjectEnvironment.KEY_DEBUGGER, "test");
|
||||||
env.setAttribute(zeroOn, TargetEnvironment.ARCH_ATTRIBUTE_NAME, arch);
|
env.setAttribute(zeroOn, TraceObjectEnvironment.KEY_ARCH, arch);
|
||||||
|
|
||||||
DBTraceObject objBinText =
|
DBTraceObject objBinText =
|
||||||
objects.createObject(TraceObjectKeyPath.parse("Targets[0].Memory[bin:.text]"));
|
objects.createObject(KeyPath.parse("Targets[0].Memory[bin:.text]"));
|
||||||
TraceObjectMemoryRegion binText =
|
TraceObjectMemoryRegion binText =
|
||||||
objBinText.queryInterface(TraceObjectMemoryRegion.class);
|
objBinText.queryInterface(TraceObjectMemoryRegion.class);
|
||||||
binText.addFlags(zeroOn, Set.of(TraceMemoryFlag.EXECUTE));
|
binText.addFlags(zeroOn, Set.of(TraceMemoryFlag.EXECUTE));
|
||||||
@@ -193,17 +193,17 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
DBTraceMemoryManager memory = tb.trace.getMemoryManager();
|
||||||
if (pcInStack) {
|
if (pcInStack) {
|
||||||
DBTraceObject objFrame = objects
|
DBTraceObject objFrame = objects
|
||||||
.createObject(TraceObjectKeyPath.parse("Targets[0].Threads[0].Stack[0]"));
|
.createObject(KeyPath.parse("Targets[0].Threads[0].Stack[0]"));
|
||||||
objFrame.insert(zeroOn, ConflictResolution.DENY);
|
objFrame.insert(zeroOn, ConflictResolution.DENY);
|
||||||
TraceObjectStackFrame frame = objFrame.queryInterface(TraceObjectStackFrame.class);
|
TraceObjectStackFrame frame = objFrame.queryInterface(TraceObjectStackFrame.class);
|
||||||
frame.setProgramCounter(zeroOn, tb.addr(offset));
|
frame.setProgramCounter(zeroOn, tb.addr(offset));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
objects.createObject(
|
objects.createObject(
|
||||||
TraceObjectKeyPath.parse("Targets[0].Threads[0].Stack[0].Registers"))
|
KeyPath.parse("Targets[0].Threads[0].Stack[0].Registers"))
|
||||||
.insert(zeroOn, ConflictResolution.DENY);
|
.insert(zeroOn, ConflictResolution.DENY);
|
||||||
TraceObjectThread thread = objects
|
TraceObjectThread thread = objects
|
||||||
.getObjectByCanonicalPath(TraceObjectKeyPath.parse("Targets[0].Threads[0]"))
|
.getObjectByCanonicalPath(KeyPath.parse("Targets[0].Threads[0]"))
|
||||||
.queryInterface(TraceObjectThread.class);
|
.queryInterface(TraceObjectThread.class);
|
||||||
traceManager.activateThread(thread);
|
traceManager.activateThread(thread);
|
||||||
DBTraceMemorySpace regs =
|
DBTraceMemorySpace regs =
|
||||||
@@ -218,7 +218,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
assertEquals(bytes.remaining(), memory.putBytes(0, tb.addr(offset), bytes));
|
assertEquals(bytes.remaining(), memory.putBytes(0, tb.addr(offset), bytes));
|
||||||
}
|
}
|
||||||
TraceObjectThread thread =
|
TraceObjectThread thread =
|
||||||
objects.getObjectByCanonicalPath(TraceObjectKeyPath.parse("Targets[0].Threads[0]"))
|
objects.getObjectByCanonicalPath(KeyPath.parse("Targets[0].Threads[0]"))
|
||||||
.queryInterface(TraceObjectThread.class);
|
.queryInterface(TraceObjectThread.class);
|
||||||
traceManager.activateThread(thread);
|
traceManager.activateThread(thread);
|
||||||
return thread;
|
return thread;
|
||||||
@@ -484,7 +484,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
tb.trace.getObjectManager()
|
tb.trace.getObjectManager()
|
||||||
.createObject(
|
.createObject(
|
||||||
TraceObjectKeyPath.parse("Targets[0].Threads[0].Stack[0].Registers"))
|
KeyPath.parse("Targets[0].Threads[0].Stack[0].Registers"))
|
||||||
.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
||||||
DBTraceMemorySpace regs = Objects.requireNonNull(
|
DBTraceMemorySpace regs = Objects.requireNonNull(
|
||||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true));
|
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true));
|
||||||
@@ -519,7 +519,7 @@ public class DebuggerDisassemblyTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
tb.trace.getObjectManager()
|
tb.trace.getObjectManager()
|
||||||
.createObject(
|
.createObject(
|
||||||
TraceObjectKeyPath.parse("Targets[0].Threads[0].Stack[0].Registers"))
|
KeyPath.parse("Targets[0].Threads[0].Stack[0].Registers"))
|
||||||
.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
||||||
DBTraceMemorySpace regs = Objects.requireNonNull(
|
DBTraceMemorySpace regs = Objects.requireNonNull(
|
||||||
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true));
|
tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true));
|
||||||
|
|||||||
@@ -51,8 +51,6 @@ import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerService
|
|||||||
import ghidra.app.services.*;
|
import ghidra.app.services.*;
|
||||||
import ghidra.app.util.viewer.listingpanel.ListingPanel;
|
import ghidra.app.util.viewer.listingpanel.ListingPanel;
|
||||||
import ghidra.async.AsyncTestUtils;
|
import ghidra.async.AsyncTestUtils;
|
||||||
import ghidra.dbg.target.schema.SchemaContext;
|
|
||||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
|
||||||
import ghidra.debug.api.action.LocationTrackingSpec;
|
import ghidra.debug.api.action.LocationTrackingSpec;
|
||||||
import ghidra.debug.api.action.LocationTrackingSpecFactory;
|
import ghidra.debug.api.action.LocationTrackingSpecFactory;
|
||||||
import ghidra.docking.settings.SettingsImpl;
|
import ghidra.docking.settings.SettingsImpl;
|
||||||
@@ -68,6 +66,8 @@ import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
|||||||
import ghidra.test.TestEnv;
|
import ghidra.test.TestEnv;
|
||||||
import ghidra.trace.database.ToyDBTraceBuilder;
|
import ghidra.trace.database.ToyDBTraceBuilder;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.target.schema.SchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||||
import ghidra.util.InvalidNameException;
|
import ghidra.util.InvalidNameException;
|
||||||
import ghidra.util.NumericUtilities;
|
import ghidra.util.NumericUtilities;
|
||||||
import ghidra.util.datastruct.TestDataStructureErrorHandlerInstaller;
|
import ghidra.util.datastruct.TestDataStructureErrorHandlerInstaller;
|
||||||
@@ -77,6 +77,39 @@ import ghidra.util.task.ConsoleTaskMonitor;
|
|||||||
public abstract class AbstractGhidraHeadedDebuggerTest
|
public abstract class AbstractGhidraHeadedDebuggerTest
|
||||||
extends AbstractGhidraHeadedIntegrationTest implements AsyncTestUtils {
|
extends AbstractGhidraHeadedIntegrationTest implements AsyncTestUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any test that uses staticall-initialized variables with any real complexity runs the risk of
|
||||||
|
* invoking the logger before said logger has been initialized. The abstract test case is
|
||||||
|
* responsible for initializing it, and it affords its subclasses the opportunity to override
|
||||||
|
* things like the application layout and configuration. Thus, we cannot initialize the
|
||||||
|
* application in the static initializer here. What will happen, then, is the logger will be
|
||||||
|
* partially initialized, and the XML config files refer to system properties that will not have
|
||||||
|
* been set yet. This manifests in strange files being created in the tests' working
|
||||||
|
* directories, e.g., <code>${sys:logFilename}</code>.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* A cheap hack to avoid this issue is to just initialize those system properties to some temp
|
||||||
|
* file. Once the logging system is initialized, the variables will be overwritten by the
|
||||||
|
* application config and the logger re- and fully-initialized. For what it's worth, the logging
|
||||||
|
* config for the test case is going to be a file in a temp directory, anyway. As long as it's
|
||||||
|
* cleaned up by the JVM or the OS, we should be happy. I just want to ensure they're not
|
||||||
|
* showing up in git commits.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* TODO: Should this hack be moved up into the super classes of the Ghidra Test framework?
|
||||||
|
*/
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
System.setProperty("logFilename",
|
||||||
|
Files.createTempFile("ghidraTest", ".log").toString());
|
||||||
|
System.setProperty("scriptLogFilename",
|
||||||
|
Files.createTempFile("ghidraTestScript", ".log").toString());
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static final String LANGID_TOYBE64 = "Toy:BE:64:default";
|
public static final String LANGID_TOYBE64 = "Toy:BE:64:default";
|
||||||
|
|
||||||
protected static byte[] arr(String hex) {
|
protected static byte[] arr(String hex) {
|
||||||
|
|||||||
@@ -36,10 +36,6 @@ import ghidra.app.plugin.core.debug.gui.memory.DebuggerRegionMapProposalDialog.R
|
|||||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueProperty;
|
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueProperty;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.QueryPanelTestHelper;
|
import ghidra.app.plugin.core.debug.gui.model.QueryPanelTestHelper;
|
||||||
import ghidra.dbg.target.TargetMemoryRegion;
|
|
||||||
import ghidra.dbg.target.schema.SchemaContext;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
|
||||||
import ghidra.debug.api.modules.RegionMapProposal.RegionMapEntry;
|
import ghidra.debug.api.modules.RegionMapProposal.RegionMapEntry;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
@@ -53,6 +49,10 @@ import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
|||||||
import ghidra.trace.model.modules.TraceStaticMapping;
|
import ghidra.trace.model.modules.TraceStaticMapping;
|
||||||
import ghidra.trace.model.target.*;
|
import ghidra.trace.model.target.*;
|
||||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
import ghidra.trace.model.target.schema.SchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
import ghidra.util.table.GhidraTable;
|
import ghidra.util.table.GhidraTable;
|
||||||
|
|
||||||
@Category(NightlyCategory.class)
|
@Category(NightlyCategory.class)
|
||||||
@@ -111,18 +111,18 @@ public class DebuggerRegionsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||||||
protected TraceObjectMemoryRegion addRegion(String name, long loaded, AddressRange range) {
|
protected TraceObjectMemoryRegion addRegion(String name, long loaded, AddressRange range) {
|
||||||
boolean isData = name.endsWith(".data");
|
boolean isData = name.endsWith(".data");
|
||||||
TraceObjectManager om = tb.trace.getObjectManager();
|
TraceObjectManager om = tb.trace.getObjectManager();
|
||||||
TraceObjectKeyPath memPath = TraceObjectKeyPath.parse("Memory");
|
KeyPath memPath = KeyPath.parse("Memory");
|
||||||
Lifespan span = Lifespan.nowOn(loaded);
|
Lifespan span = Lifespan.nowOn(loaded);
|
||||||
TraceObjectMemoryRegion region = Objects.requireNonNull(om.createObject(memPath.index(name))
|
TraceObjectMemoryRegion region = Objects.requireNonNull(om.createObject(memPath.index(name))
|
||||||
.insert(span, ConflictResolution.TRUNCATE)
|
.insert(span, ConflictResolution.TRUNCATE)
|
||||||
.getDestination(null)
|
.getDestination(null)
|
||||||
.queryInterface(TraceObjectMemoryRegion.class));
|
.queryInterface(TraceObjectMemoryRegion.class));
|
||||||
TraceObject obj = region.getObject();
|
TraceObject obj = region.getObject();
|
||||||
obj.setAttribute(span, TargetMemoryRegion.DISPLAY_ATTRIBUTE_NAME, name);
|
obj.setAttribute(span, TraceObjectMemoryRegion.KEY_DISPLAY, name);
|
||||||
obj.setAttribute(span, TargetMemoryRegion.RANGE_ATTRIBUTE_NAME, range);
|
obj.setAttribute(span, TraceObjectMemoryRegion.KEY_RANGE, range);
|
||||||
obj.setAttribute(span, TargetMemoryRegion.READABLE_ATTRIBUTE_NAME, true);
|
obj.setAttribute(span, TraceObjectMemoryRegion.KEY_READABLE, true);
|
||||||
obj.setAttribute(span, TargetMemoryRegion.WRITABLE_ATTRIBUTE_NAME, isData);
|
obj.setAttribute(span, TraceObjectMemoryRegion.KEY_WRITABLE, isData);
|
||||||
obj.setAttribute(span, TargetMemoryRegion.EXECUTABLE_ATTRIBUTE_NAME, !isData);
|
obj.setAttribute(span, TraceObjectMemoryRegion.KEY_EXECUTABLE, !isData);
|
||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,15 +38,16 @@ import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.ValueRow;
|
|||||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTreeModel.AbstractNode;
|
import ghidra.app.plugin.core.debug.gui.model.ObjectTreeModel.AbstractNode;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.PathTableModel.PathRow;
|
import ghidra.app.plugin.core.debug.gui.model.PathTableModel.PathRow;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.columns.*;
|
import ghidra.app.plugin.core.debug.gui.model.columns.*;
|
||||||
import ghidra.dbg.target.TargetEventScope;
|
|
||||||
import ghidra.dbg.target.TargetObject;
|
|
||||||
import ghidra.dbg.target.schema.SchemaContext;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.target.*;
|
import ghidra.trace.model.target.*;
|
||||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||||
|
import ghidra.trace.model.target.iface.TraceObjectEventScope;
|
||||||
|
import ghidra.trace.model.target.iface.TraceObjectInterface;
|
||||||
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
import ghidra.trace.model.target.schema.SchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
import ghidra.trace.model.thread.TraceObjectThread;
|
import ghidra.trace.model.thread.TraceObjectThread;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
|
|
||||||
@@ -150,7 +151,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
protected TraceObject createThread(long i, TraceObject prevThread) {
|
protected TraceObject createThread(long i, TraceObject prevThread) {
|
||||||
TraceObjectManager objects = tb.trace.getObjectManager();
|
TraceObjectManager objects = tb.trace.getObjectManager();
|
||||||
TraceObjectKeyPath threadContainerPath = TraceObjectKeyPath.parse("Processes[0].Threads");
|
KeyPath threadContainerPath = KeyPath.parse("Processes[0].Threads");
|
||||||
TraceObject thread = objects.createObject(threadContainerPath.index(i));
|
TraceObject thread = objects.createObject(threadContainerPath.index(i));
|
||||||
thread.insert(Lifespan.span(i, 10), ConflictResolution.DENY);
|
thread.insert(Lifespan.span(i, 10), ConflictResolution.DENY);
|
||||||
thread.insert(Lifespan.nowOn(10 + i), ConflictResolution.DENY);
|
thread.insert(Lifespan.nowOn(10 + i), ConflictResolution.DENY);
|
||||||
@@ -162,14 +163,14 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
prevThread.setAttribute(Lifespan.nowOn(i), "_next", thread);
|
prevThread.setAttribute(Lifespan.nowOn(i), "_next", thread);
|
||||||
}
|
}
|
||||||
objects.getRootObject()
|
objects.getRootObject()
|
||||||
.setAttribute(Lifespan.nowOn(i), TargetEventScope.EVENT_OBJECT_ATTRIBUTE_NAME,
|
.setAttribute(Lifespan.nowOn(i), TraceObjectEventScope.KEY_EVENT_THREAD,
|
||||||
thread);
|
thread);
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TraceObject createStack(TraceObject thread) {
|
protected TraceObject createStack(TraceObject thread) {
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
TraceObjectKeyPath stackPath = thread.getCanonicalPath().key("Stack");
|
KeyPath stackPath = thread.getCanonicalPath().key("Stack");
|
||||||
TraceObjectManager objects = tb.trace.getObjectManager();
|
TraceObjectManager objects = tb.trace.getObjectManager();
|
||||||
TraceObject stack = objects.createObject(stackPath);
|
TraceObject stack = objects.createObject(stackPath);
|
||||||
objects.createObject(stackPath.index(0))
|
objects.createObject(stackPath.index(0))
|
||||||
@@ -194,7 +195,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
TraceObjectManager objects = tb.trace.getObjectManager();
|
TraceObjectManager objects = tb.trace.getObjectManager();
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
createThread(10, objects.getObjectByCanonicalPath(
|
createThread(10, objects.getObjectByCanonicalPath(
|
||||||
TraceObjectKeyPath.parse("Processes[0].Threads[9]")));
|
KeyPath.parse("Processes[0].Threads[9]")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,7 +203,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
TraceObjectManager objects = tb.trace.getObjectManager();
|
TraceObjectManager objects = tb.trace.getObjectManager();
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
TraceObject handleContainer =
|
TraceObject handleContainer =
|
||||||
objects.createObject(TraceObjectKeyPath.parse("Processes[0].Handles"));
|
objects.createObject(KeyPath.parse("Processes[0].Handles"));
|
||||||
handleContainer.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
handleContainer.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
handleContainer.setElement(Lifespan.nowOn(-i), i,
|
handleContainer.setElement(Lifespan.nowOn(-i), i,
|
||||||
@@ -213,10 +214,10 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
protected void populateLinks() throws Throwable {
|
protected void populateLinks() throws Throwable {
|
||||||
TraceObjectManager objects = tb.trace.getObjectManager();
|
TraceObjectManager objects = tb.trace.getObjectManager();
|
||||||
TraceObjectKeyPath threadContainerPath = TraceObjectKeyPath.parse("Processes[0].Threads");
|
KeyPath threadContainerPath = KeyPath.parse("Processes[0].Threads");
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
TraceObject linkContainer =
|
TraceObject linkContainer =
|
||||||
objects.createObject(TraceObjectKeyPath.parse("Processes[0].Links"));
|
objects.createObject(KeyPath.parse("Processes[0].Links"));
|
||||||
linkContainer.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
linkContainer.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
linkContainer.setElement(Lifespan.nowOn(0), i,
|
linkContainer.setElement(Lifespan.nowOn(0), i,
|
||||||
@@ -229,10 +230,10 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
TraceObjectManager objects = tb.trace.getObjectManager();
|
TraceObjectManager objects = tb.trace.getObjectManager();
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
TraceObject boxed =
|
TraceObject boxed =
|
||||||
objects.createObject(TraceObjectKeyPath.parse("Processes[0].Boxed"));
|
objects.createObject(KeyPath.parse("Processes[0].Boxed"));
|
||||||
boxed.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
boxed.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
||||||
boxed.setAttribute(Lifespan.nowOn(2), TargetObject.DISPLAY_ATTRIBUTE_NAME, "2");
|
boxed.setAttribute(Lifespan.nowOn(2), TraceObjectInterface.KEY_DISPLAY, "2");
|
||||||
boxed.setAttribute(Lifespan.nowOn(4), TargetObject.DISPLAY_ATTRIBUTE_NAME, "4");
|
boxed.setAttribute(Lifespan.nowOn(4), TraceObjectInterface.KEY_DISPLAY, "4");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +247,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
populateBoxedPrimitive();
|
populateBoxedPrimitive();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertPathIs(TraceObjectKeyPath path, int elemCount, int attrCount) {
|
protected void assertPathIs(KeyPath path, int elemCount, int attrCount) {
|
||||||
assertEquals(path, modelProvider.getPath());
|
assertEquals(path, modelProvider.getPath());
|
||||||
assertEquals(path.toString(), modelProvider.pathField.getText());
|
assertEquals(path.toString(), modelProvider.pathField.getText());
|
||||||
// Table model is threaded
|
// Table model is threaded
|
||||||
@@ -257,22 +258,22 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void assertPathIsThreadsContainer() {
|
protected void assertPathIsThreadsContainer() {
|
||||||
assertPathIs(TraceObjectKeyPath.parse("Processes[0].Threads"), 10, 0);
|
assertPathIs(KeyPath.parse("Processes[0].Threads"), 10, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetPathWOutTrace() throws Throwable {
|
public void testSetPathWOutTrace() throws Throwable {
|
||||||
modelProvider.setPath(TraceObjectKeyPath.parse(""));
|
modelProvider.setPath(KeyPath.parse(""));
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
modelProvider.setPath(TraceObjectKeyPath.parse("Processes[0].Threads"));
|
modelProvider.setPath(KeyPath.parse("Processes[0].Threads"));
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
modelProvider.setPath(TraceObjectKeyPath.parse(""));
|
modelProvider.setPath(KeyPath.parse(""));
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSelectRootWOutTrace() throws Throwable {
|
public void testSelectRootWOutTrace() throws Throwable {
|
||||||
modelProvider.objectsTreePanel.setSelectedKeyPaths(Set.of(TraceObjectKeyPath.parse("")));
|
modelProvider.objectsTreePanel.setSelectedKeyPaths(Set.of(KeyPath.parse("")));
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,7 +284,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
modelProvider.objectsTreePanel.setSelectedKeyPaths(Set.of(TraceObjectKeyPath.parse("")));
|
modelProvider.objectsTreePanel.setSelectedKeyPaths(Set.of(KeyPath.parse("")));
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,7 +294,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
modelProvider.setPath(TraceObjectKeyPath.parse("Processes[0].Threads"));
|
modelProvider.setPath(KeyPath.parse("Processes[0].Threads"));
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
assertPathIsThreadsContainer();
|
assertPathIsThreadsContainer();
|
||||||
@@ -319,7 +320,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
modelProvider.objectsTreePanel
|
modelProvider.objectsTreePanel
|
||||||
.setSelectedKeyPaths(List.of(TraceObjectKeyPath.parse("Processes[0].Threads")));
|
.setSelectedKeyPaths(List.of(KeyPath.parse("Processes[0].Threads")));
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
waitForPass(() -> assertPathIsThreadsContainer());
|
waitForPass(() -> assertPathIsThreadsContainer());
|
||||||
@@ -331,7 +332,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
modelProvider.setPath(TraceObjectKeyPath.parse("Processes[0].Threads"));
|
modelProvider.setPath(KeyPath.parse("Processes[0].Threads"));
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
|
|
||||||
ValueRow selElem = waitForValue(() -> {
|
ValueRow selElem = waitForValue(() -> {
|
||||||
@@ -354,7 +355,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
modelProvider.activatePath(TraceObjectKeyPath.parse("Processes[0].NoSuch"));
|
modelProvider.activatePath(KeyPath.parse("Processes[0].NoSuch"));
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
|
|
||||||
assertEquals("No such object at path Processes[0].NoSuch", tool.getStatusInfo());
|
assertEquals("No such object at path Processes[0].NoSuch", tool.getStatusInfo());
|
||||||
@@ -366,7 +367,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
modelProvider.setPath(TraceObjectKeyPath.parse("Processes[0].Handles"));
|
modelProvider.setPath(KeyPath.parse("Processes[0].Handles"));
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
|
|
||||||
int keyColIndex =
|
int keyColIndex =
|
||||||
@@ -397,7 +398,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
modelProvider.setPath(TraceObjectKeyPath.parse("Processes[0].Threads"));
|
modelProvider.setPath(KeyPath.parse("Processes[0].Threads"));
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
|
|
||||||
modelProvider.pathField.setText("SomeNonsenseToBeCancelled");
|
modelProvider.pathField.setText("SomeNonsenseToBeCancelled");
|
||||||
@@ -413,7 +414,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
TraceObjectManager objects = tb.trace.getObjectManager();
|
TraceObjectManager objects = tb.trace.getObjectManager();
|
||||||
TraceObject root = objects.getRootObject();
|
TraceObject root = objects.getRootObject();
|
||||||
TraceObjectKeyPath process0Path = TraceObjectKeyPath.parse("Processes[0]");
|
KeyPath process0Path = KeyPath.parse("Processes[0]");
|
||||||
TraceObject process0 = objects.getObjectByCanonicalPath(process0Path);
|
TraceObject process0 = objects.getObjectByCanonicalPath(process0Path);
|
||||||
traceManager.activateObject(root);
|
traceManager.activateObject(root);
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
@@ -441,7 +442,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
TraceObjectKeyPath pathLinks = TraceObjectKeyPath.parse("Processes[0].Links");
|
KeyPath pathLinks = KeyPath.parse("Processes[0].Links");
|
||||||
modelProvider.setPath(pathLinks);
|
modelProvider.setPath(pathLinks);
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
|
|
||||||
@@ -463,7 +464,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
});
|
});
|
||||||
clickTableCell(modelProvider.elementsTablePanel.table, rowIndex, 0, 2);
|
clickTableCell(modelProvider.elementsTablePanel.table, rowIndex, 0, 2);
|
||||||
|
|
||||||
assertEquals(TraceObjectKeyPath.parse("Processes[0].Threads[7]"),
|
assertEquals(KeyPath.parse("Processes[0].Threads[7]"),
|
||||||
traceManager.getCurrentObject().getCanonicalPath());
|
traceManager.getCurrentObject().getCanonicalPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,7 +474,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
modelProvider.setPath(TraceObjectKeyPath.parse("Processes[0].Threads"));
|
modelProvider.setPath(KeyPath.parse("Processes[0].Threads"));
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
|
|
||||||
ValueRow row2 = waitForValue(() -> {
|
ValueRow row2 = waitForValue(() -> {
|
||||||
@@ -494,7 +495,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
});
|
});
|
||||||
clickTableCell(modelProvider.elementsTablePanel.table, rowIndex, 0, 2);
|
clickTableCell(modelProvider.elementsTablePanel.table, rowIndex, 0, 2);
|
||||||
|
|
||||||
assertEquals(TraceObjectKeyPath.parse("Processes[0].Threads[2]"),
|
assertEquals(KeyPath.parse("Processes[0].Threads[2]"),
|
||||||
traceManager.getCurrentObject().getCanonicalPath());
|
traceManager.getCurrentObject().getCanonicalPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,7 +523,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
modelProvider.setPath(TraceObjectKeyPath.parse("Processes[0].Threads[2]"));
|
modelProvider.setPath(KeyPath.parse("Processes[0].Threads[2]"));
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
selectAttribute("_next");
|
selectAttribute("_next");
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
@@ -536,7 +537,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
});
|
});
|
||||||
clickTableCell(modelProvider.attributesTablePanel.table, rowIndex, 0, 2);
|
clickTableCell(modelProvider.attributesTablePanel.table, rowIndex, 0, 2);
|
||||||
|
|
||||||
assertEquals(TraceObjectKeyPath.parse("Processes[0].Threads[3]"),
|
assertEquals(KeyPath.parse("Processes[0].Threads[3]"),
|
||||||
traceManager.getCurrentObject().getCanonicalPath());
|
traceManager.getCurrentObject().getCanonicalPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,7 +547,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
modelProvider.setPath(TraceObjectKeyPath.parse("Processes[0]"));
|
modelProvider.setPath(KeyPath.parse("Processes[0]"));
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
|
|
||||||
PathRow rowNext = waitForValue(() -> {
|
PathRow rowNext = waitForValue(() -> {
|
||||||
@@ -574,7 +575,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
clickTableCell(modelProvider.attributesTablePanel.table, rowIndex, 0, 2);
|
clickTableCell(modelProvider.attributesTablePanel.table, rowIndex, 0, 2);
|
||||||
|
|
||||||
// ThreadContainer is not activatable, so only changes provider's path
|
// ThreadContainer is not activatable, so only changes provider's path
|
||||||
assertEquals(TraceObjectKeyPath.parse("Processes[0].Threads"), modelProvider.getPath());
|
assertEquals(KeyPath.parse("Processes[0].Threads"), modelProvider.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -585,23 +586,23 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
modelProvider.setPath(TraceObjectKeyPath.parse("Processes[0].Threads"));
|
modelProvider.setPath(KeyPath.parse("Processes[0].Threads"));
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
|
|
||||||
assertPathIs(TraceObjectKeyPath.parse("Processes[0].Threads"), 10, 0);
|
assertPathIs(KeyPath.parse("Processes[0].Threads"), 10, 0);
|
||||||
|
|
||||||
performAction(modelProvider.actionLimitToCurrentSnap);
|
performAction(modelProvider.actionLimitToCurrentSnap);
|
||||||
assertTrue(modelProvider.isLimitToCurrentSnap());
|
assertTrue(modelProvider.isLimitToCurrentSnap());
|
||||||
assertTrue(modelProvider.actionLimitToCurrentSnap.isSelected());
|
assertTrue(modelProvider.actionLimitToCurrentSnap.isSelected());
|
||||||
assertPathIs(TraceObjectKeyPath.parse("Processes[0].Threads"), 1, 0);
|
assertPathIs(KeyPath.parse("Processes[0].Threads"), 1, 0);
|
||||||
|
|
||||||
traceManager.activateSnap(5);
|
traceManager.activateSnap(5);
|
||||||
assertPathIs(TraceObjectKeyPath.parse("Processes[0].Threads"), 6, 0);
|
assertPathIs(KeyPath.parse("Processes[0].Threads"), 6, 0);
|
||||||
|
|
||||||
performAction(modelProvider.actionLimitToCurrentSnap);
|
performAction(modelProvider.actionLimitToCurrentSnap);
|
||||||
assertFalse(modelProvider.isLimitToCurrentSnap());
|
assertFalse(modelProvider.isLimitToCurrentSnap());
|
||||||
assertFalse(modelProvider.actionLimitToCurrentSnap.isSelected());
|
assertFalse(modelProvider.actionLimitToCurrentSnap.isSelected());
|
||||||
assertPathIs(TraceObjectKeyPath.parse("Processes[0].Threads"), 10, 0);
|
assertPathIs(KeyPath.parse("Processes[0].Threads"), 10, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -611,7 +612,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
TraceObjectKeyPath thread2Path = TraceObjectKeyPath.parse("Processes[0].Threads[2]");
|
KeyPath thread2Path = KeyPath.parse("Processes[0].Threads[2]");
|
||||||
modelProvider.setPath(thread2Path);
|
modelProvider.setPath(thread2Path);
|
||||||
modelProvider.setTreeSelection(thread2Path);
|
modelProvider.setTreeSelection(thread2Path);
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
@@ -641,7 +642,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
modelProvider.setPath(TraceObjectKeyPath.parse("Processes[0].Threads[2]"));
|
modelProvider.setPath(KeyPath.parse("Processes[0].Threads[2]"));
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
selectAttribute("_next");
|
selectAttribute("_next");
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
@@ -651,7 +652,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
assertTrue(runSwing(() -> modelProvider.actionFollowLink.isEnabledForContext(ctx)));
|
assertTrue(runSwing(() -> modelProvider.actionFollowLink.isEnabledForContext(ctx)));
|
||||||
performAction(modelProvider.actionFollowLink, ctx, true);
|
performAction(modelProvider.actionFollowLink, ctx, true);
|
||||||
|
|
||||||
TraceObjectKeyPath thread3Path = TraceObjectKeyPath.parse("Processes[0].Threads[3]");
|
KeyPath thread3Path = KeyPath.parse("Processes[0].Threads[3]");
|
||||||
assertPathIs(thread3Path, 0, 5);
|
assertPathIs(thread3Path, 0, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -661,24 +662,24 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
modelProvider.setPath(TraceObjectKeyPath.parse("Processes[0].Threads[2]"));
|
modelProvider.setPath(KeyPath.parse("Processes[0].Threads[2]"));
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
|
|
||||||
// Pre-check
|
// Pre-check
|
||||||
assertEquals(TraceObjectKeyPath.parse("Processes[0].Threads[2]"), modelProvider.path);
|
assertEquals(KeyPath.parse("Processes[0].Threads[2]"), modelProvider.path);
|
||||||
|
|
||||||
performAction(modelProvider.actionCloneWindow);
|
performAction(modelProvider.actionCloneWindow);
|
||||||
|
|
||||||
DebuggerModelProvider clone = Unique.assertOne(modelPlugin.getDisconnectedProviders());
|
DebuggerModelProvider clone = Unique.assertOne(modelPlugin.getDisconnectedProviders());
|
||||||
|
|
||||||
assertEquals(tb.trace, clone.current.getTrace());
|
assertEquals(tb.trace, clone.current.getTrace());
|
||||||
assertEquals(TraceObjectKeyPath.parse("Processes[0].Threads[2]"), clone.path);
|
assertEquals(KeyPath.parse("Processes[0].Threads[2]"), clone.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPanesTrackAddElement() throws Throwable {
|
public void testPanesTrackAddElement() throws Throwable {
|
||||||
createTraceAndPopulateObjects();
|
createTraceAndPopulateObjects();
|
||||||
TraceObjectKeyPath path = TraceObjectKeyPath.parse("Processes[0].Threads");
|
KeyPath path = KeyPath.parse("Processes[0].Threads");
|
||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
@@ -696,7 +697,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
@Test
|
@Test
|
||||||
public void testPanesTrackAddAttribute() throws Throwable {
|
public void testPanesTrackAddAttribute() throws Throwable {
|
||||||
createTraceAndPopulateObjects();
|
createTraceAndPopulateObjects();
|
||||||
TraceObjectKeyPath path = TraceObjectKeyPath.parse("Processes[0].Threads[2]");
|
KeyPath path = KeyPath.parse("Processes[0].Threads[2]");
|
||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
@@ -717,7 +718,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
@Test
|
@Test
|
||||||
public void testPanesTrackRemoveElement() throws Throwable {
|
public void testPanesTrackRemoveElement() throws Throwable {
|
||||||
createTraceAndPopulateObjects();
|
createTraceAndPopulateObjects();
|
||||||
TraceObjectKeyPath path = TraceObjectKeyPath.parse("Processes[0].Threads");
|
KeyPath path = KeyPath.parse("Processes[0].Threads");
|
||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
@@ -738,7 +739,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
@Test
|
@Test
|
||||||
public void testPanesTrackRemoveAttribute() throws Throwable {
|
public void testPanesTrackRemoveAttribute() throws Throwable {
|
||||||
createTraceAndPopulateObjects();
|
createTraceAndPopulateObjects();
|
||||||
TraceObjectKeyPath path = TraceObjectKeyPath.parse("Processes[0].Threads[2]");
|
KeyPath path = KeyPath.parse("Processes[0].Threads[2]");
|
||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
@@ -760,7 +761,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
public void testPanesTrackLifespanChangedElement() throws Throwable {
|
public void testPanesTrackLifespanChangedElement() throws Throwable {
|
||||||
modelProvider.setLimitToCurrentSnap(true);
|
modelProvider.setLimitToCurrentSnap(true);
|
||||||
createTraceAndPopulateObjects();
|
createTraceAndPopulateObjects();
|
||||||
TraceObjectKeyPath path = TraceObjectKeyPath.parse("Processes[0].Threads");
|
KeyPath path = KeyPath.parse("Processes[0].Threads");
|
||||||
TraceObject threads = tb.trace.getObjectManager().getObjectByCanonicalPath(path);
|
TraceObject threads = tb.trace.getObjectManager().getObjectByCanonicalPath(path);
|
||||||
TraceObjectValue element2 = threads.getElement(2, 2);
|
TraceObjectValue element2 = threads.getElement(2, 2);
|
||||||
|
|
||||||
@@ -792,7 +793,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
modelProvider.setLimitToCurrentSnap(true);
|
modelProvider.setLimitToCurrentSnap(true);
|
||||||
modelProvider.setShowHidden(true);
|
modelProvider.setShowHidden(true);
|
||||||
createTraceAndPopulateObjects();
|
createTraceAndPopulateObjects();
|
||||||
TraceObjectKeyPath path = TraceObjectKeyPath.parse("Processes[0].Threads[2]");
|
KeyPath path = KeyPath.parse("Processes[0].Threads[2]");
|
||||||
TraceObject thread = tb.trace.getObjectManager().getObjectByCanonicalPath(path);
|
TraceObject thread = tb.trace.getObjectManager().getObjectByCanonicalPath(path);
|
||||||
TraceObjectValue attrSelf = thread.getAttribute(2, "_self");
|
TraceObjectValue attrSelf = thread.getAttribute(2, "_self");
|
||||||
|
|
||||||
@@ -822,7 +823,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
@Test
|
@Test
|
||||||
public void testTreeTracksDisplayChange() throws Throwable {
|
public void testTreeTracksDisplayChange() throws Throwable {
|
||||||
createTraceAndPopulateObjects();
|
createTraceAndPopulateObjects();
|
||||||
TraceObjectKeyPath path = TraceObjectKeyPath.parse("Processes[0].Threads[2]");
|
KeyPath path = KeyPath.parse("Processes[0].Threads[2]");
|
||||||
TraceObject thread = tb.trace.getObjectManager().getObjectByCanonicalPath(path);
|
TraceObject thread = tb.trace.getObjectManager().getObjectByCanonicalPath(path);
|
||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
@@ -848,7 +849,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
TraceObjectManager objects = tb.trace.getObjectManager();
|
TraceObjectManager objects = tb.trace.getObjectManager();
|
||||||
TraceObject root = objects.getRootObject();
|
TraceObject root = objects.getRootObject();
|
||||||
TraceObject process0 =
|
TraceObject process0 =
|
||||||
objects.getObjectByCanonicalPath(TraceObjectKeyPath.parse("Processes[0]"));
|
objects.getObjectByCanonicalPath(KeyPath.parse("Processes[0]"));
|
||||||
|
|
||||||
traceManager.activateObject(root);
|
traceManager.activateObject(root);
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
@@ -885,20 +886,20 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
createTraceAndPopulateObjects();
|
createTraceAndPopulateObjects();
|
||||||
TraceObjectManager objects = tb.trace.getObjectManager();
|
TraceObjectManager objects = tb.trace.getObjectManager();
|
||||||
TraceObject thread0 =
|
TraceObject thread0 =
|
||||||
objects.getObjectByCanonicalPath(TraceObjectKeyPath.parse("Processes[0].Threads[0]"));
|
objects.getObjectByCanonicalPath(KeyPath.parse("Processes[0].Threads[0]"));
|
||||||
TraceObject thread1 =
|
TraceObject thread1 =
|
||||||
objects.getObjectByCanonicalPath(TraceObjectKeyPath.parse("Processes[0].Threads[1]"));
|
objects.getObjectByCanonicalPath(KeyPath.parse("Processes[0].Threads[1]"));
|
||||||
|
|
||||||
modelProvider.setShowHidden(true);
|
modelProvider.setShowHidden(true);
|
||||||
traceManager.activateObject(thread0);
|
traceManager.activateObject(thread0);
|
||||||
traceManager.activateSnap(1);
|
traceManager.activateSnap(1);
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
modelProvider.setPath(TraceObjectKeyPath.parse("Processes[0].Threads[0]._self"));
|
modelProvider.setPath(KeyPath.parse("Processes[0].Threads[0]._self"));
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
|
|
||||||
traceManager.activateObject(thread1);
|
traceManager.activateObject(thread1);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
assertEquals(TraceObjectKeyPath.parse("Processes[0].Threads[0]._next"),
|
assertEquals(KeyPath.parse("Processes[0].Threads[0]._next"),
|
||||||
modelProvider.getPath());
|
modelProvider.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -906,7 +907,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
public void testObjectActivationSelectsElement() throws Throwable {
|
public void testObjectActivationSelectsElement() throws Throwable {
|
||||||
createTraceAndPopulateObjects();
|
createTraceAndPopulateObjects();
|
||||||
TraceObjectManager objects = tb.trace.getObjectManager();
|
TraceObjectManager objects = tb.trace.getObjectManager();
|
||||||
TraceObjectKeyPath processesPath = TraceObjectKeyPath.parse("Processes");
|
KeyPath processesPath = KeyPath.parse("Processes");
|
||||||
TraceObject processes = objects.getObjectByCanonicalPath(processesPath);
|
TraceObject processes = objects.getObjectByCanonicalPath(processesPath);
|
||||||
TraceObject process0 = processes.getElement(0, 0).getChild();
|
TraceObject process0 = processes.getElement(0, 0).getChild();
|
||||||
traceManager.activateObject(processes);
|
traceManager.activateObject(processes);
|
||||||
@@ -947,14 +948,14 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
traceManager.activateObject(processes);
|
traceManager.activateObject(processes);
|
||||||
waitForTasks();
|
waitForTasks();
|
||||||
|
|
||||||
assertEquals(TraceObjectKeyPath.of(), modelProvider.getPath());
|
assertEquals(KeyPath.of(), modelProvider.getPath());
|
||||||
assertEquals(processes, modelProvider.attributesTablePanel.getSelectedItem().getValue());
|
assertEquals(processes, modelProvider.attributesTablePanel.getSelectedItem().getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TraceThread populateThread0Stack() {
|
protected TraceThread populateThread0Stack() {
|
||||||
TraceObjectManager objects = tb.trace.getObjectManager();
|
TraceObjectManager objects = tb.trace.getObjectManager();
|
||||||
TraceObject threadObj0 =
|
TraceObject threadObj0 =
|
||||||
objects.getObjectByCanonicalPath(TraceObjectKeyPath.parse("Processes[0].Threads[0]"));
|
objects.getObjectByCanonicalPath(KeyPath.parse("Processes[0].Threads[0]"));
|
||||||
TraceThread thread0 = threadObj0.queryInterface(TraceObjectThread.class);
|
TraceThread thread0 = threadObj0.queryInterface(TraceObjectThread.class);
|
||||||
createStack(threadObj0);
|
createStack(threadObj0);
|
||||||
return thread0;
|
return thread0;
|
||||||
@@ -967,12 +968,12 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
traceManager.activate(DebuggerCoordinates.NOWHERE.thread(thread0).frame(0));
|
traceManager.activate(DebuggerCoordinates.NOWHERE.thread(thread0).frame(0));
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
assertEquals(TraceObjectKeyPath.parse("Processes[0].Threads[0].Stack[0]"),
|
assertEquals(KeyPath.parse("Processes[0].Threads[0].Stack[0]"),
|
||||||
modelProvider.getPath());
|
modelProvider.getPath());
|
||||||
|
|
||||||
traceManager.activateFrame(1);
|
traceManager.activateFrame(1);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
assertEquals(TraceObjectKeyPath.parse("Processes[0].Threads[0].Stack[1]"),
|
assertEquals(KeyPath.parse("Processes[0].Threads[0].Stack[1]"),
|
||||||
modelProvider.getPath());
|
modelProvider.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -980,7 +981,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
public void testFrameActivationSelectsElement() throws Throwable {
|
public void testFrameActivationSelectsElement() throws Throwable {
|
||||||
createTraceAndPopulateObjects();
|
createTraceAndPopulateObjects();
|
||||||
TraceThread thread0 = populateThread0Stack();
|
TraceThread thread0 = populateThread0Stack();
|
||||||
TraceObjectKeyPath stackPath = TraceObjectKeyPath.parse("Processes[0].Threads[0].Stack");
|
KeyPath stackPath = KeyPath.parse("Processes[0].Threads[0].Stack");
|
||||||
|
|
||||||
traceManager.activateThread(thread0);
|
traceManager.activateThread(thread0);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
@@ -1012,11 +1013,11 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
traceManager.activateThread(thread0);
|
traceManager.activateThread(thread0);
|
||||||
traceManager.activateSnap(1);
|
traceManager.activateSnap(1);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
assertEquals(TraceObjectKeyPath.parse("Processes[0].Threads[0]"), modelProvider.getPath());
|
assertEquals(KeyPath.parse("Processes[0].Threads[0]"), modelProvider.getPath());
|
||||||
|
|
||||||
traceManager.activateThread(thread1);
|
traceManager.activateThread(thread1);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
assertEquals(TraceObjectKeyPath.parse("Processes[0].Threads[1]"), modelProvider.getPath());
|
assertEquals(KeyPath.parse("Processes[0].Threads[1]"), modelProvider.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -1026,7 +1027,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
tb.trace.getThreadManager().getLiveThreadByPath(1, "Processes[0].Threads[0]");
|
tb.trace.getThreadManager().getLiveThreadByPath(1, "Processes[0].Threads[0]");
|
||||||
TraceThread thread1 =
|
TraceThread thread1 =
|
||||||
tb.trace.getThreadManager().getLiveThreadByPath(1, "Processes[0].Threads[1]");
|
tb.trace.getThreadManager().getLiveThreadByPath(1, "Processes[0].Threads[1]");
|
||||||
TraceObjectKeyPath threadsPath = TraceObjectKeyPath.parse("Processes[0].Threads");
|
KeyPath threadsPath = KeyPath.parse("Processes[0].Threads");
|
||||||
|
|
||||||
traceManager.activateTrace(tb.trace);
|
traceManager.activateTrace(tb.trace);
|
||||||
traceManager.activateSnap(1);
|
traceManager.activateSnap(1);
|
||||||
@@ -1053,7 +1054,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
public void testSetValueAffectsTree() throws Throwable {
|
public void testSetValueAffectsTree() throws Throwable {
|
||||||
createTraceAndPopulateObjects();
|
createTraceAndPopulateObjects();
|
||||||
|
|
||||||
TraceObjectKeyPath threadsPath = TraceObjectKeyPath.parse("Processes[0].Threads");
|
KeyPath threadsPath = KeyPath.parse("Processes[0].Threads");
|
||||||
TraceObject threads = tb.trace.getObjectManager().getObjectByCanonicalPath(threadsPath);
|
TraceObject threads = tb.trace.getObjectManager().getObjectByCanonicalPath(threadsPath);
|
||||||
TraceObject thread0 =
|
TraceObject thread0 =
|
||||||
tb.trace.getObjectManager().getObjectByCanonicalPath(threadsPath.index(0));
|
tb.trace.getObjectManager().getObjectByCanonicalPath(threadsPath.index(0));
|
||||||
@@ -1080,7 +1081,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
public void testDuplicateNameInSameParentDoesntCorruptTree() throws Throwable {
|
public void testDuplicateNameInSameParentDoesntCorruptTree() throws Throwable {
|
||||||
createTraceAndPopulateObjects();
|
createTraceAndPopulateObjects();
|
||||||
TraceObjectKeyPath threadsPath = TraceObjectKeyPath.parse("Processes[0].Threads");
|
KeyPath threadsPath = KeyPath.parse("Processes[0].Threads");
|
||||||
TraceObject threads = tb.trace.getObjectManager().getObjectByCanonicalPath(threadsPath);
|
TraceObject threads = tb.trace.getObjectManager().getObjectByCanonicalPath(threadsPath);
|
||||||
TraceObject thread0 =
|
TraceObject thread0 =
|
||||||
tb.trace.getObjectManager().getObjectByCanonicalPath(threadsPath.index(0));
|
tb.trace.getObjectManager().getObjectByCanonicalPath(threadsPath.index(0));
|
||||||
@@ -1123,7 +1124,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
@Test
|
@Test
|
||||||
public void testDuplicateNameDifferentLifespanAppearInAttributesTable() throws Throwable {
|
public void testDuplicateNameDifferentLifespanAppearInAttributesTable() throws Throwable {
|
||||||
createTraceAndPopulateObjects();
|
createTraceAndPopulateObjects();
|
||||||
TraceObjectKeyPath threadsPath = TraceObjectKeyPath.parse("Processes[0].Threads");
|
KeyPath threadsPath = KeyPath.parse("Processes[0].Threads");
|
||||||
TraceObject threads = tb.trace.getObjectManager().getObjectByCanonicalPath(threadsPath);
|
TraceObject threads = tb.trace.getObjectManager().getObjectByCanonicalPath(threadsPath);
|
||||||
TraceObject thread0 =
|
TraceObject thread0 =
|
||||||
tb.trace.getObjectManager().getObjectByCanonicalPath(threadsPath.index(0));
|
tb.trace.getObjectManager().getObjectByCanonicalPath(threadsPath.index(0));
|
||||||
@@ -1151,7 +1152,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
@Test
|
@Test
|
||||||
public void testDuplicateNameDifferentLifespanAppearInElementsTable() throws Throwable {
|
public void testDuplicateNameDifferentLifespanAppearInElementsTable() throws Throwable {
|
||||||
createTraceAndPopulateObjects();
|
createTraceAndPopulateObjects();
|
||||||
TraceObjectKeyPath threadsPath = TraceObjectKeyPath.parse("Processes[0].Threads");
|
KeyPath threadsPath = KeyPath.parse("Processes[0].Threads");
|
||||||
TraceObject threads = tb.trace.getObjectManager().getObjectByCanonicalPath(threadsPath);
|
TraceObject threads = tb.trace.getObjectManager().getObjectByCanonicalPath(threadsPath);
|
||||||
TraceObject thread0 =
|
TraceObject thread0 =
|
||||||
tb.trace.getObjectManager().getObjectByCanonicalPath(threadsPath.index(0));
|
tb.trace.getObjectManager().getObjectByCanonicalPath(threadsPath.index(0));
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -22,11 +22,11 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import db.Transaction;
|
import db.Transaction;
|
||||||
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest;
|
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest;
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.trace.database.target.DBTraceObjectManager;
|
import ghidra.trace.database.target.DBTraceObjectManager;
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||||
import ghidra.trace.model.target.TraceObjectKeyPath;
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
import ghidra.trace.model.target.TraceObjectValue;
|
import ghidra.trace.model.target.TraceObjectValue;
|
||||||
|
|
||||||
public class ModelQueryTest extends AbstractGhidraHeadedDebuggerTest {
|
public class ModelQueryTest extends AbstractGhidraHeadedDebuggerTest {
|
||||||
@@ -44,7 +44,7 @@ public class ModelQueryTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
objects.createRootObject(CTX.getSchema(new SchemaName("Session")));
|
objects.createRootObject(CTX.getSchema(new SchemaName("Session")));
|
||||||
|
|
||||||
TraceObjectValue thread0Val =
|
TraceObjectValue thread0Val =
|
||||||
objects.createObject(TraceObjectKeyPath.parse("Processes[0].Threads[0]"))
|
objects.createObject(KeyPath.parse("Processes[0].Threads[0]"))
|
||||||
.insert(Lifespan.nowOn(0), ConflictResolution.DENY)
|
.insert(Lifespan.nowOn(0), ConflictResolution.DENY)
|
||||||
.getLastEntry();
|
.getLastEntry();
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ public class ModelQueryTest extends AbstractGhidraHeadedDebuggerTest {
|
|||||||
objects.createRootObject(CTX.getSchema(new SchemaName("Session")));
|
objects.createRootObject(CTX.getSchema(new SchemaName("Session")));
|
||||||
|
|
||||||
TraceObjectValue thread0Val =
|
TraceObjectValue thread0Val =
|
||||||
objects.createObject(TraceObjectKeyPath.parse("Processes[0].Threads[0]"))
|
objects.createObject(KeyPath.parse("Processes[0].Threads[0]"))
|
||||||
.insert(Lifespan.nowOn(0), ConflictResolution.DENY)
|
.insert(Lifespan.nowOn(0), ConflictResolution.DENY)
|
||||||
.getLastEntry();
|
.getLastEntry();
|
||||||
|
|
||||||
|
|||||||
@@ -44,12 +44,6 @@ import ghidra.app.plugin.core.debug.gui.modules.DebuggerModulesProvider.MapSecti
|
|||||||
import ghidra.app.plugin.core.debug.gui.modules.DebuggerSectionMapProposalDialog.SectionMapTableColumns;
|
import ghidra.app.plugin.core.debug.gui.modules.DebuggerSectionMapProposalDialog.SectionMapTableColumns;
|
||||||
import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServiceTestAccess;
|
import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServiceTestAccess;
|
||||||
import ghidra.app.services.DebuggerListingService;
|
import ghidra.app.services.DebuggerListingService;
|
||||||
import ghidra.dbg.target.*;
|
|
||||||
import ghidra.dbg.target.schema.SchemaContext;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
|
||||||
import ghidra.dbg.util.PathPattern;
|
|
||||||
import ghidra.dbg.util.PathUtils;
|
|
||||||
import ghidra.debug.api.modules.ModuleMapProposal.ModuleMapEntry;
|
import ghidra.debug.api.modules.ModuleMapProposal.ModuleMapEntry;
|
||||||
import ghidra.debug.api.modules.SectionMapProposal.SectionMapEntry;
|
import ghidra.debug.api.modules.SectionMapProposal.SectionMapEntry;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
@@ -60,10 +54,16 @@ import ghidra.program.model.mem.MemoryBlock;
|
|||||||
import ghidra.trace.database.module.TraceObjectSection;
|
import ghidra.trace.database.module.TraceObjectSection;
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.Lifespan;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
|
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
||||||
import ghidra.trace.model.modules.TraceObjectModule;
|
import ghidra.trace.model.modules.TraceObjectModule;
|
||||||
import ghidra.trace.model.modules.TraceStaticMapping;
|
import ghidra.trace.model.modules.TraceStaticMapping;
|
||||||
import ghidra.trace.model.target.*;
|
import ghidra.trace.model.target.TraceObject;
|
||||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||||
|
import ghidra.trace.model.target.TraceObjectManager;
|
||||||
|
import ghidra.trace.model.target.path.*;
|
||||||
|
import ghidra.trace.model.target.schema.SchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
|
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||||
import ghidra.util.table.GhidraTable;
|
import ghidra.util.table.GhidraTable;
|
||||||
|
|
||||||
@Category(NightlyCategory.class)
|
@Category(NightlyCategory.class)
|
||||||
@@ -139,32 +139,33 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void addRegionsFromModules() throws Exception {
|
protected void addRegionsFromModules() throws Exception {
|
||||||
PathPattern regionPattern = new PathPattern(PathUtils.parse("Processes[1].Memory[]"));
|
PathPattern regionPattern = PathFilter.parse("Processes[1].Memory[]");
|
||||||
TraceObjectManager om = tb.trace.getObjectManager();
|
TraceObjectManager om = tb.trace.getObjectManager();
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
TraceObject root = om.getRootObject();
|
TraceObject root = om.getRootObject();
|
||||||
for (TraceObject module : (Iterable<TraceObject>) () -> root
|
for (TraceObject module : (Iterable<TraceObject>) () -> root
|
||||||
.querySuccessorsTargetInterface(Lifespan.at(0), TargetModule.class, true)
|
.findSuccessorsInterface(Lifespan.at(0), TraceObjectModule.class, true)
|
||||||
.map(p -> p.getDestination(root))
|
.map(p -> p.getDestination(root))
|
||||||
.iterator()) {
|
.iterator()) {
|
||||||
String moduleName = module.getCanonicalPath().index();
|
String moduleName = module.getCanonicalPath().index();
|
||||||
Lifespan span = module.getLife().bound();
|
Lifespan span = module.getLife().bound();
|
||||||
for (TraceObject section : (Iterable<TraceObject>) () -> module
|
for (TraceObject section : (Iterable<TraceObject>) () -> module
|
||||||
.querySuccessorsTargetInterface(Lifespan.at(0), TargetSection.class, true)
|
.findSuccessorsInterface(Lifespan.at(0), TraceObjectSection.class,
|
||||||
|
true)
|
||||||
.map(p -> p.getDestination(root))
|
.map(p -> p.getDestination(root))
|
||||||
.iterator()) {
|
.iterator()) {
|
||||||
String sectionName = section.getCanonicalPath().index();
|
String sectionName = section.getCanonicalPath().index();
|
||||||
TraceObject region = om.createObject(TraceObjectKeyPath
|
TraceObject region = om
|
||||||
.of(regionPattern.applyKeys(moduleName + ":" + sectionName)
|
.createObject(regionPattern.applyKeys(moduleName + ":" + sectionName)
|
||||||
.getSingletonPath()))
|
.getSingletonPath())
|
||||||
.insert(span, ConflictResolution.TRUNCATE)
|
.insert(span, ConflictResolution.TRUNCATE)
|
||||||
.getDestination(root);
|
.getDestination(root);
|
||||||
region.setAttribute(span, TargetMemoryRegion.RANGE_ATTRIBUTE_NAME,
|
region.setAttribute(span, TraceObjectMemoryRegion.KEY_RANGE,
|
||||||
section.getAttribute(0, TargetSection.RANGE_ATTRIBUTE_NAME).getValue());
|
section.getAttribute(0, TraceObjectSection.KEY_RANGE).getValue());
|
||||||
region.setAttribute(span, TargetMemoryRegion.READABLE_ATTRIBUTE_NAME, true);
|
region.setAttribute(span, TraceObjectMemoryRegion.KEY_READABLE, true);
|
||||||
region.setAttribute(span, TargetMemoryRegion.WRITABLE_ATTRIBUTE_NAME,
|
region.setAttribute(span, TraceObjectMemoryRegion.KEY_WRITABLE,
|
||||||
".data".equals(sectionName));
|
".data".equals(sectionName));
|
||||||
region.setAttribute(span, TargetMemoryRegion.EXECUTABLE_ATTRIBUTE_NAME,
|
region.setAttribute(span, TraceObjectMemoryRegion.KEY_EXECUTABLE,
|
||||||
".text".equals(sectionName));
|
".text".equals(sectionName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,15 +173,15 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected TraceObjectModule addModule(String name, AddressRange range, Lifespan span) {
|
protected TraceObjectModule addModule(String name, AddressRange range, Lifespan span) {
|
||||||
PathPattern modulePattern = new PathPattern(PathUtils.parse("Processes[1].Modules[]"));
|
PathPattern modulePattern = PathFilter.parse("Processes[1].Modules[]");
|
||||||
TraceObjectManager om = tb.trace.getObjectManager();
|
TraceObjectManager om = tb.trace.getObjectManager();
|
||||||
TraceObjectModule module = Objects.requireNonNull(
|
TraceObjectModule module = Objects.requireNonNull(
|
||||||
om.createObject(TraceObjectKeyPath.of(modulePattern.applyKeys(name).getSingletonPath()))
|
om.createObject(modulePattern.applyKeys(name).getSingletonPath())
|
||||||
.insert(span, ConflictResolution.TRUNCATE)
|
.insert(span, ConflictResolution.TRUNCATE)
|
||||||
.getDestination(null)
|
.getDestination(null)
|
||||||
.queryInterface(TraceObjectModule.class));
|
.queryInterface(TraceObjectModule.class));
|
||||||
module.getObject().setAttribute(span, TargetModule.MODULE_NAME_ATTRIBUTE_NAME, name);
|
module.getObject().setAttribute(span, TraceObjectModule.KEY_MODULE_NAME, name);
|
||||||
module.getObject().setAttribute(span, TargetModule.RANGE_ATTRIBUTE_NAME, range);
|
module.getObject().setAttribute(span, TraceObjectModule.KEY_RANGE, range);
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,7 +195,7 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||||||
.insert(span, ConflictResolution.TRUNCATE)
|
.insert(span, ConflictResolution.TRUNCATE)
|
||||||
.getDestination(null)
|
.getDestination(null)
|
||||||
.queryInterface(TraceObjectSection.class));
|
.queryInterface(TraceObjectSection.class));
|
||||||
section.getObject().setAttribute(span, TargetSection.RANGE_ATTRIBUTE_NAME, range);
|
section.getObject().setAttribute(span, TraceObjectSection.KEY_RANGE, range);
|
||||||
return section;
|
return section;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -717,7 +718,7 @@ public class DebuggerModulesProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||||||
for (ValueRow row : visibleSections()) {
|
for (ValueRow row : visibleSections()) {
|
||||||
assertEquals(modExe.getObject(), row.getValue()
|
assertEquals(modExe.getObject(), row.getValue()
|
||||||
.getChild()
|
.getChild()
|
||||||
.queryCanonicalAncestorsTargetInterface(TargetModule.class)
|
.findCanonicalAncestorsInterface(TraceObjectModule.class)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(null));
|
.orElse(null));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -33,13 +33,6 @@ import ghidra.app.plugin.core.debug.gui.model.QueryPanelTestHelper;
|
|||||||
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingServicePlugin;
|
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingServicePlugin;
|
||||||
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils;
|
||||||
import ghidra.app.services.DebuggerStaticMappingService;
|
import ghidra.app.services.DebuggerStaticMappingService;
|
||||||
import ghidra.dbg.target.TargetMemoryRegion;
|
|
||||||
import ghidra.dbg.target.TargetStackFrame;
|
|
||||||
import ghidra.dbg.target.schema.SchemaContext;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
|
||||||
import ghidra.dbg.util.PathPattern;
|
|
||||||
import ghidra.dbg.util.PathUtils;
|
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSet;
|
import ghidra.program.model.address.AddressSet;
|
||||||
@@ -50,8 +43,14 @@ import ghidra.program.util.ProgramLocation;
|
|||||||
import ghidra.trace.model.*;
|
import ghidra.trace.model.*;
|
||||||
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
import ghidra.trace.model.memory.TraceObjectMemoryRegion;
|
||||||
import ghidra.trace.model.stack.TraceObjectStack;
|
import ghidra.trace.model.stack.TraceObjectStack;
|
||||||
import ghidra.trace.model.target.*;
|
import ghidra.trace.model.stack.TraceObjectStackFrame;
|
||||||
|
import ghidra.trace.model.target.TraceObject;
|
||||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||||
|
import ghidra.trace.model.target.TraceObjectManager;
|
||||||
|
import ghidra.trace.model.target.path.*;
|
||||||
|
import ghidra.trace.model.target.schema.SchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
|
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||||
import ghidra.trace.model.thread.TraceObjectThread;
|
import ghidra.trace.model.thread.TraceObjectThread;
|
||||||
import ghidra.util.table.GhidraTable;
|
import ghidra.util.table.GhidraTable;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
@@ -169,9 +168,8 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected TraceObjectThread addThread(int n) {
|
protected TraceObjectThread addThread(int n) {
|
||||||
PathPattern threadPattern = new PathPattern(PathUtils.parse("Processes[1].Threads[]"));
|
PathPattern threadPattern = PathFilter.parse("Processes[1].Threads[]");
|
||||||
TraceObjectKeyPath threadPath =
|
KeyPath threadPath = threadPattern.applyIntKeys(n).getSingletonPath();
|
||||||
TraceObjectKeyPath.of(threadPattern.applyIntKeys(n).getSingletonPath());
|
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
return Objects.requireNonNull(tb.trace.getObjectManager()
|
return Objects.requireNonNull(tb.trace.getObjectManager()
|
||||||
.createObject(threadPath)
|
.createObject(threadPath)
|
||||||
@@ -182,7 +180,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected TraceObjectStack addStack(TraceObjectThread thread) {
|
protected TraceObjectStack addStack(TraceObjectThread thread) {
|
||||||
TraceObjectKeyPath stackPath = thread.getObject().getCanonicalPath().extend("Stack");
|
KeyPath stackPath = thread.getObject().getCanonicalPath().extend("Stack");
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
return Objects.requireNonNull(tb.trace.getObjectManager()
|
return Objects.requireNonNull(tb.trace.getObjectManager()
|
||||||
.createObject(stackPath)
|
.createObject(stackPath)
|
||||||
@@ -197,14 +195,14 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void addStackFrames(TraceObjectStack stack, int count) {
|
protected void addStackFrames(TraceObjectStack stack, int count) {
|
||||||
TraceObjectKeyPath stackPath = stack.getObject().getCanonicalPath();
|
KeyPath stackPath = stack.getObject().getCanonicalPath();
|
||||||
TraceObjectManager om = tb.trace.getObjectManager();
|
TraceObjectManager om = tb.trace.getObjectManager();
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
TraceObject frame = om.createObject(stackPath.index(i))
|
TraceObject frame = om.createObject(stackPath.index(i))
|
||||||
.insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE)
|
.insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE)
|
||||||
.getDestination(null);
|
.getDestination(null);
|
||||||
frame.setAttribute(Lifespan.nowOn(0), TargetStackFrame.PC_ATTRIBUTE_NAME,
|
frame.setAttribute(Lifespan.nowOn(0), TraceObjectStackFrame.KEY_PC,
|
||||||
tb.addr(0x00400100 + 0x100 * i));
|
tb.addr(0x00400100 + 0x100 * i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,7 +231,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
.getColumnByNameAndType(tableModel, table, "Function", ValueProperty.class)
|
.getColumnByNameAndType(tableModel, table, "Function", ValueProperty.class)
|
||||||
.column();
|
.column();
|
||||||
|
|
||||||
assertEquals(PathUtils.makeKey(PathUtils.makeIndex(level)), rowColVal(row, levelCol));
|
assertEquals(KeyPath.makeKey(KeyPath.makeIndex(level)), rowColVal(row, levelCol));
|
||||||
assertEquals(pcVal, rowColVal(row, pcCol));
|
assertEquals(pcVal, rowColVal(row, pcCol));
|
||||||
assertEquals(func, rowColVal(row, funcCol));
|
assertEquals(func, rowColVal(row, funcCol));
|
||||||
}
|
}
|
||||||
@@ -334,7 +332,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
assertTableSize(15);
|
assertTableSize(15);
|
||||||
List<ValueRow> allItems = stackProvider.panel.getAllItems();
|
List<ValueRow> allItems = stackProvider.panel.getAllItems();
|
||||||
for (int i = 0; i < 15; i++) {
|
for (int i = 0; i < 15; i++) {
|
||||||
assertEquals(PathUtils.makeKey(PathUtils.makeIndex(i)), allItems.get(i).getKey());
|
assertEquals(KeyPath.makeKey(KeyPath.makeIndex(i)), allItems.get(i).getKey());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -358,7 +356,7 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
.createObject(stack.getObject().getCanonicalPath().index(2))
|
.createObject(stack.getObject().getCanonicalPath().index(2))
|
||||||
.insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE)
|
.insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE)
|
||||||
.getDestination(null);
|
.getDestination(null);
|
||||||
frame2.setAttribute(Lifespan.nowOn(0), TargetStackFrame.PC_ATTRIBUTE_NAME,
|
frame2.setAttribute(Lifespan.nowOn(0), TraceObjectStackFrame.KEY_PC,
|
||||||
tb.addr(0x00400300));
|
tb.addr(0x00400300));
|
||||||
}
|
}
|
||||||
waitForDomainObject(tb.trace);
|
waitForDomainObject(tb.trace);
|
||||||
@@ -583,12 +581,12 @@ public class DebuggerStackProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
try (Transaction tx = tb.startTransaction()) {
|
try (Transaction tx = tb.startTransaction()) {
|
||||||
TraceObjectMemoryRegion region = Objects.requireNonNull(tb.trace.getObjectManager()
|
TraceObjectMemoryRegion region = Objects.requireNonNull(tb.trace.getObjectManager()
|
||||||
.createObject(TraceObjectKeyPath.parse("Processes[1].Memory[bin:.text]"))
|
.createObject(KeyPath.parse("Processes[1].Memory[bin:.text]"))
|
||||||
.insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE)
|
.insert(Lifespan.nowOn(0), ConflictResolution.TRUNCATE)
|
||||||
.getDestination(null)
|
.getDestination(null)
|
||||||
.queryInterface(TraceObjectMemoryRegion.class));
|
.queryInterface(TraceObjectMemoryRegion.class));
|
||||||
region.getObject()
|
region.getObject()
|
||||||
.setAttribute(Lifespan.nowOn(0), TargetMemoryRegion.RANGE_ATTRIBUTE_NAME,
|
.setAttribute(Lifespan.nowOn(0), TraceObjectMemoryRegion.KEY_RANGE,
|
||||||
tb.drng(0x00400000, 0x00400fff));
|
tb.drng(0x00400000, 0x00400fff));
|
||||||
|
|
||||||
TraceLocation dloc =
|
TraceLocation dloc =
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -30,19 +30,16 @@ import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest;
|
|||||||
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.*;
|
import ghidra.app.plugin.core.debug.gui.model.ObjectTableModel.*;
|
||||||
import ghidra.app.plugin.core.debug.gui.model.QueryPanelTestHelper;
|
import ghidra.app.plugin.core.debug.gui.model.QueryPanelTestHelper;
|
||||||
import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServiceTestAccess;
|
import ghidra.app.plugin.core.debug.service.tracemgr.DebuggerTraceManagerServiceTestAccess;
|
||||||
import ghidra.dbg.target.TargetExecutionStateful;
|
|
||||||
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
|
||||||
import ghidra.dbg.target.schema.SchemaContext;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
|
||||||
import ghidra.dbg.util.PathPattern;
|
|
||||||
import ghidra.dbg.util.PathUtils;
|
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.trace.model.Lifespan;
|
import ghidra.trace.model.*;
|
||||||
import ghidra.trace.model.Trace;
|
|
||||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||||
import ghidra.trace.model.target.TraceObjectKeyPath;
|
|
||||||
import ghidra.trace.model.target.TraceObjectManager;
|
import ghidra.trace.model.target.TraceObjectManager;
|
||||||
|
import ghidra.trace.model.target.iface.TraceObjectExecutionStateful;
|
||||||
|
import ghidra.trace.model.target.path.PathFilter;
|
||||||
|
import ghidra.trace.model.target.path.PathPattern;
|
||||||
|
import ghidra.trace.model.target.schema.SchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
|
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||||
import ghidra.trace.model.thread.TraceObjectThread;
|
import ghidra.trace.model.thread.TraceObjectThread;
|
||||||
import ghidra.trace.model.time.TraceTimeManager;
|
import ghidra.trace.model.time.TraceTimeManager;
|
||||||
import ghidra.util.table.GhidraTable;
|
import ghidra.util.table.GhidraTable;
|
||||||
@@ -100,15 +97,15 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||||||
|
|
||||||
protected TraceObjectThread addThread(int index, Lifespan lifespan, String comment) {
|
protected TraceObjectThread addThread(int index, Lifespan lifespan, String comment) {
|
||||||
TraceObjectManager om = tb.trace.getObjectManager();
|
TraceObjectManager om = tb.trace.getObjectManager();
|
||||||
PathPattern threadPattern = new PathPattern(PathUtils.parse("Processes[1].Threads[]"));
|
PathPattern threadPattern = PathFilter.parse("Processes[1].Threads[]");
|
||||||
TraceObjectThread thread = Objects.requireNonNull(om.createObject(
|
TraceObjectThread thread = Objects.requireNonNull(om.createObject(
|
||||||
TraceObjectKeyPath.of(threadPattern.applyIntKeys(index).getSingletonPath()))
|
threadPattern.applyIntKeys(index).getSingletonPath())
|
||||||
.insert(lifespan, ConflictResolution.TRUNCATE)
|
.insert(lifespan, ConflictResolution.TRUNCATE)
|
||||||
.getDestination(null)
|
.getDestination(null)
|
||||||
.queryInterface(TraceObjectThread.class));
|
.queryInterface(TraceObjectThread.class));
|
||||||
thread.getObject()
|
thread.getObject()
|
||||||
.setAttribute(lifespan, TargetExecutionStateful.STATE_ATTRIBUTE_NAME,
|
.setAttribute(lifespan, TraceObjectExecutionStateful.KEY_STATE,
|
||||||
TargetExecutionState.STOPPED.name());
|
TraceExecutionState.STOPPED.name());
|
||||||
thread.getObject().setAttribute(lifespan, TraceObjectThread.KEY_COMMENT, comment);
|
thread.getObject().setAttribute(lifespan, TraceObjectThread.KEY_COMMENT, comment);
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
@@ -129,7 +126,7 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void assertThreadRow(int position, Object object, String name,
|
protected void assertThreadRow(int position, Object object, String name,
|
||||||
TargetExecutionState state, String comment) {
|
TraceExecutionState state, String comment) {
|
||||||
// NB. Not testing plot, since that's unmodified from generic ObjectTable
|
// NB. Not testing plot, since that's unmodified from generic ObjectTable
|
||||||
ValueRow row = provider.panel.getAllItems().get(position);
|
ValueRow row = provider.panel.getAllItems().get(position);
|
||||||
var tableModel = QueryPanelTestHelper.getTableModel(provider.panel);
|
var tableModel = QueryPanelTestHelper.getTableModel(provider.panel);
|
||||||
@@ -154,9 +151,9 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||||||
assertThreadsTableSize(2);
|
assertThreadsTableSize(2);
|
||||||
|
|
||||||
assertThreadRow(0, thread1.getObject(), "Processes[1].Threads[1]",
|
assertThreadRow(0, thread1.getObject(), "Processes[1].Threads[1]",
|
||||||
TargetExecutionState.STOPPED, "A comment");
|
TraceExecutionState.STOPPED, "A comment");
|
||||||
assertThreadRow(1, thread2.getObject(), "Processes[1].Threads[2]",
|
assertThreadRow(1, thread2.getObject(), "Processes[1].Threads[2]",
|
||||||
TargetExecutionState.STOPPED, "Another comment");
|
TraceExecutionState.STOPPED, "Another comment");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertNoThreadSelected() {
|
protected void assertNoThreadSelected() {
|
||||||
@@ -289,7 +286,7 @@ public class DebuggerThreadsProviderTest extends AbstractGhidraHeadedDebuggerTes
|
|||||||
|
|
||||||
waitForPass(() -> {
|
waitForPass(() -> {
|
||||||
assertThreadRow(0, thread1.getObject(), "Processes[1].Threads[1]",
|
assertThreadRow(0, thread1.getObject(), "Processes[1].Threads[1]",
|
||||||
TargetExecutionState.STOPPED, "A comment");
|
TraceExecutionState.STOPPED, "A comment");
|
||||||
});
|
});
|
||||||
// NOTE: Destruction will not be visible in plot unless snapshot 15 is created
|
// NOTE: Destruction will not be visible in plot unless snapshot 15 is created
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,19 +21,19 @@ import java.util.concurrent.CompletableFuture;
|
|||||||
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import ghidra.async.AsyncUtils;
|
import ghidra.async.AsyncUtils;
|
||||||
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
|
||||||
import ghidra.debug.api.target.ActionName;
|
import ghidra.debug.api.target.ActionName;
|
||||||
import ghidra.debug.api.target.Target;
|
import ghidra.debug.api.target.Target;
|
||||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
import ghidra.program.model.lang.RegisterValue;
|
import ghidra.program.model.lang.RegisterValue;
|
||||||
|
import ghidra.trace.model.TraceExecutionState;
|
||||||
import ghidra.trace.model.Trace;
|
import ghidra.trace.model.Trace;
|
||||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||||
import ghidra.trace.model.guest.TracePlatform;
|
import ghidra.trace.model.guest.TracePlatform;
|
||||||
import ghidra.trace.model.stack.TraceStackFrame;
|
import ghidra.trace.model.stack.TraceStackFrame;
|
||||||
import ghidra.trace.model.target.TraceObjectKeyPath;
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
import ghidra.trace.model.thread.TraceThread;
|
import ghidra.trace.model.thread.TraceThread;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
@@ -76,17 +76,17 @@ public class MockTarget implements Target {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TraceThread getThreadForSuccessor(TraceObjectKeyPath path) {
|
public TraceThread getThreadForSuccessor(KeyPath path) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TargetExecutionState getThreadExecutionState(TraceThread thread) {
|
public TraceExecutionState getThreadExecutionState(TraceThread thread) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TraceStackFrame getStackFrameForSuccessor(TraceObjectKeyPath path) {
|
public TraceStackFrame getStackFrameForSuccessor(KeyPath path) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ public class MockTarget implements Target {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TraceObjectKeyPath getFocus() {
|
public KeyPath getFocus() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,9 +28,6 @@ import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerTest;
|
|||||||
import ghidra.app.plugin.core.debug.gui.modules.DebuggerModulesProviderTest;
|
import ghidra.app.plugin.core.debug.gui.modules.DebuggerModulesProviderTest;
|
||||||
import ghidra.app.services.DebuggerStaticMappingService;
|
import ghidra.app.services.DebuggerStaticMappingService;
|
||||||
import ghidra.app.services.DebuggerStaticMappingService.MappedAddressRange;
|
import ghidra.app.services.DebuggerStaticMappingService.MappedAddressRange;
|
||||||
import ghidra.dbg.target.schema.SchemaContext;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.SchemaName;
|
|
||||||
import ghidra.dbg.target.schema.XmlSchemaContext;
|
|
||||||
import ghidra.framework.model.DomainFile;
|
import ghidra.framework.model.DomainFile;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
@@ -44,7 +41,10 @@ import ghidra.trace.model.memory.TraceMemoryFlag;
|
|||||||
import ghidra.trace.model.memory.TraceMemoryRegion;
|
import ghidra.trace.model.memory.TraceMemoryRegion;
|
||||||
import ghidra.trace.model.modules.*;
|
import ghidra.trace.model.modules.*;
|
||||||
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
import ghidra.trace.model.target.TraceObject.ConflictResolution;
|
||||||
import ghidra.trace.model.target.TraceObjectKeyPath;
|
import ghidra.trace.model.target.path.KeyPath;
|
||||||
|
import ghidra.trace.model.target.schema.SchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.XmlSchemaContext;
|
||||||
|
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
// Not technically a GUI test, but must be carried out in the context of a plugin tool
|
// Not technically a GUI test, but must be carried out in the context of a plugin tool
|
||||||
@@ -684,7 +684,7 @@ public class DebuggerStaticMappingServiceTest extends AbstractGhidraHeadedDebugg
|
|||||||
DBTraceObjectManager objects = tb.trace.getObjectManager();
|
DBTraceObjectManager objects = tb.trace.getObjectManager();
|
||||||
objects.createRootObject(ctx.getSchema(new SchemaName("Session")));
|
objects.createRootObject(ctx.getSchema(new SchemaName("Session")));
|
||||||
objModBash =
|
objModBash =
|
||||||
objects.createObject(TraceObjectKeyPath.parse("Processes[1].Modules[/bin/bash]"));
|
objects.createObject(KeyPath.parse("Processes[1].Modules[/bin/bash]"));
|
||||||
objModBash.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
objModBash.insert(Lifespan.nowOn(0), ConflictResolution.DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
MODULE FILE LICENSE: lib/jna-5.14.0.jar Apache License 2.0
|
|
||||||
MODULE FILE LICENSE: lib/jna-platform-5.14.0.jar Apache License 2.0
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
# Framework-Debugging
|
|
||||||
@@ -1,172 +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.
|
|
||||||
*/
|
|
||||||
apply from: "${rootProject.projectDir}/gradle/javaProject.gradle"
|
|
||||||
apply from: "${rootProject.projectDir}/gradle/jacocoProject.gradle"
|
|
||||||
apply from: "${rootProject.projectDir}/gradle/javaTestProject.gradle"
|
|
||||||
apply from: "${rootProject.projectDir}/gradle/nativeProject.gradle"
|
|
||||||
apply from: "${rootProject.projectDir}/gradle/distributableGhidraModule.gradle"
|
|
||||||
|
|
||||||
apply plugin: 'eclipse'
|
|
||||||
eclipse.project.name = 'Debug Framework-Debugging'
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
api project(':Framework-AsyncComm')
|
|
||||||
api project(':Generic')
|
|
||||||
api project(':SoftwareModeling')
|
|
||||||
api project(':ProposedUtils')
|
|
||||||
|
|
||||||
api "net.java.dev.jna:jna:5.14.0"
|
|
||||||
api "net.java.dev.jna:jna-platform:5.14.0"
|
|
||||||
|
|
||||||
testImplementation project(path: ':Framework-AsyncComm', configuration: 'testArtifacts')
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the below native test binaries don't get built for a distribution
|
|
||||||
ext.nativesTestOnly = true
|
|
||||||
|
|
||||||
task testSpecimenWin_x86_64 {
|
|
||||||
dependsOn 'expCreateProcessWin_x86_64Executable'
|
|
||||||
dependsOn 'expCreateThreadExitWin_x86_64Executable'
|
|
||||||
//dependsOn 'expCreateThreadSpinWin_x86_64Executable'
|
|
||||||
dependsOn 'expPrintWin_x86_64Executable'
|
|
||||||
//dependsOn 'expSpinWin_x86_64Executable'
|
|
||||||
dependsOn 'expRegistersWin_x86_64Executable'
|
|
||||||
dependsOn 'expStackWin_x86_64Executable'
|
|
||||||
}
|
|
||||||
|
|
||||||
task testSpecimenLinux_x86_64 {
|
|
||||||
dependsOn 'expCloneExecExecutable'//Linux_x86_64Executable'
|
|
||||||
dependsOn 'expCloneExitLinux_x86_64Executable'
|
|
||||||
//dependsOn 'expCloneSpinExecutable'//Linux_x86_64Executable'
|
|
||||||
dependsOn 'expForkExecutable'//Linux_x86_64Executable'
|
|
||||||
dependsOn 'expPrintLinux_x86_64Executable'
|
|
||||||
dependsOn 'expReadLinux_x86_64Executable'
|
|
||||||
dependsOn 'expSpinLinux_x86_64Executable'
|
|
||||||
dependsOn 'expRegistersLinux_x86_64Executable'
|
|
||||||
dependsOn 'expStackLinux_x86_64Executable'
|
|
||||||
dependsOn 'expTraceableSleepExecutable'//Linux_x86_64Executable'
|
|
||||||
|
|
||||||
doLast {
|
|
||||||
exec {
|
|
||||||
workingDir "build/os/linux_x86_64"
|
|
||||||
commandLine "strip", "-o", "expSpin.stripped", "expSpin"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task testSpecimenMac_arm_64 {
|
|
||||||
dependsOn 'expCloneExitMac_arm_64Executable'
|
|
||||||
dependsOn 'expPrintMac_arm_64Executable'
|
|
||||||
dependsOn 'expReadMac_arm_64Executable'
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: testSpecimenMac_x86_64 (Intel)
|
|
||||||
// will likely need to codesign them to grant debugee-entitlement
|
|
||||||
|
|
||||||
model {
|
|
||||||
components {
|
|
||||||
expCreateProcess(NativeExecutableSpec) {
|
|
||||||
targetPlatform "win_x86_64"
|
|
||||||
targetPlatform "win_x86_32" // TODO: Test on these
|
|
||||||
}
|
|
||||||
expCreateThreadExit(NativeExecutableSpec) {
|
|
||||||
targetPlatform "win_x86_64"
|
|
||||||
targetPlatform "win_x86_32" // TODO: Test on these
|
|
||||||
}
|
|
||||||
expCreateThreadSpin(NativeExecutableSpec) {
|
|
||||||
targetPlatform "win_x86_64"
|
|
||||||
targetPlatform "win_x86_32" // TODO: Test on these
|
|
||||||
}
|
|
||||||
expCloneExec(NativeExecutableSpec) {
|
|
||||||
targetPlatform "linux_x86_64"
|
|
||||||
//targetPlatform "linux_x86_32" // TODO: Test on these
|
|
||||||
}
|
|
||||||
expCloneExit(NativeExecutableSpec) {
|
|
||||||
targetPlatform "linux_x86_64"
|
|
||||||
//targetPlatform "linux_x86_32" // TODO: Test on these
|
|
||||||
targetPlatform "mac_arm_64"
|
|
||||||
}
|
|
||||||
expCloneSpin(NativeExecutableSpec) {
|
|
||||||
targetPlatform "linux_x86_64"
|
|
||||||
//targetPlatform "linux_x86_32" // TODO: Test on these
|
|
||||||
}
|
|
||||||
expFork(NativeExecutableSpec) {
|
|
||||||
targetPlatform "linux_x86_64"
|
|
||||||
//targetPlatform "linux_x86_32" // TODO: Test on these
|
|
||||||
}
|
|
||||||
expPrint(NativeExecutableSpec) {
|
|
||||||
targetPlatform "linux_x86_64"
|
|
||||||
//targetPlatform "linux_x86_32" // TODO: Test on these
|
|
||||||
targetPlatform "win_x86_64"
|
|
||||||
targetPlatform "win_x86_32" // TODO: Test on these
|
|
||||||
targetPlatform "mac_arm_64"
|
|
||||||
}
|
|
||||||
expRead(NativeExecutableSpec) {
|
|
||||||
targetPlatform "linux_x86_64"
|
|
||||||
targetPlatform "mac_arm_64"
|
|
||||||
}
|
|
||||||
expSpin(NativeExecutableSpec) {
|
|
||||||
targetPlatform "linux_x86_64"
|
|
||||||
targetPlatform "win_x86_64"
|
|
||||||
targetPlatform "win_x86_32" // TODO: Test on these
|
|
||||||
}
|
|
||||||
expRegisters(NativeExecutableSpec) {
|
|
||||||
targetPlatform "linux_x86_64"
|
|
||||||
//targetPlatform "linux_x86_32" // TODO: Test on these
|
|
||||||
targetPlatform "win_x86_64"
|
|
||||||
targetPlatform "win_x86_32" // TODO: Test on these
|
|
||||||
}
|
|
||||||
expStack(NativeExecutableSpec) {
|
|
||||||
targetPlatform "linux_x86_64"
|
|
||||||
//targetPlatform "linux_x86_32" // TODO: Test on these
|
|
||||||
targetPlatform "win_x86_64"
|
|
||||||
targetPlatform "win_x86_32" // TODO: Test on these
|
|
||||||
}
|
|
||||||
expTraceableSleep(NativeExecutableSpec) {
|
|
||||||
targetPlatform "linux_x86_64"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
binaries {
|
|
||||||
withType(NativeExecutableBinarySpec) {
|
|
||||||
if (toolChain in Gcc) {
|
|
||||||
cCompiler.args("-std=c99")
|
|
||||||
linker.args("-lpthread")
|
|
||||||
linker.args("-lutil")
|
|
||||||
}
|
|
||||||
if (toolChain in VisualCpp) {
|
|
||||||
cppCompiler.define("VS_PROJECT")
|
|
||||||
// NB. No /SUBSYSTEM:CONSOLE
|
|
||||||
// that creates a subprocess
|
|
||||||
linker.args("/SUBSYSTEM:windows", "/DYNAMICBASE", "/NXCOMPAT")
|
|
||||||
linker.args("shell32.lib");
|
|
||||||
}
|
|
||||||
if (isWindows(targetPlatform.name)) {
|
|
||||||
cppCompiler.define("WIN32")
|
|
||||||
cCompiler.define("WIN32")
|
|
||||||
|
|
||||||
cppCompiler.define("_WINDOWS")
|
|
||||||
cCompiler.define("_WINDOWS")
|
|
||||||
|
|
||||||
cppCompiler.define("UNICODE")
|
|
||||||
cCompiler.define("_UNICODE")
|
|
||||||
|
|
||||||
cppCompiler.define("_UNICODE")
|
|
||||||
cCompiler.define("UNICODE")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
##VERSION: 2.0
|
|
||||||
##MODULE IP: Apache License 2.0
|
|
||||||
Module.manifest||GHIDRA||||END|
|
|
||||||
README.md||GHIDRA||||END|
|
|
||||||
data/ExtensionPoint.manifest||GHIDRA||||END|
|
|
||||||
src/main/resources/agent.log4j.xml||GHIDRA||||END|
|
|
||||||
src/main/resources/log4j-appender-console.xml||GHIDRA||||END|
|
|
||||||
src/main/resources/log4j-appender-logpanel.xml||GHIDRA||||END|
|
|
||||||
src/test/resources/ghidra/dbg/model/test_schema.xml||GHIDRA||||END|
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
DebuggerClientFactory
|
|
||||||
@@ -1,141 +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 ghidra.dbg;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
import java.lang.invoke.MethodHandle;
|
|
||||||
import java.lang.invoke.MethodHandles.Lookup;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.Parameter;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import ghidra.dbg.target.TargetObject;
|
|
||||||
import ghidra.util.Msg;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A model listener that permits {@link AttributeCallback} annotations for convenient callbacks when
|
|
||||||
* the named attribute changes
|
|
||||||
*
|
|
||||||
* @deprecated Will be removed in 11.3. Portions may be refactored into trace object database.
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true, since = "11.2")
|
|
||||||
public abstract class AnnotatedDebuggerAttributeListener implements DebuggerModelListener {
|
|
||||||
private static final String ATTR_METHODS =
|
|
||||||
"@" + AttributeCallback.class.getSimpleName() + "-annotated methods";
|
|
||||||
private static final String PARAMS_ERR =
|
|
||||||
ATTR_METHODS + " must accept 2 parameters: (TargetObject, T)";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Annotation for a method receiving an attribute change callback
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The annotated method must accept parameters {@code (TargetObject, T)}, where {@code T} is the
|
|
||||||
* type of the attribute. Currently, very little checks are applied during construction.
|
|
||||||
* Incorrect use will result in errors during callback invocation.
|
|
||||||
*/
|
|
||||||
@Target(ElementType.METHOD)
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
protected @interface AttributeCallback {
|
|
||||||
String value();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Wiring {
|
|
||||||
private final Map<String, Set<MethodHandle>> handles = new HashMap<>();
|
|
||||||
|
|
||||||
private Wiring(Class<?> cls, Lookup lookup) {
|
|
||||||
try {
|
|
||||||
collect(cls, lookup);
|
|
||||||
}
|
|
||||||
catch (IllegalAccessException e) {
|
|
||||||
throw new IllegalArgumentException("Lookup must have access " + ATTR_METHODS, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void collectFromClass(Class<?> cls, Lookup lookup) throws IllegalAccessException {
|
|
||||||
for (Method m : cls.getDeclaredMethods()) {
|
|
||||||
AttributeCallback annot = m.getAnnotation(AttributeCallback.class);
|
|
||||||
if (annot == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Parameter[] parameters = m.getParameters();
|
|
||||||
if (parameters.length != 2) {
|
|
||||||
throw new IllegalArgumentException(PARAMS_ERR);
|
|
||||||
}
|
|
||||||
if (!parameters[0].getType().isAssignableFrom(TargetObject.class)) {
|
|
||||||
throw new IllegalArgumentException(PARAMS_ERR);
|
|
||||||
}
|
|
||||||
MethodHandle handle = lookup.unreflect(m);
|
|
||||||
handles.computeIfAbsent(annot.value(), __ -> new HashSet<>()).add(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void collect(Class<?> cls, Lookup lookup) throws IllegalAccessException {
|
|
||||||
collectFromClass(cls, lookup);
|
|
||||||
|
|
||||||
Class<?> s = cls.getSuperclass();
|
|
||||||
if (s != null) {
|
|
||||||
collect(s, lookup);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Class<?> i : cls.getInterfaces()) {
|
|
||||||
collect(i, lookup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fireChange(AnnotatedDebuggerAttributeListener l, TargetObject object,
|
|
||||||
String name, Object value) {
|
|
||||||
Set<MethodHandle> set = handles.get(name);
|
|
||||||
if (set == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (MethodHandle h : set) {
|
|
||||||
try {
|
|
||||||
h.invoke(l, object, value);
|
|
||||||
}
|
|
||||||
catch (Throwable e) {
|
|
||||||
Msg.error(this, "Error invoking " + h + ": " + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Map<Class<? extends AnnotatedDebuggerAttributeListener>, Wiring> WIRINGS_BY_CLASS =
|
|
||||||
new HashMap<>();
|
|
||||||
|
|
||||||
private final Wiring wiring;
|
|
||||||
|
|
||||||
public AnnotatedDebuggerAttributeListener(Lookup lookup) {
|
|
||||||
wiring = WIRINGS_BY_CLASS.computeIfAbsent(getClass(), cls -> new Wiring(cls, lookup));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean checkFire(TargetObject object) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void attributesChanged(TargetObject object, Collection<String> removed,
|
|
||||||
Map<String, ?> added) {
|
|
||||||
if (!checkFire(object)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (String name : removed) {
|
|
||||||
wiring.fireChange(this, object, name, null);
|
|
||||||
}
|
|
||||||
for (Map.Entry<String, ?> ent : added.entrySet()) {
|
|
||||||
wiring.fireChange(this, object, ent.getKey(), ent.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,556 +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 ghidra.dbg;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import ghidra.async.*;
|
|
||||||
import ghidra.dbg.target.*;
|
|
||||||
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.dbg.util.PathPredicates;
|
|
||||||
import ghidra.dbg.util.PathUtils;
|
|
||||||
import ghidra.dbg.util.PathUtils.PathComparator;
|
|
||||||
import ghidra.util.Msg;
|
|
||||||
import ghidra.util.Swing;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Will be removed in 11.3. Portions may be refactored into trace object database.
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true, since = "11.2")
|
|
||||||
public enum DebugModelConventions {
|
|
||||||
;
|
|
||||||
|
|
||||||
protected static CompletableFuture<Void> runNotInSwing(Object originator, Runnable runnable,
|
|
||||||
String cbName) {
|
|
||||||
if (Swing.isSwingThread()) {
|
|
||||||
return CompletableFuture.runAsync(runnable).exceptionally(e -> {
|
|
||||||
Msg.error(originator, "Error in " + cbName, e);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
runnable.run();
|
|
||||||
}
|
|
||||||
catch (Throwable e) {
|
|
||||||
Msg.error(originator, "Error in " + cbName, e);
|
|
||||||
}
|
|
||||||
return AsyncUtils.nil();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search for a suitable object implementing the given interface, starting at a given seed.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This performs an n-up-1-down search starting at the given seed, seeking an object which
|
|
||||||
* implements the given interface. The 1-down part is only applied from objects implementing
|
|
||||||
* {@link TargetAggregate}. See {@link TargetObject} for the specifics of expected model
|
|
||||||
* conventions.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Note that many a debugger target object interface type require a self-referential {@code T}
|
|
||||||
* parameter referring to the implementing class type. To avoid referring to a particular
|
|
||||||
* implementation, it becomes necessary to leave {@code T} as {@code ?}, but that can never
|
|
||||||
* satisfy the constraints of this method. To work around this, such interfaces must provide a
|
|
||||||
* static {@code tclass} field, which can properly satisfy the type constraints of this method
|
|
||||||
* for such self-referential type variables. The returned value must be ascribed to the
|
|
||||||
* wild-carded type, because the work-around involves a hidden class. Perhaps a little verbose
|
|
||||||
* (hey, it's Java!), the following is the recommended pattern, e.g., to discover the
|
|
||||||
* environment of a given process:
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* CompletableFuture<? extends TargetEnvironment<?>> futureEnv =
|
|
||||||
* DebugModelConventions.findSuitable(TargetEnvironment.tclass, aProcess);
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param <T> the desired interface type.
|
|
||||||
* @param iface the (probably {@code tclass}) of the desired interface type
|
|
||||||
* @param seed the starting object
|
|
||||||
* @return a future which completes with the discovered object or completes with null, if not
|
|
||||||
* found.
|
|
||||||
* @deprecated use {@link #suitable(Class, TargetObject)} instead
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
public static <T extends TargetObject> CompletableFuture<T> findSuitable(Class<T> iface,
|
|
||||||
TargetObject seed) {
|
|
||||||
if (iface.isAssignableFrom(seed.getClass())) {
|
|
||||||
return CompletableFuture.completedFuture(iface.cast(seed));
|
|
||||||
}
|
|
||||||
if (seed instanceof TargetAggregate) {
|
|
||||||
return findInAggregate(iface, seed).thenCompose(agg -> {
|
|
||||||
if (agg.size() == 1) {
|
|
||||||
return CompletableFuture.completedFuture(agg.iterator().next());
|
|
||||||
}
|
|
||||||
return findParentSuitable(iface, seed);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return findParentSuitable(iface, seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search for a suitable object implementing the given interface, starting at a given seed.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This performs an n-up-m-down search starting at the given seed, seeking an object which
|
|
||||||
* implements the given interface. The m-down part is only applied from objects implementing
|
|
||||||
* {@link TargetAggregate}. See {@link TargetObject} for the specifics of expected model
|
|
||||||
* conventions.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Note that many a debugger target object interface type require a self-referential {@code T}
|
|
||||||
* parameter referring to the implementing class type. To avoid referring to a particular
|
|
||||||
* implementation, it becomes necessary to leave {@code T} as {@code ?}, but that can never
|
|
||||||
* satisfy the constraints of this method. To work around this, such interfaces must provide a
|
|
||||||
* static {@code tclass} field, which can properly satisfy the type constraints of this method
|
|
||||||
* for such self-referential type variables. The returned value must be ascribed to the
|
|
||||||
* wild-carded type, because the work-around involves a hidden class. Perhaps a little verbose
|
|
||||||
* (hey, it's Java!), the following is the recommended pattern, e.g., to discover the
|
|
||||||
* environment of a given process:
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* CompletableFuture<? extends TargetEnvironment<?>> futureEnv =
|
|
||||||
* DebugModelConventions.suitable(TargetEnvironment.tclass, aProcess);
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param <T> the desired interface type.
|
|
||||||
* @param iface the (probably {@code tclass}) of the desired interface type
|
|
||||||
* @param seed the starting object
|
|
||||||
* @return a future which completes with the discovered object or completes with null, if not
|
|
||||||
* found.
|
|
||||||
*/
|
|
||||||
public static <T extends TargetObject> CompletableFuture<T> suitable(Class<T> iface,
|
|
||||||
TargetObject seed) {
|
|
||||||
List<String> path =
|
|
||||||
seed.getModel().getRootSchema().searchForSuitable(iface, seed.getPath());
|
|
||||||
if (path == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return seed.getModel().fetchModelObject(path).thenApply(obj -> iface.cast(obj));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends TargetObject> T ancestor(Class<T> iface, TargetObject seed) {
|
|
||||||
List<String> path =
|
|
||||||
seed.getModel().getRootSchema().searchForAncestor(iface, seed.getPath());
|
|
||||||
if (path == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return iface.cast(seed.getModel().getModelObject(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T extends TargetObject> CompletableFuture<T> findParentSuitable(Class<T> iface,
|
|
||||||
TargetObject obj) {
|
|
||||||
TargetObject parent = obj.getParent();
|
|
||||||
if (parent == null) {
|
|
||||||
return AsyncUtils.nil();
|
|
||||||
}
|
|
||||||
return findSuitable(iface, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search for an object implementing the given interface among itself and its attributes.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This method descends into the attributes of objects which implement the
|
|
||||||
* {@link TargetAggregate} interface. All found objects will comes from the same "level" in the
|
|
||||||
* tree, the algorithm terminating as soon as it finds a level with at least one object having
|
|
||||||
* the interface. When it terminates, all such objects at that level will be included. The
|
|
||||||
* resulting collection is in no particular order.
|
|
||||||
*
|
|
||||||
* @param <T> the desired interface type.
|
|
||||||
* @param iface the (probably {@code tclass}) of the desired interface type
|
|
||||||
* @param seed the starting object
|
|
||||||
* @return a future which completes with the, possibly empty, collection of discovered objects
|
|
||||||
*/
|
|
||||||
public static <T extends TargetObject> CompletableFuture<Collection<T>> findInAggregate(
|
|
||||||
Class<T> iface, TargetObject seed) {
|
|
||||||
return findInAggregate(iface, Set.of(seed));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search for an object implementing the given interface among those given and their attributes.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* All seeds should be at the same "level", or else the result is not well defined.
|
|
||||||
*
|
|
||||||
* @see #findInAggregate(Class, TargetObject)
|
|
||||||
*/
|
|
||||||
public static <T extends TargetObject> CompletableFuture<Collection<T>> findInAggregate(
|
|
||||||
Class<T> iface, Collection<? extends TargetObject> seeds) {
|
|
||||||
if (seeds.isEmpty()) {
|
|
||||||
return CompletableFuture.completedFuture(Set.of());
|
|
||||||
}
|
|
||||||
Set<T> result = seeds.stream()
|
|
||||||
.filter(obj -> iface.isAssignableFrom(obj.getClass()))
|
|
||||||
.map(obj -> iface.cast(obj))
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
if (!result.isEmpty()) {
|
|
||||||
return CompletableFuture.completedFuture(result);
|
|
||||||
}
|
|
||||||
AsyncFence fence = new AsyncFence();
|
|
||||||
Set<TargetObject> nextLevel = new HashSet<>();
|
|
||||||
for (TargetObject seed : seeds) {
|
|
||||||
if (!(seed instanceof TargetAggregate)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
fence.include(seed.fetchAttributes().thenAccept(attributes -> {
|
|
||||||
synchronized (nextLevel) {
|
|
||||||
for (Map.Entry<String, ?> ent : attributes.entrySet()) {
|
|
||||||
Object val = ent.getValue();
|
|
||||||
if (!(val instanceof TargetObject)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
TargetObject obj = (TargetObject) val;
|
|
||||||
if (PathUtils.isLink(seed.getPath(), ent.getKey(), obj.getPath())) {
|
|
||||||
// TODO: Resolve links? Must ensure I don't re-visit anyone
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
nextLevel.add(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
return fence.ready().thenCompose(__ -> findInAggregate(iface, nextLevel));
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract static class AncestorTraversal<T> extends CompletableFuture<T> {
|
|
||||||
public enum Result {
|
|
||||||
FOUND, CONTINUE, TERMINATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected TargetObject cur;
|
|
||||||
|
|
||||||
public AncestorTraversal(TargetObject successor) {
|
|
||||||
cur = successor;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Result check(TargetObject obj);
|
|
||||||
|
|
||||||
protected abstract T finish(TargetObject obj);
|
|
||||||
|
|
||||||
public AncestorTraversal<T> start() {
|
|
||||||
try {
|
|
||||||
next(cur);
|
|
||||||
}
|
|
||||||
catch (Throwable ex) {
|
|
||||||
completeExceptionally(ex);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void next(TargetObject ancestor) {
|
|
||||||
cur = ancestor;
|
|
||||||
if (cur == null) {
|
|
||||||
complete(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (check(cur)) {
|
|
||||||
case FOUND:
|
|
||||||
complete(finish(cur));
|
|
||||||
return;
|
|
||||||
case CONTINUE:
|
|
||||||
next(cur.getParent());
|
|
||||||
return;
|
|
||||||
case TERMINATE:
|
|
||||||
complete(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Void exc(Throwable ex) {
|
|
||||||
completeExceptionally(ex);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the nearest ancestor which implements the given interface.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This is similar to {@link #findSuitable(Class, TargetObject)}, except without the 1-down
|
|
||||||
* rule.
|
|
||||||
*
|
|
||||||
* @param <T> the type of the required interface
|
|
||||||
* @param iface the (probably {@code tclass}) for the required interface
|
|
||||||
* @param successor the seed object
|
|
||||||
* @return a future which completes with the found object or completes with null if not found.
|
|
||||||
*/
|
|
||||||
public static <T extends TargetObject> CompletableFuture<T> nearestAncestor(Class<T> iface,
|
|
||||||
TargetObject successor) {
|
|
||||||
return new AncestorTraversal<T>(successor) {
|
|
||||||
@Override
|
|
||||||
protected Result check(TargetObject obj) {
|
|
||||||
if (iface.isAssignableFrom(obj.getClass())) {
|
|
||||||
return Result.FOUND;
|
|
||||||
}
|
|
||||||
return Result.CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected T finish(TargetObject obj) {
|
|
||||||
return iface.cast(obj);
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collect all ancestors (including seed) supporting the given interface
|
|
||||||
*
|
|
||||||
* @param <T> the type of interface
|
|
||||||
* @param seed the starting point
|
|
||||||
* @param iface the class of the interface
|
|
||||||
* @return the collection of ancestors supporting the interface
|
|
||||||
*/
|
|
||||||
public static <T extends TargetObject> CompletableFuture<Collection<T>> collectAncestors(
|
|
||||||
TargetObject seed, Class<T> iface) {
|
|
||||||
DebuggerObjectModel model = seed.getModel();
|
|
||||||
List<T> result = new ArrayList<>(seed.getPath().size() + 1);
|
|
||||||
AsyncFence fence = new AsyncFence();
|
|
||||||
for (List<String> path = seed.getPath(); path != null; path = PathUtils.parent(path)) {
|
|
||||||
fence.include(model.fetchModelObject(path).thenAccept(obj -> {
|
|
||||||
if (iface.isAssignableFrom(obj.getClass())) {
|
|
||||||
result.add(iface.cast(obj));
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
return fence.ready().thenApply(__ -> {
|
|
||||||
result.sort(Comparator.comparing(o -> o.getPath().size()));
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collect all successors (including seed) that are elements supporting the given interface.
|
|
||||||
*
|
|
||||||
* @param <T> the type of interface
|
|
||||||
* @param seed the starting point (root of subtree to inspect)
|
|
||||||
* @param iface the class of the interface
|
|
||||||
* @return the collection of successor elements supporting the interface
|
|
||||||
* @deprecated use {@link TargetObjectSchema#searchFor(Class, boolean)} and
|
|
||||||
* {@link PathPredicates#collectSuccessorRefs(TargetObject)} instead.
|
|
||||||
*/
|
|
||||||
// TODO: Test this method
|
|
||||||
@Deprecated(forRemoval = true)
|
|
||||||
public static <T extends TargetObject> CompletableFuture<Collection<T>> collectSuccessors(
|
|
||||||
TargetObject seed, Class<T> iface) {
|
|
||||||
Collection<T> result =
|
|
||||||
new TreeSet<>(Comparator.comparing(TargetObject::getPath, PathComparator.KEYED));
|
|
||||||
AsyncFence fence = new AsyncFence();
|
|
||||||
fence.include(seed.fetchElements().thenCompose(elements -> {
|
|
||||||
AsyncFence elemFence = new AsyncFence();
|
|
||||||
synchronized (result) {
|
|
||||||
for (TargetObject e : elements.values()) {
|
|
||||||
if (iface.isInstance(e)) {
|
|
||||||
result.add(iface.cast(e));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
elemFence.include(collectSuccessors(e, iface).thenAccept(sub -> {
|
|
||||||
synchronized (result) {
|
|
||||||
result.addAll(sub);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return elemFence.ready();
|
|
||||||
}));
|
|
||||||
fence.include(seed.fetchAttributes().thenCompose(attributes -> {
|
|
||||||
AsyncFence attrFence = new AsyncFence();
|
|
||||||
synchronized (result) {
|
|
||||||
for (Map.Entry<String, ?> ent : attributes.entrySet()) {
|
|
||||||
Object val = ent.getValue();
|
|
||||||
if (!(val instanceof TargetObject)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
TargetObject a = (TargetObject) val;
|
|
||||||
if (PathUtils.isLink(seed.getPath(), ent.getKey(), a.getPath())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (iface.isInstance(a)) {
|
|
||||||
result.add(iface.cast(a));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
attrFence.include(collectSuccessors(a, iface).thenAccept(sub -> {
|
|
||||||
synchronized (result) {
|
|
||||||
result.addAll(sub);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return attrFence.ready();
|
|
||||||
}));
|
|
||||||
return fence.ready().thenApply(__ -> {
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the nearest ancestor thread
|
|
||||||
*
|
|
||||||
* @param successor the seed object
|
|
||||||
* @return a future which completes with the found thread or completes with {@code null}.
|
|
||||||
*/
|
|
||||||
public static CompletableFuture<TargetThread> findThread(TargetObject successor) {
|
|
||||||
return new AncestorTraversal<TargetThread>(successor) {
|
|
||||||
@Override
|
|
||||||
protected Result check(TargetObject obj) {
|
|
||||||
if (obj.isRoot()) {
|
|
||||||
return Result.TERMINATE;
|
|
||||||
}
|
|
||||||
if (obj instanceof TargetThread) {
|
|
||||||
return Result.FOUND;
|
|
||||||
}
|
|
||||||
return Result.CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected TargetThread finish(TargetObject obj) {
|
|
||||||
return (TargetThread) obj;
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the given process is alive
|
|
||||||
*
|
|
||||||
* @param process the process
|
|
||||||
* @return true if alive
|
|
||||||
*/
|
|
||||||
public static boolean isProcessAlive(TargetProcess process) {
|
|
||||||
if (!process.isValid()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!(process instanceof TargetExecutionStateful)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
TargetExecutionStateful exe = (TargetExecutionStateful) process;
|
|
||||||
TargetExecutionState state = exe.getExecutionState();
|
|
||||||
if (state == null) {
|
|
||||||
Msg.trace(null, "null state for " + exe);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return state.isAlive();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a target is a live process, and cast if so
|
|
||||||
*
|
|
||||||
* @param target the potential process
|
|
||||||
* @return the process if live, or null
|
|
||||||
*/
|
|
||||||
public static TargetProcess liveProcessOrNull(TargetObject target) {
|
|
||||||
if (!(target instanceof TargetProcess)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
TargetProcess process = (TargetProcess) target;
|
|
||||||
return isProcessAlive(process) ? process : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class AsyncAttribute<T> extends AsyncReference<T, Void>
|
|
||||||
implements DebuggerModelListener {
|
|
||||||
private final TargetObject obj;
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public AsyncAttribute(TargetObject obj, String name) {
|
|
||||||
this.name = name;
|
|
||||||
this.obj = obj;
|
|
||||||
obj.getModel().addModelListener(this);
|
|
||||||
set((T) obj.getCachedAttribute(name), null);
|
|
||||||
obj.fetchAttribute(name).exceptionally(ex -> {
|
|
||||||
Msg.error(this, "Could not get initial value of " + name + " for " + obj, ex);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void attributesChanged(TargetObject parent, Collection<String> removed,
|
|
||||||
Map<String, ?> added) {
|
|
||||||
if (parent != obj) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (added.containsKey(name)) {
|
|
||||||
set((T) added.get(name), null);
|
|
||||||
}
|
|
||||||
else if (removed.contains(name)) {
|
|
||||||
set(null, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dispose() {
|
|
||||||
this.dispose(new AssertionError("disposed"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dispose(Throwable reason) {
|
|
||||||
super.dispose(reason);
|
|
||||||
obj.getModel().removeModelListener(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class AsyncState extends AsyncAttribute<TargetExecutionState> {
|
|
||||||
public AsyncState(TargetExecutionStateful stateful) {
|
|
||||||
super(stateful, TargetExecutionStateful.STATE_ATTRIBUTE_NAME);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class AsyncAccess extends AsyncAttribute<Boolean> {
|
|
||||||
public AsyncAccess(TargetAccessConditioned ac) {
|
|
||||||
super(ac, TargetAccessConditioned.ACCESSIBLE_ATTRIBUTE_NAME);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request activation of the given object in its nearest active scope
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Note if the object has no suitable active scope, this method fails silently.
|
|
||||||
*
|
|
||||||
* @param obj the object on which to request activation
|
|
||||||
* @return a future which completes when activation is granted, or exceptionally
|
|
||||||
*/
|
|
||||||
public static CompletableFuture<Void> requestActivation(TargetObject obj) {
|
|
||||||
CompletableFuture<? extends TargetActiveScope> futureActivator =
|
|
||||||
DebugModelConventions.findSuitable(TargetActiveScope.class, obj);
|
|
||||||
return futureActivator.thenCompose(activator -> {
|
|
||||||
if (activator == null) {
|
|
||||||
return AsyncUtils.nil();
|
|
||||||
}
|
|
||||||
return activator.requestActivation(obj);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request focus on the given object in its nearest focus scope
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Note if the object has no suitable focus scope, this method fails silently.
|
|
||||||
*
|
|
||||||
* @param obj the object on which to request focus
|
|
||||||
* @return a future which completes when focus is granted, or exceptionally
|
|
||||||
*/
|
|
||||||
public static CompletableFuture<Void> requestFocus(TargetObject obj) {
|
|
||||||
CompletableFuture<? extends TargetFocusScope> futureScope =
|
|
||||||
DebugModelConventions.findSuitable(TargetFocusScope.class, obj);
|
|
||||||
return futureScope.thenCompose(scope -> {
|
|
||||||
if (scope == null) {
|
|
||||||
return AsyncUtils.nil();
|
|
||||||
}
|
|
||||||
return scope.requestFocus(obj);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +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 ghidra.dbg;
|
|
||||||
|
|
||||||
@Deprecated(forRemoval = true, since = "11.2")
|
|
||||||
class DebuggerAbnormalModelClosedReason implements DebuggerModelClosedReason {
|
|
||||||
final Throwable exc;
|
|
||||||
|
|
||||||
public DebuggerAbnormalModelClosedReason(Throwable exc) {
|
|
||||||
this.exc = exc;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasException() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isClientInitiated() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Throwable getException() {
|
|
||||||
return exc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,63 +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 ghidra.dbg;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A reason given for a closed connection
|
|
||||||
*
|
|
||||||
* @deprecated Will be removed in 11.3. Portions may be refactored into trace object database.
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true, since = "11.2")
|
|
||||||
public interface DebuggerModelClosedReason {
|
|
||||||
DebuggerModelClosedReason NORMAL = DebuggerNormalModelClosedReason.NORMAL;
|
|
||||||
|
|
||||||
static DebuggerModelClosedReason normal() {
|
|
||||||
return NORMAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static DebuggerModelClosedReason abnormal(Throwable exc) {
|
|
||||||
return new DebuggerAbnormalModelClosedReason(exc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check for exceptional cause for the closed model
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Usually, if the model is closed unexpectedly, there is an exception to document the cause. If
|
|
||||||
* available, the implementation should provide this exception.
|
|
||||||
*
|
|
||||||
* @return true if an exception is recorded
|
|
||||||
*/
|
|
||||||
boolean hasException();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the model was closed by the client
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* In this case, the closed model is completely ordinary. While the model is still no longer
|
|
||||||
* valid, there is no cause to alert the user.
|
|
||||||
*
|
|
||||||
* @return true if the model was closed by the client
|
|
||||||
*/
|
|
||||||
boolean isClientInitiated();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the recorded exception, if available
|
|
||||||
*
|
|
||||||
* @return the exception or null
|
|
||||||
*/
|
|
||||||
Throwable getException();
|
|
||||||
}
|
|
||||||
@@ -1,70 +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 ghidra.dbg;
|
|
||||||
|
|
||||||
import ghidra.dbg.util.ConfigurableFactory;
|
|
||||||
import ghidra.program.model.listing.Program;
|
|
||||||
import ghidra.util.classfinder.ExtensionPoint;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A factory for a debugger model
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This provides a discoverable means of configuring and creating a debug model.
|
|
||||||
*
|
|
||||||
* @deprecated Will be removed in 11.3. Portions may be refactored into trace object database.
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true, since = "11.2")
|
|
||||||
public interface DebuggerModelFactory
|
|
||||||
extends ExtensionPoint, ConfigurableFactory<DebuggerObjectModel> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the priority for selecting this factory by default for the given program
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* A default factory is selected when the current factory and the last successful factory are
|
|
||||||
* incompatible with the current program, or if this is the very first time connecting. Of those
|
|
||||||
* factories compatible with the current program, the one with the highest priority (larger
|
|
||||||
* numerical value) is selected. If none are compatible, then the current selection is left as
|
|
||||||
* is.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Note that negative priorities imply the factory is not compatible with the given program or
|
|
||||||
* local system.
|
|
||||||
*
|
|
||||||
* @param program the current program, or null
|
|
||||||
* @return the priority, higher values mean higher priority
|
|
||||||
*/
|
|
||||||
default int getPriority(Program program) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if this factory is compatible with the local system and given program.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* <b>WARNING:</b> Implementations should not likely override this method. If one does, it must
|
|
||||||
* behave in the same manner as given in this default implementation: If
|
|
||||||
* {@link #getPriority(Program)} would return a non-negative result for the program, then this
|
|
||||||
* factory is compatible with that program. If negative, this factory is not compatible.
|
|
||||||
*
|
|
||||||
* @param program the current program, or null
|
|
||||||
* @return true if compatible
|
|
||||||
*/
|
|
||||||
default boolean isCompatible(Program program) {
|
|
||||||
return getPriority(program) >= 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,323 +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 ghidra.dbg;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import ghidra.dbg.error.DebuggerMemoryAccessException;
|
|
||||||
import ghidra.dbg.target.*;
|
|
||||||
import ghidra.dbg.target.TargetConsole.Channel;
|
|
||||||
import ghidra.dbg.target.TargetEventScope.TargetEventType;
|
|
||||||
import ghidra.dbg.target.TargetExecutionStateful.TargetExecutionState;
|
|
||||||
import ghidra.program.model.address.Address;
|
|
||||||
import ghidra.program.model.address.AddressRange;
|
|
||||||
import ghidra.util.Msg;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A listener for events related to the debugger model, including its connection and objects
|
|
||||||
*
|
|
||||||
* @deprecated Will be removed in 11.3. Portions may be refactored into trace object database.
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true, since = "11.2")
|
|
||||||
public interface DebuggerModelListener {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An error occurred such that this listener will no longer receive events
|
|
||||||
*
|
|
||||||
* @param t the exception describing the error
|
|
||||||
*/
|
|
||||||
default public void catastrophic(Throwable t) {
|
|
||||||
Msg.error(this, "Catastrophic listener error", t);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The model has been successfully opened
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* For example, the connection to a debugger daemon has been established and negotiated.
|
|
||||||
*/
|
|
||||||
default public void modelOpened() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The model's state has changed, prompting an update to its description
|
|
||||||
*/
|
|
||||||
default public void modelStateChanged() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The model was closed
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* For example, the remote closed the connection, or the connection was lost. Whatever the case,
|
|
||||||
* the model is invalid after this callback.
|
|
||||||
*
|
|
||||||
* @param reason the reason for the model to close
|
|
||||||
*/
|
|
||||||
default public void modelClosed(DebuggerModelClosedReason reason) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An object was created
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This can only be received by listening on the model. While the created object can now appear
|
|
||||||
* in other callbacks, it should not be used aside from those callbacks, until it is added to
|
|
||||||
* the model. Until that time, the object may not adhere to the schema, since its children are
|
|
||||||
* still being initialized.
|
|
||||||
*
|
|
||||||
* @param object the newly-created object
|
|
||||||
*/
|
|
||||||
default void created(TargetObject object) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An object is no longer valid
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This should be the final callback ever issued for this object. Invalidation of an object
|
|
||||||
* implies invalidation of all its successors; nevertheless, the implementation MUST explicitly
|
|
||||||
* invoke this callback for those successors in preorder. Users need only listen for
|
|
||||||
* invalidation by installing a listener on the object of interest. However, a user must be able
|
|
||||||
* to ignore invalidation events on an object it has already removed and/or invalidated. The
|
|
||||||
* {@code branch} parameter will identify the branch node of the sub-tree being removed. For
|
|
||||||
* models that are managed by a client connection, disconnecting or otherwise terminating the
|
|
||||||
* session should invalidate the root, and thus every object must receive this callback.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* If an invalidated object is replaced (i.e., a new object with the same path is added to the
|
|
||||||
* model), the implementation must be careful to issue all invalidations related to the removed
|
|
||||||
* object before the replacement is added, so that delayed invalidations are not mistakenly
|
|
||||||
* applied to the replacement or its successors.
|
|
||||||
*
|
|
||||||
* @param object the now-invalid object
|
|
||||||
* @param branch the root of the sub-tree being invalidated
|
|
||||||
* @param reason an informational, human-consumable reason, if applicable
|
|
||||||
*/
|
|
||||||
default void invalidated(TargetObject object, TargetObject branch, String reason) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The root object has been added to the model
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This indicates the root is ready, not just {@link #created(TargetObject)}. Note this callback
|
|
||||||
* indicates the root being "added to the model."
|
|
||||||
*
|
|
||||||
* @param root the root object
|
|
||||||
*/
|
|
||||||
default public void rootAdded(TargetObject root) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The object's elements changed
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The listener must have received a prior {@link #created(TargetObject)} callback for the
|
|
||||||
* parent and all (object-valued) elements being added. Assuming {@code object} has already been
|
|
||||||
* "added the model," this callback indicates all objects in the {@code added} parameter being
|
|
||||||
* "added to the model" along with their successors.
|
|
||||||
*
|
|
||||||
* @param object the object whose children changed
|
|
||||||
* @param removed the list of removed children
|
|
||||||
* @param added a map of indices to new children references
|
|
||||||
*/
|
|
||||||
default void elementsChanged(TargetObject object, Collection<String> removed,
|
|
||||||
Map<String, ? extends TargetObject> added) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The object's attributes changed
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* In the case of an object-valued attribute, changes to that object do not constitute a changed
|
|
||||||
* attribute. The attribute is considered changed only when that attribute is assigned to a
|
|
||||||
* completely different object.
|
|
||||||
*
|
|
||||||
* @param object the object whose attributes changed
|
|
||||||
* @param removed the list of removed attributes
|
|
||||||
* @param added a map of names to new/changed attributes
|
|
||||||
*/
|
|
||||||
default void attributesChanged(TargetObject object, Collection<String> removed,
|
|
||||||
Map<String, ?> added) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The model has requested the client invalidate (non-tree) caches associated with an object
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* For objects with methods exposing contents other than elements and attributes (e.g., memory
|
|
||||||
* and register contents), this callback requests that any caches associated with that content
|
|
||||||
* be invalidated. Most notably, this usually occurs when an object (e.g., thread) enters the
|
|
||||||
* {@link TargetExecutionState#RUNNING} state, to inform proxies that they should invalidate
|
|
||||||
* their memory and register caches. In most cases, clients need not worry about this callback.
|
|
||||||
* Protocol implementations that use the model, however, should forward this request to the
|
|
||||||
* client-side peer.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Note caches of elements and attributes are not affected by this callback. See
|
|
||||||
* {@link TargetObject#invalidateCaches()}.
|
|
||||||
*
|
|
||||||
* @param object the object whose caches must be invalidated
|
|
||||||
*/
|
|
||||||
default void invalidateCacheRequested(TargetObject object) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A breakpoint trapped execution
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The program counter can be obtained in a few ways. The most reliable is to get the address of
|
|
||||||
* the breakpoint location. If available, the frame will also contain the program counter.
|
|
||||||
* Finally, the trapped object or one of its relatives may offer the program counter.
|
|
||||||
*
|
|
||||||
* @param container the container whose breakpoint trapped execution
|
|
||||||
* @param trapped the object whose execution was trapped, usually a {@link TargetThread}
|
|
||||||
* @param frame the innermost stack frame, if available, of the trapped object
|
|
||||||
* @param spec the breakpoint specification
|
|
||||||
* @param breakpoint the breakpoint location that actually trapped execution
|
|
||||||
*/
|
|
||||||
default void breakpointHit(TargetObject container, TargetObject trapped,
|
|
||||||
TargetStackFrame frame, TargetBreakpointSpec spec,
|
|
||||||
TargetBreakpointLocation breakpoint) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A console has produced output (given as bytes)
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Note that "captured" outputs will not be reported in this callback. See
|
|
||||||
* {@link TargetInterpreter#executeCapture(String)}.
|
|
||||||
*
|
|
||||||
* @param console the console producing the output
|
|
||||||
* @param channel identifies the "output stream", stdout or stderr
|
|
||||||
* @param data the output data
|
|
||||||
*/
|
|
||||||
default void consoleOutput(TargetObject console, Channel channel, byte[] data) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A console has produced output (given as a string)
|
|
||||||
*
|
|
||||||
* @implNote Overriding this method is not a substitute for overriding
|
|
||||||
* {@link #consoleOutput(TargetObject, Channel, byte[])}. Some models may invoke this
|
|
||||||
* {@code String} variant as a convenience, which by default, invokes the
|
|
||||||
* {@code byte[]} variant, but models are only expected to invoke the {@code byte[]}
|
|
||||||
* variant. A client may override this method simply to avoid back-and-forth
|
|
||||||
* conversions between {@code String}s and {@code byte[]}s.
|
|
||||||
*
|
|
||||||
* @param console the console producing the output
|
|
||||||
* @param channel identifies the "output stream", stdout or stderr
|
|
||||||
* @param text the output text
|
|
||||||
*/
|
|
||||||
default void consoleOutput(TargetObject console, Channel channel, String text) {
|
|
||||||
consoleOutput(console, channel, text.getBytes(TargetConsole.CHARSET));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A "special" event has occurred
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* When present, this callback must be invoked before any other callback which results from this
|
|
||||||
* event, except creation events. E.g., for PROCESS_EXITED, this must be called before the
|
|
||||||
* affected process is invalidated.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Whenever possible, event thread must be given. This is often the thread given focus by the
|
|
||||||
* debugger immediately upon stopping for the event. Parameters are not (yet) strictly
|
|
||||||
* specified, but it should include the stopped target, if that target is not already given by
|
|
||||||
* the event thread. It may optionally contain other useful information, such as an exit code,
|
|
||||||
* but no client should depend on that information being given.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The best way to communicate to users what has happened is via the description. Almost every
|
|
||||||
* other result of an event is communicated by other means in the model, e.g., state changes,
|
|
||||||
* object creation, invalidation. The description should contain as much information as possible
|
|
||||||
* to cue users as to why the other changes have occurred, and point them to relevant objects.
|
|
||||||
* For example, if trapped on a breakpoint, the description might contain the breakpoint's
|
|
||||||
* identifier. If the debugger prints a message for this event, that message is probably a
|
|
||||||
* sufficient description.
|
|
||||||
*
|
|
||||||
* @param object the event scope
|
|
||||||
* @param eventThread if applicable, the thread causing the event
|
|
||||||
* @param type the type of event
|
|
||||||
* @param description a human-readable description of the event
|
|
||||||
* @param parameters extra parameters for the event. TODO: Specify these for each type, or break
|
|
||||||
* this into other callbacks.
|
|
||||||
*/
|
|
||||||
default void event(TargetObject object, TargetThread eventThread, TargetEventType type,
|
|
||||||
String description, List<Object> parameters) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Memory was successfully read or written
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This implies memory caches should be updated. If the implementation employs a cache, then it
|
|
||||||
* need only report reads or writes which updated that cache. However, that cache must be
|
|
||||||
* invalidated whenever any other event occurs which could change memory, e.g., the target
|
|
||||||
* stepping or running. See {@link #invalidateCacheRequested(TargetObject)}. If the
|
|
||||||
* implementation does not employ a cache, then it must report <em>every</em> successful
|
|
||||||
* client-driven read or write. If the implementation can detect <em>debugger-driven</em> memory
|
|
||||||
* reads and writes, then it is recommended to call this method for those events. However, this
|
|
||||||
* method <em>must not</em> be called for <em>target-driven</em> memory changes. In other words,
|
|
||||||
* this method should only be called for reads or writes requested by the user.
|
|
||||||
*
|
|
||||||
* @param memory this memory object
|
|
||||||
* @param address the starting address of the affected range
|
|
||||||
* @param data the new data for the affected range
|
|
||||||
*/
|
|
||||||
default void memoryUpdated(TargetObject memory, Address address, byte[] data) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An attempt to read memory failed
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Like {@link #memoryUpdated(TargetMemory, Address, byte[])}, this should only be invoked for
|
|
||||||
* <em>user-driven</em> requests. Failure of the <em>target</em> to read its own memory would
|
|
||||||
* likely be reported via an exception, not this callback.
|
|
||||||
*
|
|
||||||
* @param memory the memory object
|
|
||||||
* @param range the range for the read which generated the error
|
|
||||||
* @param e the error
|
|
||||||
*/
|
|
||||||
default void memoryReadError(TargetObject memory, AddressRange range,
|
|
||||||
DebuggerMemoryAccessException e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers were successfully read or written
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This implies register caches should be updated. If the implementation employs a cache, then
|
|
||||||
* it need only report reads or writes which updated that cache. However, that cache must be
|
|
||||||
* invalidated whenever any other event occurs which could change register values, e.g., the
|
|
||||||
* target stepping or running. See {@link #invalidateCacheRequested(TargetObject)}. If the
|
|
||||||
* implementation does not employ a cache, then it must report <em>every</em> successful
|
|
||||||
* client-driven read or write. If the implementation can detect <em>debugger-driven</em>
|
|
||||||
* register reads and writes, then it recommended to call this method for those events. However,
|
|
||||||
* this method <em>must not</em> be called for <em>target-driven</em> register changes, except
|
|
||||||
* perhaps when the target becomes suspended. Note that some models may additionally provide a
|
|
||||||
* {@code value} attribute on each register -- when the register bank is its own description
|
|
||||||
* container -- however, updating those attributes is not a substitute for this callback.
|
|
||||||
*
|
|
||||||
* @param bank this register bank object
|
|
||||||
* @param updates a name-value map of updated registers
|
|
||||||
*/
|
|
||||||
default void registersUpdated(TargetObject bank, Map<String, byte[]> updates) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +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 ghidra.dbg;
|
|
||||||
|
|
||||||
@Deprecated(forRemoval = true, since = "11.2")
|
|
||||||
enum DebuggerNormalModelClosedReason implements DebuggerModelClosedReason {
|
|
||||||
NORMAL;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasException() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isClientInitiated() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Throwable getException() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,614 +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 ghidra.dbg;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
import ghidra.async.*;
|
|
||||||
import ghidra.dbg.error.*;
|
|
||||||
import ghidra.dbg.target.TargetMemory;
|
|
||||||
import ghidra.dbg.target.TargetObject;
|
|
||||||
import ghidra.dbg.target.schema.EnumerableTargetObjectSchema;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema;
|
|
||||||
import ghidra.dbg.target.schema.TargetObjectSchema.ResyncMode;
|
|
||||||
import ghidra.dbg.util.PathUtils;
|
|
||||||
import ghidra.program.model.address.*;
|
|
||||||
import ghidra.util.Msg;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A debugger model, often a connection to an external debugger
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This is an abstraction of debugger operations and attempts to limit assumptions to those that
|
|
||||||
* generalize to most platforms. Debuggers and the target processes may be temperamental, so an
|
|
||||||
* asynchronous pattern is employed to prevent deadlocks on dropped connections, slow connections,
|
|
||||||
* buggy daemons, etc.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* For methods returning a {@link CompletableFuture}, the documentation describes its return value
|
|
||||||
* assuming successful completion. Any of the futures may complete exceptionally.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The completion of any future returned by a method does not imply any state change in the
|
|
||||||
* debugger. It merely acknowledges that the request was received by the debugger. Only listener
|
|
||||||
* callbacks confirm or otherwise communicate actual state changes. If, in the underlying protocol,
|
|
||||||
* confirmation of a request implies a state change, then the implementation must make the
|
|
||||||
* appropriate callbacks.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The model object only exposes the connection state and a root object. The model comprises an
|
|
||||||
* arbitrary tree of {@link TargetObject}s each supporting zero or more discoverable interfaces. The
|
|
||||||
* debugging framework provides a number of "stock" interfaces which should be sufficient to model
|
|
||||||
* most debuggers. The tree is how the client accesses objects, e.g., processes and threads, on the
|
|
||||||
* target.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Users and implementors of this interface may find {@link AsyncUtils} useful. An implementation of
|
|
||||||
* this interface should never block the calling thread to wait on an external event, otherwise, you
|
|
||||||
* risk deadlocking Ghidra's UI.
|
|
||||||
*
|
|
||||||
* @deprecated Will be removed in 11.3. Portions may be refactored into trace object database.
|
|
||||||
*/
|
|
||||||
@Deprecated(forRemoval = true, since = "11.2")
|
|
||||||
public interface DebuggerObjectModel {
|
|
||||||
|
|
||||||
public static enum RefreshBehavior {
|
|
||||||
REFRESH_ALWAYS {
|
|
||||||
@Override
|
|
||||||
public boolean isRefresh(Collection<?> col) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
REFRESH_NEVER {
|
|
||||||
@Override
|
|
||||||
public boolean isRefresh(Collection<?> col) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
REFRESH_WHEN_ABSENT {
|
|
||||||
@Override
|
|
||||||
public boolean isRefresh(Collection<?> col) {
|
|
||||||
return col.isEmpty();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public abstract boolean isRefresh(Collection<?> col);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final TypeSpec<Map<String, ? extends TargetObject>> ELEMENT_MAP_TYPE =
|
|
||||||
TypeSpec.auto();
|
|
||||||
public static final TypeSpec<Map<String, ?>> ATTRIBUTE_MAP_TYPE = TypeSpec.auto();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check that a given {@link TargetObject} interface has a name
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Names are assigned using the {@link DebuggerTargetObjectIface} annotation.
|
|
||||||
*
|
|
||||||
* @implNote To be language agnostic, we never use the name of the Java implementation of the
|
|
||||||
* interface.
|
|
||||||
*
|
|
||||||
* @param iface the class of the interface
|
|
||||||
* @return the name of the interface
|
|
||||||
* @throws IllegalArgumentException if the interface is not annotated
|
|
||||||
*/
|
|
||||||
public static String requireIfaceName(Class<? extends TargetObject> iface) {
|
|
||||||
DebuggerTargetObjectIface annot = iface.getAnnotation(DebuggerTargetObjectIface.class);
|
|
||||||
if (annot == null) {
|
|
||||||
throw new IllegalArgumentException(iface + " has no @" +
|
|
||||||
DebuggerTargetObjectIface.class.getSimpleName() + " annotation.");
|
|
||||||
}
|
|
||||||
return annot.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check that the given value is not null
|
|
||||||
*
|
|
||||||
* @param <T> the type of the value
|
|
||||||
* @param val the value
|
|
||||||
* @param path the path where the value was expected
|
|
||||||
* @return the non-null value
|
|
||||||
* @throws DebuggerModelNoSuchPathException if -val- is null
|
|
||||||
*/
|
|
||||||
public static <T> T requireNonNull(T val, List<String> path) {
|
|
||||||
if (val == null) {
|
|
||||||
throw new DebuggerModelNoSuchPathException("Path " + path + " does not exist");
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check that the given object is non-null and supports a required interface
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Because most of the {@link TargetObject} interfaces have a (self-referential) type parameter,
|
|
||||||
* this call will most likely be on its own line, assigned to a variable of the interface type
|
|
||||||
* using a wildcard {@code <?>} parameter. Otherwise, raw types get involved, making things
|
|
||||||
* rather messy.
|
|
||||||
*
|
|
||||||
* @param <T> the type of the interface
|
|
||||||
* @param iface the class for the interface
|
|
||||||
* @param obj the object to check
|
|
||||||
* @param path the path where the object was expected
|
|
||||||
* @return the (non-null) object cast to the required interface
|
|
||||||
* @throws DebuggerModelNoSuchPathException if -obj- is null
|
|
||||||
* @throws DebuggerModelTypeException if -obj- does not support -iface-
|
|
||||||
*/
|
|
||||||
public static <T extends TargetObject> T requireIface(Class<T> iface, TargetObject obj,
|
|
||||||
List<String> path) {
|
|
||||||
requireNonNull(obj, path);
|
|
||||||
String name = requireIfaceName(iface);
|
|
||||||
if (iface.isAssignableFrom(obj.getClass())) {
|
|
||||||
return iface.cast(obj);
|
|
||||||
}
|
|
||||||
throw new DebuggerModelTypeException("Object " + path + " is missing " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a brief description of the client, suitable for display in lists
|
|
||||||
*
|
|
||||||
* @return the description
|
|
||||||
*/
|
|
||||||
public default String getBrief() {
|
|
||||||
return toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a listener for model events
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* If requested, the listener is notified of existing objects via an event replay. It will first
|
|
||||||
* replay all the created events in the same order they were originally emitted. Any objects
|
|
||||||
* which have since been invalidated are excluded in the replay. They don't exist anymore, after
|
|
||||||
* all. Next it will replay the attribute- and element-added events in post order. This is an
|
|
||||||
* attempt to ensure an object's dependencies are met by the time the client receives its added
|
|
||||||
* event. This isn't always possible due to cycles, but such cycles are usually informational.
|
|
||||||
*
|
|
||||||
* @param listener the listener
|
|
||||||
* @param replay true to replay object tree events (doesn't include register or memory caches)
|
|
||||||
*/
|
|
||||||
public void addModelListener(DebuggerModelListener listener, boolean replay);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a listener for model events, without replay
|
|
||||||
*
|
|
||||||
* @param listener the listener
|
|
||||||
*/
|
|
||||||
public default void addModelListener(DebuggerModelListener listener) {
|
|
||||||
addModelListener(listener, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a model event listener
|
|
||||||
*
|
|
||||||
* @param listener the listener
|
|
||||||
*/
|
|
||||||
public void removeModelListener(DebuggerModelListener listener);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the model believes it is alive
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Basically, this should be true if the model has started, but not yet terminated. To test
|
|
||||||
* whether the model is actually responsive, use {@link #ping(String)}.
|
|
||||||
*
|
|
||||||
* @return true if alive
|
|
||||||
*/
|
|
||||||
public boolean isAlive();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the schema of this model, i.e., the schema of its root object.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The schema may not be known until the model has been successfully opened. Some factories will
|
|
||||||
* ensure success before providing the model, but this may not always be the case. Callers
|
|
||||||
* should listen for {@link DebuggerModelListener#modelOpened()} or retrieve the root object
|
|
||||||
* first.
|
|
||||||
*
|
|
||||||
* @return the root schema
|
|
||||||
*/
|
|
||||||
public default TargetObjectSchema getRootSchema() {
|
|
||||||
return EnumerableTargetObjectSchema.OBJECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the debugger agent is alive (optional operation)
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* For models providing such a mechanism, check if the debugger is alive and able to process
|
|
||||||
* commands. Even if an explicit "ping" command is not available, an implementor is encouraged
|
|
||||||
* to use some sort of NOP or echo command to test for responsiveness.
|
|
||||||
*
|
|
||||||
* @param content some content to optionally incorporate into the test
|
|
||||||
* @return a future that completes when the daemon is verified to be alive
|
|
||||||
*/
|
|
||||||
public CompletableFuture<Void> ping(String content);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check that a given reference (or object) belongs to this model
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* As a convenience, this method takes an expected class and casts -ref- to it. This is meant
|
|
||||||
* only to cast to an implementation-specific type, not for checking that an object supports a
|
|
||||||
* given interface. Use {@link #requireIface(Class, TargetObject, List)} for interface checking.
|
|
||||||
*
|
|
||||||
* @param <T> the required implementation-specific type
|
|
||||||
* @param cls the class for the required type
|
|
||||||
* @param obj the object to check
|
|
||||||
* @return the object, cast to the desired typed
|
|
||||||
* @throws DebuggerIllegalArgumentException if {@code obj} does not belong to this model
|
|
||||||
*/
|
|
||||||
default <T extends TargetObject> T assertMine(Class<T> cls, TargetObject obj) {
|
|
||||||
if (obj.getModel() != this) {
|
|
||||||
throw new DebuggerIllegalArgumentException(
|
|
||||||
"TargetObject " + obj + " does not belong to this model");
|
|
||||||
}
|
|
||||||
return cls.cast(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the attributes of a given model path
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Giving an empty path will retrieve the attributes of the root object. If the path does not
|
|
||||||
* exist, the future completes with {@code null}.
|
|
||||||
*
|
|
||||||
* @param path the path
|
|
||||||
* @param refresh true to invalidate caches involved in handling this request
|
|
||||||
* @return a future map of attributes
|
|
||||||
*/
|
|
||||||
public CompletableFuture<? extends Map<String, ?>> fetchObjectAttributes(List<String> path,
|
|
||||||
RefreshBehavior refresh);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the attributes of the given model path, without refreshing
|
|
||||||
*
|
|
||||||
* @see #fetchObjectAttributes(List, RefreshBehavior)
|
|
||||||
*/
|
|
||||||
public default CompletableFuture<? extends Map<String, ?>> fetchObjectAttributes(
|
|
||||||
List<String> path) {
|
|
||||||
return fetchObjectAttributes(path, RefreshBehavior.REFRESH_NEVER);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see #fetchObjectAttributes(List)
|
|
||||||
*/
|
|
||||||
public default CompletableFuture<? extends Map<String, ?>> fetchObjectAttributes(
|
|
||||||
String... path) {
|
|
||||||
return fetchObjectAttributes(List.of(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the elements of a given model path
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Giving an empty path will retrieve all the top-level objects, i.e., elements of the root. If
|
|
||||||
* the path does not exist, the future completes with {@code null}.
|
|
||||||
*
|
|
||||||
* @param path the path
|
|
||||||
* @param refresh true to invalidate caches involved in handling this request
|
|
||||||
* @return a future map of elements
|
|
||||||
*/
|
|
||||||
public CompletableFuture<? extends Map<String, ? extends TargetObject>> fetchObjectElements(
|
|
||||||
List<String> path, RefreshBehavior refresh);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the elements of the given model path, without refreshing
|
|
||||||
*
|
|
||||||
* @see #fetchObjectElements(List, RefreshBehavior)
|
|
||||||
*/
|
|
||||||
public default CompletableFuture<? extends Map<String, ? extends TargetObject>> fetchObjectElements(
|
|
||||||
List<String> path) {
|
|
||||||
return fetchObjectElements(path, RefreshBehavior.REFRESH_NEVER);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see #fetchObjectElements(List)
|
|
||||||
*/
|
|
||||||
public default CompletableFuture<? extends Map<String, ? extends TargetObject>> fetchObjectElements(
|
|
||||||
String... path) {
|
|
||||||
return fetchObjectElements(List.of(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the root object of the model
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* The root is a virtual object to contain all the top-level objects of the model tree. This
|
|
||||||
* object represents the debugger itself. Note in most cases {@link #getModelRoot()} is
|
|
||||||
* sufficient; however, if you've just created the model, it is prudent to wait for it to create
|
|
||||||
* its root. For asynchronous cases, just listen for the root-creation and -added events. This
|
|
||||||
* method returns a future which completes after the root-added event.
|
|
||||||
*
|
|
||||||
* @return a future which completes with the root
|
|
||||||
*/
|
|
||||||
public CompletableFuture<? extends TargetObject> fetchModelRoot();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the root object of the model
|
|
||||||
*
|
|
||||||
* @return the root or {@code null} if it hasn't been created, yet
|
|
||||||
*/
|
|
||||||
public TargetObject getModelRoot();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the value at the given path
|
|
||||||
*
|
|
||||||
* @param path the path of the value
|
|
||||||
* @return a future completing with the value or with {@code null} if the path does not exist
|
|
||||||
*/
|
|
||||||
public CompletableFuture<?> fetchModelValue(List<String> path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch a model value, optionally refreshing caches along the path
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* By convention, no attribute nor element may have a {@code null} value. Thus, a {@code null}
|
|
||||||
* return value always indicates the path does not exist.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* When refresh is true, only the applicable cache at each successor is refreshed. For example,
|
|
||||||
* when the path is {@code A.B[1].C[2]}, then only {@code B}'s and {@code C}'s element caches
|
|
||||||
* are refreshed; and {@code A}'s, {@code B[1]}'s, and {@code C[2]}'s attribute caches are
|
|
||||||
* refreshed.
|
|
||||||
*
|
|
||||||
* @param path the path
|
|
||||||
* @param refresh true to refresh caches
|
|
||||||
* @return the found value, or {@code null} if it does not exist
|
|
||||||
*/
|
|
||||||
public CompletableFuture<?> fetchModelValue(List<String> path, RefreshBehavior refresh);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see #fetchModelValue(List)
|
|
||||||
*/
|
|
||||||
public default CompletableFuture<?> fetchModelValue(String... path) {
|
|
||||||
return fetchModelValue(List.of(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the value at a given path
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* If the path does not exist, null is returned. Note that an attempt to access the child of a
|
|
||||||
* primitive is the same as accessing a path that does not exist; however, an error will be
|
|
||||||
* logged, since this typically indicates a programming error.
|
|
||||||
*
|
|
||||||
* @param path the path
|
|
||||||
* @return the value
|
|
||||||
*/
|
|
||||||
public default Object getModelValue(List<String> path) {
|
|
||||||
Object cur = getModelRoot();
|
|
||||||
for (String key : path) {
|
|
||||||
if (cur == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (!(cur instanceof TargetObject)) {
|
|
||||||
Msg.error(this, "Primitive " + cur + " cannot have child '" + key + "'");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
TargetObject obj = (TargetObject) cur;
|
|
||||||
if (PathUtils.isIndex(key)) {
|
|
||||||
cur = obj.getCachedElements().get(PathUtils.parseIndex(key));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
assert PathUtils.isName(key);
|
|
||||||
cur = obj.getCachedAttribute(key);
|
|
||||||
}
|
|
||||||
return cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the object with the given path
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* If the value at the path is a link, this will attempt to fetch it.
|
|
||||||
*
|
|
||||||
* @param path the path of the object
|
|
||||||
* @param refresh ignore the cache
|
|
||||||
* @return a future completing with the object or with {@code null} if it does not exist
|
|
||||||
* @throws DebuggerModelTypeException if the value at the path is not a {@link TargetObject}
|
|
||||||
*/
|
|
||||||
public default CompletableFuture<? extends TargetObject> fetchModelObject(List<String> path,
|
|
||||||
RefreshBehavior refresh) {
|
|
||||||
return fetchModelValue(path, refresh).thenApply(v -> {
|
|
||||||
if (v == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (!(v instanceof TargetObject)) {
|
|
||||||
throw DebuggerModelTypeException.typeRequired(v, path, TargetObject.class);
|
|
||||||
}
|
|
||||||
return (TargetObject) v;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an object from the model, resyncing according to the schema
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This is necessary when an object in the path has a resync mode other than
|
|
||||||
* {@link ResyncMode#NEVER} for the child being retrieved. Please note that some synchronization
|
|
||||||
* may still be required on the client side, since accessing the object before it is created
|
|
||||||
* will cause a {@code null} completion.
|
|
||||||
*
|
|
||||||
* @return a future that completes with the object or with {@code null} if it doesn't exist
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public default CompletableFuture<? extends TargetObject> fetchModelObject(List<String> path) {
|
|
||||||
return fetchModelObject(path, RefreshBehavior.REFRESH_NEVER);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an object from the model
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Note this may return an object which is still being constructed, i.e., between being created
|
|
||||||
* and being added to the model. This differs from {@link #getModelValue(List)}, which will only
|
|
||||||
* return an object after it has been added. This method also never follows links.
|
|
||||||
*
|
|
||||||
* @param path the path of the object
|
|
||||||
* @return the object or {@code null} if it doesn't exist
|
|
||||||
*/
|
|
||||||
public TargetObject getModelObject(List<String> path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all created objects matching a given predicate
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Note the predicate is executed while holding an internal model-wide lock. Be careful and keep
|
|
||||||
* it simple.
|
|
||||||
*
|
|
||||||
* @param predicate the predicate
|
|
||||||
* @return the set of matching objects
|
|
||||||
*/
|
|
||||||
public Set<TargetObject> getModelObjects(Predicate<? super TargetObject> predicate);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see #fetchModelObject(List)
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public default CompletableFuture<? extends TargetObject> fetchModelObject(String... path) {
|
|
||||||
return fetchModelObject(List.of(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see #getModelObject(List)
|
|
||||||
*/
|
|
||||||
public default TargetObject getModelObject(String... path) {
|
|
||||||
return getModelObject(List.of(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the attribute with the given path
|
|
||||||
*
|
|
||||||
* Note that model implementations should avoid nullable attributes, since a null-valued
|
|
||||||
* attribute cannot easily be distinguished from a non-existent attribute.
|
|
||||||
*
|
|
||||||
* @param path the path of the attribute
|
|
||||||
* @return a future that completes with the value or with {@code null} if it does not exist
|
|
||||||
*/
|
|
||||||
public default CompletableFuture<?> fetchObjectAttribute(List<String> path) {
|
|
||||||
return fetchModelObject(PathUtils.parent(path)).thenApply(
|
|
||||||
parent -> parent == null ? null : parent.fetchAttribute(PathUtils.getKey(path)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see #fetchObjectAttribute(List)
|
|
||||||
*/
|
|
||||||
public default CompletableFuture<?> getObjectAttribute(String... path) {
|
|
||||||
return fetchObjectAttribute(List.of(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a factory for target addresses
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Technically, putting this here instead of just {@link TargetMemory} imposes a subtle
|
|
||||||
* limitation: All targets in the model have to have the same factory. I'm not certain that's a
|
|
||||||
* huge concern at this point. The alternative is that the memory mapper has to accept and
|
|
||||||
* compose new address factories, or we need a separate mapper per factory encountered along
|
|
||||||
* with a mechanism to choose the correct one.
|
|
||||||
*
|
|
||||||
* @return the factory
|
|
||||||
*/
|
|
||||||
public AddressFactory getAddressFactory();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO Document me
|
|
||||||
*
|
|
||||||
* @param name
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
default public AddressSpace getAddressSpace(String name) {
|
|
||||||
return getAddressFactory().getAddressSpace(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO Document me
|
|
||||||
*
|
|
||||||
* @param space
|
|
||||||
* @param offset
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public default Address getAddress(String space, long offset) {
|
|
||||||
if (Address.NO_ADDRESS.getAddressSpace().getName().equals(space)) {
|
|
||||||
return Address.NO_ADDRESS;
|
|
||||||
}
|
|
||||||
return getAddressSpace(space).getAddress(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invalidate the caches for every object known locally.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Unlike, {@link TargetObject#invalidateCaches()}, this does not push the request to a remote
|
|
||||||
* object. If the objects are proxies, just the proxies' caches are cleared. Again, this does
|
|
||||||
* not apply to caches for the objects' children.
|
|
||||||
*/
|
|
||||||
public void invalidateAllLocalCaches();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the session and dispose the model
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* For local sessions, terminate the debugger. For client sessions, disconnect.
|
|
||||||
*
|
|
||||||
* @return a future which completes when the session is closed
|
|
||||||
*/
|
|
||||||
public CompletableFuture<Void> close();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A convenience for reporting errors conditionally
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* If the message is ignorable, e.g., a {@link DebuggerModelTerminatingException}, then the
|
|
||||||
* report will be reduced to a stack-free warning.
|
|
||||||
*
|
|
||||||
* @param origin the object producing the error
|
|
||||||
* @param message the error message
|
|
||||||
* @param ex the exception
|
|
||||||
*/
|
|
||||||
default void reportError(Object origin, String message, Throwable ex) {
|
|
||||||
Throwable unwrapped = AsyncUtils.unwrapThrowable(ex);
|
|
||||||
if (ex == null || DebuggerModelTerminatingException.isIgnorable(ex)) {
|
|
||||||
Msg.warn(origin, message + ": " + ex);
|
|
||||||
}
|
|
||||||
else if (unwrapped instanceof RejectedExecutionException) {
|
|
||||||
Msg.trace(origin, "Ignoring rejection", ex);
|
|
||||||
}
|
|
||||||
else if (unwrapped instanceof DisposedException) {
|
|
||||||
Msg.trace(origin, "Ignoring disposal", ex);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Msg.error(origin, message, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Permit all callbacks to be invoked before proceeding
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This operates by placing the request into the queue itself, so that any event callbacks
|
|
||||||
* queued <em>at the time of the flush invocation</em> are completed first. There are no
|
|
||||||
* guarantees with respect to events which get queued <em>after the flush invocation</em>.
|
|
||||||
*
|
|
||||||
* @return a future which completes when all queued callbacks have been invoked
|
|
||||||
*/
|
|
||||||
CompletableFuture<Void> flushEvents();
|
|
||||||
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user