/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include "pycdbextmodule.h" #include "extensioncontext.h" #include "symbolgroup.h" #include "pyfield.h" #include "pystdoutredirect.h" #include "pytype.h" #include "pyvalue.h" #include #include // cdbext python module static PyObject *cdbext_parseAndEvaluate(PyObject *, PyObject *args) // -> Value { char *expr; if (!PyArg_ParseTuple(args, "s", &expr)) return NULL; CIDebugControl *control = ExtensionCommandContext::instance()->control(); control->SetExpressionSyntax(DEBUG_EXPR_CPLUSPLUS); DEBUG_VALUE value; if (FAILED(control->Evaluate(expr, DEBUG_VALUE_INT64, &value, NULL))) Py_RETURN_NONE; return Py_BuildValue("K", value.I64); } static PyObject *cdbext_lookupType(PyObject *, PyObject *args) // -> Type { char *type; if (!PyArg_ParseTuple(args, "s", &type)) return NULL; return lookupType(type); } static PyObject *cdbext_listOfLocals(PyObject *, PyObject *) // -> [ Value ] { ExtensionCommandContext *extCmdCtx = ExtensionCommandContext::instance(); ULONG frame; if (FAILED(extCmdCtx->symbols()->GetCurrentScopeFrameIndex(&frame))) return NULL; std::string errorMessage; LocalsSymbolGroup *sg = ExtensionContext::instance().symbolGroup( extCmdCtx->symbols(), extCmdCtx->threadId(), int(frame), &errorMessage); if (!sg) return NULL; const auto children = sg->root()->children(); auto locals = PyList_New(0); for (AbstractSymbolGroupNode *abstractChild : children) { Value *childValue = PyObject_New(Value, value_pytype()); if (childValue != NULL) { if (SymbolGroupNode* child = abstractChild->asSymbolGroupNode()) { childValue->m_index = child->index(); childValue->m_symbolGroup = sg->debugSymbolGroup(); } } PyList_Append(locals, reinterpret_cast(childValue)); } return locals; } static PyObject *cdbext_pointerSize(PyObject *, PyObject *) { HRESULT isPointer64Bit = ExtensionCommandContext::instance()->control()->IsPointer64Bit(); return Py_BuildValue("i", isPointer64Bit == S_OK ? 8 : 4); } static PyObject *cdbext_readRawMemory(PyObject *, PyObject *args) { ULONG64 address = 0; ULONG size = 0; if (!PyArg_ParseTuple(args, "Kk", &address, &size)) return NULL; char *buffer = new char[size]; CIDebugDataSpaces *data = ExtensionCommandContext::instance()->dataSpaces(); ULONG bytesWritten = 0; HRESULT hr = data->ReadVirtual(address, buffer, size, &bytesWritten); if (FAILED(hr)) bytesWritten = 0; PyObject *ret = Py_BuildValue("y#", buffer, bytesWritten); delete[] buffer; return ret; } static PyMethodDef cdbextMethods[] = { {"parseAndEvaluate", cdbext_parseAndEvaluate, METH_VARARGS, "Returns value of expression or None if the expression can not be resolved"}, {"lookupType", cdbext_lookupType, METH_VARARGS, "Returns type object or None if the type can not be resolved"}, {"listOfLocals", cdbext_listOfLocals, METH_NOARGS, "Returns list of values that are currently in scope"}, {"pointerSize", cdbext_pointerSize, METH_NOARGS, "Returns the size of a pointer"}, {"readRawMemory", cdbext_readRawMemory, METH_VARARGS, "Read a block of data from the virtual address space"}, {NULL, NULL, 0, NULL} /* Sentinel */ }; static struct PyModuleDef cdbextModule = { PyModuleDef_HEAD_INIT, "cdbext", /* name of module */ "bridge to the creator cdb extension", /* module documentation */ -1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */ cdbextMethods }; PyMODINIT_FUNC PyInit_cdbext(void) { if (PyType_Ready(field_pytype()) < 0) return NULL; if (PyType_Ready(type_pytype()) < 0) return NULL; if (PyType_Ready(value_pytype()) < 0) return NULL; stdoutRedirect_pytype()->tp_new = PyType_GenericNew; if (PyType_Ready(stdoutRedirect_pytype()) < 0) return NULL; PyObject *module = PyModule_Create(&cdbextModule); if (module == NULL) return NULL; Py_INCREF(field_pytype()); Py_INCREF(stdoutRedirect_pytype()); Py_INCREF(type_pytype()); Py_INCREF(value_pytype()); PyModule_AddObject(module, "Field", reinterpret_cast(field_pytype())); PyModule_AddObject(module, "StdoutRedirect", reinterpret_cast(stdoutRedirect_pytype())); PyModule_AddObject(module, "Type", reinterpret_cast(type_pytype())); PyModule_AddObject(module, "Value", reinterpret_cast(value_pytype())); return module; } void initCdbextPythonModule() { PyImport_AppendInittab("cdbext", PyInit_cdbext); } PyObject *pyBool(bool b) { if (b) Py_RETURN_TRUE; else Py_RETURN_FALSE; }