GP-4290: fix for selectProcess/Thread

GP-4290: fix for hard-coded path
GP-4290: simpler fixes post-review
GP-4290: partial fixes for slow start & termination logic
GP-4290: build logic for tlb
GP-4290: running dbgmodel locally
GP-4290: atttempting to isolate dbgmodel code
GP-4209: filling out unimplemented methods
GP-4290: options for dbgeng vs dbgmodel
GP-4290: aisle 9 for schema
GP-4290: Aggregate for Debug.Breakpoints & Stack.Frames
GP-4290: hidden attrs for schema
GP-4290: working in both modes
GP-4290: unified interface (use_generics)
GP-4290: basics working - mem, mods, dis, regs
GP-4290: somewhat working - model is populated
GP-4290: schema updates
GP-4290: fix for names
GP-4290: AddRef
GP-4290: switch to byref
GP-4290: start on dbgmodel interposing logic
GP-4290: added GetIntrinsicValue
GP-4290: moving along
GP-4290: first pass
This commit is contained in:
d-millar 2024-02-27 10:57:38 -05:00
parent f5008f9f99
commit 2c69ffb04a
19 changed files with 2385 additions and 44 deletions

View file

@ -21,6 +21,7 @@ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
apply from: "$rootProject.projectDir/gradle/debugger/hasNodepJar.gradle" apply from: "$rootProject.projectDir/gradle/debugger/hasNodepJar.gradle"
apply from: "$rootProject.projectDir/gradle/debugger/hasPythonPackage.gradle" apply from: "$rootProject.projectDir/gradle/debugger/hasPythonPackage.gradle"
apply from: "buildNatives.gradle"
apply plugin: 'eclipse' apply plugin: 'eclipse'
eclipse.project.name = 'Debug Debugger-agent-dbgeng' eclipse.project.name = 'Debug Debugger-agent-dbgeng'
@ -36,6 +37,14 @@ dependencies {
testImplementation project(path: ":Debugger-gadp", configuration: 'testArtifacts') testImplementation project(path: ":Debugger-gadp", configuration: 'testArtifacts')
} }
// Include buildable native source in distribution
rootProject.assembleDistribution {
from (this.project.projectDir.toString()) {
include "src/**"
into { getZipPath(this.project) }
}
}
tasks.nodepJar { tasks.nodepJar {
manifest { manifest {
attributes['Main-Class'] = 'agent.dbgeng.gadp.DbgEngGadpServer' attributes['Main-Class'] = 'agent.dbgeng.gadp.DbgEngGadpServer'

View file

@ -0,0 +1,49 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
if ("win_x86_64".equals(getCurrentPlatformName())) {
String makeName = "win_x86_64TlbMake"
task(type: Exec, makeName) {
def projectPath = projectDir.toString()
def solutionBatchFilePath = projectPath + "/build/buildSolution.bat"
def projectPathWindows = projectPath.replace("/", File.separator)
doFirst {
file("build/os/win_x86_64").mkdirs()
def srcdir = "src/main/py/src/dbgmodel"
def msbuildCmd = "midl /tlb build/os/win_x86_64/dbgmodel.tlb ${srcdir}/DbgModel.idl"
println "Executing: " + msbuildCmd
new File(solutionBatchFilePath).withWriter { out ->
out.println "call " + VISUAL_STUDIO_VCVARS_CMD
out.println msbuildCmd
}
}
doLast {
assert file("build/os/win_x86_64/dbgmodel.tlb").exists() : "Failed to build dbgmodel.tlb"
}
executable "cmd"
args "/c"
args solutionBatchFilePath.replace("/", File.separator)
}
}

View file

@ -5,4 +5,5 @@ data/debugger-launchers/local-dbgeng.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/dbgmodel/DbgModel.idl||GHIDRA||||END|
src/main/py/src/ghidradbg/schema.xml||GHIDRA||||END| src/main/py/src/ghidradbg/schema.xml||GHIDRA||||END|

View file

@ -14,6 +14,8 @@
:: Use env instead of args, because "all args except first" is terrible to implement in batch :: Use env instead of args, because "all args except first" is terrible to implement in batch
::@env OPT_TARGET_IMG:str="" "Image" "The target binary executable image" ::@env OPT_TARGET_IMG:str="" "Image" "The target binary executable image"
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target" ::@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" "Path to dbgeng and associated DLLS (if not Windows Kits)."
@echo off @echo off

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,96 @@
## ###
# 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 ctypes import *
from comtypes.hresult import S_OK, S_FALSE
from comtypes.gen import DbgMod
from pybag.dbgeng import exception
import dbgmodel.imodelobject as mo
class DataModelManager(object):
def __init__(self, mgr):
self._mgr = mgr
exception.wrap_comclass(self._mgr)
def Release(self):
cnt = self._mgr.Release()
if cnt == 0:
self._mgr = None
return cnt
# DataModelManager
def GetRootNamespace(self):
root = POINTER(DbgMod.IModelObject)()
hr = self._mgr.GetRootNamespace(byref(root))
exception.check_err(hr)
return mo.ModelObject(root)
def AcquireNamedModel(self, modelName, modelObject):
raise exception.E_NOTIMPL_Error
def Close(self):
raise exception.E_NOTIMPL_Error
def CreateNoValue(self, object):
raise exception.E_NOTIMPL_Error
def CreateErrorObject(self, error, message, object):
raise exception.E_NOTIMPL_Error
def CreateTypedObject(self, context, objectLocation, objectType, object):
raise exception.E_NOTIMPL_Error
def CreateTypedObjectByReference(self, context, objectLocation, objectType, object):
raise exception.E_NOTIMPL_Error
def CreateSyntheticObject(self, context, object):
raise exception.E_NOTIMPL_Error
def CreateDataModelObject(self, dataModel, object):
raise exception.E_NOTIMPL_Error
def CreateTypedIntrinsicObject(self, intrinsicData, type, object):
raise exception.E_NOTIMPL_Error
def CreateIntrinsicObject(self, objectKind, intrinsicData, object):
raise exception.E_NOTIMPL_Error
def GetModelForTypeSignature(self, typeSignature, dataModel):
raise exception.E_NOTIMPL_Error
def GetModelForType(self, type, dataModel, typeSignature, wildcardMatches):
raise exception.E_NOTIMPL_Error
def RegisterExtensionForTypeSignature(self, typeSignature, dataModel):
raise exception.E_NOTIMPL_Error
def RegisterModelForTypeSignature(self, typeSignature, dataModel):
raise exception.E_NOTIMPL_Error
def RegisterNamedModel(self, modelName, modelObject):
raise exception.E_NOTIMPL_Error
def UnregisterExtensionForTypeSignature(self, dataModel, typeSignature):
raise exception.E_NOTIMPL_Error
def UnregisterModelForTypeSignature(self, dataModel, typeSignature):
raise exception.E_NOTIMPL_Error
def UnregisterNamedModel(self, modelName):
raise exception.E_NOTIMPL_Error

View file

@ -0,0 +1,48 @@
## ###
# 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 ctypes import *
from comtypes.hresult import S_OK, S_FALSE
from comtypes.gen import DbgMod
from pybag.dbgeng import exception
from pybag.dbgeng import win32
class DebugHost(object):
def __init__(self, host):
self._host = host
exception.wrap_comclass(self._host)
def Release(self):
cnt = self._host.Release()
if cnt == 0:
self._host = None
return cnt
# DebugHost
def GetCurrentContext(self, context):
raise exception.E_NOTIMPL_Error
def GetDefaultMetadata(self, metadata):
raise exception.E_NOTIMPL_Error
def GetHostDefinedInterface(self, hostUnk):
raise exception.E_NOTIMPL_Error

View file

@ -0,0 +1,46 @@
## ###
# 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 ctypes import *
from comtypes.hresult import S_OK, S_FALSE
from comtypes.gen import DbgMod
from pybag.dbgeng import exception
from .idatamodelmanager import DataModelManager
from .idebughost import DebugHost
class HostDataModelAccess(object):
def __init__(self, hdma):
self._hdma = hdma
exception.wrap_comclass(self._hdma)
def Release(self):
cnt = self._hdma.Release()
if cnt == 0:
self._hdma = None
return cnt
# HostDataModelAccess
def GetDataModel(self):
manager = POINTER(DbgMod.IDataModelManager)()
host = POINTER(DbgMod.IDebugHost)()
hr = self._hdma.GetDataModel(byref(manager), byref(host))
exception.check_err(hr)
return (DataModelManager(manager), DebugHost(host))

View file

@ -0,0 +1,44 @@
## ###
# IP: GHIDRA
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##
from ctypes import *
from comtypes import COMError
from comtypes.hresult import S_OK, S_FALSE
from comtypes.gen import DbgMod
from pybag.dbgeng import exception
from .imodeliterator import ModelIterator
class IterableConcept(object):
def __init__(self, concept):
self._concept = concept
concept.AddRef()
# IterableConcept
def GetDefaultIndexDimensionality(self, context, dimensionality):
raise exception.E_NOTIMPL_Error
def GetIterator(self, context):
iterator = POINTER(DbgMod.IModelIterator)()
try:
self._concept.GetIterator(context._obj, byref(iterator))
except COMError as ce:
return None
return ModelIterator(iterator)

View file

@ -0,0 +1,51 @@
## ###
# 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 ctypes import *
from comtypes import BSTR
from comtypes.hresult import S_OK, S_FALSE
from comtypes.gen import DbgMod
from pybag.dbgeng import exception
import dbgmodel.imodelobject as mo
class KeyEnumerator(object):
def __init__(self, keys):
self._keys = keys
exception.wrap_comclass(self._keys)
def Release(self):
cnt = self._keys.Release()
if cnt == 0:
self._keys = None
return cnt
# KeyEnumerator
def GetNext(self):
key = BSTR()
value = POINTER(DbgMod.IModelObject)()
store = POINTER(DbgMod.IKeyStore)()
hr = self._keys.GetNext(byref(key), byref(value), byref(store))
if hr != S_OK:
return (None, None)
return (key, mo.ModelObject(value))
def Reset(self):
hr = self._keys.Reset()
exception.check_err(hr)

View file

@ -0,0 +1,48 @@
## ###
# 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 ctypes import *
from comtypes import COMError
from comtypes.hresult import S_OK, S_FALSE
from comtypes.gen import DbgMod
from pybag.dbgeng import exception
import dbgmodel.imodelobject as mo
class ModelIterator(object):
def __init__(self, iter):
self._iter = iter
iter.AddRef()
# ModelIterator
def GetNext(self, dimensions):
object = POINTER(DbgMod.IModelObject)()
indexer = POINTER(DbgMod.IModelObject)()
metadata = POINTER(DbgMod.IKeyStore)()
try:
self._iter.GetNext(byref(object), dimensions, byref(indexer), byref(metadata))
except COMError as ce:
return None
index = mo.ModelObject(indexer)
id = index.GetIntrinsicValue().value
return (id, mo.ModelObject(object))
def Reset(self):
hr = self._keys.Reset()
exception.check_err(hr)

View file

@ -0,0 +1,273 @@
## ###
# 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 ctypes import *
from comtypes import IUnknown, COMError
from comtypes.automation import IID, VARIANT
from comtypes.hresult import S_OK, S_FALSE
from comtypes.gen.DbgMod import *
from enum import Enum
from comtypes.gen import DbgMod
from pybag.dbgeng import exception
from .ikeyenumerator import KeyEnumerator
from .iiterableconcept import IterableConcept
class ModelObjectKind(Enum):
PROPERTY_ACCESSOR = 0
CONTEXT = 1
TARGET_OBJECT = 2
TARGET_OBJECT_REFERENCE = 3
SYNTHETIC = 4
NO_VALUE = 5
ERROR = 6
INTRINSIC = 7
METHOD = 8
KEY_REFERENCE = 9
class ModelObject(object):
def __init__(self, obj):
self._obj = obj
self.concept = None
exception.wrap_comclass(self._obj)
def Release(self):
print("RELEASE ModelObject")
breakpoint()
cnt = self._obj.Release()
if cnt == 0:
self._obj = None
return cnt
# ModelObject
def AddParentModel(self, model, contextObject, override):
raise exception.E_NOTIMPL_Error
def ClearConcepts(self):
raise exception.E_NOTIMPL_Error
def ClearKeys(self):
raise exception.E_NOTIMPL_Error
def Compare(self, other, equal):
raise exception.E_NOTIMPL_Error
def Dereference(self, object):
raise exception.E_NOTIMPL_Error
def EnumerateKeyReferences(self):
raise exception.E_NOTIMPL_Error
def EnumerateKeys(self):
keys = POINTER(DbgMod.IKeyEnumerator)()
hr = self._obj.EnumerateKeys(byref(keys))
if hr != S_OK:
return None
return KeyEnumerator(keys)
def EnumerateKeyValues(self):
raise exception.E_NOTIMPL_Error
def EnumerateRawReferences(self, kind, searchFlags):
raise exception.E_NOTIMPL_Error
def EnumerateRawValues(self, kind, searchFlag):
keys = POINTER(DbgMod.IRawEnumerator)()
hr = self._obj.EnumerateRawValues(kind, searchFlag, byref(keys))
if hr != S_OK:
return None
return RawEnumerator(keys, kind)
def GetConcept(self, ref):
ifc = POINTER(IUnknown)()
metadata = POINTER(DbgMod.IKeyStore)()
hr = self._obj.GetConcept(ref._iid_, byref(ifc), byref(metadata))
if hr != S_OK:
return None
return cast(ifc, POINTER(ref))
def GetContext(self, context):
raise exception.E_NOTIMPL_Error
def GetContextForDataModel(self, dataModelObject, context):
raise exception.E_NOTIMPL_Error
def GetIntrinsicValue(self):
var = VARIANT()
hr = self._obj.GetIntrinsicValue(var)
if hr != S_OK:
return None
return var
def GetIntrinsicValueAs(self, vt):
raise exception.E_NOTIMPL_Error
def GetKey(self, key, object, metadata):
raise exception.E_NOTIMPL_Error
def GetKeyReference(self, key, objectReference, metadata):
raise exception.E_NOTIMPL_Error
def GetKeyValue(self, key):
kbuf = cast(c_wchar_p(key),POINTER(c_ushort))
value = POINTER(DbgMod.IModelObject)()
store = POINTER(DbgMod.IKeyStore)()
hr = self._obj.GetKeyValue(kbuf, byref(value), byref(store))
if hr != S_OK:
return None
return ModelObject(value)
def GetKind(self):
kind = c_long()
hr = self._obj.GetKind(kind)
exception.check_err(hr)
return kind
def GetLocation(self, location):
raise exception.E_NOTIMPL_Error
def GetNumberOfParentModels(self, numModels):
raise exception.E_NOTIMPL_Error
def GetParentModel(self, i, model, context):
raise exception.E_NOTIMPL_Error
def GetRawReference(self, kind, name, searchFlags, object):
raise exception.E_NOTIMPL_Error
def GetRawValue(self, kind, name, searchFlags, object):
raise exception.E_NOTIMPL_Error
def GetTargetInfo(self):
location = POINTER(DbgMod._Location)()
type = POINTER(DbgMod.IDebugHostType)()
hr = self._obj.GetTargetInfo(location, byref(type))
exception.check_err(hr)
return type
def GetTypeInfo(self, type):
raise exception.E_NOTIMPL_Error
def IsEqualTo(self, other, equal):
raise exception.E_NOTIMPL_Error
def RemoveParentModel(self, model):
raise exception.E_NOTIMPL_Error
def SetConcept(self, ref, interface, metadata):
raise exception.E_NOTIMPL_Error
def SetContextForDataModel(self, modelObject, context):
raise exception.E_NOTIMPL_Error
def SetKey(self, key, object, metadata):
raise exception.E_NOTIMPL_Error
def SetKeyValue(self, key, object):
raise exception.E_NOTIMPL_Error
def TryCastToRuntimeType(self, runtimeTypedObject):
raise exception.E_NOTIMPL_Error
# Auxiliary
def GetKeyValueMap(self):
map = {}
keys = self.EnumerateKeys()
(k,v) = keys.GetNext()
while k is not None:
map[k.value] = self.GetKeyValue(k.value)
(k,v) = keys.GetNext()
return map
def GetRawValueMap(self):
map = {}
kind = self.GetKind()
keys = self.EnumerateRawValues(kind, c_long(0))
(k,v) = keys.GetNext()
while k is not None:
map[k.value] = v
(k,v) = keys.GetNext()
return map
def GetAttributes(self):
map = {}
kind = self.GetKind()
if kind == ModelObjectKind.ERROR:
return map
if kind == ModelObjectKind.INTRINSIC or \
kind == ModelObjectKind.TARGET_OBJECT or \
kind == ModelObjectKind.TARGET_OBJECT_REFERENCE:
return self.GetRawValueMap()
return self.GetKeyValueMap()
def GetElements(self):
list = []
if self.concept is None:
iconcept = self.GetConcept(DbgMod.IIterableConcept)
if iconcept is None:
return list
self.concept = IterableConcept(iconcept)
iter = self.concept.GetIterator(self)
if iter is None:
print("WARNING: iter is None")
return list
next = iter.GetNext(1)
while next is not None:
list.append(next)
next = iter.GetNext(1)
return list
def GetElement(self, key):
list = self.GetElements()
for k, v in list:
if k == key:
return v
return None
def GetOffspring(self, path):
next = self
for element in path:
if element.startswith("["):
idx = element[1:len(element)-1]
if "x" not in idx:
idx = int(idx)
else:
idx = int(idx,16)
next = next.GetElement(idx)
else:
next = next.GetKeyValue(element)
if next is None:
print(f"{element} not found")
return next
def GetValue(self):
value = self.GetIntrinsicValue()
if value is None:
return None
if value.vt == 0xd:
return None
return value.value
def GetTypeKind(self):
kind = self.GetKind()
if kind == ModelObjectKind.TARGET_OBJECT or \
kind == ModelObjectKind.INTRINSIC:
return self.GetTargetInfo()
return None

View file

@ -0,0 +1,51 @@
## ###
# 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 ctypes import *
from comtypes import BSTR
from comtypes.hresult import S_OK, S_FALSE
from comtypes.gen import DbgMod
from pybag.dbgeng import exception
import dbgmodel.imodelobject as mo
class RawEnumerator(object):
def __init__(self, keys, kind):
self._keys = keys
self._kind = kind
exception.wrap_comclass(self._keys)
def Release(self):
cnt = self._keys.Release()
if cnt == 0:
self._keys = None
return cnt
# KeyEnumerator
def GetNext(self):
key = BSTR()
value = POINTER(DbgMod.IModelObject)()
hr = self._keys.GetNext(byref(key), byref(self._kind), byref(value))
if hr != S_OK:
return (None, None)
return (key, mo.ModelObject(value))
def Reset(self):
hr = self._keys.Reset()
exception.check_err(hr)

View file

@ -14,7 +14,44 @@
# limitations under the License. # limitations under the License.
## ##
from . import util, commands, methods, hooks from . import util, commands, methods, hooks
from dbgmodel.ihostdatamodelaccess import HostDataModelAccess
import ctypes import ctypes
import platform
import os
ctypes.windll.kernel32.SetErrorMode(0x0001 | 0x0002 | 0x8000) 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 os.path.exists(_dir):
dbgdir = _dir
break
if not dbgdir:
raise RuntimeError("Windbg install directory not found!")
# preload these to get correct DLLs loaded
try:
ctypes.windll.LoadLibrary(os.path.join(dbgdir, 'dbghelp.dll'))
except Exception as exc:
print(f"LoadLibrary failed: {dbgdir}\dbghelp.dll {exc}")
pass
try:
ctypes.windll.LoadLibrary(os.path.join(dbgdir, 'dbgeng.dll'))
except Exception as exc:
print(f"LoadLibrary failed: {dbgdir}\dbgeng.dll {exc}")
pass
try:
ctypes.windll.LoadLibrary(os.path.join(dbgdir, 'DbgModel.dll'))
except Exception as exc:
print(f"LoadLibrary failed: {dbgdir}\dbgmodel.dll {exc}")
pass

View file

@ -25,6 +25,7 @@ import time
from pybag import pydbg, userdbg, kerneldbg from pybag import pydbg, userdbg, kerneldbg
from pybag.dbgeng import core as DbgEng from pybag.dbgeng import core as DbgEng
from pybag.dbgeng import exception from pybag.dbgeng import exception
from dbgmodel.imodelobject import ModelObjectKind
from ghidratrace import sch from ghidratrace import sch
from ghidratrace.client import Client, Address, AddressRange, TraceObject from ghidratrace.client import Client, Address, AddressRange, TraceObject
@ -37,20 +38,21 @@ PAGE_SIZE = 4096
AVAILABLES_PATH = 'Available' AVAILABLES_PATH = 'Available'
AVAILABLE_KEY_PATTERN = '[{pid}]' AVAILABLE_KEY_PATTERN = '[{pid}]'
AVAILABLE_PATTERN = AVAILABLES_PATH + AVAILABLE_KEY_PATTERN AVAILABLE_PATTERN = AVAILABLES_PATH + AVAILABLE_KEY_PATTERN
PROCESSES_PATH = 'Processes' PROCESSES_PATH = 'Sessions[0].Processes'
PROCESS_KEY_PATTERN = '[{procnum}]' PROCESS_KEY_PATTERN = '[{procnum}]'
PROCESS_PATTERN = PROCESSES_PATH + PROCESS_KEY_PATTERN PROCESS_PATTERN = PROCESSES_PATH + PROCESS_KEY_PATTERN
PROC_BREAKS_PATTERN = PROCESS_PATTERN + '.Breakpoints' PROC_BREAKS_PATTERN = PROCESS_PATTERN + '.Debug.Breakpoints'
PROC_BREAK_KEY_PATTERN = '[{breaknum}]' PROC_BREAK_KEY_PATTERN = '[{breaknum}]'
PROC_BREAK_PATTERN = PROC_BREAKS_PATTERN + PROC_BREAK_KEY_PATTERN PROC_BREAK_PATTERN = PROC_BREAKS_PATTERN + PROC_BREAK_KEY_PATTERN
ENV_PATTERN = PROCESS_PATTERN + '.Environment' ENV_PATTERN = PROCESS_PATTERN + '.Environment'
THREADS_PATTERN = PROCESS_PATTERN + '.Threads' THREADS_PATTERN = PROCESS_PATTERN + '.Threads'
THREAD_KEY_PATTERN = '[{tnum}]' THREAD_KEY_PATTERN = '[{tnum}]'
THREAD_PATTERN = THREADS_PATTERN + THREAD_KEY_PATTERN THREAD_PATTERN = THREADS_PATTERN + THREAD_KEY_PATTERN
STACK_PATTERN = THREAD_PATTERN + '.Stack' STACK_PATTERN = THREAD_PATTERN + '.Stack.Frames'
FRAME_KEY_PATTERN = '[{level}]' FRAME_KEY_PATTERN = '[{level}]'
FRAME_PATTERN = STACK_PATTERN + FRAME_KEY_PATTERN FRAME_PATTERN = STACK_PATTERN + FRAME_KEY_PATTERN
REGS_PATTERN = THREAD_PATTERN + '.Registers' REGS_PATTERN = THREAD_PATTERN + '.Registers'
USER_REGS_PATTERN = THREAD_PATTERN + '.Registers.User'
MEMORY_PATTERN = PROCESS_PATTERN + '.Memory' MEMORY_PATTERN = PROCESS_PATTERN + '.Memory'
REGION_KEY_PATTERN = '[{start:08x}]' REGION_KEY_PATTERN = '[{start:08x}]'
REGION_PATTERN = MEMORY_PATTERN + REGION_KEY_PATTERN REGION_PATTERN = MEMORY_PATTERN + REGION_KEY_PATTERN
@ -60,6 +62,7 @@ MODULE_PATTERN = MODULES_PATTERN + MODULE_KEY_PATTERN
SECTIONS_ADD_PATTERN = '.Sections' SECTIONS_ADD_PATTERN = '.Sections'
SECTION_KEY_PATTERN = '[{secname}]' SECTION_KEY_PATTERN = '[{secname}]'
SECTION_ADD_PATTERN = SECTIONS_ADD_PATTERN + SECTION_KEY_PATTERN SECTION_ADD_PATTERN = SECTIONS_ADD_PATTERN + SECTION_KEY_PATTERN
GENERIC_KEY_PATTERN = '[{key}]'
# TODO: Symbols # TODO: Symbols
@ -209,7 +212,7 @@ def start_trace(name):
with open(schema_fn, 'r') as schema_file: with open(schema_fn, 'r') as schema_file:
schema_xml = schema_file.read() schema_xml = schema_file.read()
with STATE.trace.open_tx("Create Root Object"): with STATE.trace.open_tx("Create Root Object"):
root = STATE.trace.create_root_object(schema_xml, 'Session') root = STATE.trace.create_root_object(schema_xml, 'Root')
root.set_value('_display', util.DBG_VERSION.full + ' via pybag') root.set_value('_display', util.DBG_VERSION.full + ' via pybag')
util.set_convenience_variable('_ghidra_tracing', "true") util.set_convenience_variable('_ghidra_tracing', "true")
@ -481,6 +484,18 @@ def ghidra_trace_delmem(address, length):
@util.dbg.eng_thread @util.dbg.eng_thread
def putreg(): def putreg():
if util.dbg.use_generics:
nproc = util.selected_process()
if nproc < 0:
return
nthrd = util.selected_thread()
rpath = REGS_PATTERN.format(procnum=nproc, tnum=nthrd)
create_generic(rpath)
STATE.trace.create_overlay_space('register', rpath)
path = USER_REGS_PATTERN.format(procnum=nproc, tnum=nthrd)
(values, keys) = create_generic(path)
return {'missing': STATE.trace.put_registers(rpath, values)}
nproc = util.selected_process() nproc = util.selected_process()
if nproc < 0: if nproc < 0:
return return
@ -834,6 +849,17 @@ def compute_proc_state(nproc=None):
def put_processes(running=False): def put_processes(running=False):
# | always displays PID in hex # | always displays PID in hex
# TODO: I'm not sure about the engine id # TODO: I'm not sure about the engine id
# NB: This speeds things up, but desirable?
if running:
return
if util.dbg.use_generics and not running:
ppath = PROCESSES_PATH
(values, keys) = create_generic(ppath)
STATE.trace.proxy_object_path(PROCESSES_PATH).retain_values(keys)
return
keys = [] keys = []
# Set running=True to avoid process changes, even while stopped # Set running=True to avoid process changes, even while stopped
for i, p in enumerate(util.process_list(running=True)): for i, p in enumerate(util.process_list(running=True)):
@ -979,8 +1005,18 @@ def put_single_breakpoint(bp, ibobj, nproc, ikeys):
@util.dbg.eng_thread @util.dbg.eng_thread
def put_breakpoints(): def put_breakpoints():
target = util.get_target()
nproc = util.selected_process() nproc = util.selected_process()
# NB: Am leaving this code here in case we change our minds, but the cost
# of using put_generic here outweighs the advantage of uniformity
#
# if util.dbg.use_generics:
# path = PROC_BREAKS_PATTERN.format(procnum=nproc)
# (values, keys) = create_generic(path)
# STATE.trace.proxy_object_path(path).retain_values(keys)
# return
target = util.get_target()
ibpath = PROC_BREAKS_PATTERN.format(procnum=nproc) ibpath = PROC_BREAKS_PATTERN.format(procnum=nproc)
ibobj = STATE.trace.create_object(ibpath) ibobj = STATE.trace.create_object(ibpath)
keys = [] keys = []
@ -1010,7 +1046,8 @@ def ghidra_trace_put_breakpoints():
def put_environment(): def put_environment():
epath = ENV_PATTERN.format(procnum=util.selected_process()) nproc = util.selected_process()
epath = ENV_PATTERN.format(procnum=nproc)
envobj = STATE.trace.create_object(epath) envobj = STATE.trace.create_object(epath)
envobj.set_value('_debugger', 'pydbg') envobj.set_value('_debugger', 'pydbg')
envobj.set_value('_arch', arch.get_arch()) envobj.set_value('_arch', arch.get_arch())
@ -1036,8 +1073,7 @@ def put_regions():
regions = util.dbg._base.memory_list() regions = util.dbg._base.memory_list()
except Exception: except Exception:
regions = [] regions = []
if len(regions) == 0 and util.selected_thread() != None:
regions = [util.REGION_INFO_READER.full_mem()]
mapper = STATE.trace.memory_mapper mapper = STATE.trace.memory_mapper
keys = [] keys = []
# r : MEMORY_BASIC_INFORMATION64 # r : MEMORY_BASIC_INFORMATION64
@ -1045,9 +1081,7 @@ def put_regions():
rpath = REGION_PATTERN.format(procnum=nproc, start=r.BaseAddress) rpath = REGION_PATTERN.format(procnum=nproc, start=r.BaseAddress)
keys.append(REGION_KEY_PATTERN.format(start=r.BaseAddress)) keys.append(REGION_KEY_PATTERN.format(start=r.BaseAddress))
regobj = STATE.trace.create_object(rpath) regobj = STATE.trace.create_object(rpath)
start_base, start_addr = mapper.map(nproc, r.BaseAddress) (start_base, start_addr) = map_address(r.BaseAddress)
if start_base != start_addr.space:
STATE.trace.create_overlay_space(start_base, start_addr.space)
regobj.set_value('_range', start_addr.extend(r.RegionSize)) regobj.set_value('_range', start_addr.extend(r.RegionSize))
regobj.set_value('_readable', r.Protect == regobj.set_value('_readable', r.Protect ==
None or r.Protect & 0x66 != 0) None or r.Protect & 0x66 != 0)
@ -1078,8 +1112,15 @@ def ghidra_trace_put_regions():
@util.dbg.eng_thread @util.dbg.eng_thread
def put_modules(): def put_modules():
target = util.get_target()
nproc = util.selected_process() nproc = util.selected_process()
if util.dbg.use_generics:
mpath = MODULES_PATTERN.format(procnum=nproc)
(values, keys) = create_generic(mpath)
STATE.trace.proxy_object_path(
MODULES_PATTERN.format(procnum=nproc)).retain_values(keys)
return
target = util.get_target()
modules = util.dbg._base.module_list() modules = util.dbg._base.module_list()
mapper = STATE.trace.memory_mapper mapper = STATE.trace.memory_mapper
mod_keys = [] mod_keys = []
@ -1141,9 +1182,21 @@ def compute_thread_display(i, pid, tid, t):
def put_threads(running=False): def put_threads(running=False):
# ~ always displays PID:TID in hex # ~ always displays PID:TID in hex
# TODO: I'm not sure about the engine id # TODO: I'm not sure about the engine id
# NB: This speeds things up, but desirable?
if running:
return
nproc = util.selected_process() nproc = util.selected_process()
if nproc is None: if nproc is None:
return return
if util.dbg.use_generics and not running:
tpath = THREADS_PATTERN.format(procnum=nproc)
(values, keys) = create_generic(tpath)
STATE.trace.proxy_object_path(
THREADS_PATTERN.format(procnum=nproc)).retain_values(keys)
return
pid = util.dbg.pid pid = util.dbg.pid
keys = [] keys = []
@ -1192,10 +1245,19 @@ def ghidra_trace_put_threads():
@util.dbg.eng_thread @util.dbg.eng_thread
def put_frames(): def put_frames():
nproc = util.selected_process() nproc = util.selected_process()
mapper = STATE.trace.memory_mapper if nproc < 0:
return
nthrd = util.selected_thread() nthrd = util.selected_thread()
if nthrd is None: if nthrd is None:
return return
if util.dbg.use_generics:
path = STACK_PATTERN.format(procnum=nproc, tnum=nthrd)
(values, keys) = create_generic(path)
STATE.trace.proxy_object_path(path).retain_values(keys)
return
mapper = STATE.trace.memory_mapper
keys = [] keys = []
# f : _DEBUG_STACK_FRAME # f : _DEBUG_STACK_FRAME
for f in util.dbg._base.backtrace_list(): for f in util.dbg._base.backtrace_list():
@ -1228,6 +1290,134 @@ def ghidra_trace_put_frames():
put_frames() put_frames()
def update_by_container(np, index, obj):
if np.endswith("Processes") or np.endswith("Threads"):
istate = compute_proc_state(index)
obj.set_value('_state', istate)
if np.endswith("Processes"):
create_generic(obj.path)
id = util.get_proc_id(index)
obj.set_value('_pid', index)
obj.set_value('_display', '{:x} {:x}'.format(id, index))
if np.endswith("Breakpoints"):
create_generic(obj.path)
#id = util.get_thread_id(index)
#obj.set_value('_tid', index)
#obj.set_value('_display','{:x} {:x}'.format(id, index))
if np.endswith("Threads"):
create_generic(obj.path)
id = util.get_thread_id(index)
obj.set_value('_tid', index)
obj.set_value('_display', '{:x} {:x}'.format(id, index))
if np.endswith("Frames"):
mo = util.get_object(obj.path)
map = util.get_attributes(mo)
attr = map["Attributes"]
if attr is None:
return
create_generic(obj.path+".Attributes")
map = util.get_attributes(attr)
pc = util.get_value(map["InstructionOffset"])
(pc_base, pc_addr) = map_address(pc)
obj.set_value('_pc', pc_addr)
obj.set_value('_display', '#{:x} 0x{:x}'.format(index, pc))
if np.endswith("Modules"):
create_generic(obj.path)
mo = util.get_object(obj.path)
map = util.get_attributes(mo)
base = util.get_value(map["BaseAddress"])
size = util.get_value(map["Size"])
name = util.get_value(map["Name"])
obj.set_value('_module_name', '{}'.format(name))
(base_base, base_addr) = map_address(base)
obj.set_value('_range', base_addr.extend(size))
obj.set_value('_display', '{:x} {:x} {}'.format(index, base, name))
obj.set_value('Base', hex(base))
def create_generic(path):
obj = STATE.trace.create_object(path)
obj.insert()
result = put_generic(obj)
return result
def put_generic(node):
#print(f"put_generic: {node}")
nproc = util.selected_process()
if nproc is None:
return
nthrd = util.selected_thread()
mapper = STATE.trace.memory_mapper
mo = util.get_object(node.path)
kind = util.get_kind(mo)
type = util.get_type(mo)
vstr = util.get_value(mo)
if kind is not None:
node.set_value("_kind", kind)
if type is not None:
node.set_value("_type", type.value)
# print(f"MO={mo}")
attributes = util.get_attributes(mo)
# print(f"ATTR={attributes}")
mapper = STATE.trace.register_mapper
values = []
for key, value in attributes.items():
if value is None:
continue
kind = util.get_kind(value)
vstr = util.get_value(value)
#print(f"key={key} kind={kind} value={vstr} type={type}")
if kind == ModelObjectKind.PROPERTY_ACCESSOR.value or \
kind == ModelObjectKind.SYNTHETIC.value or \
kind == ModelObjectKind.METHOD.value:
if vstr is not None:
key += " : " + vstr
apath = node.path+'.'+key
aobj = STATE.trace.create_object(apath)
aobj.insert()
else:
try:
if node.path.endswith('.User'):
values.append(mapper.map_value(nproc, key, vstr))
node.set_value(key, hex(vstr))
except Exception as e:
pass # Error is printed by another mechanism
elements = util.get_elements(mo)
# print(f"ELEM={elements}")
keys = []
for el in elements:
index = el[0]
key = GENERIC_KEY_PATTERN.format(key=index)
lpath = node.path+key
lobj = STATE.trace.create_object(lpath)
update_by_container(node.path, index, lobj)
lobj.insert()
keys.append(key)
node.retain_values(keys)
return (values, keys)
def map_address(address):
nproc = util.selected_process()
mapper = STATE.trace.memory_mapper
base, addr = mapper.map(nproc, address)
if base != addr.space:
STATE.trace.create_overlay_space(base, addr.space)
return (base, addr)
def ghidra_trace_put_generic(node):
"""
Put the current thread's frames into the Ghidra trace
"""
STATE.require_tx()
with STATE.client.batch() as b:
put_generic(node)
def ghidra_trace_put_all(): def ghidra_trace_put_all():
""" """
Put everything currently selected into the Ghidra trace Put everything currently selected into the Ghidra trace

View file

@ -30,7 +30,6 @@ from pybag.dbgeng.idebugbreakpoint import DebugBreakpoint
from . import commands, util from . import commands, util
ALL_EVENTS = 0xFFFF ALL_EVENTS = 0xFFFF
@ -103,8 +102,9 @@ class ProcessState(object):
commands.STATE.trace.snapshot(description) commands.STATE.trace.snapshot(description)
proc = util.selected_process() proc = util.selected_process()
ipath = commands.PROCESS_PATTERN.format(procnum=proc) ipath = commands.PROCESS_PATTERN.format(procnum=proc)
commands.STATE.trace.proxy_object_path( procobj = commands.STATE.trace.proxy_object_path(ipath)
ipath).set_value('_exit_code', exit_code) procobj.set_value('_exit_code', exit_code)
procobj.set_value('_state', 'TERMINATED')
class BrkState(object): class BrkState(object):
@ -178,6 +178,8 @@ def on_state_changed(*args):
commands.put_state(proc) commands.put_state(proc)
if args[1] == DbgEng.DEBUG_STATUS_BREAK: if args[1] == DbgEng.DEBUG_STATUS_BREAK:
return on_stop(args) return on_stop(args)
elif args[1] == DbgEng.DEBUG_STATUS_NO_DEBUGGEE:
return on_exited(proc)
else: else:
return on_cont(args) return on_cont(args)
return S_OK return S_OK
@ -376,6 +378,7 @@ def on_stop(*args):
def on_exited(proc): def on_exited(proc):
# print("ON EXITED")
if proc not in PROC_STATE: if proc not in PROC_STATE:
# print("not in state") # print("not in state")
return return

View file

@ -40,13 +40,16 @@ AVAILABLE_PATTERN = re.compile('Available\[(?P<pid>\\d*)\]')
WATCHPOINT_PATTERN = re.compile('Watchpoints\[(?P<watchnum>\\d*)\]') WATCHPOINT_PATTERN = re.compile('Watchpoints\[(?P<watchnum>\\d*)\]')
BREAKPOINT_PATTERN = re.compile('Breakpoints\[(?P<breaknum>\\d*)\]') BREAKPOINT_PATTERN = re.compile('Breakpoints\[(?P<breaknum>\\d*)\]')
BREAK_LOC_PATTERN = extre(BREAKPOINT_PATTERN, '\[(?P<locnum>\\d*)\]') BREAK_LOC_PATTERN = extre(BREAKPOINT_PATTERN, '\[(?P<locnum>\\d*)\]')
PROCESS_PATTERN = re.compile('Processes\[(?P<procnum>\\d*)\]') SESSIONS_PATTERN = re.compile('Sessions')
PROC_BREAKS_PATTERN = extre(PROCESS_PATTERN, '\.Breakpoints') SESSION_PATTERN = extre(SESSIONS_PATTERN, '\[(?P<snum>\\d*)\]')
PROCESSES_PATTERN = extre(SESSION_PATTERN, '\.Processes')
PROCESS_PATTERN = extre(PROCESSES_PATTERN, '\[(?P<procnum>\\d*)\]')
PROC_BREAKS_PATTERN = extre(PROCESS_PATTERN, '\.Debug.Breakpoints')
PROC_BREAKBPT_PATTERN = extre(PROC_BREAKS_PATTERN, '\[(?P<breaknum>\\d*)\]') PROC_BREAKBPT_PATTERN = extre(PROC_BREAKS_PATTERN, '\[(?P<breaknum>\\d*)\]')
ENV_PATTERN = extre(PROCESS_PATTERN, '\.Environment') ENV_PATTERN = extre(PROCESS_PATTERN, '\.Environment')
THREADS_PATTERN = extre(PROCESS_PATTERN, '\.Threads') THREADS_PATTERN = extre(PROCESS_PATTERN, '\.Threads')
THREAD_PATTERN = extre(THREADS_PATTERN, '\[(?P<tnum>\\d*)\]') THREAD_PATTERN = extre(THREADS_PATTERN, '\[(?P<tnum>\\d*)\]')
STACK_PATTERN = extre(THREAD_PATTERN, '\.Stack') STACK_PATTERN = extre(THREAD_PATTERN, '\.Stack.Frames')
FRAME_PATTERN = extre(STACK_PATTERN, '\[(?P<level>\\d*)\]') FRAME_PATTERN = extre(STACK_PATTERN, '\[(?P<level>\\d*)\]')
REGS_PATTERN0 = extre(THREAD_PATTERN, '.Registers') REGS_PATTERN0 = extre(THREAD_PATTERN, '.Registers')
REGS_PATTERN = extre(FRAME_PATTERN, '.Registers') REGS_PATTERN = extre(FRAME_PATTERN, '.Registers')
@ -204,14 +207,21 @@ def evaluate(expr: str):
return str(eval(expr, shared_globals)) return str(eval(expr, shared_globals))
@REGISTRY.method(action='refresh') @REGISTRY.method(action='refresh', display="Refresh", condition=util.dbg.use_generics)
def refresh_generic(node: sch.OBJECT):
"""List processes on pydbg's host system."""
with commands.open_tracked_tx('Refresh Generic'):
commands.ghidra_trace_put_generic(node)
@REGISTRY.method(action='refresh', display='Refresh Available')
def refresh_available(node: sch.Schema('AvailableContainer')): def refresh_available(node: sch.Schema('AvailableContainer')):
"""List processes on pydbg's host system.""" """List processes on pydbg's host system."""
with commands.open_tracked_tx('Refresh Available'): with commands.open_tracked_tx('Refresh Available'):
commands.ghidra_trace_put_available() commands.ghidra_trace_put_available()
@REGISTRY.method(action='refresh') @REGISTRY.method(action='refresh', display='Refresh Breakpoints')
def refresh_breakpoints(node: sch.Schema('BreakpointContainer')): def refresh_breakpoints(node: sch.Schema('BreakpointContainer')):
""" """
Refresh the list of breakpoints (including locations for the current Refresh the list of breakpoints (including locations for the current
@ -221,14 +231,14 @@ def refresh_breakpoints(node: sch.Schema('BreakpointContainer')):
commands.ghidra_trace_put_breakpoints() commands.ghidra_trace_put_breakpoints()
@REGISTRY.method(action='refresh') @REGISTRY.method(action='refresh', display='Refresh Processes')
def refresh_processes(node: sch.Schema('ProcessContainer')): def refresh_processes(node: sch.Schema('ProcessContainer')):
"""Refresh the list of processes.""" """Refresh the list of processes."""
with commands.open_tracked_tx('Refresh Processes'): with commands.open_tracked_tx('Refresh Processes'):
commands.ghidra_trace_put_threads() commands.ghidra_trace_put_processes()
@REGISTRY.method(action='refresh') @REGISTRY.method(action='refresh', display='Refresh Breakpoint Locations')
def refresh_proc_breakpoints(node: sch.Schema('BreakpointLocationContainer')): def refresh_proc_breakpoints(node: sch.Schema('BreakpointLocationContainer')):
""" """
Refresh the breakpoint locations for the process. Refresh the breakpoint locations for the process.
@ -240,21 +250,21 @@ def refresh_proc_breakpoints(node: sch.Schema('BreakpointLocationContainer')):
commands.ghidra_trace_put_breakpoints() commands.ghidra_trace_put_breakpoints()
@REGISTRY.method(action='refresh') @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)."""
with commands.open_tracked_tx('Refresh Environment'): with commands.open_tracked_tx('Refresh Environment'):
commands.ghidra_trace_put_environment() commands.ghidra_trace_put_environment()
@REGISTRY.method(action='refresh') @REGISTRY.method(action='refresh', display='Refresh Threads')
def refresh_threads(node: sch.Schema('ThreadContainer')): def refresh_threads(node: sch.Schema('ThreadContainer')):
"""Refresh the list of threads in the process.""" """Refresh the list of threads in the process."""
with commands.open_tracked_tx('Refresh Threads'): with commands.open_tracked_tx('Refresh Threads'):
commands.ghidra_trace_put_threads() commands.ghidra_trace_put_threads()
@REGISTRY.method(action='refresh') @REGISTRY.method(action='refresh', display='Refresh Stack')
def refresh_stack(node: sch.Schema('Stack')): def refresh_stack(node: sch.Schema('Stack')):
"""Refresh the backtrace for the thread.""" """Refresh the backtrace for the thread."""
tnum = find_thread_by_stack_obj(node) tnum = find_thread_by_stack_obj(node)
@ -262,7 +272,7 @@ def refresh_stack(node: sch.Schema('Stack')):
commands.ghidra_trace_put_frames() commands.ghidra_trace_put_frames()
@REGISTRY.method(action='refresh') @REGISTRY.method(action='refresh', display='Refresh Registers')
def refresh_registers(node: sch.Schema('RegisterValueContainer')): def refresh_registers(node: sch.Schema('RegisterValueContainer')):
"""Refresh the register values for the frame.""" """Refresh the register values for the frame."""
tnum = find_thread_by_regs_obj(node) tnum = find_thread_by_regs_obj(node)
@ -270,14 +280,14 @@ def refresh_registers(node: sch.Schema('RegisterValueContainer')):
commands.ghidra_trace_putreg() commands.ghidra_trace_putreg()
@REGISTRY.method(action='refresh') @REGISTRY.method(action='refresh', display='Refresh Memory')
def refresh_mappings(node: sch.Schema('Memory')): def refresh_mappings(node: sch.Schema('Memory')):
"""Refresh the list of memory regions for the process.""" """Refresh the list of memory regions for the process."""
with commands.open_tracked_tx('Refresh Memory Regions'): with commands.open_tracked_tx('Refresh Memory Regions'):
commands.ghidra_trace_put_regions() commands.ghidra_trace_put_regions()
@REGISTRY.method(action='refresh') @REGISTRY.method(action='refresh', display='Refresh Modules')
def refresh_modules(node: sch.Schema('ModuleContainer')): def refresh_modules(node: sch.Schema('ModuleContainer')):
""" """
Refresh the modules and sections list for the process. Refresh the modules and sections list for the process.

View file

@ -1,4 +1,33 @@
<context> <context>
<schema name="Root" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
<interface name="Configurable" />
<attribute name="Sessions" schema="SessionContainer" required="yes" fixed="yes" />
<attribute name="Settings" schema="ANY" />
<attribute name="State" schema="ANY" />
<attribute name="Utility" schema="ANY" />
<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="ANY" hidden="yes" />
</schema>
<schema name="SessionContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
<interface name="Configurable" />
<element schema="Session" />
<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="ANY" hidden="yes" />
</schema>
<schema name="Session" elementResync="NEVER" attributeResync="NEVER"> <schema name="Session" elementResync="NEVER" attributeResync="NEVER">
<interface name="Access" /> <interface name="Access" />
<interface name="Attacher" /> <interface name="Attacher" />
@ -25,7 +54,7 @@
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" /> <attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
<attribute name="_order" schema="INT" hidden="yes" /> <attribute name="_order" schema="INT" hidden="yes" />
<attribute name="_modified" schema="BOOL" hidden="yes" /> <attribute name="_modified" schema="BOOL" hidden="yes" />
<attribute schema="VOID" /> <attribute schema="ANY" hidden="yes" />
</schema> </schema>
<schema name="Selectable" elementResync="NEVER" attributeResync="NEVER"> <schema name="Selectable" elementResync="NEVER" attributeResync="NEVER">
<element schema="OBJECT" /> <element schema="OBJECT" />
@ -38,6 +67,19 @@
<attribute name="_modified" schema="BOOL" hidden="yes" /> <attribute name="_modified" schema="BOOL" hidden="yes" />
<attribute schema="VOID" /> <attribute schema="VOID" />
</schema> </schema>
<schema name="DebugBreakpointContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
<interface name="Aggregate" />
<element schema="VOID" />
<attribute name="Breakpoints" schema="BreakpointContainer" required="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="BreakpointContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER"> <schema name="BreakpointContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
<interface name="BreakpointLocationContainer" /> <interface name="BreakpointLocationContainer" />
<interface name="BreakpointSpecContainer" /> <interface name="BreakpointSpecContainer" />
@ -50,7 +92,7 @@
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" /> <attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
<attribute name="_order" schema="INT" hidden="yes" /> <attribute name="_order" schema="INT" hidden="yes" />
<attribute name="_modified" schema="BOOL" hidden="yes" /> <attribute name="_modified" schema="BOOL" hidden="yes" />
<attribute schema="VOID" /> <attribute schema="ANY" hidden="yes" />
</schema> </schema>
<schema name="AvailableContainer" canonical="yes" elementResync="ALWAYS" attributeResync="NEVER"> <schema name="AvailableContainer" canonical="yes" elementResync="ALWAYS" attributeResync="NEVER">
<interface name="Configurable" /> <interface name="Configurable" />
@ -76,7 +118,7 @@
<attribute name="_order" schema="INT" hidden="yes" /> <attribute name="_order" schema="INT" hidden="yes" />
<attribute name="_modified" schema="BOOL" hidden="yes" /> <attribute name="_modified" schema="BOOL" hidden="yes" />
<attribute name="_base" schema="INT" /> <attribute name="_base" schema="INT" />
<attribute schema="VOID" /> <attribute schema="ANY" hidden="yes" />
</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" />
@ -134,12 +176,14 @@
<interface name="Interruptible" /> <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="Debug" schema="DebugBreakpointContainer" required="yes" fixed="yes" />
<!-- attribute name="Breakpoints" schema="BreakpointLocationContainer" 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 name="Environment" schema="Environment" required="yes" fixed="yes" /> <attribute name="Environment" schema="Environment" required="yes" fixed="yes" />
<attribute name="Memory" schema="Memory" required="yes" fixed="yes" /> <attribute name="Memory" schema="Memory" required="yes" fixed="yes" />
<attribute name="Modules" schema="ModuleContainer" required="yes" fixed="yes" /> <attribute name="Modules" schema="ModuleContainer" required="yes" fixed="yes" />
<attribute name="Handle" schema="STRING" fixed="yes" />
<attribute name="Id" schema="STRING" fixed="yes" />
<attribute name="_pid" schema="LONG" hidden="yes" /> <attribute name="_pid" schema="LONG" hidden="yes" />
<attribute name="_state" schema="EXECUTION_STATE" required="yes" 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="_supported_attach_kinds" schema="SET_ATTACH_KIND" required="yes" hidden="yes" />
@ -152,7 +196,7 @@
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" /> <attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
<attribute name="_order" schema="INT" hidden="yes" /> <attribute name="_order" schema="INT" hidden="yes" />
<attribute name="_modified" schema="BOOL" hidden="yes" /> <attribute name="_modified" schema="BOOL" hidden="yes" />
<attribute schema="VOID" /> <attribute schema="ANY" hidden="yes" />
</schema> </schema>
<schema name="Environment" elementResync="NEVER" attributeResync="NEVER"> <schema name="Environment" elementResync="NEVER" attributeResync="NEVER">
<interface name="Environment" /> <interface name="Environment" />
@ -184,7 +228,7 @@
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" /> <attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
<attribute name="_order" schema="INT" hidden="yes" /> <attribute name="_order" schema="INT" hidden="yes" />
<attribute name="_modified" schema="BOOL" hidden="yes" /> <attribute name="_modified" schema="BOOL" hidden="yes" />
<attribute schema="VOID" /> <attribute schema="ANY" hidden="yes" />
</schema> </schema>
<schema name="Memory" canonical="yes" elementResync="NEVER" attributeResync="NEVER"> <schema name="Memory" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
<interface name="Memory" /> <interface name="Memory" />
@ -235,7 +279,7 @@
<attribute name="_order" schema="INT" hidden="yes" /> <attribute name="_order" schema="INT" hidden="yes" />
<attribute name="_modified" schema="BOOL" hidden="yes" /> <attribute name="_modified" schema="BOOL" hidden="yes" />
<attribute name="_base" schema="INT" /> <attribute name="_base" schema="INT" />
<attribute schema="VOID" /> <attribute schema="ANY" hidden="yes" />
</schema> </schema>
<schema name="Method" elementResync="NEVER" attributeResync="NEVER"> <schema name="Method" elementResync="NEVER" attributeResync="NEVER">
<interface name="Method" /> <interface name="Method" />
@ -251,8 +295,10 @@
<interface name="Steppable" /> <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="StackFramesContainer" required="yes" fixed="yes" />
<attribute name="Registers" schema="RegisterValueContainer" required="yes" fixed="yes" /> <attribute name="Registers" schema="RegisterValueContainer" required="yes" fixed="yes" />
<attribute name="Environment" schema="ANY" fixed="yes" />
<attribute name="Id" schema="STRING" fixed="yes" />
<attribute name="_tid" schema="LONG" hidden="yes" /> <attribute name="_tid" schema="LONG" hidden="yes" />
<attribute name="_state" schema="EXECUTION_STATE" required="yes" 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="_supported_step_kinds" schema="SET_STEP_KIND" required="yes" fixed="yes" hidden="yes" />
@ -264,7 +310,7 @@
<attribute name="_order" schema="INT" hidden="yes" /> <attribute name="_order" schema="INT" hidden="yes" />
<attribute name="_modified" schema="BOOL" hidden="yes" /> <attribute name="_modified" schema="BOOL" hidden="yes" />
<attribute name="Advance" schema="Method" required="yes" fixed="yes" hidden="yes" /> <attribute name="Advance" schema="Method" required="yes" fixed="yes" hidden="yes" />
<attribute schema="VOID" /> <attribute schema="ANY" hidden="yes" />
</schema> </schema>
<schema name="Module" elementResync="NEVER" attributeResync="NEVER"> <schema name="Module" elementResync="NEVER" attributeResync="NEVER">
<interface name="Module" /> <interface name="Module" />
@ -282,6 +328,7 @@
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" /> <attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
<attribute name="_order" schema="INT" hidden="yes" /> <attribute name="_order" schema="INT" hidden="yes" />
<attribute name="_modified" schema="BOOL" hidden="yes" /> <attribute name="_modified" schema="BOOL" hidden="yes" />
<attribute name="ToDisplayString" schema="BOOL" hidden="yes" />
<attribute schema="VOID" /> <attribute schema="VOID" />
</schema> </schema>
<schema name="MemoryRegion" elementResync="NEVER" attributeResync="NEVER"> <schema name="MemoryRegion" elementResync="NEVER" attributeResync="NEVER">
@ -315,6 +362,19 @@
<attribute name="_modified" schema="BOOL" hidden="yes" /> <attribute name="_modified" schema="BOOL" hidden="yes" />
<attribute schema="VOID" /> <attribute schema="VOID" />
</schema> </schema>
<schema name="StackFramesContainer" canonical="yes" elementResync="NEVER" attributeResync="NEVER">
<interface name="Aggregate" />
<element schema="VOID" />
<attribute name="Frames" schema="Stack" required="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="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" />
@ -325,7 +385,7 @@
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" /> <attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
<attribute name="_order" schema="INT" hidden="yes" /> <attribute name="_order" schema="INT" hidden="yes" />
<attribute name="_modified" schema="BOOL" hidden="yes" /> <attribute name="_modified" schema="BOOL" hidden="yes" />
<attribute schema="VOID" /> <attribute schema="ANY" hidden="yes" />
</schema> </schema>
<schema name="SymbolContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER"> <schema name="SymbolContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
<interface name="SymbolNamespace" /> <interface name="SymbolNamespace" />
@ -360,7 +420,6 @@
<interface name="Aggregate" /> <interface name="Aggregate" />
<element schema="VOID" /> <element schema="VOID" />
<attribute name="_function" schema="STRING" hidden="yes" /> <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="_pc" schema="ADDRESS" required="yes" hidden="yes" />
<attribute name="_value" schema="ANY" hidden="yes" /> <attribute name="_value" schema="ANY" hidden="yes" />
<attribute name="_type" schema="STRING" hidden="yes" /> <attribute name="_type" schema="STRING" hidden="yes" />
@ -369,7 +428,7 @@
<attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" /> <attribute name="_kind" schema="STRING" fixed="yes" hidden="yes" />
<attribute name="_order" schema="INT" hidden="yes" /> <attribute name="_order" schema="INT" hidden="yes" />
<attribute name="_modified" schema="BOOL" hidden="yes" /> <attribute name="_modified" schema="BOOL" hidden="yes" />
<attribute schema="VOID" /> <attribute schema="ANY" hidden="yes" />
</schema> </schema>
<schema name="Section" elementResync="NEVER" attributeResync="NEVER"> <schema name="Section" elementResync="NEVER" attributeResync="NEVER">
<interface name="Section" /> <interface name="Section" />
@ -396,6 +455,9 @@
<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" />
<attribute name="Memory Protection Extensions" schema="RegisterBank" /> <attribute name="Memory Protection Extensions" schema="RegisterBank" />
<attribute name="FloatingPoint" schema="RegisterBank" />
<attribute name="SIMD" schema="RegisterBank" />
<attribute name="User" schema="RegisterBank" />
<attribute name="_descriptions" schema="RegisterValueContainer" /> <attribute name="_descriptions" schema="RegisterValueContainer" />
<attribute name="_value" schema="ANY" hidden="yes" /> <attribute name="_value" schema="ANY" hidden="yes" />
<attribute name="_type" schema="STRING" hidden="yes" /> <attribute name="_type" schema="STRING" hidden="yes" />

View file

@ -29,12 +29,21 @@ import traceback
from comtypes import CoClass, GUID from comtypes import CoClass, GUID
import comtypes import comtypes
from comtypes.hresult import S_OK from comtypes.hresult import S_OK
from pybag import pydbg, userdbg, kerneldbg, crashdbg from pybag import pydbg, userdbg, kerneldbg, crashdbg
from pybag.dbgeng import core as DbgEng from pybag.dbgeng import core as DbgEng
from pybag.dbgeng import exception from pybag.dbgeng import exception
from pybag.dbgeng import util as DbgUtil from pybag.dbgeng import util as DbgUtil
from pybag.dbgeng.callbacks import DbgEngCallbacks from pybag.dbgeng.callbacks import DbgEngCallbacks
from dbgmodel.ihostdatamodelaccess import HostDataModelAccess
import comtypes.client
try:
from comtypes.gen import DbgMod
except:
tlb = "..\..\..\..\build\os\win_x86_64\dbgmodel.tlb"
comtypes.client.GetModule(tlb)
from comtypes.gen import DbgMod
DbgVersion = namedtuple('DbgVersion', ['full', 'name', 'dotted', 'arch']) DbgVersion = namedtuple('DbgVersion', ['full', 'name', 'dotted', 'arch'])
@ -134,12 +143,12 @@ class DbgExecutor(object):
self._thread.start() self._thread.start()
self._executing = False self._executing = False
def submit(self, fn, / , *args, **kwargs): def submit(self, fn, /, *args, **kwargs):
f = self._submit_no_exit(fn, *args, **kwargs) f = self._submit_no_exit(fn, *args, **kwargs)
self._ghidra_dbg.exit_dispatch() self._ghidra_dbg.exit_dispatch()
return f return f
def _submit_no_exit(self, fn, / , *args, **kwargs): def _submit_no_exit(self, fn, /, *args, **kwargs):
f = Future() f = Future()
if self._executing: if self._executing:
f.set_exception(DebuggeeRunningException("Debuggee is Running")) f.set_exception(DebuggeeRunningException("Debuggee is Running"))
@ -199,6 +208,7 @@ class GhidraDbg(object):
# Wait for the executor to be operational before getting base # Wait for the executor to be operational before getting base
self._queue._submit_no_exit(lambda: None).result() self._queue._submit_no_exit(lambda: None).result()
self._install_stdin() self._install_stdin()
self.use_generics = os.getenv('OPT_USE_DBGMODEL') == "true"
base = self._protected_base base = self._protected_base
for name in ['set_output_mask', 'get_output_mask', for name in ['set_output_mask', 'get_output_mask',
@ -447,6 +457,8 @@ def get_breakpoints():
@dbg.eng_thread @dbg.eng_thread
def selected_process(): def selected_process():
try: try:
if dbg.use_generics:
return dbg._base._systems.GetCurrentProcessSystemId()
return dbg._base._systems.GetCurrentProcessId() return dbg._base._systems.GetCurrentProcessId()
except exception.E_UNEXPECTED_Error: except exception.E_UNEXPECTED_Error:
return None return None
@ -455,6 +467,8 @@ def selected_process():
@dbg.eng_thread @dbg.eng_thread
def selected_thread(): def selected_thread():
try: try:
if dbg.use_generics:
return dbg._base._systems.GetCurrentThreadSystemId()
return dbg._base._systems.GetCurrentThreadId() return dbg._base._systems.GetCurrentThreadId()
except exception.E_UNEXPECTED_Error: except exception.E_UNEXPECTED_Error:
return None return None
@ -476,11 +490,15 @@ def selected_frame():
@dbg.eng_thread @dbg.eng_thread
def select_process(id: int): def select_process(id: int):
if dbg.use_generics:
id = get_proc_id(id)
return dbg._base._systems.SetCurrentProcessId(id) return dbg._base._systems.SetCurrentProcessId(id)
@dbg.eng_thread @dbg.eng_thread
def select_thread(id: int): def select_thread(id: int):
if dbg.use_generics:
id = get_thread_id(id)
return dbg._base._systems.SetCurrentThreadId(id) return dbg._base._systems.SetCurrentThreadId(id)
@ -640,6 +658,101 @@ def thread_list(running=False):
_dbg._systems.SetCurrentThreadId(curid) _dbg._systems.SetCurrentThreadId(curid)
@dbg.eng_thread
def get_proc_id(pid):
"""Get the list of all processes"""
# TODO: Implement GetProcessIdBySystemId and replace this logic
_dbg = dbg._base
map = {}
try:
x = _dbg._systems.GetProcessIdsByIndex()
for i in range(0, len(x[0])):
map[x[1][i]] = x[0][i]
return map[pid]
except Exception:
pass
return None
@dbg.eng_thread
def get_thread_id(tid):
"""Get the list of all threads"""
# TODO: Implement GetThreadIdBySystemId and replace this logic
_dbg = dbg._base
map = {}
try:
x = _dbg._systems.GetThreadIdsByIndex()
for i in range(0, len(x[0])):
map[x[1][i]] = x[0][i]
return map[tid]
except Exception:
pass
return None
def split_path(pathString):
list = []
segs = pathString.split(".")
for s in segs:
if s.endswith("]"):
index = s.index("[")
list.append(s[:index])
list.append(s[index:])
else:
list.append(s)
return list
def IHostDataModelAccess():
return HostDataModelAccess(
dbg._base._client._cli.QueryInterface(interface=DbgMod.IHostDataModelAccess))
@dbg.eng_thread
def get_object(relpath):
"""Get the list of all threads"""
_cli = dbg._base._client._cli
access = HostDataModelAccess(_cli.QueryInterface(
interface=DbgMod.IHostDataModelAccess))
(mgr, host) = access.GetDataModel()
root = mgr.GetRootNamespace()
pathstr = "Debugger"
if relpath != '':
pathstr += "."+relpath
path = split_path(pathstr)
return root.GetOffspring(path)
@dbg.eng_thread
def get_attributes(obj):
"""Get the list of attributes"""
return obj.GetAttributes()
@dbg.eng_thread
def get_elements(obj):
"""Get the list of all threads"""
return obj.GetElements()
@dbg.eng_thread
def get_kind(obj):
"""Get the list of all threads"""
return obj.GetKind().value
@dbg.eng_thread
def get_type(obj):
"""Get the list of all threads"""
return obj.GetTypeKind()
@dbg.eng_thread
def get_value(obj):
"""Get the list of all threads"""
return obj.GetValue()
conv_map = {} conv_map = {}