#endif
-#define BTPY_REQUIRE_VALID_INSN(obj, iter) \
- do { \
- struct thread_info *tinfo = find_thread_ptid (obj->ptid); \
- if (tinfo == NULL || btrace_is_empty (tinfo)) \
- return PyErr_Format (gdbpy_gdb_error, _("Empty branch trace.")); \
- if (0 == btrace_find_insn_by_number (&iter, &tinfo->btrace, \
- obj->number)) \
- return PyErr_Format (gdbpy_gdb_error, _("No such instruction.")); \
- } while (0)
-
#define BTPY_REQUIRE_VALID_CALL(obj, iter) \
do { \
struct thread_info *tinfo = find_thread_ptid (obj->ptid); \
return PyErr_Format (gdbpy_gdb_error, _("No such call segment."));\
} while (0)
-/* This can either be a btrace instruction or a function call segment,
- depending on the chosen type. */
-
-typedef struct {
- PyObject_HEAD
-
- /* The thread this object belongs to. */
- ptid_t ptid;
-
- /* Instruction number or function call segment number, depending on the type
- of this object. */
- Py_ssize_t number;
-} btpy_object;
-
/* Python object for btrace record lists. */
typedef struct {
/* Stride size. */
Py_ssize_t step;
- /* Either &BTPY_CALL_TYPE or &BTPY_INSN_TYPE. */
+ /* Either &BTPY_CALL_TYPE or &RECPY_INSN_TYPE. */
PyTypeObject* element_type;
} btpy_list_object;
-/* Python type for btrace instructions. */
-
-static PyTypeObject btpy_insn_type = {
- PyVarObject_HEAD_INIT (NULL, 0)
-};
-
/* Python type for btrace function-calls. */
static PyTypeObject btpy_call_type = {
PyVarObject_HEAD_INIT (NULL, 0)
};
-/* Create a new gdb.BtraceInstruction or gdb.BtraceFunctionCall object,
- depending on TYPE. */
+/* Returns either a btrace_insn for the given Python gdb.RecordInstruction
+ object or sets an appropriate Python exception and returns NULL. */
-static PyObject *
-btpy_new (ptid_t ptid, Py_ssize_t number, PyTypeObject* type)
+static const btrace_insn *
+btrace_insn_from_recpy_insn (const PyObject * const pyobject)
{
- btpy_object * const obj = PyObject_New (btpy_object, type);
+ const btrace_insn *insn;
+ const recpy_element_object *obj;
+ thread_info *tinfo;
+ btrace_insn_iterator iter;
- if (obj == NULL)
- return NULL;
+ if (Py_TYPE (pyobject) != &recpy_insn_type)
+ {
+ PyErr_Format (gdbpy_gdb_error, _("Must be gdb.RecordInstruction"));
+ return NULL;
+ }
- obj->ptid = ptid;
- obj->number = number;
+ obj = (const recpy_element_object *) pyobject;
+ tinfo = find_thread_ptid (obj->ptid);
- return (PyObject *) obj;
+ if (tinfo == NULL || btrace_is_empty (tinfo))
+ {
+ PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
+ return NULL;
+ }
+
+ if (btrace_find_insn_by_number (&iter, &tinfo->btrace, obj->number) == 0)
+ {
+ PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
+ return NULL;
+ }
+
+ insn = btrace_insn_get (&iter);
+ if (insn == NULL)
+ {
+ PyErr_Format (gdbpy_gdb_error, _("Not a valid instruction."));
+ return NULL;
+ }
+
+ return insn;
}
/* Looks at the recorded item with the number NUMBER and create a
- gdb.BtraceInstruction or gdb.RecordGap object for it accordingly. */
+ gdb.RecordInstruction or gdb.RecordGap object for it accordingly. */
static PyObject *
btpy_insn_or_gap_new (const thread_info *tinfo, Py_ssize_t number)
return recpy_gap_new (err_code, err_string, number);
}
- return btpy_new (tinfo->ptid, number, &btpy_insn_type);
+ return recpy_insn_new (tinfo->ptid, RECORD_METHOD_BTRACE, number);
}
/* Create a new gdb.BtraceFunctionCall object. */
static PyObject *
btpy_call_new (ptid_t ptid, Py_ssize_t number)
{
- return btpy_new (ptid, number, &btpy_call_type);
+ recpy_element_object * const obj = PyObject_New (recpy_element_object,
+ &btpy_call_type);
+
+ if (obj == NULL)
+ return NULL;
+
+ obj->ptid = ptid;
+ obj->method = RECORD_METHOD_BTRACE;
+ obj->number = number;
+
+ return (PyObject *) obj;
}
/* Create a new gdb.BtraceList object. */
static PyObject *
btpy_number (PyObject *self, void *closure)
{
- const btpy_object * const obj = (btpy_object *) self;
+ const recpy_element_object * const obj = (const recpy_element_object *) self;
return PyInt_FromSsize_t (obj->number);
}
static Py_hash_t
btpy_hash (PyObject *self)
{
- const btpy_object * const obj = (btpy_object *) self;
+ const recpy_element_object * const obj = (const recpy_element_object *) self;
return obj->number;
}
-/* Implementation of BtraceInstruction.sal [gdb.Symtab_and_line].
- Return the SAL associated with this instruction. */
+/* Implementation of RecordInstruction.sal [gdb.Symtab_and_line] for btrace.
+ Returns the SAL associated with this instruction. */
-static PyObject *
-btpy_insn_sal (PyObject *self, void *closure)
+PyObject *
+recpy_bt_insn_sal (PyObject *self, void *closure)
{
- const btpy_object * const obj = (btpy_object *) self;
- const struct btrace_insn *insn;
- struct btrace_insn_iterator iter;
+ const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
PyObject *result = NULL;
- BTPY_REQUIRE_VALID_INSN (obj, iter);
-
- insn = btrace_insn_get (&iter);
if (insn == NULL)
- return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
+ return NULL;
TRY
{
return result;
}
-/* Implementation of BtraceInstruction.pc [int]. Returns
- the instruction address. */
+/* Implementation of RecordInstruction.pc [int] for btrace.
+ Returns the instruction address. */
-static PyObject *
-btpy_insn_pc (PyObject *self, void *closure)
+PyObject *
+recpy_bt_insn_pc (PyObject *self, void *closure)
{
- const btpy_object * const obj = (btpy_object *) self;
- const struct btrace_insn *insn;
- struct btrace_insn_iterator iter;
-
- BTPY_REQUIRE_VALID_INSN (obj, iter);
+ const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
- insn = btrace_insn_get (&iter);
if (insn == NULL)
- return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
+ return NULL;
return gdb_py_long_from_ulongest (insn->pc);
}
-/* Implementation of BtraceInstruction.size [int]. Returns
- the instruction size. */
+/* Implementation of RecordInstruction.size [int] for btrace.
+ Returns the instruction size. */
-static PyObject *
-btpy_insn_size (PyObject *self, void *closure)
+PyObject *
+recpy_bt_insn_size (PyObject *self, void *closure)
{
- const btpy_object * const obj = (btpy_object *) self;
- const struct btrace_insn *insn;
- struct btrace_insn_iterator iter;
+ const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
- BTPY_REQUIRE_VALID_INSN (obj, iter);
-
- insn = btrace_insn_get (&iter);
if (insn == NULL)
- return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
+ return NULL;
return PyInt_FromLong (insn->size);
}
-/* Implementation of BtraceInstruction.is_speculative [bool].
+/* Implementation of RecordInstruction.is_speculative [bool] for btrace.
Returns if this instruction was executed speculatively. */
-static PyObject *
-btpy_insn_is_speculative (PyObject *self, void *closure)
+PyObject *
+recpy_bt_insn_is_speculative (PyObject *self, void *closure)
{
- const btpy_object * const obj = (btpy_object *) self;
- const struct btrace_insn *insn;
- struct btrace_insn_iterator iter;
+ const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
- BTPY_REQUIRE_VALID_INSN (obj, iter);
-
- insn = btrace_insn_get (&iter);
if (insn == NULL)
- return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
+ return NULL;
if (insn->flags & BTRACE_INSN_FLAG_SPECULATIVE)
Py_RETURN_TRUE;
Py_RETURN_FALSE;
}
-/* Implementation of BtraceInstruction.data [buffer].
+/* Implementation of RecordInstruction.data [buffer] for btrace.
Returns raw instruction data. */
-static PyObject *
-btpy_insn_data (PyObject *self, void *closure)
+PyObject *
+recpy_bt_insn_data (PyObject *self, void *closure)
{
- const btpy_object * const obj = (btpy_object *) self;
- const struct btrace_insn *insn;
- struct btrace_insn_iterator iter;
+ const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
gdb_byte *buffer = NULL;
PyObject *object;
- BTPY_REQUIRE_VALID_INSN (obj, iter);
-
- insn = btrace_insn_get (&iter);
if (insn == NULL)
- return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
+ return NULL;
TRY
{
}
-/* Implementation of BtraceInstruction.decode [str]. Returns
- the instruction as human readable string. */
+/* Implementation of RecordInstruction.decoded [str] for btrace.
+ Returns the instruction as human readable string. */
-static PyObject *
-btpy_insn_decode (PyObject *self, void *closure)
+PyObject *
+recpy_bt_insn_decoded (PyObject *self, void *closure)
{
- const btpy_object * const obj = (btpy_object *) self;
- const struct btrace_insn *insn;
- struct btrace_insn_iterator iter;
+ const btrace_insn * const insn = btrace_insn_from_recpy_insn (self);
string_file strfile;
- BTPY_REQUIRE_VALID_INSN (obj, iter);
-
- insn = btrace_insn_get (&iter);
if (insn == NULL)
- return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
+ return NULL;
TRY
{
static PyObject *
btpy_call_level (PyObject *self, void *closure)
{
- const btpy_object * const obj = (btpy_object *) self;
+ const recpy_element_object * const obj = (const recpy_element_object *) self;
const struct btrace_function *func;
struct btrace_call_iterator iter;
static PyObject *
btpy_call_symbol (PyObject *self, void *closure)
{
- const btpy_object * const obj = (btpy_object *) self;
+ const recpy_element_object * const obj = (const recpy_element_object *) self;
const struct btrace_function *func;
struct btrace_call_iterator iter;
static PyObject *
btpy_call_instructions (PyObject *self, void *closure)
{
- const btpy_object * const obj = (btpy_object *) self;
+ const recpy_element_object * const obj = (const recpy_element_object *) self;
const struct btrace_function *func;
struct btrace_call_iterator iter;
unsigned int len;
len = 1;
return btpy_list_new (obj->ptid, func->insn_offset, func->insn_offset + len,
- 1, &btpy_insn_type);
+ 1, &recpy_insn_type);
}
/* Implementation of BtraceFunctionCall.up [gdb.BtraceRecordCall].
static PyObject *
btpy_call_up (PyObject *self, void *closure)
{
- const btpy_object * const obj = (btpy_object *) self;
+ const recpy_element_object * const obj = (const recpy_element_object *) self;
const struct btrace_function *func;
struct btrace_call_iterator iter;
static PyObject *
btpy_call_prev_sibling (PyObject *self, void *closure)
{
- const btpy_object * const obj = (btpy_object *) self;
+ const recpy_element_object * const obj = (const recpy_element_object *) self;
const struct btrace_function *func;
struct btrace_call_iterator iter;
static PyObject *
btpy_call_next_sibling (PyObject *self, void *closure)
{
- const btpy_object * const obj = (btpy_object *) self;
+ const recpy_element_object * const obj = (const recpy_element_object *) self;
const struct btrace_function *func;
struct btrace_call_iterator iter;
static PyObject *
btpy_richcompare (PyObject *self, PyObject *other, int op)
{
- const btpy_object * const obj1 = (btpy_object *) self;
- const btpy_object * const obj2 = (btpy_object *) other;
+ const recpy_element_object * const obj1 = (recpy_element_object *) self;
+ const recpy_element_object * const obj2 = (recpy_element_object *) other;
if (Py_TYPE (self) != Py_TYPE (other))
{
{
const btpy_list_object * const obj = (btpy_list_object *) self;
struct thread_info * const tinfo = find_thread_ptid (obj->ptid);
+ Py_ssize_t number;
if (index < 0 || index >= btpy_list_length (self))
return PyErr_Format (PyExc_IndexError, _("Index out of range: %zd."),
index);
- return btpy_new (obj->ptid, obj->first + (obj->step * index),
- obj->element_type);
+ number = obj->first + (obj->step * index);
+
+ if (obj->element_type == &recpy_insn_type)
+ return recpy_insn_new (obj->ptid, RECORD_METHOD_BTRACE, number);
+ else
+ return btpy_call_new (obj->ptid, number);
}
/* Implementation of BtraceList.__getitem__ (self, slice) -> BtraceList. */
btpy_list_position (PyObject *self, PyObject *value)
{
const btpy_list_object * const list_obj = (btpy_list_object *) self;
- const btpy_object * const obj = (btpy_object *) value;
+ const recpy_element_object * const obj = (const recpy_element_object *) value;
Py_ssize_t index = obj->number;
if (list_obj->element_type != Py_TYPE (value))
btrace_insn_end (&iterator, &tinfo->btrace);
last = btrace_insn_number (&iterator);
- return btpy_list_new (record->ptid, first, last, 1, &btpy_insn_type);
+ return btpy_list_new (record->ptid, first, last, 1, &recpy_insn_type);
}
/* Implementation of
{
const recpy_record_object * const record = (recpy_record_object *) self;
struct thread_info * const tinfo = find_thread_ptid (record->ptid);
- const btpy_object *obj;
+ const recpy_element_object *obj;
if (tinfo == NULL || btrace_is_empty (tinfo))
return PyErr_Format (gdbpy_gdb_error, _("Empty branch trace."));
if (!PyArg_ParseTuple (args, "O", &obj))
return NULL;
- if (Py_TYPE (obj) != &btpy_insn_type)
+ if (Py_TYPE (obj) != &recpy_insn_type)
return PyErr_Format (PyExc_TypeError, _("Argument must be instruction."));
TRY
Py_RETURN_NONE;
}
-/* BtraceInstruction members. */
-
-struct gdb_PyGetSetDef btpy_insn_getset[] =
-{
- { "number", btpy_number, NULL, "instruction number", NULL},
- { "sal", btpy_insn_sal, NULL, "associated symbol and line", NULL},
- { "pc", btpy_insn_pc, NULL, "instruction address", NULL},
- { "data", btpy_insn_data, NULL, "raw instruction data", NULL},
- { "decoded", btpy_insn_decode, NULL, "decoded instruction or error message \
-if the instruction is a gap", NULL},
- { "size", btpy_insn_size, NULL, "instruction size in byte", NULL},
- { "is_speculative", btpy_insn_is_speculative, NULL, "if the instruction was \
-executed speculatively", NULL},
- {NULL}
-};
-
/* BtraceFunctionCall members. */
static gdb_PyGetSetDef btpy_call_getset[] =
int
gdbpy_initialize_btrace (void)
{
- btpy_insn_type.tp_new = PyType_GenericNew;
- btpy_insn_type.tp_flags = Py_TPFLAGS_DEFAULT;
- btpy_insn_type.tp_basicsize = sizeof (btpy_object);
- btpy_insn_type.tp_name = "gdb.BtraceInstruction";
- btpy_insn_type.tp_doc = "GDB btrace instruction object";
- btpy_insn_type.tp_getset = btpy_insn_getset;
- btpy_insn_type.tp_richcompare = btpy_richcompare;
- btpy_insn_type.tp_hash = btpy_hash;
-
btpy_call_type.tp_new = PyType_GenericNew;
btpy_call_type.tp_flags = Py_TPFLAGS_DEFAULT;
- btpy_call_type.tp_basicsize = sizeof (btpy_object);
+ btpy_call_type.tp_basicsize = sizeof (recpy_element_object);
btpy_call_type.tp_name = "gdb.BtraceFunctionCall";
btpy_call_type.tp_doc = "GDB btrace call object";
btpy_call_type.tp_getset = btpy_call_getset;
btpy_list_mapping_methods.mp_subscript = btpy_list_slice;
- if (PyType_Ready (&btpy_insn_type) < 0
- || PyType_Ready (&btpy_call_type) < 0
+ if (PyType_Ready (&btpy_call_type) < 0
|| PyType_Ready (&btpy_list_type) < 0)
return -1;
else
PyVarObject_HEAD_INIT (NULL, 0)
};
+/* Python RecordInstruction type. */
+
+PyTypeObject recpy_insn_type = {
+ PyVarObject_HEAD_INIT (NULL, 0)
+};
+
/* Python RecordGap type. */
PyTypeObject recpy_gap_type = {
return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
}
+/* Create a new gdb.RecordInstruction object. */
+
+PyObject *
+recpy_insn_new (ptid_t ptid, enum record_method method, Py_ssize_t number)
+{
+ recpy_element_object * const obj = PyObject_New (recpy_element_object,
+ &recpy_insn_type);
+
+ if (obj == NULL)
+ return NULL;
+
+ obj->ptid = ptid;
+ obj->method = method;
+ obj->number = number;
+
+ return (PyObject *) obj;
+}
+
+/* Implementation of RecordInstruction.sal [gdb.Symtab_and_line]. */
+
+static PyObject *
+recpy_insn_sal (PyObject *self, void *closure)
+{
+ const recpy_element_object * const obj = (recpy_element_object *) self;
+
+ if (obj->method == RECORD_METHOD_BTRACE)
+ return recpy_bt_insn_sal (self, closure);
+
+ return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
+}
+
+/* Implementation of RecordInstruction.pc [int]. */
+
+static PyObject *
+recpy_insn_pc (PyObject *self, void *closure)
+{
+ const recpy_element_object * const obj = (recpy_element_object *) self;
+
+ if (obj->method == RECORD_METHOD_BTRACE)
+ return recpy_bt_insn_pc (self, closure);
+
+ return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
+}
+
+/* Implementation of RecordInstruction.data [buffer]. */
+
+static PyObject *
+recpy_insn_data (PyObject *self, void *closure)
+{
+ const recpy_element_object * const obj = (recpy_element_object *) self;
+
+ if (obj->method == RECORD_METHOD_BTRACE)
+ return recpy_bt_insn_data (self, closure);
+
+ return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
+}
+
+/* Implementation of RecordInstruction.decoded [str]. */
+
+static PyObject *
+recpy_insn_decoded (PyObject *self, void *closure)
+{
+ const recpy_element_object * const obj = (recpy_element_object *) self;
+
+ if (obj->method == RECORD_METHOD_BTRACE)
+ return recpy_bt_insn_decoded (self, closure);
+
+ return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
+}
+
+/* Implementation of RecordInstruction.size [int]. */
+
+static PyObject *
+recpy_insn_size (PyObject *self, void *closure)
+{
+ const recpy_element_object * const obj = (recpy_element_object *) self;
+
+ if (obj->method == RECORD_METHOD_BTRACE)
+ return recpy_bt_insn_size (self, closure);
+
+ return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
+}
+
+/* Implementation of RecordInstruction.is_speculative [bool]. */
+
+static PyObject *
+recpy_insn_is_speculative (PyObject *self, void *closure)
+{
+ const recpy_element_object * const obj = (recpy_element_object *) self;
+
+ if (obj->method == RECORD_METHOD_BTRACE)
+ return recpy_bt_insn_is_speculative (self, closure);
+
+ return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
+}
+
+/* Implementation of RecordInstruction.number [int]. */
+
+static PyObject *
+recpy_element_number (PyObject *self, void* closure)
+{
+ const recpy_element_object * const obj = (recpy_element_object *) self;
+
+ return PyInt_FromSsize_t (obj->number);
+}
+
+/* Implementation of RecordInstruction.__hash__ [int]. */
+static Py_hash_t
+recpy_element_hash (PyObject *self)
+{
+ const recpy_element_object * const obj = (recpy_element_object *) self;
+
+ return obj->number;
+}
+
+/* Implementation of operator == and != of RecordInstruction. */
+
+static PyObject *
+recpy_element_richcompare (PyObject *self, PyObject *other, int op)
+{
+ const recpy_element_object * const obj1 = (recpy_element_object *) self;
+ const recpy_element_object * const obj2 = (recpy_element_object *) other;
+
+ if (Py_TYPE (self) != Py_TYPE (other))
+ {
+ Py_INCREF (Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ switch (op)
+ {
+ case Py_EQ:
+ if (ptid_equal (obj1->ptid, obj2->ptid)
+ && obj1->method == obj2->method
+ && obj1->number == obj2->number)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+
+ case Py_NE:
+ if (!ptid_equal (obj1->ptid, obj2->ptid)
+ || obj1->method != obj2->method
+ || obj1->number != obj2->number)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+
+ default:
+ break;
+ }
+
+ Py_INCREF (Py_NotImplemented);
+ return Py_NotImplemented;
+}
+
/* Create a new gdb.RecordGap object. */
PyObject *
{ NULL }
};
+/* RecordInstruction member list. */
+
+static gdb_PyGetSetDef recpy_insn_getset[] = {
+ { "number", recpy_element_number, NULL, "instruction number", NULL},
+ { "sal", recpy_insn_sal, NULL, "associated symbol and line", NULL},
+ { "pc", recpy_insn_pc, NULL, "instruction address", NULL},
+ { "data", recpy_insn_data, NULL, "raw instruction data", NULL},
+ { "decoded", recpy_insn_decoded, NULL, "decoded instruction", NULL},
+ { "size", recpy_insn_size, NULL, "instruction size in byte", NULL},
+ { "is_speculative", recpy_insn_is_speculative, NULL, "if the instruction was \
+ executed speculatively", NULL},
+ { NULL }
+};
+
/* RecordGap member list. */
static gdb_PyGetSetDef recpy_gap_getset[] = {
recpy_record_type.tp_methods = recpy_record_methods;
recpy_record_type.tp_getset = recpy_record_getset;
+ recpy_insn_type.tp_new = PyType_GenericNew;
+ recpy_insn_type.tp_flags = Py_TPFLAGS_DEFAULT;
+ recpy_insn_type.tp_basicsize = sizeof (recpy_element_object);
+ recpy_insn_type.tp_name = "gdb.RecordInstruction";
+ recpy_insn_type.tp_doc = "GDB recorded instruction object";
+ recpy_insn_type.tp_getset = recpy_insn_getset;
+ recpy_insn_type.tp_richcompare = recpy_element_richcompare;
+ recpy_insn_type.tp_hash = recpy_element_hash;
+
recpy_gap_type.tp_new = PyType_GenericNew;
recpy_gap_type.tp_flags = Py_TPFLAGS_DEFAULT;
recpy_gap_type.tp_basicsize = sizeof (recpy_gap_object);
recpy_gap_type.tp_getset = recpy_gap_getset;
if (PyType_Ready (&recpy_record_type) < 0
+ || PyType_Ready (&recpy_insn_type) < 0
|| PyType_Ready (&recpy_gap_type) < 0)
return -1;
else