static int _adbobj_trace_trampoline(AdbObject *self, PyFrameObject *frame, int what, PyObject *arg) { int result; #ifdef DEBUG_PRINT fprintf(stderr, "_adbobj_trace_trampoline...\n"); #endif PyFrame_FastToLocals(frame); result = _adbobj_trace_dispatch(self, frame, what, arg); PyFrame_LocalsToFast(frame, 1); if (result == -1) { PyTraceBack_Here(frame); PyEval_SetTrace(NULL, NULL); Py_XDECREF(frame->f_trace); frame->f_trace = NULL; #ifdef DEBUG_PRINT fprintf(stderr, "..._adbobj_trace_trampoline NULL result\n"); #endif } #ifdef DEBUG_PRINT fprintf(stderr, "..._adbobj_trace_trampoline %d\n", result); #endif return result; }
/* A custom, fast, inlinable version of PyCFunction_Call() */ static PyObject * call_cfunc(DispatcherObject *self, PyObject *cfunc, PyObject *args, PyObject *kws, PyObject *locals) { PyCFunctionWithKeywords fn; PyThreadState *tstate; assert(PyCFunction_Check(cfunc)); assert(PyCFunction_GET_FLAGS(cfunc) == METH_VARARGS | METH_KEYWORDS); fn = (PyCFunctionWithKeywords) PyCFunction_GET_FUNCTION(cfunc); tstate = PyThreadState_GET(); if (tstate->use_tracing && tstate->c_profilefunc) { /* * The following code requires some explaining: * * We want the jit-compiled function to be visible to the profiler, so we * need to synthesize a frame for it. * The PyFrame_New() constructor doesn't do anything with the 'locals' value if the 'code's * 'CO_NEWLOCALS' flag is set (which is always the case nowadays). * So, to get local variables into the frame, we have to manually set the 'f_locals' * member, then call `PyFrame_LocalsToFast`, where a subsequent call to the `frame.f_locals` * property (by virtue of the `frame_getlocals` function in frameobject.c) will find them. */ PyCodeObject *code = (PyCodeObject*)PyObject_GetAttrString((PyObject*)self, "__code__"); PyObject *globals = PyDict_New(); PyObject *builtins = PyEval_GetBuiltins(); PyFrameObject *frame = NULL; PyObject *result = NULL; if (!code) { PyErr_Format(PyExc_RuntimeError, "No __code__ attribute found."); goto error; } /* Populate builtins, which is required by some JITted functions */ if (PyDict_SetItemString(globals, "__builtins__", builtins)) { goto error; } frame = PyFrame_New(tstate, code, globals, NULL); if (frame == NULL) { goto error; } /* Populate the 'fast locals' in `frame` */ Py_XDECREF(frame->f_locals); frame->f_locals = locals; Py_XINCREF(frame->f_locals); PyFrame_LocalsToFast(frame, 0); tstate->frame = frame; C_TRACE(result, fn(PyCFunction_GET_SELF(cfunc), args, kws)); tstate->frame = frame->f_back; error: Py_XDECREF(frame); Py_XDECREF(globals); Py_XDECREF(code); return result; } else return fn(PyCFunction_GET_SELF(cfunc), args, kws); }
// maps the PyCodeObject to our internal pit item via hash table. static _pit * _code2pit(PyFrameObject *fobj) { _hitem *it; PyCodeObject *cobj; _pit *pit; cobj = fobj->f_code; it = hfind(current_ctx->pits, (uintptr_t)cobj); if (it) { return ((_pit *)it->val); } pit = _create_pit(); if (!pit) return NULL; if (!hadd(current_ctx->pits, (uintptr_t)cobj, (uintptr_t)pit)) return NULL; pit->name = NULL; Py_INCREF(cobj->co_filename); pit->modname = cobj->co_filename; pit->lineno = cobj->co_firstlineno; PyFrame_FastToLocals(fobj); if (cobj->co_argcount) { const char *firstarg = PyStr_AS_CSTRING(PyTuple_GET_ITEM(cobj->co_varnames, 0)); if (!strcmp(firstarg, "self")) { PyObject* locals = fobj->f_locals; if (locals) { PyObject* self = PyDict_GetItemString(locals, "self"); if (self) { PyObject *class_obj = PyObject_GetAttrString(self, "__class__"); if (class_obj) { PyObject *class_name = PyObject_GetAttrString(class_obj, "__name__"); if (class_name) { pit->name = PyStr_FromFormat("%s.%s", PyStr_AS_CSTRING(class_name), PyStr_AS_CSTRING(cobj->co_name)); Py_DECREF(class_name); } Py_DECREF(class_obj); } } } } } if (!pit->name) { Py_INCREF(cobj->co_name); pit->name = cobj->co_name; } PyFrame_LocalsToFast(fobj, 0); return pit; }
//============================================================================= // METHOD: SPELLvariableMonitor::retrieveLocalVariables() //============================================================================= void SPELLvariableMonitor::retrieveLocalVariables(std::vector<SPELLvarInfo>& vars) { DEBUG("[VM] Retrieve Locals"); /* * Bottom stack frame is discarded, * as globals and locals are the same dictionary */ if (m_frame->f_back == NULL) return; /* * Get the names defined in the current code, including arguments */ std::vector<std::string> varNames = retrieveNames(); /* * Iterate over the locals dictionary, retrieving the names contained in * varNames */ PyFrame_FastToLocals(m_frame); PyObject* dict = m_frame->f_locals; DEBUG("[VM] Frame: " + PYCREPR(m_frame)); for( unsigned int index = 0; index< varNames.size(); index++) { std::string varName = varNames[index]; PyObject* pyVarName = SSTRPY(varName); if (PyDict_Contains( dict, pyVarName )) { PyObject* object = PyDict_GetItem( dict, pyVarName ); if (!SPELLpythonHelper::instance().isInstance(object, "Database", "spell.lib.adapter.databases.database")) { if (PyCallable_Check(object)) continue; if (PyClass_Check(object)) continue; if (PyModule_Check(object)) continue; if (PyInstance_Check(object)) continue; } DEBUG("[VM] Processing " + varName); std::string type = PYSSTR( PyObject_Type(object) ); DEBUG("[VM] Type : " + type); std::string value = PYREPR( object ); DEBUG("[VM] Value : " + value); DEBUG("[VM] Global : " + BSTR(false)); DEBUG("[VM] Registered: " + BSTR(isRegistered(varName))); // Mark empty values (empty strings) as "<empty>" if (value == "") value = EMPTY_STRING; vars.push_back( SPELLvarInfo(varName, type, value, false, isRegistered(varName)) ); } } PyFrame_LocalsToFast(m_frame,0); }
//============================================================================= // METHOD: SPELLvariableMonitor::changeVariable() //============================================================================= void SPELLvariableMonitor::changeVariable( SPELLvarInfo& var ) { SPELLsafePythonOperations ops("SPELLvariableMonitor::changeVariable()"); DEBUG("[VM] Request changing variable " + var.varName); // Evaluate the value for the variable PyObject* value = NULL; // If varValue is '<empty>' or empty string, do not try to evaluate it, // directly assign Python empty string if ((var.varValue == EMPTY_STRING)||(var.varValue == "")) { value = STRPY(""); } else { // Build assignment expression. We need to check first, if there // are double quotes, convert them to single quotes SPELLutils::replace(var.varValue, "\"", "'"); DEBUG("[VM] Evaluating value expression: " + var.varValue ); // Check value correctness and evaluate it value = SPELLpythonHelper::instance().eval(var.varValue, false); } if ((m_frame->f_globals)&&(var.isGlobal)) { DEBUG("[VM] Setting " + var.varName + " to " + PYREPR(value) + " in globals"); PyDict_SetItemString( m_frame->f_globals, var.varName.c_str(), value ); } else if ((m_frame->f_locals)&&(!var.isGlobal)) { DEBUG("[VM] Setting " + var.varName + " to " + PYREPR(value) + " in locals"); // Update locals from fast locals first PyFrame_FastToLocals(m_frame); PyDict_SetItemString( m_frame->f_locals, var.varName.c_str(), value ); PyFrame_LocalsToFast(m_frame,0); } var.varValue = PYSSTR(value); if (var.varValue == "") var.varValue = EMPTY_STRING; // Update the variable if it is registered, and notify to listeners VarMap::iterator it = m_variables.find(var.varName); if (it != m_variables.end()) { std::vector<SPELLvarInfo> changed; it->second.varValue = var.varValue; DEBUG("[VM] Variable changed by user: "******", current value: " + var.varValue ); changed.push_back(it->second); m_listener->variableChanged( changed ); } }