+2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
+
+ * py-record-btrace.c (btpy_insn_new): Removed.
+ (btpy_insn_or_gap_new): New function.
+ (btpy_insn_error): Removed.
+ (btpy_insn_sal, btpy_insn_pc, btpy_insn_size, btpy_insn_is_speculative,
+ btpy_insn_data, btpy_insn_decode): Remove code path for gaps.
+ (recpy_bt_replay_position, recpy_bt_begin, recpy_bt_end): Call
+ btpy_insn_or_gap_new instead of btpy_insn_new.
+ (btpy_insn_getset): Remove btpy_insn_error.
+ * py-record.c (recpy_gap_type): New static object.
+ (recpy_gap_object): New typedef.
+ (recpy_gap_new, recpy_gap_number, recpy_gap_reason_code,
+ recpy_gap_reason_string): New function.
+ (recpy_gap_getset): New static object.
+ (gdbpy_initialize_record): Initialize gdb.RecordGap type.
+ * py-record.h (recpy_gap_new): New export.
+
2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
* python/py-record.c (recpy_ptid): Remove.
+2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
+
+ * python.texi (Recording in Python): Add documentation for
+ gdb.RecordGap and remove documentation of special cases for
+ gdb.BtraceInstruction.
+
2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
* python.texi (Recording in Python): Remove Record.ptid defvar.
(@pxref{Process Record and Replay}).
@end defvar
-@defvar BtraceInstruction.error
-An integer identifying the error code for gaps in the history.
-@code{None} for regular instructions.
-@end defvar
-
@defvar BtraceInstruction.sal
A @code{gdb.Symtab_and_line} object representing the associated symtab
-and line of this instruction. May be @code{None} if the instruction
-is a gap.
+and line of this instruction. May be @code{None} if no debug information is
+available.
@end defvar
@defvar BtraceInstruction.pc
-An integer representing this instruction's address. May be @code{None}
-if the instruction is a gap or the debug symbols could not be read.
+An integer representing this instruction's address.
@end defvar
@defvar BtraceInstruction.data
-A buffer with the raw instruction data. May be @code{None} if the
-instruction is a gap. In Python 3, the return value is a @code{memoryview}
-object.
+A buffer with the raw instruction data. In Python 3, the return value is a
+@code{memoryview} object.
@end defvar
@defvar BtraceInstruction.decoded
-A human readable string with the disassembled instruction. Contains the
-error message for gaps.
+A human readable string with the disassembled instruction.
@end defvar
@defvar BtraceInstruction.size
-The size of the instruction in bytes. Will be @code{None} if the
-instruction is a gap.
+The size of the instruction in bytes.
@end defvar
@defvar BtraceInstruction.is_speculative
A boolean indicating whether the instruction was executed
-speculatively. Will be @code{None} for gaps.
+speculatively.
+@end defvar
+
+If an error occured during recording or decoding a recording, this error is
+represented by a @code{gdb.RecordGap} object in the instruction list. It has
+the following attributes:
+
+@defvar RecordGap.number
+An integer identifying this gap. @code{number} corresponds to the numbers seen
+in @code{record instruction-history} (@pxref{Process Record and Replay}).
+@end defvar
+
+@defvar RecordGap.error_code
+A numerical representation of the reason for the gap. The value is specific to
+the current recording method.
+@end defvar
+
+@defvar RecordGap.error_string
+A human readable string with the reason for the gap.
@end defvar
The attributes and methods of function call objects depend on the
@end defvar
@defvar BtraceFunctionCall.instructions
-A list of @code{gdb.BtraceInstruction} objects associated with this function
-call.
+A list of @code{gdb.BtraceInstruction} or @code{gdb.RecordGap} objects
+associated with this function call.
@end defvar
@defvar BtraceFunctionCall.up
return (PyObject *) obj;
}
-/* Create a new gdb.BtraceInstruction object. */
+/* Looks at the recorded item with the number NUMBER and create a
+ gdb.BtraceInstruction or gdb.RecordGap object for it accordingly. */
static PyObject *
-btpy_insn_new (ptid_t ptid, Py_ssize_t number)
+btpy_insn_or_gap_new (const thread_info *tinfo, Py_ssize_t number)
{
- return btpy_new (ptid, number, &btpy_insn_type);
+ btrace_insn_iterator iter;
+ int err_code;
+
+ btrace_find_insn_by_number (&iter, &tinfo->btrace, number);
+ err_code = btrace_insn_get_error (&iter);
+
+ if (err_code != 0)
+ {
+ const btrace_config *config;
+ const char *err_string;
+
+ config = btrace_conf (&tinfo->btrace);
+ err_string = btrace_decode_error (config->format, err_code);
+
+ return recpy_gap_new (err_code, err_string, number);
+ }
+
+ return btpy_new (tinfo->ptid, number, &btpy_insn_type);
}
/* Create a new gdb.BtraceFunctionCall object. */
return obj->number;
}
-/* Implementation of BtraceInstruction.error [int]. Returns the
- error code for gaps. */
-
-static PyObject *
-btpy_insn_error (PyObject *self, void *closure)
-{
- const btpy_object * const obj = (btpy_object *) self;
- struct btrace_insn_iterator iter;
- int error;
-
- BTPY_REQUIRE_VALID_INSN (obj, iter);
-
- error = btrace_insn_get_error (&iter);
-
- if (error == 0)
- Py_RETURN_NONE;
-
- return PyInt_FromLong (error);
-}
-
/* Implementation of BtraceInstruction.sal [gdb.Symtab_and_line].
Return the SAL associated with this instruction. */
insn = btrace_insn_get (&iter);
if (insn == NULL)
- Py_RETURN_NONE;
+ return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
TRY
{
insn = btrace_insn_get (&iter);
if (insn == NULL)
- Py_RETURN_NONE;
+ return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
return gdb_py_long_from_ulongest (insn->pc);
}
insn = btrace_insn_get (&iter);
if (insn == NULL)
- Py_RETURN_NONE;
+ return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
return PyInt_FromLong (insn->size);
}
insn = btrace_insn_get (&iter);
if (insn == NULL)
- Py_RETURN_NONE;
+ return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
if (insn->flags & BTRACE_INSN_FLAG_SPECULATIVE)
Py_RETURN_TRUE;
insn = btrace_insn_get (&iter);
if (insn == NULL)
- Py_RETURN_NONE;
+ return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
TRY
{
insn = btrace_insn_get (&iter);
if (insn == NULL)
- {
- int error_code = btrace_insn_get_error (&iter);
- const struct btrace_config *config;
-
- config = btrace_conf (&find_thread_ptid (obj->ptid)->btrace);
- return PyBytes_FromString (btrace_decode_error (config->format,
- error_code));
- }
+ return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
TRY
{
if (tinfo->btrace.replay == NULL)
Py_RETURN_NONE;
- return btpy_insn_new (record->ptid,
- btrace_insn_number (tinfo->btrace.replay));
+ return btpy_insn_or_gap_new (tinfo,
+ btrace_insn_number (tinfo->btrace.replay));
}
/* Implementation of
Py_RETURN_NONE;
btrace_insn_begin (&iterator, &tinfo->btrace);
- return btpy_insn_new (record->ptid, btrace_insn_number (&iterator));
+ return btpy_insn_or_gap_new (tinfo, btrace_insn_number (&iterator));
}
/* Implementation of
Py_RETURN_NONE;
btrace_insn_end (&iterator, &tinfo->btrace);
- return btpy_insn_new (record->ptid, btrace_insn_number (&iterator));
+ return btpy_insn_or_gap_new (tinfo, btrace_insn_number (&iterator));
}
/* Implementation of
struct gdb_PyGetSetDef btpy_insn_getset[] =
{
{ "number", btpy_number, NULL, "instruction number", NULL},
- { "error", btpy_insn_error, NULL, "error number for gaps", 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},
PyVarObject_HEAD_INIT (NULL, 0)
};
+/* Python RecordGap type. */
+
+PyTypeObject recpy_gap_type = {
+ PyVarObject_HEAD_INIT (NULL, 0)
+};
+
+/* Python RecordGap object. */
+typedef struct
+{
+ PyObject_HEAD
+
+ /* Reason code. */
+ int reason_code;
+
+ /* Reason message. */
+ const char *reason_string;
+
+ /* Element number. */
+ Py_ssize_t number;
+} recpy_gap_object;
+
/* Implementation of record.method. */
static PyObject *
return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
}
+/* Create a new gdb.RecordGap object. */
+
+PyObject *
+recpy_gap_new (int reason_code, const char *reason_string, Py_ssize_t number)
+{
+ recpy_gap_object * const obj = PyObject_New (recpy_gap_object,
+ &recpy_gap_type);
+
+ if (obj == NULL)
+ return NULL;
+
+ obj->reason_code = reason_code;
+ obj->reason_string = reason_string;
+ obj->number = number;
+
+ return (PyObject *) obj;
+}
+
+/* Implementation of RecordGap.number [int]. */
+
+static PyObject *
+recpy_gap_number (PyObject *self, void *closure)
+{
+ const recpy_gap_object * const obj = (const recpy_gap_object *) self;
+
+ return PyInt_FromSsize_t (obj->number);
+}
+
+/* Implementation of RecordGap.error_code [int]. */
+
+static PyObject *
+recpy_gap_reason_code (PyObject *self, void *closure)
+{
+ const recpy_gap_object * const obj = (const recpy_gap_object *) self;
+
+ return PyInt_FromLong (obj->reason_code);
+}
+
+/* Implementation of RecordGap.error_string [str]. */
+
+static PyObject *
+recpy_gap_reason_string (PyObject *self, void *closure)
+{
+ const recpy_gap_object * const obj = (const recpy_gap_object *) self;
+
+ return PyString_FromString (obj->reason_string);
+}
+
/* Record method list. */
static PyMethodDef recpy_record_methods[] = {
{ NULL }
};
+/* RecordGap member list. */
+
+static gdb_PyGetSetDef recpy_gap_getset[] = {
+ { "number", recpy_gap_number, NULL, "element number", NULL},
+ { "reason_code", recpy_gap_reason_code, NULL, "reason code", NULL},
+ { "reason_string", recpy_gap_reason_string, NULL, "reason string", NULL},
+ { NULL }
+};
+
/* Sets up the record API in the gdb module. */
int
recpy_record_type.tp_methods = recpy_record_methods;
recpy_record_type.tp_getset = recpy_record_getset;
- return PyType_Ready (&recpy_record_type);
+ 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_name = "gdb.RecordGap";
+ recpy_gap_type.tp_doc = "GDB recorded gap object";
+ recpy_gap_type.tp_getset = recpy_gap_getset;
+
+ if (PyType_Ready (&recpy_record_type) < 0
+ || PyType_Ready (&recpy_gap_type) < 0)
+ return -1;
+ else
+ return 0;
}
/* Implementation of gdb.start_recording (method) -> gdb.Record. */
enum record_method method;
} recpy_record_object;
+/* Create a new gdb.RecordGap object. */
+extern PyObject *recpy_gap_new (int reason_code, const char *reason_string,
+ Py_ssize_t number);
+
#endif /* GDB_PY_RECORD_H */
+2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
+
+ * gdb.python/py-record-btrace.exp: Remove test for
+ gdb.BtraceInstruction.error.
+
2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
* gdb.python/py-record-btrace.exp: Remove Record.ptid test.
with_test_prefix "instruction " {
gdb_test "python print(i.number)" "1"
- gdb_test "python print(i.error)" "None"
gdb_test "python print(i.sal)" "symbol and line for .*"
gdb_test "python print(i.pc)" "$decimal"
if { $gdb_py_is_py3k == 0 } {