mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
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:
parent
f5008f9f99
commit
2c69ffb04a
19 changed files with 2385 additions and 44 deletions
|
@ -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'
|
||||||
|
|
49
Ghidra/Debug/Debugger-agent-dbgeng/buildNatives.gradle
Normal file
49
Ghidra/Debug/Debugger-agent-dbgeng/buildNatives.gradle
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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|
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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" />
|
||||||
|
|
|
@ -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 = {}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue