GP-1978: Delete Framework-Debugging. Merge needed parts into

TraceModeling.
This commit is contained in:
Dan 2024-12-11 17:02:23 -05:00
parent 8dd0ea698a
commit f5a93c3072
429 changed files with 5093 additions and 23085 deletions

View file

@ -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

View file

@ -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)."""

View file

@ -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>

View file

@ -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" />

View file

@ -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'):

View file

@ -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>

View file

@ -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>

View file

@ -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|

View file

@ -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>

View file

@ -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));
} }

View file

@ -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

View file

@ -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;
} }
} }

View file

@ -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)

View file

@ -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) {

View file

@ -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()) {

View file

@ -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();

View file

@ -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);
} }

View file

@ -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')
} }

View file

@ -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
* *

View file

@ -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 {

View file

@ -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);

View file

@ -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 {
@ -377,7 +377,9 @@ 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);
} }

View file

@ -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" />

View file

@ -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')
} }

View file

@ -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));
} }

View file

@ -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;
} }

View file

@ -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;

View file

@ -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;

View file

@ -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) {}

View file

@ -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

View file

@ -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;

View file

@ -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.*;
/** /**

View file

@ -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,

View file

@ -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)

View file

@ -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();
} }

View file

@ -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;

View file

@ -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,

View file

@ -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 {

View file

@ -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));

View file

@ -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()

View file

@ -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);
} }

View file

@ -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')
} }

View file

@ -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();
}
}

View file

@ -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) {

View file

@ -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) {

View file

@ -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;
} }

View file

@ -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, "")));
} }
} }

View file

@ -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);

View file

@ -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();
} }

View file

@ -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,7 +234,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 (involves(span, pattern, value)) { if (involves(span, pattern, value)) {
return true; return true;
} }
@ -242,6 +243,6 @@ public class ModelQuery {
} }
public boolean isEmpty() { public boolean isEmpty() {
return predicates.isEmpty(); return filter.isNone();
} }
} }

View file

@ -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;
} }

View file

@ -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 {

View file

@ -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);
} }
} }

View file

@ -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;
} }

View file

@ -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);
} }

View file

@ -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());
} }
} }

View file

@ -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();
} }
} }

View file

@ -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;
} }
} }

View file

@ -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;

View file

@ -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) {

View file

@ -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) {

View file

@ -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

View file

@ -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) {

View file

@ -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);
} }

View file

@ -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() {

View file

@ -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;
} }

View file

@ -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;
} }

View file

@ -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");
} }

View file

@ -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);
} }

View file

@ -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,

View file

@ -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));
} }

View file

@ -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);
} }

View file

@ -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;

View file

@ -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);

View file

@ -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 {

View file

@ -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;

View file

@ -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);

View file

@ -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));

View file

@ -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) {

View file

@ -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;
} }

View file

@ -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));

View file

@ -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();

View file

@ -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));
} }

View file

@ -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 =

View file

@ -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
} }

View file

@ -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;
} }

View file

@ -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);
} }

View file

@ -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

View file

@ -1 +0,0 @@
# Framework-Debugging

View file

@ -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")
}
}
}
}

View file

@ -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|

View file

@ -1 +0,0 @@
DebuggerClientFactory

View file

@ -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());
}
}
}

View file

@ -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);
});
}
}

View file

@ -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;
}
}

View file

@ -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();
}

View file

@ -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;
}
}

View file

@ -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) {
}
}

View file

@ -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;
}
}

View file

@ -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