mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-03 13:23:00 +08:00
Python: Introduce gdb.RecordGap class
As discussed here: https://sourceware.org/ml/gdb-patches/2017-04/msg00157.html A gap is not an instruction and it should not pretend to be one. gdb.Record.instruction_history is now a list of gdb.RecordInstruction and gdb.RecordGap objects. This allows the user to deal with Gaps in the record in a more sane way.
This commit is contained in:
@ -1,3 +1,21 @@
|
|||||||
|
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>
|
2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
|
||||||
|
|
||||||
* python/py-record.c (recpy_ptid): Remove.
|
* python/py-record.c (recpy_ptid): Remove.
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
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>
|
2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
|
||||||
|
|
||||||
* python.texi (Recording in Python): Remove Record.ptid defvar.
|
* python.texi (Recording in Python): Remove Record.ptid defvar.
|
||||||
|
@ -3160,41 +3160,50 @@ the numbers seen in @code{record instruction-history}
|
|||||||
(@pxref{Process Record and Replay}).
|
(@pxref{Process Record and Replay}).
|
||||||
@end defvar
|
@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
|
@defvar BtraceInstruction.sal
|
||||||
A @code{gdb.Symtab_and_line} object representing the associated symtab
|
A @code{gdb.Symtab_and_line} object representing the associated symtab
|
||||||
and line of this instruction. May be @code{None} if the instruction
|
and line of this instruction. May be @code{None} if no debug information is
|
||||||
is a gap.
|
available.
|
||||||
@end defvar
|
@end defvar
|
||||||
|
|
||||||
@defvar BtraceInstruction.pc
|
@defvar BtraceInstruction.pc
|
||||||
An integer representing this instruction's address. May be @code{None}
|
An integer representing this instruction's address.
|
||||||
if the instruction is a gap or the debug symbols could not be read.
|
|
||||||
@end defvar
|
@end defvar
|
||||||
|
|
||||||
@defvar BtraceInstruction.data
|
@defvar BtraceInstruction.data
|
||||||
A buffer with the raw instruction data. May be @code{None} if the
|
A buffer with the raw instruction data. In Python 3, the return value is a
|
||||||
instruction is a gap. In Python 3, the return value is a @code{memoryview}
|
@code{memoryview} object.
|
||||||
object.
|
|
||||||
@end defvar
|
@end defvar
|
||||||
|
|
||||||
@defvar BtraceInstruction.decoded
|
@defvar BtraceInstruction.decoded
|
||||||
A human readable string with the disassembled instruction. Contains the
|
A human readable string with the disassembled instruction.
|
||||||
error message for gaps.
|
|
||||||
@end defvar
|
@end defvar
|
||||||
|
|
||||||
@defvar BtraceInstruction.size
|
@defvar BtraceInstruction.size
|
||||||
The size of the instruction in bytes. Will be @code{None} if the
|
The size of the instruction in bytes.
|
||||||
instruction is a gap.
|
|
||||||
@end defvar
|
@end defvar
|
||||||
|
|
||||||
@defvar BtraceInstruction.is_speculative
|
@defvar BtraceInstruction.is_speculative
|
||||||
A boolean indicating whether the instruction was executed
|
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
|
@end defvar
|
||||||
|
|
||||||
The attributes and methods of function call objects depend on the
|
The attributes and methods of function call objects depend on the
|
||||||
@ -3221,8 +3230,8 @@ An integer representing the function call's stack level. May be
|
|||||||
@end defvar
|
@end defvar
|
||||||
|
|
||||||
@defvar BtraceFunctionCall.instructions
|
@defvar BtraceFunctionCall.instructions
|
||||||
A list of @code{gdb.BtraceInstruction} objects associated with this function
|
A list of @code{gdb.BtraceInstruction} or @code{gdb.RecordGap} objects
|
||||||
call.
|
associated with this function call.
|
||||||
@end defvar
|
@end defvar
|
||||||
|
|
||||||
@defvar BtraceFunctionCall.up
|
@defvar BtraceFunctionCall.up
|
||||||
|
@ -126,12 +126,30 @@ btpy_new (ptid_t ptid, Py_ssize_t number, PyTypeObject* type)
|
|||||||
return (PyObject *) obj;
|
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 *
|
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. */
|
/* Create a new gdb.BtraceFunctionCall object. */
|
||||||
@ -185,26 +203,6 @@ btpy_hash (PyObject *self)
|
|||||||
return obj->number;
|
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].
|
/* Implementation of BtraceInstruction.sal [gdb.Symtab_and_line].
|
||||||
Return the SAL associated with this instruction. */
|
Return the SAL associated with this instruction. */
|
||||||
|
|
||||||
@ -220,7 +218,7 @@ btpy_insn_sal (PyObject *self, void *closure)
|
|||||||
|
|
||||||
insn = btrace_insn_get (&iter);
|
insn = btrace_insn_get (&iter);
|
||||||
if (insn == NULL)
|
if (insn == NULL)
|
||||||
Py_RETURN_NONE;
|
return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
|
||||||
|
|
||||||
TRY
|
TRY
|
||||||
{
|
{
|
||||||
@ -249,7 +247,7 @@ btpy_insn_pc (PyObject *self, void *closure)
|
|||||||
|
|
||||||
insn = btrace_insn_get (&iter);
|
insn = btrace_insn_get (&iter);
|
||||||
if (insn == NULL)
|
if (insn == NULL)
|
||||||
Py_RETURN_NONE;
|
return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
|
||||||
|
|
||||||
return gdb_py_long_from_ulongest (insn->pc);
|
return gdb_py_long_from_ulongest (insn->pc);
|
||||||
}
|
}
|
||||||
@ -268,7 +266,7 @@ btpy_insn_size (PyObject *self, void *closure)
|
|||||||
|
|
||||||
insn = btrace_insn_get (&iter);
|
insn = btrace_insn_get (&iter);
|
||||||
if (insn == NULL)
|
if (insn == NULL)
|
||||||
Py_RETURN_NONE;
|
return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
|
||||||
|
|
||||||
return PyInt_FromLong (insn->size);
|
return PyInt_FromLong (insn->size);
|
||||||
}
|
}
|
||||||
@ -287,7 +285,7 @@ btpy_insn_is_speculative (PyObject *self, void *closure)
|
|||||||
|
|
||||||
insn = btrace_insn_get (&iter);
|
insn = btrace_insn_get (&iter);
|
||||||
if (insn == NULL)
|
if (insn == NULL)
|
||||||
Py_RETURN_NONE;
|
return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
|
||||||
|
|
||||||
if (insn->flags & BTRACE_INSN_FLAG_SPECULATIVE)
|
if (insn->flags & BTRACE_INSN_FLAG_SPECULATIVE)
|
||||||
Py_RETURN_TRUE;
|
Py_RETURN_TRUE;
|
||||||
@ -311,7 +309,7 @@ btpy_insn_data (PyObject *self, void *closure)
|
|||||||
|
|
||||||
insn = btrace_insn_get (&iter);
|
insn = btrace_insn_get (&iter);
|
||||||
if (insn == NULL)
|
if (insn == NULL)
|
||||||
Py_RETURN_NONE;
|
return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
|
||||||
|
|
||||||
TRY
|
TRY
|
||||||
{
|
{
|
||||||
@ -354,14 +352,7 @@ btpy_insn_decode (PyObject *self, void *closure)
|
|||||||
|
|
||||||
insn = btrace_insn_get (&iter);
|
insn = btrace_insn_get (&iter);
|
||||||
if (insn == NULL)
|
if (insn == NULL)
|
||||||
{
|
return PyErr_Format (gdbpy_gdb_error, _("No such instruction."));
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
TRY
|
TRY
|
||||||
{
|
{
|
||||||
@ -765,7 +756,7 @@ recpy_bt_replay_position (PyObject *self, void *closure)
|
|||||||
if (tinfo->btrace.replay == NULL)
|
if (tinfo->btrace.replay == NULL)
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
|
|
||||||
return btpy_insn_new (record->ptid,
|
return btpy_insn_or_gap_new (tinfo,
|
||||||
btrace_insn_number (tinfo->btrace.replay));
|
btrace_insn_number (tinfo->btrace.replay));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -788,7 +779,7 @@ recpy_bt_begin (PyObject *self, void *closure)
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
|
|
||||||
btrace_insn_begin (&iterator, &tinfo->btrace);
|
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
|
/* Implementation of
|
||||||
@ -810,7 +801,7 @@ recpy_bt_end (PyObject *self, void *closure)
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
|
|
||||||
btrace_insn_end (&iterator, &tinfo->btrace);
|
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
|
/* Implementation of
|
||||||
@ -914,7 +905,6 @@ recpy_bt_goto (PyObject *self, PyObject *args)
|
|||||||
struct gdb_PyGetSetDef btpy_insn_getset[] =
|
struct gdb_PyGetSetDef btpy_insn_getset[] =
|
||||||
{
|
{
|
||||||
{ "number", btpy_number, NULL, "instruction number", NULL},
|
{ "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},
|
{ "sal", btpy_insn_sal, NULL, "associated symbol and line", NULL},
|
||||||
{ "pc", btpy_insn_pc, NULL, "instruction address", NULL},
|
{ "pc", btpy_insn_pc, NULL, "instruction address", NULL},
|
||||||
{ "data", btpy_insn_data, NULL, "raw instruction data", NULL},
|
{ "data", btpy_insn_data, NULL, "raw instruction data", NULL},
|
||||||
|
@ -29,6 +29,27 @@ static PyTypeObject recpy_record_type = {
|
|||||||
PyVarObject_HEAD_INIT (NULL, 0)
|
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. */
|
/* Implementation of record.method. */
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
@ -139,6 +160,54 @@ recpy_end (PyObject *self, void* closure)
|
|||||||
return PyErr_Format (PyExc_NotImplementedError, _("Not implemented."));
|
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. */
|
/* Record method list. */
|
||||||
|
|
||||||
static PyMethodDef recpy_record_methods[] = {
|
static PyMethodDef recpy_record_methods[] = {
|
||||||
@ -167,6 +236,15 @@ the current instruction and is used for e.g. record.goto (record.end).", NULL },
|
|||||||
{ NULL }
|
{ 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. */
|
/* Sets up the record API in the gdb module. */
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -180,7 +258,18 @@ gdbpy_initialize_record (void)
|
|||||||
recpy_record_type.tp_methods = recpy_record_methods;
|
recpy_record_type.tp_methods = recpy_record_methods;
|
||||||
recpy_record_type.tp_getset = recpy_record_getset;
|
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. */
|
/* Implementation of gdb.start_recording (method) -> gdb.Record. */
|
||||||
|
@ -37,4 +37,8 @@ typedef struct
|
|||||||
enum record_method method;
|
enum record_method method;
|
||||||
} recpy_record_object;
|
} 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 */
|
#endif /* GDB_PY_RECORD_H */
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
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>
|
2017-05-01 Tim Wiederhake <tim.wiederhake@intel.com>
|
||||||
|
|
||||||
* gdb.python/py-record-btrace.exp: Remove Record.ptid test.
|
* gdb.python/py-record-btrace.exp: Remove Record.ptid test.
|
||||||
|
@ -81,7 +81,6 @@ with_test_prefix "replay end" {
|
|||||||
|
|
||||||
with_test_prefix "instruction " {
|
with_test_prefix "instruction " {
|
||||||
gdb_test "python print(i.number)" "1"
|
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.sal)" "symbol and line for .*"
|
||||||
gdb_test "python print(i.pc)" "$decimal"
|
gdb_test "python print(i.pc)" "$decimal"
|
||||||
if { $gdb_py_is_py3k == 0 } {
|
if { $gdb_py_is_py3k == 0 } {
|
||||||
|
Reference in New Issue
Block a user