Class wrapping a gdb.Value that's either a (PyObject*) within the inferior process, or some subclass pointer e.g. (PyBytesObject*) There will be a subclass for every refined PyObject type that we care about. Note that at every stage the underlying pointer could be NULL, point
| 158 | |
| 159 | |
| 160 | class PyObjectPtr(object): |
| 161 | """ |
| 162 | Class wrapping a gdb.Value that's either a (PyObject*) within the |
| 163 | inferior process, or some subclass pointer e.g. (PyBytesObject*) |
| 164 | |
| 165 | There will be a subclass for every refined PyObject type that we care |
| 166 | about. |
| 167 | |
| 168 | Note that at every stage the underlying pointer could be NULL, point |
| 169 | to corrupt data, etc; this is the debugger, after all. |
| 170 | """ |
| 171 | _typename = 'PyObject' |
| 172 | |
| 173 | def __init__(self, gdbval, cast_to=None): |
| 174 | # Clear the tagged pointer |
| 175 | if gdbval.type.name == '_PyStackRef': |
| 176 | if cast_to is None: |
| 177 | cast_to = gdb.lookup_type('PyObject').pointer() |
| 178 | self._gdbval = _PyStackRef_AsPyObjectBorrow(gdbval).cast(cast_to) |
| 179 | elif cast_to: |
| 180 | self._gdbval = gdbval.cast(cast_to) |
| 181 | else: |
| 182 | self._gdbval = gdbval |
| 183 | |
| 184 | def field(self, name): |
| 185 | ''' |
| 186 | Get the gdb.Value for the given field within the PyObject. |
| 187 | |
| 188 | Various libpython types are defined using the "PyObject_HEAD" and |
| 189 | "PyObject_VAR_HEAD" macros. |
| 190 | |
| 191 | In Python, this is defined as an embedded PyVarObject type thus: |
| 192 | PyVarObject ob_base; |
| 193 | so that the "ob_size" field is located insize the "ob_base" field, and |
| 194 | the "ob_type" is most easily accessed by casting back to a (PyObject*). |
| 195 | ''' |
| 196 | if self.is_null(): |
| 197 | raise NullPyObjectPtr(self) |
| 198 | |
| 199 | if name == 'ob_type': |
| 200 | pyo_ptr = self._gdbval.cast(PyObjectPtr.get_gdb_type()) |
| 201 | return pyo_ptr.dereference()[name] |
| 202 | |
| 203 | if name == 'ob_size': |
| 204 | pyo_ptr = self._gdbval.cast(PyVarObjectPtr.get_gdb_type()) |
| 205 | return pyo_ptr.dereference()[name] |
| 206 | |
| 207 | # General case: look it up inside the object: |
| 208 | return self._gdbval.dereference()[name] |
| 209 | |
| 210 | def pyop_field(self, name): |
| 211 | ''' |
| 212 | Get a PyObjectPtr for the given PyObject* field within this PyObject. |
| 213 | ''' |
| 214 | return PyObjectPtr.from_pyobject_ptr(self.field(name)) |
| 215 | |
| 216 | def write_field_repr(self, name, out, visited): |
| 217 | ''' |
no outgoing calls
no test coverage detected
searching dependent graphs…