static PyObject * frame_getlocals(PyFrameObject *f, void *closure) { PyFrame_FastToLocals(f); Py_INCREF(f->f_locals); return f->f_locals; }
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; }
//============================================================================= // METHOD: SPELLvariableMonitor::registerVariable() //============================================================================= bool SPELLvariableMonitor::registerVariable( SPELLvarInfo& var ) { SPELLsafePythonOperations ops("SPELLvariableMonitor::registerVariable()"); if ((m_frame->f_globals)&&(var.isGlobal)) { var.varValue = PYSSTR( PyDict_GetItemString( m_frame->f_globals, var.varName.c_str() )); if (var.varValue == "") var.varValue = EMPTY_STRING; var.varType = PYSSTR( PyObject_Type( PyDict_GetItemString( m_frame->f_globals, var.varName.c_str() )) ); var.isGlobal = true; var.isRegistered = true; m_variables.insert( std::make_pair( var.varName, var ) ); DEBUG("[VM] Registered global variable: " + var.varName + ", current value: " + var.varValue ); return true; } else if ((m_frame->f_locals)&&(!var.isGlobal)) { // We need to retrieve the function arguments and other locals, which are only stored in // fast locals by default PyFrame_FastToLocals(m_frame); var.varValue = PYSSTR( PyDict_GetItemString( m_frame->f_locals, var.varName.c_str() )); if (var.varValue == "") var.varValue = EMPTY_STRING; var.varType = PYSSTR( PyObject_Type( PyDict_GetItemString( m_frame->f_locals, var.varName.c_str() )) ); var.isGlobal = true; var.isRegistered = true; m_variables.insert( std::make_pair( var.varName, var ) ); DEBUG("[VM] Registered local variable: " + var.varName + ", current value: " + var.varValue ); return true; } var.varValue = "???"; var.varType = "???"; var.isRegistered = false; DEBUG("[VM] No such variable: " + var.varName); return false; }
static PyObject * frame_getattr(PyFrameObject *f, char *name) { if (strcmp(name, "f_locals") == 0) PyFrame_FastToLocals(f); return PyMember_Get((char *)f, frame_memberlist, name); }
// 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::getAllVariables() //============================================================================= std::vector<SPELLvarInfo> SPELLvariableMonitor::getLocalVariables() { SPELLsafePythonOperations ops("SPELLvariableMonitor::getLocalVariables()"); std::vector<SPELLvarInfo> vars; // We need to retrieve the function arguments and other locals, which are only stored in // fast locals by default PyFrame_FastToLocals(m_frame); retrieveLocalVariables( vars ); return vars; }
//============================================================================= // 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 ); } }
//============================================================================= // METHOD: SPELLvariableMonitor::analyze() //============================================================================= void SPELLvariableMonitor::analyze() { std::vector<SPELLvarInfo> changed; bool copyFast = true; VarMap::iterator it; for( it = m_variables.begin(); it != m_variables.end(); it++ ) { std::string varName = it->first; std::string currentValue = ""; std::string lastValue = ""; if ( (it->second.isGlobal) && (m_frame->f_globals) ) { PyObject* pyCurrentValue = PyDict_GetItemString( m_frame->f_globals, varName.c_str() ); currentValue = PYSSTR(pyCurrentValue); lastValue = it->second.varValue; } else if ( (!it->second.isGlobal) && (m_frame->f_locals) ) { if (copyFast) { copyFast = false; // We need to retrieve the function arguments and other locals, which are only stored in // fast locals by default PyFrame_FastToLocals(m_frame); } PyObject* pyCurrentValue = PyDict_GetItemString( m_frame->f_locals, varName.c_str() ); currentValue = PYSSTR(pyCurrentValue); lastValue = it->second.varValue; } if (lastValue != currentValue) { if (currentValue == "") currentValue == EMPTY_STRING; DEBUG("[VM] Variable change: " + varName + ", current value: " + currentValue + ", previous: " + it->second.varValue ); it->second.varValue = currentValue; changed.push_back(it->second); } } if (changed.size()>0) { m_listener->variableChanged( changed ); } }
//============================================================================= // METHOD: SPELLvariableMonitor::getAllVariables() //============================================================================= std::vector<SPELLvarInfo> SPELLvariableMonitor::getAllVariables() { SPELLsafePythonOperations ops("SPELLvariableMonitor::getAllVariables()"); std::vector<SPELLvarInfo> vars; // We need to retrieve the function arguments and other locals, which are only stored in // fast locals by default PyFrame_FastToLocals(m_frame); /* * Get locals */ retrieveLocalVariables(vars); /* * Get the name of the found locals to filter them while retrieving * the locals */ std::set<std::string> locals; /* * TODO maybe we should filter globals variables whose names are the same as * variables found in the local scope * To do this, uncomment the following loop */ /*for (unsigned int index = 0; index< vars.size(); index++) { SPELLvarInfo var = vars[index]; locals.insert(var.varName); }*/ /* * Get globals */ retrieveGlobalVariables(vars, locals); return vars; }
static PyObject * CapObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { if (kwds == NULL) { // PyThreadState *tstate = PyEval_SaveThread(); PyFrameObject *frame = PyThreadState_GET()->frame; PyFrame_FastToLocals(frame); kwds = frame->f_locals; // PyFrame_LocalsToFast(frame, 0); // PyEval_RestoreThread(tstate); } PyDictObject *environ = (PyDictObject *)kwds; PyObject *env, *keys; Py_ssize_t i, size; Py_ssize_t mask, key_len; PyObject *key, *value; PyDictEntry *entries; const char* key_str; /* Preallocate the list of tuples, to avoid allocations during * the loop over the items, which could trigger GC, which * could resize the dict. :-( */ again: size = environ->ma_used; keys = PyList_New(0); if (keys == NULL) return NULL; env = PyList_New(0); if (env == NULL) return NULL; if (size != environ->ma_used) { /* Durnit. The allocations caused the dict to resize. * Just start over, this shouldn't normally happen. */ Py_DECREF(keys); Py_DECREF(env); goto again; } entries = environ->ma_table; mask = environ->ma_mask; for (i = 0; i <= mask; i++) { if ((value=entries[i].me_value) != NULL) { key = entries[i].me_key; if (!PyString_CheckExact(key)) { Py_DECREF(keys); Py_DECREF(env); PyErr_SetString(PyExc_ValueError, "Only string keys can be used in Objects."); return NULL; } key_len = PyString_GET_SIZE(key); if (!key_len) continue; key_str = PyString_AS_STRING(key); if (!memcmp(key_str, single_underscore, 1)) { if (key_len == 1 || (memcmp(key_str, double_underscore, 2))) continue; } Py_INCREF(key); PyList_Append(keys, key); Py_INCREF(value); PyList_Append(env, value); } } /* We could save more memory by sorting the keys. */ PyObject *keys_tuple; PyObject **p, **q; size = Py_SIZE(keys); keys_tuple = PyTuple_New(size); if (keys_tuple == NULL) return NULL; p = ((PyTupleObject *)keys_tuple)->ob_item; q = ((PyListObject *)keys)->ob_item; while (--size >= 0) { Py_INCREF(*q); *p = *q; p++; q++; } long hash; long id; hash = PyObject_Hash(keys_tuple); if (hash == -1) { PyErr_SetString(PyExc_ValueError, "Cannot hash the environ keys."); return NULL; } environ = (PyDictObject *)_key2id_store; entries = (environ->ma_lookup)(environ, keys_tuple, hash); if ((entries == NULL) || (entries->me_value == NULL)) { id = _id_counter; _id_counter++; value = PyLong_FromLong(id); if (value == NULL) return NULL; PyDict_SetItem(_key2id_store, keys_tuple, value); PyDict_SetItem(_id2key_store, value, keys_tuple); } else { id = PyLong_AsLong(entries->me_value); if (id == -1) return NULL; } CapObject *self; self = (CapObject *)type->tp_alloc(type, 0); if (self != NULL) { self->id = id; self->env = env; self->__weakref__ = NULL; } return (PyObject *)self; }