mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
GP-4182: broken print statment
GP-4182: better labels GP-4182: minor edits GP-8192: better initial conditiaons GP-4182: snap fix GP-4182: sort of working GP-4182: fixing my rebase error
This commit is contained in:
parent
63e64d5b28
commit
50ccce6ac0
12 changed files with 3399 additions and 2 deletions
|
@ -2,8 +2,10 @@
|
||||||
##MODULE IP: Apache License 2.0
|
##MODULE IP: Apache License 2.0
|
||||||
Module.manifest||GHIDRA||||END|
|
Module.manifest||GHIDRA||||END|
|
||||||
data/debugger-launchers/local-dbgeng.bat||GHIDRA||||END|
|
data/debugger-launchers/local-dbgeng.bat||GHIDRA||||END|
|
||||||
|
data/debugger-launchers/local-ttd.bat||GHIDRA||||END|
|
||||||
src/main/py/LICENSE||GHIDRA||||END|
|
src/main/py/LICENSE||GHIDRA||||END|
|
||||||
src/main/py/README.md||GHIDRA||||END|
|
src/main/py/README.md||GHIDRA||||END|
|
||||||
src/main/py/pyproject.toml||GHIDRA||||END|
|
src/main/py/pyproject.toml||GHIDRA||||END|
|
||||||
src/main/py/src/ghidradbg/dbgmodel/DbgModel.idl||GHIDRA||||END|
|
src/main/py/src/ghidradbg/dbgmodel/DbgModel.idl||GHIDRA||||END|
|
||||||
src/main/py/src/ghidradbg/schema.xml||GHIDRA||||END|
|
src/main/py/src/ghidradbg/schema.xml||GHIDRA||||END|
|
||||||
|
src/main/py/src/ghidrattd/schema.xml||GHIDRA||||END|
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
::@title ttd
|
||||||
|
::@desc <html><body width="300px">
|
||||||
|
::@desc <h3>Launch with <tt>ttd</tt> (in a Python interpreter)</h3>
|
||||||
|
::@desc <p>This will launch the target on the local machine using <tt>dbgeng.dll</tt>. Typically,
|
||||||
|
::@desc Windows systems have this library pre-installed, but it may have limitations, e.g., you
|
||||||
|
::@desc cannot use <tt>.server</tt>. For the full capabilities, you must install WinDbg.</p>
|
||||||
|
::@desc <p>Furthermore, you must have Python 3 installed on your system, and it must have the
|
||||||
|
::@desc <tt>pybag</tt> and <tt>protobuf</tt> packages installed.</p>
|
||||||
|
::@desc </body></html>
|
||||||
|
::@menu-group local
|
||||||
|
::@icon icon.debugger
|
||||||
|
::@help TraceRmiLauncherServicePlugin#dbgeng
|
||||||
|
::@env OPT_PYTHON_EXE:str="python" "Path to python" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH."
|
||||||
|
:: Use env instead of args, because "all args except first" is terrible to implement in batch
|
||||||
|
::@env OPT_TARGET_IMG:str="" "Trace (.run)" "A trace associated with the target binary executable"
|
||||||
|
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
||||||
|
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
||||||
|
::@env OPT_DBGMODEL_PATH:str="" "Path to dbgeng & \\ttd" "Path to dbgeng and associated DLLS (if not Windows Kits)."
|
||||||
|
|
||||||
|
@echo off
|
||||||
|
|
||||||
|
"%OPT_PYTHON_EXE%" -i ..\support\local-ttd.py
|
58
Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-ttd.py
Normal file
58
Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-ttd.py
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
## ###
|
||||||
|
# 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.
|
||||||
|
##
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
home = os.getenv('GHIDRA_HOME')
|
||||||
|
|
||||||
|
if os.path.isdir(f'{home}\\ghidra\\.git'):
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\ghidra\\Ghidra\\Debug\\Debugger-agent-dbgeng\\build\\pypkg\\src')
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\ghidra\\Ghidra\\Debug\\Debugger-rmi-trace\\build\\pypkg\\src')
|
||||||
|
elif os.path.isdir(f'{home}\\.git'):
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-agent-dbgeng\\build\\pypkg\\src')
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-rmi-trace\\build\\pypkg\\src')
|
||||||
|
else:
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-agent-dbgeng\\pypkg\\src')
|
||||||
|
sys.path.append(f'{home}\\Ghidra\\Debug\\Debugger-rmi-trace\\pypkg\\src')
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Delay these imports until sys.path is patched
|
||||||
|
from ghidrattd import commands as cmd
|
||||||
|
from ghidrattd import hooks
|
||||||
|
###from ghidrattd.util import dbg
|
||||||
|
|
||||||
|
cmd.ghidra_trace_connect(os.getenv('GHIDRA_TRACE_RMI_ADDR'))
|
||||||
|
args = os.getenv('OPT_TARGET_ARGS')
|
||||||
|
if args:
|
||||||
|
args = ' ' + args
|
||||||
|
cmd.ghidra_trace_create(
|
||||||
|
os.getenv('OPT_TARGET_IMG') + args, start_trace=True)
|
||||||
|
cmd.ghidra_trace_sync_enable()
|
||||||
|
hooks.on_stop()
|
||||||
|
|
||||||
|
cmd.repl()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
|
@ -0,0 +1,19 @@
|
||||||
|
## ###
|
||||||
|
# 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.
|
||||||
|
##
|
||||||
|
|
||||||
|
# NOTE: libraries must precede EVERYTHING, esp pybag and DbgMod
|
||||||
|
|
||||||
|
from . import libraries, util, commands, methods, hooks
|
|
@ -0,0 +1,212 @@
|
||||||
|
## ###
|
||||||
|
# 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.
|
||||||
|
##
|
||||||
|
from ghidratrace.client import Address, RegVal
|
||||||
|
|
||||||
|
from pybag import pydbg
|
||||||
|
|
||||||
|
from . import util
|
||||||
|
|
||||||
|
language_map = {
|
||||||
|
'ARM': ['AARCH64:BE:64:v8A', 'AARCH64:LE:64:AppleSilicon', 'AARCH64:LE:64:v8A', 'ARM:BE:64:v8', 'ARM:LE:64:v8'],
|
||||||
|
'Itanium': [],
|
||||||
|
'x86': ['x86:LE:32:default'],
|
||||||
|
'x86_64': ['x86:LE:64:default'],
|
||||||
|
'EFI': ['x86:LE:64:default'],
|
||||||
|
}
|
||||||
|
|
||||||
|
data64_compiler_map = {
|
||||||
|
None: 'pointer64',
|
||||||
|
}
|
||||||
|
|
||||||
|
x86_compiler_map = {
|
||||||
|
'windows': 'windows',
|
||||||
|
'Cygwin': 'windows',
|
||||||
|
}
|
||||||
|
|
||||||
|
arm_compiler_map = {
|
||||||
|
'windows': 'windows',
|
||||||
|
}
|
||||||
|
|
||||||
|
compiler_map = {
|
||||||
|
'DATA:BE:64:default': data64_compiler_map,
|
||||||
|
'DATA:LE:64:default': data64_compiler_map,
|
||||||
|
'x86:LE:32:default': x86_compiler_map,
|
||||||
|
'x86:LE:64:default': x86_compiler_map,
|
||||||
|
'AARCH64:BE:64:v8A': arm_compiler_map,
|
||||||
|
'AARCH64:LE:64:AppleSilicon': arm_compiler_map,
|
||||||
|
'AARCH64:LE:64:v8A': arm_compiler_map,
|
||||||
|
'ARM:BE:64:v8': arm_compiler_map,
|
||||||
|
'ARM:LE:64:v8': arm_compiler_map,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_arch():
|
||||||
|
return "x86_64"
|
||||||
|
|
||||||
|
|
||||||
|
def get_endian():
|
||||||
|
return 'little'
|
||||||
|
|
||||||
|
|
||||||
|
def get_osabi():
|
||||||
|
return "windows"
|
||||||
|
|
||||||
|
|
||||||
|
def compute_ghidra_language():
|
||||||
|
# First, check if the parameter is set
|
||||||
|
lang = util.get_convenience_variable('ghidra-language')
|
||||||
|
if lang != 'auto':
|
||||||
|
return lang
|
||||||
|
|
||||||
|
# Get the list of possible languages for the arch. We'll need to sift
|
||||||
|
# through them by endian and probably prefer default/simpler variants. The
|
||||||
|
# heuristic for "simpler" will be 'default' then shortest variant id.
|
||||||
|
arch = get_arch()
|
||||||
|
endian = get_endian()
|
||||||
|
lebe = ':BE:' if endian == 'big' else ':LE:'
|
||||||
|
if not arch in language_map:
|
||||||
|
return 'DATA' + lebe + '64:default'
|
||||||
|
langs = language_map[arch]
|
||||||
|
matched_endian = sorted(
|
||||||
|
(l for l in langs if lebe in l),
|
||||||
|
key=lambda l: 0 if l.endswith(':default') else len(l)
|
||||||
|
)
|
||||||
|
if len(matched_endian) > 0:
|
||||||
|
return matched_endian[0]
|
||||||
|
# NOTE: I'm disinclined to fall back to a language match with wrong endian.
|
||||||
|
return 'DATA' + lebe + '64:default'
|
||||||
|
|
||||||
|
|
||||||
|
def compute_ghidra_compiler(lang):
|
||||||
|
# First, check if the parameter is set
|
||||||
|
comp = util.get_convenience_variable('ghidra-compiler')
|
||||||
|
if comp != 'auto':
|
||||||
|
return comp
|
||||||
|
|
||||||
|
# Check if the selected lang has specific compiler recommendations
|
||||||
|
if not lang in compiler_map:
|
||||||
|
return 'default'
|
||||||
|
comp_map = compiler_map[lang]
|
||||||
|
osabi = get_osabi()
|
||||||
|
if osabi in comp_map:
|
||||||
|
return comp_map[osabi]
|
||||||
|
if None in comp_map:
|
||||||
|
return comp_map[None]
|
||||||
|
return 'default'
|
||||||
|
|
||||||
|
|
||||||
|
def compute_ghidra_lcsp():
|
||||||
|
lang = compute_ghidra_language()
|
||||||
|
comp = compute_ghidra_compiler(lang)
|
||||||
|
return lang, comp
|
||||||
|
|
||||||
|
|
||||||
|
class DefaultMemoryMapper(object):
|
||||||
|
|
||||||
|
def __init__(self, defaultSpace):
|
||||||
|
self.defaultSpace = defaultSpace
|
||||||
|
|
||||||
|
def map(self, proc: int, offset: int):
|
||||||
|
space = self.defaultSpace
|
||||||
|
return self.defaultSpace, Address(space, offset)
|
||||||
|
|
||||||
|
def map_back(self, proc: int, address: Address) -> int:
|
||||||
|
if address.space == self.defaultSpace:
|
||||||
|
return address.offset
|
||||||
|
raise ValueError(f"Address {address} is not in process {proc.GetProcessID()}")
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_MEMORY_MAPPER = DefaultMemoryMapper('ram')
|
||||||
|
|
||||||
|
memory_mappers = {}
|
||||||
|
|
||||||
|
|
||||||
|
def compute_memory_mapper(lang):
|
||||||
|
if not lang in memory_mappers:
|
||||||
|
return DEFAULT_MEMORY_MAPPER
|
||||||
|
return memory_mappers[lang]
|
||||||
|
|
||||||
|
|
||||||
|
class DefaultRegisterMapper(object):
|
||||||
|
|
||||||
|
def __init__(self, byte_order):
|
||||||
|
if not byte_order in ['big', 'little']:
|
||||||
|
raise ValueError("Invalid byte_order: {}".format(byte_order))
|
||||||
|
self.byte_order = byte_order
|
||||||
|
self.union_winners = {}
|
||||||
|
|
||||||
|
def map_name(self, proc, name):
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
def map_value(self, proc, name, value):
|
||||||
|
try:
|
||||||
|
### TODO: this seems half-baked
|
||||||
|
av = value.to_bytes(8, "big")
|
||||||
|
except Exception:
|
||||||
|
raise ValueError("Cannot convert {}'s value: '{}', type: '{}'"
|
||||||
|
.format(name, value, type(value)))
|
||||||
|
return RegVal(self.map_name(proc, name), av)
|
||||||
|
|
||||||
|
def map_name_back(self, proc, name):
|
||||||
|
return name
|
||||||
|
|
||||||
|
def map_value_back(self, proc, name, value):
|
||||||
|
return RegVal(self.map_name_back(proc, name), value)
|
||||||
|
|
||||||
|
|
||||||
|
class Intel_x86_64_RegisterMapper(DefaultRegisterMapper):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__('little')
|
||||||
|
|
||||||
|
def map_name(self, proc, name):
|
||||||
|
if name is None:
|
||||||
|
return 'UNKNOWN'
|
||||||
|
if name == 'efl':
|
||||||
|
return 'rflags'
|
||||||
|
if name.startswith('zmm'):
|
||||||
|
# Ghidra only goes up to ymm, right now
|
||||||
|
return 'ymm' + name[3:]
|
||||||
|
return super().map_name(proc, name)
|
||||||
|
|
||||||
|
def map_value(self, proc, name, value):
|
||||||
|
rv = super().map_value(proc, name, value)
|
||||||
|
if rv.name.startswith('ymm') and len(rv.value) > 32:
|
||||||
|
return RegVal(rv.name, rv.value[-32:])
|
||||||
|
return rv
|
||||||
|
|
||||||
|
def map_name_back(self, proc, name):
|
||||||
|
if name == 'rflags':
|
||||||
|
return 'eflags'
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_BE_REGISTER_MAPPER = DefaultRegisterMapper('big')
|
||||||
|
DEFAULT_LE_REGISTER_MAPPER = DefaultRegisterMapper('little')
|
||||||
|
|
||||||
|
register_mappers = {
|
||||||
|
'x86:LE:64:default': Intel_x86_64_RegisterMapper()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def compute_register_mapper(lang):
|
||||||
|
if not lang in register_mappers:
|
||||||
|
if ':BE:' in lang:
|
||||||
|
return DEFAULT_BE_REGISTER_MAPPER
|
||||||
|
if ':LE:' in lang:
|
||||||
|
return DEFAULT_LE_REGISTER_MAPPER
|
||||||
|
return register_mappers[lang]
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,441 @@
|
||||||
|
## ###
|
||||||
|
# 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.
|
||||||
|
##
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import threading
|
||||||
|
|
||||||
|
from pybag import pydbg
|
||||||
|
from pybag.dbgeng.callbacks import EventHandler
|
||||||
|
from pybag.dbgeng import core as DbgEng
|
||||||
|
from pybag.dbgeng import exception
|
||||||
|
from pybag.dbgeng.idebugbreakpoint import DebugBreakpoint
|
||||||
|
|
||||||
|
from . import commands, util
|
||||||
|
|
||||||
|
ALL_EVENTS = 0xFFFF
|
||||||
|
|
||||||
|
class HookState(object):
|
||||||
|
__slots__ = ('installed', 'mem_catchpoint')
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.installed = False
|
||||||
|
self.mem_catchpoint = None
|
||||||
|
|
||||||
|
|
||||||
|
class ProcessState(object):
|
||||||
|
__slots__ = ('first', 'regions', 'modules', 'threads', 'breaks', 'watches', 'visited', 'waiting')
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.first = True
|
||||||
|
# For things we can detect changes to between stops
|
||||||
|
self.regions = False
|
||||||
|
self.modules = False
|
||||||
|
self.threads = False
|
||||||
|
self.breaks = False
|
||||||
|
self.watches = False
|
||||||
|
# For frames and threads that have already been synced since last stop
|
||||||
|
self.visited = set()
|
||||||
|
self.waiting = True
|
||||||
|
|
||||||
|
def record(self, description=None, snap=None):
|
||||||
|
first = self.first
|
||||||
|
self.first = False
|
||||||
|
if description is not None:
|
||||||
|
commands.STATE.trace.snapshot(description, snap=snap)
|
||||||
|
if first:
|
||||||
|
commands.put_processes()
|
||||||
|
commands.put_environment()
|
||||||
|
if self.threads:
|
||||||
|
commands.put_threads()
|
||||||
|
self.threads = False
|
||||||
|
thread = util.selected_thread()
|
||||||
|
if thread is not None:
|
||||||
|
if first or thread not in self.visited:
|
||||||
|
commands.putreg()
|
||||||
|
commands.putmem("$pc", "1", display_result=False)
|
||||||
|
commands.putmem("$sp", "1", display_result=False)
|
||||||
|
#commands.put_frames()
|
||||||
|
self.visited.add(thread)
|
||||||
|
#frame = util.selected_frame()
|
||||||
|
#hashable_frame = (thread, frame)
|
||||||
|
#if first or hashable_frame not in self.visited:
|
||||||
|
# self.visited.add(hashable_frame)
|
||||||
|
if first or self.regions:
|
||||||
|
commands.put_regions()
|
||||||
|
self.regions = False
|
||||||
|
if first or self.modules:
|
||||||
|
commands.put_modules()
|
||||||
|
self.modules = False
|
||||||
|
if first or self.breaks:
|
||||||
|
commands.put_breakpoints()
|
||||||
|
self.breaks = False
|
||||||
|
|
||||||
|
def record_continued(self):
|
||||||
|
commands.put_processes(running=True)
|
||||||
|
commands.put_threads(running=True)
|
||||||
|
|
||||||
|
def record_exited(self, exit_code, description=None, snap=None):
|
||||||
|
if description is not None:
|
||||||
|
commands.STATE.trace.snapshot(description, snap)
|
||||||
|
proc = util.selected_process()
|
||||||
|
ipath = commands.PROCESS_PATTERN.format(procnum=proc)
|
||||||
|
commands.STATE.trace.proxy_object_path(
|
||||||
|
ipath).set_value('_exit_code', exit_code)
|
||||||
|
|
||||||
|
|
||||||
|
class BrkState(object):
|
||||||
|
__slots__ = ('break_loc_counts',)
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.break_loc_counts = {}
|
||||||
|
|
||||||
|
def update_brkloc_count(self, b, count):
|
||||||
|
self.break_loc_counts[b.GetID()] = count
|
||||||
|
|
||||||
|
def get_brkloc_count(self, b):
|
||||||
|
return self.break_loc_counts.get(b.GetID(), 0)
|
||||||
|
|
||||||
|
def del_brkloc_count(self, b):
|
||||||
|
if b not in self.break_loc_counts:
|
||||||
|
return 0 # TODO: Print a warning?
|
||||||
|
count = self.break_loc_counts[b.GetID()]
|
||||||
|
del self.break_loc_counts[b.GetID()]
|
||||||
|
return count
|
||||||
|
|
||||||
|
|
||||||
|
HOOK_STATE = HookState()
|
||||||
|
BRK_STATE = BrkState()
|
||||||
|
PROC_STATE = {}
|
||||||
|
|
||||||
|
|
||||||
|
def on_state_changed(*args):
|
||||||
|
#print("ON_STATE_CHANGED")
|
||||||
|
if args[0] == DbgEng.DEBUG_CES_CURRENT_THREAD:
|
||||||
|
return on_thread_selected(args)
|
||||||
|
elif args[0] == DbgEng.DEBUG_CES_BREAKPOINTS:
|
||||||
|
return on_breakpoint_modified(args)
|
||||||
|
elif args[0] == DbgEng.DEBUG_CES_RADIX:
|
||||||
|
util.set_convenience_variable('output-radix', args[1])
|
||||||
|
return DbgEng.DEBUG_STATUS_GO
|
||||||
|
elif args[0] == DbgEng.DEBUG_CES_EXECUTION_STATUS:
|
||||||
|
proc = util.selected_process()
|
||||||
|
if args[1] & DbgEng.DEBUG_STATUS_INSIDE_WAIT:
|
||||||
|
PROC_STATE[proc].waiting = True
|
||||||
|
return DbgEng.DEBUG_STATUS_GO
|
||||||
|
PROC_STATE[proc].waiting = False
|
||||||
|
commands.put_state(proc)
|
||||||
|
if args[1] == DbgEng.DEBUG_STATUS_BREAK:
|
||||||
|
return on_stop(args)
|
||||||
|
else:
|
||||||
|
return on_cont(args)
|
||||||
|
return DbgEng.DEBUG_STATUS_GO
|
||||||
|
|
||||||
|
|
||||||
|
def on_debuggee_changed(*args):
|
||||||
|
#print("ON_DEBUGGEE_CHANGED")
|
||||||
|
trace = commands.STATE.trace
|
||||||
|
if trace is None:
|
||||||
|
return
|
||||||
|
if args[1] == DbgEng.DEBUG_CDS_REGISTERS:
|
||||||
|
on_register_changed(args[0][1])
|
||||||
|
#if args[1] == DbgEng.DEBUG_CDS_DATA:
|
||||||
|
# on_memory_changed(args[0][1])
|
||||||
|
return DbgEng.DEBUG_STATUS_GO
|
||||||
|
|
||||||
|
|
||||||
|
def on_session_status_changed(*args):
|
||||||
|
#print("ON_STATUS_CHANGED")
|
||||||
|
trace = commands.STATE.trace
|
||||||
|
if trace is None:
|
||||||
|
return
|
||||||
|
if args[0] == DbgEng.DEBUG_SESSION_ACTIVE or args[0] == DbgEng.DEBUG_SSESION_REBOOT:
|
||||||
|
with commands.STATE.client.batch():
|
||||||
|
with trace.open_tx("New Process {}".format(util.selected_process())):
|
||||||
|
commands.put_processes()
|
||||||
|
return DbgEng.DEBUG_STATUS_GO
|
||||||
|
|
||||||
|
|
||||||
|
def on_symbol_state_changed(*args):
|
||||||
|
#print("ON_SYMBOL_STATE_CHANGED")
|
||||||
|
trace = commands.STATE.trace
|
||||||
|
if trace is None:
|
||||||
|
return
|
||||||
|
if args[0] == 1 or args[0] == 2:
|
||||||
|
PROC_STATE[proc].modules = True
|
||||||
|
return DbgEng.DEBUG_STATUS_GO
|
||||||
|
|
||||||
|
|
||||||
|
def on_system_error(*args):
|
||||||
|
print("ON_SYSTEM_ERROR")
|
||||||
|
print(hex(args[0]))
|
||||||
|
trace = commands.STATE.trace
|
||||||
|
if trace is None:
|
||||||
|
return
|
||||||
|
with commands.STATE.client.batch():
|
||||||
|
with trace.open_tx("New Process {}".format(util.selected_process())):
|
||||||
|
commands.put_processes()
|
||||||
|
return DbgEng.DEBUG_STATUS_BREAK
|
||||||
|
|
||||||
|
|
||||||
|
def on_new_process(*args):
|
||||||
|
#print("ON_NEW_PROCESS")
|
||||||
|
trace = commands.STATE.trace
|
||||||
|
if trace is None:
|
||||||
|
return
|
||||||
|
with commands.STATE.client.batch():
|
||||||
|
with trace.open_tx("New Process {}".format(util.selected_process())):
|
||||||
|
commands.put_processes()
|
||||||
|
return DbgEng.DEBUG_STATUS_BREAK
|
||||||
|
|
||||||
|
|
||||||
|
def on_process_selected():
|
||||||
|
#print("PROCESS_SELECTED")
|
||||||
|
proc = util.selected_process()
|
||||||
|
if proc not in PROC_STATE:
|
||||||
|
return
|
||||||
|
trace = commands.STATE.trace
|
||||||
|
if trace is None:
|
||||||
|
return
|
||||||
|
with commands.STATE.client.batch():
|
||||||
|
with trace.open_tx("Process {} selected".format(proc)):
|
||||||
|
PROC_STATE[proc].record()
|
||||||
|
commands.activate()
|
||||||
|
|
||||||
|
|
||||||
|
def on_process_deleted(*args):
|
||||||
|
#print("ON_PROCESS_DELETED")
|
||||||
|
proc = args[0]
|
||||||
|
on_exited(proc)
|
||||||
|
if proc in PROC_STATE:
|
||||||
|
del PROC_STATE[proc]
|
||||||
|
trace = commands.STATE.trace
|
||||||
|
if trace is None:
|
||||||
|
return
|
||||||
|
with commands.STATE.client.batch():
|
||||||
|
with trace.open_tx("Process {} deleted".format(proc)):
|
||||||
|
commands.put_processes() # TODO: Could just delete the one....
|
||||||
|
return DbgEng.DEBUG_STATUS_BREAK
|
||||||
|
|
||||||
|
|
||||||
|
def on_threads_changed(*args):
|
||||||
|
#print("ON_THREADS_CHANGED")
|
||||||
|
proc = util.selected_process()
|
||||||
|
if proc not in PROC_STATE:
|
||||||
|
return DbgEng.DEBUG_STATUS_GO
|
||||||
|
PROC_STATE[proc].threads = True
|
||||||
|
return DbgEng.DEBUG_STATUS_GO
|
||||||
|
|
||||||
|
|
||||||
|
def on_thread_selected(*args):
|
||||||
|
#print("THREAD_SELECTED")
|
||||||
|
nthrd = args[0][1]
|
||||||
|
nproc = util.selected_process()
|
||||||
|
if nproc not in PROC_STATE:
|
||||||
|
return
|
||||||
|
trace = commands.STATE.trace
|
||||||
|
if trace is None:
|
||||||
|
return
|
||||||
|
with commands.STATE.client.batch():
|
||||||
|
with trace.open_tx("Thread {}.{} selected".format(nproc, nthrd)):
|
||||||
|
commands.put_state(nproc)
|
||||||
|
state = PROC_STATE[nproc]
|
||||||
|
if state.waiting:
|
||||||
|
state.record_continued()
|
||||||
|
else:
|
||||||
|
state.record()
|
||||||
|
commands.activate()
|
||||||
|
|
||||||
|
|
||||||
|
def on_register_changed(regnum):
|
||||||
|
#print("REGISTER_CHANGED")
|
||||||
|
proc = util.selected_process()
|
||||||
|
if proc not in PROC_STATE:
|
||||||
|
return
|
||||||
|
trace = commands.STATE.trace
|
||||||
|
if trace is None:
|
||||||
|
return
|
||||||
|
with commands.STATE.client.batch():
|
||||||
|
with trace.open_tx("Register {} changed".format(regnum)):
|
||||||
|
commands.putreg()
|
||||||
|
commands.activate()
|
||||||
|
|
||||||
|
|
||||||
|
def on_cont(*args):
|
||||||
|
proc = util.selected_process()
|
||||||
|
if proc not in PROC_STATE:
|
||||||
|
return
|
||||||
|
trace = commands.STATE.trace
|
||||||
|
if trace is None:
|
||||||
|
return
|
||||||
|
state = PROC_STATE[proc]
|
||||||
|
with commands.STATE.client.batch():
|
||||||
|
with trace.open_tx("Continued"):
|
||||||
|
state.record_continued()
|
||||||
|
return DbgEng.DEBUG_STATUS_GO
|
||||||
|
|
||||||
|
|
||||||
|
def on_stop(*args):
|
||||||
|
proc = util.selected_process()
|
||||||
|
if proc not in PROC_STATE:
|
||||||
|
print("not in state")
|
||||||
|
return
|
||||||
|
trace = commands.STATE.trace
|
||||||
|
if trace is None:
|
||||||
|
print("no trace")
|
||||||
|
return
|
||||||
|
state = PROC_STATE[proc]
|
||||||
|
state.visited.clear()
|
||||||
|
pos = dbg().get_position()
|
||||||
|
rng = range(pos.major, util.lastpos.major)
|
||||||
|
if pos.major > util.lastpos.major:
|
||||||
|
rng = range(util.lastpos.major, pos.major)
|
||||||
|
for i in rng:
|
||||||
|
if util.evttypes.__contains__(i):
|
||||||
|
type = util.evttypes[i]
|
||||||
|
if type == "modload" or type == "modunload":
|
||||||
|
on_modules_changed()
|
||||||
|
if type == "threadcreated" or type == "threadterm":
|
||||||
|
on_threads_changed()
|
||||||
|
util.lastpos = pos
|
||||||
|
with commands.STATE.client.batch():
|
||||||
|
with trace.open_tx("Stopped"):
|
||||||
|
state.record("Stopped", util.pos2snap(pos))
|
||||||
|
commands.put_state(proc)
|
||||||
|
commands.put_event_thread()
|
||||||
|
commands.activate()
|
||||||
|
|
||||||
|
|
||||||
|
def on_exited(proc):
|
||||||
|
if proc not in PROC_STATE:
|
||||||
|
print("not in state")
|
||||||
|
return
|
||||||
|
trace = commands.STATE.trace
|
||||||
|
if trace is None:
|
||||||
|
return
|
||||||
|
state = PROC_STATE[proc]
|
||||||
|
state.visited.clear()
|
||||||
|
exit_code = util.GetExitCode()
|
||||||
|
description = "Exited with code {}".format(exit_code)
|
||||||
|
with commands.STATE.client.batch():
|
||||||
|
with trace.open_tx(description):
|
||||||
|
state.record_exited(exit_code, description)
|
||||||
|
commands.activate()
|
||||||
|
|
||||||
|
|
||||||
|
def on_modules_changed(*args):
|
||||||
|
#print("ON_MODULES_CHANGED")
|
||||||
|
proc = util.selected_process()
|
||||||
|
if proc not in PROC_STATE:
|
||||||
|
return DbgEng.DEBUG_STATUS_GO
|
||||||
|
PROC_STATE[proc].modules = True
|
||||||
|
return DbgEng.DEBUG_STATUS_GO
|
||||||
|
|
||||||
|
|
||||||
|
def on_breakpoint_created(bp):
|
||||||
|
proc = util.selected_process()
|
||||||
|
if proc not in PROC_STATE:
|
||||||
|
return
|
||||||
|
PROC_STATE[proc].breaks = True
|
||||||
|
trace = commands.STATE.trace
|
||||||
|
if trace is None:
|
||||||
|
return
|
||||||
|
ibpath = commands.PROC_BREAKS_PATTERN.format(procnum=proc)
|
||||||
|
with commands.STATE.client.batch():
|
||||||
|
with trace.open_tx("Breakpoint {} created".format(bp.id)):
|
||||||
|
ibobj = trace.create_object(ibpath)
|
||||||
|
# Do not use retain_values or it'll remove other locs
|
||||||
|
commands.put_single_breakpoint(bp, ibobj, proc, [])
|
||||||
|
ibobj.insert()
|
||||||
|
|
||||||
|
|
||||||
|
def on_breakpoint_modified(*args):
|
||||||
|
#print("BREAKPOINT_MODIFIED")
|
||||||
|
proc = util.selected_process()
|
||||||
|
if proc not in PROC_STATE:
|
||||||
|
return
|
||||||
|
PROC_STATE[proc].breaks = True
|
||||||
|
trace = commands.STATE.trace
|
||||||
|
if trace is None:
|
||||||
|
return
|
||||||
|
ibpath = commands.PROC_BREAKS_PATTERN.format(procnum=proc)
|
||||||
|
ibobj = trace.create_object(ibpath)
|
||||||
|
bpid = args[0][1]
|
||||||
|
try:
|
||||||
|
bp = dbg()._control.GetBreakpointById(bpid)
|
||||||
|
except exception.E_NOINTERFACE_Error:
|
||||||
|
dbg().breakpoints._remove_stale(bpid)
|
||||||
|
return on_breakpoint_deleted(bpid)
|
||||||
|
return on_breakpoint_created(bp)
|
||||||
|
|
||||||
|
|
||||||
|
def on_breakpoint_deleted(bpt):
|
||||||
|
proc = util.selected_process()
|
||||||
|
if proc not in PROC_STATE:
|
||||||
|
return
|
||||||
|
PROC_STATE[proc].breaks = True
|
||||||
|
trace = commands.STATE.trace
|
||||||
|
if trace is None:
|
||||||
|
return
|
||||||
|
bpath = commands.PROC_BREAK_PATTERN.format(procnum=proc, breaknum=bpt.id)
|
||||||
|
with commands.STATE.client.batch():
|
||||||
|
with trace.open_tx("Breakpoint {} deleted".format(bpt.id)):
|
||||||
|
trace.proxy_object_path(bpath).remove(tree=True)
|
||||||
|
|
||||||
|
|
||||||
|
def on_breakpoint_hit(*args):
|
||||||
|
trace = commands.STATE.trace
|
||||||
|
if trace is None:
|
||||||
|
return
|
||||||
|
with commands.STATE.client.batch():
|
||||||
|
with trace.open_tx("New Process {}".format(util.selected_process())):
|
||||||
|
commands.put_processes()
|
||||||
|
return DbgEng.DEBUG_STATUS_GO
|
||||||
|
|
||||||
|
|
||||||
|
def on_exception(*args):
|
||||||
|
trace = commands.STATE.trace
|
||||||
|
if trace is None:
|
||||||
|
return
|
||||||
|
with commands.STATE.client.batch():
|
||||||
|
with trace.open_tx("New Process {}".format(util.selected_process())):
|
||||||
|
commands.put_processes()
|
||||||
|
return DbgEng.DEBUG_STATUS_GO
|
||||||
|
|
||||||
|
|
||||||
|
def install_hooks():
|
||||||
|
if HOOK_STATE.installed:
|
||||||
|
return
|
||||||
|
HOOK_STATE.installed = True
|
||||||
|
|
||||||
|
def remove_hooks():
|
||||||
|
if not HOOK_STATE.installed:
|
||||||
|
return
|
||||||
|
HOOK_STATE.installed = False
|
||||||
|
|
||||||
|
|
||||||
|
def enable_current_process():
|
||||||
|
proc = util.selected_process()
|
||||||
|
PROC_STATE[proc] = ProcessState()
|
||||||
|
|
||||||
|
|
||||||
|
def disable_current_process():
|
||||||
|
proc = util.selected_process()
|
||||||
|
if proc in PROC_STATE:
|
||||||
|
# Silently ignore already disabled
|
||||||
|
del PROC_STATE[proc]
|
||||||
|
|
||||||
|
def dbg():
|
||||||
|
return util.get_debugger()
|
|
@ -0,0 +1,78 @@
|
||||||
|
## ###
|
||||||
|
# IP: GHIDRA
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
##
|
||||||
|
import ctypes
|
||||||
|
import os
|
||||||
|
import platform
|
||||||
|
|
||||||
|
import comtypes
|
||||||
|
import comtypes.client
|
||||||
|
|
||||||
|
|
||||||
|
ctypes.windll.kernel32.SetErrorMode(0x0001 | 0x0002 | 0x8000)
|
||||||
|
|
||||||
|
if platform.architecture()[0] == '64bit':
|
||||||
|
dbgdirs = [os.getenv('OPT_DBGMODEL_PATH'),
|
||||||
|
r'C:\Program Files\Windows Kits\10\Debuggers\x64',
|
||||||
|
r'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64']
|
||||||
|
else:
|
||||||
|
dbgdirs = [os.getenv('OPT_DBGMODEL_PATH'),
|
||||||
|
r'C:\Program Files\Windows Kits\10\Debuggers\x86',
|
||||||
|
r'C:\Program Files (x86)\Windows Kits\10\Debuggers\x86']
|
||||||
|
dbgdir = None
|
||||||
|
for _dir in dbgdirs:
|
||||||
|
if _dir is not None and os.path.exists(_dir):
|
||||||
|
dbgdir = _dir
|
||||||
|
break
|
||||||
|
|
||||||
|
if not dbgdir:
|
||||||
|
raise RuntimeError("Windbg install directory not found!")
|
||||||
|
|
||||||
|
print(f"Loading dbgeng and friends from {dbgdir}")
|
||||||
|
|
||||||
|
# preload these to get correct DLLs loaded
|
||||||
|
try:
|
||||||
|
ctypes.windll.LoadLibrary(os.path.join(dbgdir, 'dbghelp.dll'))
|
||||||
|
except Exception as exc:
|
||||||
|
print(fr"LoadLibrary failed: {dbgdir}\dbghelp.dll {exc}")
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
ctypes.windll.LoadLibrary(os.path.join(dbgdir, 'dbgeng.dll'))
|
||||||
|
except Exception as exc:
|
||||||
|
print(fr"LoadLibrary failed: {dbgdir}\dbgeng.dll {exc}")
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
ctypes.windll.LoadLibrary(os.path.join(dbgdir, 'DbgModel.dll'))
|
||||||
|
except Exception as exc:
|
||||||
|
print(fr"LoadLibrary failed: {dbgdir}\dbgmodel.dll {exc}")
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
ctypes.windll.LoadLibrary(os.path.join(dbgdir, 'ttd/TTDReplay.dll'))
|
||||||
|
except Exception as exc:
|
||||||
|
print(fr"LoadLibrary failed: {dbgdir}\ttd\TTDReplay.dll {exc}")
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
ctypes.windll.LoadLibrary(os.path.join(dbgdir, 'ttd/TTDReplayCPU.dll'))
|
||||||
|
except Exception as exc:
|
||||||
|
print(fr"LoadLibrary failed: {dbgdir}\ttd\TTDReplayCPU.dll {exc}")
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
from comtypes.gen import DbgMod
|
||||||
|
except:
|
||||||
|
tlb = os.path.join(dbgmodel.module_locator(), 'tlb', 'dbgmodel.tlb')
|
||||||
|
print(f"Loading TLB: {tlb}")
|
||||||
|
comtypes.client.GetModule(tlb)
|
||||||
|
from comtypes.gen import DbgMod
|
|
@ -0,0 +1,536 @@
|
||||||
|
## ###
|
||||||
|
# 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.
|
||||||
|
##
|
||||||
|
from concurrent.futures import Future, ThreadPoolExecutor
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from ghidratrace import sch
|
||||||
|
from ghidratrace.client import MethodRegistry, ParamDesc, Address, AddressRange
|
||||||
|
|
||||||
|
from pyttd import pyTTD
|
||||||
|
#from pybag import pydbg
|
||||||
|
#from pybag.dbgeng import core as DbgEng
|
||||||
|
|
||||||
|
from . import util, commands, hooks
|
||||||
|
from contextlib import redirect_stdout
|
||||||
|
from io import StringIO
|
||||||
|
|
||||||
|
|
||||||
|
REGISTRY = MethodRegistry(ThreadPoolExecutor(max_workers=1))
|
||||||
|
|
||||||
|
|
||||||
|
def extre(base, ext):
|
||||||
|
return re.compile(base.pattern + ext)
|
||||||
|
|
||||||
|
|
||||||
|
AVAILABLE_PATTERN = re.compile(r'Available\[(?P<pid>\\d*)\]')
|
||||||
|
WATCHPOINT_PATTERN = re.compile(r'Watchpoints\[(?P<watchnum>\\d*)\]')
|
||||||
|
BREAKPOINT_PATTERN = re.compile(r'Breakpoints\[(?P<breaknum>\\d*)\]')
|
||||||
|
BREAK_LOC_PATTERN = extre(BREAKPOINT_PATTERN, r'\[(?P<locnum>\\d*)\]')
|
||||||
|
PROCESS_PATTERN = re.compile(r'Processes\[(?P<procnum>\\d*)\]')
|
||||||
|
PROC_BREAKS_PATTERN = extre(PROCESS_PATTERN, r'\.Breakpoints')
|
||||||
|
PROC_BREAKBPT_PATTERN = extre(PROC_BREAKS_PATTERN, r'\[(?P<breaknum>\\d*)\]')
|
||||||
|
ENV_PATTERN = extre(PROCESS_PATTERN, r'\.Environment')
|
||||||
|
THREADS_PATTERN = extre(PROCESS_PATTERN, r'\.Threads')
|
||||||
|
THREAD_PATTERN = extre(THREADS_PATTERN, r'\[(?P<tnum>\\d*)\]')
|
||||||
|
STACK_PATTERN = extre(THREAD_PATTERN, r'\.Stack')
|
||||||
|
FRAME_PATTERN = extre(STACK_PATTERN, r'\[(?P<level>\\d*)\]')
|
||||||
|
REGS_PATTERN0 = extre(THREAD_PATTERN, r'.Registers')
|
||||||
|
REGS_PATTERN = extre(FRAME_PATTERN, r'.Registers')
|
||||||
|
MEMORY_PATTERN = extre(PROCESS_PATTERN, r'\.Memory')
|
||||||
|
MODULES_PATTERN = extre(PROCESS_PATTERN, r'\.Modules')
|
||||||
|
|
||||||
|
|
||||||
|
def find_availpid_by_pattern(pattern, object, err_msg):
|
||||||
|
mat = pattern.fullmatch(object.path)
|
||||||
|
if mat is None:
|
||||||
|
raise TypeError(f"{object} is not {err_msg}")
|
||||||
|
pid = int(mat['pid'])
|
||||||
|
return pid
|
||||||
|
|
||||||
|
|
||||||
|
def find_availpid_by_obj(object):
|
||||||
|
return find_availpid_by_pattern(AVAILABLE_PATTERN, object, "an Available")
|
||||||
|
|
||||||
|
|
||||||
|
def find_proc_by_num(id):
|
||||||
|
if id != util.selected_process():
|
||||||
|
util.select_process(id)
|
||||||
|
return util.selected_process()
|
||||||
|
|
||||||
|
|
||||||
|
def find_proc_by_pattern(object, pattern, err_msg):
|
||||||
|
mat = pattern.fullmatch(object.path)
|
||||||
|
if mat is None:
|
||||||
|
raise TypeError(f"{object} is not {err_msg}")
|
||||||
|
procnum = int(mat['procnum'])
|
||||||
|
return find_proc_by_num(procnum)
|
||||||
|
|
||||||
|
|
||||||
|
def find_proc_by_obj(object):
|
||||||
|
return find_proc_by_pattern(object, PROCESS_PATTERN, "an Process")
|
||||||
|
|
||||||
|
|
||||||
|
def find_proc_by_procbreak_obj(object):
|
||||||
|
return find_proc_by_pattern(object, PROC_BREAKS_PATTERN,
|
||||||
|
"a BreakpointLocationContainer")
|
||||||
|
|
||||||
|
|
||||||
|
def find_proc_by_procwatch_obj(object):
|
||||||
|
return find_proc_by_pattern(object, PROC_WATCHES_PATTERN,
|
||||||
|
"a WatchpointContainer")
|
||||||
|
|
||||||
|
|
||||||
|
def find_proc_by_env_obj(object):
|
||||||
|
return find_proc_by_pattern(object, ENV_PATTERN, "an Environment")
|
||||||
|
|
||||||
|
|
||||||
|
def find_proc_by_threads_obj(object):
|
||||||
|
return find_proc_by_pattern(object, THREADS_PATTERN, "a ThreadContainer")
|
||||||
|
|
||||||
|
|
||||||
|
def find_proc_by_mem_obj(object):
|
||||||
|
return find_proc_by_pattern(object, MEMORY_PATTERN, "a Memory")
|
||||||
|
|
||||||
|
|
||||||
|
def find_proc_by_modules_obj(object):
|
||||||
|
return find_proc_by_pattern(object, MODULES_PATTERN, "a ModuleContainer")
|
||||||
|
|
||||||
|
|
||||||
|
def find_thread_by_num(id):
|
||||||
|
if id != util.selected_thread():
|
||||||
|
util.select_thread(id)
|
||||||
|
return util.selected_thread()
|
||||||
|
|
||||||
|
|
||||||
|
def find_thread_by_pattern(pattern, object, err_msg):
|
||||||
|
mat = pattern.fullmatch(object.path)
|
||||||
|
if mat is None:
|
||||||
|
raise TypeError(f"{object} is not {err_msg}")
|
||||||
|
pnum = int(mat['procnum'])
|
||||||
|
tnum = int(mat['tnum'])
|
||||||
|
find_proc_by_num(pnum)
|
||||||
|
return find_thread_by_num(tnum)
|
||||||
|
|
||||||
|
|
||||||
|
def find_thread_by_obj(object):
|
||||||
|
return find_thread_by_pattern(THREAD_PATTERN, object, "a Thread")
|
||||||
|
|
||||||
|
|
||||||
|
def find_thread_by_stack_obj(object):
|
||||||
|
return find_thread_by_pattern(STACK_PATTERN, object, "a Stack")
|
||||||
|
|
||||||
|
|
||||||
|
def find_thread_by_regs_obj(object):
|
||||||
|
return find_thread_by_pattern(REGS_PATTERN0, object, "a RegisterValueContainer")
|
||||||
|
|
||||||
|
|
||||||
|
def find_frame_by_level(level):
|
||||||
|
return dbg().backtrace_list()[level]
|
||||||
|
|
||||||
|
|
||||||
|
def find_frame_by_pattern(pattern, object, err_msg):
|
||||||
|
mat = pattern.fullmatch(object.path)
|
||||||
|
if mat is None:
|
||||||
|
raise TypeError(f"{object} is not {err_msg}")
|
||||||
|
pnum = int(mat['procnum'])
|
||||||
|
tnum = int(mat['tnum'])
|
||||||
|
level = int(mat['level'])
|
||||||
|
find_proc_by_num(pnum)
|
||||||
|
find_thread_by_num(tnum)
|
||||||
|
return find_frame_by_level(level)
|
||||||
|
|
||||||
|
|
||||||
|
def find_frame_by_obj(object):
|
||||||
|
return find_frame_by_pattern(FRAME_PATTERN, object, "a StackFrame")
|
||||||
|
|
||||||
|
|
||||||
|
def find_bpt_by_number(breaknum):
|
||||||
|
try:
|
||||||
|
bp = util.breakpoints[breaknum]
|
||||||
|
return bp
|
||||||
|
except exception.E_NOINTERFACE_Error:
|
||||||
|
raise KeyError(f"Breakpoints[{breaknum}] does not exist")
|
||||||
|
|
||||||
|
|
||||||
|
def find_bpt_by_pattern(pattern, object, err_msg):
|
||||||
|
mat = pattern.fullmatch(object.path)
|
||||||
|
if mat is None:
|
||||||
|
raise TypeError(f"{object} is not {err_msg}")
|
||||||
|
breaknum = int(mat['breaknum'])
|
||||||
|
return find_bpt_by_number(breaknum)
|
||||||
|
|
||||||
|
|
||||||
|
def find_bpt_by_obj(object):
|
||||||
|
return find_bpt_by_pattern(PROC_BREAKBPT_PATTERN, object, "a BreakpointSpec")
|
||||||
|
|
||||||
|
|
||||||
|
shared_globals = dict()
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method
|
||||||
|
def execute(cmd: str, to_string: bool=False):
|
||||||
|
"""Execute a CLI command."""
|
||||||
|
# print("***{}***".format(cmd))
|
||||||
|
# sys.stderr.flush()
|
||||||
|
# sys.stdout.flush()
|
||||||
|
if to_string:
|
||||||
|
data = StringIO()
|
||||||
|
with redirect_stdout(data):
|
||||||
|
exec("{}".format(cmd), shared_globals)
|
||||||
|
return data.getvalue()
|
||||||
|
else:
|
||||||
|
exec("{}".format(cmd), shared_globals)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method
|
||||||
|
def evaluate(expr: str):
|
||||||
|
"""Execute a CLI command."""
|
||||||
|
return str(eval("{}".format(expr), shared_globals))
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='refresh')
|
||||||
|
def refresh_available(node: sch.Schema('AvailableContainer')):
|
||||||
|
"""List processes on pydbg's host system."""
|
||||||
|
with commands.open_tracked_tx('Refresh Available'):
|
||||||
|
commands.ghidra_trace_put_available()
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='refresh')
|
||||||
|
def refresh_breakpoints(node: sch.Schema('BreakpointContainer')):
|
||||||
|
"""
|
||||||
|
Refresh the list of breakpoints (including locations for the current
|
||||||
|
process).
|
||||||
|
"""
|
||||||
|
with commands.open_tracked_tx('Refresh Breakpoints'):
|
||||||
|
commands.ghidra_trace_put_breakpoints()
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='refresh')
|
||||||
|
def refresh_processes(node: sch.Schema('ProcessContainer')):
|
||||||
|
"""Refresh the list of processes."""
|
||||||
|
with commands.open_tracked_tx('Refresh Processes'):
|
||||||
|
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')):
|
||||||
|
"""Refresh the environment descriptors (arch, os, endian)."""
|
||||||
|
with commands.open_tracked_tx('Refresh Environment'):
|
||||||
|
commands.ghidra_trace_put_environment()
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='refresh')
|
||||||
|
def refresh_threads(node: sch.Schema('ThreadContainer')):
|
||||||
|
"""Refresh the list of threads in the process."""
|
||||||
|
with commands.open_tracked_tx('Refresh Threads'):
|
||||||
|
commands.ghidra_trace_put_threads()
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='refresh')
|
||||||
|
def refresh_stack(node: sch.Schema('Stack')):
|
||||||
|
"""Refresh the backtrace for the thread."""
|
||||||
|
tnum = find_thread_by_stack_obj(node)
|
||||||
|
with commands.open_tracked_tx('Refresh Stack'):
|
||||||
|
commands.ghidra_trace_put_frames()
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='refresh')
|
||||||
|
def refresh_registers(node: sch.Schema('RegisterValueContainer')):
|
||||||
|
"""Refresh the register values for the frame."""
|
||||||
|
tnum = find_thread_by_regs_obj(node)
|
||||||
|
with commands.open_tracked_tx('Refresh Registers'):
|
||||||
|
commands.ghidra_trace_putreg()
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='refresh')
|
||||||
|
def refresh_mappings(node: sch.Schema('Memory')):
|
||||||
|
"""Refresh the list of memory regions for the process."""
|
||||||
|
with commands.open_tracked_tx('Refresh Memory Regions'):
|
||||||
|
commands.ghidra_trace_put_regions()
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='refresh')
|
||||||
|
def refresh_modules(node: sch.Schema('ModuleContainer')):
|
||||||
|
"""
|
||||||
|
Refresh the modules and sections list for the process.
|
||||||
|
|
||||||
|
This will refresh the sections for all modules, not just the selected one.
|
||||||
|
"""
|
||||||
|
with commands.open_tracked_tx('Refresh Modules'):
|
||||||
|
commands.ghidra_trace_put_modules()
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='activate')
|
||||||
|
def activate_process(process: sch.Schema('Process')):
|
||||||
|
"""Switch to the process."""
|
||||||
|
find_proc_by_obj(process)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='activate')
|
||||||
|
def activate_thread(thread: sch.Schema('Thread')):
|
||||||
|
"""Switch to the thread."""
|
||||||
|
find_thread_by_obj(thread)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='activate')
|
||||||
|
def activate_frame(frame: sch.Schema('StackFrame')):
|
||||||
|
"""Select the frame."""
|
||||||
|
find_frame_by_obj(frame)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='delete')
|
||||||
|
def remove_process(process: sch.Schema('Process')):
|
||||||
|
"""Remove the process."""
|
||||||
|
find_proc_by_obj(process)
|
||||||
|
dbg().detach()
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='connect')
|
||||||
|
def target(process: sch.Schema('Process'), spec: str):
|
||||||
|
"""Connect to a target machine or process."""
|
||||||
|
find_proc_by_obj(process)
|
||||||
|
dbg().attach(spec)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='attach')
|
||||||
|
def attach_obj(target: sch.Schema('Attachable')):
|
||||||
|
"""Attach the process to the given target."""
|
||||||
|
pid = find_availpid_by_obj(target)
|
||||||
|
dbg().attach(pid)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='attach')
|
||||||
|
def attach_pid(pid: int):
|
||||||
|
"""Attach the process to the given target."""
|
||||||
|
dbg().attach(pid)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='attach')
|
||||||
|
def attach_name(process: sch.Schema('Process'), name: str):
|
||||||
|
"""Attach the process to the given target."""
|
||||||
|
dbg().atach(name)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method
|
||||||
|
def detach(process: sch.Schema('Process')):
|
||||||
|
"""Detach the process's target."""
|
||||||
|
dbg().detach()
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='launch')
|
||||||
|
def launch_loader(
|
||||||
|
file: ParamDesc(str, display='File'),
|
||||||
|
args: ParamDesc(str, display='Arguments')=''):
|
||||||
|
"""
|
||||||
|
Start a native process with the given command line, stopping at the ntdll initial breakpoint.
|
||||||
|
"""
|
||||||
|
command = file
|
||||||
|
if args != None:
|
||||||
|
command += " "+args
|
||||||
|
commands.ghidra_trace_create(command=file, start_trace=False)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='launch')
|
||||||
|
def launch(
|
||||||
|
timeout: ParamDesc(int, display='Timeout'),
|
||||||
|
file: ParamDesc(str, display='File'),
|
||||||
|
args: ParamDesc(str, display='Arguments')=''):
|
||||||
|
"""
|
||||||
|
Run a native process with the given command line.
|
||||||
|
"""
|
||||||
|
command = file
|
||||||
|
if args != None:
|
||||||
|
command += " "+args
|
||||||
|
commands.ghidra_trace_create(
|
||||||
|
command, initial_break=False, timeout=timeout, start_trace=False)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method
|
||||||
|
def kill(process: sch.Schema('Process')):
|
||||||
|
"""Kill execution of the process."""
|
||||||
|
dbg().terminate()
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(name='continue', action='resume')
|
||||||
|
def _continue(process: sch.Schema('Process')):
|
||||||
|
"""Continue execution of the process."""
|
||||||
|
dbg().replay_forward(pyTTD.MAX_STEP, util.last)
|
||||||
|
hooks.on_stop()
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method
|
||||||
|
def interrupt(process: sch.Schema('Process')):
|
||||||
|
"""Interrupt the execution of the debugged program."""
|
||||||
|
print("'interrupt' is unsupported for TTD")
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='step_into')
|
||||||
|
def step_into(thread: sch.Schema('Thread'), n: ParamDesc(int, display='N')=1):
|
||||||
|
"""Step one instruction exactly."""
|
||||||
|
# find_thread_by_obj(thread)
|
||||||
|
dbg().replay_forward(n, util.last)
|
||||||
|
hooks.on_stop()
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='step_over')
|
||||||
|
def step_over(thread: sch.Schema('Thread'), n: ParamDesc(int, display='N')=1):
|
||||||
|
"""Step one instruction, but proceed through subroutine calls."""
|
||||||
|
# find_thread_by_obj(thread)
|
||||||
|
dbg().replay_backward(n, util.first)
|
||||||
|
hooks.on_stop()
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='step_out')
|
||||||
|
def step_out(thread: sch.Schema('Thread')):
|
||||||
|
"""Execute until the current stack frame returns."""
|
||||||
|
dbg().replay_backward(pyTTD.MAX_STEP, util.first)
|
||||||
|
hooks.on_stop()
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='step_to')
|
||||||
|
def step_to(thread: sch.Schema('Thread'), address: Address, max=None):
|
||||||
|
"""Continue execution up to the given address."""
|
||||||
|
find_thread_by_obj(thread)
|
||||||
|
return dbg().stepto(address.offset, max)
|
||||||
|
|
||||||
|
|
||||||
|
def gen_bpt(offset: int, size: int, flags: int):
|
||||||
|
bp = pyTTD.MemoryWatchpointData(addr=offset, size=size, flags=flags)
|
||||||
|
dbg().add_memory_watchpoint(bp)
|
||||||
|
bpt = util.Watchpoint(offset, size, flags, len(util.breakpoints), bp)
|
||||||
|
util.breakpoints.append(bpt)
|
||||||
|
hooks.on_breakpoint_created(bpt)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='break_sw_execute')
|
||||||
|
def break_address(process: sch.Schema('Process'), address: Address):
|
||||||
|
"""Set a breakpoint."""
|
||||||
|
gen_bpt(offset=address.offset, size=4, flags=pyTTD.BP_FLAGS.EXEC)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='break_sw_execute')
|
||||||
|
def break_expression(expression: str):
|
||||||
|
"""Set a breakpoint."""
|
||||||
|
# TODO: Escape?
|
||||||
|
dbg().bp(expr=expression)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='break_hw_execute')
|
||||||
|
def break_hw_address(process: sch.Schema('Process'), address: Address):
|
||||||
|
"""Set a hardware-assisted breakpoint."""
|
||||||
|
gen_bpt(offset=address.offset, size=4, flags=pyTTD.BP_FLAGS.EXEC)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='break_hw_execute')
|
||||||
|
def break_hw_expression(expression: str):
|
||||||
|
"""Set a hardware-assisted breakpoint."""
|
||||||
|
dbg().ba(expr=expression)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='break_read')
|
||||||
|
def break_read_range(process: sch.Schema('Process'), range: AddressRange):
|
||||||
|
"""Set a read watchpoint."""
|
||||||
|
gen_bpt(offset=range.min, size=range.length(), flags=pyTTD.BP_FLAGS.READ)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='break_read')
|
||||||
|
def break_read_expression(expression: str):
|
||||||
|
"""Set a read watchpoint."""
|
||||||
|
dbg().ba(expr=expression, access=DbgEng.DEBUG_BREAK_READ)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='break_write')
|
||||||
|
def break_write_range(process: sch.Schema('Process'), range: AddressRange):
|
||||||
|
"""Set a watchpoint."""
|
||||||
|
gen_bpt(offset=range.min, size=range.length(), flags=pyTTD.BP_FLAGS.WRITE)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='break_write')
|
||||||
|
def break_write_expression(expression: str):
|
||||||
|
"""Set a watchpoint."""
|
||||||
|
dbg().ba(expr=expression, access=DbgEng.DEBUG_BREAK_WRITE)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='break_access')
|
||||||
|
def break_access_range(process: sch.Schema('Process'), range: AddressRange):
|
||||||
|
"""Set an access watchpoint."""
|
||||||
|
find_proc_by_obj(process)
|
||||||
|
break_read_range(process, range)
|
||||||
|
break_write_range(process, range)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='break_access')
|
||||||
|
def break_access_expression(expression: str):
|
||||||
|
"""Set an access watchpoint."""
|
||||||
|
dbg().ba(expr=expression, access=DbgEng.DEBUG_BREAK_READ | DbgEng.DEBUG_BREAK_WRITE)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='toggle')
|
||||||
|
def toggle_breakpoint(breakpoint: sch.Schema('BreakpointSpec'), enabled: bool):
|
||||||
|
"""Toggle a breakpoint."""
|
||||||
|
bpt = find_bpt_by_obj(breakpoint)
|
||||||
|
if enabled:
|
||||||
|
dbg().be(bpt.GetId())
|
||||||
|
else:
|
||||||
|
dbg().bd(bpt.GetId())
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method(action='delete')
|
||||||
|
def delete_breakpoint(breakpoint: sch.Schema('BreakpointSpec')):
|
||||||
|
"""Delete a breakpoint."""
|
||||||
|
bpt = find_bpt_by_obj(breakpoint)
|
||||||
|
dbg().remove_memory_watchpoint(bpt.bp)
|
||||||
|
util.breakpoints.remove(bpt)
|
||||||
|
hooks.on_breakpoint_deleted(bpt)
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method
|
||||||
|
def read_mem(process: sch.Schema('Process'), range: AddressRange):
|
||||||
|
"""Read memory."""
|
||||||
|
nproc = find_proc_by_obj(process)
|
||||||
|
offset_start = process.trace.memory_mapper.map_back(
|
||||||
|
nproc, Address(range.space, range.min))
|
||||||
|
with commands.open_tracked_tx('Read Memory'):
|
||||||
|
dbg().read_mem(range.min, range.length())
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method
|
||||||
|
def write_mem(process: sch.Schema('Process'), address: Address, data: bytes):
|
||||||
|
"""Write memory."""
|
||||||
|
print("'write_mem' is unsupported for TTD")
|
||||||
|
|
||||||
|
|
||||||
|
@REGISTRY.method
|
||||||
|
def write_reg(frame: sch.Schema('StackFrame'), name: str, value: bytes):
|
||||||
|
"""Write a register."""
|
||||||
|
print("'write_reg' is unsupported for TTD")
|
||||||
|
|
||||||
|
|
||||||
|
def dbg():
|
||||||
|
return util.get_debugger()
|
|
@ -0,0 +1,434 @@
|
||||||
|
<context>
|
||||||
|
<schema name="Session" 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="FocusScope" />
|
||||||
|
<interface name="Aggregate" />
|
||||||
|
<element schema="VOID" />
|
||||||
|
<attribute name="Processes" schema="ProcessContainer" required="yes" fixed="yes" />
|
||||||
|
<attribute name="Available" schema="AvailableContainer" required="yes" fixed="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="_prompt" schema="STRING" required="yes" hidden="yes" />
|
||||||
|
<attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" hidden="yes" />
|
||||||
|
<attribute name="_event_thread" schema="OBJECT" hidden="yes" />
|
||||||
|
<attribute name="_focus" schema="Selectable" required="yes" hidden="yes" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="Selectable" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<element schema="OBJECT" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="BreakpointContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="BreakpointLocationContainer" />
|
||||||
|
<interface name="BreakpointSpecContainer" />
|
||||||
|
<element schema="BreakpointSpec" />
|
||||||
|
<attribute name="_supported_breakpoint_kinds" schema="SET_BREAKPOINT_KIND" required="yes" hidden="yes" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="AvailableContainer" canonical="yes" elementResync="ALWAYS" attributeResync="NEVER">
|
||||||
|
<interface name="Configurable" />
|
||||||
|
<element schema="Attachable" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute name="_base" schema="INT" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="ProcessContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="Configurable" />
|
||||||
|
<element schema="Process" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute name="_base" schema="INT" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="BreakpointSpec" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="BreakpointSpec" />
|
||||||
|
<interface name="BreakpointLocation" />
|
||||||
|
<interface name="Deletable" />
|
||||||
|
<interface name="Togglable" />
|
||||||
|
<element schema="VOID" />
|
||||||
|
<attribute name="_container" schema="BreakpointContainer" 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="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_spec" schema="BreakpointSpec" />
|
||||||
|
<attribute name="_range" schema="RANGE" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute name="_enabled" schema="BOOL" required="yes" hidden="yes" />
|
||||||
|
<attribute name="Commands" schema="STRING" />
|
||||||
|
<attribute name="Condition" schema="STRING" />
|
||||||
|
<attribute name="Hit Count" schema="INT" />
|
||||||
|
<attribute name="Ignore Count" schema="INT" />
|
||||||
|
<attribute name="Pending" schema="BOOL" />
|
||||||
|
<attribute name="Silent" schema="BOOL" />
|
||||||
|
<attribute name="Temporary" schema="BOOL" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="Attachable" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="Attachable" />
|
||||||
|
<element schema="VOID" />
|
||||||
|
<attribute name="_pid" schema="LONG" hidden="yes" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="Process" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="Process" />
|
||||||
|
<interface name="Aggregate" />
|
||||||
|
<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" />
|
||||||
|
<attribute name="Threads" schema="ThreadContainer" 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="Environment" schema="Environment" required="yes" fixed="yes" />
|
||||||
|
<attribute name="Memory" schema="Memory" required="yes" fixed="yes" />
|
||||||
|
<attribute name="Modules" schema="ModuleContainer" required="yes" fixed="yes" />
|
||||||
|
<attribute name="_pid" schema="LONG" hidden="yes" />
|
||||||
|
<attribute name="_state" schema="EXECUTION_STATE" required="yes" hidden="yes" />
|
||||||
|
<attribute name="_supported_attach_kinds" schema="SET_ATTACH_KIND" required="yes" hidden="yes" />
|
||||||
|
<attribute name="_parameters" schema="MAP_PARAMETERS" required="yes" hidden="yes" />
|
||||||
|
<attribute name="_supported_step_kinds" schema="SET_STEP_KIND" required="yes" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="Environment" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="Environment" />
|
||||||
|
<element schema="VOID" />
|
||||||
|
<attribute name="arch" schema="STRING" />
|
||||||
|
<attribute name="os" schema="STRING" />
|
||||||
|
<attribute name="endian" schema="STRING" />
|
||||||
|
<attribute name="_arch" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_debugger" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_os" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_endian" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="ModuleContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||||
|
<interface name="ModuleContainer" />
|
||||||
|
<element schema="Module" />
|
||||||
|
<attribute name="_supports_synthetic_modules" schema="BOOL" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="Memory" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="Memory" />
|
||||||
|
<element schema="MemoryRegion" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="BreakpointLocation" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="BreakpointLocation" />
|
||||||
|
<element schema="VOID" />
|
||||||
|
<attribute name="_range" schema="RANGE" hidden="yes" />
|
||||||
|
<attribute name="_spec" schema="BreakpointSpec" required="yes" hidden="yes" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="BreakpointLocationContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="BreakpointLocationContainer" />
|
||||||
|
<element schema="BreakpointLocation" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="ThreadContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="Configurable" />
|
||||||
|
<element schema="Thread" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute name="_base" schema="INT" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</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">
|
||||||
|
<interface name="Thread" />
|
||||||
|
<interface name="ExecutionStateful" />
|
||||||
|
<interface name="Steppable" />
|
||||||
|
<interface name="Aggregate" />
|
||||||
|
<element schema="VOID" />
|
||||||
|
<attribute name="Stack" schema="Stack" required="yes" fixed="yes" />
|
||||||
|
<attribute name="Registers" schema="RegisterValueContainer" required="yes" fixed="yes" />
|
||||||
|
<attribute name="_tid" schema="LONG" hidden="yes" />
|
||||||
|
<attribute name="_state" schema="EXECUTION_STATE" required="yes" hidden="yes" />
|
||||||
|
<attribute name="_supported_step_kinds" schema="SET_STEP_KIND" required="yes" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute name="Advance" schema="Method" required="yes" fixed="yes" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="Module" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="Module" />
|
||||||
|
<element schema="VOID" />
|
||||||
|
<attribute name="Sections" schema="SectionContainer" required="yes" fixed="yes" />
|
||||||
|
<attribute name="Symbols" schema="SymbolContainer" required="yes" fixed="yes" />
|
||||||
|
<attribute name="range" schema="RANGE" />
|
||||||
|
<attribute name="module name" schema="STRING" />
|
||||||
|
<attribute name="_module_name" schema="STRING" required="yes" hidden="yes" />
|
||||||
|
<attribute name="_range" schema="RANGE" required="yes" hidden="yes" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="MemoryRegion" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="MemoryRegion" />
|
||||||
|
<element schema="VOID" />
|
||||||
|
<attribute name="_offset" schema="LONG" required="yes" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_objfile" schema="STRING" required="yes" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_readable" schema="BOOL" required="yes" hidden="yes" />
|
||||||
|
<attribute name="_writable" schema="BOOL" required="yes" hidden="yes" />
|
||||||
|
<attribute name="_executable" schema="BOOL" required="yes" hidden="yes" />
|
||||||
|
<attribute name="_range" schema="RANGE" required="yes" hidden="yes" />
|
||||||
|
<attribute name="_memory" schema="Memory" required="yes" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="SectionContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="SectionContainer" />
|
||||||
|
<element schema="Section" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="Stack" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="Stack" />
|
||||||
|
<element schema="StackFrame" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="SymbolContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||||
|
<interface name="SymbolNamespace" />
|
||||||
|
<element schema="Symbol" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="Symbol" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="Symbol" />
|
||||||
|
<element schema="VOID" />
|
||||||
|
<attribute name="_size" schema="LONG" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_namespace" schema="SymbolContainer" required="yes" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_data_type" schema="DATA_TYPE" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_value" schema="ADDRESS" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute name="_bpt" schema="STRING" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="StackFrame" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="StackFrame" />
|
||||||
|
<interface name="Aggregate" />
|
||||||
|
<element schema="VOID" />
|
||||||
|
<attribute name="_function" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="Registers" schema="RegisterValueContainer" required="yes" fixed="yes" />
|
||||||
|
<attribute name="_pc" schema="ADDRESS" required="yes" hidden="yes" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="Section" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="Section" />
|
||||||
|
<element schema="VOID" />
|
||||||
|
<attribute name="range" schema="RANGE" />
|
||||||
|
<attribute name="_module" schema="Module" required="yes" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_range" schema="RANGE" required="yes" fixed="yes" />
|
||||||
|
<attribute name="_offset" schema="INT" required="no" fixed="yes" />
|
||||||
|
<attribute name="_objfile" schema="STRING" required="no" fixed="yes" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="RegisterValueContainer" canonical="yes" elementResync="ONCE" attributeResync="ONCE">
|
||||||
|
<interface name="RegisterContainer" />
|
||||||
|
<interface name="RegisterBank" />
|
||||||
|
<element schema="RegisterValue" />
|
||||||
|
<attribute name="General Purpose Registers" schema="RegisterBank" />
|
||||||
|
<attribute name="Floating Point Registers" schema="RegisterBank" />
|
||||||
|
<attribute name="Advanced Vector Extensions" schema="RegisterBank" />
|
||||||
|
<attribute name="Memory Protection Extensions" schema="RegisterBank" />
|
||||||
|
<attribute name="_descriptions" schema="RegisterValueContainer" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="RegisterBank" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||||
|
<interface name="RegisterBank" />
|
||||||
|
<element schema="RegisterValue" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
<schema name="RegisterValue" elementResync="NEVER" attributeResync="NEVER">
|
||||||
|
<interface name="Register" />
|
||||||
|
<element schema="VOID" />
|
||||||
|
<attribute name="_container" schema="OBJECT" required="yes" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_length" schema="INT" required="yes" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_value" schema="ANY" hidden="yes" />
|
||||||
|
<attribute name="_type" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_short_display" schema="STRING" hidden="yes" />
|
||||||
|
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
|
||||||
|
<attribute name="_order" schema="INT" hidden="yes" />
|
||||||
|
<attribute name="_modified" schema="BOOL" hidden="yes" />
|
||||||
|
<attribute schema="VOID" />
|
||||||
|
</schema>
|
||||||
|
</context>
|
|
@ -0,0 +1,204 @@
|
||||||
|
## ###
|
||||||
|
# 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.
|
||||||
|
##
|
||||||
|
from collections import namedtuple
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
from pyttd import pyTTD
|
||||||
|
|
||||||
|
#from pybag import pydbg
|
||||||
|
#from pybag.dbgeng import core as DbgEng
|
||||||
|
#from pybag.dbgeng import exception
|
||||||
|
#from pybag.dbgeng import util as DbgUtil
|
||||||
|
|
||||||
|
base = False
|
||||||
|
eng = False
|
||||||
|
first = False
|
||||||
|
last = False
|
||||||
|
breakpoints = []
|
||||||
|
events = {}
|
||||||
|
evttypes = {}
|
||||||
|
starts = {}
|
||||||
|
stops = {}
|
||||||
|
lastpos = False
|
||||||
|
DbgVersion = namedtuple('DbgVersion', ['full', 'major', 'minor'])
|
||||||
|
|
||||||
|
|
||||||
|
class Watchpoint(object):
|
||||||
|
def __init__(self, addr, size, flags, id, bp):
|
||||||
|
self.addr = addr
|
||||||
|
self.size = size
|
||||||
|
self.flags = flags
|
||||||
|
self.id = id
|
||||||
|
self.bp = bp
|
||||||
|
self.expr = None
|
||||||
|
|
||||||
|
|
||||||
|
def _compute_pydbg_ver():
|
||||||
|
blurb = "" # base._control.GetActualProcessorType()
|
||||||
|
full = ""
|
||||||
|
major = 0
|
||||||
|
minor = 0
|
||||||
|
return DbgVersion(full, int(major), int(minor))
|
||||||
|
|
||||||
|
|
||||||
|
DBG_VERSION = _compute_pydbg_ver()
|
||||||
|
|
||||||
|
|
||||||
|
def get_debugger():
|
||||||
|
return base
|
||||||
|
|
||||||
|
|
||||||
|
def get_target():
|
||||||
|
return 0 # get_debugger()._systems.GetCurrentSystemId()
|
||||||
|
|
||||||
|
|
||||||
|
def get_inst(addr):
|
||||||
|
dbg = get_debugger()
|
||||||
|
ins = DbgUtil.disassemble_instruction(
|
||||||
|
dbg.bitness(), addr, dbg.read_mem(addr, 15))
|
||||||
|
return str(ins)
|
||||||
|
|
||||||
|
|
||||||
|
def get_inst_sz(addr):
|
||||||
|
dbg = get_debugger()
|
||||||
|
ins = DbgUtil.disassemble_instruction(
|
||||||
|
dbg.bitness(), addr, dbg.read_mem(addr, 15))
|
||||||
|
return str(ins.size)
|
||||||
|
|
||||||
|
|
||||||
|
def get_breakpoints():
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def selected_process():
|
||||||
|
try:
|
||||||
|
return 0
|
||||||
|
# return current_process
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def selected_thread():
|
||||||
|
try:
|
||||||
|
dbg = get_debugger()
|
||||||
|
current = dbg.get_thread_info()
|
||||||
|
return current.threadid
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def selected_frame():
|
||||||
|
return 0 # selected_thread().GetSelectedFrame()
|
||||||
|
|
||||||
|
|
||||||
|
def select_process(id: int):
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def select_thread(id: int):
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def select_frame(id: int):
|
||||||
|
# TODO: this needs to be fixed
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def parse_and_eval(expr):
|
||||||
|
dbg = get_debugger()
|
||||||
|
if expr == "$pc":
|
||||||
|
return dbg.get_program_counter()
|
||||||
|
if expr == "$sp":
|
||||||
|
return dbg.get_context_x86_64().rsp
|
||||||
|
return int(expr)
|
||||||
|
|
||||||
|
|
||||||
|
def get_eval(expr, type=None):
|
||||||
|
ctrl = get_debugger()._control._ctrl
|
||||||
|
ctrl.SetExpressionSyntax(1)
|
||||||
|
value = DbgEng._DEBUG_VALUE()
|
||||||
|
index = c_ulong()
|
||||||
|
if type == None:
|
||||||
|
type = DbgEng.DEBUG_VALUE_INT64
|
||||||
|
hr = ctrl.Evaluate(Expression="{}".format(expr).encode(
|
||||||
|
), DesiredType=type, Value=byref(value), RemainderIndex=byref(index))
|
||||||
|
exception.check_err(hr)
|
||||||
|
if type == DbgEng.DEBUG_VALUE_INT8:
|
||||||
|
return value.u.I8
|
||||||
|
if type == DbgEng.DEBUG_VALUE_INT16:
|
||||||
|
return value.u.I16
|
||||||
|
if type == DbgEng.DEBUG_VALUE_INT32:
|
||||||
|
return value.u.I32
|
||||||
|
if type == DbgEng.DEBUG_VALUE_INT64:
|
||||||
|
return value.u.I64.I64
|
||||||
|
if type == DbgEng.DEBUG_VALUE_FLOAT32:
|
||||||
|
return value.u.F32
|
||||||
|
if type == DbgEng.DEBUG_VALUE_FLOAT64:
|
||||||
|
return value.u.F64
|
||||||
|
if type == DbgEng.DEBUG_VALUE_FLOAT80:
|
||||||
|
return value.u.F80Bytes
|
||||||
|
if type == DbgEng.DEBUG_VALUE_FLOAT82:
|
||||||
|
return value.u.F82Bytes
|
||||||
|
if type == DbgEng.DEBUG_VALUE_FLOAT128:
|
||||||
|
return value.u.F128Bytes
|
||||||
|
|
||||||
|
|
||||||
|
def process_list(running=False):
|
||||||
|
"""process_list() -> list of all processes"""
|
||||||
|
sysids = [0]
|
||||||
|
return sysids
|
||||||
|
|
||||||
|
|
||||||
|
def thread_list():
|
||||||
|
"""thread_list() -> list of all threads"""
|
||||||
|
dbg = get_debugger()
|
||||||
|
return dbg.get_thread_list()
|
||||||
|
|
||||||
|
|
||||||
|
def module_list():
|
||||||
|
"""thread_list() -> list of all threads"""
|
||||||
|
dbg = get_debugger()
|
||||||
|
return dbg.get_module_list()
|
||||||
|
|
||||||
|
|
||||||
|
conv_map = {}
|
||||||
|
|
||||||
|
|
||||||
|
def get_convenience_variable(id):
|
||||||
|
#val = get_target().GetEnvironment().Get(id)
|
||||||
|
if id not in conv_map:
|
||||||
|
return "auto"
|
||||||
|
val = conv_map[id]
|
||||||
|
if val is None:
|
||||||
|
return "auto"
|
||||||
|
return val
|
||||||
|
|
||||||
|
|
||||||
|
def set_convenience_variable(id, value):
|
||||||
|
#env = get_target().GetEnvironment()
|
||||||
|
# return env.Set(id, value, True)
|
||||||
|
conv_map[id] = value
|
||||||
|
|
||||||
|
|
||||||
|
def pos2snap(pos: int):
|
||||||
|
index = int(pos.major)
|
||||||
|
if index < 0 or index >= pyTTD.MAX_STEP:
|
||||||
|
return int(last.major)*1000
|
||||||
|
return index*1000+int(pos.minor)
|
|
@ -283,14 +283,19 @@ class Trace(object):
|
||||||
self._snap += 1
|
self._snap += 1
|
||||||
return self._snap
|
return self._snap
|
||||||
|
|
||||||
def snapshot(self, description, datetime=None):
|
def snapshot(self, description, datetime=None, snap=None):
|
||||||
"""
|
"""
|
||||||
Create a snapshot.
|
Create a snapshot.
|
||||||
|
|
||||||
Future state operations implicitly modify this new snapshot.
|
Future state operations implicitly modify this new snapshot.
|
||||||
|
The snap argument is optional. If ommitted, this creates a snapshot immediately
|
||||||
|
after the last created snapshot. If given, it creates the given snapshot.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if snap is None:
|
||||||
snap = self._next_snap()
|
snap = self._next_snap()
|
||||||
|
else:
|
||||||
|
self._snap = snap
|
||||||
self.client._snapshot(self.id, description, datetime, snap)
|
self.client._snapshot(self.id, description, datetime, snap)
|
||||||
return snap
|
return snap
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue